1: <?php
2:
3: /**
4: * This file contains the global authentication class.
5: *
6: * @package Core
7: * @subpackage Authentication
8: * @author Dominik Ziegler
9: * @copyright four for business AG <www.4fb.de>
10: * @license http://www.contenido.org/license/LIZENZ.txt
11: * @link http://www.4fb.de
12: * @link http://www.contenido.org
13: */
14:
15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
16:
17: /**
18: * This class contains functions for global authentication in CONTENIDO.
19: *
20: * @package Core
21: * @subpackage Authentication
22: */
23: class cAuth {
24:
25: /**
26: * Authentification user ID for nobody.
27: *
28: * @var string
29: */
30: const AUTH_UID_NOBODY = 'nobody';
31:
32: /**
33: * Authentification user ID for calling login form.
34: *
35: * @var string
36: */
37: const AUTH_UID_FORM = 'form';
38:
39: /**
40: * The global auth information array.
41: *
42: * This array has these keys:
43: * - uid = user_id for backend users and idfrontenduser for frontendusers
44: * - uname = username as part of the credentials to login
45: * - perm = user and group permissions as CSV
46: * - exp = expiration date as Unix timestamp
47: *
48: * @var array
49: */
50: public $auth = array();
51:
52: /**
53: * Lifetime for authenticated users in minutes.
54: * After that time the authentication expires.
55: *
56: * @var int
57: */
58: protected $_lifetime = 15;
59:
60: /**
61: * Automatic authentication as nobody.
62: *
63: * @var bool
64: */
65: protected $_defaultNobody = false;
66:
67: /**
68: * The "in flag".
69: * Nobody knows, for which reason it exists.
70: *
71: * @var bool
72: */
73: private $_in = false;
74:
75: /**
76: * Property used for session persistency, by cSession.
77: * This property needs to be public since cSession has to set it!
78: *
79: * @var array
80: */
81: public $persistent_slots = ['auth'];
82:
83: /**
84: * Magic getter function for outdated variable names.
85: *
86: * @param string $name
87: * name of the variable
88: * @return mixed
89: */
90: public function __get($name) {
91: if ($name == 'lifetime') {
92: return $this->_lifetime;
93: }
94:
95: if ($name == 'classname') {
96: return get_class($this);
97: }
98: }
99:
100: /**
101: * Starts the authentication process.
102: */
103: public function start() {
104:
105: $sess = cRegistry::getSession();
106: if (!$this->_in) {
107: $sess->register('auth');
108: $this->_in = true;
109: }
110:
111: if ($this->isAuthenticated()) {
112: $authInfo = $this->getAuthInfo();
113: $userId = $authInfo['uid'];
114: if ($userId == self::AUTH_UID_FORM) {
115: $userId = $this->validateCredentials();
116: if ($userId !== false) {
117: $this->_setAuthInfo($userId);
118: $this->logSuccessfulAuth();
119: } else {
120: $this->_fetchLoginForm();
121: }
122: } elseif ($userId != self::AUTH_UID_NOBODY) {
123: $this->_setExpiration();
124: }
125: } else {
126: $this->resetAuthInfo();
127:
128: $userId = $this->preAuthorize();
129: if ($userId !== false) {
130: $this->_setAuthInfo($userId);
131:
132: return;
133: }
134:
135: if ($this->_defaultNobody == true) {
136: $this->_setAuthInfo(self::AUTH_UID_NOBODY, 0x7fffffff);
137: } else {
138: $this->_fetchLoginForm();
139: }
140: }
141: }
142:
143: /**
144: * Restarts the authentication process.
145: */
146: public function restart() {
147: $this->resetAuthInfo();
148: $this->_defaultNobody = false;
149: $this->start();
150: }
151:
152: /**
153: * Resets the global authentication information.
154: *
155: * @param bool $nobody [optional]
156: * If flag set to true, the default authentication is
157: * switched to nobody. (optional, default: false)
158: */
159: public function resetAuthInfo($nobody = false) {
160: $this->auth['uid'] = $nobody ? self::AUTH_UID_NOBODY : '';
161: $this->auth['perm'] = '';
162: $this->_setExpiration($nobody ? 0x7fffffff : 0);
163: }
164:
165: /**
166: * Logs out the current user, resets the auth information and
167: * freezes the session.
168: *
169: * @param bool $nobody [optional]
170: * If flag set to true, nobody is recreated as user.
171: * @return bool true
172: */
173: public function logout($nobody = false) {
174: $sess = cRegistry::getSession();
175:
176: $sess->unregister('auth');
177: unset($this->auth['uname']);
178:
179: $this->resetAuthInfo($nobody == false? $this->_defaultNobody : $nobody);
180: $sess->freeze();
181:
182: return true;
183: }
184:
185: /**
186: * Getter for the auth information.
187: *
188: * @return array
189: */
190: public function getAuthInfo() {
191: return $this->auth;
192: }
193:
194: /**
195: * Checks, if user is authenticated (NOT logged in!).
196: *
197: * @return bool
198: */
199: public function isAuthenticated() {
200: $authInfo = $this->getAuthInfo();
201:
202: if (isset($authInfo['uid']) && $authInfo['uid'] && (($this->_lifetime <= 0) || (time() < $authInfo['exp']))) {
203: return $authInfo['uid'];
204: } else {
205: return false;
206: }
207: }
208:
209: /**
210: * Checks, if user is currently in login form mode.
211: *
212: * @return bool
213: */
214: public function isLoginForm() {
215: $authInfo = $this->getAuthInfo();
216:
217: return isset($authInfo['uid']) && $authInfo['uid'] == self::AUTH_UID_FORM;
218: }
219:
220: /**
221: * Returns the user id of the currently authenticated user
222: *
223: * @return string
224: */
225: public function getUserId() {
226: $authInfo = $this->getAuthInfo();
227:
228: return $authInfo['uid'];
229: }
230:
231: /**
232: * Returns the user name of the currently authenticated user
233: *
234: * @return string
235: */
236: public function getUsername() {
237: $authInfo = $this->getAuthInfo();
238:
239: return $authInfo['uname'];
240: }
241:
242: /**
243: * Returns the permission string of the currently authenticated user
244: *
245: * @return string
246: */
247: public function getPerms() {
248: $authInfo = $this->getAuthInfo();
249:
250: return $authInfo['perm'];
251: }
252:
253: /**
254: * Sets or refreshs the expiration of the authentication.
255: *
256: * @param int $expiration [optional]
257: * new expiration (optional, default: NULL = current time plus lifetime minutes)
258: */
259: protected function _setExpiration($expiration = NULL) {
260: if ($expiration === NULL) {
261: $expiration = time() + (60 * $this->_lifetime);
262: }
263:
264: $this->auth['exp'] = $expiration;
265: }
266:
267: /**
268: * Fetches the login form.
269: */
270: protected function _fetchLoginForm() {
271: $sess = cRegistry::getSession();
272:
273: $this->_setAuthInfo(self::AUTH_UID_FORM, 0x7fffffff);
274:
275: // TODO Method displayLoginForm() is declared in cAuthHandlerAbstract
276: // which is extending this class! Better declare it in this class and
277: // make it abstract!
278: $this->displayLoginForm();
279:
280: $sess->freeze();
281: exit();
282: }
283:
284: /**
285: * Sets the authentication info for a user.
286: *
287: * @param string $userId
288: * user ID to set
289: * @param int $expiration [optional]
290: * expiration (optional, default: NULL)
291: */
292: protected function _setAuthInfo($userId, $expiration = NULL) {
293: $this->auth['uid'] = $userId;
294: $this->_setExpiration($expiration);
295: }
296: }
297: