tbauth.php3 8.9 KB
Newer Older
1 2 3
<?php
#
# Login support: Beware empty spaces (cookies)!
4 5 6 7 8 9
#

$CHECKLOGIN_NOTLOGGEDIN = 0;
$CHECKLOGIN_LOGGEDIN    = 1;
$CHECKLOGIN_TIMEDOUT    = -1;
$CHECKLOGIN_MAYBEVALID  = 2;
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

#
# 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);
}

27 28 29
#
# 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
30
# and HASH back, and then check the DB to see if the user is really
31 32 33
# logged in.
# 
function GETLOGIN() {
34 35
    global $CHECKLOGIN_LOGGEDIN;

36 37 38
    if (($uid = GETUID()) == FALSE)
	    return FALSE;

39
    if (CHECKLOGIN($uid) == $CHECKLOGIN_LOGGEDIN)
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
	    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;
}

60
#
61
# Verify a login by sucking a UIDs current hash value out of the database.
62 63 64
# 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.
#
65 66 67 68 69 70
# Returns: if not logged in ever.
#          if logged in okay
#          if login timed out
#          if login record exists, is not timed out, but no hash cookie.
#             this case will be caught later when the user tries to do
#             something for which a valid login is required.
71
#
72
function CHECKLOGIN($uid) {
73
    global $TBDBNAME, $TBAUTHCOOKIE, $HTTP_COOKIE_VARS, $TBAUTHTIMEOUT;
74 75
    global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
    global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
76 77

    $curhash = $HTTP_COOKIE_VARS[$TBAUTHCOOKIE];
78 79 80 81 82 83 84 85 86 87

    $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) {
88
	return $CHECKLOGIN_NOTLOGGEDIN;
89 90 91 92 93 94
    }

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

    # A match?
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    if ($timeout > time()) {
        if (strcmp($curhash, $hashkey) == 0) {
	    #
   	    # 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);
	    }
	    return $CHECKLOGIN_LOGGEDIN;
	}
	elseif (!isset($curhash) || !$curhash || $curhash == NULL) {
	    #
	    # A login is valid, but we have no proof yet. Proof will be
	    # demanded later by whatever page wants it.
	    # 
	    return $CHECKLOGIN_MAYBEVALID;
	}
121 122 123 124 125 126 127 128 129 130 131 132
    }

    #
    # 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);
    }

133
    return $CHECKLOGIN_TIMEDOUT;
134 135 136 137 138 139 140
}

#
# This one checks for login, but then dies with an appropriate error
# message.
#
function LOGGEDINORDIE($uid) {
141 142
    global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
    global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
143

144
    $status = CHECKLOGIN($uid);
145
    switch ($status) {
146 147
    case $CHECKLOGIN_NOTLOGGEDIN:
        USERERROR("You do not appear to be logged in!", 1);
148
        break;
149
    case $CHECKLOGIN_LOGGEDIN:
150 151
        return $uid;
        break;
152
    case $CHECKLOGIN_TIMEDOUT:
153 154
        USERERROR("Your login has timed out! Please log in again.", 1);
        break;
155 156 157
    case $CHECKLOGIN_MAYBEVALID:
        USERERROR("Your login cannot be verified. Are cookies turned on?", 1);
        break;
158 159 160 161 162 163 164 165 166
    }
    TBERROR("LOGGEDINORDIE failed mysteriously", 1);
}

#
# Attempt a login.
# 
function DOLOGIN($uid, $password) {
    global $TBDBNAME, $TBAUTHCOOKIE, $TBAUTHDOMAIN, $TBAUTHTIMEOUT;
167
    global $TBNAMECOOKIE, $TBSECURECOOKIES;
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

    $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. 
        #
192
	$timeout = time() + $TBAUTHTIMEOUT;
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	$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);
        }

212 213 214 215 216 217
	#
	# Create a last login record.
	#
	$query_result = mysql_db_query($TBDBNAME,
	       "REPLACE into lastlogin (uid, time) VALUES ('$uid', NOW())");

218
	#
219 220 221 222 223 224 225 226 227
	# 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. 
228
	#
229
	$timeout = time() + (60 * 60 * 24);
230 231
	setcookie($TBAUTHCOOKIE, $hashkey, $timeout, "/",
                  $TBAUTHDOMAIN, $TBSECURECOOKIES);
232

233 234 235 236 237 238 239 240 241 242 243
	#
	# 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);

244 245 246 247 248 249 250 251 252 253 254 255 256 257
	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) {
258
    global $TBDBNAME, $TBSECURECOOKIES;
259 260 261 262 263 264 265 266 267 268 269 270 271 272

    $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];
273
    $timeout = time() - 1000000;
274 275 276 277 278 279 280

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

    #
    # Issue a cookie request to delete the cookie. 
    #
281
    setcookie($TBAUTHCOOKIE, "", $timeout, "/", $TBAUTHDOMAIN, 0);
282 283 284 285

    return 0;
}

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
#
# Primitive "nologins" support.
#
function NOLOGINS() {
    global $TBDBNAME;

    $query_result = mysql_db_query($TBDBNAME,
	"SELECT nologins FROM nologins where nologins=1");
    if (! $query_result) {
        $err = mysql_error();
        TBERROR("Database Error nologins info: $err\n", 1);
    }

    # No entry
    if (($row = mysql_fetch_array($query_result)) == 0) {
	return 0;
    }

    $nologins = $row[nologins];
    return $nologins;
}

308 309 310 311 312 313 314 315 316 317 318 319 320
function LASTWEBLOGIN($uid) {
    global $TBDBNAME;

    $query_result = mysql_db_query($TBDBNAME,
	"SELECT time from lastlogin where uid=\"$uid\"");
    
    if (mysql_num_rows($query_result)) {
	$lastrow      = mysql_fetch_array($query_result);
	return $lastrow[time];
    }
    return 0;
}

321 322 323 324
#
# Beware empty spaces (cookies)!
# 
?>