summaryrefslogtreecommitdiff
path: root/hugo/libraries/plugins/auth
diff options
context:
space:
mode:
Diffstat (limited to 'hugo/libraries/plugins/auth')
-rw-r--r--hugo/libraries/plugins/auth/AuthenticationConfig.class.php172
-rw-r--r--hugo/libraries/plugins/auth/AuthenticationCookie.class.php696
-rw-r--r--hugo/libraries/plugins/auth/AuthenticationHttp.class.php249
-rw-r--r--hugo/libraries/plugins/auth/AuthenticationSignon.class.php284
-rw-r--r--hugo/libraries/plugins/auth/swekey/authentication.inc.php172
-rw-r--r--hugo/libraries/plugins/auth/swekey/musbe-ca.crt25
-rw-r--r--hugo/libraries/plugins/auth/swekey/swekey.auth.lib.php297
-rw-r--r--hugo/libraries/plugins/auth/swekey/swekey.php522
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;
+}
+
+?>