Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*/

use wcf\system\database\table\column\BinaryDatabaseTableColumn;
use wcf\system\database\table\column\CharDatabaseTableColumn;
use wcf\system\database\table\column\DefaultFalseBooleanDatabaseTableColumn;
use wcf\system\database\table\column\IntDatabaseTableColumn;
Expand Down Expand Up @@ -75,8 +76,23 @@
]),
PartialDatabaseTable::create('wcf1_acp_session_log')
->columns([
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40),
NotNullVarchar255DatabaseTableColumn::create('hostname')
->defaultValue('')
->drop(),
]),
PartialDatabaseTable::create('wcf1_session')
->columns([
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40),
]),
PartialDatabaseTable::create('wcf1_user_session')
->columns([
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40),
]),
];
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace wcf\system\package;

use ParagonIE\ConstantTime\Hex;
use wcf\data\application\Application;
use wcf\data\application\ApplicationBuilder;
use wcf\data\devtools\project\DevtoolsProjectAction;
Expand Down Expand Up @@ -257,9 +256,9 @@ protected function finalizeWcfSetup(): void
'user_session',
CryptoUtil::createSignedString(
\pack(
'CA20C',
1,
Hex::decode(WCF::getSession()->sessionID),
'Ca40C',
2,
WCF::getSession()->sessionID,
0
)
)
Expand Down
41 changes: 37 additions & 4 deletions wcfsetup/install/files/lib/system/session/SessionHandler.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace wcf\system\session;

use ParagonIE\ConstantTime\Base32;
use ParagonIE\ConstantTime\Hex;
use wcf\data\session\Session as LegacySession;
use wcf\data\session\SessionEditor;
Expand Down Expand Up @@ -194,6 +195,19 @@ private function parseCookie(string $value): array

return $data;

case 2:
if ($length !== 42) {
throw new \InvalidArgumentException(\sprintf(
'Expected exactly 42 Bytes, %d given.',
$length
));
}
$data = \unpack('Cversion/a40sessionId/Ctimestep', $value);
\assert($data['version'] === 2);
\assert(\strlen($data['sessionId']) === 40);

return $data;

default:
throw new \InvalidArgumentException(\sprintf(
'Unknown version %d',
Expand Down Expand Up @@ -275,9 +289,9 @@ private function getCookieValue(): string
}

return CryptoUtil::createSignedString(\pack(
'CA20C',
1,
Hex::decode($this->sessionID),
'Ca40C',
2,
$this->sessionID,
$this->getCookieTimestep()
));
}
Expand Down Expand Up @@ -637,7 +651,7 @@ private function getExistingSession(string $sessionID): bool
*/
private function create(): void
{
$this->sessionID = Hex::encode(\random_bytes(20));
$this->sessionID = $this->generateSessionID();

$variables = [
'frontend' => [],
Expand Down Expand Up @@ -692,6 +706,25 @@ private function create(): void
);
}

/**
* Generates a session ID that starts with its creation time, keeping inserts into
* the primary key of `wcf1_user_session` close to sequential.
*
* Format: 4 bytes of seconds and 1 byte of 1/256 second steps as Base16, followed by
* 17 random bytes (136 bits) as Base32 and the format version `V2`.
*/
private function generateSessionID(): string
{
// Both parts must come from the same clock reading, `TIME_NOW` is fixed at
// the start of the request and would break the ordering within a second.
$now = \microtime(true);
$seconds = (int)$now;

return Hex::encode(\pack('NC', $seconds, (int)(($now - $seconds) * 256)))
. \substr(Base32::encode(\random_bytes(17)), 0, 28)
. 'V2';
}

/**
* Returns the existing legacy session that is shared by all guest sessions of the given spider.
*/
Expand Down
9 changes: 4 additions & 5 deletions wcfsetup/setup/db/install_com.woltlab.wcf.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,9 @@
DatabaseTable::create('wcf1_acp_session_log')
->columns([
ObjectIdDatabaseTableColumn::create('sessionLogID'),
CharDatabaseTableColumn::create('sessionID')
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40)
->defaultValue(''),
->length(40),
IntDatabaseTableColumn::create('userID'),
VarcharDatabaseTableColumn::create('ipAddress')
->notNull()
Expand Down Expand Up @@ -3216,7 +3215,7 @@
]),
DatabaseTable::create('wcf1_session')
->columns([
CharDatabaseTableColumn::create('sessionID')
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40),
IntDatabaseTableColumn::create('userID'),
Expand Down Expand Up @@ -4777,7 +4776,7 @@
]),
DatabaseTable::create('wcf1_user_session')
->columns([
CharDatabaseTableColumn::create('sessionID')
BinaryDatabaseTableColumn::create('sessionID')
->notNull()
->length(40),
IntDatabaseTableColumn::create('userID'),
Expand Down
Loading