weekly release 3.8dev
[moodle.git] / lib / pear / Auth / RADIUS.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 /*
4 Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
11 1. Redistributions of source code must retain the above copyright
12    notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16 3. The names of the authors may not be used to endorse or promote products
17    derived from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 This code cannot simply be copied and put under the GNU Public License or
31 any other GPL-like (LGPL, GPL2) License.
33     $Id$
34 */
36 require_once('PEAR.php');
38 /**
39  * Client implementation of RADIUS. This are wrapper classes for
40  * the RADIUS PECL.
41  * Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
42  *
43  * @package Auth_RADIUS
44  * @author  Michael Bretterklieber <michael@bretterklieber.com>
45  * @access  public
46  * @version $Revision$
47  */
50 /**
51  * class Auth_RADIUS
52  *
53  * Abstract base class for RADIUS
54  *
55  * @package Auth_RADIUS
56  */
57 class Auth_RADIUS extends PEAR {
59     /**
60      * List of RADIUS servers.
61      * @var  array
62      * @see  addServer(), putServer()
63      */
64     var $_servers  = array();
66     /**
67      * Path to the configuration-file.
68      * @var  string
69      * @see  setConfigFile()
70      */
71     var $_configfile = null;
73     /**
74      * Resource.
75      * @var  resource
76      * @see  open(), close()
77      */
78     var $res = null;
80     /**
81      * Username for authentication and accounting requests.
82      * @var  string
83      */
84     var $username = null;
86     /**
87      * Password for plaintext-authentication (PAP).
88      * @var  string
89      */
90     var $password = null;
92     /**
93      * List of known attributes.
94      * @var  array
95      * @see  dumpAttributes(), getAttributes()
96      */
97     var $attributes = array();
99     /**
100      * List of raw attributes.
101      * @var  array
102      * @see  dumpAttributes(), getAttributes()
103      */
104     var $rawAttributes = array();
106     /**
107      * List of raw vendor specific attributes.
108      * @var  array
109      * @see  dumpAttributes(), getAttributes()
110      */
111     var $rawVendorAttributes = array();
113     /**
114      * Switch whether we should put standard attributes or not
115      * @var  bool
116      * @see  putStandardAttributes()
117      */
118     var $useStandardAttributes = true;
120     /**
121      * Constructor
122      *
123      * Loads the RADIUS PECL/extension
124      *
125      * @return void
126      */
127     public function __construct()
128     {
129         $this->loadExtension('radius');
130     }
132     /**
133      */
134     public function loadExtension($ext) {
135         if (extension_loaded($ext)) {
136             return true;
137         }
138         // if either returns true dl() will produce a FATAL error, stop that
139         if (
140             function_exists('dl') === false ||
141             ini_get('enable_dl') != 1 ||
142             ini_get('safe_mode') == 1
143         ) {
144             return false;
145         }
146         if (OS_WINDOWS) {
147             $suffix = '.dll';
148         } elseif (PHP_OS == 'HP-UX') {
149             $suffix = '.sl';
150         } elseif (PHP_OS == 'AIX') {
151             $suffix = '.a';
152         } elseif (PHP_OS == 'OSX') {
153             $suffix = '.bundle';
154         } else {
155             $suffix = '.so';
156         }
157         return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
158     }
160     /**
161      * Adds a RADIUS server to the list of servers for requests.
162      *
163      * At most 10 servers may be specified.     When multiple servers
164      * are given, they are tried in round-robin fashion until a
165      * valid response is received
166      *
167      * @param  string  $servername   Servername or IP-Address
168      * @param  integer $port         Portnumber
169      * @param  string  $sharedSecret Shared secret
170      * @param  integer $timeout      Timeout for each request
171      * @param  integer $maxtries     Max. retries for each request
172      * @return void
173      */
174     public function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
175     {
176         $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
177     }
179     /**
180      * Returns an error message, if an error occurred.
181      *
182      * @return string
183      */
184     public function getError()
185     {
186         return radius_strerror($this->res);
187     }
189     /**
190      * Sets the configuration-file.
191      *
192      * @param  string  $file Path to the configuration file
193      * @return void
194      */
195     public function setConfigfile($file)
196     {
197         $this->_configfile = $file;
198     }
200     /**
201      * Puts an attribute.
202      *
203      * @param  integer $attrib       Attribute-number
204      * @param  mixed   $port         Attribute-value
205      * @param  type    $type         Attribute-type
206      * @return bool  true on success, false on error
207      */
208     public function putAttribute($attrib, $value, $type = null)
209     {
210         if ($type == null) {
211             $type = gettype($value);
212         }
214         switch ($type) {
215             case 'integer':
216             case 'double':
217                 return radius_put_int($this->res, $attrib, $value);
219             case 'addr':
220                 return radius_put_addr($this->res, $attrib, $value);
222             case 'string':
223             default:
224                 return radius_put_attr($this->res, $attrib, $value);
225         }
227     }
229     /**
230      * Puts a vendor-specific attribute.
231      *
232      * @param  integer $vendor       Vendor (MSoft, Cisco, ...)
233      * @param  integer $attrib       Attribute-number
234      * @param  mixed   $port         Attribute-value
235      * @param  type    $type         Attribute-type
236      * @return bool  true on success, false on error
237      */
238     public function putVendorAttribute($vendor, $attrib, $value, $type = null)
239     {
241         if ($type == null) {
242             $type = gettype($value);
243         }
245         switch ($type) {
246             case 'integer':
247             case 'double':
248                 return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
250             case 'addr':
251                 return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
253             case 'string':
254             default:
255                 return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
256         }
258     }
260     /**
261      * Prints known attributes received from the server.
262      *
263      */
264     public function dumpAttributes()
265     {
266         foreach ($this->attributes as $name => $data) {
267             echo "$name:$data<br>\n";
268         }
269     }
271     /**
272      * Overwrite this.
273      */
274     public function open()
275     {
276     }
278     /**
279      * Overwrite this.
280      */
281     public function createRequest()
282     {
283     }
285     /**
286      * Puts standard attributes.
287      */
288     public function putStandardAttributes()
289     {
290         if (!$this->useStandardAttributes) {
291             return;
292         }
294         if (isset($_SERVER)) {
295             $var = $_SERVER;
296         } else {
297             $var = $GLOBALS['HTTP_SERVER_VARS'];
298         }
300         $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost');
301         $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
302         $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
303         $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
304         $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1');
305     }
307     /**
308      * Puts custom attributes.
309      */
310     public function putAuthAttributes()
311     {
312         if (isset($this->username)) {
313             $this->putAttribute(RADIUS_USER_NAME, $this->username);
314         }
315     }
317     /**
318      * Configures the radius library.
319      *
320      * @param  string  $servername   Servername or IP-Address
321      * @param  integer $port         Portnumber
322      * @param  string  $sharedSecret Shared secret
323      * @param  integer $timeout      Timeout for each request
324      * @param  integer $maxtries     Max. retries for each request
325      * @return bool  true on success, false on error
326      * @see addServer()
327      */
328     public function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
329     {
330         if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
331             return false;
332         }
333         return true;
334     }
336     /**
337      * Configures the radius library via external configurationfile
338      *
339      * @param  string  $servername   Servername or IP-Address
340      * @return bool  true on success, false on error
341      */
342     public function putConfigfile($file)
343     {
344         if (!radius_config($this->res, $file)) {
345             return false;
346         }
347         return true;
348     }
350     /**
351      * Initiates a RADIUS request.
352      *
353      * @return bool  true on success, false on errors
354      */
355     public function start()
356     {
357         if (!$this->open()) {
358             return false;
359         }
361         foreach ($this->_servers as $s) {
362             // Servername, port, sharedsecret, timeout, retries
363             if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
364                 return false;
365             }
366         }
368         if (!empty($this->_configfile)) {
369             if (!$this->putConfigfile($this->_configfile)) {
370                 return false;
371             }
372         }
374         $this->createRequest();
375         $this->putStandardAttributes();
376         $this->putAuthAttributes();
377         return true;
378     }
380     /**
381      * Sends a prepared RADIUS request and waits for a response
382      *
383      * @return mixed  true on success, false on reject, PEAR_Error on error
384      */
385     public function send()
386     {
387         $req = radius_send_request($this->res);
388         if (!$req) {
389             throw new Auth_RADIUS_Exception('Error sending request: ' . $this->getError());
390         }
392         switch($req) {
393             case RADIUS_ACCESS_ACCEPT:
394                 if (is_subclass_of($this, 'auth_radius_acct')) {
395                     throw new Auth_RADIUS_Exception('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
396                 }
397                 return true;
399             case RADIUS_ACCESS_REJECT:
400                 return false;
402             case RADIUS_ACCOUNTING_RESPONSE:
403                 if (is_subclass_of($this, 'auth_radius_pap')) {
404                     throw new Auth_RADIUS_Exception('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
405                 }
406                 return true;
408             default:
409                 throw new Auth_RADIUS_Exception("Unexpected return value: $req");
410         }
412     }
414     /**
415      * Reads all received attributes after sending the request.
416      *
417      * This methods stores known attributes in the property attributes,
418      * all attributes (including known attibutes) are stored in rawAttributes
419      * or rawVendorAttributes.
420      * NOTE: call this function also even if the request was rejected, because the
421      * Server returns usualy an errormessage
422      *
423      * @return bool   true on success, false on error
424      */
425     public function getAttributes()
426     {
428         while ($attrib = radius_get_attr($this->res)) {
430             if (!is_array($attrib)) {
431                 return false;
432             }
434             $attr = $attrib['attr'];
435             $data = $attrib['data'];
437             $this->rawAttributes[$attr] = $data;
439             switch ($attr) {
440                 case RADIUS_FRAMED_IP_ADDRESS:
441                     $this->attributes['framed_ip'] = radius_cvt_addr($data);
442                     break;
444                 case RADIUS_FRAMED_IP_NETMASK:
445                     $this->attributes['framed_mask'] = radius_cvt_addr($data);
446                     break;
448                 case RADIUS_FRAMED_MTU:
449                     $this->attributes['framed_mtu'] = radius_cvt_int($data);
450                     break;
452                 case RADIUS_FRAMED_COMPRESSION:
453                     $this->attributes['framed_compression'] = radius_cvt_int($data);
454                     break;
456                 case RADIUS_SESSION_TIMEOUT:
457                     $this->attributes['session_timeout'] = radius_cvt_int($data);
458                     break;
460                 case RADIUS_IDLE_TIMEOUT:
461                     $this->attributes['idle_timeout'] = radius_cvt_int($data);
462                     break;
464                 case RADIUS_SERVICE_TYPE:
465                     $this->attributes['service_type'] = radius_cvt_int($data);
466                     break;
468                 case RADIUS_CLASS:
469                     $this->attributes['class'] = radius_cvt_string($data);
470                     break;
472                 case RADIUS_FRAMED_PROTOCOL:
473                     $this->attributes['framed_protocol'] = radius_cvt_int($data);
474                     break;
476                 case RADIUS_FRAMED_ROUTING:
477                     $this->attributes['framed_routing'] = radius_cvt_int($data);
478                     break;
480                 case RADIUS_FILTER_ID:
481                     $this->attributes['filter_id'] = radius_cvt_string($data);
482                     break;
484                 case RADIUS_REPLY_MESSAGE:
485                     $this->attributes['reply_message'] = radius_cvt_string($data);
486                     break;
488                 case RADIUS_VENDOR_SPECIFIC:
489                     $attribv = radius_get_vendor_attr($data);
490                     if (!is_array($attribv)) {
491                         return false;
492                     }
494                     $vendor = $attribv['vendor'];
495                     $attrv = $attribv['attr'];
496                     $datav = $attribv['data'];
498                     $this->rawVendorAttributes[$vendor][$attrv] = $datav;
500                     if ($vendor == RADIUS_VENDOR_MICROSOFT) {
502                         switch ($attrv) {
503                             case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
504                                 $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
505                                 break;
507                             case RADIUS_MICROSOFT_MS_CHAP_ERROR:
508                                 $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
509                                 break;
511                             case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
512                                 $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
513                                 break;
515                             case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
516                                 $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
517                                 break;
519                             case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
520                                 $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
521                                 break;
523                             case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
524                                 $demangled = radius_demangle($this->res, $datav);
525                                 $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
526                                 $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
527                                 break;
529                             case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
530                                 $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
531                                 break;
533                             case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
534                                 $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
535                                 break;
537                             case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
538                                 $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
539                                 break;
540                         }
541                     }
542                     break;
544             }
545         }
547         return true;
548     }
550     /**
551      * Frees resources.
552      *
553      * Calling this method is always a good idea, because all security relevant
554      * attributes are filled with Nullbytes to leave nothing in the mem.
555      *
556      */
557     public function close()
558     {
559         if ($this->res != null) {
560             radius_close($this->res);
561             $this->res = null;
562         }
563         $this->username = str_repeat("\0", strlen($this->username));
564         $this->password = str_repeat("\0", strlen($this->password));
565     }
569 /**
570  * class Auth_RADIUS_PAP
571  *
572  * Class for authenticating using PAP (Plaintext)
573  *
574  * @package Auth_RADIUS
575  */
576 class Auth_RADIUS_PAP extends Auth_RADIUS
579     /**
580      * Constructor
581      *
582      * @param  string  $username   Username
583      * @param  string  $password   Password
584      * @return void
585      */
586     public function __construct($username = null, $password = null)
587     {
588         parent::__construct();
589         $this->username = $username;
590         $this->password = $password;
591     }
593     /**
594      * Creates a RADIUS resource
595      *
596      * Creates a RADIUS resource for authentication. This should be the first
597      * call before you make any other things with the library.
598      *
599      * @return bool   true on success, false on error
600      */
601     function open()
602     {
603         $this->res = radius_auth_open();
604         if (!$this->res) {
605             return false;
606         }
607         return true;
608     }
610     /**
611      * Creates an authentication request
612      *
613      * Creates an authentication request.
614      * You MUST call this method before you can put any attribute
615      *
616      * @return bool   true on success, false on error
617      */
618     function createRequest()
619     {
620         if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
621             return false;
622         }
623         return true;
624     }
626     /**
627      * Put authentication specific attributes
628      *
629      * @return void
630      */
631     function putAuthAttributes()
632     {
633         if (isset($this->username)) {
634             $this->putAttribute(RADIUS_USER_NAME, $this->username);
635         }
636         if (isset($this->password)) {
637             $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
638         }
639     }
643 /**
644  * class Auth_RADIUS_CHAP_MD5
645  *
646  * Class for authenticating using CHAP-MD5 see RFC1994.
647  * Instead og the plaintext password the challenge and
648  * the response are needed.
649  *
650  * @package Auth_RADIUS
651  */
652 class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
654     /**
655      * 8 Bytes binary challenge
656      * @var  string
657      */
658     var $challenge = null;
660     /**
661      * 16 Bytes MD5 response binary
662      * @var  string
663      */
664     var $response = null;
666     /**
667      * Id of the authentication request. Should incremented after every request.
668      * @var  integer
669      */
670     var $chapid = 1;
672     /**
673      * Constructor
674      *
675      * @param  string  $username   Username
676      * @param  string  $challenge  8 Bytes Challenge (binary)
677      * @param  integer $chapid     Requestnumber
678      * @return void
679      */
680     function __construct($username = null, $challenge = null, $chapid = 1)
681     {
682         parent::__construct();
683         $this->username = $username;
684         $this->challenge = $challenge;
685         $this->chapid = $chapid;
686     }
688     /**
689      * Put CHAP-MD5 specific attributes
690      *
691      * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
692      * and the response. The chapid is inserted in the first byte of the response.
693      *
694      * @return void
695      */
696     function putAuthAttributes()
697     {
698         if (isset($this->username)) {
699             $this->putAttribute(RADIUS_USER_NAME, $this->username);
700         }
701         if (isset($this->response)) {
702             $response = pack('C', $this->chapid) . $this->response;
703             $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
704         }
705         if (isset($this->challenge)) {
706             $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
707         }
708     }
710     /**
711      * Frees resources.
712      *
713      * Calling this method is always a good idea, because all security relevant
714      * attributes are filled with Nullbytes to leave nothing in the mem.
715      */
716     public function close()
717     {
718         parent::close();
719         $this->challenge =  str_repeat("\0", strlen($this->challenge));
720         $this->response =  str_repeat("\0", strlen($this->response));
721     }
725 /**
726  * class Auth_RADIUS_MSCHAPv1
727  *
728  * Class for authenticating using MS-CHAPv1 see RFC2433
729  *
730  * @package Auth_RADIUS
731  */
732 class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
734     /**
735      * LAN-Manager-Response
736      * @var  string
737      */
738     var $lmResponse = null;
740     /**
741      * Wether using deprecated LM-Responses or not.
742      * 0 = use LM-Response, 1 = use NT-Response
743      * @var  bool
744      */
745     var $flags = 1;
747     /**
748      * Put MS-CHAPv1 specific attributes
749      *
750      * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
751      * and the response. The response has this structure:
752      * struct rad_mschapvalue {
753      *   u_char ident;
754      *   u_char flags;
755      *   u_char lm_response[24];
756      *   u_char response[24];
757      * };
758      *
759      * @return void
760      */
761     function putAuthAttributes()
762     {
763         if (isset($this->username)) {
764             $this->putAttribute(RADIUS_USER_NAME, $this->username);
765         }
766         if (isset($this->response) || isset($this->lmResponse)) {
767             $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
768             $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
769             $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
770             $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
771         }
772         if (isset($this->challenge)) {
773             $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
774         }
775     }
778 /**
779  * class Auth_RADIUS_MSCHAPv2
780  *
781  * Class for authenticating using MS-CHAPv2 see RFC2759
782  *
783  * @package Auth_RADIUS
784  */
785 class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
787     /**
788      * 16 Bytes binary challenge
789      * @var  string
790      */
791     var $challenge = null;
793     /**
794      * 16 Bytes binary Peer Challenge
795      * @var  string
796      */
797     var $peerChallenge = null;
799     /**
800      * Put MS-CHAPv2 specific attributes
801      *
802      * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
803      * and the response. The response has this structure:
804      * struct rad_mschapv2value {
805      *   u_char ident;
806      *   u_char flags;
807      *   u_char pchallenge[16];
808      *   u_char reserved[8];
809      *   u_char response[24];
810      * };
811      * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
812      * @return void
813      */
814     function putAuthAttributes()
815     {
816         if (isset($this->username)) {
817             $this->putAttribute(RADIUS_USER_NAME, $this->username);
818         }
819         if (isset($this->response) && isset($this->peerChallenge)) {
820             // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
821             $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
822             $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
823         }
824         if (isset($this->challenge)) {
825             $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
826         }
827     }
829     /**
830      * Frees resources.
831      *
832      * Calling this method is always a good idea, because all security relevant
833      * attributes are filled with Nullbytes to leave nothing in the mem.
834      *
835      * @access public
836      */
837     function close()
838     {
839         parent::close();
840         $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
841     }
844 /**
845  * class Auth_RADIUS_Acct
846  *
847  * Class for RADIUS accounting
848  *
849  * @package Auth_RADIUS
850  */
851 class Auth_RADIUS_Acct extends Auth_RADIUS
853     /**
854      * Defines where the Authentication was made, possible values are:
855      * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
856      * @var  integer
857      */
858     var $authentic = null;
860     /**
861      * Defines the type of the accounting request, on of:
862      * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
863      * @var  integer
864      */
865     var $status_type = null;
867     /**
868      * The time the user was logged in in seconds
869      * @var  integer
870      */
871     var $session_time = null;
873     /**
874      * A uniq identifier for the session of the user, maybe the PHP-Session-Id
875      * @var  string
876      */
877     var $session_id = null;
879     /**
880      * Constructor
881      *
882      * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
883      * @return void
884      */
885     function __construct()
886     {
887         parent::__construct();
889         if (isset($_SERVER)) {
890             $var = $_SERVER;
891         } else {
892             $var = $GLOBALS['HTTP_SERVER_VARS'];
893         }
895         $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
896     }
898     /**
899      * Creates a RADIUS resource
900      *
901      * Creates a RADIUS resource for accounting. This should be the first
902      * call before you make any other things with the library.
903      *
904      * @return bool   true on success, false on error
905      */
906     function open()
907     {
908         $this->res = radius_acct_open();
909         if (!$this->res) {
910             return false;
911         }
912         return true;
913     }
915     /**
916      * Creates an accounting request
917      *
918      * Creates an accounting request.
919      * You MUST call this method before you can put any attribute.
920      *
921      * @return bool   true on success, false on error
922      */
923     function createRequest()
924     {
925         if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
926             return false;
927         }
928         return true;
929     }
931     /**
932      * Put attributes for accounting.
933      *
934      * Here we put some accounting values. There many more attributes for accounting,
935      * but for web-applications only certain attributes make sense.
936      * @return void
937      */
938     function putAuthAttributes()
939     {
940         $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
941         $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
942         if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
943             $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
944         }
945         if (isset($this->authentic)) {
946             $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
947         }
949     }
953 /**
954  * class Auth_RADIUS_Acct_Start
955  *
956  * Class for RADIUS accounting. Its usualy used, after the user has logged in.
957  *
958  * @package Auth_RADIUS
959  */
960 class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
962     /**
963      * Defines the type of the accounting request.
964      * It is set to RADIUS_START by default in this class.
965      * @var  integer
966      */
967     var $status_type = RADIUS_START;
970 /**
971  * class Auth_RADIUS_Acct_Start
972  *
973  * Class for RADIUS accounting. Its usualy used, after the user has logged out.
974  *
975  * @package Auth_RADIUS
976  */
977 class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
979     /**
980      * Defines the type of the accounting request.
981      * It is set to RADIUS_STOP by default in this class.
982      * @var  integer
983      */
984     var $status_type = RADIUS_STOP;
987 if (!defined('RADIUS_UPDATE')) {
988     define('RADIUS_UPDATE', 3);
991 /**
992  * class Auth_RADIUS_Acct_Update
993  *
994  * Class for interim RADIUS accounting updates.
995  *
996  * @package Auth_RADIUS
997  */
998 class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1000     /**
1001      * Defines the type of the accounting request.
1002      * It is set to RADIUS_UPDATE by default in this class.
1003      * @var  integer
1004      */
1005     var $status_type = RADIUS_UPDATE;
1008 class Auth_RADIUS_Exception extends Exception {}