Project

General

Profile

Download (36.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
/*
4
    radius.inc
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
require_once("PEAR.php");
51
require_once("radius_authentication.inc");
52
require_once("radius_accounting.inc");
53

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

    
65
PEAR::loadExtension('radius');
66

    
67
/**
68
 * class Auth_RADIUS
69
 *
70
 * Abstract base class for RADIUS
71
 *
72
 * @package Auth_RADIUS
73
 */
74
class Auth_RADIUS extends PEAR {
75

    
76
    /**
77
     * List of RADIUS servers.
78
     * @var  array
79
     * @see  addServer(), putServer()
80
     */
81
    var $_servers  = array();
82

    
83
    /**
84
     * Path to the configuration-file.
85
     * @var  string
86
     * @see  setConfigFile()
87
     */
88
    var $_configfile = null;
89

    
90
    /**
91
     * Resource.
92
     * @var  resource
93
     * @see  open(), close()
94
     */
95
    var $res = null;
96

    
97
    /**
98
     * Username for authentication and accounting requests.
99
     * @var  string
100
     */
101
    var $username = null;
102

    
103
    /**
104
     * Password for plaintext-authentication (PAP).
105
     * @var  string
106
     */
107
    var $password = null;
108

    
109
    /**
110
     * List of known attributes.
111
     * @var  array
112
     * @see  dumpAttributes(), getAttributes()
113
     */
114
    var $attributes = array();
115

    
116
    /**
117
     * List of raw attributes.
118
     * @var  array
119
     * @see  dumpAttributes(), getAttributes()
120
     */
121
    var $rawAttributes = array();
122

    
123
    /**
124
     * List of raw vendor specific attributes.
125
     * @var  array
126
     * @see  dumpAttributes(), getAttributes()
127
     */
128
    var $rawVendorAttributes = array();
129

    
130
    /**
131
     * Constructor
132
     *
133
     * Loads the RADIUS PECL/extension
134
     *
135
     * @return void
136
     */
137
    function Auth_RADIUS()
138
    {
139
        $this->PEAR();
140
    }
141

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

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

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

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

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

    
205
        case 'addr':
206
            return radius_put_addr($this->res, $attrib, $value);
207

    
208
        case 'string':
209
        default:
210
            return radius_put_attr($this->res, $attrib, $value);
211
        }
212

    
213
    }
214

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

    
228
        if ($type == null) {
229
            $type = gettype($value);
230
        }
231

    
232
        switch ($type) {
233
        case 'integer':
234
            return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
235

    
236
        case 'addr':
237
            return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
238

    
239
        case 'string':
240
        default:
241
            return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
242
        }
243

    
244
    }
245

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

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

    
268
    /**
269
     * Overwrite this.
270
     *
271
     * @access public
272
     */
273
    function open()
274
    {
275
    }
276

    
277
    /**
278
     * Overwrite this.
279
     *
280
     * @access public
281
     */
282
    function createRequest()
283
    {
284
    }
285

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

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

    
305
        // Add support for sending NAS-Identifier
306
        if (function_exists("getNasID")) {
307
            $nasId = getNasID();
308
        } else if (empty($config["captiveportal"][$cpzone]["radiusnasid"])) {
309
            $nasId = php_uname("n");
310
        } else {
311
            $nasId = $config["captiveportal"][$cpzone]["radiusnasid"];
312
        }
313
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, $nasId);
314
        
315
        if (function_exists("getNasPortType")) {
316
            $this->putAttribute(RADIUS_NAS_PORT_TYPE, getNasPortType());
317
        }
318
        
319
        if (function_exists("getNasPort")) {
320
            $this->putAttribute(RADIUS_NAS_PORT, getNasPort(), 'integer');
321
        }
322
        
323
        if (function_exists("getCalledStationId")) {
324
            $this->putAttribute(RADIUS_CALLED_STATION_ID, getCalledStationId());
325
        }
326
    }
327

    
328
    /**
329
     * Puts custom attributes.
330
     *
331
     * @access public
332
     */
333
    function putAuthAttributes()
334
    {
335
        if (isset($this->username)) {
336
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
337
        }
338
    }
339

    
340
    /**
341
     * Configures the radius library.
342
     *
343
     * @access public
344
     * @param  string  $servername   Servername or IP-Address
345
     * @param  integer $port         Portnumber
346
     * @param  string  $sharedSecret Shared secret
347
     * @param  integer $timeout      Timeout for each request
348
     * @param  integer $maxtries     Max. retries for each request
349
     * @return bool  true on success, false on error
350
     * @see addServer()
351
     */
352
    function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
353
    {
354
        if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
355
            return false;
356
        }
357
        return true;
358
    }
359

    
360
    /**
361
     * Configures the radius library via external configurationfile
362
     *
363
     * @access public
364
     * @param  string  $servername   Servername or IP-Address
365
     * @return bool  true on success, false on error
366
     */
367
    function putConfigfile($file)
368
    {
369
        if (!radius_config($this->res, $file)) {
370
            return false;
371
        }
372
        return true;
373
    }
374

    
375
    /**
376
     * Initiates a RADIUS request.
377
     *
378
     * @access public
379
     * @return bool  true on success, false on errors
380
     */
381
    function start()
382
    {
383
        if (!$this->open()) {
384
            return false;
385
        }
386

    
387
        foreach ($this->_servers as $s) {
388
            // Servername, port, sharedsecret, timeout, retries
389
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
390
                return false;
391
            }
392
        }
393

    
394
        if (!empty($this->_configfile)) {
395
            if (!$this->putConfigfile($this->_configfile)) {
396
                return false;
397
            }
398
        }
399

    
400
        $this->createRequest();
401
        $this->putStandardAttributes();
402
        $this->putAuthAttributes();
403
        return true;
404
    }
405

    
406
    /**
407
     * Sends a prepared RADIUS request and waits for a response
408
     *
409
     * @access public
410
     * @return mixed  true on success, false on reject, PEAR_Error on error
411
     */
412
    function send()
413
    {
414
        $req = radius_send_request($this->res);
415
        if (!$req) {
416
            return $this->raiseError(gettext('Error sending request:') . ' ' . $this->getError());
417
        }
418

    
419
        switch($req) {
420
        case RADIUS_ACCESS_ACCEPT:
421
            if (is_subclass_of($this, 'auth_radius_acct')) {
422
                return $this->raiseError(gettext('RADIUS_ACCESS_ACCEPT is unexpected for accounting'));
423
            }
424
            return true;
425

    
426
        case RADIUS_ACCESS_REJECT:
427
            return false;
428

    
429
        case RADIUS_ACCOUNTING_RESPONSE:
430
            if (is_subclass_of($this, 'auth_radius_pap')) {
431
                return $this->raiseError(gettext('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication'));
432
            }
433
            return true;
434

    
435
        default:
436
            return $this->raiseError(sprintf(gettext("Unexpected return value: %s"),$req));
437
        }
438

    
439
    }
440

    
441
    /**
442
     * Reads all received attributes after sending the request.
443
     *
444
     * This methos stores know attributes in the property attributes,
445
     * all attributes (including known attibutes) are stored in rawAttributes
446
     * or rawVendorAttributes.
447
     * NOTE: call this functio also even if the request was rejected, because the
448
     * Server returns usualy an errormessage
449
     *
450
     * @access public
451
     * @return bool   true on success, false on error
452
     */
453
    function getAttributes()
454
    {
455

    
456
        while ($attrib = radius_get_attr($this->res)) {
457

    
458
            if (!is_array($attrib)) {
459
                return false;
460
            }
461

    
462
            $attr = $attrib['attr'];
463
            $data = $attrib['data'];
464

    
465
            $this->rawAttributes[$attr] = $data;
466

    
467
            switch ($attr) {
468
            case RADIUS_FRAMED_IP_ADDRESS:
469
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
470
                break;
471

    
472
            case RADIUS_FRAMED_IP_NETMASK:
473
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
474
                break;
475

    
476
            case RADIUS_FRAMED_MTU:
477
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
478
                break;
479

    
480
            case RADIUS_FRAMED_COMPRESSION:
481
                $this->attributes['framed_compression'] = radius_cvt_int($data);
482
                break;
483

    
484
            case RADIUS_SESSION_TIMEOUT:
485
                $this->attributes['session_timeout'] = radius_cvt_int($data);
486
                break;
487

    
488
            case RADIUS_IDLE_TIMEOUT:
489
                $this->attributes['idle_timeout'] = radius_cvt_int($data);
490
                break;
491

    
492
            case RADIUS_SERVICE_TYPE:
493
                $this->attributes['service_type'] = radius_cvt_int($data);
494
                break;
495

    
496
            case RADIUS_CLASS:
497
                if (!array($this->attributes['class'])) {
498
                        $this->attributes['class'] = array();
499
                }
500
                $this->attributes['class'][] = radius_cvt_string($data);
501
                break;
502

    
503
            case RADIUS_FRAMED_PROTOCOL:
504
                $this->attributes['framed_protocol'] = radius_cvt_int($data);
505
                break;
506

    
507
            case RADIUS_FRAMED_ROUTING:
508
                $this->attributes['framed_routing'] = radius_cvt_int($data);
509
                break;
510

    
511
            case RADIUS_FILTER_ID:
512
                $this->attributes['filter_id'] = radius_cvt_string($data);
513
                break;
514

    
515
            case RADIUS_REPLY_MESSAGE:
516
                $this->attributes['reply_message'] = radius_cvt_string($data);
517
                break;
518

    
519
            case RADIUS_VENDOR_SPECIFIC:
520
                $attribv = radius_get_vendor_attr($data);
521
                if (!is_array($attribv)) {
522
                    return false;
523
                }
524

    
525
                $vendor = $attribv['vendor'];
526
                $attrv = $attribv['attr'];
527
                $datav = $attribv['data'];
528

    
529
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
530

    
531
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
532

    
533
                    switch ($attrv) {
534
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
535
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
536
                        break;
537

    
538
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
539
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
540
                        break;
541

    
542
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
543
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
544
                        break;
545

    
546
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
547
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
548
                        break;
549

    
550
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
551
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
552
                        break;
553

    
554
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
555
                        $demangled = radius_demangle($this->res, $datav);
556
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
557
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
558
                        break;
559

    
560
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
561
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
562
                        break;
563

    
564
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
565
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
566
                        break;
567

    
568
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
569
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
570
                        break;
571
                    }
572
                }
573

    
574
                elseif ($vendor == 1584) {
575

    
576
                    switch ($attrv) {
577
                    case 102:
578
                        $this->attributes['ces_group'] = radius_cvt_string($datav);
579
                        break;
580
                    }
581
                }
582

    
583
                elseif ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
584

    
585
                    switch ($attrv) {
586
                    case 1: /* RADIUS_NOMADIX_BW_UP */
587
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
588
                        break;
589
                    case 2: /* RADIUS_NOMADIX_BW_DOWN */
590
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
591
                        break;
592
                    case 3: /* RADIUS_NOMADIX_URL_REDIRECTION */
593
                        $this->attributes['url_redirection'] = radius_cvt_string($datav);
594
                        break;
595
                    case 5: /* RADIUS_NOMADIX_EXPIRATION */
596
                        $this->attributes['expiration'] = radius_cvt_string($datav);
597
                        break;
598
                    case 7: /* RADIUS_NOMADIX_MAXBYTESUP */
599
                        $this->attributes['maxbytesup'] = radius_cvt_int($datav);
600
                        break;
601
                    case 8: /* RADIUS_NOMADIX_MAXBYTESDOWN */
602
                        $this->attributes['maxbytesdown'] = radius_cvt_int($datav);
603
                        break;
604
                    case 10: /* RADIUS_NOMADIX_LOGOFF_URL */
605
                        $this->attributes['url_logoff'] = radius_cvt_string($datav);
606
                        break;
607
                    }
608
                }
609

    
610
                elseif ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
611

    
612
                    switch ($attrv) {
613
                    case 1: /* WISPr-Location-ID */
614
                        $this->attributes['location_id'] = radius_cvt_string($datav);
615
                        break;
616
                    case 2: /* WISPr-Location-Name */
617
                        $this->attributes['location_name'] = radius_cvt_string($datav);
618
                        break;
619
                    case 3: /* WISPr-Logoff-URL */
620
                        $this->attributes['url_logoff'] = radius_cvt_string($datav);
621
                        break;
622
                    case 4: /* WISPr-Redirection-URL */
623
                        $this->attributes['url_redirection'] = radius_cvt_string($datav);
624
                        break;
625
                    case 5: /* WISPr-Bandwidth-Min-Up */
626
                        $this->attributes['bw_up_min'] = radius_cvt_int($datav);
627
                        break;
628
                    case 6: /* WISPr-Bandwidth-Min-Down */
629
                        $this->attributes['bw_down_min'] = radius_cvt_int($datav);
630
                        break;
631
                    case 7: /* WISPr-Bandwidth-Max-Up */
632
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
633
                        break;
634
                    case 8: /* WISPr-Bandwidth-Max-Down */
635
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
636
                        break;
637
                    case 9: /* WISPr-Session-Terminate-Time */
638
                        $this->attributes['session_terminate_time'] = radius_cvt_string($datav);
639
                        break;
640
                    case 10: /* WISPr-Session-Terminate-End-Of-Day */
641
                        $this->attributes['session_terminate_endofday'] = radius_cvt_int($datav);
642
                        break;
643
                    case 11: /* WISPr-Billing-Class-Of-Service */
644
                        $this->attributes['billing_class_of_service'] = radius_cvt_string($datav);
645
                        break;
646
                    }
647
                }
648

    
649
                elseif ($vendor == 14559) { /* RADIUS_VENDOR_ChilliSpot */
650
                    switch ($attrv) {
651
                    case 4: /* ChilliSpot-Bandwidth-Max-Up */
652
                        $this->attributes['bw_up'] = radius_cvt_int($datav);
653
                        break;
654
                    case 5: /* ChilliSpot-Bandwidth-Max-Down */
655
                        $this->attributes['bw_down'] = radius_cvt_int($datav);
656
                        break;
657
                    }
658
                }
659

    
660
		elseif ($vendor == 9) { /* RADIUS_VENDOR_CISCO */
661
			switch ($attrv) {
662
			case 1: /* Cisco-AVPair */
663
				if (!is_array($this->attributes['ciscoavpair']))
664
					$this->attributes['ciscoavpair'] = array();
665
				$this->attributes['ciscoavpair'][] = radius_cvt_string($datav);
666
				break;
667
			}
668
		}
669

    
670
                elseif ($vendor == 8744) { /* Colubris / HP MSM wireless */
671
                    //documented at http://bizsupport1.austin.hp.com/bc/docs/support/SupportManual/c02704528/c02704528.pdf pg 15-67
672
                    if ($attrv == 0) { /* Colubris AV-Pair */
673
                        $datav = explode('=', $datav);
674
                        switch ($datav[0]) {
675
                        case 'max-input-rate':
676
                            // "Controls the data rate [kbps] at which traffic can be transferred from the user to the [router]."
677
                            $this->attributes['bw_up'] = radius_cvt_int($datav[1]);
678
                            break;
679
                        case 'max-output-rate':
680
                            //"Controls the data rate [kbps] at which traffic can be transferred from the [router] to the user."
681
                            $this->attributes['bw_down'] = radius_cvt_int($datav[1]);
682
                            break;
683
                        case 'max-input-octets':
684
                            $this->attributes['maxbytesup'] = radius_cvt_int($datav[1]);
685
                            break;
686
                        case 'max-output-octets':
687
                            $this->attributes['maxbytesdown'] = radius_cvt_int($datav[1]);
688
                            break;
689
                        case 'welcome-url':
690
                            $this->attributes['url_redirection'] = radius_cvt_string($datav[1]);
691
                            break;
692
                        case 'goodbye-url':
693
                            $this->attributes['url_logoff'] = radius_cvt_string($datav[1]);
694
                            break;
695
                        }
696
                    }
697
                }
698

    
699
                break;
700

    
701
            case 85: /* Acct-Interim-Interval: RFC 2869 */
702
                $this->attributes['interim_interval'] = radius_cvt_int($data);
703
                break;
704
            }
705
        }
706

    
707
        return true;
708
    }
709

    
710
    /**
711
     * Frees resources.
712
     *
713
     * Calling this method is always a good idea, because all security relevant
714
     * attributes are filled with Nullbytes to leave nothing in the mem.
715
     *
716
     * @access public
717
     */
718
    function close()
719
    {
720
        if ($this->res != null) {
721
            radius_close($this->res);
722
            $this->res = null;
723
        }
724
        $this->username = str_repeat("\0", strlen($this->username));
725
        $this->password = str_repeat("\0", strlen($this->password));
726
    }
727

    
728
}
729

    
730
/**
731
 * class Auth_RADIUS_PAP
732
 *
733
 * Class for authenticating using PAP (Plaintext)
734
 *
735
 * @package Auth_RADIUS
736
 */
737
class Auth_RADIUS_PAP extends Auth_RADIUS
738
{
739

    
740
    /**
741
     * Constructor
742
     *
743
     * @param  string  $username   Username
744
     * @param  string  $password   Password
745
     * @return void
746
     */
747
    function Auth_RADIUS_PAP($username = null, $password = null)
748
    {
749
        $this->Auth_RADIUS();
750
        $this->username = $username;
751
        $this->password = $password;
752
    }
753

    
754
    /**
755
     * Creates a RADIUS resource
756
     *
757
     * Creates a RADIUS resource for authentication. This should be the first
758
     * call before you make any other things with the library.
759
     *
760
     * @return bool   true on success, false on error
761
     */
762
    function open()
763
    {
764
        $this->res = radius_auth_open();
765
        if (!$this->res) {
766
            return false;
767
        }
768
        return true;
769
    }
770

    
771
    /**
772
     * Creates an authentication request
773
     *
774
     * Creates an authentication request.
775
     * You MUST call this method before you can put any attribute
776
     *
777
     * @return bool   true on success, false on error
778
     */
779
    function createRequest()
780
    {
781
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
782
            return false;
783
        }
784
        return true;
785
    }
786

    
787
    /**
788
     * Put authentication specific attributes
789
     *
790
     * @return void
791
     */
792
    function putAuthAttributes()
793
    {
794
        if (isset($this->username)) {
795
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
796
        }
797
        if (isset($this->password)) {
798
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
799
        }
800
    }
801

    
802
}
803

    
804
/**
805
 * class Auth_RADIUS_CHAP_MD5
806
 *
807
 * Class for authenticating using CHAP-MD5 see RFC1994.
808
 * Instead og the plaintext password the challenge and
809
 * the response are needed.
810
 *
811
 * @package Auth_RADIUS
812
 */
813
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
814
{
815
    /**
816
     * 8 Bytes binary challenge
817
     * @var  string
818
     */
819
    var $challenge = null;
820

    
821
    /**
822
     * 16 Bytes MD5 response binary
823
     * @var  string
824
     */
825
    var $response = null;
826

    
827
    /**
828
     * Id of the authentication request. Should incremented after every request.
829
     * @var  integer
830
     */
831
    var $chapid = 1;
832

    
833
    /**
834
     * Constructor
835
     *
836
     * @param  string  $username   Username
837
     * @param  string  $challenge  8 Bytes Challenge (binary)
838
     * @param  integer $chapid     Requestnumber
839
     * @return void
840
     */
841
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
842
    {
843
        $this->Auth_RADIUS_PAP();
844
        $this->username = $username;
845
        $this->challenge = $challenge;
846
        $this->chapid = $chapid;
847
    }
848

    
849
    /**
850
     * Put CHAP-MD5 specific attributes
851
     *
852
     * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
853
     * and the response. The chapid is inserted in the first byte of the response.
854
     *
855
     * @return void
856
     */
857
    function putAuthAttributes()
858
    {
859
        if (isset($this->username)) {
860
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
861
        }
862
        if (isset($this->response)) {
863
            $response = pack('C', $this->chapid) . $this->response;
864
            $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
865
        }
866
        if (isset($this->challenge)) {
867
            $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
868
        }
869
    }
870

    
871
    /**
872
     * Frees resources.
873
     *
874
     * Calling this method is always a good idea, because all security relevant
875
     * attributes are filled with Nullbytes to leave nothing in the mem.
876
     *
877
     * @access public
878
     */
879
    function close()
880
    {
881
        Auth_RADIUS_PAP::close();
882
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
883
        $this->response =  str_repeat("\0", strlen($this->response));
884
    }
885

    
886
}
887

    
888
/**
889
 * class Auth_RADIUS_MSCHAPv1
890
 *
891
 * Class for authenticating using MS-CHAPv1 see RFC2433
892
 *
893
 * @package Auth_RADIUS
894
 */
895
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
896
{
897
    /**
898
     * LAN-Manager-Response
899
     * @var  string
900
     */
901
    var $lmResponse = null;
902

    
903
    /**
904
     * Wether using deprecated LM-Responses or not.
905
     * 0 = use LM-Response, 1 = use NT-Response
906
     * @var  bool
907
     */
908
    var $flags = 1;
909

    
910
    /**
911
     * Put MS-CHAPv1 specific attributes
912
     *
913
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
914
     * and the response. The response has this structure:
915
     * struct rad_mschapvalue {
916
     *   u_char ident;
917
     *   u_char flags;
918
     *   u_char lm_response[24];
919
     *   u_char response[24];
920
     * };
921
     *
922
     * @return void
923
     */
924
    function putAuthAttributes()
925
    {
926
        if (isset($this->username)) {
927
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
928
        }
929
        if (isset($this->response) || isset($this->lmResponse)) {
930
            $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
931
            $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
932
            $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
933
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
934
        }
935
        if (isset($this->challenge)) {
936
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
937
        }
938
    }
939
}
940

    
941
/**
942
 * class Auth_RADIUS_MSCHAPv2
943
 *
944
 * Class for authenticating using MS-CHAPv2 see RFC2759
945
 *
946
 * @package Auth_RADIUS
947
 */
948
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
949
{
950
    /**
951
     * 16 Bytes binary challenge
952
     * @var  string
953
     */
954
    var $challenge = null;
955

    
956
    /**
957
     * 16 Bytes binary Peer Challenge
958
     * @var  string
959
     */
960
    var $peerChallenge = null;
961

    
962
  /**
963
     * Put MS-CHAPv2 specific attributes
964
     *
965
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
966
     * and the response. The response has this structure:
967
     * struct rad_mschapv2value {
968
     *   u_char ident;
969
     *   u_char flags;
970
     *   u_char pchallenge[16];
971
     *   u_char reserved[8];
972
     *   u_char response[24];
973
     * };
974
     * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
975
     * @return void
976
     */
977
    function putAuthAttributes()
978
    {
979
        if (isset($this->username)) {
980
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
981
        }
982
        if (isset($this->response) && isset($this->peerChallenge)) {
983
            // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
984
            $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
985
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
986
        }
987
        if (isset($this->challenge)) {
988
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
989
        }
990
    }
991

    
992
    /**
993
     * Frees resources.
994
     *
995
     * Calling this method is always a good idea, because all security relevant
996
     * attributes are filled with Nullbytes to leave nothing in the mem.
997
     *
998
     * @access public
999
     */
1000
    function close()
1001
    {
1002
        Auth_RADIUS_MSCHAPv1::close();
1003
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
1004
    }
1005
}
1006

    
1007
/**
1008
 * class Auth_RADIUS_Acct
1009
 *
1010
 * Class for RADIUS accounting
1011
 *
1012
 * @package Auth_RADIUS
1013
 */
1014
class Auth_RADIUS_Acct extends Auth_RADIUS
1015
{
1016
    /**
1017
     * Defines where the Authentication was made, possible values are:
1018
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
1019
     * @var  integer
1020
     */
1021
    var $authentic = null;
1022

    
1023
   /**
1024
     * Defines the type of the accounting request, on of:
1025
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
1026
     * @var  integer
1027
     */
1028
    var $status_type = null;
1029

    
1030
   /**
1031
     * The time the user was logged in in seconds
1032
     * @var  integer
1033
     */
1034
    var $session_time = null;
1035

    
1036
   /**
1037
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
1038
     * @var  string
1039
     */
1040
    var $session_id = null;
1041

    
1042
    /**
1043
     * Constructor
1044
     *
1045
     * This function is disabled for M0n0wall since we use our own session_id
1046
     *
1047
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
1048
     * @return void
1049
     *
1050
    function Auth_RADIUS_Acct()
1051
    {
1052
        $this->Auth_RADIUS();
1053

    
1054
        if (isset($_SERVER)) {
1055
            $var = &$_SERVER;
1056
        } else {
1057
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1058
        }
1059

    
1060
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
1061
    }
1062
    */
1063

    
1064
    /**
1065
     * Constructor
1066
     *
1067
     */
1068

    
1069
    function Auth_RADIUS_Acct()
1070
    {
1071
        $this->Auth_RADIUS();
1072
    }
1073

    
1074
    /**
1075
     * Creates a RADIUS resource
1076
     *
1077
     * Creates a RADIUS resource for accounting. This should be the first
1078
     * call before you make any other things with the library.
1079
     *
1080
     * @return bool   true on success, false on error
1081
     */
1082
    function open()
1083
    {
1084
        $this->res = radius_acct_open();
1085
        if (!$this->res) {
1086
            return false;
1087
        }
1088
        return true;
1089
    }
1090

    
1091
   /**
1092
     * Creates an accounting request
1093
     *
1094
     * Creates an accounting request.
1095
     * You MUST call this method before you can put any attribute.
1096
     *
1097
     * @return bool   true on success, false on error
1098
     */
1099
    function createRequest()
1100
    {
1101
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
1102
            return false;
1103
        }
1104
        return true;
1105
    }
1106

    
1107
  /**
1108
     * Put attributes for accounting.
1109
     *
1110
     * Here we put some accounting values. There many more attributes for accounting,
1111
     * but for web-applications only certain attributes make sense.
1112
     * @return void
1113
     */
1114
    function putAuthAttributes()
1115
    {
1116
        if (isset($this->username)) {
1117
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
1118
        }
1119
        $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
1120
        //if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
1121
        if (isset($this->session_time)) {
1122
            $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
1123
        }
1124
        if (isset($this->authentic)) {
1125
            $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
1126
        }
1127

    
1128
        $this->putStandardAttributes();
1129
    }
1130

    
1131
}
1132

    
1133
/**
1134
 * class Auth_RADIUS_Acct_Start
1135
 *
1136
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
1137
 *
1138
 * @package Auth_RADIUS
1139
 */
1140
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
1141
{
1142
   /**
1143
     * Defines the type of the accounting request.
1144
     * It is set to RADIUS_START by default in this class.
1145
     * @var  integer
1146
     */
1147
    var $status_type = RADIUS_START;
1148
}
1149

    
1150
/**
1151
 * class Auth_RADIUS_Acct_Start
1152
 *
1153
 * Class for RADIUS accounting. Its usualy used, after the user has logged out.
1154
 *
1155
 * @package Auth_RADIUS
1156
 */
1157
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
1158
{
1159
   /**
1160
     * Defines the type of the accounting request.
1161
     * It is set to RADIUS_STOP by default in this class.
1162
     * @var  integer
1163
     */
1164
    var $status_type = RADIUS_STOP;
1165
}
1166

    
1167
if (!defined('RADIUS_UPDATE'))
1168
    define('RADIUS_UPDATE', 3);
1169

    
1170
/**
1171
 * class Auth_RADIUS_Acct_Update
1172
 *
1173
 * Class for interim RADIUS accounting updates.
1174
 *
1175
 * @package Auth_RADIUS
1176
 */
1177
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1178
{
1179
   /**
1180
     * Defines the type of the accounting request.
1181
     * It is set to RADIUS_UPDATE by default in this class.
1182
     * @var  integer
1183
     */
1184
    var $status_type = RADIUS_UPDATE;
1185
}
1186

    
1187
/**
1188
 * class Auth_RADIUS_Acct_On
1189
 *
1190
 * Class for sending Accounting-On updates
1191
 *
1192
 * @package Auth_RADIUS
1193
 */
1194
class Auth_RADIUS_Acct_On extends Auth_RADIUS_Acct
1195
{
1196
    /**
1197
      * Defines the type of the accounting request.
1198
      * It is set to RADIUS_ACCOUNTING_ON by default in this class.
1199
      * @var  integer
1200
      */
1201
    var $status_type = RADIUS_ACCOUNTING_ON;
1202
}
1203

    
1204
/**
1205
 * class Auth_RADIUS_Acct_Off
1206
 *
1207
 * Class for sending Accounting-Off updates
1208
 *
1209
 * @package Auth_RADIUS
1210
 */
1211
class Auth_RADIUS_Acct_Off extends Auth_RADIUS_Acct
1212
{
1213
    /**
1214
      * Defines the type of the accounting request.
1215
      * It is set to RADIUS_ACCOUNTING_OFF by default in this class.
1216
      * @var  integer
1217
      */
1218
    var $status_type = RADIUS_ACCOUNTING_OFF;
1219
}
1220

    
1221
?>
(38-38/54)