Follow-up to bug #12499: re-added the removed function call and moved the deprecation...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_userauth.php
old mode 100755 (executable)
new mode 100644 (file)
index 8f96ed9..166ad92
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2008 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -199,7 +199,13 @@ class t3lib_userAuth {
                $this->loginType = ($this->name=='fe_typo_user') ? 'FE' : 'BE';
 
                        // set level to normal if not already set
-               $this->security_level = $this->security_level ? $this->security_level : 'normal';
+               if (!$this->security_level) {
+                       // Notice: cannot use TYPO3_MODE here because BE user can be logged in and operate inside FE!
+                       $this->security_level = trim($TYPO3_CONF_VARS[$this->loginType]['loginSecurityLevel']);
+                       if (!$this->security_level) {
+                               $this->security_level = 'normal';
+                       }
+               }
 
                        // enable dev logging if set
                if ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['writeDevLog']) $this->writeDevLog = TRUE;
@@ -213,9 +219,12 @@ class t3lib_userAuth {
                $this->newSessionID = FALSE;
                        // $id is set to ses_id if cookie is present. Else set to false, which will start a new session
                $id = isset($_COOKIE[$this->name]) ? stripslashes($_COOKIE[$this->name]) : '';
-               $this->hash_length = t3lib_div::intInRange($this->hash_length,6,32);
                $this->svConfig = $TYPO3_CONF_VARS['SVCONF']['auth'];
 
+                       // if we have a flash client, take the ID from the GP
+               if (!$id && $GLOBALS['CLIENT']['BROWSER'] == 'flash') {
+                       $id = t3lib_div::_GP($this->name);
+               }
 
                        // If fallback to get mode....
                if (!$id && $this->getFallBack && $this->get_name)      {
@@ -225,11 +234,11 @@ class t3lib_userAuth {
                }
                $this->cookieId = $id;
 
-                       // If new session...
-               if (!$id)       {
+                       // If new session or client tries to fix session...
+               if (!$id || !$this->isExistingSessionRecord($id))       {
                                // New random session-$id is made
-               $id = substr(md5(uniqid('').getmypid()),0,$this->hash_length);
-                       // New session
+                       $id = $this->createSessionId();
+                               // New session
                        $this->newSessionID = TRUE;
                }
 
@@ -265,41 +274,8 @@ class t3lib_userAuth {
                if ($this->writeDevLog && !is_array($this->user)) t3lib_div::devLog('No user session found.', 't3lib_userAuth', 2);
 
                        // Setting cookies
-               if ($TYPO3_CONF_VARS['SYS']['cookieDomain'])    {
-                       if ($TYPO3_CONF_VARS['SYS']['cookieDomain']{0} == '/')  {
-                               $matchCnt = @preg_match($TYPO3_CONF_VARS['SYS']['cookieDomain'], t3lib_div::getIndpEnv('TYPO3_HOST_ONLY'), $match);
-                               if ($matchCnt === FALSE)        {
-                                       t3lib_div::sysLog('The regular expression of $TYPO3_CONF_VARS[SYS][cookieDomain] contains errors. The session is not shared across sub-domains.', 'Core', 3);
-                               } elseif ($matchCnt)    {
-                                       $cookieDomain = $match[0];
-                               }
-                       } else {
-                               $cookieDomain = $TYPO3_CONF_VARS['SYS']['cookieDomain'];
-                       }
-               }
-
-                       // If new session and the cookie is a sessioncookie, we need to set it only once!
-               if ($this->isSetSessionCookie())        {
-                       if (!$this->dontSetCookie)      {
-                               if ($cookieDomain)      {
-                                       SetCookie($this->name, $id, 0, '/', $cookieDomain);
-                               } else {
-                                       SetCookie($this->name, $id, 0, '/');
-                               }
-                               if ($this->writeDevLog)         t3lib_div::devLog('Set new Cookie: '.$id.($cookieDomain ? ', '.$cookieDomain : ''), 't3lib_userAuth');
-                       }
-               }
-
-                       // If it is NOT a session-cookie, we need to refresh it.
-               if ($this->isRefreshTimeBasedCookie())  {
-                       if (!$this->dontSetCookie)      {
-                               if ($cookieDomain)      {
-                                       SetCookie($this->name, $id, time()+$this->lifetime, '/', $cookieDomain);
-                               } else {
-                                       SetCookie($this->name, $id, time()+$this->lifetime, '/');
-                               }
-                               if ($this->writeDevLog)         t3lib_div::devLog('Update Cookie: '.$id.($cookieDomain ? ', '.$cookieDomain : ''), 't3lib_userAuth');
-                       }
+               if (!$this->dontSetCookie)      {
+                       $this->setSessionCookie();
                }
 
                        // Hook for alternative ways of filling the $this->user array (is used by the "timtaw" extension)
@@ -332,6 +308,81 @@ class t3lib_userAuth {
                if ((rand()%100) <= $this->gc_probability)      {
                        $this->gc();
                }
+
+       }
+
+       /**
+        * Sets the session cookie for the current disposal.
+        *
+        * @return      void
+        */
+       protected function setSessionCookie() {
+               $isSetSessionCookie = $this->isSetSessionCookie();
+               $isRefreshTimeBasedCookie = $this->isRefreshTimeBasedCookie();
+
+               if ($isSetSessionCookie || $isRefreshTimeBasedCookie) {
+                       $settings = $GLOBALS['TYPO3_CONF_VARS']['SYS'];
+
+                       // Get the domain to be used for the cookie (if any):
+                       $cookieDomain = $this->getCookieDomain();
+                       // If no cookie domain is set, use the base path:
+                       $cookiePath = ($cookieDomain ? '/' : t3lib_div::getIndpEnv('TYPO3_SITE_PATH'));
+                       // If the cookie lifetime is set, use it:
+                       $cookieExpire = ($isRefreshTimeBasedCookie ? $GLOBALS['EXEC_TIME'] + $this->lifetime : 0);
+                       // Use the secure option when the current request is served by a secure connection:
+                       $cookieSecure = (bool)$settings['cookieSecure'] && t3lib_div::getIndpEnv('TYPO3_SSL');
+                       // Deliver cookies only via HTTP and prevent possible XSS by JavaScript:
+                       $cookieHttpOnly = (bool)$settings['cookieHttpOnly'];
+
+                       // Do not set cookie if cookieSecure is set to "1" (force HTTPS) and no secure channel is used:
+                       if ((int)$settings['cookieSecure'] !== 1 || t3lib_div::getIndpEnv('TYPO3_SSL')) {
+                               setcookie(
+                                       $this->name,
+                                       $this->id,
+                                       $cookieExpire,
+                                       $cookiePath,
+                                       $cookieDomain,
+                                       $cookieSecure,
+                                       $cookieHttpOnly
+                               );
+                       } else {
+                               throw new t3lib_exception(
+                                       'Cookie was not set since HTTPS was forced in $TYPO3_CONF_VARS[SYS][cookieSecure].',
+                                       1254325546
+                               );
+                       }
+
+                       if ($this->writeDevLog) {
+                               $devLogMessage = ($isRefreshTimeBasedCookie ? 'Updated Cookie: ' : 'Set Cookie: ') . $this->id;
+                               t3lib_div::devLog($devLogMessage . ($cookieDomain ? ', '.$cookieDomain : ''), 't3lib_userAuth');
+                       }
+               }
+       }
+
+       /**
+        * Gets the domain to be used on setting cookies.
+        * The information is taken from the value in $TYPO3_CONF_VARS[SYS][cookieDomain].
+        *
+        * @return      string          The domain to be used on setting cookies
+        */
+       protected function getCookieDomain() {
+               $result = '';
+               $cookieDomain = $GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieDomain'];
+
+               if ($cookieDomain) {
+                       if ($cookieDomain{0} == '/') {
+                               $matchCnt = @preg_match($cookieDomain, t3lib_div::getIndpEnv('TYPO3_HOST_ONLY'), $match);
+                               if ($matchCnt === FALSE) {
+                                       t3lib_div::sysLog('The regular expression of $TYPO3_CONF_VARS[SYS][cookieDomain] contains errors. The session is not shared across sub-domains.', 'Core', 3);
+                               } elseif ($matchCnt) {
+                                       $result = $match[0];
+                               }
+                       } else {
+                               $result = $cookieDomain;
+                       }
+               }
+
+               return $result;
        }
 
        /**
@@ -599,6 +650,14 @@ class t3lib_userAuth {
                }
        }
 
+       /**
+        * Creates a new session ID.
+        *
+        * @return      string          The new session ID
+        */
+       public function createSessionId() {
+               return substr(md5(uniqid('') . getmypid()), 0, $this->hash_length);
+       }
 
 
 
@@ -676,20 +735,10 @@ class t3lib_userAuth {
 
                if ($this->writeDevLog)         t3lib_div::devLog('Fetch session ses_id = '.$this->id, 't3lib_userAuth');
 
-                       // The session_id is used to find user in the database. Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
-               $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
-                                               '*',
-                                               $this->session_table.','.$this->user_table,
-                                               $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
-                                                       AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
-                                                       AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
-                                                       '.$this->ipLockClause().'
-                                                       '.$this->hashLockClause().'
-                                                       '.$this->user_where_clause()
-                                       );
-
+                       // fetch the user session from the DB
+               $dbres = $this->fetchUserSessionFromDB();
 
-               if ($user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres))      {
+               if ($dbres && $user = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($dbres)) {
                                // A user was found
                        if (is_string($this->auth_timeout_field))       {
                                $timeout = intval($user[$this->auth_timeout_field]);            // Get timeout-time from usertable
@@ -756,6 +805,22 @@ class t3lib_userAuth {
                }
        }
 
+       /**
+        * Determine whether there's an according session record to a given session_id
+        * in the database. Don't care if session record is still valid or not.
+        *
+        * @param       integer         Claimed Session ID
+        * @return      boolean         Returns true if a corresponding session was found in the database
+        */
+       function isExistingSessionRecord($id) {
+               $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
+                                               'ses_id',
+                                               $this->session_table,
+                                               'ses_id=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($id, $this->session_table)
+                                       );
+               return (($count ? true : false));
+       }
+
 
 
 
@@ -775,6 +840,27 @@ class t3lib_userAuth {
         *************************/
 
        /**
+        * The session_id is used to find user in the database.
+        * Two tables are joined: The session-table with user_id of the session and the usertable with its primary key
+        * @return DB result object or false on error
+        * @access private
+        */
+       protected function fetchUserSessionFromDB() {
+               $dbres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                       '*',
+                                       $this->session_table.','.$this->user_table,
+                                       $this->session_table.'.ses_id = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, $this->session_table).'
+                                               AND '.$this->session_table.'.ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table).'
+                                               AND '.$this->session_table.'.ses_userid = '.$this->user_table.'.'.$this->userid_column.'
+                                               '.$this->ipLockClause().'
+                                               '.$this->hashLockClause().'
+                                               '.$this->user_where_clause()
+               );
+               return $dbres;
+       }
+
+
+       /**
         * This returns the where-clause needed to select the user with respect flags like deleted, hidden, starttime, endtime
         *
         * @return      string
@@ -784,8 +870,8 @@ class t3lib_userAuth {
                return  (($this->enablecolumns['rootLevel']) ? 'AND '.$this->user_table.'.pid=0 ' : '').
                                (($this->enablecolumns['disabled']) ? ' AND '.$this->user_table.'.'.$this->enablecolumns['disabled'].'=0' : '').
                                (($this->enablecolumns['deleted']) ? ' AND '.$this->user_table.'.'.$this->enablecolumns['deleted'].'=0' : '').
-                               (($this->enablecolumns['starttime']) ? ' AND ('.$this->user_table.'.'.$this->enablecolumns['starttime'].'<='.time().')' : '').
-                               (($this->enablecolumns['endtime']) ? ' AND ('.$this->user_table.'.'.$this->enablecolumns['endtime'].'=0 OR '.$this->user_table.'.'.$this->enablecolumns['endtime'].'>'.time().')' : '');
+                               (($this->enablecolumns['starttime']) ? ' AND (' . $this->user_table . '.' . $this->enablecolumns['starttime'] . '<=' . $GLOBALS['EXEC_TIME'] . ')' : '') .
+                               (($this->enablecolumns['endtime']) ? ' AND (' . $this->user_table . '.' . $this->enablecolumns['endtime'] . '=0 OR ' . $this->user_table . '.' . $this->enablecolumns['endtime'] . '>' . $GLOBALS['EXEC_TIME'] . ')' : '');
        }
 
        /**
@@ -1120,8 +1206,8 @@ class t3lib_userAuth {
        function gc() {
                $GLOBALS['TYPO3_DB']->exec_DELETEquery(
                                        $this->session_table,
-                                       'ses_tstamp < '.intval(time()-($this->gc_time)).'
-                                               AND ses_name = '.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table)
+                                       'ses_tstamp < ' . intval($GLOBALS['EXEC_TIME'] - ($this->gc_time)) .
+                                               ' AND ses_name = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->name, $this->session_table)
                                );
        }
 
@@ -1129,12 +1215,13 @@ class t3lib_userAuth {
         * Redirect to somewhere (obsolete).
         *
         * @return      void
-        * @deprecated since TYPO3 3.6
+        * @deprecated since TYPO3 3.6, this function will be removed in TYPO3 4.5.
         * @obsolete
         * @ignore
         */
        function redirect() {
                if (!$this->userid && $this->auth_url)  {        // if no userid AND an include-document for login is given
+                       t3lib_div::deprecationLog('Redirection after login via PHP include is deprecated.');
                        include ($this->auth_include);
                        exit;
                }
@@ -1289,4 +1376,4 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_userauth.php']);
 }
 
-?>
+?>
\ No newline at end of file