radiusauth/libradauth.php
changeset 0 7e0b422b1725
equal deleted inserted replaced
-1:000000000000 0:7e0b422b1725
       
     1 <?php
       
     2 
       
     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 The author of this file respectfully requests that you refrain from
       
    31 relicensing it under the GPL, although the BSD license permits you to do so.
       
    32 
       
    33 */
       
    34 
       
    35 class RadiusAuth
       
    36 {
       
    37   var $radius;
       
    38   
       
    39   var $server = 'localhost';
       
    40   var $secret = 's3cr35SHH';
       
    41   var $port = 1812;
       
    42   
       
    43   function __construct($server, $secret, $port = 1812)
       
    44   {
       
    45     $this->radius = radius_auth_open();
       
    46     if ( !$this->radius )
       
    47     {
       
    48       throw new RadiusError("Could not get RADIUS resource");
       
    49     }
       
    50     
       
    51     $this->set_server_params($server, $secret, $port);
       
    52     $this->create_request();
       
    53   }
       
    54   
       
    55   function set_server_params($server, $secret, $port = 1812)
       
    56   {
       
    57     $this->server = $server;
       
    58     $this->secret = $secret;
       
    59     $this->port = $port;
       
    60   }
       
    61   
       
    62   function create_request()
       
    63   {
       
    64     if ( !radius_add_server($this->radius, $this->server, $this->port, $this->secret, 3, 3) )
       
    65       throw new RadiusError(radius_strerror($this->radius));
       
    66     
       
    67     if ( !radius_create_request($this->radius, RADIUS_ACCESS_REQUEST) )
       
    68       throw new RadiusError(radius_strerror($this->radius));
       
    69     
       
    70     if (!radius_put_string($this->radius, RADIUS_NAS_IDENTIFIER, isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'))
       
    71       throw new RadiusError(radius_strerror($this->radius));
       
    72     
       
    73     /*
       
    74     if (!radius_put_int($this->radius, RADIUS_SERVICE_TYPE, RADIUS_FRAMED))
       
    75       throw new RadiusError(radius_strerror($this->radius));
       
    76       
       
    77     if (!radius_put_int($this->radius, RADIUS_FRAMED_PROTOCOL, RADIUS_PPP))
       
    78       throw new RadiusError(radius_strerror($this->radius));
       
    79     */
       
    80     
       
    81     if (!radius_put_string($this->radius, RADIUS_CALLING_STATION_ID, isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1'))
       
    82       throw new RadiusError(radius_strerror($this->radius));
       
    83   }
       
    84   
       
    85   function authenticate($username, $password, $method = 'pap')
       
    86   {
       
    87     //
       
    88     // Send the username
       
    89     //
       
    90     
       
    91     if ( !radius_put_string($this->radius, RADIUS_USER_NAME, $username) )
       
    92       throw new RadiusError("RADIUS_USER_NAME: " . radius_strerror($this->radius));
       
    93     
       
    94     //
       
    95     // Send the password, or complete the challenge process
       
    96     //
       
    97     
       
    98     switch ( $method )
       
    99     {
       
   100       case 'chap':
       
   101         
       
   102         //
       
   103         // CHAP
       
   104         //
       
   105         
       
   106         /* generate Challenge */
       
   107         mt_srand(time() * mt_rand());
       
   108         $chall = mt_rand();
       
   109     
       
   110         // FYI: CHAP = md5(ident + plaintextpass + challenge)
       
   111         $chapval = pack('H*', md5(pack('Ca*', 1, $password . $chall)));
       
   112         // Radius wants the CHAP Ident in the first byte of the CHAP-Password
       
   113         $pass_chap = pack('C', 1) . $chapval;
       
   114     
       
   115         if (!radius_put_attr($this->radius, RADIUS_CHAP_PASSWORD, $pass_chap))
       
   116           throw new RadiusError(radius_strerror($this->radius));
       
   117     
       
   118         if (!radius_put_attr($this->radius, RADIUS_CHAP_CHALLENGE, $chall))
       
   119           throw new RadiusError(radius_strerror($this->radius));
       
   120         
       
   121         break;
       
   122         
       
   123       case 'mschap':
       
   124         
       
   125         //
       
   126         // MS-CHAP v1
       
   127         //
       
   128         
       
   129         require_once(ENANO_ROOT . '/plugins/radiusauth/libradauth.php');
       
   130 
       
   131         $challenge = GenerateChallenge();
       
   132         
       
   133         if (!radius_put_vendor_attr($this->radius, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $challenge))
       
   134           throw new RadiusError(radius_strerror($this->radius));
       
   135         
       
   136         $ntresp = ChallengeResponse($challenge, NtPasswordHash($password));
       
   137         $lmresp = str_repeat ("\0", 24);
       
   138         
       
   139         // Response: chapid, flags (1 = use NT Response), LM Response, NT Response
       
   140         $resp = pack('CCa48',1 , 1, $lmresp . $ntresp);
       
   141         
       
   142         if ( !radius_put_vendor_attr($this->radius, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp))
       
   143           throw new RadiusError(radius_strerror($this->radius));
       
   144         
       
   145         break;
       
   146         
       
   147       case 'mschapv2':
       
   148         
       
   149         //
       
   150         // MS-CHAP v2
       
   151         //
       
   152         
       
   153         require_once(ENANO_ROOT . '/plugins/radiusauth/libradauth.php');
       
   154 
       
   155         $authChallenge = GenerateChallenge(16);
       
   156         
       
   157         if (!radius_put_vendor_attr($this->radius, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $authChallenge))
       
   158           throw new RadiusError(radius_strerror($this->radius));
       
   159     
       
   160         // we have no client, therefore we generate the Peer-Challenge
       
   161         $peerChallenge = GeneratePeerChallenge();
       
   162     
       
   163         $ntresp = GenerateNTResponse($authChallenge, $peerChallenge, $username, $password);
       
   164         $reserved = str_repeat ("\0", 8);
       
   165     
       
   166         // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
       
   167         $resp = pack('CCa16a8a24',1 , 1, $peerChallenge, $reserved, $ntresp);
       
   168     
       
   169         if (!radius_put_vendor_attr($this->radius, RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp))
       
   170           throw new RadiusError(radius_strerror($this->radius));
       
   171         
       
   172         break;
       
   173         
       
   174       case 'pap':
       
   175       default:
       
   176         
       
   177         //
       
   178         // PAP
       
   179         //
       
   180         
       
   181         if ( !radius_put_string($this->radius, RADIUS_USER_PASSWORD, $password) )
       
   182           throw new RadiusError("RADIUS_USER_PASSWORD: " . radius_strerror($this->radius));
       
   183         
       
   184         break;
       
   185     }
       
   186     
       
   187     $req = radius_send_request($this->radius);
       
   188     if ( !$req )
       
   189       throw new RadiusError(radius_strerror($this->radius));
       
   190     
       
   191     switch($req)
       
   192     {
       
   193       case RADIUS_ACCESS_ACCEPT:
       
   194         return true;
       
   195       
       
   196       case RADIUS_ACCESS_REJECT:
       
   197         return false;
       
   198       
       
   199       default:
       
   200         echo "Unexpected return value:$req\n<br>";
       
   201         return false;
       
   202     }
       
   203   }
       
   204   
       
   205   function get_attrs()
       
   206   {
       
   207     $attrs = array();
       
   208     while ($resa = radius_get_attr($this->radius))
       
   209     {
       
   210       $attrs[ $resa['attr'] ] = $resa['data'];
       
   211     }
       
   212     
       
   213     return $attrs;
       
   214   }
       
   215   
       
   216   function get_authenticator()
       
   217   {
       
   218     if ( $authent = radius_request_authenticator($this->radius) )
       
   219       return $authent;
       
   220     
       
   221     throw new RadiusError(radius_strerror($this->radius));
       
   222   }
       
   223   
       
   224   function close()
       
   225   {
       
   226     radius_close($this->radius);
       
   227   }
       
   228 }
       
   229 
       
   230 class RadiusError extends Exception
       
   231 {
       
   232   
       
   233 }