* Copyright 1999-2001, VA Linux Systems, Inc.
* Copyright 2001-2002, 2009, Roland Mas
* Copyright 2004-2005, GForge, LLC
+ * Copyright 2013, Franck Villaume - TrivialDev
+ * Copyright © 2013
+ * Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
*
* This file is part of FusionForge. FusionForge is free software;
* you can redistribute it and/or modify it under the terms of the
$session_ser = getStringFromCookie('session_ser');
/**
- * session_build_session_cookie() - Construct session cookie for the user
+ * session_build_session_token() - Construct session token for the user
*
* @param int User_id of the logged in user
- * @return cookie value
+ * @return string token value
*/
-
- $session_serial = $user_id.'-*-'.time().'-*-'.getStringFromServer('REMOTE_ADDR').'-*-'.getStringFromServer('HTTP_USER_AGENT');
- $session_serial_hash = md5($session_serial.forge_get_config('session_key'));
- $session_serial_token = base64_encode($session_serial).'-*-'.$session_serial_hash;
- return $session_serial_token;
+function session_build_session_token($user_id) {
+ if (!$user_id) {
+ return '';
+ }
++ return session_build_session_cookie($user_id);
++}
+ function session_build_session_cookie($user_id) {
+ $session_cookie_data = array(
+ $user_id,
+ getStringFromServer('REMOTE_ADDR'),
+ getStringFromServer('HTTP_USER_AGENT'),
+ );
+ $session_cookie = "" . time();
+ foreach ($session_cookie_data as $s) {
+ /* for escaping; this is not really HTML */
+ $session_cookie .= '<' . util_html_encode($s);
+ }
+ $session_cookie_hmac = hash_hmac("sha256", $session_cookie,
+ forge_get_config('session_key'), true);
+ $session_serial_cookie = base64_encode($session_cookie) . '!' .
+ base64_encode($session_cookie_hmac);
+ return $session_serial_cookie;
}
/**
*
* This hash can be used as a key to identify session, e.g. in DB.
*
- * @param string Value of the session cookie
+ * @param string Value of the session token
* @return hash
*/
- list ($junk, $hash) = explode('-*-', $session_token);
- return $hash;
+function session_get_hash_from_token($session_token) {
++ return session_get_session_cookie_hash($session_token);
++}
+ function session_get_session_cookie_hash($session_cookie) {
+ /*
+ * we cannot just use the HMAC as that may be longer than
+ * the database fields, and this code used to return a
+ * string of the size of an md5(), so just md5 it
+ */
+ return md5($session_cookie);
}
/**
- * session_check_session_cookie() - Check that session cookie passed from user is ok
+ * session_check_session_token() - Check that session token passed from user is ok
*
- * @param string Value of the session cookie
- * @return user_id if cookie is ok, false otherwise
+ * @param string Value of the session token
+ * @return user_id if token is ok, false otherwise
*/
+function session_check_session_token($session_token) {
+ if ($session_token == '') {
+ return false;
+ }
++ return session_check_session_cookie($session_token);
++}
+ function session_check_session_cookie($session_cookie) {
+ if (!preg_match('#^[A-Za-z0-9+/=]*![A-Za-z0-9+/=]*$#',
+ $session_cookie)) {
+ /*
+ * does not match basic format, off; recommended by
+ * http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
+ * to protect the below code from malformed strings
+ */
+ return false;
+ }
- list ($session_serial, $hash) = explode('-*-', $session_token);
- $session_serial = base64_decode($session_serial);
- $new_hash = md5($session_serial.forge_get_config('session_key'));
-
- if ($hash != $new_hash) {
+ list($session_cookie, $session_cookie_hmac) = explode('!',
+ $session_cookie);
+ $session_cookie = base64_decode($session_cookie);
+ $session_cookie_hmac = base64_decode($session_cookie_hmac);
+ if (hash_hmac("sha256", $session_cookie,
+ forge_get_config('session_key'), true) !== $session_cookie_hmac) {
+ /* HMAC mismatch */
return false;
}
*
*/
function session_logout() {
- RBACEngine::getInstance()->invalidateRoleCaches() ;
+ plugin_hook('close_auth_session');
++
+ // delete both session and username cookies
+ // NB: cookies must be deleted with the same scope parameters they were set with
+ //
+ session_cookie('session_ser', '');
+
+ RBACEngine::getInstance()->invalidateRoleCaches();
return true;
}
return false;
}
- return session_login_valid_dbonly ($loginname, $passwd, $allowpending) ;
- }
-
- function session_login_valid_dbonly($loginname, $passwd, $allowpending=false) {
- return session_check_credentials_in_database($loginname, $passwd, $allowpending);
+ return session_login_valid_dbonly($loginname, $passwd, $allowpending);
}
- global $warning_msg ,$userstatus;
+function session_check_credentials_in_database($loginname, $passwd, $allowpending=false) {
++ return session_login_valid_dbonly($loginname, $passwd, $allowpending);
++}
+ function session_login_valid_dbonly($loginname, $passwd, $allowpending) {
+ global $feedback, $userstatus;
- // Try to get the users from the database using user_id and (MD5) user_pw
+ // Try to get the users from the database using user_id and (MD5) user_pw
if (forge_get_config('require_unique_email')) {
$res = db_query_params ('SELECT user_id,status,unix_pw FROM users WHERE (user_name=$1 OR email=$1) AND user_pw=$2',
array ($loginname,
return false;
}
}
- //create a new session
+ // create a new session
- session_set_new(db_result($res,0,'user_id'));
+ session_set_new(db_result($res, 0, 'user_id'));
return true;
}
* @param string Value of cookie
* @param string Domain scope (default '')
* @param string Expiration time in UNIX seconds (default 0)
- * @return true/false
*/
- function session_set_cookie($name ,$value, $domain = '', $expiration = 0) {
- if (php_sapi_name() != 'cli') {
- if ( $expiration != 0){
- setcookie($name, $value, time() + $expiration, '/', $domain, 0);
- } else {
- setcookie($name, $value, $expiration, '/', $domain, 0);
- }
++function session_set_cookie($name, $value, $domain='', $expiration=0) {
++ return session_cookie($name, $value, $domain, $expiration);
++}
+ function session_cookie($name, $value, $domain='', $expiration=0) {
+ if (php_sapi_name() == 'cli') {
+ return;
+ }
+ if ($expiration) {
+ $expiration = time() + $expiration;
+ }
+ /* evolvis: force secure (SSL-only) session cookies */
+ //$force_secure = true;
+ /* not (yet?) in FusionForge */
+ $force_secure = false;
+ if ($force_secure && !session_issecure()) {
+ return;
}
+ setcookie($name, $value, $expiration, '/', $domain, $force_secure, true);
}
/**
- * session_redirect() - Redirect browser within the site
+ * session_redirect_uri() - Redirect browser
*
- * @param string Absolute path within the site
+ * @param string Absolute URI
* @return never returns
*/
- function session_redirect($loc) {
- session_redirect_external(util_make_url ($loc));
++function session_redirect_external($url) {
++ session_redirect_uri($url);
++}
+ function session_redirect_uri($loc) {
+ sysdebug_off("Status: 301 Moved Permanently", true, 301);
+ header("Location: ${loc}", true);
+ echo "\nPlease go to ${loc} instead!\n";
exit;
}
* fails checks.
*
*/
- function session_require_perm($section, $reference, $action = NULL, $reason='') {
+ function session_require_perm($section, $reference, $action=NULL, $reason='') {
if (!forge_check_perm($section, $reference, $action)) {
- exit_permission_denied($reason, '');
+ exit_permission_denied($reason, $section);
}
}
if (!forge_check_global_perm($section, $action)) {
if (!$reason) {
$reason = sprintf(_('Permission denied. The %s administrators will have to grant you permission to view this page.'),
- forge_get_config ('forge_name')) ;
+ forge_get_config('forge_name'));
}
- exit_permission_denied($reason, '');
+ exit_permission_denied($reason, $section);
}
}
* @return none
*/
function session_set_new($user_id) {
- global $session_ser;
+ $token = session_build_session_token($user_id);
- $res = db_query_params ('SELECT count(*) as c FROM user_session WHERE session_hash = $1',
- array (session_get_hash_from_token($token))) ;
- if (!$res || db_result($res,0,'c') < 1) {
- db_query_params ('INSERT INTO user_session (session_hash,ip_addr,time,user_id) VALUES ($1,$2,$3,$4)',
- array (session_get_hash_from_token($token),
- getStringFromServer('REMOTE_ADDR'),
- time(),
- $user_id)) ;
+ // set session cookie
+ //
+ $cookie = session_build_session_cookie($user_id);
- session_cookie("session_ser", $cookie, "", forge_get_config('session_expire'));
- $session_ser = $cookie;
++// session_cookie("session_ser", $cookie, "", forge_get_config('session_expire'));
++// $session_ser = $cookie;
+
+ $res = db_query_params('SELECT count(*) as c FROM user_session
+ WHERE session_hash=$1',
+ array(($shash = session_get_session_cookie_hash($cookie))));
+ if (!$res || db_result($res, 0, 'c') < 1) {
+ db_query_params('INSERT INTO user_session
+ (session_hash,ip_addr,time,user_id)
+ VALUES ($1,$2,$3,$4)',
+ array(
+ $shash,
+ getStringFromServer('REMOTE_ADDR'),
+ time(),
+ $user_id,
+ ));
}
// check uniqueness of the session_hash in the database
// otherwise make new session
$id_is_good = false;
- // If user says he's logged in (by presenting cookie), check that
- if ($session_ser) {
- $user_id = session_check_session_cookie($session_ser);
- if ($user_id) {
- $result = session_getdata($user_id);
- if (db_numrows($result) > 0) {
- $id_is_good = true;
- }
+ $params = array();
+ // pass the session_ser from cookie to the auth plugins
+ // (see AuthBuiltinPlugin::checkAuthSession() or likes)
+ // expect FORGE_AUTH_AUTHORITATIVE_ACCEPT, FORGE_AUTH_AUTHORITATIVE_REJECT or FORGE_AUTH_NOT_AUTHORITATIVE
+ // in results
+ $params['auth_token'] = $session_ser;
+ $params['results'] = array();
+ plugin_hook_by_reference('check_auth_session', $params);
+
+ $seen_yes = false;
+ $seen_no = false;
+ foreach ($params['results'] as $p => $r) {
+ if ($r == FORGE_AUTH_AUTHORITATIVE_ACCEPT) {
+ $seen_yes = true;
+ } elseif ($r == FORGE_AUTH_AUTHORITATIVE_REJECT) {
+ $seen_no = true;
}
- } // else (hash does not exist) or (session hash is bad)
+ }
+ if ($seen_yes && !$seen_no) {
+ // see AuthBuiltinPlugin::fetchAuthUser() or likes
+ // expect user object in results
+ $params = array();
+ $params['results'] = NULL;
+ plugin_hook_by_reference('fetch_authenticated_user', $params);
+ $user = $params['results'];
+
+ if ($user) {
+ $params = array();
+ $params['username'] = $user->getUnixName();
+ $params['event'] = 'every-page';
+ plugin_hook('sync_account_info', $params);
+
+ $user->setLoggedIn(true);
+ $G_SESSION = $user;
+ } else {
+ $G_SESSION=false;
+ }
+ }
+ // TODO: else... what ?
+
+ $re = RBACEngine::getInstance();
+ $re->invalidateRoleCaches() ;
+}
+
+/**
+ * Re initializes a session, trusting a non-sufficient plugin only temporarily
+ *
+ * The checkAuthSession of the Auth plugin will have to acknowledge the 'sufficient_forced' param in 'check_auth_session' hook
+ * @param string $authpluginname
+ */
+function session_set_for_authplugin($authpluginname) {
+ global $G_SESSION;
+ global $session_ser;
+
+ // assume bad session_hash and session. If all checks work, then allow
+ // otherwise make new session
+ $id_is_good = false;
+
+ $params = array();
+ // pass the session_ser from cookie to the auth plugins
+ // (see AuthBuiltinPlugin::checkAuthSession() or likes)
+ // expect FORGE_AUTH_AUTHORITATIVE_ACCEPT, FORGE_AUTH_AUTHORITATIVE_REJECT or FORGE_AUTH_NOT_AUTHORITATIVE
+ // in results
+ $params['sufficient_forced'] = $authpluginname;
+
+ $params['auth_token'] = $session_ser;
+ $params['results'] = array();
+
+ plugin_hook_by_reference('check_auth_session', $params);
- if ($id_is_good) {
- $G_SESSION = user_get_object($user_id, $result);
- if ($G_SESSION) {
- $G_SESSION->setLoggedIn(true);
+ $seen_yes = false;
+ foreach ($params['results'] as $p => $r) {
+ if ($r == FORGE_AUTH_AUTHORITATIVE_ACCEPT) {
+ $seen_yes = true;
}
- } else {
- $G_SESSION=false;
+ }
+
+ if ($seen_yes) {
+ //echo "user ok\n";
+ // see AuthBuiltinPlugin::fetchAuthUser() or likes
+ // expect user object in results
+ $params = array();
+ $params['results'] = NULL;
- // if there was bad session cookie, kill it and the user cookie
- if ($session_ser) {
- session_logout();
+ plugin_hook_by_reference('fetch_authenticated_user', $params);
+
+ $user = $params['results'];
+
+ if ($user) {
+ $params = array();
+ $params['username'] = $user->getUnixName();
+ $params['event'] = 'every-page';
+ plugin_hook('sync_account_info', $params);
+
+ $user->setLoggedIn(true);echo "user:".$user->getUnixName();
+ $G_SESSION = $user;
-
++
+ } else {
+ $G_SESSION=false;
}
}
- plugin_hook('session_set_return');
+ // TODO: else... what ?
- RBACEngine::getInstance()->invalidateRoleCaches();
+ $re = RBACEngine::getInstance();
+ //print_r($re->getGlobalRoles());
+ //print_r($re->getPublicRoles());
+ $re->invalidateRoleCaches() ;
+ //print_r($re->getAvailableRoles());
-
-
}
//TODO - this should be generalized and used for pre.php,