3 // vim: expandtab sw=4 ts=4 sts=4:
6 // +--------------------------------------------------------------------------+
7 // | Set of functions used to run cookie based authentication. |
8 // | Thanks to Piotr Roszatycki <d3xter at users.sourceforge.net> and |
9 // | Dan Wilson who builds this patch for the Debian package. |
10 // +--------------------------------------------------------------------------+
13 if (!defined('PMA_COOKIE_AUTH_INCLUDED')) {
14 define('PMA_COOKIE_AUTH_INCLUDED', 1);
16 if (!isset($coming_from_common)) {
19 // emulate array_values() for PHP 3
20 // if (PMA_PHP_INT_VERSION < 40000) {
21 if (!@function_exists
('array_values')) {
22 function array_values ($arr) {
24 while (list($k, $v) = each ($arr)) {
31 include('./libraries/blowfish.php3');
33 // Gets the default font sizes
35 // Defines the cookie path and whether the server is using https or not
36 $pma_uri_parts = parse_url($cfg['PmaAbsoluteUri']);
37 $cookie_path = substr($pma_uri_parts['path'], 0, strrpos($pma_uri_parts['path'], '/'));
38 $is_https = (isset($pma_uri_parts['scheme']) && $pma_uri_parts['scheme'] == 'https') ?
1 : 0;
43 * @param string input string
44 * @param integer length of the result
45 * @param string the filling string
46 * @param integer padding mode
48 * @return string the padded string
52 function full_str_pad($input, $pad_length, $pad_string = '', $pad_type = 0) {
54 $length = $pad_length - strlen($input);
55 if ($length > 0) { // str_repeat doesn't like negatives
56 if ($pad_type == STR_PAD_RIGHT
) { // STR_PAD_RIGHT == 1
57 $str = $input.str_repeat($pad_string, $length);
58 } elseif ($pad_type == STR_PAD_BOTH
) { // STR_PAD_BOTH == 2
59 $str = str_repeat($pad_string, floor($length/2));
61 $str .= str_repeat($pad_string, ceil($length/2));
62 } else { // defaults to STR_PAD_LEFT == 0
63 $str = str_repeat($pad_string, $length).$input;
65 } else { // if $length is negative or zero we don't need to do anything
72 * Encryption using blowfish algorithm
74 * @param string original data
75 * @param string the secret
77 * @return string the encrypted result
83 function PMA_blowfish_encrypt($data, $secret) {
84 $pma_cipher = new Horde_Cipher_blowfish
;
86 for ($i=0; $i<strlen($data); $i+
=8) {
87 $block = substr($data, $i, 8);
88 if (strlen($block) < 8) {
89 $block = full_str_pad($block,8,"\0", 1);
91 $encrypt .= $pma_cipher->encryptBlock($block, $secret);
97 * Decryption using blowfish algorithm
99 * @param string encrypted data
100 * @param string the secret
102 * @return string original data
108 function PMA_blowfish_decrypt($data, $secret) {
109 $pma_cipher = new Horde_Cipher_blowfish
;
111 for ($i=0; $i<strlen($data); $i+
=8) {
112 $decrypt .= $pma_cipher->decryptBlock(substr($data, $i, 8), $secret);
114 return trim($decrypt);
118 * Sorts available languages by their true names
120 * @param array the array to be sorted
121 * @param mixed a required parameter
123 * @return the sorted array
127 function PMA_cookie_cmp(&$a, $b)
129 return (strcmp($a[1], $b[1]));
130 } // end of the 'PMA_cmp()' function
134 * Displays authentication form
136 * @global string the font face to use
137 * @global string the default font size to use
138 * @global string the big font size to use
139 * @global array the list of servers settings
140 * @global array the list of available translations
141 * @global string the current language
142 * @global integer the current server id
143 * @global string the currect charset for MySQL
144 * @global array the array of cookie variables if register_globals is
147 * @return boolean always true (no return indeed)
153 global $right_font_family, $font_size, $font_bigger;
154 global $cfg, $available_languages;
155 global $lang, $server, $convcharset;
157 global $HTTP_COOKIE_VARS;
159 // Tries to get the username from cookie whatever are the values of the
160 // 'register_globals' and the 'variables_order' directives if last login
161 // should be recalled, else skip the IE autocomplete feature.
162 if ($cfg['LoginCookieRecall']) {
163 if (!empty($GLOBALS['pma_cookie_username'])) {
164 $default_user = $GLOBALS['pma_cookie_username'];
166 else if (!empty($_COOKIE) && isset($_COOKIE['pma_cookie_username'])) {
167 $default_user = $_COOKIE['pma_cookie_username'];
169 else if (!empty($HTTP_COOKIE_VARS) && isset($HTTP_COOKIE_VARS['pma_cookie_username'])) {
170 $default_user = $HTTP_COOKIE_VARS['pma_cookie_username'];
172 if (isset($default_user) && get_magic_quotes_gpc()) {
173 $default_user = stripslashes($default_user);
179 $autocomplete = ' autocomplete="off"';
182 $cell_align = ($GLOBALS['text_dir'] == 'ltr') ?
'left' : 'right';
184 // Defines the charset to be used
185 header('Content-Type: text/html; charset=' . $GLOBALS['charset']);
189 <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
190 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
191 <html xmlns
="http://www.w3.org/1999/xhtml" xml
:lang
="<?php echo $GLOBALS['available_languages'][$GLOBALS['lang']][2]; ?>" lang
="<?php echo $GLOBALS['available_languages'][$GLOBALS['lang']][2]; ?>" dir
="<?php echo $GLOBALS['text_dir']; ?>">
194 <title
>phpMyAdmin
<?php
echo PMA_VERSION
; ?
></title
>
195 <meta http
-equiv
="Content-Type" content
="text/html; charset=<?php echo $GLOBALS['charset']; ?>" />
196 <base href
="<?php echo $cfg['PmaAbsoluteUri']; ?>" />
197 <style type
="text/css">
199 body
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_size; ?
>; color
: #000000}
200 td
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_size; ?
>; color
: #000000}
201 h1
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_bigger; ?
>; font
-weight
: bold
}
202 select
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_size; ?
>; background
-color
:#ffffff; color:#000000}
203 input
.textfield
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_size; ?
>; background
-color
:#ffffff; color:#000000}
204 .warning
{font
-family
: <?php
echo $right_font_family; ?
>; font
-size
: <?php
echo $font_size; ?
>; font
-weight
: bold
; color
: #FF0000}
209 <body bgcolor
="<?php echo $cfg['RightBgColor']; ?>">
211 <a href
="http://www.phpmyadmin.net" target
="_blank"><img name
="imLogo" id
="imLogo" src
="images/pma_logo.png" border
="0" width
="88" height
="31" alt
="phpMyAdmin" /></a
>
212 <h1
><?php
echo sprintf($GLOBALS['strWelcome'], ' phpMyAdmin ' . PMA_VERSION
. ' - ' . $GLOBALS['strLogin']); ?
></h1
>
216 // Displays the languages form
217 if (empty($cfg['Lang'])) {
220 <!-- Language selection
-->
221 <form method
="post" action
="index.php3">
222 <input type
="hidden" name
="server" value
="<?php echo $server; ?>" />
223 <b
>Language
: 
;</b
>
224 <select name
="lang" dir
="ltr" onchange
="this.form.submit();">
228 uasort($available_languages, 'PMA_cookie_cmp');
229 reset($available_languages);
230 while (list($id, $tmplang) = each($available_languages)) {
231 $lang_name = ucfirst(substr(strstr($tmplang[0], '|'), 1));
233 $selected = ' selected="selected"';
238 echo '<option value="' . $id . '"' . $selected . '>' . $lang_name . ' (' . $id . ')</option>' . "\n";
242 <input type
="submit" value
="<?php echo $GLOBALS['strGo']; ?>" />
249 // Displays the warning message and the login form
251 if ($GLOBALS['cfg']['blowfish_secret']=='') {
253 <p
class="warning"><?php
echo $GLOBALS['strSecretRequired']; ?
></p
>
260 <p
><?php
echo '(' . $GLOBALS['strCookiesRequired'] . ')'; ?
></p
>
265 <form method
="post" action
="index.php3" name
="login_form"<?php
echo $autocomplete; ?
>>
266 <table cellpadding
="5">
268 <td align
="<?php echo $cell_align; ?>"><b
><?php
echo $GLOBALS['strLogUsername']; ?
> 
;</b
></td
>
269 <td align
="<?php echo $cell_align; ?>">
270 <input type
="text" name
="pma_username" value
="<?php echo (isset($default_user) ? $default_user : ''); ?>" size
="24" class="textfield" onfocus
="this.select()" />
274 <td align
="<?php echo $cell_align; ?>"><b
><?php
echo $GLOBALS['strLogPassword']; ?
> 
;</b
></td
>
275 <td align
="<?php echo $cell_align; ?>">
276 <input type
="password" name
="pma_password" value
="" size
="24" class="textfield" onfocus
="this.select()" />
280 if (count($cfg['Servers']) > 1) {
284 <td align
="<?php echo $cell_align; ?>"><b
><?php
echo $GLOBALS['strServerChoice']; ?
> 
;: 
;</b
></td
>
285 <td align
="<?php echo $cell_align; ?>">
286 <select name
="server">
289 // Displays the MySQL servers choice
290 reset($cfg['Servers']);
291 while (list($key, $val) = each($cfg['Servers'])) {
292 if (!empty($val['host'])) {
293 echo ' <option value="' . $key . '"';
294 if (!empty($server) && ($server == $key)) {
295 echo ' selected="selected"';
298 if ($val['verbose'] != '') {
299 echo $val['verbose'];
302 if (!empty($val['port'])) {
303 echo ':' . $val['port'];
305 // loic1: skip this because it's not a so good idea to
306 // display sockets used to everybody
307 // if (!empty($val['socket']) && PMA_PHP_INT_VERSION >= 30010) {
308 // echo ':' . $val['socket'];
311 // loic1: if 'only_db' is an array and there is more than one
312 // value, displaying such informations may not be a so
314 if (!empty($val['only_db'])) {
315 echo ' - ' . (is_array($val['only_db']) ?
implode(', ', $val['only_db']) : $val['only_db']);
317 if (!empty($val['user']) && ($val['auth_type'] == 'basic')) {
318 echo ' (' . $val['user'] . ')';
320 echo ' </option>' . "\n";
321 } // end if (!empty($val['host']))
328 } // end if (server choice)
332 if (!empty($conn_error)) {
333 echo '<tr><td colspan="2" align="center"><p class="warning">'.
335 '</p></td></tr>'."\n";
339 <td colspan
="2" align
="center">
341 if (count($cfg['Servers']) == 1) {
342 echo ' <input type="hidden" name="server" value="' . $server . '" />';
346 <input type
="hidden" name
="lang" value
="<?php echo $lang; ?>" />
347 <input type
="hidden" name
="convcharset" value
="<?php echo $convcharset; ?>" />
348 <input type
="submit" value
="<?php echo $GLOBALS['strLogin']; ?>" />
355 <script type
="text/javascript" language
="javascript">
356 var uname
= document
.forms
['login_form'].elements
['pma_username'];
357 var pword
= document
.forms
['login_form'].elements
['pma_password'];
358 if (uname
.value
== '') {
371 } // end of the 'PMA_auth()' function
375 * Gets advanced authentication settings
377 * @global string the username if register_globals is on
378 * @global string the password if register_globals is on
379 * @global array the array of cookie variables if register_globals is
381 * @global string the username sent by the login form
382 * @global string the password sent by the login form
383 * @global string the username of the user who logs out
384 * @global boolean whether the login/password pair is grabbed from a
387 * @return boolean whether we get authentication settings or not
391 function PMA_auth_check()
393 global $PHP_AUTH_USER, $PHP_AUTH_PW;
394 global $HTTP_COOKIE_VARS;
395 global $pma_username, $pma_password, $old_usr;
399 $PHP_AUTH_USER = $PHP_AUTH_PW = '';
400 $from_cookie = FALSE;
403 // The user wants to be logged out -> delete password cookie
404 if (!empty($old_usr)) {
405 setcookie('pma_cookie_password', base64_encode(''), 0, $GLOBALS['cookie_path'], '' , $GLOBALS['is_https']);
408 // The user just logged in
409 else if (!empty($pma_username)) {
410 $PHP_AUTH_USER = $pma_username;
411 $PHP_AUTH_PW = (empty($pma_password)) ?
'' : $pma_password;
415 // At the end, try to set the $PHP_AUTH_USER & $PHP_AUTH_PW variables
416 // from cookies whatever are the values of the 'register_globals' and
417 // the 'variables_order' directives
419 if (!empty($pma_cookie_username)) {
420 $PHP_AUTH_USER = $pma_cookie_username;
423 else if (!empty($_COOKIE) && isset($_COOKIE['pma_cookie_username'])) {
424 $PHP_AUTH_USER = $_COOKIE['pma_cookie_username'];
427 else if (!empty($HTTP_COOKIE_VARS) && isset($HTTP_COOKIE_VARS['pma_cookie_username'])) {
428 $PHP_AUTH_USER = $HTTP_COOKIE_VARS['pma_cookie_username'];
431 if (!empty($pma_cookie_password)) {
432 $PHP_AUTH_PW = $pma_cookie_password;
434 else if (!empty($_COOKIE) && isset($_COOKIE['pma_cookie_password'])) {
435 $PHP_AUTH_PW = $_COOKIE['pma_cookie_password'];
437 else if (!empty($HTTP_COOKIE_VARS) && isset($HTTP_COOKIE_VARS['pma_cookie_password'])) {
438 $PHP_AUTH_PW = $HTTP_COOKIE_VARS['pma_cookie_password'];
441 $from_cookie = FALSE;
443 $PHP_AUTH_PW = base64_decode($PHP_AUTH_PW);
444 $PHP_AUTH_PW = PMA_blowfish_decrypt($PHP_AUTH_PW,$GLOBALS['cfg']['blowfish_secret']);
446 if ($PHP_AUTH_PW == "\xff(blank)") {
451 // Returns whether we get authentication settings or not
452 if (!$from_cookie && !$from_form) {
454 } elseif ($from_cookie) {
455 if (get_magic_quotes_gpc()) {
456 $PHP_AUTH_USER = stripslashes($PHP_AUTH_USER);
457 // no need to strip password as it is encrypted during transfer
461 // we don't need to strip here, it is done in grab_globals
464 } // end of the 'PMA_auth_check()' function
468 * Set the user and password after last checkings if required
470 * @global array the valid servers settings
471 * @global integer the id of the current server
472 * @global array the current server settings
473 * @global string the current username
474 * @global string the current password
475 * @global boolean whether the login/password pair has been grabbed from
478 * @return boolean always true
482 function PMA_auth_set_user()
484 global $cfg, $server;
485 global $PHP_AUTH_USER, $PHP_AUTH_PW;
488 // Ensures valid authentication mode, 'only_db', bookmark database and
489 // table names and relation table name are used
490 if ($cfg['Server']['user'] != $PHP_AUTH_USER) {
491 $servers_cnt = count($cfg['Servers']);
492 for ($i = 1; $i <= $servers_cnt; $i++
) {
493 if (isset($cfg['Servers'][$i])
494 && ($cfg['Servers'][$i]['host'] == $cfg['Server']['host'] && $cfg['Servers'][$i]['user'] == $PHP_AUTH_USER)) {
496 $cfg['Server'] = $cfg['Servers'][$i];
502 $cfg['Server']['user'] = $PHP_AUTH_USER;
503 $cfg['Server']['password'] = $PHP_AUTH_PW;
505 // Set cookies if required (once per session) and, in this case, force
506 // reload to ensure the client accepts cookies
508 // Duration = one month for username
509 setcookie('pma_cookie_username',
510 $cfg['Server']['user'],
511 time() +
(60 * 60 * 24 * 30),
512 $GLOBALS['cookie_path'], '',
513 $GLOBALS['is_https']);
515 // Duration = till the browser is closed for password
516 // Some binary contents are now retrieved properly when stored
517 // as a cookie, so we base64_encode()
518 setcookie('pma_cookie_password',
519 base64_encode(PMA_blowfish_encrypt(((!empty($cfg['Server']['password'])) ?
$cfg['Server']['password'] : "\xff(blank)"), $GLOBALS['cfg']['blowfish_secret'])),
521 $GLOBALS['cookie_path'], '',
522 $GLOBALS['is_https']);
523 // loic1: workaround against a IIS 5.0 bug
524 if (empty($GLOBALS['SERVER_SOFTWARE'])) {
525 if (isset($_SERVER) && !empty($_SERVER['SERVER_SOFTWARE'])) {
526 $GLOBALS['SERVER_SOFTWARE'] = $_SERVER['SERVER_SOFTWARE'];
528 else if (isset($GLOBALS['HTTP_SERVER_VARS']) && !empty($GLOBALS['HTTP_SERVER_VARS']['SERVER_SOFTWARE'])) {
529 $GLOBALS['SERVER_SOFTWARE'] = $GLOBALS['HTTP_SERVER_VARS']['SERVER_SOFTWARE'];
532 if (!empty($GLOBALS['SERVER_SOFTWARE']) && $GLOBALS['SERVER_SOFTWARE'] == 'Microsoft-IIS/5.0') {
533 header('Refresh: 0; url=' . $cfg['PmaAbsoluteUri'] . 'index.php3?' . PMA_generate_common_url('', '', '&'));
536 header('Location: ' . $cfg['PmaAbsoluteUri'] . 'index.php3?' . PMA_generate_common_url('', '', '&'));
542 } // end of the 'PMA_auth_set_user()' function
546 * User is not allowed to login to MySQL -> authentication failed
548 * @return boolean always true (no return indeed)
552 function PMA_auth_fails()
556 // Deletes password cookie and displays the login form
557 setcookie('pma_cookie_password', base64_encode(''), 0, $GLOBALS['cookie_path'], '' , $GLOBALS['is_https']);
559 if (PMA_mysql_error()) {
560 $conn_error = PMA_mysql_error();
561 } else if (isset($php_errormsg)) {
562 $conn_error = $php_errormsg;
564 $conn_error = $GLOBALS['strCannotLogin'];
570 } // end of the 'PMA_auth_fails()' function
572 } // $__PMA_COOKIE_AUTH_LIB__