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

Documentation generated on Mon, 11 Mar 2019 14:57:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.