Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1173 jp_milcent 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
 
4
/**
5
 * The main include file for Auth package
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: This source file is subject to version 3.01 of the PHP license
10
 * that is available through the world-wide-web at the following URI:
11
 * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
12
 * the PHP License and are unable to obtain it through the web, please
13
 * send a note to license@php.net so we can mail you a copy immediately.
14
 *
15
 * @category   Authentication
16
 * @package    Auth
17
 * @author     Martin Jansen <mj@php.net>
18
 * @author     Adam Ashley <aashley@php.net>
19
 * @copyright  2001-2006 The PHP Group
20
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
21
 * @version    CVS: $Id: Auth.php,v 1.2 2006-12-14 15:04:29 jp_milcent Exp $
22
 * @link       http://pear.php.net/package/Auth
23
 */
24
 
25
/**
26
 * Returned if session exceeds idle time
27
 */
28
define('AUTH_IDLED',                    -1);
29
/**
30
 * Returned if session has expired
31
 */
32
define('AUTH_EXPIRED',                  -2);
33
/**
34
 * Returned if container is unable to authenticate user/password pair
35
 */
36
define('AUTH_WRONG_LOGIN',              -3);
37
/**
38
 * Returned if a container method is not supported.
39
 */
40
define('AUTH_METHOD_NOT_SUPPORTED',     -4);
41
/**
42
 * Returned if new Advanced security system detects a breach
43
 */
44
define('AUTH_SECURITY_BREACH',          -5);
45
/**
46
 * Returned if checkAuthCallback says session should not continue.
47
 */
48
define('AUTH_CALLBACK_ABORT',           -6);
49
 
50
/**
51
 * PEAR::Auth
52
 *
53
 * The PEAR::Auth class provides methods for creating an
54
 * authentication system using PHP.
55
 *
56
 * @category   Authentication
57
 * @package    Auth
58
 * @author     Martin Jansen <mj@php.net>
59
 * @author     Adam Ashley <aashley@php.net>
60
 * @copyright  2001-2006 The PHP Group
61
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
62
 * @version    Release: 1.4.3  File: $Revision: 1.2 $
63
 * @link       http://pear.php.net/package/Auth
64
 */
65
class Auth {
66
 
67
    // {{{ properties
68
 
69
    /**
70
     * Auth lifetime in seconds
71
     *
72
     * If this variable is set to 0, auth never expires
73
     *
74
     * @var  integer
75
     * @see  setExpire(), checkAuth()
76
     */
77
    var $expire = 0;
78
 
79
    /**
80
     * Has the auth session expired?
81
     *
82
     * @var   bool
83
     * @see   checkAuth()
84
     */
85
    var $expired = false;
86
 
87
    /**
88
     * Maximum idletime in seconds
89
     *
90
     * The difference to $expire is, that the idletime gets
91
     * refreshed each time checkAuth() is called. If this
92
     * variable is set to 0, idletime is never checked.
93
     *
94
     * @var integer
95
     * @see setIdle(), checkAuth()
96
     */
97
    var $idle = 0;
98
 
99
    /**
100
     * Is the maximum idletime over?
101
     *
102
     * @var boolean
103
     * @see checkAuth()
104
     */
105
    var $idled = false;
106
 
107
    /**
108
     * Storage object
109
     *
110
     * @var object
111
     * @see Auth(), validateLogin()
112
     */
113
    var $storage = '';
114
 
115
    /**
116
     * User-defined function that creates the login screen
117
     *
118
     * @var string
119
     */
120
    var $loginFunction = '';
121
 
122
    /**
123
     * Should the login form be displayed
124
     *
125
     * @var   bool
126
     * @see   setShowlogin()
127
     */
128
    var $showLogin = true;
129
 
130
    /**
131
      * Is Login Allowed from this page
132
      *
133
      * @var  bool
134
      * @see setAllowLogin
135
      */
136
    var $allowLogin = true;
137
 
138
    /**
139
     * Current authentication status
140
     *
141
     * @var string
142
     */
143
    var $status = '';
144
 
145
    /**
146
     * Username
147
     *
148
     * @var string
149
     */
150
    var $username = '';
151
 
152
    /**
153
     * Password
154
     *
155
     * @var string
156
     */
157
    var $password = '';
158
 
159
    /**
160
     * checkAuth callback function name
161
     *
162
     * @var string
163
     * @see setCheckAuthCallback()
164
     */
165
    var $checkAuthCallback = '';
166
 
167
    /**
168
     * Login callback function name
169
     *
170
     * @var string
171
     * @see setLoginCallback()
172
     */
173
    var $loginCallback = '';
174
 
175
    /**
176
     * Failed Login callback function name
177
     *
178
     * @var string
179
     * @see setFailedLoginCallback()
180
     */
181
    var $loginFailedCallback = '';
182
 
183
    /**
184
     * Logout callback function name
185
     *
186
     * @var string
187
     * @see setLogoutCallback()
188
     */
189
    var $logoutCallback = '';
190
 
191
    /**
192
     * Auth session-array name
193
     *
194
     * @var string
195
     */
196
    var $_sessionName = '_authsession';
197
 
198
    /**
199
     * Package Version
200
     *
201
     * @var string
202
     */
203
    var $version = "@version@";
204
 
205
    /**
206
     * Flag to use advanced security
207
     * When set extra checks will be made to see if the
208
     * user's IP or useragent have changed across requests.
209
     * Turned off by default to preserve BC.
210
     *
211
     * @var boolean
212
     */
213
    var $advancedsecurity = false;
214
 
215
    /**
216
     * Username key in POST array
217
     *
218
     * @var string
219
     */
220
    var $_postUsername = 'username';
221
 
222
    /**
223
     * Password key in POST array
224
     *
225
     * @var string
226
     */
227
    var $_postPassword = 'password';
228
 
229
    /**
230
     * Holds a reference to the session auth variable
231
     * @var array
232
     */
233
    var $session;
234
 
235
    /**
236
     * Holds a reference to the global server variable
237
     * @var array
238
     */
239
    var $server;
240
 
241
    /**
242
     * Holds a reference to the global post variable
243
     * @var array
244
     */
245
    var $post;
246
 
247
    /**
248
     * Holds a reference to the global cookie variable
249
     * @var array
250
     */
251
    var $cookie;
252
 
253
    /**
254
     * A hash to hold various superglobals as reference
255
     * @var array
256
     */
257
    var $authdata;
258
 
259
    /**
260
      * How many times has checkAuth been called
261
      * var int
262
      */
263
    var $authChecks = 0;
264
 
265
    // }}}
266
    // {{{ Auth() [constructor]
267
 
268
    /**
269
     * Constructor
270
     *
271
     * Set up the storage driver.
272
     *
273
     * @param string    Type of the storage driver
274
     * @param mixed     Additional options for the storage driver
275
     *                  (example: if you are using DB as the storage
276
     *                   driver, you have to pass the dsn string here)
277
     *
278
     * @param string    Name of the function that creates the login form
279
     * @param boolean   Should the login form be displayed if neccessary?
280
     * @return void
281
     */
282
    function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true)
283
    {
284
        $this->applyAuthOptions($options);
285
 
286
        // Start the session suppress error if already started
287
        if(!session_id()){
288
            @session_start();
289
            if(!session_id()) {
290
                // Throw error
291
                include_once 'PEAR.php';
292
                PEAR::throwError('Session could not be started by Auth, '
293
                        .'possibly headers are already sent, try putting '
294
                        .'ob_start in the beginning of your script');
295
            }
296
        }
297
 
298
        // Make Sure Auth session variable is there
299
        if(!isset($_SESSION[$this->_sessionName])) {
300
            $_SESSION[$this->_sessionName] = array();
301
        }
302
 
303
        // Assign Some globals to internal references, this will replace _importGlobalVariable
304
        $this->session =& $_SESSION[$this->_sessionName];
305
        $this->server =& $_SERVER;
306
        $this->post =& $_POST;
307
        $this->cookie =& $_COOKIE;
308
 
309
        if ($loginFunction != '' && is_callable($loginFunction)) {
310
            $this->loginFunction = $loginFunction;
311
        }
312
 
313
        if (is_bool($showLogin)) {
314
            $this->showLogin = $showLogin;
315
        }
316
 
317
        if (is_object($storageDriver)) {
318
            $this->storage =& $storageDriver;
319
            // Pass a reference to auth to the container, ugly but works
320
            // this is used by the DB container to use method setAuthData not staticaly.
321
            $this->storage->_auth_obj =& $this;
322
        } else {
323
            // $this->storage = $this->_factory($storageDriver, $options);
324
            //
325
            $this->storage_driver = $storageDriver;
326
            $this->storage_options =& $options;
327
        }
328
    }
329
 
330
    // }}}
331
    // {{{ applyAuthOptions()
332
 
333
    /**
334
      * Set the Auth options
335
      *
336
      * Some options which are Auth specific will be applied
337
      * the rest will be left for usage by the container
338
      *
339
      * @param array    An array of Auth options
340
      * @return array   The options which were not applied
341
      * @access private
342
      */
343
    function &applyAuthOptions(&$options)
344
    {
345
        if(is_array($options)){
346
            if (!empty($options['sessionName'])) {
347
                $this->_sessionName = $options['sessionName'];
348
                unset($options['sessionName']);
349
            }
350
            if (isset($options['allowLogin'])) {
351
                $this->allowLogin = $options['allowLogin'];
352
                unset($options['allowLogin']);
353
            }
354
            if (!empty($options['postUsername'])) {
355
                $this->_postUsername = $options['postUsername'];
356
                unset($options['postUsername']);
357
            }
358
            if (!empty($options['postPassword'])) {
359
                $this->_postPassword = $options['postPassword'];
360
                unset($options['postPassword']);
361
            }
362
            if (isset($options['advancedsecurity'])) {
363
                $this->advancedsecurity = $options['advancedsecurity'];
364
                unset($options['advancedsecurity']);
365
            }
366
        }
367
        return($options);
368
    }
369
 
370
    // }}}
371
    // {{{ _loadStorage()
372
 
373
    /**
374
      * Load Storage Driver if not already loaded
375
      *
376
      * Suspend storage instantiation to make Auth lighter to use
377
      * for calls which do not require login
378
      *
379
      * @return bool    True if the conainer is loaded, false if the container
380
      *                 is already loaded
381
      * @access private
382
      */
383
    function _loadStorage()
384
    {
385
        if(!is_object($this->storage)) {
386
            $this->storage =& $this->_factory($this->storage_driver,
387
                    $this->storage_options);
388
            $this->storage->_auth_obj =& $this;
389
            return(true);
390
        }
391
        return(false);
392
    }
393
 
394
    // }}}
395
    // {{{ _factory()
396
 
397
    /**
398
     * Return a storage driver based on $driver and $options
399
     *
400
     * @static
401
     * @param  string $driver  Type of storage class to return
402
     * @param  string $options Optional parameters for the storage class
403
     * @return object Object   Storage object
404
     * @access private
405
     */
406
    function &_factory($driver, $options = '')
407
    {
408
        $storage_class = 'Auth_Container_' . $driver;
409
        include_once 'Auth/Container/' . $driver . '.php';
410
        $obj =& new $storage_class($options);
411
        return $obj;
412
    }
413
 
414
    // }}}
415
    // {{{ assignData()
416
 
417
    /**
418
     * Assign data from login form to internal values
419
     *
420
     * This function takes the values for username and password
421
     * from $HTTP_POST_VARS/$_POST and assigns them to internal variables.
422
     * If you wish to use another source apart from $HTTP_POST_VARS/$_POST,
423
     * you have to derive this function.
424
     *
425
     * @global $HTTP_POST_VARS, $_POST
426
     * @see    Auth
427
     * @return void
428
     * @access private
429
     */
430
    function assignData()
431
    {
432
        if (   isset($this->post[$this->_postUsername])
433
            && $this->post[$this->_postUsername] != '') {
434
            $this->username = (get_magic_quotes_gpc() == 1
435
                    ? stripslashes($this->post[$this->_postUsername])
436
                    : $this->post[$this->_postUsername]);
437
        }
438
        if (   isset($this->post[$this->_postPassword])
439
            && $this->post[$this->_postPassword] != '') {
440
            $this->password = (get_magic_quotes_gpc() == 1
441
                    ? stripslashes($this->post[$this->_postPassword])
442
                    : $this->post[$this->_postPassword] );
443
        }
444
    }
445
 
446
    // }}}
447
    // {{{ start()
448
 
449
    /**
450
     * Start new auth session
451
     *
452
     * @return void
453
     * @access public
454
     */
455
    function start()
456
    {
457
        $this->assignData();
458
        if (!$this->checkAuth() && $this->allowLogin) {
459
            $this->login();
460
        }
461
    }
462
 
463
    // }}}
464
    // {{{ login()
465
 
466
    /**
467
     * Login function
468
     *
469
     * @return void
470
     * @access private
471
     */
472
    function login()
473
    {
474
        $login_ok = false;
475
        $this->_loadStorage();
476
 
477
        // Check if using challenge response
478
        (isset($this->post['authsecret']) && $this->post['authsecret'] == 1)
479
            ? $usingChap = true
480
            : $usingChap = false;
481
 
482
 
483
        // When the user has already entered a username, we have to validate it.
484
        if (!empty($this->username)) {
485
            if (true === $this->storage->fetchData($this->username, $this->password, $usingChap)) {
486
                $this->session['challengekey'] = md5($this->username.$this->password);
487
                $login_ok = true;
488
            }
489
        }
490
 
491
        if (!empty($this->username) && $login_ok) {
492
            $this->setAuth($this->username);
493
            if (is_callable($this->loginCallback)) {
494
                call_user_func_array($this->loginCallback, array($this->username, &$this));
495
            }
496
        }
497
 
498
        // If the login failed or the user entered no username,
499
        // output the login screen again.
500
        if (!empty($this->username) && !$login_ok) {
501
            $this->status = AUTH_WRONG_LOGIN;
502
            if (is_callable($this->loginFailedCallback)) {
503
                call_user_func_array($this->loginFailedCallback, array($this->username, &$this));
504
            }
505
        }
506
 
507
        if ((empty($this->username) || !$login_ok) && $this->showLogin) {
508
            if (is_callable($this->loginFunction)) {
509
                call_user_func_array($this->loginFunction, array($this->username, $this->status, &$this));
510
            } else {
511
                // BC fix Auth used to use drawLogin for this
512
                // call is sub classes implement this
513
                if (is_callable(array($this, 'drawLogin'))) {
514
                    return $this->drawLogin($this->username, $this);
515
                }
516
 
517
                // New Login form
518
                include_once 'Auth/Frontend/Html.php';
519
                return Auth_Frontend_Html::render($this, $this->username);
520
            }
521
        } else {
522
            return;
523
        }
524
    }
525
 
526
    // }}}
527
    // {{{ setExpire()
528
 
529
    /**
530
     * Set the maximum expire time
531
     *
532
     * @param  integer time in seconds
533
     * @param  bool    add time to current expire time or not
534
     * @return void
535
     * @access public
536
     */
537
    function setExpire($time, $add = false)
538
    {
539
        $add ? $this->expire += $time : $this->expire = $time;
540
    }
541
 
542
    // }}}
543
    // {{{ setIdle()
544
 
545
    /**
546
     * Set the maximum idle time
547
     *
548
     * @param  integer time in seconds
549
     * @param  bool    add time to current maximum idle time or not
550
     * @return void
551
     * @access public
552
     */
553
    function setIdle($time, $add = false)
554
    {
555
        $add ? $this->idle += $time : $this->idle = $time;
556
    }
557
 
558
    // }}}
559
    // {{{ setSessionName()
560
 
561
    /**
562
     * Set name of the session to a customized value.
563
     *
564
     * If you are using multiple instances of PEAR::Auth
565
     * on the same domain, you can change the name of
566
     * session per application via this function.
567
     * This will chnage the name of the session variable
568
     * auth uses to store it's data in the session
569
     *
570
     * @param  string New name for the session
571
     * @return void
572
     * @access public
573
     */
574
    function setSessionName($name = 'session')
575
    {
576
        $this->_sessionName = '_auth_'.$name;
577
        $this->session =& $_SESSION[$this->_sessionName];
578
    }
579
 
580
    // }}}
581
    // {{{ setShowLogin()
582
 
583
    /**
584
     * Should the login form be displayed if neccessary?
585
     *
586
     * @param  bool    show login form or not
587
     * @return void
588
     * @access public
589
     */
590
    function setShowLogin($showLogin = true)
591
    {
592
        $this->showLogin = $showLogin;
593
    }
594
 
595
    // }}}
596
    // {{{ setAllowLogin()
597
 
598
    /**
599
     * Should the login form be displayed if neccessary?
600
     *
601
     * @param  bool    show login form or not
602
     * @return void
603
     * @access public
604
     */
605
    function setAllowLogin($allowLogin = true)
606
    {
607
        $this->allowLogin = $allowLogin;
608
    }
609
 
610
    // }}}
611
    // {{{ setCheckAuthCallback()
612
 
613
    /**
614
     * Register a callback function to be called whenever the validity of the login is checked
615
     * The function will receive two parameters, the username and a reference to the auth object.
616
     *
617
     * @param  string  callback function name
618
     * @return void
619
     * @access public
620
     * @since Method available since Release 1.4.3
621
     */
622
    function setCheckAuthCallback($checkAuthCallback)
623
    {
624
        $this->checkAuthCallback = $checkAuthCallback;
625
    }
626
 
627
    // }}}
628
    // {{{ setLoginCallback()
629
 
630
    /**
631
     * Register a callback function to be called on user login.
632
     * The function will receive two parameters, the username and a reference to the auth object.
633
     *
634
     * @param  string  callback function name
635
     * @return void
636
     * @see    setLogoutCallback()
637
     * @access public
638
     */
639
    function setLoginCallback($loginCallback)
640
    {
641
        $this->loginCallback = $loginCallback;
642
    }
643
 
644
    // }}}
645
    // {{{ setFailedLoginCallback()
646
 
647
    /**
648
     * Register a callback function to be called on failed user login.
649
     * The function will receive two parameters, the username and a reference to the auth object.
650
     *
651
     * @param  string  callback function name
652
     * @return void
653
     * @access public
654
     */
655
    function setFailedLoginCallback($loginFailedCallback)
656
    {
657
        $this->loginFailedCallback = $loginFailedCallback;
658
    }
659
 
660
    // }}}
661
    // {{{ setLogoutCallback()
662
 
663
    /**
664
     * Register a callback function to be called on user logout.
665
     * The function will receive three parameters, the username and a reference to the auth object.
666
     *
667
     * @param  string  callback function name
668
     * @return void
669
     * @see    setLoginCallback()
670
     * @access public
671
     */
672
    function setLogoutCallback($logoutCallback)
673
    {
674
        $this->logoutCallback = $logoutCallback;
675
    }
676
 
677
    // }}}
678
    // {{{ setAuthData()
679
 
680
    /**
681
     * Register additional information that is to be stored
682
     * in the session.
683
     *
684
     * @param  string  Name of the data field
685
     * @param  mixed   Value of the data field
686
     * @param  boolean Should existing data be overwritten? (default
687
     *                 is true)
688
     * @return void
689
     * @access public
690
     */
691
    function setAuthData($name, $value, $overwrite = true)
692
    {
693
        if (!empty($this->session['data'][$name]) && $overwrite == false) {
694
            return;
695
        }
696
        $this->session['data'][$name] = $value;
697
    }
698
 
699
    // }}}
700
    // {{{ getAuthData()
701
 
702
    /**
703
     * Get additional information that is stored in the session.
704
     *
705
     * If no value for the first parameter is passed, the method will
706
     * return all data that is currently stored.
707
     *
708
     * @param  string Name of the data field
709
     * @return mixed  Value of the data field.
710
     * @access public
711
     */
712
    function getAuthData($name = null)
713
    {
714
        if (!isset($this->session['data'])) {
715
            return null;
716
        }
717
        if(!isset($name)) {
718
            return $this->session['data'];
719
        }
720
        if (isset($name) && isset($this->session['data'][$name])) {
721
            return $this->session['data'][$name];
722
        }
723
        return null;
724
    }
725
 
726
    // }}}
727
    // {{{ setAuth()
728
 
729
    /**
730
     * Register variable in a session telling that the user
731
     * has logged in successfully
732
     *
733
     * @param  string Username
734
     * @return void
735
     * @access public
736
     */
737
    function setAuth($username)
738
    {
739
 
740
        // #2021 - Change the session id to avoid session fixation attacks php 4.3.3 >
741
        session_regenerate_id(true);
742
 
743
        if (!isset($this->session) || !is_array($this->session)) {
744
            $this->session = array();
745
        }
746
 
747
        if (!isset($this->session['data'])) {
748
            $this->session['data'] = array();
749
        }
750
 
751
        $this->session['sessionip'] = isset($this->server['REMOTE_ADDR'])
752
            ? $this->server['REMOTE_ADDR']
753
            : '';
754
        $this->session['sessionuseragent'] = isset($this->server['HTTP_USER_AGENT'])
755
            ? $this->server['HTTP_USER_AGENT']
756
            : '';
757
 
758
        // This should be set by the container to something more safe
759
        // Like md5(passwd.microtime)
760
        if(empty($this->session['challengekey'])) {
761
            $this->session['challengekey'] = md5($username.microtime());
762
        }
763
 
764
        $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
765
        setcookie('authchallenge', $this->session['challengecookie']);
766
 
767
        $this->session['registered'] = true;
768
        $this->session['username']   = $username;
769
        $this->session['timestamp']  = time();
770
        $this->session['idle']       = time();
771
    }
772
 
773
    // }}}
774
    // {{{ setAdvancedSecurity()
775
 
776
    /**
777
      * Enables advanced security checks
778
      *
779
      * Currently only ip change and useragent change
780
      * are detected
781
      * @todo Add challenge cookies - Create a cookie which changes every time
782
      *       and contains some challenge key which the server can verify with
783
      *       a session var cookie might need to be crypted (user pass)
784
      * @param bool Enable or disable
785
      * @return void
786
      * @access public
787
      */
788
    function setAdvancedSecurity($flag=true)
789
    {
790
        $this->advancedsecurity = $flag;
791
    }
792
 
793
    // }}}
794
    // {{{ checkAuth()
795
 
796
    /**
797
     * Checks if there is a session with valid auth information.
798
     *
799
     * @access public
800
     * @return boolean  Whether or not the user is authenticated.
801
     */
802
    function checkAuth()
803
    {
804
        $this->authChecks++;
805
        if (isset($this->session)) {
806
            // Check if authentication session is expired
807
            if (   $this->expire > 0
808
                && isset($this->session['timestamp'])
809
                && ($this->session['timestamp'] + $this->expire) < time()) {
810
                $this->expired = true;
811
                $this->status = AUTH_EXPIRED;
812
                $this->logout();
813
                return false;
814
            }
815
 
816
            // Check if maximum idle time is reached
817
            if (   $this->idle > 0
818
                && isset($this->session['idle'])
819
                && ($this->session['idle'] + $this->idle) < time()) {
820
                $this->idled = true;
821
                $this->status = AUTH_IDLED;
822
                $this->logout();
823
                return false;
824
            }
825
 
826
            if (   isset($this->session['registered'])
827
                && isset($this->session['username'])
828
                && $this->session['registered'] == true
829
                && $this->session['username'] != '') {
830
                Auth::updateIdle();
831
 
832
                if ($this->advancedsecurity) {
833
 
834
                    // Only Generate the challenge once
835
                    if($this->authChecks == 1) {
836
                        $this->session['challengecookieold'] = $this->session['challengecookie'];
837
                        $this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
838
                        setcookie('authchallenge', $this->session['challengecookie']);
839
                    }
840
 
841
                    // Check for ip change
842
                    if (   isset($this->server['REMOTE_ADDR'])
843
                        && $this->session['sessionip'] != $this->server['REMOTE_ADDR']) {
844
                        // Check if the IP of the user has changed, if so we
845
                        // assume a man in the middle attack and log him out
846
                        $this->expired = true;
847
                        $this->status = AUTH_SECURITY_BREACH;
848
                        $this->logout();
849
                        return false;
850
                    }
851
 
852
                    // Check for useragent change
853
                    if (   isset($this->server['HTTP_USER_AGENT'])
854
                        && $this->session['sessionuseragent'] != $this->server['HTTP_USER_AGENT']) {
855
                        // Check if the User-Agent of the user has changed, if
856
                        // so we assume a man in the middle attack and log him out
857
                        $this->expired = true;
858
                        $this->status = AUTH_SECURITY_BREACH;
859
                        $this->logout();
860
                        return false;
861
                    }
862
 
863
                    // Check challenge cookie here, if challengecookieold is not set
864
                    // this is the first time and check is skipped
865
                    // TODO when user open two pages similtaneuly (open in new window,open
866
                    // in tab) auth breach is caused find out a way around that if possible
867
                    if (   isset($this->session['challengecookieold'])
868
                        && $this->session['challengecookieold'] != $this->cookie['authchallenge']) {
869
                        $this->expired = true;
870
                        $this->status = AUTH_SECURITY_BREACH;
871
                        $this->logout();
872
                        $this->login();
873
                        return false;
874
                    }
875
                }
876
 
877
                if (is_callable($this->checkAuthCallback)) {
878
                    $checkCallback = call_user_func_array($this->checkAuthCallback, array($this->username, &$this));
879
                    if ($checkCallback == false) {
880
                        $this->expired = true;
881
                        $this->status = AUTH_CALLBACK_ABORT;
882
                        $this->logout();
883
                        return false;
884
                    }
885
                }
886
 
887
                return true;
888
            }
889
        }
890
        return false;
891
    }
892
 
893
    // }}}
894
    // {{{ staticCheckAuth() [static]
895
 
896
    /**
897
     * Statically checks if there is a session with valid auth information.
898
     *
899
     * @access public
900
     * @see checkAuth
901
     * @return boolean  Whether or not the user is authenticated.
902
     * @static
903
     */
904
    function staticCheckAuth($options = null)
905
    {
906
        static $staticAuth;
907
        if(!isset($staticAuth)) {
908
            $staticAuth = new Auth('null', $options);
909
        }
910
        return $staticAuth->checkAuth();
911
    }
912
 
913
    // }}}
914
    // {{{ getAuth()
915
 
916
    /**
917
     * Has the user been authenticated?
918
     *
919
     * @access public
920
     * @return bool  True if the user is logged in, otherwise false.
921
     */
922
    function getAuth()
923
    {
924
        return $this->checkAuth();
925
    }
926
 
927
    // }}}
928
    // {{{ logout()
929
 
930
    /**
931
     * Logout function
932
     *
933
     * This function clears any auth tokens in the currently
934
     * active session and executes the logout callback function,
935
     * if any
936
     *
937
     * @access public
938
     * @return void
939
     */
940
    function logout()
941
    {
942
        if (is_callable($this->logoutCallback)) {
943
            call_user_func_array($this->logoutCallback, array($this->session['username'], &$this));
944
        }
945
 
946
        $this->username = '';
947
        $this->password = '';
948
 
949
        $this->session = null;
950
    }
951
 
952
    // }}}
953
    // {{{ updateIdle()
954
 
955
    /**
956
     * Update the idletime
957
     *
958
     * @access private
959
     * @return void
960
     */
961
    function updateIdle()
962
    {
963
        $this->session['idle'] = time();
964
    }
965
 
966
    // }}}
967
    // {{{ getUsername()
968
 
969
    /**
970
     * Get the username
971
     *
972
     * @return string
973
     * @access public
974
     */
975
    function getUsername()
976
    {
977
        if (isset($this->session['username'])) {
978
            return($this->session['username']);
979
        }
980
        return('');
981
    }
982
 
983
    // }}}
984
    // {{{ getStatus()
985
 
986
    /**
987
     * Get the current status
988
     *
989
     * @return string
990
     * @access public
991
     */
992
    function getStatus()
993
    {
994
        return $this->status;
995
    }
996
 
997
    // }}}
998
    // {{{ getPostUsernameField()
999
 
1000
    /**
1001
     * Gets the post varible used for the username
1002
     *
1003
     * @return string
1004
     * @access public
1005
     */
1006
    function getPostUsernameField()
1007
    {
1008
        return($this->_postUsername);
1009
    }
1010
 
1011
    // }}}
1012
    // {{{ getPostPasswordField()
1013
 
1014
    /**
1015
     * Gets the post varible used for the username
1016
     *
1017
     * @return string
1018
     * @access public
1019
     */
1020
    function getPostPasswordField()
1021
    {
1022
        return($this->_postPassword);
1023
    }
1024
 
1025
    // }}}
1026
    // {{{ sessionValidThru()
1027
 
1028
    /**
1029
     * Returns the time up to the session is valid
1030
     *
1031
     * @access public
1032
     * @return integer
1033
     */
1034
    function sessionValidThru()
1035
    {
1036
        if (!isset($this->session['idle'])) {
1037
            return 0;
1038
        }
1039
        if ($this->idle == 0) {
1040
            return 0;
1041
        }
1042
        return ($this->session['idle'] + $this->idle);
1043
    }
1044
 
1045
    // }}}
1046
    // {{{ listUsers()
1047
 
1048
    /**
1049
     * List all users that are currently available in the storage
1050
     * container
1051
     *
1052
     * @access public
1053
     * @return array
1054
     */
1055
    function listUsers()
1056
    {
1057
        $this->_loadStorage();
1058
        return $this->storage->listUsers();
1059
    }
1060
 
1061
    // }}}
1062
    // {{{ addUser()
1063
 
1064
    /**
1065
     * Add user to the storage container
1066
     *
1067
     * @access public
1068
     * @param  string Username
1069
     * @param  string Password
1070
     * @param  mixed  Additional parameters
1071
     * @return mixed  True on success, PEAR error object on error
1072
     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
1073
     */
1074
    function addUser($username, $password, $additional = '')
1075
    {
1076
        $this->_loadStorage();
1077
        return $this->storage->addUser($username, $password, $additional);
1078
    }
1079
 
1080
    // }}}
1081
    // {{{ removeUser()
1082
 
1083
    /**
1084
     * Remove user from the storage container
1085
     *
1086
     * @access public
1087
     * @param  string Username
1088
     * @return mixed  True on success, PEAR error object on error
1089
     *                and AUTH_METHOD_NOT_SUPPORTED otherwise.
1090
     */
1091
    function removeUser($username)
1092
    {
1093
        $this->_loadStorage();
1094
        return $this->storage->removeUser($username);
1095
    }
1096
 
1097
    // }}}
1098
    // {{{ changePassword()
1099
 
1100
    /**
1101
     * Change password for user in the storage container
1102
     *
1103
     * @access public
1104
     * @param string Username
1105
     * @param string The new password
1106
     * @return mixed True on success, PEAR error object on error
1107
     *               and AUTH_METHOD_NOT_SUPPORTED otherwise.
1108
     */
1109
    function changePassword($username, $password)
1110
    {
1111
        $this->_loadStorage();
1112
        return $this->storage->changePassword($username, $password);
1113
    }
1114
 
1115
    // }}}
1116
 
1117
}
1118
?>