Дозаливка
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Config Authentication plugin for phpMyAdmin
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
* @subpackage Config
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Get the authentication interface */
|
||||
require_once 'libraries/plugins/AuthenticationPlugin.class.php';
|
||||
|
||||
/**
|
||||
* Handles the config authentication method
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
*/
|
||||
class AuthenticationConfig extends AuthenticationPlugin
|
||||
{
|
||||
/**
|
||||
* Displays authentication form
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets advanced authentication settings
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function authCheck()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user and password after last checkings if required
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function authSetUser()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* User is not allowed to login to MySQL -> authentication failed
|
||||
*
|
||||
* @global string the MySQL error message PHP returns
|
||||
* @global string the connection type (persistent or not)
|
||||
* @global string the MySQL server port to use
|
||||
* @global string the MySQL socket port to use
|
||||
* @global array the current server settings
|
||||
* @global string the font face to use in case of failure
|
||||
* @global string the default font size to use in case of failure
|
||||
* @global string the big font size to use in case of failure
|
||||
* @global boolean tell the "PMA_mysqlDie()" function headers have been
|
||||
* sent
|
||||
*
|
||||
* @return boolean always true (no return indeed)
|
||||
*/
|
||||
public function authFails()
|
||||
{
|
||||
$conn_error = $GLOBALS['dbi']->getError();
|
||||
if (! $conn_error) {
|
||||
$conn_error = __('Cannot connect: invalid settings.');
|
||||
}
|
||||
|
||||
/* HTML header */
|
||||
$response = PMA_Response::getInstance();
|
||||
$response->getFooter()->setMinimal();
|
||||
$header = $response->getHeader();
|
||||
$header->setBodyId('loginform');
|
||||
$header->setTitle(__('Access denied'));
|
||||
$header->disableMenu();
|
||||
echo '<br /><br />
|
||||
<center>
|
||||
<h1>';
|
||||
echo sprintf(__('Welcome to %s'), ' phpMyAdmin ');
|
||||
echo '</h1>
|
||||
</center>
|
||||
<br />
|
||||
<table cellpadding="0" cellspacing="3" style="margin: 0 auto" width="80%">
|
||||
<tr>
|
||||
<td>';
|
||||
if (isset($GLOBALS['allowDeny_forbidden'])
|
||||
&& $GLOBALS['allowDeny_forbidden']
|
||||
) {
|
||||
trigger_error(__('Access denied'), E_USER_NOTICE);
|
||||
} else {
|
||||
// Check whether user has configured something
|
||||
if ($GLOBALS['PMA_Config']->source_mtime == 0) {
|
||||
echo '<p>' . sprintf(
|
||||
__(
|
||||
'You probably did not create a configuration file.'
|
||||
. ' You might want to use the %1$ssetup script%2$s to'
|
||||
. ' create one.'
|
||||
),
|
||||
'<a href="setup/">',
|
||||
'</a>'
|
||||
) . '</p>' . "\n";
|
||||
} elseif (! isset($GLOBALS['errno'])
|
||||
|| (isset($GLOBALS['errno']) && $GLOBALS['errno'] != 2002)
|
||||
&& $GLOBALS['errno'] != 2003
|
||||
) {
|
||||
// if we display the "Server not responding" error, do not confuse
|
||||
// users by telling them they have a settings problem
|
||||
// (note: it's true that they could have a badly typed host name,
|
||||
// but anyway the current message tells that the server
|
||||
// rejected the connection, which is not really what happened)
|
||||
// 2002 is the error given by mysqli
|
||||
// 2003 is the error given by mysql
|
||||
trigger_error(
|
||||
__(
|
||||
'phpMyAdmin tried to connect to the MySQL server, and the'
|
||||
. ' server rejected the connection. You should check the'
|
||||
. ' host, username and password in your configuration and'
|
||||
. ' make sure that they correspond to the information given'
|
||||
. ' by the administrator of the MySQL server.'
|
||||
), E_USER_WARNING
|
||||
);
|
||||
}
|
||||
echo PMA_Util::mysqlDie(
|
||||
$conn_error, '', true, '', false
|
||||
);
|
||||
}
|
||||
$GLOBALS['error_handler']->dispUserErrors();
|
||||
echo '</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>' . "\n";
|
||||
echo '<a href="'
|
||||
. $GLOBALS['cfg']['DefaultTabServer']
|
||||
. PMA_URL_getCommon(array()) . '" class="button disableAjax">'
|
||||
. __('Retry to connect')
|
||||
. '</a>' . "\n";
|
||||
echo '</td>
|
||||
</tr>' . "\n";
|
||||
if (count($GLOBALS['cfg']['Servers']) > 1) {
|
||||
// offer a chance to login to other servers if the current one failed
|
||||
include_once './libraries/select_server.lib.php';
|
||||
echo '<tr>' . "\n";
|
||||
echo ' <td>' . "\n";
|
||||
echo PMA_selectServer(true, true);
|
||||
echo ' </td>' . "\n";
|
||||
echo '</tr>' . "\n";
|
||||
}
|
||||
echo '</table>' . "\n";
|
||||
if (!defined('TESTSUITE')) {
|
||||
exit;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when any PluginManager to which the observer
|
||||
* is attached calls PluginManager::notify()
|
||||
*
|
||||
* @param SplSubject $subject The PluginManager notifying the observer
|
||||
* of an update.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update (SplSubject $subject)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,817 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Cookie Authentication plugin for phpMyAdmin
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
* @subpackage Cookie
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Get the authentication interface */
|
||||
require_once 'libraries/plugins/AuthenticationPlugin.class.php';
|
||||
|
||||
/**
|
||||
* Remember where to redirect the user
|
||||
* in case of an expired session.
|
||||
*/
|
||||
if (! empty($_REQUEST['target'])) {
|
||||
$GLOBALS['target'] = $_REQUEST['target'];
|
||||
} else if (PMA_getenv('SCRIPT_NAME')) {
|
||||
$GLOBALS['target'] = basename(PMA_getenv('SCRIPT_NAME'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swekey authentication functions.
|
||||
*/
|
||||
require './libraries/plugins/auth/swekey/swekey.auth.lib.php';
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
* Store the initialization vector because it will be needed for
|
||||
* further decryption. I don't think necessary to have one iv
|
||||
* per server so I don't put the server number in the cookie name.
|
||||
*/
|
||||
if (function_exists('mcrypt_encrypt')) {
|
||||
if (empty($_COOKIE['pma_mcrypt_iv'])
|
||||
|| ! ($iv = base64_decode($_COOKIE['pma_mcrypt_iv'], true))
|
||||
) {
|
||||
srand((double) microtime() * 1000000);
|
||||
$td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
|
||||
if ($td === false) {
|
||||
PMA_fatalError(__('Failed to use Blowfish from mcrypt!'));
|
||||
}
|
||||
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pma_mcrypt_iv',
|
||||
base64_encode($iv)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the cookie authentication method
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
*/
|
||||
class AuthenticationCookie extends AuthenticationPlugin
|
||||
{
|
||||
/**
|
||||
* Displays authentication form
|
||||
*
|
||||
* this function MUST exit/quit the application
|
||||
*
|
||||
* @global string $conn_error the last connection error
|
||||
*
|
||||
* @return boolean|void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
global $conn_error;
|
||||
|
||||
$response = PMA_Response::getInstance();
|
||||
if ($response->isAjax()) {
|
||||
$response->isSuccess(false);
|
||||
|
||||
$login_link = '<br /><br />[ ' .
|
||||
sprintf(
|
||||
'<a href="%s" class="ajax login-link">%s</a>',
|
||||
$GLOBALS['cfg']['PmaAbsoluteUri'],
|
||||
__('Log in')
|
||||
)
|
||||
. ' ]';
|
||||
|
||||
if (! empty($conn_error)) {
|
||||
|
||||
$conn_error .= $login_link;
|
||||
|
||||
$response->addJSON(
|
||||
'message',
|
||||
PMA_Message::error(
|
||||
$conn_error
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response->addJSON(
|
||||
'message',
|
||||
PMA_Message::error(
|
||||
__('Your session has expired. Please log in again.') .
|
||||
$login_link
|
||||
)
|
||||
);
|
||||
}
|
||||
if (defined('TESTSUITE')) {
|
||||
return true;
|
||||
} else {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform logout to custom URL */
|
||||
if (! empty($_REQUEST['old_usr'])
|
||||
&& ! empty($GLOBALS['cfg']['Server']['LogoutURL'])
|
||||
) {
|
||||
PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']);
|
||||
if (defined('TESTSUITE')) {
|
||||
return true;
|
||||
} else {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// No recall if blowfish secret is not configured as it would produce
|
||||
// garbage
|
||||
if ($GLOBALS['cfg']['LoginCookieRecall']
|
||||
&& ! empty($GLOBALS['cfg']['blowfish_secret'])
|
||||
) {
|
||||
$default_user = $GLOBALS['PHP_AUTH_USER'];
|
||||
$default_server = $GLOBALS['pma_auth_server'];
|
||||
$autocomplete = '';
|
||||
} else {
|
||||
$default_user = '';
|
||||
$default_server = '';
|
||||
// skip the IE autocomplete feature.
|
||||
$autocomplete = ' autocomplete="off"';
|
||||
}
|
||||
|
||||
$response->getFooter()->setMinimal();
|
||||
$header = $response->getHeader();
|
||||
$header->setBodyId('loginform');
|
||||
$header->setTitle('phpMyAdmin');
|
||||
$header->disableMenu();
|
||||
$header->disableWarnings();
|
||||
|
||||
if (file_exists(CUSTOM_HEADER_FILE)) {
|
||||
include CUSTOM_HEADER_FILE;
|
||||
}
|
||||
echo '
|
||||
<div class="container">
|
||||
<a href="';
|
||||
echo PMA_linkURL('http://www.phpmyadmin.net/');
|
||||
echo '" target="_blank" class="logo">';
|
||||
$logo_image = $GLOBALS['pmaThemeImage'] . 'logo_right.png';
|
||||
if (@file_exists($logo_image)) {
|
||||
echo '<img src="' . $logo_image
|
||||
. '" id="imLogo" name="imLogo" alt="phpMyAdmin" border="0" />';
|
||||
} else {
|
||||
echo '<img name="imLogo" id="imLogo" src="'
|
||||
. $GLOBALS['pmaThemeImage'] . 'pma_logo.png' . '" '
|
||||
. 'border="0" width="88" height="31" alt="phpMyAdmin" />';
|
||||
}
|
||||
echo '</a>
|
||||
<h1>';
|
||||
echo sprintf(
|
||||
__('Welcome to %s'),
|
||||
'<bdo dir="ltr" lang="en">phpMyAdmin</bdo>'
|
||||
);
|
||||
echo "</h1>";
|
||||
|
||||
// Show error message
|
||||
if (! empty($conn_error)) {
|
||||
PMA_Message::rawError($conn_error)->display();
|
||||
}
|
||||
|
||||
echo "<noscript>\n";
|
||||
PMA_message::error(
|
||||
__("Javascript must be enabled past this point")
|
||||
)->display();
|
||||
echo "</noscript>\n";
|
||||
|
||||
echo "<div class='hide js-show'>";
|
||||
// Displays the languages form
|
||||
if (empty($GLOBALS['cfg']['Lang'])) {
|
||||
include_once './libraries/display_select_lang.lib.php';
|
||||
// use fieldset, don't show doc link
|
||||
echo PMA_getLanguageSelectorHtml(true, false);
|
||||
}
|
||||
echo '</div>
|
||||
<br />
|
||||
<!-- Login form -->
|
||||
<form method="post" action="index.php" name="login_form"' . $autocomplete .
|
||||
' class="disableAjax login hide js-show">
|
||||
<fieldset>
|
||||
<legend>';
|
||||
echo __('Log in');
|
||||
echo PMA_Util::showDocu('index');
|
||||
echo '</legend>';
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']) {
|
||||
echo '
|
||||
<div class="item">
|
||||
<label for="input_servername" title="';
|
||||
echo __(
|
||||
'You can enter hostname/IP address and port separated by space.'
|
||||
);
|
||||
echo '">';
|
||||
echo __('Server:');
|
||||
echo '</label>
|
||||
<input type="text" name="pma_servername" id="input_servername"';
|
||||
echo ' value="';
|
||||
echo htmlspecialchars($default_server);
|
||||
echo '" size="24" class="textfield" title="';
|
||||
echo __(
|
||||
'You can enter hostname/IP address and port separated by space.'
|
||||
); echo '" />
|
||||
</div>';
|
||||
}
|
||||
echo '<div class="item">
|
||||
<label for="input_username">' . __('Username:') . '</label>
|
||||
<input type="text" name="pma_username" id="input_username" '
|
||||
. 'value="' . htmlspecialchars($default_user) . '" size="24"'
|
||||
. ' class="textfield"/>
|
||||
</div>
|
||||
<div class="item">
|
||||
<label for="input_password">' . __('Password:') . '</label>
|
||||
<input type="password" name="pma_password" id="input_password"'
|
||||
. ' value="" size="24" class="textfield" />
|
||||
</div>';
|
||||
if (count($GLOBALS['cfg']['Servers']) > 1) {
|
||||
echo '<div class="item">
|
||||
<label for="select_server">' . __('Server Choice:') .'</label>
|
||||
<select name="server" id="select_server"';
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']) {
|
||||
echo ' onchange="document.forms[\'login_form\'].'
|
||||
. 'elements[\'pma_servername\'].value = \'\'" ';
|
||||
}
|
||||
echo '>';
|
||||
|
||||
include_once './libraries/select_server.lib.php';
|
||||
echo PMA_selectServer(false, false);
|
||||
|
||||
echo '</select></div>';
|
||||
} else {
|
||||
echo ' <input type="hidden" name="server" value="'
|
||||
. $GLOBALS['server'] . '" />';
|
||||
} // end if (server choice)
|
||||
|
||||
// We already have one correct captcha.
|
||||
$skip = false;
|
||||
if ( isset($_SESSION['last_valid_captcha'])
|
||||
&& $_SESSION['last_valid_captcha']
|
||||
) {
|
||||
$skip = true;
|
||||
}
|
||||
|
||||
// Add captcha input field if reCaptcha is enabled
|
||||
if ( !empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
|
||||
&& !empty($GLOBALS['cfg']['CaptchaLoginPublicKey'])
|
||||
&& !$skip
|
||||
) {
|
||||
// If enabled show captcha to the user on the login screen.
|
||||
echo '<script type="text/javascript"
|
||||
src="https://www.google.com/recaptcha/api/challenge?'
|
||||
. 'k=' . $GLOBALS['cfg']['CaptchaLoginPublicKey'] . '&'
|
||||
. 'hl=' . $GLOBALS['lang'] . '">
|
||||
</script>
|
||||
<noscript>
|
||||
<iframe src="https://www.google.com/recaptcha/api/noscript?k='
|
||||
. $GLOBALS['cfg']['CaptchaLoginPublicKey'] . '"
|
||||
height="300" width="500" frameborder="0"></iframe><br>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
|
||||
</textarea>
|
||||
<input type="hidden" name="recaptcha_response_field"
|
||||
value="manual_challenge">
|
||||
</noscript>
|
||||
<script type="text/javascript">
|
||||
$("#recaptcha_reload_btn").addClass("disableAjax");
|
||||
$("#recaptcha_switch_audio_btn").addClass("disableAjax");
|
||||
$("#recaptcha_switch_img_btn").addClass("disableAjax");
|
||||
$("#recaptcha_whatsthis_btn").addClass("disableAjax");
|
||||
$("#recaptcha_audio_play_again").live("mouseover", function() {
|
||||
$(this).addClass("disableAjax");
|
||||
});
|
||||
</script>';
|
||||
}
|
||||
|
||||
echo '</fieldset>
|
||||
<fieldset class="tblFooters">
|
||||
<input value="' . __('Go') . '" type="submit" id="input_go" />';
|
||||
$_form_params = array();
|
||||
if (! empty($GLOBALS['target'])) {
|
||||
$_form_params['target'] = $GLOBALS['target'];
|
||||
}
|
||||
if (! empty($GLOBALS['db'])) {
|
||||
$_form_params['db'] = $GLOBALS['db'];
|
||||
}
|
||||
if (! empty($GLOBALS['table'])) {
|
||||
$_form_params['table'] = $GLOBALS['table'];
|
||||
}
|
||||
// do not generate a "server" hidden field as we want the "server"
|
||||
// drop-down to have priority
|
||||
echo PMA_URL_getHiddenInputs($_form_params, '', 0, 'server');
|
||||
echo '</fieldset>
|
||||
</form>';
|
||||
|
||||
// BEGIN Swekey Integration
|
||||
Swekey_login('input_username', 'input_go');
|
||||
// END Swekey Integration
|
||||
|
||||
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
|
||||
echo '<div>';
|
||||
$GLOBALS['error_handler']->dispErrors();
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
if (file_exists(CUSTOM_FOOTER_FILE)) {
|
||||
include CUSTOM_FOOTER_FILE;
|
||||
}
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets advanced authentication settings
|
||||
*
|
||||
* this function DOES NOT check authentication - it just checks/provides
|
||||
* authentication credentials required to connect to the MySQL server
|
||||
* usually with $GLOBALS['dbi']->connect()
|
||||
*
|
||||
* it returns false if something is missing - which usually leads to
|
||||
* auth() which displays login form
|
||||
*
|
||||
* it returns true if all seems ok which usually leads to auth_set_user()
|
||||
*
|
||||
* it directly switches to authFails() if user inactivity timout is reached
|
||||
*
|
||||
* @todo AllowArbitraryServer on does not imply that the user wants an
|
||||
* arbitrary server, or? so we should also check if this is filled
|
||||
* and not only if allowed
|
||||
*
|
||||
* @return boolean whether we get authentication settings or not
|
||||
*/
|
||||
public function authCheck()
|
||||
{
|
||||
global $conn_error;
|
||||
|
||||
// Initialization
|
||||
/**
|
||||
* @global $GLOBALS['pma_auth_server'] the user provided server to
|
||||
* connect to
|
||||
*/
|
||||
$GLOBALS['pma_auth_server'] = '';
|
||||
|
||||
$GLOBALS['PHP_AUTH_USER'] = $GLOBALS['PHP_AUTH_PW'] = '';
|
||||
$GLOBALS['from_cookie'] = false;
|
||||
|
||||
// BEGIN Swekey Integration
|
||||
if (! Swekey_Auth_check()) {
|
||||
return false;
|
||||
}
|
||||
// END Swekey Integration
|
||||
|
||||
if (defined('PMA_CLEAR_COOKIES')) {
|
||||
foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaServer-' . $key);
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaUser-' . $key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// We already have one correct captcha.
|
||||
$skip = false;
|
||||
if ( isset($_SESSION['last_valid_captcha'])
|
||||
&& $_SESSION['last_valid_captcha']
|
||||
) {
|
||||
$skip = true;
|
||||
}
|
||||
|
||||
// Verify Captcha if it is required.
|
||||
if ( !empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
|
||||
&& !empty($GLOBALS['cfg']['CaptchaLoginPublicKey'])
|
||||
&& !$skip
|
||||
) {
|
||||
if ( !empty($_POST["recaptcha_challenge_field"])
|
||||
&& !empty($_POST["recaptcha_response_field"])
|
||||
) {
|
||||
include_once 'libraries/plugins/auth/recaptchalib.php';
|
||||
|
||||
// Use private key to verify captcha status.
|
||||
$resp = recaptcha_check_answer(
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'],
|
||||
$_SERVER["REMOTE_ADDR"],
|
||||
$_POST["recaptcha_challenge_field"],
|
||||
$_POST["recaptcha_response_field"]
|
||||
);
|
||||
|
||||
// Check if the captcha entered is valid, if not stop the login.
|
||||
if ( !$resp->is_valid ) {
|
||||
$conn_error = __('Entered captcha is wrong, try again!');
|
||||
$_SESSION['last_valid_captcha'] = false;
|
||||
return false;
|
||||
} else {
|
||||
$_SESSION['last_valid_captcha'] = true;
|
||||
}
|
||||
} elseif (! empty($_POST["recaptcha_challenge_field"])
|
||||
&& empty($_POST["recaptcha_response_field"])
|
||||
) {
|
||||
$conn_error = __('Please enter correct captcha!');
|
||||
return false;
|
||||
} else {
|
||||
if (! isset($_SESSION['last_valid_captcha'])
|
||||
|| ! $_SESSION['last_valid_captcha']
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($_REQUEST['old_usr'])) {
|
||||
// The user wants to be logged out
|
||||
// -> delete his choices that were stored in session
|
||||
|
||||
// according to the PHP manual we should do this before the destroy:
|
||||
//$_SESSION = array();
|
||||
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_destroy();
|
||||
// $_SESSION array is not immediately emptied
|
||||
$_SESSION['last_valid_captcha'] = false;
|
||||
}
|
||||
// -> delete password cookie(s)
|
||||
if ($GLOBALS['cfg']['LoginCookieDeleteAll']) {
|
||||
foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
|
||||
if (isset($_COOKIE['pmaPass-' . $key])) {
|
||||
unset($_COOKIE['pmaPass-' . $key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$GLOBALS['PMA_Config']->removeCookie(
|
||||
'pmaPass-' . $GLOBALS['server']
|
||||
);
|
||||
if (isset($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
|
||||
unset($_COOKIE['pmaPass-' . $GLOBALS['server']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($_REQUEST['pma_username'])) {
|
||||
// The user just logged in
|
||||
$GLOBALS['PHP_AUTH_USER'] = $_REQUEST['pma_username'];
|
||||
$GLOBALS['PHP_AUTH_PW'] = empty($_REQUEST['pma_password'])
|
||||
? ''
|
||||
: $_REQUEST['pma_password'];
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']
|
||||
&& isset($_REQUEST['pma_servername'])
|
||||
) {
|
||||
$GLOBALS['pma_auth_server'] = $_REQUEST['pma_servername'];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// At the end, try to set the $GLOBALS['PHP_AUTH_USER']
|
||||
// and $GLOBALS['PHP_AUTH_PW'] variables from cookies
|
||||
|
||||
// servername
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']
|
||||
&& ! empty($_COOKIE['pmaServer-' . $GLOBALS['server']])
|
||||
) {
|
||||
$GLOBALS['pma_auth_server']
|
||||
= $_COOKIE['pmaServer-' . $GLOBALS['server']];
|
||||
}
|
||||
|
||||
// username
|
||||
if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$GLOBALS['PHP_AUTH_USER'] = $this->blowfishDecrypt(
|
||||
$_COOKIE['pmaUser-' . $GLOBALS['server']],
|
||||
$this->_getBlowfishSecret()
|
||||
);
|
||||
|
||||
// user was never logged in since session start
|
||||
if (empty($_SESSION['last_access_time'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// User inactive too long
|
||||
$last_access_time = time() - $GLOBALS['cfg']['LoginCookieValidity'];
|
||||
if ($_SESSION['last_access_time'] < $last_access_time
|
||||
) {
|
||||
PMA_Util::cacheUnset('is_create_db_priv', true);
|
||||
PMA_Util::cacheUnset('is_process_priv', true);
|
||||
PMA_Util::cacheUnset('is_reload_priv', true);
|
||||
PMA_Util::cacheUnset('db_to_create', true);
|
||||
PMA_Util::cacheUnset('dbs_where_create_table_allowed', true);
|
||||
$GLOBALS['no_activity'] = true;
|
||||
$this->authFails();
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// password
|
||||
if (empty($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$GLOBALS['PHP_AUTH_PW'] = $this->blowfishDecrypt(
|
||||
$_COOKIE['pmaPass-' . $GLOBALS['server']],
|
||||
$this->_getBlowfishSecret()
|
||||
);
|
||||
|
||||
if ($GLOBALS['PHP_AUTH_PW'] == "\xff(blank)") {
|
||||
$GLOBALS['PHP_AUTH_PW'] = '';
|
||||
}
|
||||
|
||||
$GLOBALS['from_cookie'] = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user and password after last checkings if required
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function authSetUser()
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
// Ensures valid authentication mode, 'only_db', bookmark database and
|
||||
// table names and relation table name are used
|
||||
if ($cfg['Server']['user'] != $GLOBALS['PHP_AUTH_USER']) {
|
||||
foreach ($cfg['Servers'] as $idx => $current) {
|
||||
if ($current['host'] == $cfg['Server']['host']
|
||||
&& $current['port'] == $cfg['Server']['port']
|
||||
&& $current['socket'] == $cfg['Server']['socket']
|
||||
&& $current['ssl'] == $cfg['Server']['ssl']
|
||||
&& $current['connect_type'] == $cfg['Server']['connect_type']
|
||||
&& $current['user'] == $GLOBALS['PHP_AUTH_USER']
|
||||
) {
|
||||
$GLOBALS['server'] = $idx;
|
||||
$cfg['Server'] = $current;
|
||||
break;
|
||||
}
|
||||
} // end foreach
|
||||
} // end if
|
||||
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']
|
||||
&& ! empty($GLOBALS['pma_auth_server'])
|
||||
) {
|
||||
/* Allow to specify 'host port' */
|
||||
$parts = explode(' ', $GLOBALS['pma_auth_server']);
|
||||
if (count($parts) == 2) {
|
||||
$tmp_host = $parts[0];
|
||||
$tmp_port = $parts[1];
|
||||
} else {
|
||||
$tmp_host = $GLOBALS['pma_auth_server'];
|
||||
$tmp_port = '';
|
||||
}
|
||||
if ($cfg['Server']['host'] != $GLOBALS['pma_auth_server']) {
|
||||
$cfg['Server']['host'] = $tmp_host;
|
||||
if (! empty($tmp_port)) {
|
||||
$cfg['Server']['port'] = $tmp_port;
|
||||
}
|
||||
}
|
||||
unset($tmp_host, $tmp_port, $parts);
|
||||
}
|
||||
$cfg['Server']['user'] = $GLOBALS['PHP_AUTH_USER'];
|
||||
$cfg['Server']['password'] = $GLOBALS['PHP_AUTH_PW'];
|
||||
|
||||
// Avoid showing the password in phpinfo()'s output
|
||||
unset($GLOBALS['PHP_AUTH_PW']);
|
||||
unset($_SERVER['PHP_AUTH_PW']);
|
||||
|
||||
$_SESSION['last_access_time'] = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores user credentials after successful login.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function storeUserCredentials()
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
// Name and password cookies need to be refreshed each time
|
||||
// Duration = one month for username
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pmaUser-' . $GLOBALS['server'],
|
||||
$this->blowfishEncrypt(
|
||||
$cfg['Server']['user'],
|
||||
$this->_getBlowfishSecret()
|
||||
)
|
||||
);
|
||||
|
||||
// Duration = as configured
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pmaPass-' . $GLOBALS['server'],
|
||||
$this->blowfishEncrypt(
|
||||
! empty($cfg['Server']['password'])
|
||||
? $cfg['Server']['password'] : "\xff(blank)",
|
||||
$this->_getBlowfishSecret()
|
||||
),
|
||||
null,
|
||||
$GLOBALS['cfg']['LoginCookieStore']
|
||||
);
|
||||
|
||||
// Set server cookies if required (once per session) and, in this case,
|
||||
// force reload to ensure the client accepts cookies
|
||||
if (! $GLOBALS['from_cookie']) {
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']) {
|
||||
if (! empty($GLOBALS['pma_auth_server'])) {
|
||||
// Duration = one month for servername
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pmaServer-' . $GLOBALS['server'],
|
||||
$cfg['Server']['host']
|
||||
);
|
||||
} else {
|
||||
// Delete servername cookie
|
||||
$GLOBALS['PMA_Config']->removeCookie(
|
||||
'pmaServer-' . $GLOBALS['server']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// URL where to go:
|
||||
$redirect_url = $cfg['PmaAbsoluteUri'] . 'index.php';
|
||||
|
||||
// any parameters to pass?
|
||||
$url_params = array();
|
||||
if (strlen($GLOBALS['db'])) {
|
||||
$url_params['db'] = $GLOBALS['db'];
|
||||
}
|
||||
if (strlen($GLOBALS['table'])) {
|
||||
$url_params['table'] = $GLOBALS['table'];
|
||||
}
|
||||
// any target to pass?
|
||||
if (! empty($GLOBALS['target'])
|
||||
&& $GLOBALS['target'] != 'index.php'
|
||||
) {
|
||||
$url_params['target'] = $GLOBALS['target'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear user cache.
|
||||
*/
|
||||
PMA_Util::clearUserCache();
|
||||
|
||||
PMA_Response::getInstance()->disable();
|
||||
|
||||
PMA_sendHeaderLocation(
|
||||
$redirect_url . PMA_URL_getCommon($url_params, '&'),
|
||||
true
|
||||
);
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} // end if
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* User is not allowed to login to MySQL -> authentication failed
|
||||
*
|
||||
* prepares error message and switches to auth() which display the error
|
||||
* and the login form
|
||||
*
|
||||
* this function MUST exit/quit the application,
|
||||
* currently doen by call to auth()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authFails()
|
||||
{
|
||||
global $conn_error;
|
||||
|
||||
// Deletes password cookie and displays the login form
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $GLOBALS['server']);
|
||||
|
||||
if (! empty($GLOBALS['login_without_password_is_forbidden'])) {
|
||||
$conn_error = __(
|
||||
'Login without a password is forbidden by configuration'
|
||||
. ' (see AllowNoPassword)'
|
||||
);
|
||||
} elseif (! empty($GLOBALS['allowDeny_forbidden'])) {
|
||||
$conn_error = __('Access denied');
|
||||
} elseif (! empty($GLOBALS['no_activity'])) {
|
||||
$conn_error = sprintf(
|
||||
__('No activity within %s seconds; please log in again.'),
|
||||
$GLOBALS['cfg']['LoginCookieValidity']
|
||||
);
|
||||
} elseif ($GLOBALS['dbi']->getError()) {
|
||||
$conn_error = '#' . $GLOBALS['errno'] . ' '
|
||||
. __('Cannot log in to the MySQL server');
|
||||
} else {
|
||||
$conn_error = __('Cannot log in to the MySQL server');
|
||||
}
|
||||
|
||||
// needed for PHP-CGI (not need for FastCGI or mod-php)
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Pragma: no-cache');
|
||||
|
||||
$this->auth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns blowfish secret or generates one if needed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function _getBlowfishSecret()
|
||||
{
|
||||
if (empty($GLOBALS['cfg']['blowfish_secret'])) {
|
||||
if (empty($_SESSION['auto_blowfish_secret'])) {
|
||||
// this returns 23 characters
|
||||
$_SESSION['auto_blowfish_secret'] = uniqid('', true);
|
||||
}
|
||||
return $_SESSION['auto_blowfish_secret'];
|
||||
} else {
|
||||
// apply md5() to work around too long secrets (returns 32 characters)
|
||||
return md5($GLOBALS['cfg']['blowfish_secret']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption using blowfish algorithm (mcrypt)
|
||||
* or phpseclib's AES if mcrypt not available
|
||||
*
|
||||
* @param string $data original data
|
||||
* @param string $secret the secret
|
||||
*
|
||||
* @return string the encrypted result
|
||||
*/
|
||||
public function blowfishEncrypt($data, $secret)
|
||||
{
|
||||
global $iv;
|
||||
if (! function_exists('mcrypt_encrypt')) {
|
||||
/**
|
||||
* This library uses mcrypt when available, so
|
||||
* we could always call it instead of having an
|
||||
* if/then/else logic, however the include_once
|
||||
* call is costly
|
||||
*/
|
||||
include_once "./libraries/phpseclib/Crypt/AES.php";
|
||||
$cipher = new Crypt_AES(CRYPT_AES_MODE_ECB);
|
||||
$cipher->setKey($secret);
|
||||
return base64_encode($cipher->encrypt($data));
|
||||
} else {
|
||||
return base64_encode(
|
||||
mcrypt_encrypt(
|
||||
MCRYPT_BLOWFISH,
|
||||
$secret,
|
||||
$data,
|
||||
MCRYPT_MODE_CBC,
|
||||
$iv
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decryption using blowfish algorithm (mcrypt)
|
||||
* or phpseclib's AES if mcrypt not available
|
||||
*
|
||||
* @param string $encdata encrypted data
|
||||
* @param string $secret the secret
|
||||
*
|
||||
* @return string original data
|
||||
*/
|
||||
public function blowfishDecrypt($encdata, $secret)
|
||||
{
|
||||
global $iv;
|
||||
if (! function_exists('mcrypt_encrypt')) {
|
||||
include_once "./libraries/phpseclib/Crypt/AES.php";
|
||||
$cipher = new Crypt_AES(CRYPT_AES_MODE_ECB);
|
||||
$cipher->setKey($secret);
|
||||
return $cipher->decrypt(base64_decode($encdata));
|
||||
} else {
|
||||
$data = base64_decode($encdata);
|
||||
$decrypted = mcrypt_decrypt(
|
||||
MCRYPT_BLOWFISH,
|
||||
$secret,
|
||||
$data,
|
||||
MCRYPT_MODE_CBC,
|
||||
$iv
|
||||
);
|
||||
return trim($decrypted);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when any PluginManager to which the observer
|
||||
* is attached calls PluginManager::notify()
|
||||
*
|
||||
* @param SplSubject $subject The PluginManager notifying the observer
|
||||
* of an update.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update (SplSubject $subject)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* HTTP Authentication plugin for phpMyAdmin.
|
||||
* NOTE: Requires PHP loaded as a Apache module.
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
* @subpackage HTTP
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Get the authentication interface */
|
||||
require_once 'libraries/plugins/AuthenticationPlugin.class.php';
|
||||
|
||||
/**
|
||||
* Handles the HTTP authentication methods
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
*/
|
||||
class AuthenticationHttp extends AuthenticationPlugin
|
||||
{
|
||||
/**
|
||||
* Displays authentication form
|
||||
*
|
||||
* @global string the font face to use in case of failure
|
||||
* @global string the default font size to use in case of failure
|
||||
* @global string the big font size to use in case of failure
|
||||
*
|
||||
* @return boolean always true (no return indeed)
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
/* Perform logout to custom URL */
|
||||
if (! empty($_REQUEST['old_usr'])
|
||||
&& ! empty($GLOBALS['cfg']['Server']['LogoutURL'])
|
||||
) {
|
||||
PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']);
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($GLOBALS['cfg']['Server']['auth_http_realm'])) {
|
||||
if (empty($GLOBALS['cfg']['Server']['verbose'])) {
|
||||
$server_message = $GLOBALS['cfg']['Server']['host'];
|
||||
} else {
|
||||
$server_message = $GLOBALS['cfg']['Server']['verbose'];
|
||||
}
|
||||
$realm_message = 'phpMyAdmin ' . $server_message;
|
||||
} else {
|
||||
$realm_message = $GLOBALS['cfg']['Server']['auth_http_realm'];
|
||||
}
|
||||
// remove non US-ASCII to respect RFC2616
|
||||
$realm_message = preg_replace('/[^\x20-\x7e]/i', '', $realm_message);
|
||||
header('WWW-Authenticate: Basic realm="' . $realm_message . '"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
if (php_sapi_name() !== 'cgi-fcgi') {
|
||||
header('status: 401 Unauthorized');
|
||||
}
|
||||
|
||||
/* HTML header */
|
||||
$response = PMA_Response::getInstance();
|
||||
$response->getFooter()->setMinimal();
|
||||
$header = $response->getHeader();
|
||||
$header->setTitle(__('Access denied'));
|
||||
$header->disableMenu();
|
||||
$header->setBodyId('loginform');
|
||||
|
||||
$response->addHTML('<h1>');
|
||||
$response->addHTML(sprintf(__('Welcome to %s'), ' phpMyAdmin'));
|
||||
$response->addHTML('</h1>');
|
||||
$response->addHTML('<h3>');
|
||||
$response->addHTML(
|
||||
PMA_Message::error(
|
||||
__('Wrong username/password. Access denied.')
|
||||
)
|
||||
);
|
||||
$response->addHTML('</h3>');
|
||||
|
||||
if (file_exists(CUSTOM_FOOTER_FILE)) {
|
||||
include CUSTOM_FOOTER_FILE;
|
||||
}
|
||||
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets advanced authentication settings
|
||||
*
|
||||
* @global string $PHP_AUTH_USER the username if register_globals is on
|
||||
* @global string $PHP_AUTH_PW the password if register_globals is on
|
||||
* @global array the array of server variables if
|
||||
* register_globals is off
|
||||
* @global array the array of environment variables if
|
||||
* register_globals is off
|
||||
* @global string the username for the ? server
|
||||
* @global string the password for the ? server
|
||||
* @global string the username for the WebSite Professional
|
||||
* server
|
||||
* @global string the password for the WebSite Professional
|
||||
* server
|
||||
* @global string the username of the user who logs out
|
||||
*
|
||||
* @return boolean whether we get authentication settings or not
|
||||
*/
|
||||
public function authCheck()
|
||||
{
|
||||
global $PHP_AUTH_USER, $PHP_AUTH_PW;
|
||||
|
||||
// Grabs the $PHP_AUTH_USER variable whatever are the values of the
|
||||
// 'register_globals' and the 'variables_order' directives
|
||||
if (empty($PHP_AUTH_USER)) {
|
||||
if (PMA_getenv('PHP_AUTH_USER')) {
|
||||
$PHP_AUTH_USER = PMA_getenv('PHP_AUTH_USER');
|
||||
} elseif (PMA_getenv('REMOTE_USER')) {
|
||||
// CGI, might be encoded, see below
|
||||
$PHP_AUTH_USER = PMA_getenv('REMOTE_USER');
|
||||
} elseif (PMA_getenv('REDIRECT_REMOTE_USER')) {
|
||||
// CGI, might be encoded, see below
|
||||
$PHP_AUTH_USER = PMA_getenv('REDIRECT_REMOTE_USER');
|
||||
} elseif (PMA_getenv('AUTH_USER')) {
|
||||
// WebSite Professional
|
||||
$PHP_AUTH_USER = PMA_getenv('AUTH_USER');
|
||||
} elseif (PMA_getenv('HTTP_AUTHORIZATION')
|
||||
&& false === strpos(PMA_getenv('HTTP_AUTHORIZATION'), '<')
|
||||
) {
|
||||
// IIS, might be encoded, see below; also prevent XSS
|
||||
$PHP_AUTH_USER = PMA_getenv('HTTP_AUTHORIZATION');
|
||||
} elseif (PMA_getenv('Authorization')) {
|
||||
// FastCGI, might be encoded, see below
|
||||
$PHP_AUTH_USER = PMA_getenv('Authorization');
|
||||
}
|
||||
}
|
||||
// Grabs the $PHP_AUTH_PW variable whatever are the values of the
|
||||
// 'register_globals' and the 'variables_order' directives
|
||||
if (empty($PHP_AUTH_PW)) {
|
||||
if (PMA_getenv('PHP_AUTH_PW')) {
|
||||
$PHP_AUTH_PW = PMA_getenv('PHP_AUTH_PW');
|
||||
} elseif (PMA_getenv('REMOTE_PASSWORD')) {
|
||||
// Apache/CGI
|
||||
$PHP_AUTH_PW = PMA_getenv('REMOTE_PASSWORD');
|
||||
} elseif (PMA_getenv('AUTH_PASSWORD')) {
|
||||
// WebSite Professional
|
||||
$PHP_AUTH_PW = PMA_getenv('AUTH_PASSWORD');
|
||||
}
|
||||
}
|
||||
|
||||
// Decode possibly encoded information (used by IIS/CGI/FastCGI)
|
||||
// (do not use explode() because a user might have a colon in his password
|
||||
if (strcmp(substr($PHP_AUTH_USER, 0, 6), 'Basic ') == 0) {
|
||||
$usr_pass = base64_decode(substr($PHP_AUTH_USER, 6));
|
||||
if (! empty($usr_pass)) {
|
||||
$colon = strpos($usr_pass, ':');
|
||||
if ($colon) {
|
||||
$PHP_AUTH_USER = substr($usr_pass, 0, $colon);
|
||||
$PHP_AUTH_PW = substr($usr_pass, $colon + 1);
|
||||
}
|
||||
unset($colon);
|
||||
}
|
||||
unset($usr_pass);
|
||||
}
|
||||
|
||||
// User logged out -> ensure the new username is not the same
|
||||
$old_usr = isset($_REQUEST['old_usr']) ? $_REQUEST['old_usr'] : '';
|
||||
if (! empty($old_usr)
|
||||
&& (isset($PHP_AUTH_USER) && $old_usr == $PHP_AUTH_USER)
|
||||
) {
|
||||
$PHP_AUTH_USER = '';
|
||||
// -> delete user's choices that were stored in session
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether we get authentication settings or not
|
||||
if (empty($PHP_AUTH_USER)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user and password after last checkings if required
|
||||
*
|
||||
* @global array $cfg the valid servers settings
|
||||
* @global integer $server the id of the current server
|
||||
* @global array the current server settings
|
||||
* @global string $PHP_AUTH_USER the current username
|
||||
* @global string $PHP_AUTH_PW the current password
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function authSetUser()
|
||||
{
|
||||
global $cfg, $server;
|
||||
global $PHP_AUTH_USER, $PHP_AUTH_PW;
|
||||
|
||||
// Ensures valid authentication mode, 'only_db', bookmark database and
|
||||
// table names and relation table name are used
|
||||
if ($cfg['Server']['user'] != $PHP_AUTH_USER) {
|
||||
$servers_cnt = count($cfg['Servers']);
|
||||
for ($i = 1; $i <= $servers_cnt; $i++) {
|
||||
if (isset($cfg['Servers'][$i])
|
||||
&& ($cfg['Servers'][$i]['host'] == $cfg['Server']['host']
|
||||
&& $cfg['Servers'][$i]['user'] == $PHP_AUTH_USER)
|
||||
) {
|
||||
$server = $i;
|
||||
$cfg['Server'] = $cfg['Servers'][$i];
|
||||
break;
|
||||
}
|
||||
} // end for
|
||||
} // end if
|
||||
|
||||
$cfg['Server']['user'] = $PHP_AUTH_USER;
|
||||
$cfg['Server']['password'] = $PHP_AUTH_PW;
|
||||
|
||||
// Avoid showing the password in phpinfo()'s output
|
||||
unset($GLOBALS['PHP_AUTH_PW']);
|
||||
unset($_SERVER['PHP_AUTH_PW']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* User is not allowed to login to MySQL -> authentication failed
|
||||
*
|
||||
* @return boolean always true (no return indeed)
|
||||
*/
|
||||
public function authFails()
|
||||
{
|
||||
$error = $GLOBALS['dbi']->getError();
|
||||
if ($error && $GLOBALS['errno'] != 1045) {
|
||||
PMA_fatalError($error);
|
||||
} else {
|
||||
$this->auth();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when any PluginManager to which the observer
|
||||
* is attached calls PluginManager::notify()
|
||||
*
|
||||
* @param SplSubject $subject The PluginManager notifying the observer
|
||||
* of an update.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update (SplSubject $subject)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* SignOn Authentication plugin for phpMyAdmin
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
* @subpackage SignOn
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Get the authentication interface */
|
||||
require_once 'libraries/plugins/AuthenticationPlugin.class.php';
|
||||
|
||||
/**
|
||||
* Handles the SignOn authentication method
|
||||
*
|
||||
* @package PhpMyAdmin-Authentication
|
||||
*/
|
||||
class AuthenticationSignon extends AuthenticationPlugin
|
||||
{
|
||||
/**
|
||||
* Displays authentication form
|
||||
*
|
||||
* @global string the font face to use in case of failure
|
||||
* @global string the default font size to use in case of failure
|
||||
* @global string the big font size to use in case of failure
|
||||
*
|
||||
* @return boolean always true (no return indeed)
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
unset($_SESSION['LAST_SIGNON_URL']);
|
||||
if (empty($GLOBALS['cfg']['Server']['SignonURL'])) {
|
||||
PMA_fatalError('You must set SignonURL!');
|
||||
} elseif (! empty($_REQUEST['old_usr'])
|
||||
&& ! empty($GLOBALS['cfg']['Server']['LogoutURL'])
|
||||
) {
|
||||
/* Perform logout to custom URL */
|
||||
PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']);
|
||||
} else {
|
||||
PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['SignonURL']);
|
||||
}
|
||||
|
||||
if (! defined('TESTSUITE')) {
|
||||
exit();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets advanced authentication settings
|
||||
*
|
||||
* @global string $PHP_AUTH_USER the username if register_globals is on
|
||||
* @global string $PHP_AUTH_PW the password if register_globals is on
|
||||
* @global array the array of server variables if
|
||||
* register_globals is off
|
||||
* @global array the array of environment variables if
|
||||
* register_globals is off
|
||||
* @global string the username for the ? server
|
||||
* @global string the password for the ? server
|
||||
* @global string the username for the WebSite Professional server
|
||||
* @global string the password for the WebSite Professional server
|
||||
* @global string the username of the user who logs out
|
||||
*
|
||||
* @return boolean whether we get authentication settings or not
|
||||
*/
|
||||
public function authCheck()
|
||||
{
|
||||
global $PHP_AUTH_USER, $PHP_AUTH_PW;
|
||||
|
||||
/* Check if we're using same sigon server */
|
||||
$signon_url = $GLOBALS['cfg']['Server']['SignonURL'];
|
||||
if (isset($_SESSION['LAST_SIGNON_URL'])
|
||||
&& $_SESSION['LAST_SIGNON_URL'] != $signon_url
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Script name */
|
||||
$script_name = $GLOBALS['cfg']['Server']['SignonScript'];
|
||||
|
||||
/* Session name */
|
||||
$session_name = $GLOBALS['cfg']['Server']['SignonSession'];
|
||||
|
||||
/* Login URL */
|
||||
$signon_url = $GLOBALS['cfg']['Server']['SignonURL'];
|
||||
|
||||
/* Current host */
|
||||
$single_signon_host = $GLOBALS['cfg']['Server']['host'];
|
||||
|
||||
/* Current port */
|
||||
$single_signon_port = $GLOBALS['cfg']['Server']['port'];
|
||||
|
||||
/* No configuration updates */
|
||||
$single_signon_cfgupdate = array();
|
||||
|
||||
/* Are we requested to do logout? */
|
||||
$do_logout = !empty($_REQUEST['old_usr']);
|
||||
|
||||
/* Handle script based auth */
|
||||
if (!empty($script_name)) {
|
||||
if (! file_exists($script_name)) {
|
||||
PMA_fatalError(
|
||||
__('Can not find signon authentication script:')
|
||||
. ' '. $script_name
|
||||
);
|
||||
}
|
||||
include $script_name;
|
||||
|
||||
list ($PHP_AUTH_USER, $PHP_AUTH_PW)
|
||||
= get_login_credentials($GLOBALS['cfg']['Server']['user']);
|
||||
|
||||
} elseif (isset($_COOKIE[$session_name])) { /* Does session exist? */
|
||||
/* End current session */
|
||||
$old_session = session_name();
|
||||
$old_id = session_id();
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/* Load single signon session */
|
||||
session_name($session_name);
|
||||
session_id($_COOKIE[$session_name]);
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
/* Clear error message */
|
||||
unset($_SESSION['PMA_single_signon_error_message']);
|
||||
|
||||
/* Grab credentials if they exist */
|
||||
if (isset($_SESSION['PMA_single_signon_user'])) {
|
||||
if ($do_logout) {
|
||||
$PHP_AUTH_USER = '';
|
||||
} else {
|
||||
$PHP_AUTH_USER = $_SESSION['PMA_single_signon_user'];
|
||||
}
|
||||
}
|
||||
if (isset($_SESSION['PMA_single_signon_password'])) {
|
||||
if ($do_logout) {
|
||||
$PHP_AUTH_PW = '';
|
||||
} else {
|
||||
$PHP_AUTH_PW = $_SESSION['PMA_single_signon_password'];
|
||||
}
|
||||
}
|
||||
if (isset($_SESSION['PMA_single_signon_host'])) {
|
||||
$single_signon_host = $_SESSION['PMA_single_signon_host'];
|
||||
}
|
||||
|
||||
if (isset($_SESSION['PMA_single_signon_port'])) {
|
||||
$single_signon_port = $_SESSION['PMA_single_signon_port'];
|
||||
}
|
||||
|
||||
if (isset($_SESSION['PMA_single_signon_cfgupdate'])) {
|
||||
$single_signon_cfgupdate = $_SESSION['PMA_single_signon_cfgupdate'];
|
||||
}
|
||||
|
||||
|
||||
/* Also get token as it is needed to access subpages */
|
||||
if (isset($_SESSION['PMA_single_signon_token'])) {
|
||||
/* No need to care about token on logout */
|
||||
$pma_token = $_SESSION['PMA_single_signon_token'];
|
||||
}
|
||||
|
||||
/* End single signon session */
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/* Restart phpMyAdmin session */
|
||||
session_name($old_session);
|
||||
if (!empty($old_id)) {
|
||||
session_id($old_id);
|
||||
}
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
/* Set the single signon host */
|
||||
$GLOBALS['cfg']['Server']['host'] = $single_signon_host;
|
||||
|
||||
/* Set the single signon port */
|
||||
$GLOBALS['cfg']['Server']['port'] = $single_signon_port;
|
||||
|
||||
/* Configuration update */
|
||||
$GLOBALS['cfg']['Server'] = array_merge(
|
||||
$GLOBALS['cfg']['Server'],
|
||||
$single_signon_cfgupdate
|
||||
);
|
||||
|
||||
/* Restore our token */
|
||||
if (!empty($pma_token)) {
|
||||
$_SESSION[' PMA_token '] = $pma_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear user cache.
|
||||
*/
|
||||
PMA_Util::clearUserCache();
|
||||
}
|
||||
|
||||
// Returns whether we get authentication settings or not
|
||||
if (empty($PHP_AUTH_USER)) {
|
||||
unset($_SESSION['LAST_SIGNON_URL']);
|
||||
return false;
|
||||
} else {
|
||||
$_SESSION['LAST_SIGNON_URL'] = $GLOBALS['cfg']['Server']['SignonURL'];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user and password after last checkings if required
|
||||
*
|
||||
* @global array $cfg the valid servers settings
|
||||
* @global integer the id of the current server
|
||||
* @global array the current server settings
|
||||
* @global string $PHP_AUTH_USER the current username
|
||||
* @global string $PHP_AUTH_PW the current password
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function authSetUser()
|
||||
{
|
||||
global $cfg;
|
||||
global $PHP_AUTH_USER, $PHP_AUTH_PW;
|
||||
|
||||
$cfg['Server']['user'] = $PHP_AUTH_USER;
|
||||
$cfg['Server']['password'] = $PHP_AUTH_PW;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* User is not allowed to login to MySQL -> authentication failed
|
||||
*
|
||||
* @return boolean always true (no return indeed)
|
||||
*/
|
||||
public function authFails()
|
||||
{
|
||||
/* Session name */
|
||||
$session_name = $GLOBALS['cfg']['Server']['SignonSession'];
|
||||
|
||||
/* Does session exist? */
|
||||
if (isset($_COOKIE[$session_name])) {
|
||||
/* End current session */
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/* Load single signon session */
|
||||
session_name($session_name);
|
||||
session_id($_COOKIE[$session_name]);
|
||||
if (! defined('TESTSUITE')) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
/* Set error message */
|
||||
if (! empty($GLOBALS['login_without_password_is_forbidden'])) {
|
||||
$_SESSION['PMA_single_signon_error_message'] = __(
|
||||
'Login without a password is forbidden by configuration '
|
||||
. '(see AllowNoPassword)'
|
||||
);
|
||||
} elseif (! empty($GLOBALS['allowDeny_forbidden'])) {
|
||||
$_SESSION['PMA_single_signon_error_message'] = __('Access denied');
|
||||
} elseif (! empty($GLOBALS['no_activity'])) {
|
||||
$_SESSION['PMA_single_signon_error_message'] = sprintf(
|
||||
__('No activity within %s seconds; please log in again.'),
|
||||
$GLOBALS['cfg']['LoginCookieValidity']
|
||||
);
|
||||
} elseif ($GLOBALS['dbi']->getError()) {
|
||||
$_SESSION['PMA_single_signon_error_message'] = PMA_sanitize(
|
||||
$GLOBALS['dbi']->getError()
|
||||
);
|
||||
} else {
|
||||
$_SESSION['PMA_single_signon_error_message'] = __(
|
||||
'Cannot log in to the MySQL server'
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->auth();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when any PluginManager to which the observer
|
||||
* is attached calls PluginManager::notify()
|
||||
*
|
||||
* @param SplSubject $subject The PluginManager notifying the observer
|
||||
* of an update.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update (SplSubject $subject)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
/*
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
* - Documentation and latest version
|
||||
* http://recaptcha.net/plugins/php/
|
||||
* - Get a reCAPTCHA API Key
|
||||
* https://www.google.com/recaptcha/admin/create
|
||||
* - Discussion group
|
||||
* http://groups.google.com/group/recaptcha
|
||||
*
|
||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
* AUTHORS:
|
||||
* Mike Crawford
|
||||
* Ben Maurer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The reCAPTCHA server URL's
|
||||
*/
|
||||
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
|
||||
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
|
||||
|
||||
/**
|
||||
* Encodes the given data into a query string format
|
||||
* @param $data - array of string elements to be encoded
|
||||
* @return string - encoded request
|
||||
*/
|
||||
function _recaptcha_qsencode ($data) {
|
||||
$req = "";
|
||||
foreach ( $data as $key => $value )
|
||||
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
|
||||
|
||||
// Cut the last '&'
|
||||
$req=substr($req,0,strlen($req)-1);
|
||||
return $req;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Submits an HTTP POST to a reCAPTCHA server
|
||||
* @param string $host
|
||||
* @param string $path
|
||||
* @param array $data
|
||||
* @param int port
|
||||
* @return array response
|
||||
*/
|
||||
function _recaptcha_http_post($host, $path, $data, $port = 80) {
|
||||
|
||||
$req = _recaptcha_qsencode ($data);
|
||||
|
||||
$http_request = "POST $path HTTP/1.0\r\n";
|
||||
$http_request .= "Host: $host\r\n";
|
||||
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
|
||||
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
|
||||
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
|
||||
$http_request .= "\r\n";
|
||||
$http_request .= $req;
|
||||
|
||||
$response = '';
|
||||
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
|
||||
die ('Could not open socket');
|
||||
}
|
||||
|
||||
fwrite($fs, $http_request);
|
||||
|
||||
while ( !feof($fs) )
|
||||
$response .= fgets($fs, 1160); // One TCP-IP packet
|
||||
fclose($fs);
|
||||
$response = explode("\r\n\r\n", $response, 2);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the challenge HTML (javascript and non-javascript version).
|
||||
* This is called from the browser, and the resulting reCAPTCHA HTML widget
|
||||
* is embedded within the HTML form it was called from.
|
||||
* @param string $pubkey A public key for reCAPTCHA
|
||||
* @param string $error The error given by reCAPTCHA (optional, default is null)
|
||||
* @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
|
||||
|
||||
* @return string - The HTML to be embedded in the user's form.
|
||||
*/
|
||||
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
|
||||
{
|
||||
if ($pubkey == null || $pubkey == '') {
|
||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
}
|
||||
|
||||
if ($use_ssl) {
|
||||
$server = RECAPTCHA_API_SECURE_SERVER;
|
||||
} else {
|
||||
$server = RECAPTCHA_API_SERVER;
|
||||
}
|
||||
|
||||
$errorpart = "";
|
||||
if ($error) {
|
||||
$errorpart = "&error=" . $error;
|
||||
}
|
||||
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
|
||||
</noscript>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A ReCaptchaResponse is returned from recaptcha_check_answer()
|
||||
*/
|
||||
class ReCaptchaResponse {
|
||||
var $is_valid;
|
||||
var $error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls an HTTP POST function to verify if the user's guess was correct
|
||||
* @param string $privkey
|
||||
* @param string $remoteip
|
||||
* @param string $challenge
|
||||
* @param string $response
|
||||
* @param array $extra_params an array of extra variables to post to the server
|
||||
* @return ReCaptchaResponse
|
||||
*/
|
||||
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
|
||||
{
|
||||
if ($privkey == null || $privkey == '') {
|
||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
||||
}
|
||||
|
||||
if ($remoteip == null || $remoteip == '') {
|
||||
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//discard spam submissions
|
||||
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = 'incorrect-captcha-sol';
|
||||
return $recaptcha_response;
|
||||
}
|
||||
|
||||
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
|
||||
array (
|
||||
'privatekey' => $privkey,
|
||||
'remoteip' => $remoteip,
|
||||
'challenge' => $challenge,
|
||||
'response' => $response
|
||||
) + $extra_params
|
||||
);
|
||||
|
||||
$answers = explode ("\n", $response [1]);
|
||||
$recaptcha_response = new ReCaptchaResponse();
|
||||
|
||||
if (trim ($answers [0]) == 'true') {
|
||||
$recaptcha_response->is_valid = true;
|
||||
}
|
||||
else {
|
||||
$recaptcha_response->is_valid = false;
|
||||
$recaptcha_response->error = $answers [1];
|
||||
}
|
||||
return $recaptcha_response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a URL where the user can sign up for reCAPTCHA. If your application
|
||||
* has a configuration page where you enter a key, you should provide a link
|
||||
* using this function.
|
||||
* @param string $domain The domain where the page is hosted
|
||||
* @param string $appname The name of your application
|
||||
*/
|
||||
function recaptcha_get_signup_url ($domain = null, $appname = null) {
|
||||
return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
|
||||
}
|
||||
|
||||
function _recaptcha_aes_pad($val) {
|
||||
$block_size = 16;
|
||||
$numpad = $block_size - (strlen ($val) % $block_size);
|
||||
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
|
||||
}
|
||||
|
||||
/* Mailhide related code */
|
||||
|
||||
function _recaptcha_aes_encrypt($val,$ky) {
|
||||
if (! function_exists ("mcrypt_encrypt")) {
|
||||
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
|
||||
}
|
||||
$mode=MCRYPT_MODE_CBC;
|
||||
$enc=MCRYPT_RIJNDAEL_128;
|
||||
$val=_recaptcha_aes_pad($val);
|
||||
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
|
||||
|
||||
function _recaptcha_mailhide_urlbase64 ($x) {
|
||||
return strtr(base64_encode ($x), '+/', '-_');
|
||||
}
|
||||
|
||||
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
|
||||
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
|
||||
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
|
||||
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
|
||||
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
|
||||
}
|
||||
|
||||
|
||||
$ky = pack('H*', $privkey);
|
||||
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
|
||||
|
||||
return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the parts of the email to expose to the user.
|
||||
* eg, given johndoe@example,com return ["john", "example.com"].
|
||||
* the email is then displayed as john...@example.com
|
||||
*/
|
||||
function _recaptcha_mailhide_email_parts ($email) {
|
||||
$arr = preg_split("/@/", $email );
|
||||
|
||||
if (strlen ($arr[0]) <= 4) {
|
||||
$arr[0] = substr ($arr[0], 0, 1);
|
||||
} else if (strlen ($arr[0]) <= 6) {
|
||||
$arr[0] = substr ($arr[0], 0, 3);
|
||||
} else {
|
||||
$arr[0] = substr ($arr[0], 0, 4);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets html to display an email address given a public an private key.
|
||||
* to get a key, go to:
|
||||
*
|
||||
* http://www.google.com/recaptcha/mailhide/apikey
|
||||
*/
|
||||
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
|
||||
$emailparts = _recaptcha_mailhide_email_parts ($email);
|
||||
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
|
||||
|
||||
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
|
||||
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Swekey
|
||||
*/
|
||||
?>
|
||||
|
||||
<script>
|
||||
|
||||
var g_SwekeyPlugin = null;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Create the swekey plugin if it does not exists
|
||||
function Swekey_Plugin()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (g_SwekeyPlugin != null)
|
||||
return g_SwekeyPlugin;
|
||||
|
||||
if (window.ActiveXObject)
|
||||
{
|
||||
g_SwekeyPlugin = document.getElementById("swekey_activex");
|
||||
if (g_SwekeyPlugin == null)
|
||||
{
|
||||
// we must create the activex that way instead of new ActiveXObject("FbAuthAx.FbAuthCtl");
|
||||
// ortherwise SetClientSite is not called and we can not get the url
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML='<object id="swekey_activex" style="display:none" CLASSID="CLSID:8E02E3F9-57AA-4EE1-AA68-A42DD7B0FADE"></object>';
|
||||
|
||||
// Never append to the body because it may still loading and it breaks IE
|
||||
document.body.insertBefore(div, document.body.firstChild);
|
||||
g_SwekeyPlugin = document.getElementById("swekey_activex");
|
||||
}
|
||||
return g_SwekeyPlugin;
|
||||
}
|
||||
|
||||
g_SwekeyPlugin = document.getElementById("swekey_plugin");
|
||||
if (g_SwekeyPlugin != null)
|
||||
return g_SwekeyPlugin;
|
||||
|
||||
for (i = 0; i < navigator.plugins.length; i ++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (navigator.plugins[i] == null)
|
||||
{
|
||||
navigator.plugins.refresh();
|
||||
}
|
||||
else if (navigator.plugins[i][0] != null && navigator.plugins[i][0].type == "application/fbauth-plugin")
|
||||
{
|
||||
var x = document.createElement('embed');
|
||||
x.setAttribute('type', 'application/fbauth-plugin');
|
||||
x.setAttribute('id', 'swekey_plugin');
|
||||
x.setAttribute('width', '0');
|
||||
x.setAttribute('height', '0');
|
||||
x.style.dislay='none';
|
||||
|
||||
//document.body.appendChild(x);
|
||||
document.body.insertBefore(x, document.body.firstChild);
|
||||
g_SwekeyPlugin = document.getElementById("swekey_plugin");
|
||||
return g_SwekeyPlugin;
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
navigator.plugins.refresh();
|
||||
//alert ('Failed to create plugin: ' + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
//alert("Swekey_Plugin " + e);
|
||||
g_SwekeyPlugin = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Returns true if the swekey plugin is installed
|
||||
function Swekey_Installed()
|
||||
{
|
||||
return (Swekey_Plugin() != null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// List the id of the Swekey connected to the PC
|
||||
// Returns a string containing comma separated Swekey Ids
|
||||
// A Swekey is a 32 char hexadecimal value.
|
||||
function Swekey_ListKeyIds()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().list();
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_ListKeyIds " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Ask the Connected Swekey to generate an OTP
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
function Swekey_GetOtp(id, rt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().getotp(id, rt);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_GetOtp " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Ask the Connected Swekey to generate a OTP linked to the current https host
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
// or "" if the current url does not start with https
|
||||
function Swekey_GetLinkedOtp(id, rt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().getlinkedotp(id, rt);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_GetSOtp " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Calls Swekey_GetOtp or Swekey_GetLinkedOtp depending if we are in
|
||||
// an https page or not.
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
function Swekey_GetSmartOtp(id, rt)
|
||||
{
|
||||
var res = Swekey_GetLinkedOtp(id, rt);
|
||||
if (res == "")
|
||||
res = Swekey_GetOtp(id, rt);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Set a unplug handler (url) to the specified connected feebee
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// key: The key that index that url, (aplhanumeric values only)
|
||||
// url: The url that will be launched ("" deletes the url)
|
||||
function Swekey_SetUnplugUrl(id, key, url)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().setunplugurl(id, key, url);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_SetUnplugUrl " + e);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEKjCCAxKgAwIBAgIJAMjw7QcLWCd6MA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5j
|
||||
LjESMBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2Jl
|
||||
LmNvbTAeFw0wODA5MDQxNDE2MTNaFw0zNzEyMjExNDE2MTNaMGsxCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
|
||||
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
|
||||
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBhOljxVzQfK4gted2I
|
||||
d3BemcjW4abAUOzn3KYWXpPO5xIfVeXNDGkDbyH+X+7fo94sX25/ewuKNFDSOcvo
|
||||
tXHq7uQenTHB35r+a+LY81KceUHgW90a3XsqPAkwAjyYcgo3zmM2DtLvw+5Yod8T
|
||||
wAHk9m3qavnQ1uk99jBTwL7RZ9jIZHh9pFCL93uJc2obtd8O96Iycbn2q0w/AWbb
|
||||
+eUVWIHzvLtfPvROeL3lJzr/Uz5LjKapxJ3qyqASflfHpnj9pU8l6g2TQ6Hg5KT5
|
||||
tLFkRe7uGhOfRtOQ/+NjaWrEuNCFnpyN4Q5Fv+5qA1Ip1IpH0200sWbAf/k2u0Qp
|
||||
Sx0CAwEAAaOB0DCBzTAdBgNVHQ4EFgQUczJrQ7hCvtsnzcqiDIZ/GSn/CiwwgZ0G
|
||||
A1UdIwSBlTCBkoAUczJrQ7hCvtsnzcqiDIZ/GSn/Ciyhb6RtMGsxCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
|
||||
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
|
||||
bYIJAMjw7QcLWCd6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGxk
|
||||
8xzIljeBDQWWVRr0NEALVSv3i09V4jAKkyEOfmZ8lKMKJi0atwbtjrXTzLnNYj+Q
|
||||
pyUbyY/8ItWvV7pnVxMiF9qcer7e9X4vw358GZuMVE/da1nWxz+CwzTm5oO30RzA
|
||||
antM9bISFFr9lJq69bDWOnCUi1IG8DSL3TxtlABso7S4vqiZ+sB33l6k1K4a/Njb
|
||||
QkU9UejKhKkVVZTsOrumfnOJ4MCmPfX8Y/AY2o670y5HnzpxerIYziCVzApPVrW7
|
||||
sKH0tuVGturMfQOKgstYe4/m9glBTeTLMkjD+6MJC2ONBD7GAiOO95gNl5M1fzJQ
|
||||
FEe5CJ7DCYl0GdmLXXw=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package Swekey
|
||||
*/
|
||||
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks Swekey authentication.
|
||||
*/
|
||||
function Swekey_Auth_check()
|
||||
{
|
||||
global $cfg;
|
||||
$confFile = $cfg['Server']['auth_swekey_config'];
|
||||
|
||||
if (! isset($_SESSION['SWEKEY'])) {
|
||||
$_SESSION['SWEKEY'] = array();
|
||||
}
|
||||
|
||||
$_SESSION['SWEKEY']['ENABLED'] = (! empty($confFile) && file_exists($confFile));
|
||||
|
||||
// Load the swekey.conf file the first time
|
||||
if ($_SESSION['SWEKEY']['ENABLED']
|
||||
&& empty($_SESSION['SWEKEY']['CONF_LOADED'])
|
||||
) {
|
||||
$_SESSION['SWEKEY']['CONF_LOADED'] = true;
|
||||
$_SESSION['SWEKEY']['VALID_SWEKEYS'] = array();
|
||||
$valid_swekeys = explode("\n", @file_get_contents($confFile));
|
||||
foreach ($valid_swekeys as $line) {
|
||||
if (preg_match("/^[0-9A-F]{32}:.+$/", $line) != false) {
|
||||
$items = explode(":", $line);
|
||||
if (count($items) == 2) {
|
||||
$_SESSION['SWEKEY']['VALID_SWEKEYS'][$items[0]] = trim($items[1]);
|
||||
}
|
||||
} elseif (preg_match("/^[A-Z_]+=.*$/", $line) != false) {
|
||||
$items = explode("=", $line);
|
||||
$_SESSION['SWEKEY']['CONF_'.trim($items[0])] = trim($items[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set default values for settings
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_CHECK'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_CHECK'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_STATUS'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_STATUS'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_CA_FILE'])) {
|
||||
$_SESSION['SWEKEY']['CONF_CA_FILE'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'])) {
|
||||
$_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'] = true;
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_DEBUG'])) {
|
||||
$_SESSION['SWEKEY']['CONF_DEBUG'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a web key has been authenticated
|
||||
if ($_SESSION['SWEKEY']['ENABLED']) {
|
||||
if (empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle Swekey authentication error.
|
||||
*/
|
||||
function Swekey_Auth_error()
|
||||
{
|
||||
if (! isset($_SESSION['SWEKEY'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $_SESSION['SWEKEY']['ENABLED']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
include_once './libraries/plugins/auth/swekey/authentication.inc.php';
|
||||
|
||||
?>
|
||||
<script>
|
||||
function Swekey_GetValidKey()
|
||||
{
|
||||
var valids = "<?php
|
||||
foreach ($_SESSION['SWEKEY']['VALID_SWEKEYS'] as $key => $value) {
|
||||
echo $key.',';
|
||||
}
|
||||
?>";
|
||||
var connected_keys = Swekey_ListKeyIds().split(",");
|
||||
for (i in connected_keys) {
|
||||
if (connected_keys[i] != null && connected_keys[i].length == 32) {
|
||||
if (valids.indexOf(connected_keys[i]) >= 0) {
|
||||
return connected_keys[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (connected_keys.length > 0) {
|
||||
if (connected_keys[0].length == 32) {
|
||||
return "unknown_key_" + connected_keys[0];
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
var key = Swekey_GetValidKey();
|
||||
|
||||
function timedCheck()
|
||||
{
|
||||
if (key != Swekey_GetValidKey()) {
|
||||
window.location.search = "?swekey_reset";
|
||||
} else {
|
||||
setTimeout("timedCheck()",1000);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout("timedCheck()",1000);
|
||||
</script>
|
||||
<?php
|
||||
|
||||
if (! empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count($_SESSION['SWEKEY']['VALID_SWEKEYS']) == 0) {
|
||||
return sprintf(
|
||||
__('File %s does not contain any key id'),
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config']
|
||||
);
|
||||
}
|
||||
|
||||
include_once "libraries/plugins/auth/swekey/swekey.php";
|
||||
|
||||
Swekey_SetCheckServer($_SESSION['SWEKEY']['CONF_SERVER_CHECK']);
|
||||
Swekey_SetRndTokenServer($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN']);
|
||||
Swekey_SetStatusServer($_SESSION['SWEKEY']['CONF_SERVER_STATUS']);
|
||||
Swekey_EnableTokenCache($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE']);
|
||||
|
||||
$caFile = $_SESSION['SWEKEY']['CONF_CA_FILE'];
|
||||
if (empty($caFile)) {
|
||||
$caFile = __FILE__;
|
||||
$pos = strrpos($caFile, '/');
|
||||
if ($pos === false) {
|
||||
$pos = strrpos($caFile, '\\'); // windows
|
||||
}
|
||||
$caFile = substr($caFile, 0, $pos + 1).'musbe-ca.crt';
|
||||
// echo "\n<!-- $caFile -->\n";
|
||||
// if (file_exists($caFile))
|
||||
// echo "<!-- exists -->\n";
|
||||
}
|
||||
|
||||
if (file_exists($caFile)) {
|
||||
Swekey_SetCAFile($caFile);
|
||||
} elseif (! empty($caFile)
|
||||
&& (substr($_SESSION['SWEKEY']['CONF_SERVER_CHECK'], 0, 8) == "https://")) {
|
||||
return "Internal Error: CA File $caFile not found";
|
||||
}
|
||||
|
||||
$result = null;
|
||||
$swekey_id = $_GET['swekey_id'];
|
||||
$swekey_otp = $_GET['swekey_otp'];
|
||||
|
||||
if (isset($swekey_id)) {
|
||||
unset($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY']);
|
||||
if (! isset($_SESSION['SWEKEY']['RND_TOKEN'])) {
|
||||
unset($swekey_id);
|
||||
} else {
|
||||
if (strlen($swekey_id) == 32) {
|
||||
$res = Swekey_CheckOtp($swekey_id, $_SESSION['SWEKEY']['RND_TOKEN'], $swekey_otp);
|
||||
unset($_SESSION['SWEKEY']['RND_TOKEN']);
|
||||
if (! $res) {
|
||||
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
|
||||
} else {
|
||||
$_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'] = $swekey_id;
|
||||
$_SESSION['SWEKEY']['FORCE_USER'] = $_SESSION['SWEKEY']['VALID_SWEKEYS'][$swekey_id];
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$result = __('No valid authentication key plugged');
|
||||
if ($_SESSION['SWEKEY']['CONF_DEBUG']) {
|
||||
$result .= "<br/>" . htmlspecialchars($swekey_id);
|
||||
}
|
||||
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unset($_SESSION['SWEKEY']);
|
||||
}
|
||||
|
||||
$_SESSION['SWEKEY']['RND_TOKEN'] = Swekey_GetFastRndToken();
|
||||
if (strlen($_SESSION['SWEKEY']['RND_TOKEN']) != 64) {
|
||||
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
|
||||
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
|
||||
}
|
||||
|
||||
if (! isset($swekey_id)) {
|
||||
?>
|
||||
<script>
|
||||
if (key.length != 32) {
|
||||
window.location.search="?swekey_id=" + key + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
|
||||
} else {
|
||||
var url = "" + window.location;
|
||||
if (url.indexOf("?") > 0) {
|
||||
url = url.substr(0, url.indexOf("?"));
|
||||
}
|
||||
Swekey_SetUnplugUrl(key, "pma_login", url + "?session_to_unset=<?php echo session_id();?>&token=<?php echo $_SESSION[' PMA_token ']; ?>");
|
||||
var otp = Swekey_GetOtp(key, <?php echo '"'.$_SESSION['SWEKEY']['RND_TOKEN'].'"';?>);
|
||||
window.location.search="?swekey_id=" + key + "&swekey_otp=" + otp + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
return __('Authenticating…');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform login using Swekey.
|
||||
*/
|
||||
function Swekey_login($input_name, $input_go)
|
||||
{
|
||||
$swekeyErr = Swekey_Auth_error();
|
||||
if ($swekeyErr != null) {
|
||||
PMA_Message::error($swekeyErr)->display();
|
||||
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
|
||||
echo '<div>';
|
||||
$GLOBALS['error_handler']->dispErrors();
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SESSION['SWEKEY']) && $_SESSION['SWEKEY']['ENABLED']) {
|
||||
echo '<script type="text/javascript">';
|
||||
if (empty($_SESSION['SWEKEY']['FORCE_USER'])) {
|
||||
echo 'var user = null;';
|
||||
} else {
|
||||
echo 'var user = "'.$_SESSION['SWEKEY']['FORCE_USER'].'";';
|
||||
}
|
||||
|
||||
?>
|
||||
function open_swekey_site()
|
||||
{
|
||||
window.open("<?php echo PMA_linkURL('http://phpmyadmin.net/auth_key'); ?>");
|
||||
}
|
||||
|
||||
var input_username = document.getElementById("<?php echo $input_name; ?>");
|
||||
var input_go = document.getElementById("<?php echo $input_go; ?>");
|
||||
var swekey_status = document.createElement('img');
|
||||
swekey_status.setAttribute('onclick', 'open_swekey_site()');
|
||||
swekey_status.setAttribute('style', 'width:8px; height:16px; border:0px; vspace:0px; hspace:0px; frameborder:no');
|
||||
if (user == null) {
|
||||
swekey_status.setAttribute('src', 'http://artwork.swekey.com/unplugged-8x16.png');
|
||||
//swekey_status.setAttribute('title', 'No swekey plugged');
|
||||
input_go.disabled = true;
|
||||
} else {
|
||||
swekey_status.setAttribute('src', 'http://artwork.swekey.com/plugged-8x16.png');
|
||||
//swekey_status.setAttribute('title', 'swekey plugged');
|
||||
input_username.value = user;
|
||||
}
|
||||
input_username.readOnly = true;
|
||||
|
||||
if (input_username.nextSibling == null) {
|
||||
input_username.parentNode.appendChild(swekey_status);
|
||||
} else {
|
||||
input_username.parentNode.insertBefore(swekey_status, input_username.nextSibling);
|
||||
}
|
||||
|
||||
<?php
|
||||
echo '</script>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_GET['session_to_unset'])) {
|
||||
session_write_close();
|
||||
session_id($_GET['session_to_unset']);
|
||||
session_start();
|
||||
$_SESSION = array();
|
||||
session_write_close();
|
||||
session_destroy();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET['swekey_reset'])) {
|
||||
unset($_SESSION['SWEKEY']);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,522 @@
|
||||
<?php
|
||||
/**
|
||||
* Library that provides common functions that are used to help integrating Swekey Authentication in a PHP web site
|
||||
* Version 1.0
|
||||
*
|
||||
* History:
|
||||
* 1.2 Use curl (widely installed) to query the server
|
||||
* Fixed a possible tempfile race attack
|
||||
* Random token cache can now be disabled
|
||||
* 1.1 Added Swekey_HttpGet function that support faulty servers
|
||||
* Support for custom servers
|
||||
* 1.0 First release
|
||||
*
|
||||
* @package Swekey
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Errors codes
|
||||
*/
|
||||
define("SWEKEY_ERR_INVALID_DEV_STATUS", 901); // The satus of the device is not SWEKEY_STATUS_OK
|
||||
define("SWEKEY_ERR_INTERNAL", 902); // Should never occurd
|
||||
define("SWEKEY_ERR_OUTDATED_RND_TOKEN", 910); // You random token is too old
|
||||
define("SWEKEY_ERR_INVALID_OTP", 911); // The otp was not correct
|
||||
|
||||
/**
|
||||
* Those errors are considered as an attack and your site will be blacklisted during one minute
|
||||
* if you receive one of those errors
|
||||
*/
|
||||
define("SWEKEY_ERR_BADLY_ENCODED_REQUEST", 920);
|
||||
define("SWEKEY_ERR_INVALID_RND_TOKEN", 921);
|
||||
define("SWEKEY_ERR_DEV_NOT_FOUND", 922);
|
||||
|
||||
/**
|
||||
* Default values for configuration.
|
||||
*/
|
||||
define('SWEKEY_DEFAULT_CHECK_SERVER', 'https://auth-check.musbe.net');
|
||||
define('SWEKEY_DEFAULT_RND_SERVER', 'https://auth-rnd-gen.musbe.net');
|
||||
define('SWEKEY_DEFAULT_STATUS_SERVER', 'https://auth-status.musbe.net');
|
||||
|
||||
/**
|
||||
* The last error of an operation is alway put in this global var
|
||||
*/
|
||||
|
||||
global $gSwekeyLastError;
|
||||
$gSwekeyLastError = 0;
|
||||
|
||||
global $gSwekeyLastResult;
|
||||
$gSwekeyLastResult = "<not set>";
|
||||
|
||||
/**
|
||||
* Servers addresses
|
||||
* Use the Swekey_SetXxxServer($server) functions to set them
|
||||
*/
|
||||
|
||||
global $gSwekeyCheckServer;
|
||||
if (! isset($gSwekeyCheckServer)) {
|
||||
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyRndTokenServer;
|
||||
if (! isset($gSwekeyRndTokenServer)) {
|
||||
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyStatusServer;
|
||||
if (! isset($gSwekeyStatusServer)) {
|
||||
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyCA;
|
||||
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
if (! isset($gSwekeyTokenCacheEnabled)) {
|
||||
$gSwekeyTokenCacheEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Check server.
|
||||
* If $server is empty the default value 'http://auth-check.musbe.net' will be used
|
||||
*
|
||||
* @param server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetCheckServer($server)
|
||||
{
|
||||
global $gSwekeyCheckServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
|
||||
} else {
|
||||
$gSwekeyCheckServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Random Token Generator server.
|
||||
* If $server is empty the default value 'http://auth-rnd-gen.musbe.net' will be used
|
||||
*
|
||||
* @param server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetRndTokenServer($server)
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
|
||||
} else {
|
||||
$gSwekeyRndTokenServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Satus server.
|
||||
* If $server is empty the default value 'http://auth-status.musbe.net' will be used
|
||||
*
|
||||
* @param server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetStatusServer($server)
|
||||
{
|
||||
global $gSwekeyStatusServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
|
||||
} else {
|
||||
$gSwekeyStatusServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the certificat file in case of the the severs use https instead of http
|
||||
*
|
||||
* @param cafile The path of the crt file to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetCAFile($cafile)
|
||||
{
|
||||
global $gSwekeyCA;
|
||||
$gSwekeyCA = $cafile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the random token caching
|
||||
* Because everybody has full access to the cache file, it can be a DOS vulnerability
|
||||
* So disable it if you are running in a non secure enviromnement
|
||||
*
|
||||
* @param $enable
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_EnableTokenCache($enable)
|
||||
{
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
$gSwekeyTokenCacheEnabled = ! empty($enable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the last error.
|
||||
*
|
||||
* @return The Last Error
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetLastError()
|
||||
{
|
||||
global $gSwekeyLastError;
|
||||
return $gSwekeyLastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last result.
|
||||
*
|
||||
* @return The Last Error
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetLastResult()
|
||||
{
|
||||
global $gSwekeyLastResult;
|
||||
return $gSwekeyLastResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a synchronous request to the server.
|
||||
* This function manages timeout then will not block if one of the server is down
|
||||
*
|
||||
* @param url The url to get
|
||||
* @param response_code The response code
|
||||
*
|
||||
* @return The body of the response or "" in case of error
|
||||
* @access private
|
||||
*/
|
||||
function Swekey_HttpGet($url, &$response_code)
|
||||
{
|
||||
global $gSwekeyLastError;
|
||||
$gSwekeyLastError = 0;
|
||||
global $gSwekeyLastResult;
|
||||
$gSwekeyLastResult = "<not set>";
|
||||
|
||||
// use curl if available
|
||||
if (function_exists('curl_init')) {
|
||||
$sess = curl_init($url);
|
||||
if (substr($url, 0, 8) == "https://") {
|
||||
global $gSwekeyCA;
|
||||
|
||||
if (! empty($gSwekeyCA)) {
|
||||
if (file_exists($gSwekeyCA)) {
|
||||
if (! curl_setopt($sess, CURLOPT_CAINFO, $gSwekeyCA)) {
|
||||
error_log("SWEKEY_ERROR:Could not set CA file : ".curl_error($sess));
|
||||
} else {
|
||||
$caFileOk = true;
|
||||
}
|
||||
} else {
|
||||
error_log("SWEKEY_ERROR:Could not find CA file $gSwekeyCA getting $url");
|
||||
}
|
||||
}
|
||||
|
||||
curl_setopt($sess, CURLOPT_SSL_VERIFYHOST, '2');
|
||||
curl_setopt($sess, CURLOPT_SSL_VERIFYPEER, '2');
|
||||
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '20');
|
||||
curl_setopt($sess, CURLOPT_TIMEOUT, '20');
|
||||
} else {
|
||||
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '3');
|
||||
curl_setopt($sess, CURLOPT_TIMEOUT, '5');
|
||||
}
|
||||
|
||||
curl_setopt($sess, CURLOPT_RETURNTRANSFER, '1');
|
||||
$res=curl_exec($sess);
|
||||
$response_code = curl_getinfo($sess, CURLINFO_HTTP_CODE);
|
||||
$curlerr = curl_error($sess);
|
||||
curl_close($sess);
|
||||
|
||||
if ($response_code == 200) {
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
if (! empty($response_code)) {
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error $gSwekeyLastError ($curlerr) getting $url");
|
||||
return "";
|
||||
}
|
||||
|
||||
$response_code = 408; // Request Timeout
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error $curlerr getting $url");
|
||||
return "";
|
||||
}
|
||||
|
||||
// use pecl_http if available
|
||||
if (class_exists('HttpRequest')) {
|
||||
// retry if one of the server is down
|
||||
for ($num=1; $num <= 3; $num++ ) {
|
||||
$r = new HttpRequest($url);
|
||||
$options = array('timeout' => '3');
|
||||
|
||||
if (substr($url, 0, 6) == "https:") {
|
||||
$sslOptions = array();
|
||||
$sslOptions['verifypeer'] = true;
|
||||
$sslOptions['verifyhost'] = true;
|
||||
|
||||
$capath = __FILE__;
|
||||
$name = strrchr($capath, '/');
|
||||
// windows
|
||||
if (empty($name)) {
|
||||
$name = strrchr($capath, '\\');
|
||||
}
|
||||
$capath = substr($capath, 0, strlen($capath) - strlen($name) + 1).'musbe-ca.crt';
|
||||
|
||||
if (! empty($gSwekeyCA)) {
|
||||
$sslOptions['cainfo'] = $gSwekeyCA;
|
||||
}
|
||||
|
||||
$options['ssl'] = $sslOptions;
|
||||
}
|
||||
|
||||
$r->setOptions($options);
|
||||
|
||||
// try
|
||||
{
|
||||
$reply = $r->send();
|
||||
$res = $reply->getBody();
|
||||
$info = $r->getResponseInfo();
|
||||
$response_code = $info['response_code'];
|
||||
if ($response_code != 200) {
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
}
|
||||
// catch (HttpException $e)
|
||||
// {
|
||||
// error_log("SWEKEY_WARNING:HttpException ".$e." getting ".$url);
|
||||
// }
|
||||
}
|
||||
|
||||
$response_code = 408; // Request Timeout
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
|
||||
return "";
|
||||
}
|
||||
|
||||
global $http_response_header;
|
||||
$res = @file_get_contents($url);
|
||||
$response_code = substr($http_response_header[0], 9, 3); //HTTP/1.0
|
||||
if ($response_code == 200) {
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error ".$response_code." getting ".$url);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Random Token from a Token Server
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* You should better use Swekey_GetFastRndToken() for performance
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetRndToken()
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
return Swekey_HttpGet($gSwekeyRndTokenServer.'/FULL-RND-TOKEN', $response_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Half Random Token from a Token Server
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* Use this value if you want to make your own Swekey_GetFastRndToken()
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetHalfRndToken()
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
return Swekey_HttpGet($gSwekeyRndTokenServer.'/HALF-RND-TOKEN', $response_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Half Random Token
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* This function get a new random token and reuse it.
|
||||
* Token are refetched from the server only once every 30 seconds.
|
||||
* You should always use this function to get half random token.
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetFastHalfRndToken()
|
||||
{
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
|
||||
$res = "";
|
||||
$cachefile = "";
|
||||
|
||||
// We check if we have a valid RT is the session
|
||||
if (isset($_SESSION['rnd-token-date'])) {
|
||||
if (time() - $_SESSION['rnd-token-date'] < 30) {
|
||||
$res = $_SESSION['rnd-token'];
|
||||
}
|
||||
}
|
||||
|
||||
// If not we try to get it from a temp file (PHP >= 5.2.1 only)
|
||||
if (strlen($res) != 32 && $gSwekeyTokenCacheEnabled) {
|
||||
if (function_exists('sys_get_temp_dir')) {
|
||||
$tempdir = sys_get_temp_dir();
|
||||
$cachefile = $tempdir."/swekey-rnd-token-".get_current_user();
|
||||
$modif = filemtime($cachefile);
|
||||
if ($modif != false) {
|
||||
if (time() - $modif < 30) {
|
||||
$res = @file_get_contents($cachefile);
|
||||
if (strlen($res) != 32) {
|
||||
$res = "";
|
||||
} else {
|
||||
$_SESSION['rnd-token'] = $res;
|
||||
$_SESSION['rnd-token-date'] = $modif;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have a valid RT here we have to get it from the server
|
||||
if (strlen($res) != 32) {
|
||||
$res = substr(Swekey_GetHalfRndToken(), 0, 32);
|
||||
$_SESSION['rnd-token'] = $res;
|
||||
$_SESSION['rnd-token-date'] = time();
|
||||
if (! empty($cachefile)) {
|
||||
// we unlink the file so no possible tempfile race attack
|
||||
unlink($cachefile);
|
||||
$file = fopen($cachefile, "x");
|
||||
if ($file != false) {
|
||||
@fwrite($file, $res);
|
||||
@fclose($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res."00000000000000000000000000000000";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Random Token
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* This function generates a unique random token for each call but call the
|
||||
* server only once every 30 seconds.
|
||||
* You should always use this function to get random token.
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetFastRndToken()
|
||||
{
|
||||
$res = Swekey_GetFastHalfRndToken();
|
||||
if (strlen($res) == 64) {
|
||||
return substr($res, 0, 32).strtoupper(md5("Musbe Authentication Key" . mt_rand() . date(DATE_ATOM)));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that an OTP generated by a Swekey is valid
|
||||
*
|
||||
* @param id The id of the swekey
|
||||
* @param rt The random token used to generate the otp
|
||||
* @param otp The otp generated by the swekey
|
||||
*
|
||||
* @return true or false
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_CheckOtp($id, $rt, $otp)
|
||||
{
|
||||
global $gSwekeyCheckServer;
|
||||
$res = Swekey_HttpGet($gSwekeyCheckServer.'/CHECK-OTP/'.$id.'/'.$rt.'/'.$otp, $response_code);
|
||||
return $response_code == 200 && $res == "OK";
|
||||
}
|
||||
|
||||
/**
|
||||
* Values that are associated with a key.
|
||||
* The following values can be returned by the Swekey_GetStatus() function
|
||||
*/
|
||||
define("SWEKEY_STATUS_OK", 0);
|
||||
define("SWEKEY_STATUS_NOT_FOUND", 1); // The key does not exist in the db
|
||||
define("SWEKEY_STATUS_INACTIVE", 2); // The key has never been activated
|
||||
define("SWEKEY_STATUS_LOST", 3); // The user has lost his key
|
||||
define("SWEKEY_STATUS_STOLEN", 4); // The key was stolen
|
||||
define("SWEKEY_STATUS_FEE_DUE", 5); // The annual fee was not paid
|
||||
define("SWEKEY_STATUS_OBSOLETE", 6); // The hardware is no longer supported
|
||||
define("SWEKEY_STATUS_UNKOWN", 201); // We could not connect to the authentication server
|
||||
|
||||
/**
|
||||
* Values that are associated with a key.
|
||||
* The Javascript Api can also return the following values
|
||||
*/
|
||||
define("SWEKEY_STATUS_REPLACED", 100); // This key has been replaced by a backup key
|
||||
define("SWEKEY_STATUS_BACKUP_KEY", 101); // This key is a backup key that is not activated yet
|
||||
define("SWEKEY_STATUS_NOTPLUGGED", 200); // This key is not plugged in the computer
|
||||
|
||||
|
||||
/**
|
||||
* Return the text corresponding to the integer status of a key
|
||||
*
|
||||
* @param status The status
|
||||
*
|
||||
* @return The text corresponding to the status
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetStatusStr($status)
|
||||
{
|
||||
switch($status)
|
||||
{
|
||||
case SWEKEY_STATUS_OK :
|
||||
return 'OK';
|
||||
case SWEKEY_STATUS_NOT_FOUND :
|
||||
return 'Key does not exist in the db';
|
||||
case SWEKEY_STATUS_INACTIVE :
|
||||
return 'Key not activated';
|
||||
case SWEKEY_STATUS_LOST :
|
||||
return 'Key was lost';
|
||||
case SWEKEY_STATUS_STOLEN :
|
||||
return 'Key was stolen';
|
||||
case SWEKEY_STATUS_FEE_DUE :
|
||||
return 'The annual fee was not paid';
|
||||
case SWEKEY_STATUS_OBSOLETE :
|
||||
return 'Key no longer supported';
|
||||
case SWEKEY_STATUS_REPLACED :
|
||||
return 'This key has been replaced by a backup key';
|
||||
case SWEKEY_STATUS_BACKUP_KEY :
|
||||
return 'This key is a backup key that is not activated yet';
|
||||
case SWEKEY_STATUS_NOTPLUGGED :
|
||||
return 'This key is not plugged in the computer';
|
||||
case SWEKEY_STATUS_UNKOWN :
|
||||
return 'Unknow Status, could not connect to the authentication server';
|
||||
}
|
||||
return 'unknown status '.$status;
|
||||
}
|
||||
|
||||
/**
|
||||
* If your web site requires a key to login you should check that the key
|
||||
* is still valid (has not been lost or stolen) before requiring it.
|
||||
* A key can be authenticated only if its status is SWEKEY_STATUS_OK
|
||||
*
|
||||
* @param id The id of the swekey
|
||||
*
|
||||
* @return The status of the swekey
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetStatus($id)
|
||||
{
|
||||
global $gSwekeyStatusServer;
|
||||
$res = Swekey_HttpGet($gSwekeyStatusServer.'/GET-STATUS/'.$id, $response_code);
|
||||
if ($response_code == 200) {
|
||||
return intval($res);
|
||||
}
|
||||
return SWEKEY_STATUS_UNKOWN;
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user