From aad6e2a9c4857715c8bd56693d21b87dd0c16263 Mon Sep 17 00:00:00 2001 From: thomascube <thomas@roundcube.net> Date: Tue, 27 Mar 2007 05:34:30 -0400 Subject: [PATCH] New session authentication, should fix bugs #1483951 and #1484299; testing required --- program/include/main.inc | 121 ++++++++++++++++++++++++++-------------- 1 files changed, 78 insertions(+), 43 deletions(-) diff --git a/program/include/main.inc b/program/include/main.inc index 1abd84a..b6d995c 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -33,7 +33,7 @@ // register session and connect to server function rcmail_startup($task='mail') { - global $sess_id, $sess_auth, $sess_user_lang; + global $sess_id, $sess_user_lang; global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $JS_OBJECT_NAME; // check client @@ -53,9 +53,8 @@ $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql'; $DB->db_connect('w'); - // we can use the database for storing session data - if (!$DB->is_error()) - include_once('include/session.inc'); + // use database for storing session data + include_once('include/session.inc'); // init session session_start(); @@ -65,8 +64,8 @@ if (!isset($_SESSION['auth_time'])) { $_SESSION['user_lang'] = rcube_language_prop($CONFIG['locale_string']); - $_SESSION['auth_time'] = mktime(); - setcookie('sessauth', rcmail_auth_hash($sess_id, $_SESSION['auth_time'])); + $_SESSION['auth_time'] = time(); + $_SESSION['temp'] = true; } // set session vars global @@ -178,24 +177,29 @@ // compare the auth hash sent by the client with the local session credentials function rcmail_authenticate_session() { - $now = mktime(); - $valid = ($_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['auth_time']) || - $_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['last_auth'])); + global $CONFIG, $SESS_CLIENT_IP, $SESS_CHANGED; + + // advanced session authentication + if ($CONFIG['double_auth']) + { + $now = time(); + $valid = ($_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['auth_time']) || + $_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['last_auth'])); - // renew auth cookie every 5 minutes (only for GET requests) - if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now-$_SESSION['auth_time'] > 300)) + // renew auth cookie every 5 minutes (only for GET requests) + if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now-$_SESSION['auth_time'] > 300)) { - $_SESSION['last_auth'] = $_SESSION['auth_time']; - $_SESSION['auth_time'] = $now; - setcookie('sessauth', rcmail_auth_hash(session_id(), $now)); + $_SESSION['last_auth'] = $_SESSION['auth_time']; + $_SESSION['auth_time'] = $now; + setcookie('sessauth', rcmail_auth_hash(session_id(), $now)); } - - if (!$valid) - write_log('timeouts', - "REQUEST: " . var_export($_REQUEST, true) . - "\nEXPECTED: " . rcmail_auth_hash(session_id(), $_SESSION['auth_time']) . - "\nOR LAST: " . rcmail_auth_hash(session_id(), $_SESSION['last_auth']) . - "\nSESSION: " . var_export($_SESSION, true)); + } + else + $valid = $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] == $SESS_CLIENT_IP : true; + + // check session filetime + if (!empty($CONFIG['session_lifetime']) && isset($SESS_CHANGED) && $SESS_CHANGED + $CONFIG['session_lifetime']*60 < time()) + $valid = false; return $valid; } @@ -282,8 +286,8 @@ rcmail_save_user_prefs($a_user_prefs); } - $_SESSION = array(); - session_destroy(); + $_SESSION = array('user_lang' => $GLOBALS['sess_user_lang'], 'auth_time' => time(), 'temp' => true); + setcookie('sessauth', '-del-', time()-60); } @@ -400,7 +404,7 @@ // set localization charset based on the given language function rcmail_set_locale($lang) { - global $OUTPUT, $MBSTRING; + global $OUTPUT, $CHARSET, $MBSTRING; static $s_mbstring_loaded = NULL; // settings for mbstring module (by Tadashi Jokagi) @@ -408,6 +412,9 @@ $MBSTRING = $s_mbstring_loaded = extension_loaded("mbstring"); else $MBSTRING = $s_mbstring_loaded = FALSE; + + if ($MBSTRING) + mb_internal_encoding($CHARSET); $OUTPUT->set_charset(rcube_language_prop($lang, 'charset')); } @@ -449,6 +456,26 @@ if (!$host) $host = $CONFIG['default_host']; + + // Validate that selected host is in the list of configured hosts + if (is_array($CONFIG['default_host'])) + { + $allowed = FALSE; + foreach ($CONFIG['default_host'] as $key => $host_allowed) + { + if (!is_numeric($key)) + $host_allowed = $key; + if ($host == $host_allowed) + { + $allowed = TRUE; + break; + } + } + if (!$allowed) + return FALSE; + } + else if (!empty($CONFIG['default_host']) && $host != $CONFIG['default_host']) + return FALSE; // parse $host URL $a_host = parse_url($host); @@ -536,6 +563,7 @@ $_SESSION['username'] = $user; $_SESSION['user_lang'] = $sess_user_lang; $_SESSION['password'] = encrypt_passwd($pass); + $_SESSION['login_time'] = mktime(); // force reloading complete list of subscribed mailboxes rcmail_set_imap_prop(); @@ -563,10 +591,10 @@ $DB->query("INSERT INTO ".get_table_name('users')." (created, last_login, username, mail_host, alias, language) VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)", - $user, - $host, - $user_email, - $_SESSION['user_lang']); + strip_newlines($user), + strip_newlines($host), + strip_newlines($user_email), + $_SESSION['user_lang']); if ($user_id = $DB->insert_id(get_sequence_name('users'))) { @@ -578,7 +606,7 @@ $user_name = $user!=$user_email ? $user : ''; // try to resolve the e-mail address from the virtuser table - if (!empty($CONFIG['virtuser_query']) && + if (!empty($CONFIG['virtuser_query']) && ($sql_result = $DB->query(preg_replace('/%u/', $user, $CONFIG['virtuser_query']))) && ($DB->num_rows()>0)) while ($sql_arr = $DB->fetch_array($sql_result)) @@ -587,7 +615,7 @@ (user_id, del, standard, name, email) VALUES (?, 0, 1, ?, ?)", $user_id, - $user_name, + strip_newlines($user_name), preg_replace('/^@/', $user . '@', $sql_arr[0])); } else @@ -597,8 +625,8 @@ (user_id, del, standard, name, email) VALUES (?, 0, 1, ?, ?)", $user_id, - $user_name, - $user_email); + strip_newlines($user_name), + strip_newlines($user_email)); } // get existing mailboxes @@ -1009,7 +1037,7 @@ $str = strip_tags($str); // avoid douple quotation of & - $out = preg_replace('/&([a-z]{2,5});/', '&\\1;', strtr($str, $encode_arr)); + $out = preg_replace('/&([a-z]{2,5}|#[0-9]{2,4});/', '&\\1;', strtr($str, $encode_arr)); return $newlines ? nl2br($out) : $out; } @@ -1020,7 +1048,7 @@ // if the replace tables for XML and JS are not yet defined if (!$js_rep_table) { - $js_rep_tabl = $xml_rep_table = array(); + $js_rep_table = $xml_rep_table = array(); $xml_rep_table['&'] = '&'; for ($c=160; $c<256; $c++) // can be increased to support more charsets @@ -1032,7 +1060,6 @@ $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex); } - $js_rep_table['"'] = sprintf("\u%s%s", str_repeat('0', 4-strlen(dechex(34))), dechex(34)); $xml_rep_table['"'] = '"'; } @@ -1066,9 +1093,9 @@ * Quote a given string. Alias function for rep_specialchars_output * @see rep_specialchars_output */ -function JQ($str, $mode='strict', $newlines=TRUE) +function JQ($str) { - return rep_specialchars_output($str, 'js', $mode, $newlines); + return rep_specialchars_output($str, 'js'); } @@ -1122,6 +1149,14 @@ function strip_quotes($str) { return preg_replace('/[\'"]/', '', $str); +} + +/** + * Remove new lines characters from given string + */ +function strip_newlines($str) +{ + return preg_replace('/[\r\n]/', '', $str); } @@ -1667,12 +1702,12 @@ function parse_attrib_string($str) { $attrib = array(); - preg_match_all('/\s*([-_a-z]+)=["]([^"]+)["]?/i', stripslashes($str), $regs, PREG_SET_ORDER); + preg_match_all('/\s*([-_a-z]+)=(["\'])([^"]+)\2/Ui', stripslashes($str), $regs, PREG_SET_ORDER); // convert attributes to an associative array (name => value) if ($regs) foreach ($regs as $attr) - $attrib[strtolower($attr[1])] = $attr[2]; + $attrib[strtolower($attr[1])] = $attr[3]; return $attrib; } @@ -1710,9 +1745,9 @@ $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); // define date format depending on current time - if ($CONFIG['prettydate'] && !$format && $timestamp > $today_limit) - return sprintf('%s %s', rcube_label('today'), date('H:i', $timestamp)); - else if ($CONFIG['prettydate'] && !$format && $timestamp > $week_limit) + if ($CONFIG['prettydate'] && !$format && $timestamp > $today_limit && $timestamp < $now) + return sprintf('%s %s', rcube_label('today'), date($CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i', $timestamp)); + else if ($CONFIG['prettydate'] && !$format && $timestamp > $week_limit && $timestamp < $now) $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i'; else if (!$format) $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i'; @@ -1830,7 +1865,7 @@ $labels['pass'] = rcube_label('password'); $labels['host'] = rcube_label('server'); - $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30)); + $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off')); $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30)); $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login')); -- Gitblit v1.9.1