Project

General

Profile

Download (35.4 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.inc");
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 (empty($config["captiveportal"][$cpzone]["radiusnasid"])) {
307
            $nasId = php_uname("n");
308
        } else {
309
            $nasId = $config["captiveportal"][$cpzone]["radiusnasid"];
310
        }
311
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, $nasId);
312
    }
313

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

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

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

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

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

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

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

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

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

    
412
        case RADIUS_ACCESS_REJECT:
413
            return false;
414

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

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

    
425
    }
426

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
514
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
515

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

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

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

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

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

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

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

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

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

    
557
                elseif ($vendor == 1584) {
558

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

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

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

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

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

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

    
643
		elseif ($vendor == 9) { /* RADIUS_VENDOR_CISCO */
644
			switch ($attrv) {
645
			case 1: /* Cisco-AVPair */
646
				if (!is_array($this->attributes['ciscoavpair']))
647
					$this->attributes['ciscoavpair'] = array();
648
				$this->attributes['ciscoavpair'][] = radius_cvt_string($datav);
649
				break;
650
			}
651
		}
652

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

    
682
                break;
683

    
684
            case 85: /* Acct-Interim-Interval: RFC 2869 */
685
                $this->attributes['interim_interval'] = radius_cvt_int($data);
686
                break;
687
            }
688
        }
689

    
690
        return true;
691
    }
692

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

    
711
}
712

    
713
/**
714
 * class Auth_RADIUS_PAP
715
 *
716
 * Class for authenticating using PAP (Plaintext)
717
 *
718
 * @package Auth_RADIUS
719
 */
720
class Auth_RADIUS_PAP extends Auth_RADIUS
721
{
722

    
723
    /**
724
     * Constructor
725
     *
726
     * @param  string  $username   Username
727
     * @param  string  $password   Password
728
     * @return void
729
     */
730
    function Auth_RADIUS_PAP($username = null, $password = null)
731
    {
732
        $this->Auth_RADIUS();
733
        $this->username = $username;
734
        $this->password = $password;
735
    }
736

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

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

    
770
    /**
771
     * Put authentication specific attributes
772
     *
773
     * @return void
774
     */
775
    function putAuthAttributes()
776
    {
777
        if (isset($this->username)) {
778
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
779
        }
780
        if (isset($this->password)) {
781
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
782
        }
783
    }
784

    
785
}
786

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

    
804
    /**
805
     * 16 Bytes MD5 response binary
806
     * @var  string
807
     */
808
    var $response = null;
809

    
810
    /**
811
     * Id of the authentication request. Should incremented after every request.
812
     * @var  integer
813
     */
814
    var $chapid = 1;
815

    
816
    /**
817
     * Constructor
818
     *
819
     * @param  string  $username   Username
820
     * @param  string  $challenge  8 Bytes Challenge (binary)
821
     * @param  integer $chapid     Requestnumber
822
     * @return void
823
     */
824
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
825
    {
826
        $this->Auth_RADIUS_PAP();
827
        $this->username = $username;
828
        $this->challenge = $challenge;
829
        $this->chapid = $chapid;
830
    }
831

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

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

    
869
}
870

    
871
/**
872
 * class Auth_RADIUS_MSCHAPv1
873
 *
874
 * Class for authenticating using MS-CHAPv1 see RFC2433
875
 *
876
 * @package Auth_RADIUS
877
 */
878
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
879
{
880
    /**
881
     * LAN-Manager-Response
882
     * @var  string
883
     */
884
    var $lmResponse = null;
885

    
886
    /**
887
     * Wether using deprecated LM-Responses or not.
888
     * 0 = use LM-Response, 1 = use NT-Response
889
     * @var  bool
890
     */
891
    var $flags = 1;
892

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

    
924
/**
925
 * class Auth_RADIUS_MSCHAPv2
926
 *
927
 * Class for authenticating using MS-CHAPv2 see RFC2759
928
 *
929
 * @package Auth_RADIUS
930
 */
931
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
932
{
933
    /**
934
     * 16 Bytes binary challenge
935
     * @var  string
936
     */
937
    var $challenge = null;
938

    
939
    /**
940
     * 16 Bytes binary Peer Challenge
941
     * @var  string
942
     */
943
    var $peerChallenge = null;
944

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

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

    
990
/**
991
 * class Auth_RADIUS_Acct
992
 *
993
 * Class for RADIUS accounting
994
 *
995
 * @package Auth_RADIUS
996
 */
997
class Auth_RADIUS_Acct extends Auth_RADIUS
998
{
999
    /**
1000
     * Defines where the Authentication was made, possible values are:
1001
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
1002
     * @var  integer
1003
     */
1004
    var $authentic = null;
1005

    
1006
   /**
1007
     * Defines the type of the accounting request, on of:
1008
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
1009
     * @var  integer
1010
     */
1011
    var $status_type = null;
1012

    
1013
   /**
1014
     * The time the user was logged in in seconds
1015
     * @var  integer
1016
     */
1017
    var $session_time = null;
1018

    
1019
   /**
1020
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
1021
     * @var  string
1022
     */
1023
    var $session_id = null;
1024

    
1025
    /**
1026
     * Constructor
1027
     *
1028
     * This function is disabled for M0n0wall since we use our own session_id
1029
     *
1030
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
1031
     * @return void
1032
     *
1033
    function Auth_RADIUS_Acct()
1034
    {
1035
        $this->Auth_RADIUS();
1036

    
1037
        if (isset($_SERVER)) {
1038
            $var = &$_SERVER;
1039
        } else {
1040
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1041
        }
1042

    
1043
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
1044
    }
1045
    */
1046

    
1047
    /**
1048
     * Constructor
1049
     *
1050
     */
1051

    
1052
    function Auth_RADIUS_Acct()
1053
    {
1054
        $this->Auth_RADIUS();
1055
    }
1056

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

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

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

    
1111
        $this->putStandardAttributes();
1112
    }
1113

    
1114
}
1115

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

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

    
1150
if (!defined('RADIUS_UPDATE'))
1151
    define('RADIUS_UPDATE', 3);
1152

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

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

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

    
1204
?>
(45-45/65)