weekly release 3.8dev
[moodle.git] / lib / pear / Auth / RADIUS.php
CommitLineData
3b8c2482 1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3/*
4Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
5All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions
9are met:
10
111. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
132. 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.
163. The names of the authors may not be used to endorse or promote products
17 derived from this software without specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30This code cannot simply be copied and put under the GNU Public License or
31any other GPL-like (LGPL, GPL2) License.
32
33 $Id$
34*/
35
112117c0 36require_once('PEAR.php');
3b8c2482 37
38/**
112117c0
MN
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 */
3b8c2482 48
3b8c2482 49
50/**
51 * class Auth_RADIUS
52 *
53 * Abstract base class for RADIUS
54 *
55 * @package Auth_RADIUS
56 */
57class Auth_RADIUS extends PEAR {
58
59 /**
60 * List of RADIUS servers.
61 * @var array
62 * @see addServer(), putServer()
63 */
64 var $_servers = array();
65
66 /**
67 * Path to the configuration-file.
68 * @var string
69 * @see setConfigFile()
70 */
71 var $_configfile = null;
72
73 /**
74 * Resource.
75 * @var resource
76 * @see open(), close()
77 */
78 var $res = null;
79
80 /**
81 * Username for authentication and accounting requests.
82 * @var string
83 */
84 var $username = null;
85
86 /**
87 * Password for plaintext-authentication (PAP).
88 * @var string
89 */
90 var $password = null;
91
92 /**
93 * List of known attributes.
94 * @var array
95 * @see dumpAttributes(), getAttributes()
96 */
97 var $attributes = array();
98
99 /**
100 * List of raw attributes.
101 * @var array
102 * @see dumpAttributes(), getAttributes()
103 */
104 var $rawAttributes = array();
105
106 /**
107 * List of raw vendor specific attributes.
108 * @var array
109 * @see dumpAttributes(), getAttributes()
110 */
111 var $rawVendorAttributes = array();
112
113 /**
114 * Switch whether we should put standard attributes or not
115 * @var bool
116 * @see putStandardAttributes()
117 */
118 var $useStandardAttributes = true;
119
120 /**
121 * Constructor
122 *
123 * Loads the RADIUS PECL/extension
124 *
125 * @return void
126 */
112117c0 127 public function __construct()
3b8c2482 128 {
112117c0
MN
129 $this->loadExtension('radius');
130 }
131
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);
3b8c2482 158 }
159
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 *
3b8c2482 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 */
112117c0 174 public function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
3b8c2482 175 {
176 $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
177 }
178
179 /**
180 * Returns an error message, if an error occurred.
181 *
3b8c2482 182 * @return string
183 */
112117c0 184 public function getError()
3b8c2482 185 {
186 return radius_strerror($this->res);
187 }
188
189 /**
190 * Sets the configuration-file.
191 *
3b8c2482 192 * @param string $file Path to the configuration file
193 * @return void
194 */
112117c0 195 public function setConfigfile($file)
3b8c2482 196 {
197 $this->_configfile = $file;
198 }
199
200 /**
201 * Puts an attribute.
202 *
3b8c2482 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 */
112117c0 208 public function putAttribute($attrib, $value, $type = null)
3b8c2482 209 {
210 if ($type == null) {
211 $type = gettype($value);
212 }
213
214 switch ($type) {
112117c0
MN
215 case 'integer':
216 case 'double':
217 return radius_put_int($this->res, $attrib, $value);
3b8c2482 218
112117c0
MN
219 case 'addr':
220 return radius_put_addr($this->res, $attrib, $value);
3b8c2482 221
112117c0
MN
222 case 'string':
223 default:
224 return radius_put_attr($this->res, $attrib, $value);
3b8c2482 225 }
226
227 }
228
229 /**
230 * Puts a vendor-specific attribute.
231 *
3b8c2482 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 */
112117c0 238 public function putVendorAttribute($vendor, $attrib, $value, $type = null)
3b8c2482 239 {
240
241 if ($type == null) {
242 $type = gettype($value);
243 }
244
245 switch ($type) {
112117c0
MN
246 case 'integer':
247 case 'double':
248 return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
3b8c2482 249
112117c0
MN
250 case 'addr':
251 return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
3b8c2482 252
112117c0
MN
253 case 'string':
254 default:
255 return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
3b8c2482 256 }
257
258 }
259
260 /**
261 * Prints known attributes received from the server.
262 *
3b8c2482 263 */
112117c0 264 public function dumpAttributes()
3b8c2482 265 {
266 foreach ($this->attributes as $name => $data) {
267 echo "$name:$data<br>\n";
268 }
269 }
270
271 /**
272 * Overwrite this.
3b8c2482 273 */
112117c0 274 public function open()
3b8c2482 275 {
276 }
277
278 /**
279 * Overwrite this.
3b8c2482 280 */
112117c0 281 public function createRequest()
3b8c2482 282 {
283 }
284
285 /**
286 * Puts standard attributes.
3b8c2482 287 */
112117c0 288 public function putStandardAttributes()
3b8c2482 289 {
112117c0
MN
290 if (!$this->useStandardAttributes) {
291 return;
292 }
3b8c2482 293
294 if (isset($_SERVER)) {
112117c0 295 $var = $_SERVER;
3b8c2482 296 } else {
112117c0 297 $var = $GLOBALS['HTTP_SERVER_VARS'];
3b8c2482 298 }
299
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 }
306
307 /**
308 * Puts custom attributes.
3b8c2482 309 */
112117c0 310 public function putAuthAttributes()
3b8c2482 311 {
312 if (isset($this->username)) {
313 $this->putAttribute(RADIUS_USER_NAME, $this->username);
314 }
315 }
316
317 /**
318 * Configures the radius library.
319 *
3b8c2482 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 */
112117c0 328 public function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
3b8c2482 329 {
330 if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
331 return false;
332 }
333 return true;
334 }
335
336 /**
337 * Configures the radius library via external configurationfile
338 *
3b8c2482 339 * @param string $servername Servername or IP-Address
340 * @return bool true on success, false on error
341 */
112117c0 342 public function putConfigfile($file)
3b8c2482 343 {
344 if (!radius_config($this->res, $file)) {
345 return false;
346 }
347 return true;
348 }
349
350 /**
351 * Initiates a RADIUS request.
352 *
3b8c2482 353 * @return bool true on success, false on errors
354 */
112117c0 355 public function start()
3b8c2482 356 {
357 if (!$this->open()) {
358 return false;
359 }
360
361 foreach ($this->_servers as $s) {
112117c0 362 // Servername, port, sharedsecret, timeout, retries
3b8c2482 363 if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
364 return false;
365 }
366 }
367
368 if (!empty($this->_configfile)) {
369 if (!$this->putConfigfile($this->_configfile)) {
370 return false;
371 }
372 }
373
374 $this->createRequest();
375 $this->putStandardAttributes();
376 $this->putAuthAttributes();
377 return true;
378 }
379
380 /**
381 * Sends a prepared RADIUS request and waits for a response
382 *
3b8c2482 383 * @return mixed true on success, false on reject, PEAR_Error on error
384 */
112117c0 385 public function send()
3b8c2482 386 {
387 $req = radius_send_request($this->res);
388 if (!$req) {
112117c0 389 throw new Auth_RADIUS_Exception('Error sending request: ' . $this->getError());
3b8c2482 390 }
391
392 switch($req) {
112117c0
MN
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;
3b8c2482 398
112117c0
MN
399 case RADIUS_ACCESS_REJECT:
400 return false;
3b8c2482 401
112117c0
MN
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;
3b8c2482 407
112117c0
MN
408 default:
409 throw new Auth_RADIUS_Exception("Unexpected return value: $req");
3b8c2482 410 }
411
412 }
413
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 *
3b8c2482 423 * @return bool true on success, false on error
424 */
112117c0 425 public function getAttributes()
3b8c2482 426 {
427
428 while ($attrib = radius_get_attr($this->res)) {
429
430 if (!is_array($attrib)) {
431 return false;
432 }
433
434 $attr = $attrib['attr'];
435 $data = $attrib['data'];
436
437 $this->rawAttributes[$attr] = $data;
438
439 switch ($attr) {
112117c0
MN
440 case RADIUS_FRAMED_IP_ADDRESS:
441 $this->attributes['framed_ip'] = radius_cvt_addr($data);
442 break;
443
444 case RADIUS_FRAMED_IP_NETMASK:
445 $this->attributes['framed_mask'] = radius_cvt_addr($data);
446 break;
447
448 case RADIUS_FRAMED_MTU:
449 $this->attributes['framed_mtu'] = radius_cvt_int($data);
450 break;
451
452 case RADIUS_FRAMED_COMPRESSION:
453 $this->attributes['framed_compression'] = radius_cvt_int($data);
454 break;
455
456 case RADIUS_SESSION_TIMEOUT:
457 $this->attributes['session_timeout'] = radius_cvt_int($data);
458 break;
459
460 case RADIUS_IDLE_TIMEOUT:
461 $this->attributes['idle_timeout'] = radius_cvt_int($data);
462 break;
463
464 case RADIUS_SERVICE_TYPE:
465 $this->attributes['service_type'] = radius_cvt_int($data);
466 break;
467
468 case RADIUS_CLASS:
469 $this->attributes['class'] = radius_cvt_string($data);
470 break;
471
472 case RADIUS_FRAMED_PROTOCOL:
473 $this->attributes['framed_protocol'] = radius_cvt_int($data);
474 break;
475
476 case RADIUS_FRAMED_ROUTING:
477 $this->attributes['framed_routing'] = radius_cvt_int($data);
478 break;
479
480 case RADIUS_FILTER_ID:
481 $this->attributes['filter_id'] = radius_cvt_string($data);
482 break;
483
484 case RADIUS_REPLY_MESSAGE:
485 $this->attributes['reply_message'] = radius_cvt_string($data);
486 break;
487
488 case RADIUS_VENDOR_SPECIFIC:
489 $attribv = radius_get_vendor_attr($data);
490 if (!is_array($attribv)) {
491 return false;
492 }
3b8c2482 493
112117c0
MN
494 $vendor = $attribv['vendor'];
495 $attrv = $attribv['attr'];
496 $datav = $attribv['data'];
3b8c2482 497
112117c0 498 $this->rawVendorAttributes[$vendor][$attrv] = $datav;
3b8c2482 499
112117c0 500 if ($vendor == RADIUS_VENDOR_MICROSOFT) {
3b8c2482 501
112117c0
MN
502 switch ($attrv) {
503 case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
504 $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
505 break;
3b8c2482 506
112117c0
MN
507 case RADIUS_MICROSOFT_MS_CHAP_ERROR:
508 $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
509 break;
3b8c2482 510
112117c0
MN
511 case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
512 $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
513 break;
3b8c2482 514
112117c0
MN
515 case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
516 $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
517 break;
3b8c2482 518
112117c0
MN
519 case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
520 $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
521 break;
3b8c2482 522
112117c0
MN
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;
3b8c2482 528
112117c0
MN
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;
3b8c2482 532
112117c0
MN
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;
3b8c2482 536
112117c0
MN
537 case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
538 $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
539 break;
540 }
3b8c2482 541 }
112117c0 542 break;
3b8c2482 543
544 }
545 }
546
547 return true;
548 }
549
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 *
3b8c2482 556 */
112117c0 557 public function close()
3b8c2482 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 }
566
567}
568
569/**
570 * class Auth_RADIUS_PAP
571 *
572 * Class for authenticating using PAP (Plaintext)
573 *
574 * @package Auth_RADIUS
575 */
576class Auth_RADIUS_PAP extends Auth_RADIUS
577{
578
579 /**
580 * Constructor
581 *
582 * @param string $username Username
583 * @param string $password Password
584 * @return void
585 */
112117c0 586 public function __construct($username = null, $password = null)
3b8c2482 587 {
112117c0 588 parent::__construct();
3b8c2482 589 $this->username = $username;
590 $this->password = $password;
591 }
592
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 }
609
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 }
625
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 }
640
641}
642
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 */
652class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
653{
654 /**
655 * 8 Bytes binary challenge
656 * @var string
657 */
658 var $challenge = null;
659
660 /**
661 * 16 Bytes MD5 response binary
662 * @var string
663 */
664 var $response = null;
665
666 /**
667 * Id of the authentication request. Should incremented after every request.
668 * @var integer
669 */
670 var $chapid = 1;
671
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 */
112117c0 680 function __construct($username = null, $challenge = null, $chapid = 1)
3b8c2482 681 {
112117c0 682 parent::__construct();
3b8c2482 683 $this->username = $username;
684 $this->challenge = $challenge;
685 $this->chapid = $chapid;
686 }
687
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 }
709
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.
3b8c2482 715 */
112117c0 716 public function close()
3b8c2482 717 {
112117c0 718 parent::close();
3b8c2482 719 $this->challenge = str_repeat("\0", strlen($this->challenge));
720 $this->response = str_repeat("\0", strlen($this->response));
721 }
722
723}
724
725/**
726 * class Auth_RADIUS_MSCHAPv1
727 *
728 * Class for authenticating using MS-CHAPv1 see RFC2433
729 *
730 * @package Auth_RADIUS
731 */
732class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
733{
734 /**
735 * LAN-Manager-Response
736 * @var string
737 */
738 var $lmResponse = null;
739
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;
746
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 }
776}
777
778/**
779 * class Auth_RADIUS_MSCHAPv2
780 *
781 * Class for authenticating using MS-CHAPv2 see RFC2759
782 *
783 * @package Auth_RADIUS
784 */
785class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
786{
787 /**
788 * 16 Bytes binary challenge
789 * @var string
790 */
791 var $challenge = null;
792
793 /**
794 * 16 Bytes binary Peer Challenge
795 * @var string
796 */
797 var $peerChallenge = null;
798
112117c0 799 /**
3b8c2482 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 }
828
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 {
112117c0 839 parent::close();
3b8c2482 840 $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
841 }
842}
843
844/**
845 * class Auth_RADIUS_Acct
846 *
847 * Class for RADIUS accounting
848 *
849 * @package Auth_RADIUS
850 */
851class Auth_RADIUS_Acct extends Auth_RADIUS
852{
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;
859
112117c0 860 /**
3b8c2482 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;
866
112117c0 867 /**
3b8c2482 868 * The time the user was logged in in seconds
869 * @var integer
870 */
871 var $session_time = null;
872
112117c0 873 /**
3b8c2482 874 * A uniq identifier for the session of the user, maybe the PHP-Session-Id
875 * @var string
876 */
877 var $session_id = null;
878
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 */
112117c0 885 function __construct()
3b8c2482 886 {
112117c0 887 parent::__construct();
3b8c2482 888
889 if (isset($_SERVER)) {
112117c0 890 $var = $_SERVER;
3b8c2482 891 } else {
112117c0 892 $var = $GLOBALS['HTTP_SERVER_VARS'];
3b8c2482 893 }
894
895 $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
896 }
897
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 }
914
112117c0 915 /**
3b8c2482 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 }
930
112117c0 931 /**
3b8c2482 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 }
948
949 }
950
951}
952
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 */
960class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
961{
112117c0 962 /**
3b8c2482 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;
968}
969
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 */
977class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
978{
112117c0 979 /**
3b8c2482 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;
985}
986
112117c0 987if (!defined('RADIUS_UPDATE')) {
3b8c2482 988 define('RADIUS_UPDATE', 3);
112117c0 989}
3b8c2482 990
991/**
992 * class Auth_RADIUS_Acct_Update
993 *
994 * Class for interim RADIUS accounting updates.
995 *
996 * @package Auth_RADIUS
997 */
998class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
999{
112117c0 1000 /**
3b8c2482 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;
1006}
1007
112117c0 1008class Auth_RADIUS_Exception extends Exception {}