$this->executeAddIndexStatement($match[1], ($match[3] ?: self::getGenericIndexName($match[1], $match[4])), array('type' => strtoupper($match[2]), 'columns' => $match[4]));
}
// add foreign key
- else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+FOREIGN KEY\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)\s+REFERENCES\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)(?:\s+ON\s+(UPDATE|DELETE)\s+(CASCADE|SET NULL|NO ACTION))?~is', $query, $match)) {
- $this->executeAddForeignKeyStatement($match[1], ($match[2] ?: self::getGenericIndexName($match[1], $match[3], 'fk')), array('columns' => $match[3], 'referencedTable' => $match[4], 'referencedColumns' => $match[5], 'operation' => $match[6], 'action' => $match[7]));
+ else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+FOREIGN KEY\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)\s+REFERENCES\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)(?:\s+ON\s+DELETE\s+(CASCADE|SET NULL|NO ACTION))?(?:\s+ON\s+UPDATE\s+(CASCADE|SET NULL|NO ACTION))?~is', $query, $match)) {
+ $this->executeAddForeignKeyStatement($match[1], ($match[2] ?: self::getGenericIndexName($match[1], $match[3], 'fk')), array(
+ 'columns' => $match[3],
+ 'referencedTable' => $match[4],
+ 'referencedColumns' => $match[5],
+ 'ON DELETE' => $match[6],
+ 'ON UPDATE' => $match[7]
+ ));
}
// add/change column
else if (preg_match("~^ALTER\s+TABLE\s+(\w+)\s+(?:(ADD)\s+(?:COLUMN\s+)?|(CHANGE)\s+(?:COLUMN\s+)?(\w+)\s+)(\w+)\s+(\w+)(?:\s*\((\s*(?:\d+(?:\s*,\s*\d+)?|'[^']*'(?:\s*,\s*'[^']*')*))\s*\))?(?:\s+UNSIGNED)?(?:\s+(NOT NULL|NULL))?(?:\s+DEFAULT\s+(-?\d+.\d+|-?\d+|NULL|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'))?(?:\s+(AUTO_INCREMENT))?(?:\s+(UNIQUE|PRIMARY)(?: KEY)?)?~is", $query, $match)) {
// init session environment
$this->loadVariables();
$this->initSecurityToken();
+
+ // session id change was delayed to the next request
+ // as the SID constants already were defined
+ if ($this->getVar('__changeSessionID')) {
+ $this->unregister('__changeSessionID');
+ $this->changeSessionID();
+ }
$this->defineConstants();
// assign language and style id
$this->initEnvironment();
}
+ /**
+ * Changes the session id to a new random one.
+ *
+ * Usually a change is requested after login to ensure
+ * that the user is not running a fixated session by an
+ * attacker.
+ */
+ protected function changeSessionID() {
+ $oldSessionID = $this->session->sessionID;
+ $newSessionID = StringUtil::getRandomID();
+
+ $sessionEditor = new $this->sessionEditorClassName($this->session);
+ $sessionEditor->update(array(
+ 'sessionID' => $newSessionID
+ ));
+
+ // fetch new session data from database
+ $this->session = new $this->sessionClassName($newSessionID);
+
+ if ($this->useCookies) {
+ // we know that the user accepts cookies, simply send new session id
+ HeaderUtil::setCookie('cookieHash', $newSessionID);
+ }
+ else if ($_SERVER['REQUEST_METHOD'] === 'GET') {
+ // user maybe does not accept cookies, replace session id in url
+ // otherwise reloading the page will generate a new session
+
+ $this->update();
+ HeaderUtil::redirect(str_replace('s='.$oldSessionID, 's='.$newSessionID, UserUtil::getRequestURI()));
+ exit;
+ }
+ }
+
/**
* Enables cookie support.
*/
// update session
$sessionEditor = new $this->sessionEditorClassName($this->session);
- // regenerating the session id is essential to prevent session fixation attacks
- // FIXME: but it cannot be used if cookies are not available, as the constants are already
- // defined, erase security token in this case for basic security
- if ($this->useCookies) {
- $newSessionID = StringUtil::getRandomID();
- }
- else {
- $this->unregister('__SECURITY_TOKEN');
- $newSessionID = $this->session->sessionID;
- }
+ $this->register('__changeSessionID', true);
try {
$sessionEditor->update(array(
- 'sessionID' => $newSessionID,
'userID' => $user->userID
));
}
AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute(array($this->sessionID, $user->userID));
-
+
// update session
$sessionEditor->update(array(
- 'sessionID' => $newSessionID,
'userID' => $user->userID
));
}
throw $e;
}
}
-
- $this->session = new $this->sessionClassName($newSessionID);
-
- if ($this->useCookies) HeaderUtil::setCookie('cookieHash', $newSessionID);
}
}
$sessionEditor = new $this->sessionEditorClassName($this->session);
try {
- // regenerating the session id is essential to prevent session fixation attacks
- // FIXME: but it cannot be used if cookies are not available, as the constants are already
- // defined, erase security token in this case for basic security
- if ($this->useCookies) {
- $newSessionID = StringUtil::getRandomID();
- }
- else {
- $this->unregister('__SECURITY_TOKEN');
- $newSessionID = $this->session->sessionID;
- }
+ $this->register('__changeSessionID', true);
$sessionEditor->update(array(
- 'sessionID' => $newSessionID,
'userID' => $user->userID
));
- $this->session = new $this->sessionClassName($newSessionID);
-
- if ($this->useCookies) HeaderUtil::setCookie('cookieHash', $newSessionID);
}
catch (DatabaseException $e) {
// MySQL error 23000 = unique key