ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
RADIUS.php
Go to the documentation of this file.
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 /*
4 Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 
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.
18 
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.
29 
30 This code cannot simply be copied and put under the GNU Public License or
31 any other GPL-like (LGPL, GPL2) License.
32 
33  $Id: RADIUS.php,v 1.8 2007/03/27 17:28:44 mbretter Exp $
34 */
35 
36 require_once 'PEAR.php';
37 
49 PEAR::loadExtension('radius');
50 
58 class Auth_RADIUS extends PEAR {
59 
65  var $_servers = array();
66 
72  var $_configfile = null;
73 
79  var $res = null;
80 
85  var $username = null;
86 
91  var $password = null;
92 
98  var $attributes = array();
99 
105  var $rawAttributes = array();
106 
112  var $rawVendorAttributes = array();
113 
120 
128  function Auth_RADIUS()
129  {
130  $this->PEAR();
131  }
132 
148  function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
149  {
150  $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
151  }
152 
159  function getError()
160  {
161  return radius_strerror($this->res);
162  }
163 
171  function setConfigfile($file)
172  {
173  $this->_configfile = $file;
174  }
175 
185  function putAttribute($attrib, $value, $type = null)
186  {
187  if ($type == null) {
188  $type = gettype($value);
189  }
190 
191  switch ($type) {
192  case 'integer':
193  case 'double':
194  return radius_put_int($this->res, $attrib, $value);
195 
196  case 'addr':
197  return radius_put_addr($this->res, $attrib, $value);
198 
199  case 'string':
200  default:
201  return radius_put_attr($this->res, $attrib, $value);
202  }
203 
204  }
205 
216  function putVendorAttribute($vendor, $attrib, $value, $type = null)
217  {
218 
219  if ($type == null) {
220  $type = gettype($value);
221  }
222 
223  switch ($type) {
224  case 'integer':
225  case 'double':
226  return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
227 
228  case 'addr':
229  return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
230 
231  case 'string':
232  default:
233  return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
234  }
235 
236  }
237 
243  function dumpAttributes()
244  {
245  foreach ($this->attributes as $name => $data) {
246  echo "$name:$data<br>\n";
247  }
248  }
249 
255  function open()
256  {
257  }
258 
264  function createRequest()
265  {
266  }
267 
274  {
275  if (!$this->useStandardAttributes)
276  return;
277 
278  if (isset($_SERVER)) {
279  $var = &$_SERVER;
280  } else {
281  $var = &$GLOBALS['HTTP_SERVER_VARS'];
282  }
283 
284  $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost');
285  $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
286  $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
287  $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
288  $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1');
289  }
290 
296  function putAuthAttributes()
297  {
298  if (isset($this->username)) {
299  $this->putAttribute(RADIUS_USER_NAME, $this->username);
300  }
301  }
302 
315  function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
316  {
317  if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
318  return false;
319  }
320  return true;
321  }
322 
330  function putConfigfile($file)
331  {
332  if (!radius_config($this->res, $file)) {
333  return false;
334  }
335  return true;
336  }
337 
344  function start()
345  {
346  if (!$this->open()) {
347  return false;
348  }
349 
350  foreach ($this->_servers as $s) {
351  // Servername, port, sharedsecret, timeout, retries
352  if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
353  return false;
354  }
355  }
356 
357  if (!empty($this->_configfile)) {
358  if (!$this->putConfigfile($this->_configfile)) {
359  return false;
360  }
361  }
362 
363  $this->createRequest();
364  $this->putStandardAttributes();
365  $this->putAuthAttributes();
366  return true;
367  }
368 
375  function send()
376  {
377  $req = radius_send_request($this->res);
378  if (!$req) {
379  return $this->raiseError('Error sending request: ' . $this->getError());
380  }
381 
382  switch($req) {
383  case RADIUS_ACCESS_ACCEPT:
384  if (is_subclass_of($this, 'auth_radius_acct')) {
385  return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
386  }
387  return true;
388 
389  case RADIUS_ACCESS_REJECT:
390  return false;
391 
392  case RADIUS_ACCOUNTING_RESPONSE:
393  if (is_subclass_of($this, 'auth_radius_pap')) {
394  return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
395  }
396  return true;
397 
398  default:
399  return $this->raiseError("Unexpected return value: $req");
400  }
401 
402  }
403 
416  function getAttributes()
417  {
418 
419  while ($attrib = radius_get_attr($this->res)) {
420 
421  if (!is_array($attrib)) {
422  return false;
423  }
424 
425  $attr = $attrib['attr'];
426  $data = $attrib['data'];
427 
428  $this->rawAttributes[$attr] = $data;
429 
430  switch ($attr) {
431  case RADIUS_FRAMED_IP_ADDRESS:
432  $this->attributes['framed_ip'] = radius_cvt_addr($data);
433  break;
434 
435  case RADIUS_FRAMED_IP_NETMASK:
436  $this->attributes['framed_mask'] = radius_cvt_addr($data);
437  break;
438 
439  case RADIUS_FRAMED_MTU:
440  $this->attributes['framed_mtu'] = radius_cvt_int($data);
441  break;
442 
443  case RADIUS_FRAMED_COMPRESSION:
444  $this->attributes['framed_compression'] = radius_cvt_int($data);
445  break;
446 
447  case RADIUS_SESSION_TIMEOUT:
448  $this->attributes['session_timeout'] = radius_cvt_int($data);
449  break;
450 
451  case RADIUS_IDLE_TIMEOUT:
452  $this->attributes['idle_timeout'] = radius_cvt_int($data);
453  break;
454 
455  case RADIUS_SERVICE_TYPE:
456  $this->attributes['service_type'] = radius_cvt_int($data);
457  break;
458 
459  case RADIUS_CLASS:
460  $this->attributes['class'] = radius_cvt_string($data);
461  break;
462 
463  case RADIUS_FRAMED_PROTOCOL:
464  $this->attributes['framed_protocol'] = radius_cvt_int($data);
465  break;
466 
467  case RADIUS_FRAMED_ROUTING:
468  $this->attributes['framed_routing'] = radius_cvt_int($data);
469  break;
470 
471  case RADIUS_FILTER_ID:
472  $this->attributes['filter_id'] = radius_cvt_string($data);
473  break;
474 
475  case RADIUS_REPLY_MESSAGE:
476  $this->attributes['reply_message'] = radius_cvt_string($data);
477  break;
478 
479  case RADIUS_VENDOR_SPECIFIC:
480  $attribv = radius_get_vendor_attr($data);
481  if (!is_array($attribv)) {
482  return false;
483  }
484 
485  $vendor = $attribv['vendor'];
486  $attrv = $attribv['attr'];
487  $datav = $attribv['data'];
488 
489  $this->rawVendorAttributes[$vendor][$attrv] = $datav;
490 
491  if ($vendor == RADIUS_VENDOR_MICROSOFT) {
492 
493  switch ($attrv) {
494  case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
495  $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
496  break;
497 
498  case RADIUS_MICROSOFT_MS_CHAP_ERROR:
499  $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
500  break;
501 
502  case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
503  $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
504  break;
505 
506  case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
507  $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
508  break;
509 
510  case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
511  $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
512  break;
513 
514  case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
515  $demangled = radius_demangle($this->res, $datav);
516  $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
517  $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
518  break;
519 
520  case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
521  $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
522  break;
523 
524  case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
525  $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
526  break;
527 
528  case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
529  $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
530  break;
531  }
532  }
533  break;
534 
535  }
536  }
537 
538  return true;
539  }
540 
549  function close()
550  {
551  if ($this->res != null) {
552  radius_close($this->res);
553  $this->res = null;
554  }
555  $this->username = str_repeat("\0", strlen($this->username));
556  $this->password = str_repeat("\0", strlen($this->password));
557  }
558 
559 }
560 
569 {
570 
578  function Auth_RADIUS_PAP($username = null, $password = null)
579  {
580  $this->Auth_RADIUS();
581  $this->username = $username;
582  $this->password = $password;
583  }
584 
593  function open()
594  {
595  $this->res = radius_auth_open();
596  if (!$this->res) {
597  return false;
598  }
599  return true;
600  }
601 
610  function createRequest()
611  {
612  if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
613  return false;
614  }
615  return true;
616  }
617 
623  function putAuthAttributes()
624  {
625  if (isset($this->username)) {
626  $this->putAttribute(RADIUS_USER_NAME, $this->username);
627  }
628  if (isset($this->password)) {
629  $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
630  }
631  }
632 
633 }
634 
645 {
650  var $challenge = null;
651 
656  var $response = null;
657 
662  var $chapid = 1;
663 
672  function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
673  {
674  $this->Auth_RADIUS_PAP();
675  $this->username = $username;
676  $this->challenge = $challenge;
677  $this->chapid = $chapid;
678  }
679 
688  function putAuthAttributes()
689  {
690  if (isset($this->username)) {
691  $this->putAttribute(RADIUS_USER_NAME, $this->username);
692  }
693  if (isset($this->response)) {
694  $response = pack('C', $this->chapid) . $this->response;
695  $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
696  }
697  if (isset($this->challenge)) {
698  $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
699  }
700  }
701 
710  function close()
711  {
713  $this->challenge = str_repeat("\0", strlen($this->challenge));
714  $this->response = str_repeat("\0", strlen($this->response));
715  }
716 
717 }
718 
727 {
732  var $lmResponse = null;
733 
739  var $flags = 1;
740 
755  function putAuthAttributes()
756  {
757  if (isset($this->username)) {
758  $this->putAttribute(RADIUS_USER_NAME, $this->username);
759  }
760  if (isset($this->response) || isset($this->lmResponse)) {
761  $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
762  $ntResp = isset($this->response) ? $this->response : str_repeat ("\0", 24);
763  $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
764  $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
765  }
766  if (isset($this->challenge)) {
767  $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
768  }
769  }
770 }
771 
780 {
785  var $challenge = null;
786 
791  var $peerChallenge = null;
792 
808  function putAuthAttributes()
809  {
810  if (isset($this->username)) {
811  $this->putAttribute(RADIUS_USER_NAME, $this->username);
812  }
813  if (isset($this->response) && isset($this->peerChallenge)) {
814  // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
815  $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
816  $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
817  }
818  if (isset($this->challenge)) {
819  $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
820  }
821  }
822 
831  function close()
832  {
834  $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
835  }
836 }
837 
846 {
852  var $authentic = null;
853 
859  var $status_type = null;
860 
865  var $session_time = null;
866 
871  var $session_id = null;
872 
879  function Auth_RADIUS_Acct()
880  {
881  $this->Auth_RADIUS();
882 
883  if (isset($_SERVER)) {
884  $var = &$_SERVER;
885  } else {
886  $var = &$GLOBALS['HTTP_SERVER_VARS'];
887  }
888 
889  $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
890  }
891 
900  function open()
901  {
902  $this->res = radius_acct_open();
903  if (!$this->res) {
904  return false;
905  }
906  return true;
907  }
908 
917  function createRequest()
918  {
919  if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
920  return false;
921  }
922  return true;
923  }
924 
932  function putAuthAttributes()
933  {
934  $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
935  $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
936  if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
937  $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
938  }
939  if (isset($this->authentic)) {
940  $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
941  }
942 
943  }
944 
945 }
946 
955 {
961  var $status_type = RADIUS_START;
962 }
963 
972 {
978  var $status_type = RADIUS_STOP;
979 }
980 
981 if (!defined('RADIUS_UPDATE'))
982  define('RADIUS_UPDATE', 3);
983 
992 {
998  var $status_type = RADIUS_UPDATE;
999 }
1000 
1001 ?>