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