Project

General

Profile

Download (34.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 $g;
300

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

    
308
        // Add support for sending NAS-Identifier
309
	$nasId = php_uname("n");
310
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, $nasId);
311
    }
312

    
313
    /**
314
     * Puts custom attributes.
315
     *
316
     * @access public
317
     */
318
    function putAuthAttributes()
319
    {
320
        if (isset($this->username)) {
321
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
322
        }
323
    }
324

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

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

    
360
    /**
361
     * Initiates a RADIUS request. 
362
     *
363
     * @access public
364
     * @return bool  true on success, false on errors     
365
     */ 
366
    function start()
367
    {
368
        if (!$this->open()) {
369
            return false;
370
        }
371

    
372
        foreach ($this->_servers as $s) {
373
            // Servername, port, sharedsecret, timeout, retries
374
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
375
                return false;
376
            }
377
        }
378

    
379
        if (!empty($this->_configfile)) {
380
            if (!$this->putConfigfile($this->_configfile)) {
381
                return false;
382
            }
383
        }
384

    
385
        $this->createRequest();
386
        $this->putStandardAttributes();
387
        $this->putAuthAttributes();
388
        return true;
389
    }
390

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

    
404
        switch($req) {
405
        case RADIUS_ACCESS_ACCEPT:
406
            if (is_subclass_of($this, 'auth_radius_acct')) {
407
                return $this->raiseError(gettext('RADIUS_ACCESS_ACCEPT is unexpected for accounting'));
408
            }
409
            return true;
410

    
411
        case RADIUS_ACCESS_REJECT:
412
            return false;
413

    
414
        case RADIUS_ACCOUNTING_RESPONSE:
415
            if (is_subclass_of($this, 'auth_radius_pap')) {
416
                return $this->raiseError(gettext('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication'));
417
            }
418
            return true;
419

    
420
        default:
421
            return $this->raiseError(sprintf(gettext("Unexpected return value: %s"),$req));
422
        }
423

    
424
    }
425

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

    
441
        while ($attrib = radius_get_attr($this->res)) {
442

    
443
            if (!is_array($attrib)) {
444
                return false;
445
            }        
446

    
447
            $attr = $attrib['attr'];
448
            $data = $attrib['data'];
449

    
450
            $this->rawAttributes[$attr] = $data;
451

    
452
            switch ($attr) {
453
            case RADIUS_FRAMED_IP_ADDRESS:
454
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
455
                break;
456

    
457
            case RADIUS_FRAMED_IP_NETMASK:
458
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
459
                break;
460

    
461
            case RADIUS_FRAMED_MTU:
462
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
463
                break;
464

    
465
            case RADIUS_FRAMED_COMPRESSION:
466
                $this->attributes['framed_compression'] = radius_cvt_int($data);
467
                break;
468

    
469
            case RADIUS_SESSION_TIMEOUT:
470
                $this->attributes['session_timeout'] = radius_cvt_int($data);
471
                break;
472

    
473
            case RADIUS_IDLE_TIMEOUT:
474
                $this->attributes['idle_timeout'] = radius_cvt_int($data);
475
                break;
476

    
477
            case RADIUS_SERVICE_TYPE:
478
                $this->attributes['service_type'] = radius_cvt_int($data);
479
                break;
480

    
481
            case RADIUS_CLASS:
482
                $this->attributes['class'] = radius_cvt_int($data);
483
                break;
484

    
485
            case RADIUS_FRAMED_PROTOCOL:
486
                $this->attributes['framed_protocol'] = radius_cvt_int($data);
487
                break;
488

    
489
            case RADIUS_FRAMED_ROUTING:
490
                $this->attributes['framed_routing'] = radius_cvt_int($data);
491
                break;
492

    
493
            case RADIUS_FILTER_ID:
494
                $this->attributes['filter_id'] = radius_cvt_string($data);
495
                break;
496

    
497
            case RADIUS_REPLY_MESSAGE:
498
                $this->attributes['reply_message'] = radius_cvt_string($data);
499
                break;
500

    
501
            case RADIUS_VENDOR_SPECIFIC:
502
                $attribv = radius_get_vendor_attr($data);
503
                if (!is_array($attribv)) {
504
                    return false;
505
                }
506

    
507
                $vendor = $attribv['vendor'];
508
                $attrv = $attribv['attr'];
509
                $datav = $attribv['data'];
510

    
511
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
512

    
513
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
514

    
515
                    switch ($attrv) {
516
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
517
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
518
                        break;
519

    
520
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
521
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
522
                        break;
523

    
524
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
525
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
526
                        break;
527

    
528
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
529
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
530
                        break;
531

    
532
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
533
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
534
                        break;
535

    
536
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
537
                        $demangled = radius_demangle($this->res, $datav);
538
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
539
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
540
                        break;
541

    
542
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
543
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
544
                        break;
545

    
546
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
547
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
548
                        break;
549

    
550
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
551
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
552
                        break;
553
                    }
554
                }
555

    
556
                elseif ($vendor == 1584) {
557

    
558
                    switch ($attrv) {
559
                    case 102:
560
                        $this->attributes['ces_group'] = radius_cvt_string($datav);
561
                        break;
562
                    }
563
                }
564

    
565
                elseif ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
566

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

    
592
                elseif ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
593

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

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

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

    
671
                break;
672

    
673
            case 85: /* Acct-Interim-Interval: RFC 2869 */
674
                $this->attributes['interim_interval'] = radius_cvt_int($datav);
675
                break;
676
            }
677
        }
678

    
679
        return true;
680
    }
681

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

    
700
}
701

    
702
/**
703
 * class Auth_RADIUS_PAP
704
 *
705
 * Class for authenticating using PAP (Plaintext)
706
 *
707
 * @package Auth_RADIUS 
708
 */
709
class Auth_RADIUS_PAP extends Auth_RADIUS 
710
{
711

    
712
    /**
713
     * Constructor
714
     *
715
     * @param  string  $username   Username
716
     * @param  string  $password   Password
717
     * @return void
718
     */
719
    function Auth_RADIUS_PAP($username = null, $password = null)
720
    {
721
        $this->Auth_RADIUS();
722
        $this->username = $username;
723
        $this->password = $password;
724
    }
725

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

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

    
759
    /**
760
     * Put authentication specific attributes 
761
     *
762
     * @return void
763
     */
764
    function putAuthAttributes()
765
    {
766
        if (isset($this->username)) {
767
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
768
        }
769
        if (isset($this->password)) {
770
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
771
        }
772
    }
773

    
774
}
775

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

    
793
    /**
794
     * 16 Bytes MD5 response binary
795
     * @var  string
796
     */
797
    var $response = null;
798

    
799
    /**
800
     * Id of the authentication request. Should incremented after every request.
801
     * @var  integer
802
     */
803
    var $chapid = 1;
804

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

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

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

    
858
}
859

    
860
/**
861
 * class Auth_RADIUS_MSCHAPv1
862
 *
863
 * Class for authenticating using MS-CHAPv1 see RFC2433
864
 *
865
 * @package Auth_RADIUS 
866
 */
867
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 
868
{
869
    /**
870
     * LAN-Manager-Response
871
     * @var  string
872
     */
873
    var $lmResponse = null;
874

    
875
    /**
876
     * Wether using deprecated LM-Responses or not.
877
     * 0 = use LM-Response, 1 = use NT-Response
878
     * @var  bool
879
     */
880
    var $flags = 1;
881

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

    
913
/**
914
 * class Auth_RADIUS_MSCHAPv2
915
 *
916
 * Class for authenticating using MS-CHAPv2 see RFC2759
917
 *
918
 * @package Auth_RADIUS 
919
 */
920
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 
921
{
922
    /**
923
     * 16 Bytes binary challenge
924
     * @var  string
925
     */
926
    var $challenge = null;
927

    
928
    /**
929
     * 16 Bytes binary Peer Challenge
930
     * @var  string
931
     */
932
    var $peerChallenge = null;
933

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

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

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

    
995
   /**
996
     * Defines the type of the accounting request, on of:
997
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
998
     * @var  integer
999
     */    
1000
    var $status_type = null;
1001

    
1002
   /**
1003
     * The time the user was logged in in seconds
1004
     * @var  integer
1005
     */    
1006
    var $session_time = null;
1007

    
1008
   /**
1009
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
1010
     * @var  string
1011
     */    
1012
    var $session_id = null;
1013

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

    
1026
        if (isset($_SERVER)) {
1027
            $var = &$_SERVER;
1028
        } else {
1029
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1030
        }
1031

    
1032
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
1033
    }
1034
    */
1035

    
1036
    /**
1037
     * Constructor
1038
     *
1039
     */
1040

    
1041
    function Auth_RADIUS_Acct()
1042
    {
1043
        $this->Auth_RADIUS();
1044
    }
1045

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

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

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

    
1100
	$this->putStandardAttributes();
1101
    }
1102

    
1103
}
1104

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

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

    
1139
if (!defined('RADIUS_UPDATE'))
1140
    define('RADIUS_UPDATE', 3);
1141

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

    
1159
?>
(45-45/67)