Crypt_CHAP
[ class tree: Crypt_CHAP ] [ index: Crypt_CHAP ] [ all elements ]

Source for file CHAP.php

Documentation is available at CHAP.php

  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: CHAP.php 302857 2010-08-28 21:12:59Z mbretter $
  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: 302857 $
  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.     function Crypt_CHAP()
  89.     {
  90.         $this->PEAR();
  91.         $this->generateChallenge();
  92.     }
  93.     
  94.     /**
  95.      * Generates a random binary challenge
  96.      *
  97.      * @param  string  $varname  Name of the property
  98.      * @param  integer $size     Size of the challenge in Bytes
  99.      * @return void 
  100.      */
  101.     function generateChallenge($varname 'challenge'$size = 8)
  102.     {
  103.         $this->$varname '';
  104.         for ($i = 0; $i $size$i++{
  105.             $this->$varname .= pack('C'1 + mt_rand(% 255);
  106.         }
  107.         return $this->$varname;
  108.     }
  109.  
  110.     /**
  111.      * Generates the response. Overwrite this.
  112.      *
  113.      * @return void 
  114.      */    
  115.     function challengeResponse()
  116.     {
  117.     }
  118.         
  119. }
  120.  
  121. /**
  122.  * class Crypt_CHAP_MD5
  123.  *
  124.  * Generate CHAP-MD5 Packets
  125.  *
  126.  * @package Crypt_CHAP
  127.  */
  128. class Crypt_CHAP_MD5 extends Crypt_CHAP 
  129. {
  130.  
  131.     /**
  132.      * Generates the response.
  133.      *
  134.      * CHAP-MD5 uses MD5-Hash for generating the response. The Hash consists
  135.      * of the chapid, the plaintext password and the challenge.
  136.      *
  137.      * @return string 
  138.      */ 
  139.     function challengeResponse()
  140.     {
  141.         return pack('H*'md5(pack('C'$this->chapid$this->password . $this->challenge));
  142.     }
  143. }
  144.  
  145. /**
  146.  * class Crypt_CHAP_MSv1
  147.  *
  148.  * Generate MS-CHAPv1 Packets. MS-CHAP doesen't use the plaintext password, it uses the
  149.  * NT-HASH wich is stored in the SAM-Database or in the smbpasswd, if you are using samba.
  150.  * The NT-HASH is MD4(str2unicode(plaintextpass)).
  151.  * You need the hash extension for this class.
  152.  * 
  153.  * @package Crypt_CHAP
  154.  */
  155. class Crypt_CHAP_MSv1 extends Crypt_CHAP
  156. {
  157.     /**
  158.      * Wether using deprecated LM-Responses or not.
  159.      * 0 = use LM-Response, 1 = use NT-Response
  160.      * @var  bool 
  161.      */
  162.     var $flags = 1;
  163.     
  164.     /**
  165.      * Constructor
  166.      *
  167.      * Loads the hash extension
  168.      * @return void 
  169.      */
  170.     function Crypt_CHAP_MSv1()
  171.     {
  172.         $this->Crypt_CHAP();
  173.         $this->loadExtension('hash');        
  174.     }
  175.     
  176.     /**
  177.      * Generates the NT-HASH from the given plaintext password.
  178.      *
  179.      * @access public
  180.      * @return string 
  181.      */
  182.     function ntPasswordHash($password = null
  183.     {
  184.         if (isset($password)) {
  185.             return pack('H*',hash('md4'$this->str2unicode($password)));
  186.         else {
  187.             return pack('H*',hash('md4'$this->str2unicode($this->password)));
  188.         }
  189.     }
  190.     
  191.     /**
  192.      * Converts ascii to unicode.
  193.      *
  194.      * @access public
  195.      * @return string 
  196.      */
  197.     function str2unicode($str
  198.     {
  199.         $uni '';
  200.         $str = (string) $str;
  201.         for ($i = 0; $i strlen($str)$i++{
  202.             $a ord($str{$i}<< 8;
  203.             $uni .= sprintf("%X"$a);
  204.         }
  205.         return pack('H*'$uni);
  206.     }    
  207.     
  208.     /**
  209.      * Generates the NT-Response.
  210.      *
  211.      * @access public
  212.      * @return string 
  213.      */  
  214.     function challengeResponse(
  215.     {
  216.         return $this->_challengeResponse();
  217.     }
  218.     
  219.     /**
  220.      * Generates the NT-Response.
  221.      *
  222.      * @access public
  223.      * @return string 
  224.      */  
  225.     function ntChallengeResponse(
  226.     {
  227.         return $this->_challengeResponse(false);
  228.     }    
  229.     
  230.     /**
  231.      * Generates the LAN-Manager-Response.
  232.      *
  233.      * @access public
  234.      * @return string 
  235.      */
  236.     function lmChallengeResponse()
  237.     {
  238.         return $this->_challengeResponse(true);
  239.     }
  240.  
  241.     /**
  242.      * Generates the response.
  243.      *
  244.      * Generates the response using DES.
  245.      *
  246.      * @param  bool  $lm  wether generating LAN-Manager-Response
  247.      * @access private
  248.      * @return string 
  249.      */
  250.     function _challengeResponse($lm = false)
  251.     {
  252.         if ($lm{
  253.             $hash $this->lmPasswordHash();
  254.         else {
  255.             $hash $this->ntPasswordHash();
  256.         }
  257.  
  258.         while (strlen($hash< 21{
  259.             $hash .= "\0";
  260.         }
  261.  
  262.         $td = mcrypt_module_open(MCRYPT_DES''MCRYPT_MODE_ECB'');
  263.         $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td)MCRYPT_RAND);
  264.         $key $this->_desAddParity(substr($hash07));
  265.         mcrypt_generic_init($td$key$iv);
  266.         $resp1 = mcrypt_generic($td$this->challenge);
  267.         mcrypt_generic_deinit($td);
  268.  
  269.         $key $this->_desAddParity(substr($hash77));
  270.         mcrypt_generic_init($td$key$iv);
  271.         $resp2 = mcrypt_generic($td$this->challenge);
  272.         mcrypt_generic_deinit($td);
  273.  
  274.         $key $this->_desAddParity(substr($hash147));
  275.         mcrypt_generic_init($td$key$iv);
  276.         $resp3 = mcrypt_generic($td$this->challenge);
  277.         mcrypt_generic_deinit($td);
  278.         mcrypt_module_close($td);
  279.  
  280.         return $resp1 $resp2 $resp3;
  281.     }
  282.  
  283.     /**
  284.      * Generates the LAN-Manager-HASH from the given plaintext password.
  285.      *
  286.      * @access public
  287.      * @return string 
  288.      */
  289.     function lmPasswordHash($password = null)
  290.     {
  291.         $plain = isset($password$password $this->password;
  292.  
  293.         $plain substr(strtoupper($plain)014);
  294.         while (strlen($plain< 14{
  295.              $plain .= "\0";
  296.         }
  297.  
  298.         return $this->_desHash(substr($plain07)) $this->_desHash(substr($plain77));
  299.     }
  300.  
  301.     /**
  302.      * Generates an irreversible HASH.
  303.      *
  304.      * @access private
  305.      * @return string 
  306.      */
  307.     function _desHash($plain)
  308.     {
  309.         $key $this->_desAddParity($plain);
  310.         $td = mcrypt_module_open(MCRYPT_DES''MCRYPT_MODE_ECB'');
  311.         $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td)MCRYPT_RAND);
  312.         mcrypt_generic_init($td$key$iv);
  313.         $hash = mcrypt_generic($td'KGS!@#$%');
  314.         mcrypt_generic_deinit($td);
  315.         mcrypt_module_close($td);
  316.         return $hash;
  317.     }
  318.  
  319.     /**
  320.      * Adds the parity bit to the given DES key.
  321.      *
  322.      * @access private
  323.      * @param  string  $key 7-Bytes Key without parity
  324.      * @return string 
  325.      */
  326.     function _desAddParity($key)
  327.     {
  328.         static $odd_parity = array(
  329.                 1,  1,  2,  2,  4,  4,  7,  7,  8,  8111113131414,
  330.                 16161919212122222525262628283131,
  331.                 32323535373738384141424244444747,
  332.                 49495050525255555656595961616262,
  333.                 64646767696970707373747476767979,
  334.                 81818282848487878888919193939494,
  335.                 97979898,100,100,103,103,104,104,107,107,109,109,110,110,
  336.                 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
  337.                 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
  338.                 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
  339.                 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
  340.                 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
  341.                 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
  342.                 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
  343.                 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
  344.                 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254);
  345.  
  346.         $bin '';
  347.         for ($i = 0; $i < strlen($key)$i++{
  348.             $bin .= sprintf('%08s'decbin(ord($key{$i})));
  349.         }
  350.  
  351.         $str1 explode('-'substr(chunk_split($bin7'-')0-1));
  352.         $x '';
  353.         foreach($str1 as $s{
  354.             $x .= sprintf('%02s'dechex($odd_parity[bindec($s '0')]));
  355.         }
  356.  
  357.         return pack('H*'$x);
  358.  
  359.     }
  360.     
  361.     /**
  362.      * Generates the response-packet.
  363.      *
  364.      * @param  bool  $lm  wether including LAN-Manager-Response
  365.      * @access private
  366.      * @return string 
  367.      */      
  368.     function response($lm = false)
  369.     {
  370.         $ntresp $this->ntChallengeResponse();
  371.         if ($lm{
  372.             $lmresp $this->lmChallengeResponse();
  373.         else {
  374.             $lmresp str_repeat ("\0"24);
  375.         }
  376.  
  377.         // Response: LM Response, NT Response, flags (0 = use LM Response, 1 = use NT Response)
  378.         return $lmresp $ntresp pack('C'!$lm);
  379.     }
  380. }
  381.  
  382. /**
  383.  * class Crypt_CHAP_MSv2
  384.  *
  385.  * Generate MS-CHAPv2 Packets. This version of MS-CHAP uses a 16 Bytes authenticator
  386.  * challenge and a 16 Bytes peer Challenge. LAN-Manager responses no longer exists
  387.  * in this version. The challenge is already a SHA1 challenge hash of both challenges
  388.  * and of the username.
  389.  * 
  390.  * @package Crypt_CHAP
  391.  */
  392. {
  393.     /**
  394.      * The username
  395.      * @var  string 
  396.      */
  397.     var $username = null;
  398.  
  399.     /**
  400.      * The 16 Bytes random binary peer challenge
  401.      * @var  string 
  402.      */
  403.     var $peerChallenge = null;
  404.  
  405.     /**
  406.      * The 16 Bytes random binary authenticator challenge
  407.      * @var  string 
  408.      */
  409.     var $authChallenge = null;
  410.     
  411.     /**
  412.      * Constructor
  413.      *
  414.      * Generates the 16 Bytes peer and authentication challenge
  415.      * @return void 
  416.      */
  417.     function Crypt_CHAP_MSv2()
  418.     {
  419.         $this->Crypt_CHAP_MSv1();
  420.         $this->generateChallenge('peerChallenge'16);
  421.         $this->generateChallenge('authChallenge'16);
  422.     }    
  423.  
  424.     /**
  425.      * Generates a hash from the NT-HASH.
  426.      *
  427.      * @access public
  428.      * @param  string  $nthash The NT-HASH
  429.      * @return string 
  430.      */    
  431.     function ntPasswordHashHash($nthash
  432.     {
  433.         return pack('H*',hash('md4'$nthash));
  434.     }
  435.     
  436.     /**
  437.      * Generates the challenge hash from the peer and the authenticator challenge and
  438.      * the username. SHA1 is used for this, but only the first 8 Bytes are used.
  439.      *
  440.      * @access public
  441.      * @return string 
  442.      */   
  443.     function challengeHash(
  444.     {
  445.         return substr(pack('H*',hash('sha1'$this->peerChallenge . $this->authChallenge . $this->username))08);
  446.     }    
  447.  
  448.     /**
  449.      * Generates the response.
  450.      *
  451.      * @access public
  452.      * @return string 
  453.      */  
  454.     function challengeResponse(
  455.     {
  456.         $this->challenge = $this->challengeHash();
  457.         return $this->_challengeResponse();
  458.     }    
  459. }
  460.  
  461.  
  462. ?>

Documentation generated on Mon, 11 Mar 2019 15:39:04 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.