diff options
Diffstat (limited to 'hugo/libraries/plugins/auth')
| -rw-r--r-- | hugo/libraries/plugins/auth/AuthenticationConfig.class.php | 172 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/AuthenticationCookie.class.php | 696 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/AuthenticationHttp.class.php | 249 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/AuthenticationSignon.class.php | 284 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/swekey/authentication.inc.php | 172 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/swekey/musbe-ca.crt | 25 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/swekey/swekey.auth.lib.php | 297 | ||||
| -rw-r--r-- | hugo/libraries/plugins/auth/swekey/swekey.php | 522 |
8 files changed, 2417 insertions, 0 deletions
diff --git a/hugo/libraries/plugins/auth/AuthenticationConfig.class.php b/hugo/libraries/plugins/auth/AuthenticationConfig.class.php new file mode 100644 index 0000000..07ad7cb --- /dev/null +++ b/hugo/libraries/plugins/auth/AuthenticationConfig.class.php @@ -0,0 +1,172 @@ +<?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 = PMA_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_generate_common_url(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"; + 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) + { + } +} diff --git a/hugo/libraries/plugins/auth/AuthenticationCookie.class.php b/hugo/libraries/plugins/auth/AuthenticationCookie.class.php new file mode 100644 index 0000000..72274d9 --- /dev/null +++ b/hugo/libraries/plugins/auth/AuthenticationCookie.class.php @@ -0,0 +1,696 @@ +<?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 the last connection error + * + * @return 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 + ) + ); + } + exit; + } + + /* Perform logout to custom URL */ + if (! empty($_REQUEST['old_usr']) + && ! empty($GLOBALS['cfg']['Server']['LogoutURL']) + ) { + PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']); + 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"'; + } + + $cell_align = ($GLOBALS['text_dir'] == 'ltr') ? 'left' : 'right'; + + $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) + + 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_generate_common_hidden_inputs($_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; + } + exit; + } + + /** + * 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 PMA_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() + { + // 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; + } + + 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(); + + session_destroy(); + // -> 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(); + exit; + } + + // 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(); + + // 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_generate_common_url($url_params, '&'), + true + ); + exit; + } // 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 (PMA_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) + { + } +} diff --git a/hugo/libraries/plugins/auth/AuthenticationHttp.class.php b/hugo/libraries/plugins/auth/AuthenticationHttp.class.php new file mode 100644 index 0000000..f81ab92 --- /dev/null +++ b/hugo/libraries/plugins/auth/AuthenticationHttp.class.php @@ -0,0 +1,249 @@ +<?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']); + exit; + } + + 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; + } + + exit; + } + + /** + * Gets advanced authentication settings + * + * @global string the username if register_globals is on + * @global string 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 + 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 the valid servers settings + * @global integer the id of the current server + * @global array the current server settings + * @global string the current username + * @global string 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 = PMA_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) + { + } +} diff --git a/hugo/libraries/plugins/auth/AuthenticationSignon.class.php b/hugo/libraries/plugins/auth/AuthenticationSignon.class.php new file mode 100644 index 0000000..ee1cf36 --- /dev/null +++ b/hugo/libraries/plugins/auth/AuthenticationSignon.class.php @@ -0,0 +1,284 @@ +<?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']); + } + exit(); + } + + /** + * Gets advanced authentication settings + * + * @global string the username if register_globals is on + * @global string 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($cfg['Server']['user']); + + } elseif (isset($_COOKIE[$session_name])) { /* Does session exist? */ + /* End current session */ + $old_session = session_name(); + $old_id = session_id(); + session_write_close(); + + /* Load single signon session */ + session_name($session_name); + session_id($_COOKIE[$session_name]); + 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 */ + session_write_close(); + + /* Restart phpMyAdmin session */ + session_name($old_session); + if (!empty($old_id)) { + session_id($old_id); + } + 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 the valid servers settings + * @global integer the id of the current server + * @global array the current server settings + * @global string the current username + * @global string 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 */ + $old_session = session_name(); + $old_id = session_id(); + session_write_close(); + + /* Load single signon session */ + session_name($session_name); + session_id($_COOKIE[$session_name]); + 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 (PMA_DBI_getError()) { + $_SESSION['PMA_single_signon_error_message'] = PMA_sanitize( + PMA_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) + { + } +}
\ No newline at end of file diff --git a/hugo/libraries/plugins/auth/swekey/authentication.inc.php b/hugo/libraries/plugins/auth/swekey/authentication.inc.php new file mode 100644 index 0000000..1977f88 --- /dev/null +++ b/hugo/libraries/plugins/auth/swekey/authentication.inc.php @@ -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> diff --git a/hugo/libraries/plugins/auth/swekey/musbe-ca.crt b/hugo/libraries/plugins/auth/swekey/musbe-ca.crt new file mode 100644 index 0000000..2a31ad1 --- /dev/null +++ b/hugo/libraries/plugins/auth/swekey/musbe-ca.crt @@ -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----- diff --git a/hugo/libraries/plugins/auth/swekey/swekey.auth.lib.php b/hugo/libraries/plugins/auth/swekey/swekey.auth.lib.php new file mode 100644 index 0000000..678cb1a --- /dev/null +++ b/hugo/libraries/plugins/auth/swekey/swekey.auth.lib.php @@ -0,0 +1,297 @@ +<?php +/** + * @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']); +} + +?> diff --git a/hugo/libraries/plugins/auth/swekey/swekey.php b/hugo/libraries/plugins/auth/swekey/swekey.php new file mode 100644 index 0000000..d495d45 --- /dev/null +++ b/hugo/libraries/plugins/auth/swekey/swekey.php @@ -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; +} + +?> |
