Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
 
4
/**
5
 * File::Passwd::Authbasic
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: This source file is subject to version 3.0 of the PHP license
10
 * that is available through the world-wide-web at the following URI:
11
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
12
 * the PHP License and are unable to obtain it through the web, please
13
 * send a note to license@php.net so we can mail you a copy immediately.
14
 *
15
 * @category   FileFormats
16
 * @package    File_Passwd
17
 * @author     Michael Wallner <mike@php.net>
18
 * @copyright  2003-2005 Michael Wallner
19
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
20
 * @version    CVS: $Id: Authbasic.php,v 1.17 2005/03/30 18:33:33 mike Exp $
21
 * @link       http://pear.php.net/package/File_Passwd
22
 */
23
 
24
/**
25
* Requires File::Passwd::Common
26
*/
27
require_once 'File/Passwd/Common.php';
28
 
29
/**
30
* Manipulate AuthUserFiles as used for HTTP Basic Authentication.
31
*
32
* <kbd><u>
33
*   Usage Example:
34
* </u></kbd>
35
* <code>
36
*   $htp = &File_Passwd::factory('AuthBasic');
37
*   $htp->setMode('sha');
38
*   $htp->setFile('/www/mike/auth/.htpasswd');
39
*   $htp->load();
40
*   $htp->addUser('mike', 'secret');
41
*   $htp->save();
42
* </code>
43
*
44
* <kbd><u>
45
*   Output of listUser()
46
* </u></kbd>
47
* <pre>
48
*      array
49
*       + user => crypted_passwd
50
*       + user => crypted_passwd
51
* </pre>
52
*
53
* @author   Michael Wallner <mike@php.net>
54
* @package  File_Passwd
55
* @version  $Revision: 1.17 $
56
* @access   public
57
*/
58
class File_Passwd_Authbasic extends File_Passwd_Common
59
{
60
    /**
61
    * Path to AuthUserFile
62
    *
63
    * @var string
64
    * @access private
65
    */
66
    var $_file = '.htpasswd';
67
 
68
    /**
69
    * Actual encryption mode
70
    *
71
    * @var string
72
    * @access private
73
    */
74
    var $_mode = 'sha';
75
 
76
    /**
77
    * Supported encryption modes
78
    *
79
    * @var array
80
    * @access private
81
    */
82
    var $_modes = array('md5' => 'm', 'des' => 'd', 'sha' => 's');
83
 
84
    /**
85
    * Constructor
86
    *
87
    * @access public
88
    * @param  string $file   path to AuthUserFile
89
    */
90
    function File_Passwd_Authbasic($file = '.htpasswd')
91
    {
92
        File_Passwd_Authbasic::__construct($file);
93
    }
94
 
95
    /**
96
    * Constructor (ZE2)
97
    *
98
    * Rewritten because DES encryption is not
99
    * supportet by the Win32 httpd.
100
    *
101
    * @access protected
102
    * @param  string $file   path to AuthUserFile
103
    */
104
    function __construct($file = '.htpasswd')
105
    {
106
        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
107
            unset($this->_modes['des']);
108
        }
109
        $this->setFile($file);
110
    }
111
 
112
    /**
113
    * Fast authentication of a certain user
114
    *
115
    * Returns a PEAR_Error if:
116
    *   o file doesn't exist
117
    *   o file couldn't be opened in read mode
118
    *   o file couldn't be locked exclusively
119
    *   o file couldn't be unlocked (only if auth fails)
120
    *   o file couldn't be closed (only if auth fails)
121
    *
122
    * @static   call this method statically for a reasonable fast authentication
123
    *
124
    * @throws   PEAR_Error
125
    * @access   public
126
    * @return   mixed   true if authenticated, false if not or PEAR_Error
127
    * @param    string  $file   path to passwd file
128
    * @param    string  $user   user to authenticate
129
    * @param    string  $pass   plaintext password
130
    * @param    string  $mode   des, sha or md5
131
    */
132
    function staticAuth($file, $user, $pass, $mode)
133
    {
134
        $line = File_Passwd_Common::_auth($file, $user);
135
        if (!$line || PEAR::isError($line)) {
136
            return $line;
137
        }
138
        list(,$real)    = explode(':', $line);
139
        $crypted        = File_Passwd_Authbasic::_genPass($pass, $real, $mode);
140
        if (PEAR::isError($crypted)) {
141
            return $crypted;
142
        }
143
        return ($real === $crypted);
144
    }
145
 
146
    /**
147
    * Apply changes and rewrite AuthUserFile
148
    *
149
    * Returns a PEAR_Error if:
150
    *   o directory in which the file should reside couldn't be created
151
    *   o file couldn't be opened in write mode
152
    *   o file couldn't be locked exclusively
153
    *   o file couldn't be unlocked
154
    *   o file couldn't be closed
155
    *
156
    * @throws PEAR_Error
157
    * @access public
158
    * @return mixed true on success or PEAR_Error
159
    */
160
    function save()
161
    {
162
        $content = '';
163
        foreach ($this->_users as $user => $pass) {
164
            $content .= $user . ':' . $pass . "\n";
165
        }
166
        return $this->_save($content);
167
    }
168
 
169
    /**
170
    * Add an user
171
    *
172
    * The username must start with an alphabetical character and must NOT
173
    * contain any other characters than alphanumerics, the underline and dash.
174
    *
175
    * Returns a PEAR_Error if:
176
    *   o user already exists
177
    *   o user contains illegal characters
178
    *
179
    * @throws PEAR_Error
180
    * @access public
181
    * @return mixed true on success or PEAR_Error
182
    * @param string $user
183
    * @param string $pass
184
    */
185
    function addUser($user, $pass)
186
    {
187
        if ($this->userExists($user)) {
188
            return PEAR::raiseError(
189
                sprintf(FILE_PASSWD_E_EXISTS_ALREADY_STR, 'User ', $user),
190
                FILE_PASSWD_E_EXISTS_ALREADY
191
            );
192
        }
193
        if (!preg_match($this->_pcre, $user)) {
194
            return PEAR::raiseError(
195
                sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'User ', $user),
196
                FILE_PASSWD_E_INVALID_CHARS
197
            );
198
        }
199
        $this->_users[$user] = $this->_genPass($pass);
200
        return true;
201
    }
202
 
203
    /**
204
    * Change the password of a certain user
205
    *
206
    * Returns a PEAR_Error if user doesn't exist.
207
    *
208
    * @throws PEAR_Error
209
    * @access public
210
    * @return mixed true on success or a PEAR_Error
211
    * @param string $user   the user whose password should be changed
212
    * @param string $pass   the new plaintext password
213
    */
214
    function changePasswd($user, $pass)
215
    {
216
        if (!$this->userExists($user)) {
217
            return PEAR::raiseError(
218
                sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
219
                FILE_PASSWD_E_EXISTS_NOT
220
            );
221
        }
222
        $this->_users[$user] = $this->_genPass($pass);
223
        return true;
224
    }
225
 
226
    /**
227
    * Verify password
228
    *
229
    * Returns a PEAR_Error if:
230
    *   o user doesn't exist
231
    *   o an invalid encryption mode was supplied
232
    *
233
    * @throws PEAR_Error
234
    * @access public
235
    * @return mixed true if passwords equal, false if they don't, or PEAR_Error
236
    * @param string $user   the user whose password should be verified
237
    * @param string $pass   the plaintext password to verify
238
    */
239
    function verifyPasswd($user, $pass)
240
    {
241
        if (!$this->userExists($user)) {
242
            return PEAR::raiseError(
243
                sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
244
                FILE_PASSWD_E_EXISTS_NOT
245
            );
246
        }
247
        $real = $this->_users[$user];
248
        return ($real === $this->_genPass($pass, $real));
249
    }
250
 
251
    /**
252
    * Get actual encryption mode
253
    *
254
    * @access public
255
    * @return string
256
    */
257
    function getMode()
258
    {
259
        return $this->_mode;
260
    }
261
 
262
    /**
263
    * Get supported encryption modes
264
    *
265
    * <pre>
266
    *   array
267
    *    + md5
268
    *    + sha
269
    *    + des
270
    * </pre>
271
    *
272
    * ATTN: DES encryption not available on Win32!
273
    *
274
    * @access public
275
    * @return array
276
    */
277
    function listModes()
278
    {
279
        return array_keys($this->_modes);
280
    }
281
 
282
    /**
283
    * Set the encryption mode
284
    *
285
    * You can choose one of md5, sha or des.
286
    *
287
    * ATTN: DES encryption not available on Win32!
288
    *
289
    * Returns a PEAR_Error if a specific encryption mode is not supported.
290
    *
291
    * @throws PEAR_Error
292
    * @access public
293
    * @return mixed true on succes or PEAR_Error
294
    * @param string $mode
295
    */
296
    function setMode($mode)
297
    {
298
        $mode = strToLower($mode);
299
        if (!isset($this->_modes[$mode])) {
300
            return PEAR::raiseError(
301
                sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $this->_mode),
302
                FILE_PASSWD_E_INVALID_ENC_MODE
303
            );
304
        }
305
        $this->_mode = $mode;
306
        return true;
307
    }
308
 
309
    /**
310
    * Generate password with htpasswd executable
311
    *
312
    * @access   private
313
    * @return   string  the crypted password
314
    * @param    string  $pass   the plaintext password
315
    * @param    string  $salt   the salt to use
316
    * @param    string  $mode   encyption mode, usually determined from
317
    *                           <var>$this->_mode</var>
318
    */
319
    function _genPass($pass, $salt = null, $mode = null)
320
    {
321
        $mode = is_null($mode) ? strToLower($this->_mode) : strToLower($mode);
322
 
323
        if ($mode == 'md5') {
324
            return File_Passwd::crypt_apr_md5($pass, $salt);
325
        } elseif ($mode == 'des') {
326
            return File_Passwd::crypt_des($pass, $salt);
327
        } elseif ($mode == 'sha') {
328
            return File_Passwd::crypt_sha($pass, $salt);
329
        }
330
 
331
        return PEAR::raiseError(
332
            sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
333
            FILE_PASSWD_E_INVALID_ENC_MODE
334
        );
335
    }
336
 
337
    /**
338
    * Parse the AuthUserFile
339
    *
340
    * Returns a PEAR_Error if AuthUserFile has invalid format.
341
    *
342
    * @throws PEAR_Error
343
    * @access public
344
    * @return mixed true on success or PEAR_error
345
    */
346
    function parse()
347
    {
348
        $this->_users = array();
349
        foreach ($this->_contents as $line) {
350
            $user = explode(':', $line);
351
            if (count($user) != 2) {
352
                return PEAR::raiseError(
353
                    FILE_PASSWD_E_INVALID_FORMAT_STR,
354
                    FILE_PASSWD_E_INVALID_FORMAT
355
                );
356
            }
357
            $this->_users[$user[0]] = trim($user[1]);
358
        }
359
        $this->_contents = array();
360
        return true;
361
    }
362
 
363
    /**
364
    * Generate Password
365
    *
366
    * Returns PEAR_Error FILE_PASSD_E_INVALID_ENC_MODE if the supplied
367
    * encryption mode is not supported.
368
    *
369
    * @static
370
    * @access   public
371
    * @return   mixed   The crypted password on success or PEAR_Error on failure.
372
    * @param    string  $pass The plaintext password.
373
    * @param    string  $mode The encryption mode to use (des|md5|sha).
374
    * @param    string  $salt The salt to use.
375
    */
376
    function generatePasswd($pass, $mode = FILE_PASSWD_DES, $salt = null)
377
    {
378
        if (!in_array(strToLower($mode), array('des', 'md5', 'sha'))) {
379
            return PEAR::raiseError(
380
                sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
381
                FILE_PASSWD_E_INVALID_ENC_MODE
382
            );
383
        }
384
        return File_Passwd_Authbasic::_genPass($pass, $salt, $mode);
385
    }
386
 
387
    /**
388
     * @ignore
389
     * @deprecated
390
     */
391
    function generatePassword($pass, $mode = FILE_PASSWD_DES, $salt = null)
392
    {
393
        return File_Passwd_Authbasic::generatePasswd($pass, $mode, $salt);
394
    }
395
}
396
?>