Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
/*
4
Copyright (c) 2003, Michael Bretterklieber <michael@bretterklieber.com>
5
All rights reserved.
6
 
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions
9
are met:
10
 
11
1. Redistributions of source code must retain the above copyright
12
   notice, this list of conditions and the following disclaimer.
13
2. Redistributions in binary form must reproduce the above copyright
14
   notice, this list of conditions and the following disclaimer in the
15
   documentation and/or other materials provided with the distribution.
16
3. The names of the authors may not be used to endorse or promote products
17
   derived from this software without specific prior written permission.
18
 
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 
30
This code cannot simply be copied and put under the GNU Public License or
31
any other GPL-like (LGPL, GPL2) License.
32
 
33
    $Id: RADIUS.php 257341 2008-04-13 10:31:44Z mbretter $
34
*/
35
 
36
require_once 'PEAR.php';
37
 
38
/**
39
* Client implementation of RADIUS. This are wrapper classes for
40
* the RADIUS PECL.
41
* Provides RADIUS Authentication (RFC2865) and RADIUS Accounting (RFC2866).
42
*
43
* @package Auth_RADIUS
44
* @author  Michael Bretterklieber <michael@bretterklieber.com>
45
* @access  public
46
* @version $Revision: 257341 $
47
*/
48
 
49
PEAR::loadExtension('radius');
50
 
51
/**
52
 * class Auth_RADIUS
53
 *
54
 * Abstract base class for RADIUS
55
 *
56
 * @package Auth_RADIUS
57
 */
58
class Auth_RADIUS extends PEAR {
59
 
60
    /**
61
     * List of RADIUS servers.
62
     * @var  array
63
     * @see  addServer(), putServer()
64
     */
65
    var $_servers  = array();
66
 
67
    /**
68
     * Path to the configuration-file.
69
     * @var  string
70
     * @see  setConfigFile()
71
     */
72
    var $_configfile = null;
73
 
74
    /**
75
     * Resource.
76
     * @var  resource
77
     * @see  open(), close()
78
     */
79
    var $res = null;
80
 
81
    /**
82
     * Username for authentication and accounting requests.
83
     * @var  string
84
     */
85
    var $username = null;
86
 
87
    /**
88
     * Password for plaintext-authentication (PAP).
89
     * @var  string
90
     */
91
    var $password = null;
92
 
93
    /**
94
     * List of known attributes.
95
     * @var  array
96
     * @see  dumpAttributes(), getAttributes()
97
     */
98
    var $attributes = array();
99
 
100
    /**
101
     * List of raw attributes.
102
     * @var  array
103
     * @see  dumpAttributes(), getAttributes()
104
     */
105
    var $rawAttributes = array();
106
 
107
    /**
108
     * List of raw vendor specific attributes.
109
     * @var  array
110
     * @see  dumpAttributes(), getAttributes()
111
     */
112
    var $rawVendorAttributes = array();
113
 
114
    /**
115
     * Switch whether we should put standard attributes or not
116
     * @var  bool
117
     * @see  putStandardAttributes()
118
     */
119
    var $useStandardAttributes = true;
120
 
121
    /**
122
     * Constructor
123
     *
124
     * Loads the RADIUS PECL/extension
125
     *
126
     * @return void
127
     */
128
    function Auth_RADIUS()
129
    {
130
        $this->PEAR();
131
    }
132
 
133
    /**
134
     * Adds a RADIUS server to the list of servers for requests.
135
     *
136
     * At most 10 servers may be specified.	When multiple servers
137
     * are given, they are tried in round-robin fashion until a
138
     * valid response is received
139
     *
140
     * @access public
141
     * @param  string  $servername   Servername or IP-Address
142
     * @param  integer $port         Portnumber
143
     * @param  string  $sharedSecret Shared secret
144
     * @param  integer $timeout      Timeout for each request
145
     * @param  integer $maxtries     Max. retries for each request
146
     * @return void
147
     */
148
    function addServer($servername = 'localhost', $port = 0, $sharedSecret = 'testing123', $timeout = 3, $maxtries = 3)
149
    {
150
        $this->_servers[] = array($servername, $port, $sharedSecret, $timeout, $maxtries);
151
    }
152
 
153
    /**
154
     * Returns an error message, if an error occurred.
155
     *
156
     * @access public
157
     * @return string
158
     */
159
    function getError()
160
    {
161
        return radius_strerror($this->res);
162
    }
163
 
164
    /**
165
     * Sets the configuration-file.
166
     *
167
     * @access public
168
     * @param  string  $file Path to the configuration file
169
     * @return void
170
     */
171
    function setConfigfile($file)
172
    {
173
        $this->_configfile = $file;
174
    }
175
 
176
    /**
177
     * Puts an attribute.
178
     *
179
     * @access public
180
     * @param  integer $attrib       Attribute-number
181
     * @param  mixed   $port         Attribute-value
182
     * @param  type    $type         Attribute-type
183
     * @return bool  true on success, false on error
184
     */
185
    function putAttribute($attrib, $value, $type = null)
186
    {
187
        if ($type == null) {
188
            $type = gettype($value);
189
        }
190
 
191
        switch ($type) {
192
        case 'integer':
193
        case 'double':
194
            return radius_put_int($this->res, $attrib, $value);
195
 
196
        case 'addr':
197
            return radius_put_addr($this->res, $attrib, $value);
198
 
199
        case 'string':
200
        default:
201
            return radius_put_attr($this->res, $attrib, $value);
202
        }
203
 
204
    }
205
 
206
    /**
207
     * Puts a vendor-specific attribute.
208
     *
209
     * @access public
210
     * @param  integer $vendor       Vendor (MSoft, Cisco, ...)
211
     * @param  integer $attrib       Attribute-number
212
     * @param  mixed   $port         Attribute-value
213
     * @param  type    $type         Attribute-type
214
     * @return bool  true on success, false on error
215
     */
216
    function putVendorAttribute($vendor, $attrib, $value, $type = null)
217
    {
218
 
219
        if ($type == null) {
220
            $type = gettype($value);
221
        }
222
 
223
        switch ($type) {
224
        case 'integer':
225
        case 'double':
226
            return radius_put_vendor_int($this->res, $vendor, $attrib, $value);
227
 
228
        case 'addr':
229
            return radius_put_vendor_addr($this->res, $vendor,$attrib, $value);
230
 
231
        case 'string':
232
        default:
233
            return radius_put_vendor_attr($this->res, $vendor, $attrib, $value);
234
        }
235
 
236
    }
237
 
238
    /**
239
     * Prints known attributes received from the server.
240
     *
241
     * @access public
242
     */
243
    function dumpAttributes()
244
    {
245
        foreach ($this->attributes as $name => $data) {
246
            echo "$name:$data<br>\n";
247
        }
248
    }
249
 
250
    /**
251
     * Overwrite this.
252
     *
253
     * @access public
254
     */
255
    function open()
256
    {
257
    }
258
 
259
    /**
260
     * Overwrite this.
261
     *
262
     * @access public
263
     */
264
    function createRequest()
265
    {
266
    }
267
 
268
    /**
269
     * Puts standard attributes.
270
     *
271
     * @access public
272
     */
273
    function putStandardAttributes()
274
    {
275
        if (!$this->useStandardAttributes)
276
		return;
277
 
278
        if (isset($_SERVER)) {
279
            $var = &$_SERVER;
280
        } else {
281
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
282
        }
283
 
284
        $this->putAttribute(RADIUS_NAS_IDENTIFIER, isset($var['HTTP_HOST']) ? $var['HTTP_HOST'] : 'localhost');
285
        $this->putAttribute(RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
286
        $this->putAttribute(RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
287
        $this->putAttribute(RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
288
        $this->putAttribute(RADIUS_CALLING_STATION_ID, isset($var['REMOTE_HOST']) ? $var['REMOTE_HOST'] : '127.0.0.1');
289
    }
290
 
291
    /**
292
     * Puts custom attributes.
293
     *
294
     * @access public
295
     */
296
    function putAuthAttributes()
297
    {
298
        if (isset($this->username)) {
299
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
300
        }
301
    }
302
 
303
    /**
304
     * Configures the radius library.
305
     *
306
     * @access public
307
     * @param  string  $servername   Servername or IP-Address
308
     * @param  integer $port         Portnumber
309
     * @param  string  $sharedSecret Shared secret
310
     * @param  integer $timeout      Timeout for each request
311
     * @param  integer $maxtries     Max. retries for each request
312
     * @return bool  true on success, false on error
313
     * @see addServer()
314
     */
315
    function putServer($servername, $port = 0, $sharedsecret = 'testing123', $timeout = 3, $maxtries = 3)
316
    {
317
        if (!radius_add_server($this->res, $servername, $port, $sharedsecret, $timeout, $maxtries)) {
318
            return false;
319
        }
320
        return true;
321
    }
322
 
323
    /**
324
     * Configures the radius library via external configurationfile
325
     *
326
     * @access public
327
     * @param  string  $servername   Servername or IP-Address
328
     * @return bool  true on success, false on error
329
     */
330
    function putConfigfile($file)
331
    {
332
        if (!radius_config($this->res, $file)) {
333
            return false;
334
        }
335
        return true;
336
    }
337
 
338
    /**
339
     * Initiates a RADIUS request.
340
     *
341
     * @access public
342
     * @return bool  true on success, false on errors
343
     */
344
    function start()
345
    {
346
        if (!$this->open()) {
347
            return false;
348
        }
349
 
350
        foreach ($this->_servers as $s) {
351
	        // Servername, port, sharedsecret, timeout, retries
352
            if (!$this->putServer($s[0], $s[1], $s[2], $s[3], $s[4])) {
353
                return false;
354
            }
355
        }
356
 
357
        if (!empty($this->_configfile)) {
358
            if (!$this->putConfigfile($this->_configfile)) {
359
                return false;
360
            }
361
        }
362
 
363
        $this->createRequest();
364
        $this->putStandardAttributes();
365
        $this->putAuthAttributes();
366
        return true;
367
    }
368
 
369
    /**
370
     * Sends a prepared RADIUS request and waits for a response
371
     *
372
     * @access public
373
     * @return mixed  true on success, false on reject, PEAR_Error on error
374
     */
375
    function send()
376
    {
377
        $req = radius_send_request($this->res);
378
        if (!$req) {
379
            return $this->raiseError('Error sending request: ' . $this->getError());
380
        }
381
 
382
        switch($req) {
383
        case RADIUS_ACCESS_ACCEPT:
384
            if (is_subclass_of($this, 'auth_radius_acct')) {
385
                return $this->raiseError('RADIUS_ACCESS_ACCEPT is unexpected for accounting');
386
            }
387
            return true;
388
 
389
        case RADIUS_ACCESS_REJECT:
390
            return false;
391
 
392
        case RADIUS_ACCOUNTING_RESPONSE:
393
            if (is_subclass_of($this, 'auth_radius_pap')) {
394
                return $this->raiseError('RADIUS_ACCOUNTING_RESPONSE is unexpected for authentication');
395
            }
396
            return true;
397
 
398
        default:
399
            return $this->raiseError("Unexpected return value: $req");
400
        }
401
 
402
    }
403
 
404
    /**
405
     * Reads all received attributes after sending the request.
406
     *
407
     * This methods stores known attributes in the property attributes,
408
     * all attributes (including known attibutes) are stored in rawAttributes
409
     * or rawVendorAttributes.
410
     * NOTE: call this function also even if the request was rejected, because the
411
     * Server returns usualy an errormessage
412
     *
413
     * @access public
414
     * @return bool   true on success, false on error
415
     */
416
    function getAttributes()
417
    {
418
 
419
        while ($attrib = radius_get_attr($this->res)) {
420
 
421
            if (!is_array($attrib)) {
422
                return false;
423
            }
424
 
425
            $attr = $attrib['attr'];
426
            $data = $attrib['data'];
427
 
428
            $this->rawAttributes[$attr] = $data;
429
 
430
            switch ($attr) {
431
            case RADIUS_FRAMED_IP_ADDRESS:
432
                $this->attributes['framed_ip'] = radius_cvt_addr($data);
433
                break;
434
 
435
            case RADIUS_FRAMED_IP_NETMASK:
436
                $this->attributes['framed_mask'] = radius_cvt_addr($data);
437
                break;
438
 
439
            case RADIUS_FRAMED_MTU:
440
                $this->attributes['framed_mtu'] = radius_cvt_int($data);
441
                break;
442
 
443
            case RADIUS_FRAMED_COMPRESSION:
444
                $this->attributes['framed_compression'] = radius_cvt_int($data);
445
                break;
446
 
447
            case RADIUS_SESSION_TIMEOUT:
448
                $this->attributes['session_timeout'] = radius_cvt_int($data);
449
                break;
450
 
451
            case RADIUS_IDLE_TIMEOUT:
452
                $this->attributes['idle_timeout'] = radius_cvt_int($data);
453
                break;
454
 
455
            case RADIUS_SERVICE_TYPE:
456
                $this->attributes['service_type'] = radius_cvt_int($data);
457
                break;
458
 
459
            case RADIUS_CLASS:
460
                $this->attributes['class'] = radius_cvt_string($data);
461
                break;
462
 
463
            case RADIUS_FRAMED_PROTOCOL:
464
                $this->attributes['framed_protocol'] = radius_cvt_int($data);
465
                break;
466
 
467
            case RADIUS_FRAMED_ROUTING:
468
                $this->attributes['framed_routing'] = radius_cvt_int($data);
469
                break;
470
 
471
            case RADIUS_FILTER_ID:
472
                $this->attributes['filter_id'] = radius_cvt_string($data);
473
                break;
474
 
475
            case RADIUS_REPLY_MESSAGE:
476
                $this->attributes['reply_message'] = radius_cvt_string($data);
477
                break;
478
 
479
            case RADIUS_VENDOR_SPECIFIC:
480
                $attribv = radius_get_vendor_attr($data);
481
                if (!is_array($attribv)) {
482
                    return false;
483
                }
484
 
485
                $vendor = $attribv['vendor'];
486
                $attrv = $attribv['attr'];
487
                $datav = $attribv['data'];
488
 
489
                $this->rawVendorAttributes[$vendor][$attrv] = $datav;
490
 
491
                if ($vendor == RADIUS_VENDOR_MICROSOFT) {
492
 
493
                    switch ($attrv) {
494
                    case RADIUS_MICROSOFT_MS_CHAP2_SUCCESS:
495
                        $this->attributes['ms_chap2_success'] = radius_cvt_string($datav);
496
                        break;
497
 
498
                    case RADIUS_MICROSOFT_MS_CHAP_ERROR:
499
                        $this->attributes['ms_chap_error'] = radius_cvt_string(substr($datav,1));
500
                        break;
501
 
502
                    case RADIUS_MICROSOFT_MS_CHAP_DOMAIN:
503
                        $this->attributes['ms_chap_domain'] = radius_cvt_string($datav);
504
                        break;
505
 
506
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
507
                        $this->attributes['ms_mppe_encryption_policy'] = radius_cvt_int($datav);
508
                        break;
509
 
510
                    case RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
511
                        $this->attributes['ms_mppe_encryption_types'] = radius_cvt_int($datav);
512
                        break;
513
 
514
                    case RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS:
515
                        $demangled = radius_demangle($this->res, $datav);
516
                        $this->attributes['ms_chap_mppe_lm_key'] = substr($demangled, 0, 8);
517
                        $this->attributes['ms_chap_mppe_nt_key'] = substr($demangled, 8, RADIUS_MPPE_KEY_LEN);
518
                        break;
519
 
520
                    case RADIUS_MICROSOFT_MS_MPPE_SEND_KEY:
521
                        $this->attributes['ms_chap_mppe_send_key'] = radius_demangle_mppe_key($this->res, $datav);
522
                        break;
523
 
524
                    case RADIUS_MICROSOFT_MS_MPPE_RECV_KEY:
525
                        $this->attributes['ms_chap_mppe_recv_key'] = radius_demangle_mppe_key($this->res, $datav);
526
                        break;
527
 
528
                    case RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER:
529
                        $this->attributes['ms_primary_dns_server'] = radius_cvt_string($datav);
530
                        break;
531
                    }
532
                }
533
                break;
534
 
535
            }
536
        }
537
 
538
        return true;
539
    }
540
 
541
    /**
542
     * Frees resources.
543
     *
544
     * Calling this method is always a good idea, because all security relevant
545
     * attributes are filled with Nullbytes to leave nothing in the mem.
546
     *
547
     * @access public
548
     */
549
    function close()
550
    {
551
        if ($this->res != null) {
552
            radius_close($this->res);
553
            $this->res = null;
554
        }
555
        $this->username = str_repeat("\0", strlen($this->username));
556
        $this->password = str_repeat("\0", strlen($this->password));
557
    }
558
 
559
}
560
 
561
/**
562
 * class Auth_RADIUS_PAP
563
 *
564
 * Class for authenticating using PAP (Plaintext)
565
 *
566
 * @package Auth_RADIUS
567
 */
568
class Auth_RADIUS_PAP extends Auth_RADIUS
569
{
570
 
571
    /**
572
     * Constructor
573
     *
574
     * @param  string  $username   Username
575
     * @param  string  $password   Password
576
     * @return void
577
     */
578
    function Auth_RADIUS_PAP($username = null, $password = null)
579
    {
580
        $this->Auth_RADIUS();
581
        $this->username = $username;
582
        $this->password = $password;
583
    }
584
 
585
    /**
586
     * Creates a RADIUS resource
587
     *
588
     * Creates a RADIUS resource for authentication. This should be the first
589
     * call before you make any other things with the library.
590
     *
591
     * @return bool   true on success, false on error
592
     */
593
    function open()
594
    {
595
        $this->res = radius_auth_open();
596
        if (!$this->res) {
597
            return false;
598
        }
599
        return true;
600
    }
601
 
602
    /**
603
     * Creates an authentication request
604
     *
605
     * Creates an authentication request.
606
     * You MUST call this method before you can put any attribute
607
     *
608
     * @return bool   true on success, false on error
609
     */
610
    function createRequest()
611
    {
612
        if (!radius_create_request($this->res, RADIUS_ACCESS_REQUEST)) {
613
            return false;
614
        }
615
        return true;
616
    }
617
 
618
    /**
619
     * Put authentication specific attributes
620
     *
621
     * @return void
622
     */
623
    function putAuthAttributes()
624
    {
625
        if (isset($this->username)) {
626
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
627
        }
628
        if (isset($this->password)) {
629
            $this->putAttribute(RADIUS_USER_PASSWORD, $this->password);
630
        }
631
    }
632
 
633
}
634
 
635
/**
636
 * class Auth_RADIUS_CHAP_MD5
637
 *
638
 * Class for authenticating using CHAP-MD5 see RFC1994.
639
 * Instead og the plaintext password the challenge and
640
 * the response are needed.
641
 *
642
 * @package Auth_RADIUS
643
 */
644
class Auth_RADIUS_CHAP_MD5 extends Auth_RADIUS_PAP
645
{
646
    /**
647
     * 8 Bytes binary challenge
648
     * @var  string
649
     */
650
    var $challenge = null;
651
 
652
    /**
653
     * 16 Bytes MD5 response binary
654
     * @var  string
655
     */
656
    var $response = null;
657
 
658
    /**
659
     * Id of the authentication request. Should incremented after every request.
660
     * @var  integer
661
     */
662
    var $chapid = 1;
663
 
664
    /**
665
     * Constructor
666
     *
667
     * @param  string  $username   Username
668
     * @param  string  $challenge  8 Bytes Challenge (binary)
669
     * @param  integer $chapid     Requestnumber
670
     * @return void
671
     */
672
    function Auth_RADIUS_CHAP_MD5($username = null, $challenge = null, $chapid = 1)
673
    {
674
        $this->Auth_RADIUS_PAP();
675
        $this->username = $username;
676
        $this->challenge = $challenge;
677
        $this->chapid = $chapid;
678
    }
679
 
680
    /**
681
     * Put CHAP-MD5 specific attributes
682
     *
683
     * For authenticating using CHAP-MD5 via RADIUS you have to put the challenge
684
     * and the response. The chapid is inserted in the first byte of the response.
685
     *
686
     * @return void
687
     */
688
    function putAuthAttributes()
689
    {
690
        if (isset($this->username)) {
691
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
692
        }
693
        if (isset($this->response)) {
694
            $response = pack('C', $this->chapid) . $this->response;
695
            $this->putAttribute(RADIUS_CHAP_PASSWORD, $response);
696
        }
697
        if (isset($this->challenge)) {
698
            $this->putAttribute(RADIUS_CHAP_CHALLENGE, $this->challenge);
699
        }
700
    }
701
 
702
    /**
703
     * Frees resources.
704
     *
705
     * Calling this method is always a good idea, because all security relevant
706
     * attributes are filled with Nullbytes to leave nothing in the mem.
707
     *
708
     * @access public
709
     */
710
    function close()
711
    {
712
        Auth_RADIUS_PAP::close();
713
        $this->challenge =  str_repeat("\0", strlen($this->challenge));
714
        $this->response =  str_repeat("\0", strlen($this->response));
715
    }
716
 
717
}
718
 
719
/**
720
 * class Auth_RADIUS_MSCHAPv1
721
 *
722
 * Class for authenticating using MS-CHAPv1 see RFC2433
723
 *
724
 * @package Auth_RADIUS
725
 */
726
class Auth_RADIUS_MSCHAPv1 extends Auth_RADIUS_CHAP_MD5
727
{
728
    /**
729
     * LAN-Manager-Response
730
     * @var  string
731
     */
732
    var $lmResponse = null;
733
 
734
    /**
735
     * Wether using deprecated LM-Responses or not.
736
     * 0 = use LM-Response, 1 = use NT-Response
737
     * @var  bool
738
     */
739
    var $flags = 1;
740
 
741
    /**
742
     * Put MS-CHAPv1 specific attributes
743
     *
744
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
745
     * and the response. The response has this structure:
746
     * struct rad_mschapvalue {
747
     *   u_char ident;
748
     *   u_char flags;
749
     *   u_char lm_response[24];
750
     *   u_char response[24];
751
     * };
752
     *
753
     * @return void
754
     */
755
    function putAuthAttributes()
756
    {
757
        if (isset($this->username)) {
758
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
759
        }
760
        if (isset($this->response) || isset($this->lmResponse)) {
761
            $lmResp = isset($this->lmResponse) ? $this->lmResponse : str_repeat ("\0", 24);
762
            $ntResp = isset($this->response)   ? $this->response :   str_repeat ("\0", 24);
763
            $resp = pack('CC', $this->chapid, $this->flags) . $lmResp . $ntResp;
764
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_RESPONSE, $resp);
765
        }
766
        if (isset($this->challenge)) {
767
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
768
        }
769
    }
770
}
771
 
772
/**
773
 * class Auth_RADIUS_MSCHAPv2
774
 *
775
 * Class for authenticating using MS-CHAPv2 see RFC2759
776
 *
777
 * @package Auth_RADIUS
778
 */
779
class Auth_RADIUS_MSCHAPv2 extends Auth_RADIUS_MSCHAPv1
780
{
781
    /**
782
     * 16 Bytes binary challenge
783
     * @var  string
784
     */
785
    var $challenge = null;
786
 
787
    /**
788
     * 16 Bytes binary Peer Challenge
789
     * @var  string
790
     */
791
    var $peerChallenge = null;
792
 
793
  /**
794
     * Put MS-CHAPv2 specific attributes
795
     *
796
     * For authenticating using MS-CHAPv1 via RADIUS you have to put the challenge
797
     * and the response. The response has this structure:
798
     * struct rad_mschapv2value {
799
     *   u_char ident;
800
     *   u_char flags;
801
     *   u_char pchallenge[16];
802
     *   u_char reserved[8];
803
     *   u_char response[24];
804
     * };
805
     * where pchallenge is the peer challenge. Like for MS-CHAPv1 we set the flags field to 1.
806
     * @return void
807
     */
808
    function putAuthAttributes()
809
    {
810
        if (isset($this->username)) {
811
            $this->putAttribute(RADIUS_USER_NAME, $this->username);
812
        }
813
        if (isset($this->response) && isset($this->peerChallenge)) {
814
            // Response: chapid, flags (1 = use NT Response), Peer challenge, reserved, Response
815
            $resp = pack('CCa16a8a24',$this->chapid , 1, $this->peerChallenge, str_repeat("\0", 8), $this->response);
816
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP2_RESPONSE, $resp);
817
        }
818
        if (isset($this->challenge)) {
819
            $this->putVendorAttribute(RADIUS_VENDOR_MICROSOFT, RADIUS_MICROSOFT_MS_CHAP_CHALLENGE, $this->challenge);
820
        }
821
    }
822
 
823
    /**
824
     * Frees resources.
825
     *
826
     * Calling this method is always a good idea, because all security relevant
827
     * attributes are filled with Nullbytes to leave nothing in the mem.
828
     *
829
     * @access public
830
     */
831
    function close()
832
    {
833
        Auth_RADIUS_MSCHAPv1::close();
834
        $this->peerChallenge = str_repeat("\0", strlen($this->peerChallenge));
835
    }
836
}
837
 
838
/**
839
 * class Auth_RADIUS_Acct
840
 *
841
 * Class for RADIUS accounting
842
 *
843
 * @package Auth_RADIUS
844
 */
845
class Auth_RADIUS_Acct extends Auth_RADIUS
846
{
847
    /**
848
     * Defines where the Authentication was made, possible values are:
849
     * RADIUS_AUTH_RADIUS, RADIUS_AUTH_LOCAL, RADIUS_AUTH_REMOTE
850
     * @var  integer
851
     */
852
    var $authentic = null;
853
 
854
   /**
855
     * Defines the type of the accounting request, on of:
856
     * RADIUS_START, RADIUS_STOP, RADIUS_ACCOUNTING_ON, RADIUS_ACCOUNTING_OFF
857
     * @var  integer
858
     */
859
    var $status_type = null;
860
 
861
   /**
862
     * The time the user was logged in in seconds
863
     * @var  integer
864
     */
865
    var $session_time = null;
866
 
867
   /**
868
     * A uniq identifier for the session of the user, maybe the PHP-Session-Id
869
     * @var  string
870
     */
871
    var $session_id = null;
872
 
873
    /**
874
     * Constructor
875
     *
876
     * Generates a predefined session_id. We use the Remote-Address, the PID, and the Current user.
877
     * @return void
878
     */
879
    function Auth_RADIUS_Acct()
880
    {
881
        $this->Auth_RADIUS();
882
 
883
        if (isset($_SERVER)) {
884
            $var = &$_SERVER;
885
        } else {
886
            $var = &$GLOBALS['HTTP_SERVER_VARS'];
887
        }
888
 
889
        $this->session_id = sprintf("%s:%d-%s", isset($var['REMOTE_ADDR']) ? $var['REMOTE_ADDR'] : '127.0.0.1' , getmypid(), get_current_user());
890
    }
891
 
892
    /**
893
     * Creates a RADIUS resource
894
     *
895
     * Creates a RADIUS resource for accounting. This should be the first
896
     * call before you make any other things with the library.
897
     *
898
     * @return bool   true on success, false on error
899
     */
900
    function open()
901
    {
902
        $this->res = radius_acct_open();
903
        if (!$this->res) {
904
            return false;
905
        }
906
        return true;
907
    }
908
 
909
   /**
910
     * Creates an accounting request
911
     *
912
     * Creates an accounting request.
913
     * You MUST call this method before you can put any attribute.
914
     *
915
     * @return bool   true on success, false on error
916
     */
917
    function createRequest()
918
    {
919
        if (!radius_create_request($this->res, RADIUS_ACCOUNTING_REQUEST)) {
920
            return false;
921
        }
922
        return true;
923
    }
924
 
925
  /**
926
     * Put attributes for accounting.
927
     *
928
     * Here we put some accounting values. There many more attributes for accounting,
929
     * but for web-applications only certain attributes make sense.
930
     * @return void
931
     */
932
    function putAuthAttributes()
933
    {
934
        $this->putAttribute(RADIUS_ACCT_SESSION_ID, $this->session_id);
935
        $this->putAttribute(RADIUS_ACCT_STATUS_TYPE, $this->status_type);
936
        if (isset($this->session_time) && $this->status_type == RADIUS_STOP) {
937
            $this->putAttribute(RADIUS_ACCT_SESSION_TIME, $this->session_time);
938
        }
939
        if (isset($this->authentic)) {
940
            $this->putAttribute(RADIUS_ACCT_AUTHENTIC, $this->authentic);
941
        }
942
 
943
    }
944
 
945
}
946
 
947
/**
948
 * class Auth_RADIUS_Acct_Start
949
 *
950
 * Class for RADIUS accounting. Its usualy used, after the user has logged in.
951
 *
952
 * @package Auth_RADIUS
953
 */
954
class Auth_RADIUS_Acct_Start extends Auth_RADIUS_Acct
955
{
956
   /**
957
     * Defines the type of the accounting request.
958
     * It is set to RADIUS_START by default in this class.
959
     * @var  integer
960
     */
961
    var $status_type = RADIUS_START;
962
}
963
 
964
/**
965
 * class Auth_RADIUS_Acct_Start
966
 *
967
 * Class for RADIUS accounting. Its usualy used, after the user has logged out.
968
 *
969
 * @package Auth_RADIUS
970
 */
971
class Auth_RADIUS_Acct_Stop extends Auth_RADIUS_Acct
972
{
973
   /**
974
     * Defines the type of the accounting request.
975
     * It is set to RADIUS_STOP by default in this class.
976
     * @var  integer
977
     */
978
    var $status_type = RADIUS_STOP;
979
}
980
 
981
if (!defined('RADIUS_UPDATE'))
982
    define('RADIUS_UPDATE', 3);
983
 
984
/**
985
 * class Auth_RADIUS_Acct_Update
986
 *
987
 * Class for interim RADIUS accounting updates.
988
 *
989
 * @package Auth_RADIUS
990
 */
991
class Auth_RADIUS_Acct_Update extends Auth_RADIUS_Acct
992
{
993
   /**
994
     * Defines the type of the accounting request.
995
     * It is set to RADIUS_UPDATE by default in this class.
996
     * @var  integer
997
     */
998
    var $status_type = RADIUS_UPDATE;
999
}
1000
 
1001
?>