Project

General

Profile

Download (31.9 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

    
300
        // Add support for sending NAS-IP-Address, set this explicitly as an ip_addr
301
        $this->putAttribute(RADIUS_NAS_IP_ADDRESS, getNasIP(), "addr");
302

    
303
        // Add support for sending NAS-Identifier
304
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, getNasID());
305

    
306
    }
307

    
308
    /**
309
     * Puts custom attributes.
310
     *
311
     * @access public
312
     */
313
    function putAuthAttributes()
314
    {
315
        if (isset($this->username)) {
316
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
317
        }
318
    }
319

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

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

    
355
    /**
356
     * Initiates a RADIUS request. 
357
     *
358
     * @access public
359
     * @return bool  true on success, false on errors     
360
     */ 
361
    function start()
362
    {
363
        if (!$this->open()) {
364
            return false;
365
        }
366

    
367
        foreach ($this->_servers as $s) {
368
            // Servername, port, sharedsecret, timeout, retries
369
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
370
                return false;
371
            }
372
        }
373

    
374
        if (!empty($this->_configfile)) {
375
            if (!$this->putConfigfile($this->_configfile)) {
376
                return false;
377
            }
378
        }
379

    
380
        $this->createRequest();
381
        $this->putStandardAttributes();
382
        $this->putAuthAttributes();
383
        return true;
384
    }
385

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

    
399
        switch($req) {
400
        case RADIUS_ACCESS_ACCEPT:
401
            if (is_subclass_of($this, 'auth_radius_acct')) {
402
                return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
403
            }
404
            return true;
405

    
406
        case RADIUS_ACCESS_REJECT:
407
            return false;
408

    
409
        case RADIUS_ACCOUNTING_RESPONSE:
410
            if (is_subclass_of($this, 'auth_radius_pap')) {
411
                return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
412
            }
413
            return true;
414

    
415
        default:
416
            return $this->raiseError("Unexpected return value: $req");
417
        }
418

    
419
    }
420

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

    
436
        while ($attrib = radius_get_attr($this->res)) {
437

    
438
            if (!is_array($attrib)) {
439
                return false;
440
            }        
441

    
442
            $attr = $attrib['attr'];
443
            $data = $attrib['data'];
444

    
445
            $this->rawAttributes[$attr] = $data;
446

    
447
            switch ($attr) {
448
            case RADIUS_FRAMED_IP_ADDRESS:
449
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
450
                break;
451

    
452
            case RADIUS_FRAMED_IP_NETMASK:
453
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
454
                break;
455

    
456
            case RADIUS_FRAMED_MTU:
457
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
458
                break;
459

    
460
            case RADIUS_FRAMED_COMPRESSION:
461
                $this->attributes['framed_compression'] = radius_cvt_int($data);
462
                break;
463

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

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

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

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

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

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

    
488
            case RADIUS_FILTER_ID:
489
                $this->attributes['filter_id'] = radius_cvt_string($data);
490
                break;
491

    
492
            case RADIUS_REPLY_MESSAGE:
493
                $this->attributes['reply_message'] = radius_cvt_string($data);
494
                break;
495

    
496
            case RADIUS_VENDOR_SPECIFIC:
497
                $attribv = radius_get_vendor_attr($data);
498
                if (!is_array($attribv)) {
499
                    return false;
500
                }
501

    
502
                $vendor = $attribv['vendor'];
503
                $attrv = $attribv['attr'];
504
                $datav = $attribv['data'];
505

    
506
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
507

    
508
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
509

    
510
                    switch ($attrv) {
511
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
512
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
513
                        break;
514

    
515
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
516
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
517
                        break;
518

    
519
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
520
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
521
                        break;
522

    
523
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
524
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
525
                        break;
526

    
527
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
528
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
529
                        break;
530

    
531
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
532
                        $demangled = radius_demangle($this->res, $datav);
533
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
534
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
535
                        break;
536

    
537
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
538
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
539
                        break;
540

    
541
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
542
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
543
                        break;
544

    
545
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
546
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
547
                        break;
548
                    }
549
                }
550

    
551
                if ($vendor == 1584) {
552

    
553
                    switch ($attrv) {
554
                    case 102:
555
                        $this->attributes['ces_group'] = radius_cvt_string($datav);
556
                        break;
557
                    }
558
                }
559

    
560
                if ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
561

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

    
587
        	if ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
588

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

    
626
		if ($vendor == 14559) { /* RADIUS_VENDOR_ChilliSpot */
627
			switch ($attrv) {
628
			case 4: /* ChilliSpot-Bandwidth-Max-Up */
629
				$this->attributes['bw_up'] = radius_cvt_int($datav);
630
				break;
631
			case 5: /* ChilliSpot-Bandwidth-Max-Down */
632
				$this->attributes['bw_down'] = radius_cvt_int($datav);
633
				break;
634
			}
635
		}
636

    
637
                break;
638

    
639
            }
640
        }
641

    
642
        return true;
643
    }
644

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

    
663
}
664

    
665
/**
666
 * class Auth_RADIUS_PAP
667
 *
668
 * Class for authenticating using PAP (Plaintext)
669
 *
670
 * @package Auth_RADIUS 
671
 */
672
class Auth_RADIUS_PAP extends Auth_RADIUS 
673
{
674

    
675
    /**
676
     * Constructor
677
     *
678
     * @param  string  $username   Username
679
     * @param  string  $password   Password
680
     * @return void
681
     */
682
    function Auth_RADIUS_PAP($username = null, $password = null)
683
    {
684
        $this->Auth_RADIUS();
685
        $this->username = $username;
686
        $this->password = $password;
687
    }
688

    
689
    /**
690
     * Creates a RADIUS resource
691
     *
692
     * Creates a RADIUS resource for authentication. This should be the first
693
     * call before you make any other things with the library.
694
     *
695
     * @return bool   true on success, false on error
696
     */
697
    function open() 
698
    {
699
        $this->res = radius_auth_open();
700
        if (!$this->res) {
701
            return false;
702
        }
703
        return true;
704
    }
705

    
706
    /**
707
     * Creates an authentication request 
708
     *
709
     * Creates an authentication request.
710
     * You MUST call this method before you can put any attribute
711
     *
712
     * @return bool   true on success, false on error
713
     */
714
    function createRequest()
715
    {
716
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
717
            return false;
718
        }
719
        return true;
720
    }
721

    
722
    /**
723
     * Put authentication specific attributes 
724
     *
725
     * @return void
726
     */
727
    function putAuthAttributes()
728
    {
729
        if (isset($this->username)) {
730
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
731
        }
732
        if (isset($this->password)) {
733
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
734
        }
735
    }
736

    
737
}
738

    
739
/**
740
 * class Auth_RADIUS_CHAP_MD5
741
 *
742
 * Class for authenticating using CHAP-MD5 see RFC1994.
743
 * Instead og the plaintext password the challenge and 
744
 * the response are needed.
745
 *
746
 * @package Auth_RADIUS 
747
 */
748
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
749
{
750
    /**
751
     * 8 Bytes binary challenge
752
     * @var  string
753
     */
754
    var $challenge = null;
755

    
756
    /**
757
     * 16 Bytes MD5 response binary
758
     * @var  string
759
     */
760
    var $response = null;
761

    
762
    /**
763
     * Id of the authentication request. Should incremented after every request.
764
     * @var  integer
765
     */
766
    var $chapid = 1;
767

    
768
    /**
769
     * Constructor
770
     *
771
     * @param  string  $username   Username
772
     * @param  string  $challenge  8 Bytes Challenge (binary)
773
     * @param  integer $chapid     Requestnumber
774
     * @return void
775
     */
776
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
777
    {
778
        $this->Auth_RADIUS_PAP();
779
        $this->username = $username;
780
        $this->challenge = $challenge;
781
        $this->chapid = $chapid;
782
    }
783

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

    
806
    /**
807
     * Frees resources.
808
     *
809
     * Calling this method is always a good idea, because all security relevant
810
     * attributes are filled with Nullbytes to leave nothing in the mem.
811
     *
812
     * @access public
813
     */
814
    function close()
815
    {
816
        Auth_RADIUS_PAP::close();
817
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
818
        $this->response =  str_repeat("\0", strlen($this->response));
819
    }
820

    
821
}
822

    
823
/**
824
 * class Auth_RADIUS_MSCHAPv1
825
 *
826
 * Class for authenticating using MS-CHAPv1 see RFC2433
827
 *
828
 * @package Auth_RADIUS 
829
 */
830
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 
831
{
832
    /**
833
     * LAN-Manager-Response
834
     * @var  string
835
     */
836
    var $lmResponse = null;
837

    
838
    /**
839
     * Wether using deprecated LM-Responses or not.
840
     * 0 = use LM-Response, 1 = use NT-Response
841
     * @var  bool
842
     */
843
    var $flags = 1;
844

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

    
876
/**
877
 * class Auth_RADIUS_MSCHAPv2
878
 *
879
 * Class for authenticating using MS-CHAPv2 see RFC2759
880
 *
881
 * @package Auth_RADIUS 
882
 */
883
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 
884
{
885
    /**
886
     * 16 Bytes binary challenge
887
     * @var  string
888
     */
889
    var $challenge = null;
890

    
891
    /**
892
     * 16 Bytes binary Peer Challenge
893
     * @var  string
894
     */
895
    var $peerChallenge = null;
896

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

    
927
    /**
928
     * Frees resources.
929
     *
930
     * Calling this method is always a good idea, because all security relevant
931
     * attributes are filled with Nullbytes to leave nothing in the mem.
932
     *
933
     * @access public
934
     */   
935
    function close()
936
    {
937
        Auth_RADIUS_MSCHAPv1::close();
938
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
939
    }
940
}
941

    
942
/**
943
 * class Auth_RADIUS_Acct
944
 *
945
 * Class for RADIUS accounting
946
 * 
947
 * @package Auth_RADIUS 
948
 */
949
class Auth_RADIUS_Acct extends Auth_RADIUS 
950
{
951
    /**
952
     * Defines where the Authentication was made, possible values are:
953
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
954
     * @var  integer
955
     */
956
    var $authentic = null;
957

    
958
   /**
959
     * Defines the type of the accounting request, on of:
960
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
961
     * @var  integer
962
     */    
963
    var $status_type = null;
964

    
965
   /**
966
     * The time the user was logged in in seconds
967
     * @var  integer
968
     */    
969
    var $session_time = null;
970

    
971
   /**
972
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
973
     * @var  string
974
     */    
975
    var $session_id = null;
976

    
977
    /**
978
     * Constructor
979
     *
980
     * This function is disabled for M0n0wall since we use our own session_id
981
     *
982
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
983
     * @return void
984
     *
985
    function Auth_RADIUS_Acct()
986
    {
987
        $this->Auth_RADIUS();
988

    
989
        if (isset($_SERVER)) {
990
            $var = &$_SERVER;
991
        } else {
992
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
993
        }
994

    
995
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
996
    }
997
    */
998

    
999
    /**
1000
     * Constructor
1001
     *
1002
     */
1003

    
1004
    function Auth_RADIUS_Acct()
1005
    {
1006
        $this->Auth_RADIUS();
1007
    }
1008

    
1009
    /**
1010
     * Creates a RADIUS resource
1011
     *
1012
     * Creates a RADIUS resource for accounting. This should be the first
1013
     * call before you make any other things with the library.
1014
     *
1015
     * @return bool   true on success, false on error
1016
     */
1017
    function open() 
1018
    {
1019
        $this->res = radius_acct_open();
1020
        if (!$this->res) {
1021
            return false;
1022
        }
1023
        return true;
1024
    }
1025

    
1026
   /**
1027
     * Creates an accounting request 
1028
     *
1029
     * Creates an accounting request.
1030
     * You MUST call this method before you can put any attribute.
1031
     *
1032
     * @return bool   true on success, false on error
1033
     */
1034
    function createRequest()
1035
    {
1036
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
1037
            return false;
1038
        }
1039
        return true;
1040
    }
1041

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

    
1063
    }
1064

    
1065
}
1066

    
1067
/**
1068
 * class Auth_RADIUS_Acct_Start
1069
 *
1070
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
1071
 * 
1072
 * @package Auth_RADIUS
1073
 */
1074
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct 
1075
{
1076
   /**
1077
     * Defines the type of the accounting request.
1078
     * It is set to RADIUS_START by default in this class.
1079
     * @var  integer
1080
     */
1081
    var $status_type = RADIUS_START;
1082
}
1083

    
1084
/**
1085
 * class Auth_RADIUS_Acct_Start
1086
 *
1087
 * Class for RADIUS accounting. Its usualy used, after the user has logged out.
1088
 *
1089
 * @package Auth_RADIUS
1090
 */
1091
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
1092
{
1093
   /**
1094
     * Defines the type of the accounting request.
1095
     * It is set to RADIUS_STOP by default in this class.
1096
     * @var  integer
1097
     */
1098
    var $status_type = RADIUS_STOP;
1099
}
1100

    
1101
if (!defined('RADIUS_UPDATE'))
1102
    define('RADIUS_UPDATE', 3);
1103

    
1104
/**
1105
 * class Auth_RADIUS_Acct_Update
1106
 *
1107
 * Class for interim RADIUS accounting updates.
1108
 *
1109
 * @package Auth_RADIUS
1110
 */
1111
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1112
{
1113
   /**
1114
     * Defines the type of the accounting request.
1115
     * It is set to RADIUS_UPDATE by default in this class.
1116
     * @var  integer
1117
     */
1118
    var $status_type = RADIUS_UPDATE;
1119
}
1120

    
1121
?>
(31-31/46)