<?php
/* Check password security, check AlbumCookie and load user preferences.
* Make sure globals.php and db.php are both included before this file.
*
* Inputs from web browser:
* AlbumCookie - a cookie
* admin - do we want to be in admin mode
*
* The following variables are set by this include file:
* user_record - database record for logged in user
* cookie_record - database record if browser has cookie, false otherwise
* admin - are we in admin mode
* admin_allow - full admin mode is allowed
* admin_allow_read_only - read-only admin mode is allowed
*
* Written by: Chris Studholme
* Copyright: GPL (http://www.fsf.org/copyleft/gpl.html)
* $Id: security.php,v 1.13 2003/12/17 04:28:20 cstudhol Exp $
*/
function sql_users_login($login) {
global $conn;
return "SELECT *, (now()-date_login>'5 min') AS loginflag".
" FROM users WHERE login=".$conn->quote_string($login);
}
function sql_users_query($userid) {
return "SELECT *, (now()-date_login>'5 min') AS loginflag".
" FROM users WHERE userid=".$userid;
}
function sql_cookies_query($cookie) {
global $conn,$config;
$limit = $config["auth_cookielogin_timelimit"];
return "SELECT *, (now()-date_login>'5 min') AS loginflag,".
" (now()-date_login>".$conn->quote_string($limit." days").
") AS passwordflag FROM cookies".
" WHERE cookie=".$conn->quote_string($cookie);
}
// returns database record if found, false otherwise.
function query_cookie($cookie) {
global $conn;
$result = $conn->query(sql_cookies_query($cookie));
if (($result)&&($result->num_rows()>0))
return $result->fetch_assoc();
return array();
}
// returns database record if found, false otherwise.
function query_user($login) {
global $conn;
$result = $conn->query(sql_users_login($login));
if (($result)&&($result->num_rows()>0))
return $result->fetch_assoc();
return array();
}
// returns database record if found, false otherwise.
function query_userid($userid) {
global $conn;
$result = $conn->query(sql_users_query($userid));
if (($result)&&($result->num_rows()>0))
return $result->fetch_assoc();
return array();
}
function update_cookie_login($cookie_record) {
global $conn;
if ($cookie_record["loginflag"]!="f") {
$fields = array("date_login"=>$conn->date_now(),
"addr"=>$conn->quote_string(getenv("REMOTE_ADDR")));
if ($cookie_record["userid"])
$fields["userid"]=$cookie_record["userid"];
$query = $conn->sql_update("cookies",$fields,
"cid=".$cookie_record["cid"]);
@$conn->query($query,true); // we don't care if it succeeds or not
}
}
function update_user_login($user_record) {
global $conn;
if ($user_record["loginflag"]!="f") {
$query = $conn->sql_update("users",
array("date_login"=>$conn->date_now()),
"userid=".$user_record["userid"]).";";
@$conn->query($query,true); // we don't care if it succeeds or not
}
}
/* Lookup cookie in database and load preferences. If the newcookie field
* is non-blank, the user's cookie is changed to the cookie specified in
* newcookie and that new cookie is looked up in the database. cookie_login
* cannot be used in cases where a change of cookie is being made.
*
* If successful, the database record corresponding to the cookie is returned.
* Otherwise, false is returned.
* If cookie_record["_cookie_login"]==true, no password is required.
*/
function verify_cookie($cookie,$admin) {
global $config,$admin_cookie_login;
$change=false;
while ($cookie) {
$cookie_record = query_cookie($cookie);
if (!$cookie_record) {
// bogus cookie
return array();
}
if (!$cookie_record["newcookie"]) {
$cookie_record["_cookie_login"]=false;
// reasons why cookie login is not allowed
if ($change||
!$cookie_record["userid"]||
($cookie_record["passwordflag"]!="f")||
($config["auth_cookielogin_location"]&&
($cookie_record["addr"]!=getenv("REMOTE_ADDR")))) {
return $cookie_record;
}
// one more reason
if ($admin&&!$admin_cookie_login) {
return $cookie_record;
}
// cookie login is allowed
$cookie_record["_cookie_login"]=true;
return $cookie_record;
}
// cookie has been deprecated, switch to new cookie
$cookie=$cookie_record["newcookie"];
$change=true;
// update last login (attempt) in cookies table
update_cookie_login($cookie_record);
}
return array();
}
/* If we're using the built-in password_list security, check the supplied
* username and password against the list. If no match is found, output
* to client '401 Unauthorized' code and return false. Return database
* record for user if password is ok.
*/
function verify_user($user_record=array()) {
global $HTTP_SERVER_VARS;
global $external_login;
global $config, $conn;
if ($external_login) {
$remote_user = getenv("REMOTE_USER");
if ($remote_user) {
if ($remote_user!=$user_record["login"])
$user_record = query_user($remote_user);
if ($remote_user==$user_record["login"])
return $user_record;
}
// failed to find user in database
Header("HTTP/1.0 403 Forbidden");
}
else {
$auth_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
$auth_pw = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
if (isset($auth_user)&&$auth_user) {
if ($auth_user!=$user_record["login"])
$user_record = query_user($auth_user);
if ($user_record&&
password_check($auth_pw,$user_record["password"]))
return $user_record;
}
Header("WWW-Authenticate: Basic realm=\"".$config["auth_realm"]."\"");
Header("HTTP/1.0 401 Unauthorized");
}
start_head();
end_head_start_body(true);
$strings = get_strings();
format_error($strings["err_noaccess"],$strings["err_noaccess_long"]);
end_body();
return false;
}
/**************************************************************************/
// check inputs
$AlbumCookie = input_cookie();
$admin = input_int("admin");
/* First, if the browser has submitted a cookie, look it up in the database
* and check if a cookie_login can be done. For cookie_login to work, all
* the following must be true:
* - record for cookie exists in database
* - the cookie is not deprecated
* - the last login with that cookie wasn't too long ago
* - the login may need to come from the same address as the last login
* - userid in the cookie record is valid
* - the user is not disabled
* - if in admin mode, additional restrictions may apply
*/
$user_record=array();
// check the cookie
$cookie_record=verify_cookie($AlbumCookie,$admin);
if ($cookie_record["_cookie_login"]) {
// make sure we can read user record from database
$user_record = query_userid($cookie_record["userid"]);
if (!$user_record||!$user_record["password"])
$cookie_record["_cookie_login"]=false;
}
if (!$cookie_record["_cookie_login"]) {
// password is required
$user_record = verify_user($user_record);
if (!$user_record)
exit();
}
/* At this point, the user is successfully logged in. */
// make sure userid in cookie_record is correct
if ($cookie_record&&($cookie_record["userid"]!=$user_record["userid"])) {
$cookie_record["userid"] = $user_record["userid"];
$cookie_record["loginflag"] = false;
}
// update cookie with browser and maybe in database too
if ($cookie_record) {
// send updated cookie to browser
SetCookie("AlbumCookie",$cookie_record["cookie"],time()+$cookie_expire);
// update cookie record in database
update_cookie_login($cookie_record);
}
// update user record in database
update_user_login($user_record);
// if admin, verify admin's source location
if (($user_record["admin"]==1)||($cookie_record["admin"]==1)) {
// check for SSL
if (getenv("HTTPS")=="on" && getenv("HTTPS_CIPHER") &&
(int)getenv("HTTPS_KEYSIZE")>=$admin_ssl_keybits) {
if (ereg("^".$admin_address_ssl."$",getenv("REMOTE_ADDR"))) {
$admin_allow=true;
$admin_allow_read_only=true;
}
}
else {
// non-SSL
if (ereg("^".$admin_address_allow."$",getenv("REMOTE_ADDR"))) {
$admin_allow=true;
$admin_allow_read_only=true;
}
}
}
// admin_address_always is a backdoor for admins to get in (use carefully!)
if ($admin_address_always&&
ereg("^".$admin_address_always."$",getenv("REMOTE_ADDR"))) {
$admin_allow=true;
$admin_allow_read_only=true;
}
// need at least read-only admin to have any admin at all
if (!$admin_allow_read_only) {
$admin_allow=false;
$admin=false;
}
?>