|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 00003 /* 00004 Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com> 00005 All rights reserved. 00006 00007 Redistribution and use in source and binary forms, with or without 00008 modification, are permitted provided that the following conditions 00009 are met: 00010 00011 1. Redistributions of source code must retain the above copyright 00012 notice, this list of conditions and the following disclaimer. 00013 2. Redistributions in binary form must reproduce the above copyright 00014 notice, this list of conditions and the following disclaimer in the 00015 documentation and/or other materials provided with the distribution. 00016 3. The names of the authors may not be used to endorse or promote products 00017 derived from this software without specific prior written permission. 00018 00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00020 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00022 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00023 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00024 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00026 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00028 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 00030 This code cannot simply be copied and put under the GNU Public License or 00031 any other GPL-like (LGPL, GPL2) License. 00032 00033 $Id: RADIUS.php,v 1.2 2010/12/14 17:36:06 moodlerobot Exp $ 00034 */ 00035 00036 require_once 'PEAR.php'; 00037 00049 PEAR::loadExtension('radius'); 00050 00058 class Auth_RADIUS extends PEAR { 00059 00065 var $_servers = array(); 00066 00072 var $_configfile = null; 00073 00079 var $res = null; 00080 00085 var $username = null; 00086 00091 var $password = null; 00092 00098 var $attributes = array(); 00099 00105 var $rawAttributes = array(); 00106 00112 var $rawVendorAttributes = array(); 00113 00119 var $useStandardAttributes = true; 00120 00128 function Auth_RADIUS() 00129 { 00130 $this->PEAR(); 00131 } 00132 00148 function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3) 00149 { 00150 $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries); 00151 } 00152 00159 function getError() 00160 { 00161 return radius_strerror($this->res); 00162 } 00163 00171 function setConfigfile($file) 00172 { 00173 $this->_configfile = $file; 00174 } 00175 00185 function putAttribute($attrib, $value, $type = null) 00186 { 00187 if ($type == null) { 00188 $type = gettype($value); 00189 } 00190 00191 switch ($type) { 00192 case 'integer': 00193 case 'double': 00194 return radius_put_int($this->res, $attrib, $value); 00195 00196 case 'addr': 00197 return radius_put_addr($this->res, $attrib, $value); 00198 00199 case 'string': 00200 default: 00201 return radius_put_attr($this->res, $attrib, $value); 00202 } 00203 00204 } 00205 00216 function putVendorAttribute($vendor, $attrib, $value, $type = null) 00217 { 00218 00219 if ($type == null) { 00220 $type = gettype($value); 00221 } 00222 00223 switch ($type) { 00224 case 'integer': 00225 case 'double': 00226 return radius_put_vendor_int($this->res, $vendor, $attrib, $value); 00227 00228 case 'addr': 00229 return radius_put_vendor_addr($this->res, $vendor,$attrib, $value); 00230 00231 case 'string': 00232 default: 00233 return radius_put_vendor_attr($this->res, $vendor, $attrib, $value); 00234 } 00235 00236 } 00237 00243 function dumpAttributes() 00244 { 00245 foreach ($this->attributes as $name => $data) { 00246 echo "$name:$data<br>\n"; 00247 } 00248 } 00249 00255 function open() 00256 { 00257 } 00258 00264 function createRequest() 00265 { 00266 } 00267 00273 function putStandardAttributes() 00274 { 00275 if (!$this->useStandardAttributes) 00276 return; 00277 00278 if (isset($_SERVER)) { 00279 $var = &$_SERVER; 00280 } else { 00281 $var = &$GLOBALS['HTTP_SERVER_VARS']; 00282 } 00283 00284 $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost'); 00285 $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL); 00286 $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED); 00287 $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP); 00288 $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1'); 00289 } 00290 00296 function putAuthAttributes() 00297 { 00298 if (isset($this->username)) { 00299 $this->putAttribute(RADIUS_USER_NAME, $this->username); 00300 } 00301 } 00302 00315 function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3) 00316 { 00317 if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) { 00318 return false; 00319 } 00320 return true; 00321 } 00322 00330 function putConfigfile($file) 00331 { 00332 if (!radius_config($this->res, $file)) { 00333 return false; 00334 } 00335 return true; 00336 } 00337 00344 function start() 00345 { 00346 if (!$this->open()) { 00347 return false; 00348 } 00349 00350 foreach ($this->_servers as $s) { 00351 // Servername, port, sharedsecret, timeout, retries 00352 if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) { 00353 return false; 00354 } 00355 } 00356 00357 if (!empty($this->_configfile)) { 00358 if (!$this->putConfigfile($this->_configfile)) { 00359 return false; 00360 } 00361 } 00362 00363 $this->createRequest(); 00364 $this->putStandardAttributes(); 00365 $this->putAuthAttributes(); 00366 return true; 00367 } 00368 00375 function send() 00376 { 00377 $req = radius_send_request($this->res); 00378 if (!$req) { 00379 return $this->raiseError('Error sending request: ' . $this->getError()); 00380 } 00381 00382 switch($req) { 00383 case RADIUS_ACCESS_ACCEPT: 00384 if (is_subclass_of($this, 'auth_radius_acct')) { 00385 return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting'); 00386 } 00387 return true; 00388 00389 case RADIUS_ACCESS_REJECT: 00390 return false; 00391 00392 case RADIUS_ACCOUNTING_RESPONSE: 00393 if (is_subclass_of($this, 'auth_radius_pap')) { 00394 return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication'); 00395 } 00396 return true; 00397 00398 default: 00399 return $this->raiseError("Unexpected return value: $req"); 00400 } 00401 00402 } 00403 00416 function getAttributes() 00417 { 00418 00419 while ($attrib = radius_get_attr($this->res)) { 00420 00421 if (!is_array($attrib)) { 00422 return false; 00423 } 00424 00425 $attr = $attrib['attr']; 00426 $data = $attrib['data']; 00427 00428 $this->rawAttributes[$attr] = $data; 00429 00430 switch ($attr) { 00431 case RADIUS_FRAMED_IP_ADDRESS: 00432 $this->attributes['framed_ip'] = radius_cvt_addr($data); 00433 break; 00434 00435 case RADIUS_FRAMED_IP_NETMASK: 00436 $this->attributes['framed_mask'] = radius_cvt_addr($data); 00437 break; 00438 00439 case RADIUS_FRAMED_MTU: 00440 $this->attributes['framed_mtu'] = radius_cvt_int($data); 00441 break; 00442 00443 case RADIUS_FRAMED_COMPRESSION: 00444 $this->attributes['framed_compression'] = radius_cvt_int($data); 00445 break; 00446 00447 case RADIUS_SESSION_TIMEOUT: 00448 $this->attributes['session_timeout'] = radius_cvt_int($data); 00449 break; 00450 00451 case RADIUS_IDLE_TIMEOUT: 00452 $this->attributes['idle_timeout'] = radius_cvt_int($data); 00453 break; 00454 00455 case RADIUS_SERVICE_TYPE: 00456 $this->attributes['service_type'] = radius_cvt_int($data); 00457 break; 00458 00459 case RADIUS_CLASS: 00460 $this->attributes['class'] = radius_cvt_string($data); 00461 break; 00462 00463 case RADIUS_FRAMED_PROTOCOL: 00464 $this->attributes['framed_protocol'] = radius_cvt_int($data); 00465 break; 00466 00467 case RADIUS_FRAMED_ROUTING: 00468 $this->attributes['framed_routing'] = radius_cvt_int($data); 00469 break; 00470 00471 case RADIUS_FILTER_ID: 00472 $this->attributes['filter_id'] = radius_cvt_string($data); 00473 break; 00474 00475 case RADIUS_REPLY_MESSAGE: 00476 $this->attributes['reply_message'] = radius_cvt_string($data); 00477 break; 00478 00479 case RADIUS_VENDOR_SPECIFIC: 00480 $attribv = radius_get_vendor_attr($data); 00481 if (!is_array($attribv)) { 00482 return false; 00483 } 00484 00485 $vendor = $attribv['vendor']; 00486 $attrv = $attribv['attr']; 00487 $datav = $attribv['data']; 00488 00489 $this->rawVendorAttributes[$vendor][$attrv] = $datav; 00490 00491 if ($vendor == RADIUS_VENDOR_MICROSOFT) { 00492 00493 switch ($attrv) { 00494 case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS: 00495 $this->attributes['ms_chap2_success'] = radius_cvt_string($datav); 00496 break; 00497 00498 case RADIUS_MICROSOFT_MS_CHAP_ERROR: 00499 $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1)); 00500 break; 00501 00502 case RADIUS_MICROSOFT_MS_CHAP_DOMAIN: 00503 $this->attributes['ms_chap_domain'] = radius_cvt_string($datav); 00504 break; 00505 00506 case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY: 00507 $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav); 00508 break; 00509 00510 case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES: 00511 $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav); 00512 break; 00513 00514 case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS: 00515 $demangled = radius_demangle($this->res, $datav); 00516 $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8); 00517 $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN); 00518 break; 00519 00520 case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY: 00521 $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav); 00522 break; 00523 00524 case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY: 00525 $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav); 00526 break; 00527 00528 case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER: 00529 $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav); 00530 break; 00531 } 00532 } 00533 break; 00534 00535 } 00536 } 00537 00538 return true; 00539 } 00540 00549 function close() 00550 { 00551 if ($this->res != null) { 00552 radius_close($this->res); 00553 $this->res = null; 00554 } 00555 $this->username = str_repeat("\0", strlen($this->username)); 00556 $this->password = str_repeat("\0", strlen($this->password)); 00557 } 00558 00559 } 00560 00568 class Auth_RADIUS_PAP extends Auth_RADIUS 00569 { 00570 00578 function Auth_RADIUS_PAP($username = null, $password = null) 00579 { 00580 $this->Auth_RADIUS(); 00581 $this->username = $username; 00582 $this->password = $password; 00583 } 00584 00593 function open() 00594 { 00595 $this->res = radius_auth_open(); 00596 if (!$this->res) { 00597 return false; 00598 } 00599 return true; 00600 } 00601 00610 function createRequest() 00611 { 00612 if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) { 00613 return false; 00614 } 00615 return true; 00616 } 00617 00623 function putAuthAttributes() 00624 { 00625 if (isset($this->username)) { 00626 $this->putAttribute(RADIUS_USER_NAME, $this->username); 00627 } 00628 if (isset($this->password)) { 00629 $this->putAttribute(RADIUS_USER_PASSWORD, $this->password); 00630 } 00631 } 00632 00633 } 00634 00644 class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP 00645 { 00650 var $challenge = null; 00651 00656 var $response = null; 00657 00662 var $chapid = 1; 00663 00672 function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1) 00673 { 00674 $this->Auth_RADIUS_PAP(); 00675 $this->username = $username; 00676 $this->challenge = $challenge; 00677 $this->chapid = $chapid; 00678 } 00679 00688 function putAuthAttributes() 00689 { 00690 if (isset($this->username)) { 00691 $this->putAttribute(RADIUS_USER_NAME, $this->username); 00692 } 00693 if (isset($this->response)) { 00694 $response = pack('C', $this->chapid) . $this->response; 00695 $this->putAttribute(RADIUS_CHAP_PASSWORD, $response); 00696 } 00697 if (isset($this->challenge)) { 00698 $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge); 00699 } 00700 } 00701 00710 function close() 00711 { 00712 Auth_RADIUS_PAP::close(); 00713 $this->challenge = str_repeat("\0", strlen($this->challenge)); 00714 $this->response = str_repeat("\0", strlen($this->response)); 00715 } 00716 00717 } 00718 00726 class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 00727 { 00732 var $lmResponse = null; 00733 00739 var $flags = 1; 00740 00755 function putAuthAttributes() 00756 { 00757 if (isset($this->username)) { 00758 $this->putAttribute(RADIUS_USER_NAME, $this->username); 00759 } 00760 if (isset($this->response) || isset($this->lmResponse)) { 00761 $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24); 00762 $ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24); 00763 $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp; 00764 $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp); 00765 } 00766 if (isset($this->challenge)) { 00767 $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge); 00768 } 00769 } 00770 } 00771 00779 class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 00780 { 00785 var $challenge = null; 00786 00791 var $peerChallenge = null; 00792 00808 function putAuthAttributes() 00809 { 00810 if (isset($this->username)) { 00811 $this->putAttribute(RADIUS_USER_NAME, $this->username); 00812 } 00813 if (isset($this->response) && isset($this->peerChallenge)) { 00814 // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response 00815 $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response); 00816 $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp); 00817 } 00818 if (isset($this->challenge)) { 00819 $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge); 00820 } 00821 } 00822 00831 function close() 00832 { 00833 Auth_RADIUS_MSCHAPv1::close(); 00834 $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge)); 00835 } 00836 } 00837 00845 class Auth_RADIUS_Acct extends Auth_RADIUS 00846 { 00852 var $authentic = null; 00853 00859 var $status_type = null; 00860 00865 var $session_time = null; 00866 00871 var $session_id = null; 00872 00879 function Auth_RADIUS_Acct() 00880 { 00881 $this->Auth_RADIUS(); 00882 00883 if (isset($_SERVER)) { 00884 $var = &$_SERVER; 00885 } else { 00886 $var = &$GLOBALS['HTTP_SERVER_VARS']; 00887 } 00888 00889 $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user()); 00890 } 00891 00900 function open() 00901 { 00902 $this->res = radius_acct_open(); 00903 if (!$this->res) { 00904 return false; 00905 } 00906 return true; 00907 } 00908 00917 function createRequest() 00918 { 00919 if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) { 00920 return false; 00921 } 00922 return true; 00923 } 00924 00932 function putAuthAttributes() 00933 { 00934 $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id); 00935 $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type); 00936 if (isset($this->session_time) && $this->status_type == RADIUS_STOP) { 00937 $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time); 00938 } 00939 if (isset($this->authentic)) { 00940 $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic); 00941 } 00942 00943 } 00944 00945 } 00946 00954 class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct 00955 { 00961 var $status_type = RADIUS_START; 00962 } 00963 00971 class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct 00972 { 00978 var $status_type = RADIUS_STOP; 00979 } 00980 00981 if (!defined('RADIUS_UPDATE')) 00982 define('RADIUS_UPDATE', 3); 00983 00991 class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct 00992 { 00998 var $status_type = RADIUS_UPDATE; 00999 } 01000 01001 ?>