Claroline PHP Cross Reference Learning Management Systems

Source: /claroline/inc/lib/thirdparty/pear/File/Passwd.php - 420 lines - 13881 bytes - Summary - Text - Print

Description: Manipulate many kinds of passwd files.

   1  <?php
   2  // +----------------------------------------------------------------------+
   3  // | PEAR :: File :: Passwd                                               |
   4  // +----------------------------------------------------------------------+
   5  // | This source file is subject to version 3.0 of the PHP license,       |
   6  // | that is available at http://www.php.net/license/3_0.txt              |
   7  // | If you did not receive a copy of the PHP license and are unable      |
   8  // | to obtain it through the world-wide-web, please send a note to       |
   9  // | license@php.net so we can mail you a copy immediately.               |
  10  // +----------------------------------------------------------------------+
  11  // | Copyright (c) 2003-2004 Michael Wallner <mike@iworks.at>             |
  12  // +----------------------------------------------------------------------+
  13  //
  14  // $Id: Passwd.php 11091 2008-09-01 14:25:20Z zefredz $
  15  
  16  /**
  17  * Manipulate many kinds of passwd files.
  18  * 
  19  * @author       Michael Wallner <mike@php.net>
  20  * @package      File_Passwd
  21  * @category     FileSystem
  22  */
  23  
  24  /**
  25  * Requires PEAR.
  26  */
  27  require_once  'PEAR.php';
  28  
  29  /**
  30  * Encryption constants.
  31  */
  32  // SHA encryption.
  33  define('FILE_PASSWD_SHA',   'sha');
  34  // MD5 encryption
  35  define('FILE_PASSWD_MD5',   'md5');
  36  // DES encryption
  37  define('FILE_PASSWD_DES',   'des');
  38  // NT hash encryption.
  39  define('FILE_PASSWD_NT',    'nt');
  40  // LM hash encryption.
  41  define('FILE_PASSWD_LM',    'lm');
  42  // PLAIN (no encryption)
  43  define('FILE_PASSWD_PLAIN', 'plain');
  44  
  45  /**
  46  * Error constants.
  47  */
  48  // Undefined error.
  49  define('FILE_PASSWD_E_UNDEFINED',                   0);
  50  // Invalid file format.
  51  define('FILE_PASSWD_E_INVALID_FORMAT',              1);
  52  define('FILE_PASSWD_E_INVALID_FORMAT_STR',          'Passwd file has invalid format.');
  53  // Invalid extra property.
  54  define('FILE_PASSWD_E_INVALID_PROPERTY',            2);
  55  define('FILE_PASSWD_E_INVALID_PROPERTY_STR',        'Invalid property \'%s\'.');
  56  // Invalid characters.
  57  define('FILE_PASSWD_E_INVALID_CHARS',               3);
  58  define('FILE_PASSWD_E_INVALID_CHARS_STR',           '%s\'%s\' contains illegal characters.');
  59  // Invalid encryption mode.
  60  define('FILE_PASSWD_E_INVALID_ENC_MODE',            4);
  61  define('FILE_PASSWD_E_INVALID_ENC_MODE_STR',        'Encryption mode \'%s\' not supported.');
  62  // Exists already.
  63  define('FILE_PASSWD_E_EXISTS_ALREADY',              5);
  64  define('FILE_PASSWD_E_EXISTS_ALREADY_STR',          '%s\'%s\' already exists.');
  65  // Exists not.
  66  define('FILE_PASSWD_E_EXISTS_NOT',                  6);
  67  define('FILE_PASSWD_E_EXISTS_NOT_STR',              '%s\'%s\' doesn\'t exist.');
  68  // User not in group.
  69  define('FILE_PASSWD_E_USER_NOT_IN_GROUP',           7);
  70  define('FILE_PASSWD_E_USER_NOT_IN_GROUP_STR',       'User \'%s\' doesn\'t exist in group \'%s\'.');
  71  // User not in realm.
  72  define('FILE_PASSWD_E_USER_NOT_IN_REALM',           8);
  73  define('FILE_PASSWD_E_USER_NOT_IN_REALM_STR',       'User \'%s\' doesn\'t exist in realm \'%s\'.');
  74  // Parameter must be of type array.
  75  define('FILE_PASSWD_E_PARAM_MUST_BE_ARRAY',         9);
  76  define('FILE_PASSWD_E_PARAM_MUST_BE_ARRAY_STR',     'Parameter %s must be of type array.');
  77  // Method not implemented.
  78  define('FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED',      10);
  79  define('FILE_PASSWD_E_METHOD_NOT_IMPLEMENTED_STR',  'Method \'%s()\' not implemented.');
  80  // Directory couldn't be created.
  81  define('FILE_PASSWD_E_DIR_NOT_CREATED',             11);
  82  define('FILE_PASSWD_E_DIR_NOT_CREATED_STR',         'Couldn\'t create directory \'%s\'.');
  83  // File couldn't be opened.
  84  define('FILE_PASSWD_E_FILE_NOT_OPENED',             12);
  85  define('FILE_PASSWD_E_FILE_NOT_OPENED_STR',         'Couldn\'t open file \'%s\'.');
  86  // File coudn't be locked.
  87  define('FILE_PASSWD_E_FILE_NOT_LOCKED',             13);
  88  define('FILE_PASSWD_E_FILE_NOT_LOCKED_STR',         'Couldn\'t lock file \'%s\'.');
  89  // File couldn't be unlocked.
  90  define('FILE_PASSWD_E_FILE_NOT_UNLOCKED',           14);
  91  define('FILE_PASSWD_E_FILE_NOT_UNLOCKED_STR',       'Couldn\'t unlock file.');
  92  // File couldn't be closed.
  93  define('FILE_PASSWD_E_FILE_NOT_CLOSED',             15);
  94  define('FILE_PASSWD_E_FILE_NOT_CLOSED_STR',         'Couldn\'t close file.');
  95  
  96  /**
  97  * Allowed 64 chars for salts
  98  */
  99  $GLOBALS['_FILE_PASSWD_64'] =
 100      './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
 101  
 102  /**
 103  * The package File_Passwd provides classes and methods 
 104  * to handle many different kinds of passwd files.
 105  * 
 106  * The File_Passwd class in certain is a factory container for its special 
 107  * purpose extension classes, each handling a specific passwd file format.
 108  * It also provides a static method for reasonable fast user authentication.
 109  * Beside that it offers some encryption methods used by the extensions.
 110  *
 111  * @author       Michael Wallner <mike@php.net>
 112  * @version     $Revision: 11091 $
 113  * 
 114  * Usage Example:
 115  * <code>
 116  *  $passwd = &File_Passwd::factory('Unix');
 117  * </code>
 118  */
 119  class File_Passwd
 120  {
 121      /**
 122      * Get API version
 123      *
 124      * @static
 125      * @access   public
 126      * @return   string          API version
 127      */
 128      function apiVersion()
 129      {
 130          return '1.0.0';
 131      }
 132  
 133      /**
 134      * Generate salt
 135      *
 136      * @access   public
 137      * @return   mixed
 138      * @param    int     $length     salt length
 139      * @return   string  the salt
 140      */
 141      function salt($length = 2)
 142      {
 143          $salt = '';
 144          $length = (int) $length;
 145          $length < 2 && $length = 2;
 146          for($i = 0; $i < $length; $i++) {
 147              $salt .= $GLOBALS['_FILE_PASSWD_64'][rand(0, 63)];
 148          }
 149          return $salt;
 150      }
 151  
 152      /**
 153      * No encryption (plaintext)
 154      *
 155      * @access   public
 156      * @return   string  plaintext input
 157      * @param    string  plaintext passwd
 158      */
 159      function crypt_plain($plain)
 160      {
 161          return $plain;
 162      }
 163      
 164      /**
 165      * DES encryption
 166      *
 167      * @static
 168      * @access   public
 169      * @return   string  crypted text
 170      * @param    string  $plain  plaintext to encrypt
 171      * @param    string  $salt   the salt to use for encryption (2 chars)
 172      */
 173      function crypt_des($plain, $salt = null)
 174      {
 175          (is_null($salt) || strlen($salt) < 2) && $salt = File_Passwd::salt(2);
 176          return crypt($plain, $salt);
 177      }
 178      
 179      /**
 180      * MD5 encryption
 181      *
 182      * @static
 183      * @access   public
 184      * @return   string  crypted text
 185      * @param    string  $plain  plaintext to encrypt
 186      * @param    string  $salt   the salt to use for encryption 
 187      *                           (>2 chars starting with $1$)
 188      */
 189      function crypt_md5($plain, $salt = null)
 190      {
 191          if (
 192              is_null($salt) || 
 193              strlen($salt) < 3 || 
 194              !preg_match('/^\$1\$/', $salt))
 195          {
 196              $salt = '$1$' . File_Passwd::salt(8);
 197          }
 198          return crypt($plain, $salt);
 199      }
 200      
 201      /**
 202      * SHA1 encryption
 203      *
 204      * Returns a PEAR_Error if sha1() is not available (PHP<4.3).
 205      * 
 206      * @static
 207      * @throws   PEAR_Error
 208      * @access   public
 209      * @return   mixed   crypted string or PEAR_Error
 210      * @param    string  $plain  plaintext to encrypt
 211      */
 212      function crypt_sha($plain)
 213      {
 214          if (!function_exists('sha1')) {
 215              return PEAR::raiseError(
 216                  'SHA1 encryption is not available (PHP < 4.3).',
 217                  FILE_PASSWD_E_INVALID_ENC_MODE
 218              );
 219          }
 220          $hash = PEAR_ZE2 ? sha1($plain, true) : pack('H40', sha1($plain));
 221          return '{SHA}' . base64_encode($hash);
 222  
 223      }
 224          
 225      /**
 226      * APR compatible MD5 encryption
 227      *
 228      * @access   public
 229      * @return   mixed
 230      * @param    string  $plain  plaintext to crypt
 231      * @param    string  $salt   the salt to use for encryption
 232      */
 233      function crypt_apr_md5($plain, $salt = null)
 234      {
 235          if (is_null($salt)) {
 236              $salt = File_Passwd::salt(8);
 237          } elseif (preg_match('/^\$apr1\$/', $salt)) {
 238              $salt = preg_replace('/^\$apr1\$([^$]+)\$.*/', '\\1', $salt);
 239          } else {
 240              $salt = substr($salt, 0,8);
 241          }
 242          
 243          $length     = strlen($plain);
 244          $context    = $plain . '$apr1$' . $salt;
 245          
 246          if (PEAR_ZE2) {
 247              $binary = md5($plain . $salt . $plain, true);
 248          } else {
 249              $binary = pack('H32', md5($plain . $salt . $plain));
 250          }
 251          
 252          for ($i = $length; $i > 0; $i -= 16) {
 253              $context .= substr($binary, 0, min(16 , $i));
 254          }
 255          for ( $i = $length; $i > 0; $i >>= 1) {
 256              $context .= ($i & 1) ? chr(0) : $plain[0];
 257          }
 258          
 259          if (PEAR_ZE2) {
 260              $binary = md5($plain . $salt . $plain, true);
 261          } else {
 262              $binary = pack('H32', md5($plain . $salt . $plain));
 263          }
 264          
 265          for($i = 0; $i < 1000; $i++) {
 266              $new = ($i & 1) ? $plain : $binary;
 267              if ($i % 3) {
 268                  $new .= $salt;
 269              }
 270              if ($i % 7) {
 271                  $new .= $plain;
 272              }
 273              $new .= ($i & 1) ? $binary : $plain;
 274              $binary = PEAR_ZE2 ? md5($new, true) : pack('H32', md5($new));
 275          }
 276          
 277          $p = array();
 278          for ($i = 0; $i < 5; $i++) {
 279              $k = $i + 6;
 280              $j = $i + 12;
 281              if ($j == 16) {
 282                  $j = 5;
 283              }
 284              $p[] = File_Passwd::_64(
 285                  (ord($binary[$i]) << 16) |
 286                  (ord($binary[$k]) << 8) |
 287                  (ord($binary[$j])),
 288                  5
 289              );
 290          }
 291          
 292          return 
 293              '$apr1$' . $salt . '$' . implode($p) . 
 294              File_Passwd::_64(ord($binary[11]), 3);
 295      }
 296  
 297      /**
 298      * Convert hexadecimal string to binary data
 299      *
 300      * @static
 301      * @access   private
 302      * @return   mixed
 303      * @param    string  $hex
 304      */
 305      function _hexbin($hex)
 306      {
 307          $rs = '';
 308          $ln = strlen($hex);
 309          for($i = 0; $i < $ln; $i += 2) {
 310              $rs .= chr(hexdec($hex{$i} . $hex{$i+1}));
 311          }
 312          return $rs;
 313      }
 314      
 315      /**
 316      * Convert to allowed 64 characters for encryption
 317      *
 318      * @static
 319      * @access   private
 320      * @return   string
 321      * @param    string  $value
 322      * @param    int     $count
 323      */
 324      function _64($value, $count)
 325      {
 326          $result = '';
 327          while(--$count) {
 328              $result .= $GLOBALS['_FILE_PASSWD_64'][$value & 0x3f];
 329              $value >>= 6;
 330          }
 331          return $result;
 332      }
 333  
 334      /**
 335      * Factory for new extensions
 336      * 
 337      * o Unix        for standard Unix passwd files
 338      * o CVS         for CVS pserver passwd files
 339      * o SMB         for SMB server passwd files
 340      * o Authbasic   for AuthUserFiles
 341      * o Authdigest  for AuthDigestFiles
 342      * o Custom      for custom formatted passwd files
 343      * 
 344      * Returns a PEAR_Error if the desired class/file couldn't be loaded.
 345      * 
 346      * @static   use &File_Passwd::factory() for instantiating your passwd object
 347      * 
 348      * @throws   PEAR_Error
 349      * @access   public
 350      * @return   object    File_Passwd_$class - desired Passwd object
 351      * @param    string    $class the desired subclass of File_Passwd
 352      */
 353      function &factory($class)
 354      {
 355          $class = ucFirst(strToLower($class));
 356          if (!@include_once "File/Passwd/$class.php") {
 357              return PEAR::raiseError("Couldn't load file Passwd/$class.php", 0);
 358          }
 359          $class = 'File_Passwd_'.$class;
 360          if (!class_exists($class)) {
 361              return PEAR::raiseError("Couldn't load class $class.", 0);
 362          }
 363          $instance = &new $class();
 364          return $instance;
 365      }
 366      
 367      /**
 368      * Fast authentication of a certain user
 369      * 
 370      * Though this approach should be reasonable fast, it is NOT
 371      * with APR compatible MD5 encryption used for htpasswd style
 372      * password files encrypted in MD5. Generating one MD5 password
 373      * takes about 0.3 seconds!
 374      * 
 375      * Returns a PEAR_Error if:
 376      *   o file doesn't exist
 377      *   o file couldn't be opened in read mode
 378      *   o file couldn't be locked exclusively
 379      *   o file couldn't be unlocked (only if auth fails)
 380      *   o file couldn't be closed (only if auth fails)
 381      *   o invalid <var>$type</var> was provided
 382      *   o invalid <var>$opt</var> was provided
 383      * 
 384      * Depending on <var>$type</var>, <var>$opt</var> should be:
 385      *   o Smb:          encryption method (NT or LM)
 386      *   o Unix:         encryption method (des or md5)
 387      *   o Authbasic:    encryption method (des, sha or md5)
 388      *   o Authdigest:   the realm the user is in
 389      *   o Cvs:          n/a (empty)
 390      *   o Custom:       array of 2 elements: encryption function and delimiter
 391      * 
 392      * @static   call this method statically for a reasonable fast authentication
 393      * 
 394      * @throws   PEAR_Error
 395      * @access   public
 396      * @return   return      mixed   true if authenticated, 
 397      *                               false if not or PEAR_error
 398      * 
 399      * @param    string      $type   Unix, Cvs, Smb, Authbasic or Authdigest
 400      * @param    string      $file   path to passwd file
 401      * @param    string      $user   the user to authenticate
 402      * @param    string      $pass   the plaintext password
 403      * @param    mixed       $opt    o Smb:          NT or LM
 404      *                               o Unix:         des or md5
 405      *                               o Authbasic     des, sha or md5
 406      *                               o Authdigest    realm the user is in
 407      *                               o Custom        encryption function and
 408      *                                               delimiter character
 409      */
 410      function staticAuth($type, $file, $user, $pass, $opt = '')
 411      {
 412          $type = ucFirst(strToLower($type));
 413          if (!@include_once "File/Passwd/$type.php") {
 414              return PEAR::raiseError("Couldn't load file Passwd/$type.php", 0);
 415          }
 416          $func = array('File_Passwd_' . $type, 'staticAuth');
 417          return call_user_func($func, $file, $user, $pass, $opt);
 418      }
 419  }
 420  ?>

title

Description

title

Description

title

Description

title

title

Body