X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=blobdiff_plain;f=functions%2Fglobal.php;h=acfa06253b8cc3689741b14e6c698591de0f151a;hp=c3b611299e4a6d5a3c47e0483b531e298b4e452f;hb=8f557b942c5a3fb6663c349f4cc7d4a1c8aa4504;hpb=f6cd95a165c5de73e4008d8e3e4b6845b2bff561 diff --git a/functions/global.php b/functions/global.php index c3b61129..acfa0625 100644 --- a/functions/global.php +++ b/functions/global.php @@ -348,6 +348,69 @@ function sqgetGlobalVar($name, &$value, $search = SQ_INORDER, $default = NULL, $ return $result; } +/** + * Get an immutable copy of a configuration variable if SquirrelMail + * is in "secured configuration" mode. This guarantees the caller + * gets a copy of the requested value as it is set in the main + * application configuration (including config_local overrides), and + * not what it might be after possibly having been modified by some + * other code (usually a plugin overriding configuration values for + * one reason or another). + * + * WARNING: Please use this function as little as possible, because + * every time it is called, it forcibly reloads the main configuration + * file(s). + * + * Caller beware that this function will do nothing if SquirrelMail + * is not in "secured configuration" mode per the $secured_config + * setting. + * + * @param string $var_name The name of the desired variable + * + * @return mixed The desired value + * + * @since 1.5.2 + * + */ +function get_secured_config_value($var_name) { + + static $return_values = array(); + + // if we can avoid it, return values that have + // already been retrieved (so we don't have to + // include the config file yet again) + // + if (isset($return_values[$var_name])) { + return $return_values[$var_name]; + } + + + // load site configuration + // + require(SM_PATH . 'config/config.php'); + + // load local configuration overrides + // + if (file_exists(SM_PATH . 'config/config_local.php')) { + require(SM_PATH . 'config/config_local.php'); + } + + // if SM isn't in "secured configuration" mode, + // just return the desired value from the global scope + // + if (!$secured_config) { + global $$var_name; + $return_values[$var_name] = $$var_name; + return $$var_name; + } + + // else we return what we got from the config file + // + $return_values[$var_name] = $$var_name; + return $$var_name; + +} + /** * Deletes an existing session, more advanced than the standard PHP * session_destroy(), it explicitly deletes the cookies and global vars. @@ -416,28 +479,47 @@ function sqsession_start() { // was: @session_start(); $session_id = session_id(); - // session_starts sets the sessionid cookie buth without the httponly var + // session_starts sets the sessionid cookie but without the httponly var // setting the cookie again sets the httponly cookie attribute - sqsetcookie(session_name(),$session_id,false,$base_uri); + // + // need to check if headers have been sent, since sqsession_is_active() + // has become just a passthru to this function, so the sqsetcookie() + // below is called every time, even after headers have already been sent + // + if (!headers_sent()) + sqsetcookie(session_name(),$session_id,false,$base_uri); } + /** * Set a cookie + * * @param string $sName The name of the cookie. * @param string $sValue The value of the cookie. - * @param int $iExpire The time the cookie expires. This is a Unix timestamp so is in number of seconds since the epoch. - * @param string $sPath The path on the server in which the cookie will be available on. + * @param int $iExpire The time the cookie expires. This is a Unix + * timestamp so is in number of seconds since + * the epoch. + * @param string $sPath The path on the server in which the cookie + * will be available on. * @param string $sDomain The domain that the cookie is available. - * @param boolean $bSecure Indicates that the cookie should only be transmitted over a secure HTTPS connection. + * @param boolean $bSecure Indicates that the cookie should only be + * transmitted over a secure HTTPS connection. * @param boolean $bHttpOnly Disallow JS to access the cookie (IE6 only) + * @param boolean $bReplace Replace previous cookies with same name? + * * @return void + * + * @since 1.4.16 and 1.5.1 + * */ -function sqsetcookie($sName,$sValue='deleted',$iExpire=0,$sPath="",$sDomain="",$bSecure=false,$bHttpOnly=true) { +function sqsetcookie($sName, $sValue='deleted', $iExpire=0, $sPath="", $sDomain="", + $bSecure=false, $bHttpOnly=true, $bReplace=false) { + // if we have a secure connection then limit the cookies to https only. - if ($sName && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) { + global $is_secure_connection; + if ($sName && $is_secure_connection) $bSecure = true; - } // admin config can override the restriction of secure-only cookies global $only_secure_cookies; @@ -464,23 +546,19 @@ function sqsetcookie($sName,$sValue='deleted',$iExpire=0,$sPath="",$sDomain="",$ . (empty($sPath) ? '' : '; path=' . $sPath) . (empty($sDomain) ? '' : '; domain=' . $sDomain) . (!$bSecure ? '' : '; secure') - . (!$bHttpOnly ? '' : '; HttpOnly'), false); + . (!$bHttpOnly ? '' : '; HttpOnly'), $bReplace); } } + /** * session_regenerate_id replacement for PHP < 4.3.2 * * This code is borrowed from Gallery, session.php version 1.53.2.1 */ if (!function_exists('session_regenerate_id')) { - function make_seed() { - list($usec, $sec) = explode(' ', microtime()); - return (float)$sec + ((float)$usec * 100000); - } function php_combined_lcg() { - mt_srand(make_seed()); $tv = gettimeofday(); $lcg['s1'] = $tv['sec'] ^ (~$tv['usec']); $lcg['s2'] = mt_rand(); @@ -508,9 +586,7 @@ if (!function_exists('session_regenerate_id')) { $buf = sprintf("%.15s%ld%ld%0.8f", $remote_addr, $tv['sec'], $tv['usec'], php_combined_lcg() * 10); session_id(md5($buf)); if (ini_get('session.use_cookies')) { - // at a later stage we use sqsetcookie. At this point just do - // what session_regenerate_id would do - setcookie(session_name(), session_id(), NULL, $base_uri); + sqsetcookie(session_name(), session_id(), 0, $base_uri); } return TRUE; } @@ -547,143 +623,6 @@ function php_self () { } -/** - * Find files and/or directories in a given directory optionally - * limited to only those with the given file extension. If the - * directory is not found or cannot be opened, no error is generated; - * only an empty file list is returned. -FIXME: do we WANT to throw an error or a notice or... or return FALSE? - * - * @param string $directory_path The path (relative or absolute) - * to the desired directory. - * @param mixed $extension The file extension filter - either - * an array of desired extension(s), - * or a comma-separated list of same - * (optional; default is to return - * all files (dirs). - * @param boolean $return_filenames_only When TRUE, only file/dir names - * are returned, otherwise the - * $directory_path string is - * prepended to each file/dir in - * the returned list (optional; - * default is filename/dirname only) - * @param boolean $include_directories When TRUE, directories are - * included (optional; default - * DO include directories). - * @param boolean $directories_only When TRUE, ONLY directories - * are included (optional; default - * is to include files too). - * @param boolean $separate_files_and_directories When TRUE, files and - * directories are returned - * in separate lists, so - * the return value is - * formatted as a two-element - * array with the two keys - * "FILES" and "DIRECTORIES", - * where corresponding values - * are lists of either all - * files or all directories - * (optional; default do not - * split up return array). - * @param boolean $only_sm When TRUE, a security check will - * limit directory access to only - * paths within the SquirrelMail - * installation currently being used - * (optional; default TRUE) - * - * @return array The requested file/directory list(s). - * - * @since 1.5.2 - * - */ -function list_files($directory_path, $extensions='', $return_filenames_only=TRUE, - $include_directories=TRUE, $directories_only=FALSE, - $separate_files_and_directories=FALSE, $only_sm=TRUE) { - - $files = array(); - $directories = array(); - - - // make sure requested path is under SM_PATH if needed - // - if ($only_sm) { - if (strpos(realpath($directory_path), realpath(SM_PATH)) !== 0) { - //plain_error_message(_("Illegal filesystem access was requested")); - echo _("Illegal filesystem access was requested"); - exit; - } - } - - - // validate given directory - // - if (empty($directory_path) - || !is_dir($directory_path) - || !($DIR = opendir($directory_path))) { - return $files; - } - - - // ensure extensions is an array and is properly formatted - // - if (!empty($extensions)) { - if (!is_array($extensions)) - $extensions = explode(',', $extensions); - $temp_extensions = array(); - foreach ($extensions as $ext) - $temp_extensions[] = '.' . trim(trim($ext), '.'); - $extensions = $temp_extensions; - } else $extensions = array(); - - - $directory_path = rtrim($directory_path, '/'); - - - // parse through the files - // - while (($file = readdir($DIR)) !== false) { - - if ($file == '.' || $file == '..') continue; - - if (!empty($extensions)) - foreach ($extensions as $ext) - if (strrpos($file, $ext) !== (strlen($file) - strlen($ext))) - continue 2; - - // only use is_dir() if we really need to (be as efficient as possible) - // - $is_dir = FALSE; - if (!$include_directories || $directories_only - || $separate_files_and_directories) { - if (is_dir($directory_path . '/' . $file)) { - if (!$include_directories) continue; - $is_dir = TRUE; - $directories[] = ($return_filenames_only - ? $file - : $directory_path . '/' . $file); - } - if ($directories_only) continue; - } - - if (!$separate_files_and_directories - || ($separate_files_and_directories && !$is_dir)) { - $files[] = ($return_filenames_only - ? $file - : $directory_path . '/' . $file); - } - - } - closedir($DIR); - - - if ($directories_only) return $directories; - if ($separate_files_and_directories) return array('FILES' => $files, - 'DIRECTORIES' => $directories); - return $files; - -} - - /** * Print variable * @@ -780,3 +719,53 @@ function sq_htmlspecialchars($value, $quote_style=ENT_QUOTES) { return $value; } + + +/** + * Detect whether or not we have a SSL secured (HTTPS) connection + * connection to the browser + * + * It is thought to be so if you have 'SSLOptions +StdEnvVars' + * in your Apache configuration, + * OR if you have HTTPS set to a non-empty value (except "off") + * in your HTTP_SERVER_VARS, + * OR if you have HTTP_X_FORWARDED_PROTO=https in your HTTP_SERVER_VARS, + * OR if you are on port 443. + * + * Note: HTTP_X_FORWARDED_PROTO could be sent from the client and + * therefore possibly spoofed/hackable. Thus, SquirrelMail + * ignores such headers by default. The administrator + * can tell SM to use such header values by setting + * $sq_ignore_http_x_forwarded_headers to boolean FALSE + * in config/config.php or by using config/conf.pl. + * + * Note: It is possible to run SSL on a port other than 443, and + * if that is the case, the administrator should set + * $sq_https_port in config/config.php or by using config/conf.pl. + * + * @return boolean TRUE if the current connection is SSL-encrypted; + * FALSE otherwise. + * + * @since 1.4.17 and 1.5.2 + * + */ +function is_ssl_secured_connection() +{ + global $sq_ignore_http_x_forwarded_headers, $sq_https_port; + $https_env_var = getenv('HTTPS'); + if ($sq_ignore_http_x_forwarded_headers + || !sqgetGlobalVar('HTTP_X_FORWARDED_PROTO', $forwarded_proto, SQ_SERVER)) + $forwarded_proto = ''; + if (empty($sq_https_port)) // won't work with port 0 (zero) + $sq_https_port = 443; + if ((isset($https_env_var) && strcasecmp($https_env_var, 'on') === 0) + || (sqgetGlobalVar('HTTPS', $https, SQ_SERVER) && !empty($https) + && strcasecmp($https, 'off') !== 0) + || (strcasecmp($forwarded_proto, 'https') === 0) + || (sqgetGlobalVar('SERVER_PORT', $server_port, SQ_SERVER) + && $server_port == $sq_https_port)) + return TRUE; + return FALSE; +} + +