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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    switch ($status) {
    case 0:
        USERERROR("You do not appear to be logged in!", 1);
        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)!
# 
?>