tbauth.php3 6.95 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
<?php
#
# Login support: Beware empty spaces (cookies)!
# 

#
# Generate a hash value suitable for authorization. We use the results of
# microtime, combined with a random number.
# 
function GENHASH() {
    $fp = fopen("/dev/urandom", "r");
    if (! $fp) {
        TBERROR("Error opening /dev/urandom", 1);
    }
    $random_bytes = fread($fp, 8);
    fclose($fp);

    $hash  = mhash (MHASH_MD5, bin2hex($retval) . " " . microtime());
    return bin2hex($hash);
}

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#
# Return the value of the currently logged in uid, or null if not
# logged in. Basically, check the browser to see if its sending a UID
# and HASH back, and then check the DB to see if the useris really
# logged in.
# 
function GETLOGIN() {
    if (($uid = GETUID()) == FALSE)
	    return FALSE;

    if (CHECKLOGIN($uid) == 1)
	    return $uid;

    return FALSE;
}

#
# Return the value of the UID cookie. This does not check to see if
# this person is currently logged in. We just want to know what the
# browser thinks, if anything.
# 
function GETUID() {
    global $TBNAMECOOKIE, $HTTP_COOKIE_VARS;

    $curname = $HTTP_COOKIE_VARS[$TBNAMECOOKIE];
    if ($curname == NULL)
	    return FALSE;

    return $curname;
}

53 54 55 56 57 58 59 60 61 62 63
#
# Verify a login by sucking a UID's current hash value out of the database.
# If the login has expired, or of the hashkey in the database does not
# match what came back in the cookie, then the UID is no longer logged in.
#
# Should we advance the timeout since the user is still being active?
#
# Returns: 0 if not logged in ever.
#          1 if logged in okay
#         -1 if login timed out
#
64
function CHECKLOGIN($uid) {
65
    global $TBDBNAME, $TBAUTHCOOKIE, $HTTP_COOKIE_VARS, $TBAUTHTIMEOUT;
66 67

    $curhash = $HTTP_COOKIE_VARS[$TBAUTHCOOKIE];
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

    $query_result = mysql_db_query($TBDBNAME,
	"SELECT hashkey, timeout FROM login WHERE uid=\"$uid\"");
    if (! $query_result) {
        $err = mysql_error();
        TBERROR("Database Error retrieving login info for $uid: $err\n", 1);
    }

    # Not logged in.
    if (($row = mysql_fetch_array($query_result)) == 0) {
	return 0;
    }

    $hashkey = $row[hashkey];
    $timeout = $row[timeout];

    # A match?
    if ($timeout > time() &&
        strcmp($curhash, $hashkey) == 0) {
87 88 89 90 91 92 93 94 95 96 97 98 99 100
	#
	# We update the time in the database. Basically, each time the
	# user does something, we bump the logout further into the future.
	# This avoids timing them out just when they are doing useful work.
	#
	$timeout = time() + $TBAUTHTIMEOUT;

	$query_result = mysql_db_query($TBDBNAME,
		"UPDATE login set timeout='$timeout' ".
		"WHERE uid=\"$uid\"");
	if (! $query_result) {
            $err = mysql_error();
            TBERROR("Database Error updating login timeout for $uid: $err", 1);
        }
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
	return 1;
    }

    #
    # Clear out the database entry for completeness.
    #
    $query_result = mysql_db_query($TBDBNAME,
	"DELETE FROM login WHERE uid=\"$uid\"");
    if (! $query_result) {
        $err = mysql_error();
        TBERROR("Database Error deleting login info for $uid: $err\n", 1);
    }

    return -1;
}

#
# This one checks for login, but then dies with an appropriate error
# message.
#
function LOGGEDINORDIE($uid) {

123
    $status = CHECKLOGIN($uid);
124 125
    switch ($status) {
    case 0:
126
        USERERROR("You $uid do not appear to be logged in!", 1);
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
        break;
    case 1:
        return $uid;
        break;
    case -1:
        USERERROR("Your login has timed out! Please log in again.", 1);
        break;
    }
    TBERROR("LOGGEDINORDIE failed mysteriously", 1);
}

#
# Attempt a login.
# 
function DOLOGIN($uid, $password) {
    global $TBDBNAME, $TBAUTHCOOKIE, $TBAUTHDOMAIN, $TBAUTHTIMEOUT;
143
    global $TBNAMECOOKIE;
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

    $query_result = mysql_db_query($TBDBNAME,
	"SELECT usr_pswd FROM users WHERE uid=\"$uid\"");
    if (! $query_result) {
        $err = mysql_error();
        TBERROR("Database Error retrieving password for $uid: $err\n", 1);
    }

    #
    # Check password in the database against provided. 
    #
    if ($row = mysql_fetch_row($query_result)) {
        $db_encoding = $row[0];
        $salt = substr($db_encoding, 0, 2);
        if ($salt[0] == $salt[1]) { $salt = $salt[0]; }
        $encoding = crypt("$password", $salt);
        if (strcmp($encoding, $db_encoding)) {
            return -1;
        }
        #
        # Pass! Insert a record in the login table for this uid with
        # the new hash value. If the user is already logged in, thats
        # okay; just update it in place with a new hash and timeout. 
        #
168
	$timeout = time() + $TBAUTHTIMEOUT;
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
	$hashkey = GENHASH();
        $query_result = mysql_db_query($TBDBNAME,
		"SELECT timeout FROM login WHERE uid=\"$uid\"");
	if (mysql_num_rows($query_result)) {
		$query_result = mysql_db_query($TBDBNAME,
			"UPDATE login set ".
			"timeout='$timeout', hashkey='$hashkey' ".
			"WHERE uid=\"$uid\"");
	}
	else {
		$query_result = mysql_db_query($TBDBNAME,
			"INSERT into login (uid, hashkey, timeout) ".
                        "VALUES ('$uid', '$hashkey', '$timeout')");
	}
        if (! $query_result) {
            $err = mysql_error();
            TBERROR("Database Error logging in $uid: $err\n", 1);
        }

	#
189 190 191 192 193 194 195 196 197
	# Issue the cookie requests so that subsequent pages come back
	# with the hash value and auth usr embedded.

	#
	# For the hashkey, we give it a longish timeout since we are going
	# to control the actual timeout via the database. This just avoids
	# having to update the hash as we update the timeout in the database
	# each time the user does something. Eventually the cookie will
	# expire and the user will be forced to log in again anyway. 
198
	#
199
	$timeout = time() + (60 * 60 * 24);
200 201
	setcookie($TBAUTHCOOKIE, $hashkey, $timeout, "/", $TBAUTHDOMAIN, 0);

202 203 204 205 206 207 208 209 210 211 212
	#
	# We give this a really long timeout. We want to remember who the
	# the user was each time they load a page, and more importantly,
	# each time they come back to the main page so we can fill in their
	# user name. NOTE: This cookie is integral to authorization, since
	# we do not pass around the UID anymore, but look for it in the
	# cookie.
	# 
	$timeout = time() + (60 * 60 * 24 * 32);
	setcookie($TBNAMECOOKIE, $uid, $timeout, "/", $TBAUTHDOMAIN, 0);

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	return 0;
    }
    #
    # No such user
    #
    return -1;
}

#
# Log out a UID. Simply clear the entry from the login table.
#
# Should we kill the cookie? 
# 
function DOLOGOUT($uid) {
    global $TBDBNAME;

    $query_result = mysql_db_query($TBDBNAME,
	"SELECT hashkey timeout FROM login WHERE uid=\"$uid\"");
    if (! $query_result) {
        $err = mysql_error();
        TBERROR("Database Error retrieving login info for $uid: $err\n", 1);
    }

    # Not logged in.
    if (($row = mysql_fetch_array($query_result)) == 0) {
	return 0;
    }

    $hashkey = $row[hashkey];
    $timeout = time() - 3600;

    $query_result = mysql_db_query($TBDBNAME,
	"DELETE FROM login WHERE uid=\"$uid\"");

    #
    # Issue a cookie request to delete the cookie. 
    #
    setcookie($TBAUTHCOOKIE, $hashkey, $timeout, "/", $TBAUTHDOMAIN, 0);

    return 0;
}

#
# Beware empty spaces (cookies)!
# 
?>