From 3b8c248237a9594849a0dfae435adf36c052573b Mon Sep 17 00:00:00 2001
From: jonathanharker
Date: Fri, 12 Dec 2008 04:44:53 +0000
Subject: [PATCH] MDL-17549 auth/radius: add CHAP and MSCHAP auth support,
detect PHP extension
* Added support for CHAP and MSCHAP authentication schemes
contributed by Stanislav Tsymbalov http://www.tsymbalov.net/
original code at http://sourceforge.net/projects/moodleradius/
* Tweak the detection of PHP RADIUS extension and Pear code
* Update the warning notices to use more Moodly CSS classes
lib/pear: Add RADIUS and CHAP PEAR libs
* Add PEAR Auth_RADIUS and Crypt_CHAP packages to lib/pear
Author: Jonathan Harker
---
auth/radius/auth.php | 52 +-
auth/radius/config.html | 35 +-
lang/en_utf8/auth.php | 8 +-
lib/pear/Auth/RADIUS.php | 1001 ++++++++++++++++++++++++++++++++++++++
lib/pear/Crypt/CHAP.php | 464 ++++++++++++++++++
lib/pear/README.txt | 11 +
6 files changed, 1565 insertions(+), 6 deletions(-)
create mode 100644 lib/pear/Auth/RADIUS.php
create mode 100644 lib/pear/Crypt/CHAP.php
diff --git a/auth/radius/auth.php b/auth/radius/auth.php
index 4e2dd44edb..d84e2a956e 100644
--- a/auth/radius/auth.php
+++ b/auth/radius/auth.php
@@ -9,8 +9,10 @@
*
* Authenticates against a RADIUS server.
* Contributed by Clive Gould
+ * CHAP support contributed by Stanislav Tsymbalov http://www.tsymbalov.net/
*
* 2006-08-31 File created.
+ * 2008-03-12 CHAP support added by Stanislav Tsymbalov.
*/
if (!defined('MOODLE_INTERNAL')) {
@@ -42,6 +44,7 @@ class auth_plugin_radius extends auth_plugin_base {
*/
function user_login ($username, $password) {
require_once 'Auth/RADIUS.php';
+ require_once 'Crypt/CHAP.php';
// Added by Clive on 7th May for test purposes
// printf("Username: $username
");
@@ -50,9 +53,52 @@ class auth_plugin_radius extends auth_plugin_base {
// printf("nasport: $this->config->nasport
");
// printf("secret: $this->config->secret
");
- $rauth = new Auth_RADIUS_PAP($username, $password);
+ // Added by Stanislav Tsymbalov on 12th March 2008 only for test purposes
+ //$type = 'PAP';
+ //$type = 'CHAP_MD5';
+ //$type = 'MSCHAPv1';
+ //$type = 'MSCHAPv2';
+ $type = $this->config->radiustype;
+ if (empty($type)) {
+ $type = 'PAP';
+ }
+
+ $classname = 'Auth_RADIUS_' . $type;
+ $rauth = new $classname($username, $password);
$rauth->addServer($this->config->host, $this->config->nasport, $this->config->secret);
+ $rauth->username = $username;
+
+ switch($type) {
+ case 'CHAP_MD5':
+ case 'MSCHAPv1':
+ $classname = $type == 'MSCHAPv1' ? 'Crypt_CHAP_MSv1' : 'Crypt_CHAP_MD5';
+ $crpt = new $classname;
+ $crpt->password = $password;
+ $rauth->challenge = $crpt->challenge;
+ $rauth->chapid = $crpt->chapid;
+ $rauth->response = $crpt->challengeResponse();
+ $rauth->flags = 1;
+ // If you must use deprecated and weak LAN-Manager-Responses use this:
+ // $rauth->lmResponse = $crpt->lmChallengeResponse();
+ // $rauth->flags = 0;
+ break;
+
+ case 'MSCHAPv2':
+ $crpt = new Crypt_CHAP_MSv2;
+ $crpt->username = $username;
+ $crpt->password = $password;
+ $rauth->challenge = $crpt->authChallenge;
+ $rauth->peerChallenge = $crpt->peerChallenge;
+ $rauth->chapid = $crpt->chapid;
+ $rauth->response = $crpt->challengeResponse();
+ break;
+
+ default:
+ $rauth->password = $password;
+ break;
+ }
+
if (!$rauth->start()) {
printf("Radius start: %s
\n", $rauth->getError());
exit;
@@ -122,6 +168,9 @@ class auth_plugin_radius extends auth_plugin_base {
if (!isset ($config->nasport)) {
$config->nasport = '1812';
}
+ if (!isset($config->radiustype)) {
+ $config->radiustype = 'PAP';
+ }
if (!isset ($config->secret)) {
$config->secret = '';
}
@@ -134,6 +183,7 @@ class auth_plugin_radius extends auth_plugin_base {
set_config('nasport', $config->nasport, 'auth/radius');
set_config('secret', $config->secret, 'auth/radius');
set_config('changepasswordurl', $config->changepasswordurl, 'auth/radius');
+ set_config('radiustype', $config->radiustype, 'auth/radius');
return true;
}
diff --git a/auth/radius/config.html b/auth/radius/config.html
index 449f0c0694..d56f9477c9 100644
--- a/auth/radius/config.html
+++ b/auth/radius/config.html
@@ -1,10 +1,12 @@
Warning: The Auth_RADIUS module does not seem to be present. Please ensure it is installed and enabled.
';
+if (!extension_loaded('radius')) {
+ print '
: |
diff --git a/lang/en_utf8/auth.php b/lang/en_utf8/auth.php
index 55b22b2756..db94c0bc6e 100644
--- a/lang/en_utf8/auth.php
+++ b/lang/en_utf8/auth.php
@@ -314,10 +314,16 @@ $string['auth_radiusdescription'] = 'This method uses a Shibboleth. Be sure to read the README for Shibboleth on how to set up your Moodle with Shibboleth';
@@ -355,7 +361,7 @@ $string['auth_usernameexists'] = 'Selected username already exists. Please choos
$string['authenticationoptions'] = 'Authentication options';
$string['authinstructions'] = 'Here you can provide instructions for your users, so they know which username and password they should be using. The text you enter here will appear on the login page. If you leave this blank then no instructions will be printed.';
$string['changepassword'] = 'Change password URL';
-$string['changepasswordhelp'] = 'Here you can specify a location at which your users can recover or change their username/password if they\'ve forgotten it. This will be provided to users as a button on the login page and their user page. if you leave this blank the button will not be printed.';
+$string['changepasswordhelp'] = 'Here you can specify a location at which your users can recover or change their username/password if they\'ve forgotten it. This will be provided to users as a button on the login page and their user page. If you leave this blank the button will not be printed.';
$string['chooseauthmethod'] = 'Choose an authentication method';
$string['createpasswordifneeded'] = 'Create password if needed';
$string['errorpasswordupdate'] = 'Error updating password, password not changed';
diff --git a/lib/pear/Auth/RADIUS.php b/lib/pear/Auth/RADIUS.php
new file mode 100644
index 0000000000..d40050da23
--- /dev/null
+++ b/lib/pear/Auth/RADIUS.php
@@ -0,0 +1,1001 @@
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This code cannot simply be copied and put under the GNU Public License or
+any other GPL-like (LGPL, GPL2) License.
+
+ $Id$
+*/
+
+require_once 'PEAR.php';
+
+/**
+* Client implementation of RADIUS. This are wrapper classes for
+* the RADIUS PECL.
+* Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
+*
+* @package Auth_RADIUS
+* @author Michael Bretterklieber
+* @access public
+* @version $Revision$
+*/
+
+PEAR::loadExtension('radius');
+
+/**
+ * class Auth_RADIUS
+ *
+ * Abstract base class for RADIUS
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS extends PEAR {
+
+ /**
+ * List of RADIUS servers.
+ * @var array
+ * @see addServer(), putServer()
+ */
+ var $_servers = array();
+
+ /**
+ * Path to the configuration-file.
+ * @var string
+ * @see setConfigFile()
+ */
+ var $_configfile = null;
+
+ /**
+ * Resource.
+ * @var resource
+ * @see open(), close()
+ */
+ var $res = null;
+
+ /**
+ * Username for authentication and accounting requests.
+ * @var string
+ */
+ var $username = null;
+
+ /**
+ * Password for plaintext-authentication (PAP).
+ * @var string
+ */
+ var $password = null;
+
+ /**
+ * List of known attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $attributes = array();
+
+ /**
+ * List of raw attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $rawAttributes = array();
+
+ /**
+ * List of raw vendor specific attributes.
+ * @var array
+ * @see dumpAttributes(), getAttributes()
+ */
+ var $rawVendorAttributes = array();
+
+ /**
+ * Switch whether we should put standard attributes or not
+ * @var bool
+ * @see putStandardAttributes()
+ */
+ var $useStandardAttributes = true;
+
+ /**
+ * Constructor
+ *
+ * Loads the RADIUS PECL/extension
+ *
+ * @return void
+ */
+ function Auth_RADIUS()
+ {
+ $this->PEAR();
+ }
+
+ /**
+ * Adds a RADIUS server to the list of servers for requests.
+ *
+ * At most 10 servers may be specified. When multiple servers
+ * are given, they are tried in round-robin fashion until a
+ * valid response is received
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @param integer $port Portnumber
+ * @param string $sharedSecret Shared secret
+ * @param integer $timeout Timeout for each request
+ * @param integer $maxtries Max. retries for each request
+ * @return void
+ */
+ function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
+ {
+ $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
+ }
+
+ /**
+ * Returns an error message, if an error occurred.
+ *
+ * @access public
+ * @return string
+ */
+ function getError()
+ {
+ return radius_strerror($this->res);
+ }
+
+ /**
+ * Sets the configuration-file.
+ *
+ * @access public
+ * @param string $file Path to the configuration file
+ * @return void
+ */
+ function setConfigfile($file)
+ {
+ $this->_configfile = $file;
+ }
+
+ /**
+ * Puts an attribute.
+ *
+ * @access public
+ * @param integer $attrib Attribute-number
+ * @param mixed $port Attribute-value
+ * @param type $type Attribute-type
+ * @return bool true on success, false on error
+ */
+ function putAttribute($attrib, $value, $type = null)
+ {
+ if ($type == null) {
+ $type = gettype($value);
+ }
+
+ switch ($type) {
+ case 'integer':
+ case 'double':
+ return radius_put_int($this->res, $attrib, $value);
+
+ case 'addr':
+ return radius_put_addr($this->res, $attrib, $value);
+
+ case 'string':
+ default:
+ return radius_put_attr($this->res, $attrib, $value);
+ }
+
+ }
+
+ /**
+ * Puts a vendor-specific attribute.
+ *
+ * @access public
+ * @param integer $vendor Vendor (MSoft, Cisco, ...)
+ * @param integer $attrib Attribute-number
+ * @param mixed $port Attribute-value
+ * @param type $type Attribute-type
+ * @return bool true on success, false on error
+ */
+ function putVendorAttribute($vendor, $attrib, $value, $type = null)
+ {
+
+ if ($type == null) {
+ $type = gettype($value);
+ }
+
+ switch ($type) {
+ case 'integer':
+ case 'double':
+ return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
+
+ case 'addr':
+ return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
+
+ case 'string':
+ default:
+ return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
+ }
+
+ }
+
+ /**
+ * Prints known attributes received from the server.
+ *
+ * @access public
+ */
+ function dumpAttributes()
+ {
+ foreach ($this->attributes as $name => $data) {
+ echo "$name:$data \n";
+ }
+ }
+
+ /**
+ * Overwrite this.
+ *
+ * @access public
+ */
+ function open()
+ {
+ }
+
+ /**
+ * Overwrite this.
+ *
+ * @access public
+ */
+ function createRequest()
+ {
+ }
+
+ /**
+ * Puts standard attributes.
+ *
+ * @access public
+ */
+ function putStandardAttributes()
+ {
+ if (!$this->useStandardAttributes)
+ return;
+
+ if (isset($_SERVER)) {
+ $var = &$_SERVER;
+ } else {
+ $var = &$GLOBALS['HTTP_SERVER_VARS'];
+ }
+
+ $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost');
+ $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
+ $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
+ $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
+ $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1');
+ }
+
+ /**
+ * Puts custom attributes.
+ *
+ * @access public
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ }
+
+ /**
+ * Configures the radius library.
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @param integer $port Portnumber
+ * @param string $sharedSecret Shared secret
+ * @param integer $timeout Timeout for each request
+ * @param integer $maxtries Max. retries for each request
+ * @return bool true on success, false on error
+ * @see addServer()
+ */
+ function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
+ {
+ if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Configures the radius library via external configurationfile
+ *
+ * @access public
+ * @param string $servername Servername or IP-Address
+ * @return bool true on success, false on error
+ */
+ function putConfigfile($file)
+ {
+ if (!radius_config($this->res, $file)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Initiates a RADIUS request.
+ *
+ * @access public
+ * @return bool true on success, false on errors
+ */
+ function start()
+ {
+ if (!$this->open()) {
+ return false;
+ }
+
+ foreach ($this->_servers as $s) {
+ // Servername, port, sharedsecret, timeout, retries
+ if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
+ return false;
+ }
+ }
+
+ if (!empty($this->_configfile)) {
+ if (!$this->putConfigfile($this->_configfile)) {
+ return false;
+ }
+ }
+
+ $this->createRequest();
+ $this->putStandardAttributes();
+ $this->putAuthAttributes();
+ return true;
+ }
+
+ /**
+ * Sends a prepared RADIUS request and waits for a response
+ *
+ * @access public
+ * @return mixed true on success, false on reject, PEAR_Error on error
+ */
+ function send()
+ {
+ $req = radius_send_request($this->res);
+ if (!$req) {
+ return $this->raiseError('Error sending request: ' . $this->getError());
+ }
+
+ switch($req) {
+ case RADIUS_ACCESS_ACCEPT:
+ if (is_subclass_of($this, 'auth_radius_acct')) {
+ return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
+ }
+ return true;
+
+ case RADIUS_ACCESS_REJECT:
+ return false;
+
+ case RADIUS_ACCOUNTING_RESPONSE:
+ if (is_subclass_of($this, 'auth_radius_pap')) {
+ return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
+ }
+ return true;
+
+ default:
+ return $this->raiseError("Unexpected return value: $req");
+ }
+
+ }
+
+ /**
+ * Reads all received attributes after sending the request.
+ *
+ * This methods stores known attributes in the property attributes,
+ * all attributes (including known attibutes) are stored in rawAttributes
+ * or rawVendorAttributes.
+ * NOTE: call this function also even if the request was rejected, because the
+ * Server returns usualy an errormessage
+ *
+ * @access public
+ * @return bool true on success, false on error
+ */
+ function getAttributes()
+ {
+
+ while ($attrib = radius_get_attr($this->res)) {
+
+ if (!is_array($attrib)) {
+ return false;
+ }
+
+ $attr = $attrib['attr'];
+ $data = $attrib['data'];
+
+ $this->rawAttributes[$attr] = $data;
+
+ switch ($attr) {
+ case RADIUS_FRAMED_IP_ADDRESS:
+ $this->attributes['framed_ip'] = radius_cvt_addr($data);
+ break;
+
+ case RADIUS_FRAMED_IP_NETMASK:
+ $this->attributes['framed_mask'] = radius_cvt_addr($data);
+ break;
+
+ case RADIUS_FRAMED_MTU:
+ $this->attributes['framed_mtu'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FRAMED_COMPRESSION:
+ $this->attributes['framed_compression'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_SESSION_TIMEOUT:
+ $this->attributes['session_timeout'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_IDLE_TIMEOUT:
+ $this->attributes['idle_timeout'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_SERVICE_TYPE:
+ $this->attributes['service_type'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_CLASS:
+ $this->attributes['class'] = radius_cvt_string($data);
+ break;
+
+ case RADIUS_FRAMED_PROTOCOL:
+ $this->attributes['framed_protocol'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FRAMED_ROUTING:
+ $this->attributes['framed_routing'] = radius_cvt_int($data);
+ break;
+
+ case RADIUS_FILTER_ID:
+ $this->attributes['filter_id'] = radius_cvt_string($data);
+ break;
+
+ case RADIUS_REPLY_MESSAGE:
+ $this->attributes['reply_message'] = radius_cvt_string($data);
+ break;
+
+ case RADIUS_VENDOR_SPECIFIC:
+ $attribv = radius_get_vendor_attr($data);
+ if (!is_array($attribv)) {
+ return false;
+ }
+
+ $vendor = $attribv['vendor'];
+ $attrv = $attribv['attr'];
+ $datav = $attribv['data'];
+
+ $this->rawVendorAttributes[$vendor][$attrv] = $datav;
+
+ if ($vendor == RADIUS_VENDOR_MICROSOFT) {
+
+ switch ($attrv) {
+ case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
+ $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_ERROR:
+ $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
+ $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
+ $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
+ $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
+ $demangled = radius_demangle($this->res, $datav);
+ $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
+ $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
+ $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
+ $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
+ break;
+
+ case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
+ $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
+ break;
+ }
+ }
+ break;
+
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ if ($this->res != null) {
+ radius_close($this->res);
+ $this->res = null;
+ }
+ $this->username = str_repeat("\0", strlen($this->username));
+ $this->password = str_repeat("\0", strlen($this->password));
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_PAP
+ *
+ * Class for authenticating using PAP (Plaintext)
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_PAP extends Auth_RADIUS
+{
+
+ /**
+ * Constructor
+ *
+ * @param string $username Username
+ * @param string $password Password
+ * @return void
+ */
+ function Auth_RADIUS_PAP($username = null, $password = null)
+ {
+ $this->Auth_RADIUS();
+ $this->username = $username;
+ $this->password = $password;
+ }
+
+ /**
+ * Creates a RADIUS resource
+ *
+ * Creates a RADIUS resource for authentication. This should be the first
+ * call before you make any other things with the library.
+ *
+ * @return bool true on success, false on error
+ */
+ function open()
+ {
+ $this->res = radius_auth_open();
+ if (!$this->res) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates an authentication request
+ *
+ * Creates an authentication request.
+ * You MUST call this method before you can put any attribute
+ *
+ * @return bool true on success, false on error
+ */
+ function createRequest()
+ {
+ if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Put authentication specific attributes
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->password)) {
+ $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
+ }
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_CHAP_MD5
+ *
+ * Class for authenticating using CHAP-MD5 see RFC1994.
+ * Instead og the plaintext password the challenge and
+ * the response are needed.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
+{
+ /**
+ * 8 Bytes binary challenge
+ * @var string
+ */
+ var $challenge = null;
+
+ /**
+ * 16 Bytes MD5 response binary
+ * @var string
+ */
+ var $response = null;
+
+ /**
+ * Id of the authentication request. Should incremented after every request.
+ * @var integer
+ */
+ var $chapid = 1;
+
+ /**
+ * Constructor
+ *
+ * @param string $username Username
+ * @param string $challenge 8 Bytes Challenge (binary)
+ * @param integer $chapid Requestnumber
+ * @return void
+ */
+ function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
+ {
+ $this->Auth_RADIUS_PAP();
+ $this->username = $username;
+ $this->challenge = $challenge;
+ $this->chapid = $chapid;
+ }
+
+ /**
+ * Put CHAP-MD5 specific attributes
+ *
+ * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
+ * and the response. The chapid is inserted in the first byte of the response.
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response)) {
+ $response = pack('C', $this->chapid) . $this->response;
+ $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
+ }
+ if (isset($this->challenge)) {
+ $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ Auth_RADIUS_PAP::close();
+ $this->challenge = str_repeat("\0", strlen($this->challenge));
+ $this->response = str_repeat("\0", strlen($this->response));
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_MSCHAPv1
+ *
+ * Class for authenticating using MS-CHAPv1 see RFC2433
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
+{
+ /**
+ * LAN-Manager-Response
+ * @var string
+ */
+ var $lmResponse = null;
+
+ /**
+ * Wether using deprecated LM-Responses or not.
+ * 0 = use LM-Response, 1 = use NT-Response
+ * @var bool
+ */
+ var $flags = 1;
+
+ /**
+ * Put MS-CHAPv1 specific attributes
+ *
+ * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
+ * and the response. The response has this structure:
+ * struct rad_mschapvalue {
+ * u_char ident;
+ * u_char flags;
+ * u_char lm_response[24];
+ * u_char response[24];
+ * };
+ *
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response) || isset($this->lmResponse)) {
+ $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
+ $ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24);
+ $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
+ }
+ if (isset($this->challenge)) {
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+}
+
+/**
+ * class Auth_RADIUS_MSCHAPv2
+ *
+ * Class for authenticating using MS-CHAPv2 see RFC2759
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
+{
+ /**
+ * 16 Bytes binary challenge
+ * @var string
+ */
+ var $challenge = null;
+
+ /**
+ * 16 Bytes binary Peer Challenge
+ * @var string
+ */
+ var $peerChallenge = null;
+
+ /**
+ * Put MS-CHAPv2 specific attributes
+ *
+ * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
+ * and the response. The response has this structure:
+ * struct rad_mschapv2value {
+ * u_char ident;
+ * u_char flags;
+ * u_char pchallenge[16];
+ * u_char reserved[8];
+ * u_char response[24];
+ * };
+ * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ if (isset($this->username)) {
+ $this->putAttribute(RADIUS_USER_NAME, $this->username);
+ }
+ if (isset($this->response) && isset($this->peerChallenge)) {
+ // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
+ $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
+ }
+ if (isset($this->challenge)) {
+ $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
+ }
+ }
+
+ /**
+ * Frees resources.
+ *
+ * Calling this method is always a good idea, because all security relevant
+ * attributes are filled with Nullbytes to leave nothing in the mem.
+ *
+ * @access public
+ */
+ function close()
+ {
+ Auth_RADIUS_MSCHAPv1::close();
+ $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
+ }
+}
+
+/**
+ * class Auth_RADIUS_Acct
+ *
+ * Class for RADIUS accounting
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct extends Auth_RADIUS
+{
+ /**
+ * Defines where the Authentication was made, possible values are:
+ * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
+ * @var integer
+ */
+ var $authentic = null;
+
+ /**
+ * Defines the type of the accounting request, on of:
+ * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
+ * @var integer
+ */
+ var $status_type = null;
+
+ /**
+ * The time the user was logged in in seconds
+ * @var integer
+ */
+ var $session_time = null;
+
+ /**
+ * A uniq identifier for the session of the user, maybe the PHP-Session-Id
+ * @var string
+ */
+ var $session_id = null;
+
+ /**
+ * Constructor
+ *
+ * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
+ * @return void
+ */
+ function Auth_RADIUS_Acct()
+ {
+ $this->Auth_RADIUS();
+
+ if (isset($_SERVER)) {
+ $var = &$_SERVER;
+ } else {
+ $var = &$GLOBALS['HTTP_SERVER_VARS'];
+ }
+
+ $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
+ }
+
+ /**
+ * Creates a RADIUS resource
+ *
+ * Creates a RADIUS resource for accounting. This should be the first
+ * call before you make any other things with the library.
+ *
+ * @return bool true on success, false on error
+ */
+ function open()
+ {
+ $this->res = radius_acct_open();
+ if (!$this->res) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates an accounting request
+ *
+ * Creates an accounting request.
+ * You MUST call this method before you can put any attribute.
+ *
+ * @return bool true on success, false on error
+ */
+ function createRequest()
+ {
+ if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Put attributes for accounting.
+ *
+ * Here we put some accounting values. There many more attributes for accounting,
+ * but for web-applications only certain attributes make sense.
+ * @return void
+ */
+ function putAuthAttributes()
+ {
+ $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
+ $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
+ if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
+ $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
+ }
+ if (isset($this->authentic)) {
+ $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
+ }
+
+ }
+
+}
+
+/**
+ * class Auth_RADIUS_Acct_Start
+ *
+ * Class for RADIUS accounting. Its usualy used, after the user has logged in.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_START by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_START;
+}
+
+/**
+ * class Auth_RADIUS_Acct_Start
+ *
+ * Class for RADIUS accounting. Its usualy used, after the user has logged out.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_STOP by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_STOP;
+}
+
+if (!defined('RADIUS_UPDATE'))
+ define('RADIUS_UPDATE', 3);
+
+/**
+ * class Auth_RADIUS_Acct_Update
+ *
+ * Class for interim RADIUS accounting updates.
+ *
+ * @package Auth_RADIUS
+ */
+class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
+{
+ /**
+ * Defines the type of the accounting request.
+ * It is set to RADIUS_UPDATE by default in this class.
+ * @var integer
+ */
+ var $status_type = RADIUS_UPDATE;
+}
+
+?>
diff --git a/lib/pear/Crypt/CHAP.php b/lib/pear/Crypt/CHAP.php
new file mode 100644
index 0000000000..db33e987b1
--- /dev/null
+++ b/lib/pear/Crypt/CHAP.php
@@ -0,0 +1,464 @@
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This code cannot simply be copied and put under the GNU Public License or
+any other GPL-like (LGPL, GPL2) License.
+
+ $Id$
+*/
+
+require_once 'PEAR.php';
+
+/**
+* Classes for generating packets for various CHAP Protocols:
+* CHAP-MD5: RFC1994
+* MS-CHAPv1: RFC2433
+* MS-CHAPv2: RFC2759
+*
+* @package Crypt_CHAP
+* @author Michael Bretterklieber
+* @access public
+* @version $Revision$
+*/
+
+/**
+ * class Crypt_CHAP
+ *
+ * Abstract base class for CHAP
+ *
+ * @package Crypt_CHAP
+ */
+class Crypt_CHAP extends PEAR
+{
+ /**
+ * Random binary challenge
+ * @var string
+ */
+ var $challenge = null;
+
+ /**
+ * Binary response
+ * @var string
+ */
+ var $response = null;
+
+ /**
+ * User password
+ * @var string
+ */
+ var $password = null;
+
+ /**
+ * Id of the authentication request. Should incremented after every request.
+ * @var integer
+ */
+ var $chapid = 1;
+
+ /**
+ * Constructor
+ *
+ * Generates a random challenge
+ * @return void
+ */
+ function Crypt_CHAP()
+ {
+ $this->PEAR();
+ $this->generateChallenge();
+ }
+
+ /**
+ * Generates a random binary challenge
+ *
+ * @param string $varname Name of the property
+ * @param integer $size Size of the challenge in Bytes
+ * @return void
+ */
+ function generateChallenge($varname = 'challenge', $size = 8)
+ {
+ $this->$varname = '';
+ mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
+ for ($i = 0; $i < $size; $i++) {
+ $this->$varname .= pack('C', 1 + mt_rand() % 255);
+ }
+ return $this->$varname;
+ }
+
+ /**
+ * Generates the response. Overwrite this.
+ *
+ * @return void
+ */
+ function challengeResponse()
+ {
+ }
+
+}
+
+/**
+ * class Crypt_CHAP_MD5
+ *
+ * Generate CHAP-MD5 Packets
+ *
+ * @package Crypt_CHAP
+ */
+class Crypt_CHAP_MD5 extends Crypt_CHAP
+{
+
+ /**
+ * Generates the response.
+ *
+ * CHAP-MD5 uses MD5-Hash for generating the response. The Hash consists
+ * of the chapid, the plaintext password and the challenge.
+ *
+ * @return string
+ */
+ function challengeResponse()
+ {
+ return pack('H*', md5(pack('C', $this->chapid) . $this->password . $this->challenge));
+ }
+}
+
+/**
+ * class Crypt_CHAP_MSv1
+ *
+ * Generate MS-CHAPv1 Packets. MS-CHAP doesen't use the plaintext password, it uses the
+ * NT-HASH wich is stored in the SAM-Database or in the smbpasswd, if you are using samba.
+ * The NT-HASH is MD4(str2unicode(plaintextpass)).
+ * You need the mhash extension for this class.
+ *
+ * @package Crypt_CHAP
+ */
+class Crypt_CHAP_MSv1 extends Crypt_CHAP
+{
+ /**
+ * Wether using deprecated LM-Responses or not.
+ * 0 = use LM-Response, 1 = use NT-Response
+ * @var bool
+ */
+ var $flags = 1;
+
+ /**
+ * Constructor
+ *
+ * Loads the mhash extension
+ * @return void
+ */
+ function Crypt_CHAP_MSv1()
+ {
+ $this->Crypt_CHAP();
+ $this->loadExtension('mhash');
+ }
+
+ /**
+ * Generates the NT-HASH from the given plaintext password.
+ *
+ * @access public
+ * @return string
+ */
+ function ntPasswordHash($password = null)
+ {
+ if (isset($password)) {
+ return mhash(MHASH_MD4, $this->str2unicode($password));
+ } else {
+ return mhash(MHASH_MD4, $this->str2unicode($this->password));
+ }
+ }
+
+ /**
+ * Converts ascii to unicode.
+ *
+ * @access public
+ * @return string
+ */
+ function str2unicode($str)
+ {
+ $uni = '';
+ $str = (string) $str;
+ for ($i = 0; $i < strlen($str); $i++) {
+ $a = ord($str{$i}) << 8;
+ $uni .= sprintf("%X", $a);
+ }
+ return pack('H*', $uni);
+ }
+
+ /**
+ * Generates the NT-Response.
+ *
+ * @access public
+ * @return string
+ */
+ function challengeResponse()
+ {
+ return $this->_challengeResponse();
+ }
+
+ /**
+ * Generates the NT-Response.
+ *
+ * @access public
+ * @return string
+ */
+ function ntChallengeResponse()
+ {
+ return $this->_challengeResponse(false);
+ }
+
+ /**
+ * Generates the LAN-Manager-Response.
+ *
+ * @access public
+ * @return string
+ */
+ function lmChallengeResponse()
+ {
+ return $this->_challengeResponse(true);
+ }
+
+ /**
+ * Generates the response.
+ *
+ * Generates the response using DES.
+ *
+ * @param bool $lm wether generating LAN-Manager-Response
+ * @access private
+ * @return string
+ */
+ function _challengeResponse($lm = false)
+ {
+ if ($lm) {
+ $hash = $this->lmPasswordHash();
+ } else {
+ $hash = $this->ntPasswordHash();
+ }
+
+ while (strlen($hash) < 21) {
+ $hash .= "\0";
+ }
+
+ $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
+ $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
+ $key = $this->_desAddParity(substr($hash, 0, 7));
+ mcrypt_generic_init($td, $key, $iv);
+ $resp1 = mcrypt_generic($td, $this->challenge);
+ mcrypt_generic_deinit($td);
+
+ $key = $this->_desAddParity(substr($hash, 7, 7));
+ mcrypt_generic_init($td, $key, $iv);
+ $resp2 = mcrypt_generic($td, $this->challenge);
+ mcrypt_generic_deinit($td);
+
+ $key = $this->_desAddParity(substr($hash, 14, 7));
+ mcrypt_generic_init($td, $key, $iv);
+ $resp3 = mcrypt_generic($td, $this->challenge);
+ mcrypt_generic_deinit($td);
+ mcrypt_module_close($td);
+
+ return $resp1 . $resp2 . $resp3;
+ }
+
+ /**
+ * Generates the LAN-Manager-HASH from the given plaintext password.
+ *
+ * @access public
+ * @return string
+ */
+ function lmPasswordHash($password = null)
+ {
+ $plain = isset($password) ? $password : $this->password;
+
+ $plain = substr(strtoupper($plain), 0, 14);
+ while (strlen($plain) < 14) {
+ $plain .= "\0";
+ }
+
+ return $this->_desHash(substr($plain, 0, 7)) . $this->_desHash(substr($plain, 7, 7));
+ }
+
+ /**
+ * Generates an irreversible HASH.
+ *
+ * @access private
+ * @return string
+ */
+ function _desHash($plain)
+ {
+ $key = $this->_desAddParity($plain);
+ $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
+ $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
+ mcrypt_generic_init($td, $key, $iv);
+ $hash = mcrypt_generic($td, 'KGS!@#$%');
+ mcrypt_generic_deinit($td);
+ mcrypt_module_close($td);
+ return $hash;
+ }
+
+ /**
+ * Adds the parity bit to the given DES key.
+ *
+ * @access private
+ * @param string $key 7-Bytes Key without parity
+ * @return string
+ */
+ function _desAddParity($key)
+ {
+ static $odd_parity = array(
+ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
+ 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
+ 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
+ 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
+ 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
+ 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
+ 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
+ 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
+ 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
+ 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254);
+
+ $bin = '';
+ for ($i = 0; $i < strlen($key); $i++) {
+ $bin .= sprintf('%08s', decbin(ord($key{$i})));
+ }
+
+ $str1 = explode('-', substr(chunk_split($bin, 7, '-'), 0, -1));
+ $x = '';
+ foreach($str1 as $s) {
+ $x .= sprintf('%02s', dechex($odd_parity[bindec($s . '0')]));
+ }
+
+ return pack('H*', $x);
+
+ }
+
+ /**
+ * Generates the response-packet.
+ *
+ * @param bool $lm wether including LAN-Manager-Response
+ * @access private
+ * @return string
+ */
+ function response($lm = false)
+ {
+ $ntresp = $this->ntChallengeResponse();
+ if ($lm) {
+ $lmresp = $this->lmChallengeResponse();
+ } else {
+ $lmresp = str_repeat ("\0", 24);
+ }
+
+ // Response: LM Response, NT Response, flags (0 = use LM Response, 1 = use NT Response)
+ return $lmresp . $ntresp . pack('C', !$lm);
+ }
+}
+
+/**
+ * class Crypt_CHAP_MSv2
+ *
+ * Generate MS-CHAPv2 Packets. This version of MS-CHAP uses a 16 Bytes authenticator
+ * challenge and a 16 Bytes peer Challenge. LAN-Manager responses no longer exists
+ * in this version. The challenge is already a SHA1 challenge hash of both challenges
+ * and of the username.
+ *
+ * @package Crypt_CHAP
+ */
+class Crypt_CHAP_MSv2 extends Crypt_CHAP_MSv1
+{
+ /**
+ * The username
+ * @var string
+ */
+ var $username = null;
+
+ /**
+ * The 16 Bytes random binary peer challenge
+ * @var string
+ */
+ var $peerChallenge = null;
+
+ /**
+ * The 16 Bytes random binary authenticator challenge
+ * @var string
+ */
+ var $authChallenge = null;
+
+ /**
+ * Constructor
+ *
+ * Generates the 16 Bytes peer and authentication challenge
+ * @return void
+ */
+ function Crypt_CHAP_MSv2()
+ {
+ $this->Crypt_CHAP_MSv1();
+ $this->generateChallenge('peerChallenge', 16);
+ $this->generateChallenge('authChallenge', 16);
+ }
+
+ /**
+ * Generates a hash from the NT-HASH.
+ *
+ * @access public
+ * @param string $nthash The NT-HASH
+ * @return string
+ */
+ function ntPasswordHashHash($nthash)
+ {
+ return mhash(MHASH_MD4, $nthash);
+ }
+
+ /**
+ * Generates the challenge hash from the peer and the authenticator challenge and
+ * the username. SHA1 is used for this, but only the first 8 Bytes are used.
+ *
+ * @access public
+ * @return string
+ */
+ function challengeHash()
+ {
+ return substr(mhash(MHASH_SHA1, $this->peerChallenge . $this->authChallenge . $this->username), 0, 8);
+ }
+
+ /**
+ * Generates the response.
+ *
+ * @access public
+ * @return string
+ */
+ function challengeResponse()
+ {
+ $this->challenge = $this->challengeHash();
+ return $this->_challengeResponse();
+ }
+}
+
+
+?>
diff --git a/lib/pear/README.txt b/lib/pear/README.txt
index 3b1f4a477c..dcf82d65b2 100644
--- a/lib/pear/README.txt
+++ b/lib/pear/README.txt
@@ -65,6 +65,17 @@ In detail, the libraries added here are:
- by Elizabeth Smith, Arpad Ray, Joshua Eichorn, David Coallier and Laurent Yaish
- License: LGPL
- http://pear.php.net/package/HTML_AJAX/
+- PEAR Auth_RADIUS:
+ - Current version: 1.0.6 (2008-04-13)
+ - by Michael Bretterklieber
+ - License: BSD
+ - http://pear.php.net/package/Auth_RADIUS
+- PEAR Crypt_CHAP:
+ - Current Version: 1.0.1 (2007-03-14)
+ - by Michael Bretterklieber
+ - License: BSD
+ - http://pear.php.net/package/Crypt_CHAP
+
----------------------------------------------------------------
--
2.39.5
|