Project

General

Profile

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

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

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

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

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

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

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

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

    
48
*/
49

    
50
/*
51
	pfSense_MODULE:	auth
52
*/
53

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
217
    }
218

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

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

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

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

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

    
248
    }
249

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

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

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

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

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

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

    
308
        // Add support for sending NAS-Identifier
309
	$nasId = "";
310
	exec("/bin/hostname", $nasId);
311
	if(!$nasId[0])
312
		$nasId[0] = "{$g['product_name']}";
313
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, $nasId[0]);
314
    }
315

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

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

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

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

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

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

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

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

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

    
414
        case RADIUS_ACCESS_REJECT:
415
            return false;
416

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

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

    
427
    }
428

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

    
444
        while ($attrib = radius_get_attr($this->res)) {
445

    
446
            if (!is_array($attrib)) {
447
                return false;
448
            }        
449

    
450
            $attr = $attrib['attr'];
451
            $data = $attrib['data'];
452

    
453
            $this->rawAttributes[$attr] = $data;
454

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
516
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
517

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

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

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

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

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

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

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

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

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

    
559
                if ($vendor == 1584) {
560

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

    
568
                if ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
569

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

    
595
        	if ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
596

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

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

    
645
                break;
646

    
647
            }
648
        }
649

    
650
        return true;
651
    }
652

    
653
    /**
654
     * Frees resources.
655
     *
656
     * Calling this method is always a good idea, because all security relevant
657
     * attributes are filled with Nullbytes to leave nothing in the mem.
658
     *
659
     * @access public
660
     */
661
    function close()
662
    {
663
        if ($this->res != null) {
664
            radius_close($this->res);
665
            $this->res = null;
666
        }
667
        $this->username = str_repeat("\0", strlen($this->username));
668
        $this->password = str_repeat("\0", strlen($this->password));
669
    }
670

    
671
}
672

    
673
/**
674
 * class Auth_RADIUS_PAP
675
 *
676
 * Class for authenticating using PAP (Plaintext)
677
 *
678
 * @package Auth_RADIUS 
679
 */
680
class Auth_RADIUS_PAP extends Auth_RADIUS 
681
{
682

    
683
    /**
684
     * Constructor
685
     *
686
     * @param  string  $username   Username
687
     * @param  string  $password   Password
688
     * @return void
689
     */
690
    function Auth_RADIUS_PAP($username = null, $password = null)
691
    {
692
        $this->Auth_RADIUS();
693
        $this->username = $username;
694
        $this->password = $password;
695
    }
696

    
697
    /**
698
     * Creates a RADIUS resource
699
     *
700
     * Creates a RADIUS resource for authentication. This should be the first
701
     * call before you make any other things with the library.
702
     *
703
     * @return bool   true on success, false on error
704
     */
705
    function open() 
706
    {
707
        $this->res = radius_auth_open();
708
        if (!$this->res) {
709
            return false;
710
        }
711
        return true;
712
    }
713

    
714
    /**
715
     * Creates an authentication request 
716
     *
717
     * Creates an authentication request.
718
     * You MUST call this method before you can put any attribute
719
     *
720
     * @return bool   true on success, false on error
721
     */
722
    function createRequest()
723
    {
724
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
725
            return false;
726
        }
727
        return true;
728
    }
729

    
730
    /**
731
     * Put authentication specific attributes 
732
     *
733
     * @return void
734
     */
735
    function putAuthAttributes()
736
    {
737
        if (isset($this->username)) {
738
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
739
        }
740
        if (isset($this->password)) {
741
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
742
        }
743
    }
744

    
745
}
746

    
747
/**
748
 * class Auth_RADIUS_CHAP_MD5
749
 *
750
 * Class for authenticating using CHAP-MD5 see RFC1994.
751
 * Instead og the plaintext password the challenge and 
752
 * the response are needed.
753
 *
754
 * @package Auth_RADIUS 
755
 */
756
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
757
{
758
    /**
759
     * 8 Bytes binary challenge
760
     * @var  string
761
     */
762
    var $challenge = null;
763

    
764
    /**
765
     * 16 Bytes MD5 response binary
766
     * @var  string
767
     */
768
    var $response = null;
769

    
770
    /**
771
     * Id of the authentication request. Should incremented after every request.
772
     * @var  integer
773
     */
774
    var $chapid = 1;
775

    
776
    /**
777
     * Constructor
778
     *
779
     * @param  string  $username   Username
780
     * @param  string  $challenge  8 Bytes Challenge (binary)
781
     * @param  integer $chapid     Requestnumber
782
     * @return void
783
     */
784
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
785
    {
786
        $this->Auth_RADIUS_PAP();
787
        $this->username = $username;
788
        $this->challenge = $challenge;
789
        $this->chapid = $chapid;
790
    }
791

    
792
    /**
793
     * Put CHAP-MD5 specific attributes
794
     *
795
     * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge 
796
     * and the response. The chapid is inserted in the first byte of the response.
797
     *
798
     * @return void
799
     */
800
    function putAuthAttributes()
801
    {
802
        if (isset($this->username)) {
803
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
804
        }
805
        if (isset($this->response)) {
806
            $response = pack('C', $this->chapid) . $this->response;
807
            $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
808
        }
809
        if (isset($this->challenge)) {
810
            $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
811
        }
812
    }
813

    
814
    /**
815
     * Frees resources.
816
     *
817
     * Calling this method is always a good idea, because all security relevant
818
     * attributes are filled with Nullbytes to leave nothing in the mem.
819
     *
820
     * @access public
821
     */
822
    function close()
823
    {
824
        Auth_RADIUS_PAP::close();
825
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
826
        $this->response =  str_repeat("\0", strlen($this->response));
827
    }
828

    
829
}
830

    
831
/**
832
 * class Auth_RADIUS_MSCHAPv1
833
 *
834
 * Class for authenticating using MS-CHAPv1 see RFC2433
835
 *
836
 * @package Auth_RADIUS 
837
 */
838
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 
839
{
840
    /**
841
     * LAN-Manager-Response
842
     * @var  string
843
     */
844
    var $lmResponse = null;
845

    
846
    /**
847
     * Wether using deprecated LM-Responses or not.
848
     * 0 = use LM-Response, 1 = use NT-Response
849
     * @var  bool
850
     */
851
    var $flags = 1;
852

    
853
    /**
854
     * Put MS-CHAPv1 specific attributes 
855
     *
856
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
857
     * and the response. The response has this structure:
858
     * struct rad_mschapvalue {
859
     *   u_char ident;
860
     *   u_char flags;
861
     *   u_char lm_response[24];
862
     *   u_char response[24];
863
     * };
864
     *
865
     * @return void
866
     */
867
    function putAuthAttributes()
868
    {
869
        if (isset($this->username)) {
870
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
871
        }
872
        if (isset($this->response) || isset($this->lmResponse)) {
873
            $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
874
            $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
875
            $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
876
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
877
        }
878
        if (isset($this->challenge)) {
879
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
880
        }
881
    }
882
}
883

    
884
/**
885
 * class Auth_RADIUS_MSCHAPv2
886
 *
887
 * Class for authenticating using MS-CHAPv2 see RFC2759
888
 *
889
 * @package Auth_RADIUS 
890
 */
891
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 
892
{
893
    /**
894
     * 16 Bytes binary challenge
895
     * @var  string
896
     */
897
    var $challenge = null;
898

    
899
    /**
900
     * 16 Bytes binary Peer Challenge
901
     * @var  string
902
     */
903
    var $peerChallenge = null;
904

    
905
  /**
906
     * Put MS-CHAPv2 specific attributes 
907
     *
908
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
909
     * and the response. The response has this structure:
910
     * struct rad_mschapv2value {
911
     *   u_char ident;
912
     *   u_char flags;
913
     *   u_char pchallenge[16];
914
     *   u_char reserved[8];
915
     *   u_char response[24];
916
     * };
917
     * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
918
     * @return void
919
     */
920
    function putAuthAttributes()
921
    {
922
        if (isset($this->username)) {
923
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
924
        }
925
        if (isset($this->response) && isset($this->peerChallenge)) {
926
            // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response        
927
            $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);        
928
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
929
        }
930
        if (isset($this->challenge)) {
931
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
932
        }
933
    }
934

    
935
    /**
936
     * Frees resources.
937
     *
938
     * Calling this method is always a good idea, because all security relevant
939
     * attributes are filled with Nullbytes to leave nothing in the mem.
940
     *
941
     * @access public
942
     */   
943
    function close()
944
    {
945
        Auth_RADIUS_MSCHAPv1::close();
946
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
947
    }
948
}
949

    
950
/**
951
 * class Auth_RADIUS_Acct
952
 *
953
 * Class for RADIUS accounting
954
 * 
955
 * @package Auth_RADIUS 
956
 */
957
class Auth_RADIUS_Acct extends Auth_RADIUS 
958
{
959
    /**
960
     * Defines where the Authentication was made, possible values are:
961
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
962
     * @var  integer
963
     */
964
    var $authentic = null;
965

    
966
   /**
967
     * Defines the type of the accounting request, on of:
968
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
969
     * @var  integer
970
     */    
971
    var $status_type = null;
972

    
973
   /**
974
     * The time the user was logged in in seconds
975
     * @var  integer
976
     */    
977
    var $session_time = null;
978

    
979
   /**
980
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
981
     * @var  string
982
     */    
983
    var $session_id = null;
984

    
985
    /**
986
     * Constructor
987
     *
988
     * This function is disabled for M0n0wall since we use our own session_id
989
     *
990
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
991
     * @return void
992
     *
993
    function Auth_RADIUS_Acct()
994
    {
995
        $this->Auth_RADIUS();
996

    
997
        if (isset($_SERVER)) {
998
            $var = &$_SERVER;
999
        } else {
1000
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
1001
        }
1002

    
1003
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
1004
    }
1005
    */
1006

    
1007
    /**
1008
     * Constructor
1009
     *
1010
     */
1011

    
1012
    function Auth_RADIUS_Acct()
1013
    {
1014
        $this->Auth_RADIUS();
1015
    }
1016

    
1017
    /**
1018
     * Creates a RADIUS resource
1019
     *
1020
     * Creates a RADIUS resource for accounting. This should be the first
1021
     * call before you make any other things with the library.
1022
     *
1023
     * @return bool   true on success, false on error
1024
     */
1025
    function open() 
1026
    {
1027
        $this->res = radius_acct_open();
1028
        if (!$this->res) {
1029
            return false;
1030
        }
1031
        return true;
1032
    }
1033

    
1034
   /**
1035
     * Creates an accounting request 
1036
     *
1037
     * Creates an accounting request.
1038
     * You MUST call this method before you can put any attribute.
1039
     *
1040
     * @return bool   true on success, false on error
1041
     */
1042
    function createRequest()
1043
    {
1044
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
1045
            return false;
1046
        }
1047
        return true;
1048
    }
1049

    
1050
  /**
1051
     * Put attributes for accounting.
1052
     *
1053
     * Here we put some accounting values. There many more attributes for accounting, 
1054
     * but for web-applications only certain attributes make sense.
1055
     * @return void
1056
     */ 
1057
    function putAuthAttributes()
1058
    {
1059
        if (isset($this->username)) {
1060
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
1061
        }
1062
        $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
1063
        //if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
1064
	if (isset($this->session_time)) {
1065
            $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
1066
        }
1067
        if (isset($this->authentic)) {
1068
            $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
1069
        }
1070

    
1071
    }
1072

    
1073
}
1074

    
1075
/**
1076
 * class Auth_RADIUS_Acct_Start
1077
 *
1078
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
1079
 * 
1080
 * @package Auth_RADIUS
1081
 */
1082
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct 
1083
{
1084
   /**
1085
     * Defines the type of the accounting request.
1086
     * It is set to RADIUS_START by default in this class.
1087
     * @var  integer
1088
     */
1089
    var $status_type = RADIUS_START;
1090
}
1091

    
1092
/**
1093
 * class Auth_RADIUS_Acct_Start
1094
 *
1095
 * Class for RADIUS accounting. Its usualy used, after the user has logged out.
1096
 *
1097
 * @package Auth_RADIUS
1098
 */
1099
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
1100
{
1101
   /**
1102
     * Defines the type of the accounting request.
1103
     * It is set to RADIUS_STOP by default in this class.
1104
     * @var  integer
1105
     */
1106
    var $status_type = RADIUS_STOP;
1107
}
1108

    
1109
if (!defined('RADIUS_UPDATE'))
1110
    define('RADIUS_UPDATE', 3);
1111

    
1112
/**
1113
 * class Auth_RADIUS_Acct_Update
1114
 *
1115
 * Class for interim RADIUS accounting updates.
1116
 *
1117
 * @package Auth_RADIUS
1118
 */
1119
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1120
{
1121
   /**
1122
     * Defines the type of the accounting request.
1123
     * It is set to RADIUS_UPDATE by default in this class.
1124
     * @var  integer
1125
     */
1126
    var $status_type = RADIUS_UPDATE;
1127
}
1128

    
1129
?>
(43-43/65)