Project

General

Profile

Download (31.4 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 <jonathan@imelda.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

    
47
*/
48

    
49
require_once("PEAR.inc");
50
require_once("radius_authentication.inc");
51
require_once("radius_accounting.inc");
52

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
212
    }
213

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

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

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

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

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

    
243
    }
244

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

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

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

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

    
285
    /**
286
     * Puts standard attributes.
287
     *
288
     * These attributes will always be present in a radius request
289
     *
290
     * @access public
291
     */
292
    function putStandardAttributes()
293
    {
294

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

    
298
        // Add support for sending NAS-Identifier
299
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, getNasID());
300

    
301
    }
302

    
303
    /**
304
     * Puts custom attributes.
305
     *
306
     * @access public
307
     */
308
    function putAuthAttributes()
309
    {
310
        if (isset($this->username)) {
311
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
312
        }
313
    }
314

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

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

    
350
    /**
351
     * Initiates a RADIUS request. 
352
     *
353
     * @access public
354
     * @return bool  true on success, false on errors     
355
     */ 
356
    function start()
357
    {
358
        if (!$this->open()) {
359
            return false;
360
        }
361

    
362
        foreach ($this->_servers as $s) {
363
            // Servername, port, sharedsecret, timeout, retries
364
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
365
                return false;
366
            }
367
        }
368

    
369
        if (!empty($this->_configfile)) {
370
            if (!$this->putConfigfile($this->_configfile)) {
371
                return false;
372
            }
373
        }
374

    
375
        $this->createRequest();
376
        $this->putStandardAttributes();
377
        $this->putAuthAttributes();
378
        return true;
379
    }
380

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

    
394
        switch($req) {
395
        case RADIUS_ACCESS_ACCEPT:
396
            if (is_subclass_of($this, 'auth_radius_acct')) {
397
                return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
398
            }
399
            return true;
400

    
401
        case RADIUS_ACCESS_REJECT:
402
            return false;
403

    
404
        case RADIUS_ACCOUNTING_RESPONSE:
405
            if (is_subclass_of($this, 'auth_radius_pap')) {
406
                return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
407
            }
408
            return true;
409

    
410
        default:
411
            return $this->raiseError("Unexpected return value: $req");
412
        }
413

    
414
    }
415

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

    
431
        while ($attrib = radius_get_attr($this->res)) {
432

    
433
            if (!is_array($attrib)) {
434
                return false;
435
            }        
436

    
437
            $attr = $attrib['attr'];
438
            $data = $attrib['data'];
439

    
440
            $this->rawAttributes[$attr] = $data;
441

    
442
            switch ($attr) {
443
            case RADIUS_FRAMED_IP_ADDRESS:
444
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
445
                break;
446

    
447
            case RADIUS_FRAMED_IP_NETMASK:
448
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
449
                break;
450

    
451
            case RADIUS_FRAMED_MTU:
452
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
453
                break;
454

    
455
            case RADIUS_FRAMED_COMPRESSION:
456
                $this->attributes['framed_compression'] = radius_cvt_int($data);
457
                break;
458

    
459
            case RADIUS_SESSION_TIMEOUT:
460
                $this->attributes['session_timeout'] = radius_cvt_int($data);
461
                break;
462

    
463
            case RADIUS_IDLE_TIMEOUT:
464
                $this->attributes['idle_timeout'] = radius_cvt_int($data);
465
                break;
466

    
467
            case RADIUS_SERVICE_TYPE:
468
                $this->attributes['service_type'] = radius_cvt_int($data);
469
                break;
470

    
471
            case RADIUS_CLASS:
472
                $this->attributes['class'] = radius_cvt_int($data);
473
                break;
474

    
475
            case RADIUS_FRAMED_PROTOCOL:
476
                $this->attributes['framed_protocol'] = radius_cvt_int($data);
477
                break;
478

    
479
            case RADIUS_FRAMED_ROUTING:
480
                $this->attributes['framed_routing'] = radius_cvt_int($data);
481
                break;
482

    
483
            case RADIUS_FILTER_ID:
484
                $this->attributes['filter_id'] = radius_cvt_string($data);
485
                break;
486

    
487
            case RADIUS_REPLY_MESSAGE:
488
                $this->attributes['reply_message'] = radius_cvt_string($data);
489
                break;
490

    
491
            case RADIUS_VENDOR_SPECIFIC:
492
                $attribv = radius_get_vendor_attr($data);
493
                if (!is_array($attribv)) {
494
                    return false;
495
                }
496

    
497
                $vendor = $attribv['vendor'];
498
                $attrv = $attribv['attr'];
499
                $datav = $attribv['data'];
500

    
501
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
502

    
503
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
504

    
505
                    switch ($attrv) {
506
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
507
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
508
                        break;
509

    
510
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
511
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
512
                        break;
513

    
514
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
515
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
516
                        break;
517

    
518
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
519
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
520
                        break;
521

    
522
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
523
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
524
                        break;
525

    
526
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
527
                        $demangled = radius_demangle($this->res, $datav);
528
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
529
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
530
                        break;
531

    
532
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
533
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
534
                        break;
535

    
536
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
537
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
538
                        break;
539

    
540
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
541
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
542
                        break;
543
                    }
544
                }
545

    
546
                if ($vendor == 1584) {
547

    
548
                    switch ($attrv) {
549
                    case 102:
550
                        $this->attributes['ces_group'] = radius_cvt_string($datav);
551
                        break;
552
                    }
553
                }
554

    
555
                if ($vendor == 3309) {    /* RADIUS_VENDOR_NOMADIX */
556

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

    
582
        if ($vendor == 14122) { /* RADIUS_VENDOR_WISPr Wi-Fi Alliance */
583

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

    
621
                break;
622

    
623
            }
624
        }
625

    
626
        return true;
627
    }
628

    
629
    /**
630
     * Frees resources.
631
     *
632
     * Calling this method is always a good idea, because all security relevant
633
     * attributes are filled with Nullbytes to leave nothing in the mem.
634
     *
635
     * @access public
636
     */
637
    function close()
638
    {
639
        if ($this->res != null) {
640
            radius_close($this->res);
641
            $this->res = null;
642
        }
643
        $this->username = str_repeat("\0", strlen($this->username));
644
        $this->password = str_repeat("\0", strlen($this->password));
645
    }
646

    
647
}
648

    
649
/**
650
 * class Auth_RADIUS_PAP
651
 *
652
 * Class for authenticating using PAP (Plaintext)
653
 *
654
 * @package Auth_RADIUS 
655
 */
656
class Auth_RADIUS_PAP extends Auth_RADIUS 
657
{
658

    
659
    /**
660
     * Constructor
661
     *
662
     * @param  string  $username   Username
663
     * @param  string  $password   Password
664
     * @return void
665
     */
666
    function Auth_RADIUS_PAP($username = null, $password = null)
667
    {
668
        $this->Auth_RADIUS();
669
        $this->username = $username;
670
        $this->password = $password;
671
    }
672

    
673
    /**
674
     * Creates a RADIUS resource
675
     *
676
     * Creates a RADIUS resource for authentication. This should be the first
677
     * call before you make any other things with the library.
678
     *
679
     * @return bool   true on success, false on error
680
     */
681
    function open() 
682
    {
683
        $this->res = radius_auth_open();
684
        if (!$this->res) {
685
            return false;
686
        }
687
        return true;
688
    }
689

    
690
    /**
691
     * Creates an authentication request 
692
     *
693
     * Creates an authentication request.
694
     * You MUST call this method before you can put any attribute
695
     *
696
     * @return bool   true on success, false on error
697
     */
698
    function createRequest()
699
    {
700
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
701
            return false;
702
        }
703
        return true;
704
    }
705

    
706
    /**
707
     * Put authentication specific attributes 
708
     *
709
     * @return void
710
     */
711
    function putAuthAttributes()
712
    {
713
        if (isset($this->username)) {
714
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
715
        }
716
        if (isset($this->password)) {
717
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
718
        }
719
    }
720

    
721
}
722

    
723
/**
724
 * class Auth_RADIUS_CHAP_MD5
725
 *
726
 * Class for authenticating using CHAP-MD5 see RFC1994.
727
 * Instead og the plaintext password the challenge and 
728
 * the response are needed.
729
 *
730
 * @package Auth_RADIUS 
731
 */
732
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
733
{
734
    /**
735
     * 8 Bytes binary challenge
736
     * @var  string
737
     */
738
    var $challenge = null;
739

    
740
    /**
741
     * 16 Bytes MD5 response binary
742
     * @var  string
743
     */
744
    var $response = null;
745

    
746
    /**
747
     * Id of the authentication request. Should incremented after every request.
748
     * @var  integer
749
     */
750
    var $chapid = 1;
751

    
752
    /**
753
     * Constructor
754
     *
755
     * @param  string  $username   Username
756
     * @param  string  $challenge  8 Bytes Challenge (binary)
757
     * @param  integer $chapid     Requestnumber
758
     * @return void
759
     */
760
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
761
    {
762
        $this->Auth_RADIUS_PAP();
763
        $this->username = $username;
764
        $this->challenge = $challenge;
765
        $this->chapid = $chapid;
766
    }
767

    
768
    /**
769
     * Put CHAP-MD5 specific attributes
770
     *
771
     * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge 
772
     * and the response. The chapid is inserted in the first byte of the response.
773
     *
774
     * @return void
775
     */
776
    function putAuthAttributes()
777
    {
778
        if (isset($this->username)) {
779
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
780
        }
781
        if (isset($this->response)) {
782
            $response = pack('C', $this->chapid) . $this->response;
783
            $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
784
        }
785
        if (isset($this->challenge)) {
786
            $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
787
        }
788
    }
789

    
790
    /**
791
     * Frees resources.
792
     *
793
     * Calling this method is always a good idea, because all security relevant
794
     * attributes are filled with Nullbytes to leave nothing in the mem.
795
     *
796
     * @access public
797
     */
798
    function close()
799
    {
800
        Auth_RADIUS_PAP::close();
801
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
802
        $this->response =  str_repeat("\0", strlen($this->response));
803
    }
804

    
805
}
806

    
807
/**
808
 * class Auth_RADIUS_MSCHAPv1
809
 *
810
 * Class for authenticating using MS-CHAPv1 see RFC2433
811
 *
812
 * @package Auth_RADIUS 
813
 */
814
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5 
815
{
816
    /**
817
     * LAN-Manager-Response
818
     * @var  string
819
     */
820
    var $lmResponse = null;
821

    
822
    /**
823
     * Wether using deprecated LM-Responses or not.
824
     * 0 = use LM-Response, 1 = use NT-Response
825
     * @var  bool
826
     */
827
    var $flags = 1;
828

    
829
    /**
830
     * Put MS-CHAPv1 specific attributes 
831
     *
832
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
833
     * and the response. The response has this structure:
834
     * struct rad_mschapvalue {
835
     *   u_char ident;
836
     *   u_char flags;
837
     *   u_char lm_response[24];
838
     *   u_char response[24];
839
     * };
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) || isset($this->lmResponse)) {
849
            $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
850
            $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
851
            $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
852
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
853
        }
854
        if (isset($this->challenge)) {
855
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
856
        }
857
    }
858
}
859

    
860
/**
861
 * class Auth_RADIUS_MSCHAPv2
862
 *
863
 * Class for authenticating using MS-CHAPv2 see RFC2759
864
 *
865
 * @package Auth_RADIUS 
866
 */
867
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1 
868
{
869
    /**
870
     * 16 Bytes binary challenge
871
     * @var  string
872
     */
873
    var $challenge = null;
874

    
875
    /**
876
     * 16 Bytes binary Peer Challenge
877
     * @var  string
878
     */
879
    var $peerChallenge = null;
880

    
881
  /**
882
     * Put MS-CHAPv2 specific attributes 
883
     *
884
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge 
885
     * and the response. The response has this structure:
886
     * struct rad_mschapv2value {
887
     *   u_char ident;
888
     *   u_char flags;
889
     *   u_char pchallenge[16];
890
     *   u_char reserved[8];
891
     *   u_char response[24];
892
     * };
893
     * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
894
     * @return void
895
     */
896
    function putAuthAttributes()
897
    {
898
        if (isset($this->username)) {
899
            $this->putAttribute(RADIUS_USER_NAME, $this->username);        
900
        }
901
        if (isset($this->response) && isset($this->peerChallenge)) {
902
            // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response        
903
            $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);        
904
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
905
        }
906
        if (isset($this->challenge)) {
907
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
908
        }
909
    }
910

    
911
    /**
912
     * Frees resources.
913
     *
914
     * Calling this method is always a good idea, because all security relevant
915
     * attributes are filled with Nullbytes to leave nothing in the mem.
916
     *
917
     * @access public
918
     */   
919
    function close()
920
    {
921
        Auth_RADIUS_MSCHAPv1::close();
922
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
923
    }
924
}
925

    
926
/**
927
 * class Auth_RADIUS_Acct
928
 *
929
 * Class for RADIUS accounting
930
 * 
931
 * @package Auth_RADIUS 
932
 */
933
class Auth_RADIUS_Acct extends Auth_RADIUS 
934
{
935
    /**
936
     * Defines where the Authentication was made, possible values are:
937
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
938
     * @var  integer
939
     */
940
    var $authentic = null;
941

    
942
   /**
943
     * Defines the type of the accounting request, on of:
944
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
945
     * @var  integer
946
     */    
947
    var $status_type = null;
948

    
949
   /**
950
     * The time the user was logged in in seconds
951
     * @var  integer
952
     */    
953
    var $session_time = null;
954

    
955
   /**
956
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
957
     * @var  string
958
     */    
959
    var $session_id = null;
960

    
961
    /**
962
     * Constructor
963
     *
964
     * This function is disabled for M0n0wall since we use our own session_id
965
     *
966
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
967
     * @return void
968
     *
969
    function Auth_RADIUS_Acct()
970
    {
971
        $this->Auth_RADIUS();
972

    
973
        if (isset($_SERVER)) {
974
            $var = &$_SERVER;
975
        } else {
976
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
977
        }
978

    
979
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
980
    }
981
    */
982

    
983
    /**
984
     * Constructor
985
     *
986
     */
987

    
988
    function Auth_RADIUS_Acct()
989
    {
990
        $this->Auth_RADIUS();
991
    }
992

    
993
    /**
994
     * Creates a RADIUS resource
995
     *
996
     * Creates a RADIUS resource for accounting. This should be the first
997
     * call before you make any other things with the library.
998
     *
999
     * @return bool   true on success, false on error
1000
     */
1001
    function open() 
1002
    {
1003
        $this->res = radius_acct_open();
1004
        if (!$this->res) {
1005
            return false;
1006
        }
1007
        return true;
1008
    }
1009

    
1010
   /**
1011
     * Creates an accounting request 
1012
     *
1013
     * Creates an accounting request.
1014
     * You MUST call this method before you can put any attribute.
1015
     *
1016
     * @return bool   true on success, false on error
1017
     */
1018
    function createRequest()
1019
    {
1020
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
1021
            return false;
1022
        }
1023
        return true;
1024
    }
1025

    
1026
  /**
1027
     * Put attributes for accounting.
1028
     *
1029
     * Here we put some accounting values. There many more attributes for accounting, 
1030
     * but for web-applications only certain attributes make sense.
1031
     * @return void
1032
     */ 
1033
    function putAuthAttributes()
1034
    {
1035
        if (isset($this->username)) {
1036
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
1037
        }
1038
        $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
1039
        if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
1040
            $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
1041
        }
1042
        if (isset($this->authentic)) {
1043
            $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
1044
        }
1045

    
1046
    }
1047

    
1048
}
1049

    
1050
/**
1051
 * class Auth_RADIUS_Acct_Start
1052
 *
1053
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
1054
 * 
1055
 * @package Auth_RADIUS
1056
 */
1057
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct 
1058
{
1059
   /**
1060
     * Defines the type of the accounting request.
1061
     * It is set to RADIUS_START by default in this class.
1062
     * @var  integer
1063
     */
1064
    var $status_type = RADIUS_START;
1065
}
1066

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

    
1084
if (!defined('RADIUS_UPDATE'))
1085
    define('RADIUS_UPDATE', 3);
1086

    
1087
/**
1088
 * class Auth_RADIUS_Acct_Update
1089
 *
1090
 * Class for interim RADIUS accounting updates.
1091
 *
1092
 * @package Auth_RADIUS
1093
 */
1094
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
1095
{
1096
   /**
1097
     * Defines the type of the accounting request.
1098
     * It is set to RADIUS_UPDATE by default in this class.
1099
     * @var  integer
1100
     */
1101
    var $status_type = RADIUS_UPDATE;
1102
}
1103

    
1104
?>
(16-16/27)