Add controls for page referal verification and security token system to the configura...
[squirrelmail.git] / functions / global.php
index 7a77c256e080e93fa430e413752e2199cbb002f6..92a3705ecb343388958431594b2d30a3b895fe34 100644 (file)
@@ -7,7 +7,7 @@
  * It also has some session register functions that work across various
  * php versions.
  *
- * @copyright © 1999-2007 The SquirrelMail Project Team
+ * @copyright © 1999-2009 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -155,7 +155,9 @@ function sqsession_unregister ($name) {
 
     unset($_SESSION[$name]);
 
-    session_unregister("$name");
+    // starts throwing warnings in PHP 5.3.0 and is
+    // removed in PHP 6 and is redundant anyway
+    //session_unregister("$name");
 }
 
 /**
@@ -340,6 +342,9 @@ function sqgetGlobalVar($name, &$value, $search = SQ_INORDER, $default = NULL, $
             case SQ_TYPE_INT: $value = (int) $value; break;
             case SQ_TYPE_STRING: $value = (string) $value; break;
             case SQ_TYPE_BOOL: $value = (bool) $value; break;
+            case SQ_TYPE_BIGINT:
+                $value = (preg_match('/^[0-9]+$/', $value) ? $value : '0');
+                break;
             default: break;
         }
     } else if (!$result && !is_null($default)) {
@@ -437,9 +442,29 @@ function sqsession_destroy() {
 
     global $base_uri, $_COOKIE, $_SESSION;
 
-    if (isset($_COOKIE[session_name()]) && session_name()) sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri);
+    if (isset($_COOKIE[session_name()]) && session_name()) {
+        sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri);
+
+        /*
+         * Make sure to kill /src and /src/ cookies, just in case there are
+         * some left-over or malicious ones set in user's browser.
+         * NB: Note that an attacker could try to plant a cookie for one
+         *     of the /plugins/* directories.  Such cookies can block
+         *     access to certain plugin pages, but they do not influence
+         *     or fixate the $base_uri cookie, so we don't worry about
+         *     trying to delete all of them here.
+         */
+        sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src');
+        sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src/');
+    }
+
     if (isset($_COOKIE['key']) && $_COOKIE['key']) sqsetcookie('key','SQMTRASH',1,$base_uri);
 
+    /* Make sure new session id is generated on subsequent session_start() */
+    unset($_COOKIE[session_name()]);
+    unset($_GET[session_name()]);
+    unset($_POST[session_name()]);
+
     $sessid = session_id();
     if (!empty( $sessid )) {
         $_SESSION = array();
@@ -517,9 +542,9 @@ 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;
@@ -555,6 +580,7 @@ function sqsetcookie($sName, $sValue='deleted', $iExpire=0, $sPath="", $sDomain=
  * session_regenerate_id replacement for PHP < 4.3.2
  *
  * This code is borrowed from Gallery, session.php version 1.53.2.1
+FIXME: I saw this code on php.net (in the manual); that's where it comes from originally, but I don't think we need it - it's just redundant to all the hard work we already did seeding the random number generator IMO.  I think we can just call to GenerateRandomString() and dump the rest.
  */
 if (!function_exists('session_regenerate_id')) {
 
@@ -604,9 +630,11 @@ if (!function_exists('session_regenerate_id')) {
  * @since 1.2.3
  */
 function php_self () {
-    if ( sqgetGlobalVar('REQUEST_URI', $req_uri, SQ_SERVER) && !empty($req_uri) ) {
-      return $req_uri;
-    }
+    // PHP 4.4.4 apparently gives the wrong value here - missing the query string
+    // this code is commented out in the 1.4.x code, so we'll do the same here
+    //if ( sqgetGlobalVar('REQUEST_URI', $req_uri, SQ_SERVER) && !empty($req_uri) ) {
+    //  return $req_uri;
+    //}
 
     if ( sqgetGlobalVar('PHP_SELF', $php_self, SQ_SERVER) && !empty($php_self) ) {
 
@@ -721,3 +749,96 @@ function sq_htmlspecialchars($value, $quote_style=ENT_QUOTES) {
 }
 
 
+/**
+ * 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;
+}
+
+
+/**
+ * Endeavor to detect what user and group PHP is currently
+ * running as.  Probably only works in non-Windows environments.
+ *
+ * @return mixed Boolean FALSE is returned if something went wrong,
+ *               otherwise an array is returned with the following
+ *               elements:
+ *                  uid    The current process' UID (integer)
+ *                  euid   The current process' effective UID (integer)
+ *                  gid    The current process' GID (integer)
+ *                  egid   The current process' effective GID (integer)
+ *                  name   The current process' name/handle (string)
+ *                  ename  The current process' effective name/handle (string)
+ *                  group  The current process' group name (string)
+ *                  egroup The current process' effective group name (string)
+ *               Note that some of these elements may have empty
+ *               values, especially if they could not be determined.
+ *
+ * @since 1.5.2
+ *
+ */
+function get_process_owner_info()
+{
+    if (!function_exists('posix_getuid'))
+        return FALSE;
+
+    $process_info['uid'] = posix_getuid();
+    $process_info['euid'] = posix_geteuid();
+    $process_info['gid'] = posix_getgid();
+    $process_info['egid'] = posix_getegid();
+
+    $user_info = posix_getpwuid($process_info['uid']);
+    $euser_info = posix_getpwuid($process_info['euid']);
+    $group_info = posix_getgrgid($process_info['gid']);
+    $egroup_info = posix_getgrgid($process_info['egid']);
+
+    $process_info['name'] = $user_info['name'];
+    $process_info['ename'] = $euser_info['name'];
+    $process_info['group'] = $user_info['name'];
+    $process_info['egroup'] = $euser_info['name'];
+    
+    return $process_info;
+}
+
+