source: tags/1.0.0/lib/AuthSQL.inc.php @ 1

Last change on this file since 1 was 1, checked in by scdev, 19 years ago

Initial import.

File size: 32.6 KB
Line 
1<?php
2/**
3 * The Auth_File:: class provides a SQL implementation for authentication.
4 *
5 * @author  Quinn Comendant <quinn@strangecode.com>
6 * @inspiration  Horde's Auth class <www.horde.org>
7 * @version 1.0
8 */
9class AuthSQL {
10
11    var $_params = array();
12    var $_auth_name = '_auth';
13    var $_authentication_tested;
14
15    /**
16     * Constructs a new authentication object.
17     *
18     * @access public
19     *
20     * @param optional array $params  A hash containing parameters.
21     */
22    function AuthSQL($params = array())
23    {
24        global $CFG;
25       
26        // The name of this auth session.
27        $this->_params['auth_name'] = isset($params['auth_name']) ? $params['auth_name'] : '';
28       
29        // The database table containing users to authenticate.
30        $this->_params['user_tbl'] = isset($params['user_tbl']) ? $params['user_tbl'] : 'user_tbl';
31       
32        // The name of the primary key for the user_tbl.
33        $this->_params['user_id_column'] = isset($params['user_id_column']) ? $params['user_id_column'] : 'user_id';
34       
35        // The name of the username key for the user_tbl.
36        $this->_params['username_column'] = isset($params['username_column']) ? $params['username_column'] : 'username';
37       
38        // If using the login_tbl feature, specify the login_tbl. The primary key must match the primary key for the user_tbl.
39        $this->_params['login_tbl'] = isset($params['login_tbl']) ? $params['login_tbl'] : 'login_tbl';
40       
41        // The type of encryption to use for passwords stored in the user_tbl. Use 'md5' or 'crypt'.
42        $this->_params['encryption_type'] = isset($params['encryption_type']) ? $params['encryption_type'] : 'md5';
43
44        // The URL the user will be directed if unsuccessfully calling requireLogin.
45        $this->_params['login_url'] = isset($params['login_url']) ? $params['login_url'] : '/';
46
47        // The maximum amount of time a user is allowed to be logged in. They will be forced to login again if they expire.
48        // This applies to admins and users. In seconds. 21600 seconds = 6 hours.
49        $this->_params['login_timeout'] = isset($params['login_timeout']) ? $params['login_timeout'] : $CFG->login_timeout;
50       
51        // The maximum amount of time a user is allowed to be idle before their session expires. They will be forced to login again if they expire.
52        // This applies to admins and users. In seconds. 3600 seconds = 1 hour.
53        $this->_params['idle_timeout'] = isset($params['idle_timeout']) ? $params['idle_timeout'] : $CFG->idle_timeout;
54
55        // The period of time to compare login abuse attempts. If a threshold of logins is reached in this amount of time the account is blocked.
56        // Days and hours, like this: 'DD:HH'
57        $this->_params['login_abuse_timeframe'] = isset($params['login_abuse_timeframe']) ? $params['login_abuse_timeframe'] : $CFG->login_abuse_timeframe;
58
59        // When an account is accessed from this many different IPs, the user's password is reset and they are issued a warning.
60        $this->_params['login_abuse_warning_ips'] = isset($params['login_abuse_warning_ips']) ? $params['login_abuse_warning_ips'] : $CFG->login_abuse_warning_ips;
61
62        // The number of warnings a user will receive (and their password reset each time) before their account is completely blocked.
63        $this->_params['login_abuse_warnings'] = isset($params['login_abuse_warnings']) ? $params['login_abuse_warnings'] : $CFG->login_abuse_warnings;
64
65        // The maximum number of IP addresses a user can login with over the timeout period before their account is blocked.
66        $this->_params['login_abuse_max_ips'] = isset($params['login_abuse_max_ips']) ? $params['login_abuse_max_ips'] : $CFG->login_abuse_max_ips;
67
68        // The IP address subnet size threshold. Uses a CIDR notation network mask. Any integar between 0 and 32 is permitted. Setting this
69        // to '24' permits any address in a class C network (255.255.255.0) to be considered the same. Setting to '32' compares each IP absolutely.
70        // Setting to '0' ignores all IPs, thus disabling this feature.
71        $this->_params['login_abuse_ip_bitmask'] = isset($params['login_abuse_ip_bitmask']) ? $params['login_abuse_ip_bitmask'] : $CFG->login_abuse_ip_bitmask;
72
73        // Specify usernames to exclude from the account abuse detection system. This is specified as a hardcoded array provided at
74        // class instantiation time, or can be saved in the user_tbl under the login_abuse_exempt field.
75        $this->_params['login_abuse_exempt_usernames'] = isset($params['login_abuse_exempt_usernames']) && is_array($params['login_abuse_exempt_usernames']) ? $params['login_abuse_exempt_usernames'] : array();
76       
77        $this->_params['trusted_networks'] = isset($params['trusted_networks']) && is_array($params['trusted_networks']) ? $params['trusted_networks'] : $CFG->trusted_networks;
78
79        // Feature: Allow user accounts to be blocked? Requires the user table to have the columns 'blocked' and 'blocked_reason'
80        $this->_params['features']['blocking'] = isset($params['features']['blocking']) ? $params['features']['blocking'] : false;
81       
82        // Feature: Use a login_tbl to detect excessive logins. This requires blocking to be enabled.
83        $this->_params['features']['abuse_detection'] = isset($params['features']['abuse_detection']) ? $params['features']['abuse_detection'] : false;
84       
85        $this->_auth_name = '_auth_' . $this->_params['auth_name'];
86    }
87
88    /**
89     * Clear any authentication tokens in the current session. A.K.A. logout.
90     *
91     * @access public
92     */
93    function clearAuth()
94    {
95        dbQuery("
96            UPDATE " . $this->_params['user_tbl'] . " SET
97            seconds_online = seconds_online + (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(last_access_datetime)),
98            last_login_datetime = '0000-00-00 00:00:00'
99            WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'
100        ");
101        $_SESSION[$this->_auth_name] = array();
102        $_SESSION[$this->_auth_name]['authenticated'] = false;
103    }
104
105    /**
106     * Sets a variable into a registered auth session.
107     *
108     * @access public
109     *
110     * @param mixed $key      Which value to set.
111     * @param mixed $val      Value to set variable to.
112     */
113    function setVal($key, $val)
114    {
115        if (!isset($_SESSION[$this->_auth_name]['user_data'])) {
116            $_SESSION[$this->_auth_name]['user_data'] = array();
117        }
118        $_SESSION[$this->_auth_name]['user_data'][$key] = $val;
119    }
120
121    /**
122     * Returns a specified value from a registered auth session.
123     *
124     * @access public
125     *
126     * @param mixed $key      Which value to return.
127     * @param mixed $default  Value to return if key not found in user_data.
128     *
129     * @return mixed          Value stored in session.
130     */
131    function getVal($key, $default='')
132    {
133        if (isset($_SESSION[$this->_auth_name][$key])) {
134            return $_SESSION[$this->_auth_name][$key];
135        } else if (isset($_SESSION[$this->_auth_name]['user_data'][$key])) {
136            return $_SESSION[$this->_auth_name]['user_data'][$key];
137        } else {
138            return $default;
139        }
140    }
141   
142    /**
143     * Set the features of an auth object.
144     *
145     * @param  array $features   Array of feature keys and value to set.
146     *
147     * @return bool true on success, false on failure
148     */
149    function setFeature($features=null)
150    {
151        if (isset($features) && is_array($features)) {
152            // Set features for this object.
153            $this->_params['features'] = array_merge($this->_params['features'], $features);
154        }
155    }
156
157    /**
158     * Return the value of a feature configuration. This usually returns a bool value.
159     *
160     * @access public
161     *
162     * @param string $feature      Which feature to return.
163     *
164     * @return mixed               Configured feature value.
165     */
166    function getFeature($feature)
167    {
168        return $this->_params['features'][$feature];
169    }
170
171    /**
172     * Find out if a set of login credentials are valid.
173     *
174     * @access private
175     *
176     * @param string $username      The username to check.
177     * @param string $password      The password to compare to username.
178     *
179     * @return mixed  False if credentials not found in DB, or returns DB row matching credentials.
180     */
181    function authenticate($username, $password)
182    {       
183        // Query DB for user matching credentials.
184        $qid = dbQuery("
185            SELECT *, " . $this->_params['user_id_column'] . " AS user_id
186            FROM " . $this->_params['user_tbl'] . "
187            WHERE BINARY username = '" . addslashes($username) . "'
188            AND BINARY userpass = '" . addslashes($this->encryptPassword($password)) . "'
189        ");
190       
191        // Return user data if found.
192        if ($user_data = mysql_fetch_assoc($qid)) {
193            return $user_data;
194        } else {
195            return false;
196        }
197    }
198
199    /**
200     * If user authenticated, register login into session.
201     *
202     * @access private
203     *
204     * @param string $username     The username to check.
205     * @param string $password     The password to compare to username.
206     *
207     * @return boolean  Whether or not the credentials are valid.
208     */
209    function login($username, $password)
210    {
211        $this->clearAuth();
212
213        if (!$user_data = $this->authenticate($username, $password)) {
214            // No login: failed authentication!
215            return false;
216        }
217
218        // Register authenticated session.
219        $_SESSION[$this->_auth_name] = array(
220            'authenticated'         => true,
221            'user_id'               => $user_data['user_id'],
222            'auth_name'             => $this->_params['auth_name'],
223            'username'              => $username,
224            'priv'                  => $user_data['priv'],
225            'login_datetime'        => date('Y-m-d H:i:s'),
226            'last_access_datetime'  => date('Y-m-d H:i:s'),
227            'remote_ip'             => getRemoteAddr(),
228            'abuse_warning_level'   => $user_data['abuse_warning_level'],
229            'login_abuse_exempt'    => isset($user_data['login_abuse_exempt']) ? !empty($user_data['login_abuse_exempt']) : in_array($username, $this->_params['login_abuse_exempt_usernames']),
230            'user_data'             => $user_data
231        );
232       
233        /**
234         * Check if the account is blocked, respond in context to reason. Cancel the login if blocked.
235         */
236        if ($this->getFeature('blocking')) {
237            if (!empty($user_data['blocked'])) {
238               
239                logMsg(sprintf('Login failed, blocked account. User: %s (%s) Reason: %s', $user_data['user_id'], $username, $user_data['blocked_reason']), LOG_NOTICE, __FILE__, __LINE__);
240               
241                switch ($user_data['blocked_reason']) {
242                    case 'account abuse' :
243                        raiseMsg(sprintf(_("This account has been blocked due to possible account abuse. Please contact us to reactivate."), null), MSG_WARNING, __FILE__, __LINE__);
244                        break;
245                    default :
246                        raiseMsg(sprintf(_("This account is currently not active. %s"), $user_data['blocked_reason']), MSG_WARNING, __FILE__, __LINE__);
247                        break;
248                }
249               
250                // No login: user is blocked!
251                $this->clearAuth();
252                return false;
253            }
254        }
255       
256        /**
257         * Check the login_tbl for too many logins under this account.
258         * (1) Count the number of unique IP addresses that logged in under this user within the login_abuse_timeframe
259         * (2) If this number exceeds the login_abuse_max_ips, assume multiple people are logging in under the same account.
260        **/
261        if ($this->getFeature('abuse_detection') && !$this->getVal('login_abuse_exempt')) {
262            $qid = dbQuery("
263                SELECT COUNT(DISTINCT LEFT(remote_ip_binary, " . $this->_params['login_abuse_ip_bitmask'] . "))
264                FROM " . $this->_params['login_tbl'] . "
265                WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'
266                AND DATE_ADD(login_datetime, INTERVAL '" . $this->_params['login_abuse_timeframe'] . "' DAY_HOUR) > NOW()
267            ");
268            list($distinct_ips) = mysql_fetch_row($qid);
269            if ($distinct_ips > $this->_params['login_abuse_max_ips']) {
270                if ($this->getVal('abuse_warning_level') < $this->_params['login_abuse_warnings']) {
271                    // Warn the user with a password reset.
272                    $this->resetPassword(null, _("This is a security precaution. We have detected this account has been accessed from multiple computers simultaneously. It is against policy to share your login information with others. If further account abuse is detected your account will be blocked."));
273                    raiseMsg(_("Your password has been reset as a security precaution. Please check your email for more information."), MSG_NOTICE, __FILE__, __LINE__);
274                    logMsg(sprintf('Account abuse detected for user %s from IP %s', $this->getVal('username'), $this->getVal('remote_ip')), LOG_WARNING, __FILE__, __LINE__);
275                } else {
276                    // Block the account with the reason of account abuse.
277                    $this->blockAccount(null, 'account abuse');
278                    raiseMsg(_("Your account has been blocked as a security precaution. Please contact us for more information."), MSG_NOTICE, __FILE__, __LINE__);
279                    logMsg(sprintf('Account blocked for user %s from IP %s', $this->getVal('username'), $this->getVal('remote_ip')), LOG_ALERT, __FILE__, __LINE__);
280                }
281                // Increment user's warning level.
282                dbQuery("UPDATE " . $this->_params['user_tbl'] . " SET abuse_warning_level = abuse_warning_level + 1 WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'");
283                // Reset the login counter for this user.
284                dbQuery("DELETE FROM " . $this->_params['login_tbl'] . " WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'");
285                // No login: reset password because of account abuse!
286                $this->clearAuth();
287                return false;
288            }
289
290            // Update the login counter table with this login access. Convert IP to binary.
291            dbQuery("
292                INSERT INTO " . $this->_params['login_tbl'] . " (
293                    " . $this->_params['user_id_column'] . ",
294                    login_datetime,
295                    remote_ip_binary
296                ) VALUES (
297                    '" . $this->getVal('user_id') . "',
298                    '" . $this->getVal('login_datetime') . "',
299                    '" . sprintf('%032b', ip2long($this->getVal('remote_ip'))) . "'
300                )
301            ");
302        }
303       
304        // Update user table with this login.
305        dbQuery("
306            UPDATE " . $this->_params['user_tbl'] . " SET
307                last_login_datetime = '" . $this->getVal('login_datetime') . "',
308                last_access_datetime = '" . $this->getVal('login_datetime') . "',
309                last_login_ip = '" . $this->getVal('remote_ip') . "'
310            WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'
311        ");
312       
313        // We're logged-in!
314        return true;
315    }
316
317    /**
318     * Test if user has a currently logged-in session.
319     *  - authentication flag set to true
320     *  - username not empty
321     *  - total logged-in time is not greater than login_timeout
322     *  - idle time is not greater than idle_timeout
323     *  - remote address is the same as the login remote address (aol users excluded).
324     *
325     * @access public
326     */
327    function isLoggedIn($user_id=null)
328    {
329        if (isset($user_id)) {
330            // Check the login status of a specific user.
331            $qid = dbQuery("
332                SELECT 1 FROM " . $this->_params['user_tbl'] . "
333                WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
334                AND DATE_ADD(last_login_datetime, INTERVAL '" . $this->_params['login_timeout'] . "' SECOND) > NOW()
335                AND DATE_ADD(last_access_datetime, INTERVAL '" . $this->_params['idle_timeout'] . "' SECOND) > NOW()
336            ");
337            return (mysql_num_rows($qid) > 0);
338        }
339       
340        // User login test need only be run once per script execution. We cache the result in the session.
341        if ($this->_authentication_tested && isset($_SESSION[$this->_auth_name]['authenticated'])) {
342            return $_SESSION[$this->_auth_name]['authenticated'];
343        }
344       
345        // Tesing login should occur once. This is the first time. Set flag.
346        $this->_authentication_tested = true;
347       
348        // Some users will access from networks with changing IP number (i.e. behind a proxy server). These users must be allowed entry be adding their IP to the list of trusted_networks.
349        if ($trusted_net = ipInRange(getRemoteAddr(), $this->_params['trusted_networks'])) {
350            $user_in_trusted_network = true;
351            logMsg(sprintf('%s%s accessing from trusted network %s', 
352                ucfirst($this->_params['auth_name']), 
353                ($this->getVal('user_id') ? ' ' . $this->getVal('user_id') . ' (' .  $this->getVal('username') . ')' : ''),
354                $trusted_net
355            ), LOG_INFO, __FILE__, __LINE__);
356        } else if (preg_match('/proxy.aol.com$/i', getRemoteAddr(true))) {
357            $user_in_trusted_network = true;
358            logMsg(sprintf('%s%s accessing from trusted network proxy.aol.com', 
359                ucfirst($this->_params['auth_name']), 
360                ($this->getVal('user_id') ? ' ' . $this->getVal('user_id') . ' (' .  $this->getVal('username') . ')' : '')
361            ), LOG_NOTICE, __FILE__, __LINE__);
362        } else {
363            $user_in_trusted_network = false;
364        }
365       
366        // Test login with information stored in session. Skip IP matching for users from trusted networks.
367        if (true === $_SESSION[$this->_auth_name]['authenticated']
368            && !empty($_SESSION[$this->_auth_name]['username'])
369            && strtotime($_SESSION[$this->_auth_name]['login_datetime']) > time() - $this->_params['login_timeout']
370            && strtotime($_SESSION[$this->_auth_name]['last_access_datetime']) > time() - $this->_params['idle_timeout']
371            && ($_SESSION[$this->_auth_name]['remote_ip'] == getRemoteAddr() || $user_in_trusted_network)
372        ) {
373            // User is authenticated!
374            $_SESSION[$this->_auth_name]['last_access_datetime'] = date('Y-m-d H:i:s');
375
376            // Update the DB with the last_access_datetime and increment the seconds_online.
377            dbQuery("
378                UPDATE " . $this->_params['user_tbl'] . " SET
379                seconds_online = seconds_online + (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(last_access_datetime)) + 1,
380                last_access_datetime = '" . $this->getVal('last_access_datetime') . "'
381                WHERE " . $this->_params['user_id_column'] . " = '" . $this->getVal('user_id') . "'
382            ");
383            if (mysql_affected_rows($GLOBALS['dbh']) > 0) {
384                // User record still exists in DB. Do this to ensure user was not delete from DB between accesses. Notice "+ 1" in SQL above to ensure record is modified.
385                return true;
386            } else {
387                logMsg(sprintf('User update failed. Record not found for %s %s (%s).', $this->_params['auth_name'], $this->getVal('user_id'), $this->getVal('username')), LOG_NOTICE, __FILE__, __LINE__);
388            }
389        } else if (true === $_SESSION[$this->_auth_name]['authenticated']) {
390            // User is authenticated, but login has expired.
391            raiseMsg(sprintf(_("Your %s session has closed. You need to log-in again."), strtolower($this->_params['auth_name'])), MSG_NOTICE, __FILE__, __LINE__);
392           
393            // Log the reason for login expiration.
394            $expire_reasons = array();
395            if (empty($_SESSION[$this->_auth_name]['username'])) {
396                $expire_reasons[] = 'username not found';
397            }
398            if (strtotime($_SESSION[$this->_auth_name]['login_datetime']) <= time() - $this->_params['login_timeout']) {
399                $expire_reasons[] = 'login_timeout expired';
400            }
401            if (strtotime($_SESSION[$this->_auth_name]['last_access_datetime']) <= time() - $this->_params['idle_timeout']) {
402                $expire_reasons[] = 'idle_timeout expired';
403            }
404            if ($_SESSION[$this->_auth_name]['remote_ip'] != getRemoteAddr()) {
405                $expire_reasons[] = sprintf('remote_ip not matched (%s != %s)', $_SESSION[$this->_auth_name]['remote_ip'], getRemoteAddr());
406            }
407            logMsg(sprintf('%s %s (%s) session expired: %s', ucfirst($this->_params['auth_name']), $this->getVal('user_id'), $this->getVal('username'), join(', ', $expire_reasons)), LOG_DEBUG, __FILE__, __LINE__);
408        }
409
410        // User is not authenticated.
411        $this->clearAuth();
412        return false;
413    }
414
415    /**
416     * Redirect user to login page if they are not logged in.
417     *
418     * @param string $msg     The text description of a message to raise.
419     * @param int    $type    The type of message: MSG_NOTICE,
420     *                        MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
421     * @param string $file    __FILE__.
422     * @param string $line    __LINE__.
423     *
424     * @access public
425     */
426    function requireLogin($msg='', $type=MSG_NOTICE, $file=null, $line=null)
427    {
428        if (!$this->isLoggedIn()) {
429            if ('' != $msg) {
430                raiseMsg($msg, $type, $file, $line);
431            }
432            setBoomerangURL(absoluteMe());
433            dieURL($this->_params['login_url']);
434        }
435    }
436
437    /**
438     * This sets the 'blocked' field for a user in the user_tbl, and also
439     * adds an optional reason
440     *
441     * @param  string   $reason      The reason for blocking the account.
442     */
443    function blockAccount($user_id=null, $reason='')
444    {
445        if ($this->getFeature('blocking')) {
446            if (strlen(addslashes($reason)) > 255) {
447                // blocked_reason field is varchar(255).
448                logMsg(sprintf('Blocked reason provided is greater than 255 characters: %s', $reason), LOG_WARNING, __FILE__, __LINE__);
449            }
450           
451            // Get user_id if specified.
452            $user_id = isset($user_id) ? $user_id : $this->getVal('user_id');
453            dbQuery("
454                UPDATE " . $this->_params['user_tbl'] . " SET
455                blocked = 'true',
456                blocked_reason = '" . addslashes($reason) . "'
457                WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
458            ");
459        }
460    }
461
462    /**
463     * Unblocks a user in the user_tbl, and clears any blocked_reason.
464     */
465    function unblockAccount($user_id=null)
466    {
467        if ($this->getFeature('blocking')) {
468            // Get user_id if specified.
469            $user_id = isset($user_id) ? $user_id : $this->getVal('user_id');
470            dbQuery("
471                UPDATE " . $this->_params['user_tbl'] . " SET
472                blocked = '',
473                blocked_reason = ''
474                WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
475            ");
476        }
477    }
478
479    /**
480     * Returns true if username already exists in database.
481     *
482     * @param  string  $username    Username to look for.
483     *
484     * @return bool                 True if username exists.
485     */
486    function usernameExists($username)
487    {   
488        $qid = dbQuery("SELECT 1 FROM " . $this->_params['user_tbl'] . " WHERE username = '" . addslashes($username) . "'");
489        return (mysql_num_rows($qid) > 0);
490    }
491
492    /**
493     * Returns a username for a specified user id.
494     *
495     * @param  string  $user_id     User id to look for.
496     *
497     * @return string               Username, or false if none found.
498     */
499    function getUsername($user_id)
500    {   
501        $qid = dbQuery("SELECT " . $this->_params['username_column'] . " FROM " . $this->_params['user_tbl'] . " WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'");
502        if (list($username) = mysql_fetch_row($qid)) {
503            return $username;
504        } else {
505            return false;
506        }
507    }
508
509    /**
510     * Returns a randomly generated password based on $pattern. The pattern is any
511     * sequence of 'x', 'V', 'C', 'v', 'c', or 'd' and if it is something like 'cvccv' this
512     * function will generate a pronouncable password. Recommend using more complex
513     * patterns, at minimum the US State Department standard: cvcddcvc.
514     *
515     * - x    a random upper or lower alpha character or digit
516     * - C    a random upper or lower consanant
517     * - V    a random upper or lower vowel
518     * - c    a random lowercase consanant
519     * - v    a random lowercase vowel
520     * - d    a random digit
521     *
522     * @param  string $pattern  a sequence of character types, above.
523     *
524     * @return string           a password
525     */
526    function generatePassword($pattern='CvccvCdd')
527    {
528        mt_srand((double) microtime() * 10000000);
529        for ($i=0; $i<strlen($pattern); $i++) {
530            $x = substr('bcdfghjklmnprstvwxzBCDFGHJKLMNPRSTVWXZaeiouyAEIOUY0123456789', (mt_rand() % 60), 1);
531            $c = substr('bcdfghjklmnprstvwxz', (mt_rand() % 19), 1);
532            $C = substr('bcdfghjklmnprstvwxzBCDFGHJKLMNPRSTVWXZ', (mt_rand() % 38), 1);
533            $v = substr('aeiouy', (mt_rand() % 6), 1);
534            $V = substr('aeiouyAEIOUY', (mt_rand() % 12), 1);
535            $d = substr('0123456789', (mt_rand() % 10), 1);
536            $str .= $$pattern{$i};
537        }
538        return $str;
539    }
540   
541    /**
542     *
543     */
544    function encryptPassword($password)
545    {
546        switch ($this->_params['encryption_type']) {
547        case 'plain' :
548            return $password;
549            break;
550           
551        case 'crypt' :
552            return crypt($password, crypt($password));
553            break;
554           
555        case 'sha1' :
556            if (function_exists('sha1')) { // Only in PHP 4.3.0+
557                return sha1($password);
558                break;
559            }
560           
561        case 'md5' :
562        default :
563            return md5($password);
564            break;
565        }
566    }
567
568    /**
569     *
570     */
571    function setPassword($user_id=null, $password)
572    {       
573        // Get user_id if specified.
574        $user_id = isset($user_id) ? $user_id : $this->getVal('user_id');
575       
576        // Issue the password change query.
577        dbQuery("
578            UPDATE " . $this->_params['user_tbl'] . "
579            SET userpass = '" . addslashes($this->encryptPassword($password)) . "'
580            WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
581        ");
582    }
583
584    /**
585     * Resets the password for the user with the specified id.
586     *
587     * @param  string $user_id   The id of the user to reset.
588     * @param  string $reason    Additional message to add to the reset email.
589     *
590     * @return string            The user's new password.
591     */
592    function resetPassword($user_id=null, $reason='')
593    {
594        global $CFG;
595       
596        // Get user_id if specified.
597        $user_id = isset($user_id) ? $user_id : $this->getVal('user_id');
598       
599        // Reset password of a specific user.
600        $qid = dbQuery("
601            SELECT * FROM " . $this->_params['user_tbl'] . "
602            WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
603        ");
604        $user_data = mysql_fetch_assoc($qid);
605
606        // Get new password.
607        $password = $this->generatePassword();
608       
609        // Issue the password change query.
610        dbQuery("
611            UPDATE " . $this->_params['user_tbl'] . "
612            SET userpass = '" . addslashes($this->encryptPassword($password)) . "'
613            WHERE " . $this->_params['user_id_column'] . " = '" . addslashes($user_id) . "'
614        ");
615
616        // Email the user with the new account information.
617        // $reason is used in this template.
618        if (include 'email_reset_password.ihtml') {
619            mail($user_data['email'], $email_subject, $email_body, "From: $CFG->site_name <$CFG->site_email>\r\n", $CFG->envelope_sender_address);
620        }
621   
622        return array('username'=>$user_data['username'], 'userpass'=>$password);
623    }
624   
625    /**
626     * If the current user has access to the specified $security_zone, return true.
627     * If the optional $priv is supplied, test that against the zone.
628     *
629     * @param  constant $security_zone   string of comma delimited priviliges for the zone
630     * @param  string   $priv            a privilege that might be found in a zone
631     *
632     * @return bool     true if user is a member of security zone, false otherwise
633     */
634    function inClearanceZone($security_zone, $priv='')
635    {
636        $zone_members = preg_split('/,\s*/', $security_zone);
637        $priv = empty($priv) ? $this->getVal('priv') : $priv;
638       
639        // If the current user's privilege level is NOT in that array or if the
640        // user has no privilege, return false. Otherwise the user is clear.
641        if (!in_array($priv, $zone_members) || empty($priv)) {
642            return false;
643        } else {
644            return true;
645        }
646    }
647   
648    /**
649     * This function tests a list of arguments $security_zone against the priv that the current user has.
650     * If the user doesn't have one of the supplied privs, die.
651     *
652     * @param  constant $security_zone   string of comma delimited priviliges for the zone
653     */
654    function requireAccessClearance($security_zone, $msg='')
655    {
656        $zone_members = preg_split('/,\s*/', $security_zone);
657   
658        /* If the current user's privilege level is NOT in that array or if the
659         * user has no privilege, DIE with a message. */
660        if (!in_array($this->getVal('priv'), $zone_members) || !$this->getVal('priv')) {
661            $msg = empty($msg) ? _("You have insufficient privileges to view that page.") : $msg;
662            raiseMsg($msg, MSG_NOTICE, __FILE__, __LINE__);
663            dieBoomerangURL();
664        }
665    }
666
667} // end class
668
669// CIDR cheatsheet
670//
671// Netmask              Netmask (binary)                 CIDR     Notes   
672// _____________________________________________________________________________
673// 255.255.255.255  11111111.11111111.11111111.11111111  /32  Host (single addr)
674// 255.255.255.254  11111111.11111111.11111111.11111110  /31  Unuseable
675// 255.255.255.252  11111111.11111111.11111111.11111100  /30    2  useable
676// 255.255.255.248  11111111.11111111.11111111.11111000  /29    6  useable
677// 255.255.255.240  11111111.11111111.11111111.11110000  /28   14  useable
678// 255.255.255.224  11111111.11111111.11111111.11100000  /27   30  useable
679// 255.255.255.192  11111111.11111111.11111111.11000000  /26   62  useable
680// 255.255.255.128  11111111.11111111.11111111.10000000  /25  126  useable
681// 255.255.255.0    11111111.11111111.11111111.00000000  /24 "Class C" 254 useable
682//
683// 255.255.254.0    11111111.11111111.11111110.00000000  /23    2  Class C's
684// 255.255.252.0    11111111.11111111.11111100.00000000  /22    4  Class C's
685// 255.255.248.0    11111111.11111111.11111000.00000000  /21    8  Class C's
686// 255.255.240.0    11111111.11111111.11110000.00000000  /20   16  Class C's
687// 255.255.224.0    11111111.11111111.11100000.00000000  /19   32  Class C's
688// 255.255.192.0    11111111.11111111.11000000.00000000  /18   64  Class C's
689// 255.255.128.0    11111111.11111111.10000000.00000000  /17  128  Class C's
690// 255.255.0.0      11111111.11111111.00000000.00000000  /16  "Class B"
691//     
692// 255.254.0.0      11111111.11111110.00000000.00000000  /15    2  Class B's
693// 255.252.0.0      11111111.11111100.00000000.00000000  /14    4  Class B's
694// 255.248.0.0      11111111.11111000.00000000.00000000  /13    8  Class B's
695// 255.240.0.0      11111111.11110000.00000000.00000000  /12   16  Class B's
696// 255.224.0.0      11111111.11100000.00000000.00000000  /11   32  Class B's
697// 255.192.0.0      11111111.11000000.00000000.00000000  /10   64  Class B's
698// 255.128.0.0      11111111.10000000.00000000.00000000  /9   128  Class B's
699// 255.0.0.0        11111111.00000000.00000000.00000000  /8   "Class A"
700//   
701// 254.0.0.0        11111110.00000000.00000000.00000000  /7
702// 252.0.0.0        11111100.00000000.00000000.00000000  /6
703// 248.0.0.0        11111000.00000000.00000000.00000000  /5
704// 240.0.0.0        11110000.00000000.00000000.00000000  /4
705// 224.0.0.0        11100000.00000000.00000000.00000000  /3
706// 192.0.0.0        11000000.00000000.00000000.00000000  /2
707// 128.0.0.0        10000000.00000000.00000000.00000000  /1
708// 0.0.0.0          00000000.00000000.00000000.00000000  /0   IP space
709?>
Note: See TracBrowser for help on using the repository browser.