[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/pear/Crypt/ -> CHAP.php (source)

   1  <?php
   2  /*
   3  Copyright (c) 2002-2010, Michael Bretterklieber <michael@bretterklieber.com>
   4  All rights reserved.
   5  
   6  Redistribution and use in source and binary forms, with or without
   7  modification, are permitted provided that the following conditions
   8  are met:
   9  
  10  1. Redistributions of source code must retain the above copyright
  11     notice, this list of conditions and the following disclaimer.
  12  2. Redistributions in binary form must reproduce the above copyright
  13     notice, this list of conditions and the following disclaimer in the
  14     documentation and/or other materials provided with the distribution.
  15  3. The names of the authors may not be used to endorse or promote products
  16     derived from this software without specific prior written permission.
  17  
  18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  22  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  25  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  26  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  27  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28  
  29  This code cannot simply be copied and put under the GNU Public License or
  30  any other GPL-like (LGPL, GPL2) License.
  31  
  32      $Id$
  33  */
  34  
  35  require_once 'PEAR.php';
  36  
  37  /**
  38  * Classes for generating packets for various CHAP Protocols:
  39  * CHAP-MD5: RFC1994
  40  * MS-CHAPv1: RFC2433
  41  * MS-CHAPv2: RFC2759
  42  *
  43  * @package Crypt_CHAP
  44  * @author  Michael Bretterklieber <michael@bretterklieber.com>
  45  * @access  public
  46  * @version $Revision$
  47  */
  48  
  49  /**
  50   * class Crypt_CHAP
  51   *
  52   * Abstract base class for CHAP
  53   *
  54   * @package Crypt_CHAP
  55   */
  56  class Crypt_CHAP extends PEAR
  57  {
  58      /**
  59       * Random binary challenge
  60       * @var  string
  61       */
  62      var $challenge = null;
  63  
  64      /**
  65       * Binary response
  66       * @var  string
  67       */
  68      var $response = null;
  69  
  70      /**
  71       * User password
  72       * @var  string
  73       */
  74      var $password = null;
  75  
  76      /**
  77       * Id of the authentication request. Should incremented after every request.
  78       * @var  integer
  79       */
  80      var $chapid = 1;
  81  
  82      /**
  83       * Constructor
  84       *
  85       * Generates a random challenge
  86       * @return void
  87       */
  88      public function __construct()
  89      {
  90          parent::__construct();
  91          $this->generateChallenge();
  92      }
  93  
  94      function Crypt_CHAP()
  95      {
  96          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
  97          self::__construct();
  98      }
  99  
 100      /**
 101       * Generates a random binary challenge
 102       *
 103       * @param  string  $varname  Name of the property
 104       * @param  integer $size     Size of the challenge in Bytes
 105       * @return void
 106       */
 107      function generateChallenge($varname = 'challenge', $size = 8)
 108      {
 109          $this->$varname = '';
 110          for ($i = 0; $i < $size; $i++) {
 111              $this->$varname .= pack('C', 1 + mt_rand() % 255);
 112          }
 113          return $this->$varname;
 114      }
 115  
 116      /**
 117       * Generates the response. Overwrite this.
 118       *
 119       * @return void
 120       */
 121      function challengeResponse()
 122      {
 123      }
 124  
 125  }
 126  
 127  /**
 128   * class Crypt_CHAP_MD5
 129   *
 130   * Generate CHAP-MD5 Packets
 131   *
 132   * @package Crypt_CHAP
 133   */
 134  class Crypt_CHAP_MD5 extends Crypt_CHAP
 135  {
 136  
 137      /**
 138       * Generates the response.
 139       *
 140       * CHAP-MD5 uses MD5-Hash for generating the response. The Hash consists
 141       * of the chapid, the plaintext password and the challenge.
 142       *
 143       * @return string
 144       */
 145      function challengeResponse()
 146      {
 147          return pack('H*', md5(pack('C', $this->chapid) . $this->password . $this->challenge));
 148      }
 149  }
 150  
 151  /**
 152   * class Crypt_CHAP_MSv1
 153   *
 154   * Generate MS-CHAPv1 Packets. MS-CHAP doesen't use the plaintext password, it uses the
 155   * NT-HASH wich is stored in the SAM-Database or in the smbpasswd, if you are using samba.
 156   * The NT-HASH is MD4(str2unicode(plaintextpass)).
 157   * You need the hash extension for this class.
 158   *
 159   * @package Crypt_CHAP
 160   */
 161  class Crypt_CHAP_MSv1 extends Crypt_CHAP
 162  {
 163      /**
 164       * Wether using deprecated LM-Responses or not.
 165       * 0 = use LM-Response, 1 = use NT-Response
 166       * @var  bool
 167       */
 168      var $flags = 1;
 169  
 170      /**
 171       * Constructor
 172       *
 173       * Loads the hash extension
 174       * @return void
 175       */
 176      public function __construct()
 177      {
 178          parent::__construct();
 179          $this->loadExtension('hash');
 180      }
 181  
 182      function Crypt_CHAP_MSv1()
 183      {
 184          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 185          self::__construct();
 186      }
 187  
 188      /**
 189       * Generates the NT-HASH from the given plaintext password.
 190       *
 191       * @access public
 192       * @return string
 193       */
 194      function ntPasswordHash($password = null)
 195      {
 196          if (isset($password)) {
 197              return pack('H*',hash('md4', $this->str2unicode($password)));
 198          } else {
 199              return pack('H*',hash('md4', $this->str2unicode($this->password)));
 200          }
 201      }
 202  
 203      /**
 204       * Converts ascii to unicode.
 205       *
 206       * @access public
 207       * @return string
 208       */
 209      function str2unicode($str)
 210      {
 211          $uni = '';
 212          $str = (string) $str;
 213          for ($i = 0; $i < strlen($str); $i++) {
 214              $a = ord($str{$i}) << 8;
 215              $uni .= sprintf("%X", $a);
 216          }
 217          return pack('H*', $uni);
 218      }
 219  
 220      /**
 221       * Generates the NT-Response.
 222       *
 223       * @access public
 224       * @return string
 225       */
 226      function challengeResponse()
 227      {
 228          return $this->_challengeResponse();
 229      }
 230  
 231      /**
 232       * Generates the NT-Response.
 233       *
 234       * @access public
 235       * @return string
 236       */
 237      function ntChallengeResponse()
 238      {
 239          return $this->_challengeResponse(false);
 240      }
 241  
 242      /**
 243       * Generates the LAN-Manager-Response.
 244       *
 245       * @access public
 246       * @return string
 247       */
 248      function lmChallengeResponse()
 249      {
 250          return $this->_challengeResponse(true);
 251      }
 252  
 253      /**
 254       * Generates the response.
 255       *
 256       * Generates the response using DES.
 257       *
 258       * @param  bool  $lm  wether generating LAN-Manager-Response
 259       * @access private
 260       * @return string
 261       */
 262      function _challengeResponse($lm = false)
 263      {
 264          if ($lm) {
 265              $hash = $this->lmPasswordHash();
 266          } else {
 267              $hash = $this->ntPasswordHash();
 268          }
 269  
 270          while (strlen($hash) < 21) {
 271              $hash .= "\0";
 272          }
 273  
 274          $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
 275          $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
 276          $key = $this->_desAddParity(substr($hash, 0, 7));
 277          mcrypt_generic_init($td, $key, $iv);
 278          $resp1 = mcrypt_generic($td, $this->challenge);
 279          mcrypt_generic_deinit($td);
 280  
 281          $key = $this->_desAddParity(substr($hash, 7, 7));
 282          mcrypt_generic_init($td, $key, $iv);
 283          $resp2 = mcrypt_generic($td, $this->challenge);
 284          mcrypt_generic_deinit($td);
 285  
 286          $key = $this->_desAddParity(substr($hash, 14, 7));
 287          mcrypt_generic_init($td, $key, $iv);
 288          $resp3 = mcrypt_generic($td, $this->challenge);
 289          mcrypt_generic_deinit($td);
 290          mcrypt_module_close($td);
 291  
 292          return $resp1 . $resp2 . $resp3;
 293      }
 294  
 295      /**
 296       * Generates the LAN-Manager-HASH from the given plaintext password.
 297       *
 298       * @access public
 299       * @return string
 300       */
 301      function lmPasswordHash($password = null)
 302      {
 303          $plain = isset($password) ? $password : $this->password;
 304  
 305          $plain = substr(strtoupper($plain), 0, 14);
 306          while (strlen($plain) < 14) {
 307               $plain .= "\0";
 308          }
 309  
 310          return $this->_desHash(substr($plain, 0, 7)) . $this->_desHash(substr($plain, 7, 7));
 311      }
 312  
 313      /**
 314       * Generates an irreversible HASH.
 315       *
 316       * @access private
 317       * @return string
 318       */
 319      function _desHash($plain)
 320      {
 321          $key = $this->_desAddParity($plain);
 322          $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
 323          $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
 324          mcrypt_generic_init($td, $key, $iv);
 325          $hash = mcrypt_generic($td, 'KGS!@#$%');
 326          mcrypt_generic_deinit($td);
 327          mcrypt_module_close($td);
 328          return $hash;
 329      }
 330  
 331      /**
 332       * Adds the parity bit to the given DES key.
 333       *
 334       * @access private
 335       * @param  string  $key 7-Bytes Key without parity
 336       * @return string
 337       */
 338      function _desAddParity($key)
 339      {
 340          static $odd_parity = array(
 341                  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,
 342                  16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
 343                  32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
 344                  49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
 345                  64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
 346                  81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
 347                  97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
 348                  112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
 349                  128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
 350                  145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
 351                  161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
 352                  176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
 353                  193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
 354                  208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
 355                  224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
 356                  241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254);
 357  
 358          $bin = '';
 359          for ($i = 0; $i < strlen($key); $i++) {
 360              $bin .= sprintf('%08s', decbin(ord($key{$i})));
 361          }
 362  
 363          $str1 = explode('-', substr(chunk_split($bin, 7, '-'), 0, -1));
 364          $x = '';
 365          foreach($str1 as $s) {
 366              $x .= sprintf('%02s', dechex($odd_parity[bindec($s . '0')]));
 367          }
 368  
 369          return pack('H*', $x);
 370  
 371      }
 372  
 373      /**
 374       * Generates the response-packet.
 375       *
 376       * @param  bool  $lm  wether including LAN-Manager-Response
 377       * @access private
 378       * @return string
 379       */
 380      function response($lm = false)
 381      {
 382          $ntresp = $this->ntChallengeResponse();
 383          if ($lm) {
 384              $lmresp = $this->lmChallengeResponse();
 385          } else {
 386              $lmresp = str_repeat ("\0", 24);
 387          }
 388  
 389          // Response: LM Response, NT Response, flags (0 = use LM Response, 1 = use NT Response)
 390          return $lmresp . $ntresp . pack('C', !$lm);
 391      }
 392  }
 393  
 394  /**
 395   * class Crypt_CHAP_MSv2
 396   *
 397   * Generate MS-CHAPv2 Packets. This version of MS-CHAP uses a 16 Bytes authenticator
 398   * challenge and a 16 Bytes peer Challenge. LAN-Manager responses no longer exists
 399   * in this version. The challenge is already a SHA1 challenge hash of both challenges
 400   * and of the username.
 401   *
 402   * @package Crypt_CHAP
 403   */
 404  class Crypt_CHAP_MSv2 extends Crypt_CHAP_MSv1
 405  {
 406      /**
 407       * The username
 408       * @var  string
 409       */
 410      var $username = null;
 411  
 412      /**
 413       * The 16 Bytes random binary peer challenge
 414       * @var  string
 415       */
 416      var $peerChallenge = null;
 417  
 418      /**
 419       * The 16 Bytes random binary authenticator challenge
 420       * @var  string
 421       */
 422      var $authChallenge = null;
 423  
 424      /**
 425       * Constructor
 426       *
 427       * Generates the 16 Bytes peer and authentication challenge
 428       * @return void
 429       */
 430      public function __construct()
 431      {
 432          parent::__construct();
 433          $this->generateChallenge('peerChallenge', 16);
 434          $this->generateChallenge('authChallenge', 16);
 435      }
 436  
 437      /**
 438       * Generates a hash from the NT-HASH.
 439       *
 440       * @access public
 441       * @param  string  $nthash The NT-HASH
 442       * @return string
 443       */
 444      function ntPasswordHashHash($nthash)
 445      {
 446          return pack('H*',hash('md4', $nthash));
 447      }
 448  
 449      /**
 450       * Generates the challenge hash from the peer and the authenticator challenge and
 451       * the username. SHA1 is used for this, but only the first 8 Bytes are used.
 452       *
 453       * @access public
 454       * @return string
 455       */
 456      function challengeHash()
 457      {
 458          return substr(pack('H*',hash('sha1', $this->peerChallenge . $this->authChallenge . $this->username)), 0, 8);
 459      }
 460  
 461      /**
 462       * Generates the response.
 463       *
 464       * @access public
 465       * @return string
 466       */
 467      function challengeResponse()
 468      {
 469          $this->challenge = $this->challengeHash();
 470          return $this->_challengeResponse();
 471      }
 472  }
 473  
 474  
 475  ?>


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1