Project

General

Profile

Download (35.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
/*
4
    $Id$
5

    
6
    Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
7
    All rights reserved.
8

    
9
    Redistribution and use in source and binary forms, with or without 
10
    modification, are permitted provided that the following conditions 
11
    are met:
12

    
13
    1. Redistributions of source code must retain the above copyright 
14
       notice, this list of conditions and the following disclaimer.
15
    2. Redistributions in binary form must reproduce the above copyright 
16
       notice, this list of conditions and the following disclaimer in the 
17
       documentation and/or other materials provided with the distribution.
18
    3. The names of the authors may not be used to endorse or promote products 
19
       derived from this software without specific prior written permission.
20

    
21
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
22
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
23
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
24
    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
25
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26
    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
27
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
28
    OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
29
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
30
    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31

    
32
    This code cannot simply be copied and put under the GNU Public License or 
33
    any other GPL-like (LGPL, GPL2) License.
34

    
35
        This version of RADIUS.php has been modified by
36
        Jonathan De Graeve <m0n0wall@esstec.be> to integrate with M0n0wall <http://www.m0n0.ch/wall>
37

    
38
        Changes made include:
39
        * StandardAttributes for M0n0wall use
40
        * Removed internal Session-Id creation
41
        * Adding of ReplyMessage to getAttributes()
42
        * Adding of listAttributes()
43
        * Adding of VENDOR Bay Networks (Nortel)
44
        * Adding of VENDOR Nomadix
45
        * Adding of VENDOR WISPr (Wi-Fi Alliance)
46
        * Adding of VENDOR ChilliSpot (bandwidth-attributes only)
47

    
48
*/
49

    
50
/*
51
    pfSense_MODULE:    auth
52
*/
53

    
54
require_once("PEAR.inc");
55
require_once("radius_authentication.inc");
56
require_once("radius_accounting.inc");
57

    
58
/**
59
* Client implementation of RADIUS. This are wrapper classes for
60
* the RADIUS PECL
61
* Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
62
*
63
* @package Auth_RADIUS
64
* @author  Michael Bretterklieber <michael@bretterklieber.com>
65
* @access  public
66
* @version $Revision: 1.5 $
67
*/
68

    
69
PEAR::loadExtension('radius');
70

    
71
/**
72
 * class Auth_RADIUS
73
 *
74
 * Abstract base class for RADIUS
75
 *
76
 * @package Auth_RADIUS 
77
 */
78
class Auth_RADIUS extends PEAR {
79

    
80
    /**
81
     * List of RADIUS servers.
82
     * @var  array
83
     * @see  addServer(), putServer()
84
     */
85
    var $_servers  = array();
86

    
87
    /**
88
     * Path to the configuration-file.
89
     * @var  string
90
     * @see  setConfigFile()
91
     */
92
    var $_configfile = null;
93

    
94
    /**
95
     * Resource.
96
     * @var  resource
97
     * @see  open(), close()
98
     */
99
    var $res = null;
100

    
101
    /**
102
     * Username for authentication and accounting requests.
103
     * @var  string
104
     */
105
    var $username = null;
106

    
107
    /**
108
     * Password for plaintext-authentication (PAP).
109
     * @var  string
110
     */
111
    var $password = null;
112

    
113
    /**
114
     * List of known attributes.
115
     * @var  array
116
     * @see  dumpAttributes(), getAttributes()
117
     */
118
    var $attributes = array();
119

    
120
    /**
121
     * List of raw attributes.
122
     * @var  array
123
     * @see  dumpAttributes(), getAttributes()
124
     */
125
    var $rawAttributes = array();
126

    
127
    /**
128
     * List of raw vendor specific attributes.
129
     * @var  array
130
     * @see  dumpAttributes(), getAttributes()
131
     */
132
    var $rawVendorAttributes = array();
133

    
134
    /**
135
     * Constructor
136
     *
137
     * Loads the RADIUS PECL/extension
138
     *
139
     * @return void
140
     */
141
    function Auth_RADIUS() 
142
    {
143
        $this->PEAR();
144
    }
145

    
146
    /**
147
     * Adds a RADIUS server to the list of servers for requests.
148
     *
149
     * At most 10 servers may be specified.    When multiple servers 
150
     * are given, they are tried in round-robin fashion until a 
151
     * valid response is received
152
     *
153
     * @access public
154
     * @param  string  $servername   Servername or IP-Address
155
     * @param  integer $port         Portnumber
156
     * @param  string  $sharedSecret Shared secret
157
     * @param  integer $timeout      Timeout for each request
158
     * @param  integer $maxtries     Max. retries for each request
159
     * @return void
160
     */
161
    function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 2) 
162
    {
163
        $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
164
    }
165

    
166
    /**
167
     * Returns an error message, if an error occurred.
168
     *
169
     * @access public
170
     * @return string
171
     */
172
    function getError() 
173
    {
174
        return radius_strerror($this->res);
175
    }
176

    
177
    /**
178
     * Sets the configuration-file.
179
     *
180
     * @access public
181
     * @param  string  $file Path to the configuration file
182
     * @return void
183
     */
184
    function setConfigfile($file) 
185
    {
186
        $this->_configfile = $file;
187
    }
188

    
189
    /**
190
     * Puts an attribute.
191
     *
192
     * @access public
193
     * @param  integer $attrib       Attribute-number
194
     * @param  mixed   $port         Attribute-value
195
     * @param  type    $type         Attribute-type
196
     * @return bool  true on success, false on error
197
     */
198
    function putAttribute($attrib, $value, $type = null) 
199
    {
200
        if ($type == null) {
201
            $type = gettype($value);
202
        }
203

    
204
        switch ($type) {
205
        case 'integer':
206
            // Fix a conversion error so we should be able to handle 4GB values
207
            return radius_put_int($this->res, $attrib, (float)$value);
208

    
209
        case 'addr':
210
            return radius_put_addr($this->res, $attrib, $value);
211

    
212
        case 'string':
213
        default:
214
            return radius_put_attr($this->res, $attrib, $value);
215
        }
216

    
217
    }
218

    
219
    /**
220
     * Puts a vendor-specific attribute.
221
     *
222
     * @access public
223
     * @param  integer $vendor       Vendor (MSoft, Cisco, ...)
224
     * @param  integer $attrib       Attribute-number
225
     * @param  mixed   $port         Attribute-value
226
     * @param  type    $type         Attribute-type
227
     * @return bool  true on success, false on error
228
     */ 
229
    function putVendorAttribute($vendor, $attrib, $value, $type = null) 
230
    {
231

    
232
        if ($type == null) {
233
            $type = gettype($value);
234
        }
235

    
236
        switch ($type) {
237
        case 'integer':
238
            return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
239

    
240
        case 'addr':
241
            return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
242

    
243
        case 'string':
244
        default:
245
            return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
246
        }
247

    
248
    }
249

    
250
    /**
251
     * Prints known attributes received from the server.
252
     *
253
     * @access public
254
     */
255
    function dumpAttributes()
256
    {
257
        foreach ($this->attributes as $name => $data) {
258
            echo "$name:$data<br>\n";
259
        }
260
    }
261

    
262
    /**
263
     * Return our know attributes array received from the server.
264
     *
265
     * @access public
266
     */
267
    function listAttributes()
268
    {
269
        return $this->attributes;
270
    }
271

    
272
    /**
273
     * Overwrite this. 
274
     *
275
     * @access public
276
     */
277
    function open() 
278
    {
279
    }
280

    
281
    /**
282
     * Overwrite this.
283
     *
284
     * @access public
285
     */
286
    function createRequest()
287
    {
288
    }
289

    
290
    /**
291
     * Puts standard attributes.
292
     *
293
     * These attributes will always be present in a radius request
294
     *
295
     * @access public
296
     */
297
    function putStandardAttributes()
298
    {
299
        global $config, $cpzone;
300

    
301
        if (!function_exists("getNasIp")) {
302
            $ipaddr = "0.0.0.0";
303
        } else {
304
            $ipaddr = getNasIP();
305
        }
306
        // Add support for sending NAS-IP-Address, set this explicitly as an ip_addr
307
        $this->putAttribute(RADIUS_NAS_IP_ADDRESS, $ipaddr, "addr");
308

    
309
        // Add support for sending NAS-Identifier
310
        if (empty($config["captiveportal"][$cpzone]["radiusnasid"])) {
311
            $nasId = php_uname("n");
312
        } else {
313
            $nasId = $config["captiveportal"][$cpzone]["radiusnasid"];
314
        }
315
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, $nasId);
316
    }
317

    
318
    /**
319
     * Puts custom attributes.
320
     *
321
     * @access public
322
     */
323
    function putAuthAttributes()
324
    {
325
        if (isset($this->username)) {
326
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
327
        }
328
    }
329

    
330
    /**
331
     * Configures the radius library.
332
     *
333
     * @access public
334
     * @param  string  $servername   Servername or IP-Address
335
     * @param  integer $port         Portnumber
336
     * @param  string  $sharedSecret Shared secret
337
     * @param  integer $timeout      Timeout for each request
338
     * @param  integer $maxtries     Max. retries for each request
339
     * @return bool  true on success, false on error
340
     * @see addServer()
341
     */
342
    function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3) 
343
    {
344
        if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
345
            return false;
346
        }
347
        return true;
348
    }
349

    
350
    /**
351
     * Configures the radius library via external configurationfile
352
     *
353
     * @access public
354
     * @param  string  $servername   Servername or IP-Address
355
     * @return bool  true on success, false on error
356
     */
357
    function putConfigfile($file) 
358
    {
359
        if (!radius_config($this->res, $file)) {
360
            return false;
361
        }
362
        return true;
363
    }
364

    
365
    /**
366
     * Initiates a RADIUS request. 
367
     *
368
     * @access public
369
     * @return bool  true on success, false on errors     
370
     */ 
371
    function start()
372
    {
373
        if (!$this->open()) {
374
            return false;
375
        }
376

    
377
        foreach ($this->_servers as $s) {
378
            // Servername, port, sharedsecret, timeout, retries
379
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
380
                return false;
381
            }
382
        }
383

    
384
        if (!empty($this->_configfile)) {
385
            if (!$this->putConfigfile($this->_configfile)) {
386
                return false;
387
            }
388
        }
389

    
390
        $this->createRequest();
391
        $this->putStandardAttributes();
392
        $this->putAuthAttributes();
393
        return true;
394
    }
395

    
396
    /**
397
     * Sends a prepared RADIUS request and waits for a response
398
     *
399
     * @access public
400
     * @return mixed  true on success, false on reject, PEAR_Error on error
401
     */
402
    function send()
403
    {
404
        $req = radius_send_request($this->res);
405
        if (!$req) {
406
            return $this->raiseError(gettext('Error sending request:') . ' ' . $this->getError());
407
        }
408

    
409
        switch($req) {
410
        case RADIUS_ACCESS_ACCEPT:
411
            if (is_subclass_of($this, 'auth_radius_acct')) {
412
                return $this->raiseError(gettext('RADIUS_ACCESS_ACCEPT is unexpected for accounting'));
413
            }
414
            return true;
415

    
416
        case RADIUS_ACCESS_REJECT:
417
            return false;
418

    
419
        case RADIUS_ACCOUNTING_RESPONSE:
420
            if (is_subclass_of($this, 'auth_radius_pap')) {
421
                return $this->raiseError(gettext('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication'));
422
            }
423
            return true;
424

    
425
        default:
426
            return $this->raiseError(sprintf(gettext("Unexpected return value: %s"),$req));
427
        }
428

    
429
    }
430

    
431
    /**
432
     * Reads all received attributes after sending the request.
433
     *
434
     * This methos stores know attributes in the property attributes,
435
     * all attributes (including known attibutes) are stored in rawAttributes
436
     * or rawVendorAttributes.
437
     * NOTE: call this functio also even if the request was rejected, because the
438
     * Server returns usualy an errormessage
439
     *
440
     * @access public
441
     * @return bool   true on success, false on error
442
     */
443
    function getAttributes()
444
    {
445

    
446
        while ($attrib = radius_get_attr($this->res)) {
447

    
448
            if (!is_array($attrib)) {
449
                return false;
450
            }        
451

    
452
            $attr = $attrib['attr'];
453
            $data = $attrib['data'];
454

    
455
            $this->rawAttributes[$attr] = $data;
456

    
457
            switch ($attr) {
458
            case RADIUS_FRAMED_IP_ADDRESS:
459
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
460
                break;
461

    
462
            case RADIUS_FRAMED_IP_NETMASK:
463
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
464
                break;
465

    
466
            case RADIUS_FRAMED_MTU:
467
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
468
                break;
469

    
470
            case RADIUS_FRAMED_COMPRESSION:
471
                $this->attributes['framed_compression'] = radius_cvt_int($data);
472
                break;
473

    
474
            case RADIUS_SESSION_TIMEOUT:
475
                $this->attributes['session_timeout'] = radius_cvt_int($data);
476
                break;
477

    
478
            case RADIUS_IDLE_TIMEOUT:
479
                $this->attributes['idle_timeout'] = radius_cvt_int($data);
480
                break;
481

    
482
            case RADIUS_SERVICE_TYPE:
483
                $this->attributes['service_type'] = radius_cvt_int($data);
484
                break;
485

    
486
            case RADIUS_CLASS:
487
                $this->attributes['class'] = radius_cvt_int($data);
488
                break;
489

    
490
            case RADIUS_FRAMED_PROTOCOL:
491
                $this->attributes['framed_protocol'] = radius_cvt_int($data);
492
                break;
493

    
494
            case RADIUS_FRAMED_ROUTING:
495
                $this->attributes['framed_routing'] = radius_cvt_int($data);
496
                break;
497

    
498
            case RADIUS_FILTER_ID:
499
                $this->attributes['filter_id'] = radius_cvt_string($data);
500
                break;
501

    
502
            case RADIUS_REPLY_MESSAGE:
503
                $this->attributes['reply_message'] = radius_cvt_string($data);
504
                break;
505

    
506
            case RADIUS_VENDOR_SPECIFIC:
507
                $attribv = radius_get_vendor_attr($data);
508
                if (!is_array($attribv)) {
509
                    return false;
510
                }
511

    
512
                $vendor = $attribv['vendor'];
513
                $attrv = $attribv['attr'];
514
                $datav = $attribv['data'];
515

    
516
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
517

    
518
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
519

    
520
                    switch ($attrv) {
521
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
522
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
523
                        break;
524

    
525
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
526
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
527
                        break;
528

    
529
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
530
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
531
                        break;
532

    
533
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
534
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
535
                        break;
536

    
537
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
538
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
539
                        break;
540

    
541
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
542
                        $demangled = radius_demangle($this->res, $datav);
543
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
544
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
545
                        break;
546

    
547
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
548
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
549
                        break;
550

    
551
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
552
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
553
                        break;
554

    
555
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
556
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
557
                        break;
558
                    }
559
                }
560

    
561
                elseif ($vendor == 1584) {
562

    
563
                    switch ($attrv) {
564
                    case 102:
565
                        $this->attributes['ces_group'] = radius_cvt_string($datav);
566
                        break;
567
                    }
568
                }
569

    
570
                elseif ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
571

    
572
                    switch ($attrv) {
573
                    case 1: /* RADIUS_NOMADIX_BW_UP */
574
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
575
                        break;
576
                    case 2: /* RADIUS_NOMADIX_BW_DOWN */
577
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
578
                        break;
579
                    case 3: /* RADIUS_NOMADIX_URL_REDIRECTION */
580
                        $this->attributes['url_redirection'] = radius_cvt_string($datav);
581
                        break;
582
                    case 5: /* RADIUS_NOMADIX_EXPIRATION */
583
                        $this->attributes['expiration'] = radius_cvt_string($datav);
584
                        break;
585
                    case 7: /* RADIUS_NOMADIX_MAXBYTESUP */
586
                        $this->attributes['maxbytesup'] = radius_cvt_int($datav);
587
                        break;
588
                    case 8: /* RADIUS_NOMADIX_MAXBYTESDOWN */
589
                        $this->attributes['maxbytesdown'] = radius_cvt_int($datav);
590
                        break;
591
                    case 10: /* RADIUS_NOMADIX_LOGOFF_URL */
592
                        $this->attributes['url_logoff'] = radius_cvt_string($datav);
593
                        break;
594
                    }
595
                } 
596

    
597
                elseif ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
598

    
599
                    switch ($attrv) {
600
                    case 1: /* WISPr-Location-ID */
601
                        $this->attributes['location_id'] = radius_cvt_string($datav);
602
                        break;
603
                    case 2: /* WISPr-Location-Name */
604
                        $this->attributes['location_name'] = radius_cvt_string($datav);
605
                        break;
606
                    case 3: /* WISPr-Logoff-URL */
607
                        $this->attributes['url_logoff'] = radius_cvt_string($datav);
608
                        break;
609
                    case 4: /* WISPr-Redirection-URL */
610
                        $this->attributes['url_redirection'] = radius_cvt_string($datav);
611
                        break;
612
                    case 5: /* WISPr-Bandwidth-Min-Up */
613
                        $this->attributes['bw_up_min'] = radius_cvt_int($datav);
614
                        break;
615
                    case 6: /* WISPr-Bandwidth-Min-Down */
616
                        $this->attributes['bw_down_min'] = radius_cvt_int($datav);
617
                        break;
618
                    case 7: /* WISPr-Bandwidth-Max-Up */
619
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
620
                        break;
621
                    case 8: /* WISPr-Bandwidth-Max-Down */
622
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
623
                        break;
624
                    case 9: /* WISPr-Session-Terminate-Time */
625
                        $this->attributes['session_terminate_time'] = radius_cvt_string($datav);
626
                        break;
627
                    case 10: /* WISPr-Session-Terminate-End-Of-Day */
628
                        $this->attributes['session_terminate_endofday'] = radius_cvt_int($datav);
629
                        break;
630
                    case 11: /* WISPr-Billing-Class-Of-Service */
631
                        $this->attributes['billing_class_of_service'] = radius_cvt_string($datav);
632
                        break;
633
                    }
634
                }
635

    
636
                elseif ($vendor == 14559) { /* RADIUS_VENDOR_ChilliSpot */
637
                    switch ($attrv) {
638
                    case 4: /* ChilliSpot-Bandwidth-Max-Up */
639
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
640
                        break;
641
                    case 5: /* ChilliSpot-Bandwidth-Max-Down */
642
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
643
                        break;
644
                    }
645
                }
646

    
647
                elseif ($vendor == 8744) { /* Colubris / HP MSM wireless */
648
                    //documented at http://bizsupport1.austin.hp.com/bc/docs/support/SupportManual/c02704528/c02704528.pdf pg 15-67
649
                    if ($attrv == 0) { /* Colubris AV-Pair */
650
                        $datav = explode('=', $datav);
651
                        switch ($datav[0]) {
652
                        case 'max-input-rate':
653
                            // "Controls the data rate [kbps] at which traffic can be transferred from the user to the [router]."
654
                            $this->attributes['bw_up'] = radius_cvt_int($datav[1]);
655
                            break;
656
                        case 'max-output-rate':
657
                            //"Controls the data rate [kbps] at which traffic can be transferred from the [router] to the user."
658
                            $this->attributes['bw_down'] = radius_cvt_int($datav[1]);
659
                            break;
660
                        case 'max-input-octets':
661
                            $this->attributes['maxbytesup'] = radius_cvt_int($datav[1]);
662
                            break;
663
                        case 'max-output-octets':
664
                            $this->attributes['maxbytesdown'] = radius_cvt_int($datav[1]);
665
                            break;
666
                        case 'welcome-url':
667
                            $this->attributes['url_redirection'] = radius_cvt_string($datav[1]);
668
                            break;
669
                        case 'goodbye-url':
670
                            $this->attributes['url_logoff'] = radius_cvt_string($datav[1]);
671
                            break;
672
                        }
673
                    }
674
                }
675

    
676
                break;
677

    
678
            case 85: /* Acct-Interim-Interval: RFC 2869 */
679
                $this->attributes['interim_interval'] = radius_cvt_int($datav[1]);
680
                break;
681
            }
682
        }
683

    
684
        return true;
685
    }
686

    
687
    /**
688
     * Frees resources.
689
     *
690
     * Calling this method is always a good idea, because all security relevant
691
     * attributes are filled with Nullbytes to leave nothing in the mem.
692
     *
693
     * @access public
694
     */
695
    function close()
696
    {
697
        if ($this->res != null) {
698
            radius_close($this->res);
699
            $this->res = null;
700
        }
701
        $this->username = str_repeat("\0", strlen($this->username));
702
        $this->password = str_repeat("\0", strlen($this->password));
703
    }
704

    
705
}
706

    
707
/**
708
 * class Auth_RADIUS_PAP
709
 *
710
 * Class for authenticating using PAP (Plaintext)
711
 *
712
 * @package Auth_RADIUS 
713
 */
714
class Auth_RADIUS_PAP extends Auth_RADIUS 
715
{
716

    
717
    /**
718
     * Constructor
719
     *
720
     * @param  string  $username   Username
721
     * @param  string  $password   Password
722
     * @return void
723
     */
724
    function Auth_RADIUS_PAP($username = null, $password = null)
725
    {
726
        $this->Auth_RADIUS();
727
        $this->username = $username;
728
        $this->password = $password;
729
    }
730

    
731
    /**
732
     * Creates a RADIUS resource
733
     *
734
     * Creates a RADIUS resource for authentication. This should be the first
735
     * call before you make any other things with the library.
736
     *
737
     * @return bool   true on success, false on error
738
     */
739
    function open() 
740
    {
741
        $this->res = radius_auth_open();
742
        if (!$this->res) {
743
            return false;
744
        }
745
        return true;
746
    }
747

    
748
    /**
749
     * Creates an authentication request 
750
     *
751
     * Creates an authentication request.
752
     * You MUST call this method before you can put any attribute
753
     *
754
     * @return bool   true on success, false on error
755
     */
756
    function createRequest()
757
    {
758
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
759
            return false;
760
        }
761
        return true;
762
    }
763

    
764
    /**
765
     * Put authentication specific attributes 
766
     *
767
     * @return void
768
     */
769
    function putAuthAttributes()
770
    {
771
        if (isset($this->username)) {
772
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
773
        }
774
        if (isset($this->password)) {
775
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
776
        }
777
    }
778

    
779
}
780

    
781
/**
782
 * class Auth_RADIUS_CHAP_MD5
783
 *
784
 * Class for authenticating using CHAP-MD5 see RFC1994.
785
 * Instead og the plaintext password the challenge and 
786
 * the response are needed.
787
 *
788
 * @package Auth_RADIUS 
789
 */
790
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
791
{
792
    /**
793
     * 8 Bytes binary challenge
794
     * @var  string
795
     */
796
    var $challenge = null;
797

    
798
    /**
799
     * 16 Bytes MD5 response binary
800
     * @var  string
801
     */
802
    var $response = null;
803

    
804
    /**
805
     * Id of the authentication request. Should incremented after every request.
806
     * @var  integer
807
     */
808
    var $chapid = 1;
809

    
810
    /**
811
     * Constructor
812
     *
813
     * @param  string  $username   Username
814
     * @param  string  $challenge  8 Bytes Challenge (binary)
815
     * @param  integer $chapid     Requestnumber
816
     * @return void
817
     */
818
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
819
    {
820
        $this->Auth_RADIUS_PAP();
821
        $this->username = $username;
822
        $this->challenge = $challenge;
823
        $this->chapid = $chapid;
824
    }
825

    
826
    /**
827
     * Put CHAP-MD5 specific attributes
828
     *
829
     * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge 
830
     * and the response. The chapid is inserted in the first byte of the response.
831
     *
832
     * @return void
833
     */
834
    function putAuthAttributes()
835
    {
836
        if (isset($this->username)) {
837
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
838
        }
839
        if (isset($this->response)) {
840
            $response = pack('C', $this->chapid) . $this->response;
841
            $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
842
        }
843
        if (isset($this->challenge)) {
844
            $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
845
        }
846
    }
847

    
848
    /**
849
     * Frees resources.
850
     *
851
     * Calling this method is always a good idea, because all security relevant
852
     * attributes are filled with Nullbytes to leave nothing in the mem.
853
     *
854
     * @access public
855
     */
856
    function close()
857
    {
858
        Auth_RADIUS_PAP::close();
859
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
860
        $this->response =  str_repeat("\0", strlen($this->response));
861
    }
862

    
863
}
864

    
865
/**
866
 * class Auth_RADIUS_MSCHAPv1
867
 *
868
 * Class for authenticating using MS-CHAPv1 see RFC2433
869
 *
870
 * @package Auth_RADIUS 
871
 */
872
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 
873
{
874
    /**
875
     * LAN-Manager-Response
876
     * @var  string
877
     */
878
    var $lmResponse = null;
879

    
880
    /**
881
     * Wether using deprecated LM-Responses or not.
882
     * 0 = use LM-Response, 1 = use NT-Response
883
     * @var  bool
884
     */
885
    var $flags = 1;
886

    
887
    /**
888
     * Put MS-CHAPv1 specific attributes 
889
     *
890
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
891
     * and the response. The response has this structure:
892
     * struct rad_mschapvalue {
893
     *   u_char ident;
894
     *   u_char flags;
895
     *   u_char lm_response[24];
896
     *   u_char response[24];
897
     * };
898
     *
899
     * @return void
900
     */
901
    function putAuthAttributes()
902
    {
903
        if (isset($this->username)) {
904
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
905
        }
906
        if (isset($this->response) || isset($this->lmResponse)) {
907
            $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
908
            $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
909
            $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
910
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
911
        }
912
        if (isset($this->challenge)) {
913
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
914
        }
915
    }
916
}
917

    
918
/**
919
 * class Auth_RADIUS_MSCHAPv2
920
 *
921
 * Class for authenticating using MS-CHAPv2 see RFC2759
922
 *
923
 * @package Auth_RADIUS 
924
 */
925
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 
926
{
927
    /**
928
     * 16 Bytes binary challenge
929
     * @var  string
930
     */
931
    var $challenge = null;
932

    
933
    /**
934
     * 16 Bytes binary Peer Challenge
935
     * @var  string
936
     */
937
    var $peerChallenge = null;
938

    
939
  /**
940
     * Put MS-CHAPv2 specific attributes 
941
     *
942
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
943
     * and the response. The response has this structure:
944
     * struct rad_mschapv2value {
945
     *   u_char ident;
946
     *   u_char flags;
947
     *   u_char pchallenge[16];
948
     *   u_char reserved[8];
949
     *   u_char response[24];
950
     * };
951
     * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
952
     * @return void
953
     */
954
    function putAuthAttributes()
955
    {
956
        if (isset($this->username)) {
957
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
958
        }
959
        if (isset($this->response) && isset($this->peerChallenge)) {
960
            // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response        
961
            $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);        
962
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
963
        }
964
        if (isset($this->challenge)) {
965
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
966
        }
967
    }
968

    
969
    /**
970
     * Frees resources.
971
     *
972
     * Calling this method is always a good idea, because all security relevant
973
     * attributes are filled with Nullbytes to leave nothing in the mem.
974
     *
975
     * @access public
976
     */   
977
    function close()
978
    {
979
        Auth_RADIUS_MSCHAPv1::close();
980
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
981
    }
982
}
983

    
984
/**
985
 * class Auth_RADIUS_Acct
986
 *
987
 * Class for RADIUS accounting
988
 * 
989
 * @package Auth_RADIUS 
990
 */
991
class Auth_RADIUS_Acct extends Auth_RADIUS 
992
{
993
    /**
994
     * Defines where the Authentication was made, possible values are:
995
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
996
     * @var  integer
997
     */
998
    var $authentic = null;
999

    
1000
   /**
1001
     * Defines the type of the accounting request, on of:
1002
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
1003
     * @var  integer
1004
     */    
1005
    var $status_type = null;
1006

    
1007
   /**
1008
     * The time the user was logged in in seconds
1009
     * @var  integer
1010
     */    
1011
    var $session_time = null;
1012

    
1013
   /**
1014
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
1015
     * @var  string
1016
     */    
1017
    var $session_id = null;
1018

    
1019
    /**
1020
     * Constructor
1021
     *
1022
     * This function is disabled for M0n0wall since we use our own session_id
1023
     *
1024
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
1025
     * @return void
1026
     *
1027
    function Auth_RADIUS_Acct()
1028
    {
1029
        $this->Auth_RADIUS();
1030

    
1031
        if (isset($_SERVER)) {
1032
            $var = &$_SERVER;
1033
        } else {
1034
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1035
        }
1036

    
1037
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
1038
    }
1039
    */
1040

    
1041
    /**
1042
     * Constructor
1043
     *
1044
     */
1045

    
1046
    function Auth_RADIUS_Acct()
1047
    {
1048
        $this->Auth_RADIUS();
1049
    }
1050

    
1051
    /**
1052
     * Creates a RADIUS resource
1053
     *
1054
     * Creates a RADIUS resource for accounting. This should be the first
1055
     * call before you make any other things with the library.
1056
     *
1057
     * @return bool   true on success, false on error
1058
     */
1059
    function open() 
1060
    {
1061
        $this->res = radius_acct_open();
1062
        if (!$this->res) {
1063
            return false;
1064
        }
1065
        return true;
1066
    }
1067

    
1068
   /**
1069
     * Creates an accounting request 
1070
     *
1071
     * Creates an accounting request.
1072
     * You MUST call this method before you can put any attribute.
1073
     *
1074
     * @return bool   true on success, false on error
1075
     */
1076
    function createRequest()
1077
    {
1078
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
1079
            return false;
1080
        }
1081
        return true;
1082
    }
1083

    
1084
  /**
1085
     * Put attributes for accounting.
1086
     *
1087
     * Here we put some accounting values. There many more attributes for accounting, 
1088
     * but for web-applications only certain attributes make sense.
1089
     * @return void
1090
     */ 
1091
    function putAuthAttributes()
1092
    {
1093
        if (isset($this->username)) {
1094
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
1095
        }
1096
        $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
1097
        //if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
1098
        if (isset($this->session_time)) {
1099
            $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
1100
        }
1101
        if (isset($this->authentic)) {
1102
            $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
1103
        }
1104

    
1105
        $this->putStandardAttributes();
1106
    }
1107

    
1108
}
1109

    
1110
/**
1111
 * class Auth_RADIUS_Acct_Start
1112
 *
1113
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
1114
 * 
1115
 * @package Auth_RADIUS
1116
 */
1117
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct 
1118
{
1119
   /**
1120
     * Defines the type of the accounting request.
1121
     * It is set to RADIUS_START by default in this class.
1122
     * @var  integer
1123
     */
1124
    var $status_type = RADIUS_START;
1125
}
1126

    
1127
/**
1128
 * class Auth_RADIUS_Acct_Start
1129
 *
1130
 * Class for RADIUS accounting. Its usualy used, after the user has logged out.
1131
 *
1132
 * @package Auth_RADIUS
1133
 */
1134
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
1135
{
1136
   /**
1137
     * Defines the type of the accounting request.
1138
     * It is set to RADIUS_STOP by default in this class.
1139
     * @var  integer
1140
     */
1141
    var $status_type = RADIUS_STOP;
1142
}
1143

    
1144
if (!defined('RADIUS_UPDATE'))
1145
    define('RADIUS_UPDATE', 3);
1146

    
1147
/**
1148
 * class Auth_RADIUS_Acct_Update
1149
 *
1150
 * Class for interim RADIUS accounting updates.
1151
 *
1152
 * @package Auth_RADIUS
1153
 */
1154
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1155
{
1156
   /**
1157
     * Defines the type of the accounting request.
1158
     * It is set to RADIUS_UPDATE by default in this class.
1159
     * @var  integer
1160
     */
1161
    var $status_type = RADIUS_UPDATE;
1162
}
1163

    
1164
/**
1165
 * class Auth_RADIUS_Acct_On
1166
 *
1167
 * Class for sending Accounting-On updates
1168
 *
1169
 * @package Auth_RADIUS
1170
 */
1171
class Auth_RADIUS_Acct_On extends Auth_RADIUS_Acct
1172
{
1173
    /**
1174
      * Defines the type of the accounting request.
1175
      * It is set to RADIUS_ACCOUNTING_ON by default in this class.
1176
      * @var  integer
1177
      */
1178
    var $status_type = RADIUS_ACCOUNTING_ON;
1179
}
1180

    
1181
/**
1182
 * class Auth_RADIUS_Acct_Off
1183
 *
1184
 * Class for sending Accounting-Off updates
1185
 *
1186
 * @package Auth_RADIUS
1187
 */
1188
class Auth_RADIUS_Acct_Off extends Auth_RADIUS_Acct
1189
{
1190
    /**
1191
      * Defines the type of the accounting request.
1192
      * It is set to RADIUS_ACCOUNTING_OFF by default in this class.
1193
      * @var  integer
1194
      */
1195
    var $status_type = RADIUS_ACCOUNTING_OFF;
1196
}
1197

    
1198
?>
(45-45/66)