Project

General

Profile

Download (35.6 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
                if (!array($this->attributes['class'])) {
484
                        $this->attributes['class'] = array();
485
                }
486
                $this->attributes['class'][] = radius_cvt_string($data);
487
                break;
488

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

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

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

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

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

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

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

    
517
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
518

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

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

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

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

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

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

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

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

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

    
560
                elseif ($vendor == 1584) {
561

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

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

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

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

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

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

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

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

    
685
                break;
686

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

    
693
        return true;
694
    }
695

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

    
714
}
715

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

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

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

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

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

    
788
}
789

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

    
807
    /**
808
     * 16 Bytes MD5 response binary
809
     * @var  string
810
     */
811
    var $response = null;
812

    
813
    /**
814
     * Id of the authentication request. Should incremented after every request.
815
     * @var  integer
816
     */
817
    var $chapid = 1;
818

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

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

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

    
872
}
873

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

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

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

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

    
942
    /**
943
     * 16 Bytes binary Peer Challenge
944
     * @var  string
945
     */
946
    var $peerChallenge = null;
947

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

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

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

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

    
1016
   /**
1017
     * The time the user was logged in in seconds
1018
     * @var  integer
1019
     */
1020
    var $session_time = null;
1021

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

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

    
1040
        if (isset($_SERVER)) {
1041
            $var = &$_SERVER;
1042
        } else {
1043
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1044
        }
1045

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

    
1050
    /**
1051
     * Constructor
1052
     *
1053
     */
1054

    
1055
    function Auth_RADIUS_Acct()
1056
    {
1057
        $this->Auth_RADIUS();
1058
    }
1059

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

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

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

    
1114
        $this->putStandardAttributes();
1115
    }
1116

    
1117
}
1118

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

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

    
1153
if (!defined('RADIUS_UPDATE'))
1154
    define('RADIUS_UPDATE', 3);
1155

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

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

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

    
1207
?>
(45-45/65)