Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reresubmit: improved persistent cookies :) #31

Merged
merged 15 commits into from
Oct 16, 2012
Merged
5 changes: 4 additions & 1 deletion config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
/* Loglevel to start logging at. 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR (default is WARN) */
"loglevel" => "",

/* Lifetime of the remember login cookie, default is 15 days */
"remember_login_cookie_lifetime" => 60*60*24*15,

/* The directory where the user data is stored, default to data in the owncloud
* directory. The sqlite database is also stored here, when sqlite is used.
*/
Expand All @@ -104,4 +107,4 @@
'writable' => true,
),
),
);
);
70 changes: 60 additions & 10 deletions lib/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,30 @@ public static function initTemplateEngine() {
}

public static function initSession() {
// prevents javascript from accessing php session cookies
ini_set('session.cookie_httponly', '1;');

// (re)-initialize session
session_start();

// regenerate session id periodically to avoid session fixation
if (!isset($_SESSION['SID_CREATED'])) {
$_SESSION['SID_CREATED'] = time();
} else if (time() - $_SESSION['SID_CREATED'] > 900) {
session_regenerate_id(true);
$_SESSION['SID_CREATED'] = time();
}

// session timeout
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) {
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time() - 42000, '/');
}
session_unset();
session_destroy();
session_start();
}
$_SESSION['LAST_ACTIVITY'] = time();
}

public static function init() {
Expand Down Expand Up @@ -449,6 +471,7 @@ public static function handleRequest() {
OC_App::loadApps();
OC_User::setupBackends();
if(isset($_GET["logout"]) and ($_GET["logout"])) {
OC_Preferences::deleteKey(OC_User::getUser(), 'login_token', $_COOKIE['oc_token']);
OC_User::logout();
header("Location: ".OC::$WEBROOT.'/');
}else{
Expand Down Expand Up @@ -510,6 +533,17 @@ protected static function handleLogin() {
OC_Util::displayLoginPage($error);
}

protected static function cleanupLoginTokens($user) {
$cutoff = time() - OC_Config::getValue('remember_login_cookie_lifetime', 60*60*24*15);
$tokens = OC_Preferences::getKeys($user, 'login_token');
foreach($tokens as $token) {
$time = OC_Preferences::getValue($user, 'login_token', $token);
if ($time < $cutoff) {
OC_Preferences::deleteKey($user, 'login_token', $token);
}
}
}

protected static function tryRememberLogin() {
if(!isset($_COOKIE["oc_remember_login"])
|| !isset($_COOKIE["oc_token"])
Expand All @@ -523,15 +557,30 @@ protected static function tryRememberLogin() {
OC_Log::write('core', 'Trying to login from cookie', OC_Log::DEBUG);
}
// confirm credentials in cookie
if(isset($_COOKIE['oc_token']) && OC_User::userExists($_COOKIE['oc_username']) &&
OC_Preferences::getValue($_COOKIE['oc_username'], "login", "token") === $_COOKIE['oc_token'])
{
OC_User::setUserId($_COOKIE['oc_username']);
OC_Util::redirectToDefaultPage();
}
else {
OC_User::unsetMagicInCookie();
if(isset($_COOKIE['oc_token']) && OC_User::userExists($_COOKIE['oc_username'])) {
// delete outdated cookies
self::cleanupLoginTokens($_COOKIE['oc_username']);
// get stored tokens
$tokens = OC_Preferences::getKeys($_COOKIE['oc_username'], 'login_token');
// test cookies token against stored tokens
if (in_array($_COOKIE['oc_token'], $tokens, true)) {
// replace successfully used token with a new one
OC_Preferences::deleteKey($_COOKIE['oc_username'], 'login_token', $_COOKIE['oc_token']);
$token = OC_Util::generate_random_bytes(32);
OC_Preferences::setValue($_COOKIE['oc_username'], 'login_token', $token, time());
OC_User::setMagicInCookie($_COOKIE['oc_username'], $token);
// login
OC_User::setUserId($_COOKIE['oc_username']);
OC_Util::redirectToDefaultPage();
// doesn't return
}
// if you reach this point you have changed your password
// or you are an attacker
// we can not delete tokens here because users may reach
// this point multiple times after a password change
OC_Log::write('core', 'Authentication cookie rejected for user '.$_COOKIE['oc_username'], OC_Log::WARN);
}
OC_User::unsetMagicInCookie();
return true;
}

Expand All @@ -546,12 +595,13 @@ protected static function tryFormLogin() {
OC_User::setupBackends();

if(OC_User::login($_POST["user"], $_POST["password"])) {
self::cleanupLoginTokens($_POST['user']);
if(!empty($_POST["remember_login"])) {
if(defined("DEBUG") && DEBUG) {
OC_Log::write('core', 'Setting remember login to cookie', OC_Log::DEBUG);
}
$token = md5($_POST["user"].time().$_POST['password']);
OC_Preferences::setValue($_POST['user'], 'login', 'token', $token);
$token = OC_Util::generate_random_bytes(32);
OC_Preferences::setValue($_POST['user'], 'login_token', $token, time());
OC_User::setMagicInCookie($_POST["user"], $token);
}
else {
Expand Down
9 changes: 6 additions & 3 deletions lib/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ public static function setPassword( $uid, $password ) {
}
}
}
// invalidate all login cookies
OC_Preferences::deleteApp($uid, 'login_token');
OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password ));
return $success;
}
Expand Down Expand Up @@ -472,9 +474,10 @@ public static function isEnabled($userid) {
*/
public static function setMagicInCookie($username, $token) {
$secure_cookie = OC_Config::getValue("forcessl", false);
setcookie("oc_username", $username, time()+60*60*24*15, '', '', $secure_cookie);
setcookie("oc_token", $token, time()+60*60*24*15, '', '', $secure_cookie);
setcookie("oc_remember_login", true, time()+60*60*24*15, '', '', $secure_cookie);
$expires = time() + OC_Config::getValue('remember_login_cookie_lifetime', 60*60*24*15);
setcookie("oc_username", $username, $expires, '', '', $secure_cookie);
setcookie("oc_token", $token, $expires, '', '', $secure_cookie);
setcookie("oc_remember_login", true, $expires, '', '', $secure_cookie);
}

/**
Expand Down