source: trunk/lib/Auth_File.inc.php @ 1

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

Initial import.

File size: 6.3 KB
Line 
1<?php
2/**
3 * The Auth_File:: class provides a htpasswd file implementation for
4 * authentication.
5 *
6 * @author  Quinn Comendant <quinn@strangecode.com>
7 * @inspiration  Horde's Auth class <www.horde.org>
8 * @version 1.0
9 */
10class Auth_File {
11
12    var $_params = array(
13        'encryption_type' => 'des',
14        'htpasswd_file' => null,
15        'login_timeout' => 21600, // 6 hours.
16        'idle_timeout' => 3600, // 1 hour.
17    );
18    var $auths = array();
19
20    /**
21     * Constructs a new htpasswd authentication object.
22     *
23     * @access public
24     *
25     * @param optional array $params  A hash containing parameters.
26     */
27    function Auth_File($params = array())
28    {
29        $this->_params = array_merge($this->_params, $params);
30
31        if (!empty($this->_params['htpasswd_file'])) {
32            if (false === ($users = @file($this->_params['htpasswd_file']))) {
33                App::logMsg(sprintf(_("Could not read htpasswd file: %s"), $this->_params['htpasswd_file']), LOG_ERR, __FILE__, __LINE__);
34            }
35            if (is_array($users)) {
36                foreach ($users as $line) {
37                    list($user, $pass) = explode(':', $line, 2);
38                    $this->_users[trim($user)] = trim($pass);
39                }
40            }
41        }
42    }
43
44    /**
45     * Find out if a set of login credentials are valid. Only supports
46     * htpasswd files with DES passwords right now.
47     *
48     * @access private
49     *
50     * @param string $user_id      The user_id to check.
51     * @param array $password      The password to compare to user_id.
52     *
53     * @return boolean  Whether or not the credentials are valid.
54     */
55    function authenticate($user_id, $password)
56    {
57        if (empty($password)) {
58            App::logMsg(_("No password provided for htpasswd authentication."), LOG_NOTICE, __FILE__, __LINE__);
59            return false;
60        }
61
62        if (empty($this->_users[$user_id])) {
63            App::logMsg(_("User ID provided does not exist."), LOG_NOTICE, __FILE__, __LINE__);
64            return false;
65        }
66
67        $hash = $this->_encrypt($password, $this->_salt($user_id));
68        if ($hash == $this->_users[$user_id]) {
69            return true;
70        } else {
71            return false;
72        }
73    }
74
75    /**
76     * If user passes authentication create authenticated session.
77     *
78     * @access private
79     *
80     * @param string $user_id     The user_id to check.
81     * @param array $password     The password to compare to user_id.
82     *
83     * @return boolean  Whether or not the credentials are valid.
84     */
85    function login($user_id, $password)
86    {
87        $user_id = trim($user_id);
88       
89        $this->clearAuth();
90
91        if ($this->authenticate($user_id, $password)) {
92            $_SESSION['_auth'] = array(
93                'authenticated' => true,
94                'user_id' => $user_id,
95                'user_type' => 'admin',
96                'priv' => 'editor',
97                'login_datetime' => date('Y-m-d H:i:s'),
98                'last_access_datetime' => date('Y-m-d H:i:s'),
99                'remote_addr' => getRemoteAddr()
100            );
101            return true;
102        }
103        return false;
104    }
105
106    /**
107     * Clear any authentication tokens in the current session. A.K.A. logout.
108     *
109     * @access public
110     */
111    function clearAuth()
112    {
113        $_SESSION['_auth'] = array();
114        $_SESSION['_auth']['authenticated'] = false;
115    }
116
117    /**
118     * Test if user has a currently logged-in session.
119     *  - authentication flag set to true
120     *  - user_id not empty
121     *  - total logged-in time is not greater than login_timeout
122     *  - idle time is not greater than idle_timeout
123     *  - remote address is the same as the login remote address.
124     *
125     * @access public
126     */
127    function isLoggedIn()
128    {
129        if (isset($_SESSION['_auth'])) {
130            if (true === $_SESSION['_auth']['authenticated']
131            && !empty($_SESSION['_auth']['user_id'])
132            && strtotime($_SESSION['_auth']['login_datetime']) > time() - $this->_params['login_timeout']
133            && strtotime($_SESSION['_auth']['last_access_datetime']) > time() - $this->_params['idle_timeout']
134            && $_SESSION['_auth']['remote_addr'] == getRemoteAddr()
135            ) {
136                $_SESSION['_auth']['last_access_datetime'] = date('Y-m-d H:i:s');
137                return true;
138            } else if (true === $_SESSION['_auth']['authenticated']) {
139                App::raiseMsg(_("Your session has closed. You need to log-in again."), MSG_NOTICE, __FILE__, __LINE__);
140                $this->clearAuth();
141            }
142        }
143        return false;
144    }
145
146    /**
147     * Test if user is of user_type 'admin'.
148     *
149     * @access public
150     */
151    function isAdmin()
152    {
153        if ($_SESSION['_auth']['user_type'] == 'admin') {
154            return true;
155        }
156        return false;
157    }
158
159    /**
160     * Redirect user to login page if they are not logged in.
161     *
162     * @access public
163     */
164    function requireAdminLogin()
165    {
166        if (!$this->isLoggedIn() || !$this->isAdmin()) {
167            App::setBoomerangURL(absoluteMe());
168            App::dieURL('/admin/login.php');
169        }
170    }
171
172    /**
173     * Hash a given password according to the configured encryption
174     * type.
175     *
176     * @param string $password  The password to encrypt.
177     * @param string $salt      The salt to use, if needed.
178     *
179     * @return string  The hashed password.
180     */
181    function _encrypt($password, $salt=null)
182    {
183        switch ($this->_params['encryption_type']) {
184        case 'des' :
185            if (isset($salt)) {
186                return crypt($password, $salt);
187            } else {
188                return crypt($password);
189            }
190            break;
191        default : 
192            App::logMsg('Encryption type not found.', LOG_ERR, __FILE__, __LINE__);
193        }
194
195        return false;
196    }
197
198    /**
199     * Get a salt for $user_id, or generate a new one.
200     *
201     * @return string  The salt.
202     */
203    function _salt($user_id)
204    {
205        switch ($this->_params['encryption_type']) {
206        case 'des':
207            if (!empty($this->_users[$user_id])) {
208                return substr($this->_users[$user_id], 0, 2);
209            }
210            break;
211        default : 
212            App::logMsg('Encryption type not found.', LOG_ERR, __FILE__, __LINE__);
213        }
214
215        return '';
216    }
217
218}
219?>
Note: See TracBrowser for help on using the repository browser.