Open Monograph Press  3.3.0
Validation.inc.php
1 <?php
2 
16 class Validation {
17 
26  static function login($username, $password, &$reason, $remember = false) {
27  $reason = null;
28  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
29  $user = $userDao->getByUsername($username, true);
30  if (!isset($user)) {
31  // User does not exist
32  return false;
33  }
34 
35  if ($user->getAuthId()) {
36  $authDao = DAORegistry::getDAO('AuthSourceDAO'); /* @var $authDao AuthSourceDAO */
37  $auth = $authDao->getPlugin($user->getAuthId());
38  } else {
39  $auth = null;
40  }
41 
42  if ($auth) {
43  // Validate against remote authentication source
44  $valid = $auth->authenticate($username, $password);
45  if ($valid) {
46  $oldEmail = $user->getEmail();
47  $auth->doGetUserInfo($user);
48  if ($user->getEmail() != $oldEmail) {
49  // FIXME requires email addresses to be unique; if changed email already exists, ignore
50  if ($userDao->userExistsByEmail($user->getEmail())) {
51  $user->setEmail($oldEmail);
52  }
53  }
54  }
55  } else {
56  // Validate against user database
57  $rehash = null;
58  $valid = self::verifyPassword($username, $password, $user->getPassword(), $rehash);
59 
60  if ($valid && !empty($rehash)) {
61  // update to new hashing algorithm
62  $user->setPassword($rehash);
63  }
64  }
65 
66  if (!$valid) {
67  // Login credentials are invalid
68  return false;
69 
70  } else {
71  return self::registerUserSession($user, $reason, $remember);
72  }
73  }
74 
84  static function verifyPassword($username, $password, $hash, &$rehash) {
85  if (password_needs_rehash($hash, PASSWORD_BCRYPT)) {
86  // update to new hashing algorithm
87  $oldHash = self::encryptCredentials($username, $password, false, true);
88 
89  if ($oldHash === $hash) {
90  // update hash
91  $rehash = self::encryptCredentials($username, $password);
92 
93  return true;
94  }
95  }
96 
97  return password_verify($password, $hash);
98  }
99 
107  static function registerUserSession($user, &$reason, $remember = false) {
108  if (!is_a($user, 'User')) return false;
109 
110  if ($user->getDisabled()) {
111  // The user has been disabled.
112  $reason = $user->getDisabledReason();
113  if ($reason === null) $reason = '';
114  return false;
115  }
116 
117  // The user is valid, mark user as logged in in current session
118  $sessionManager = SessionManager::getManager();
119 
120  // Regenerate session ID first
121  $sessionManager->regenerateSessionId();
122 
123  $session = $sessionManager->getUserSession();
124  $session->setSessionVar('userId', $user->getId());
125  $session->setUserId($user->getId());
126  $session->setSessionVar('username', $user->getUsername());
127  $session->getCSRFToken(); // Force generation (see issue #2417)
128  $session->setRemember($remember);
129 
130  if ($remember && Config::getVar('general', 'session_lifetime') > 0) {
131  // Update session expiration time
132  $sessionManager->updateSessionLifetime(time() + Config::getVar('general', 'session_lifetime') * 86400);
133  }
134 
135  $user->setDateLastLogin(Core::getCurrentDate());
136  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
137  $userDao->updateObject($user);
138 
139  return $user;
140  }
141 
146  static function logout() {
147  $sessionManager = SessionManager::getManager();
148  $session = $sessionManager->getUserSession();
149  $session->unsetSessionVar('userId');
150  $session->unsetSessionVar('signedInAs');
151  $session->setUserId(null);
152 
153  if ($session->getRemember()) {
154  $session->setRemember(0);
155  $sessionManager->updateSessionLifetime(0);
156  }
157 
158  $sessionDao = DAORegistry::getDAO('SessionDAO'); /* @var $sessionDao SessionDAO */
159  $sessionDao->updateObject($session);
160 
161  return true;
162  }
163 
168  static function redirectLogin($message = null) {
169  $args = array();
170 
171  if (isset($_SERVER['REQUEST_URI'])) {
172  $args['source'] = $_SERVER['REQUEST_URI'];
173  }
174  if ($message !== null) {
175  $args['loginMessage'] = $message;
176  }
177 
178  $request = Application::get()->getRequest();
179  $request->redirect(null, 'login', null, null, $args);
180  }
181 
188  static function checkCredentials($username, $password) {
189  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
190  $user = $userDao->getByUsername($username, false);
191 
192  $valid = false;
193  if (isset($user)) {
194  if ($user->getAuthId()) {
195  $authDao = DAORegistry::getDAO('AuthSourceDAO'); /* @var $authDao AuthSourceDAO */
196  $auth =& $authDao->getPlugin($user->getAuthId());
197  }
198 
199  if (isset($auth)) {
200  $valid = $auth->authenticate($username, $password);
201  } else {
202  // Validate against user database
203  $rehash = null;
204  $valid = self::verifyPassword($username, $password, $user->getPassword(), $rehash);
205 
206  if ($valid && !empty($rehash)) {
207  // update to new hashing algorithm
208  $user->setPassword($rehash);
209 
210  // save new password hash to database
211  $userDao->updateObject($user);
212  }
213  }
214  }
215 
216  return $valid;
217  }
218 
225  static function isAuthorized($roleId, $contextId = 0) {
226  if (!self::isLoggedIn()) {
227  return false;
228  }
229 
230  if ($contextId === -1) {
231  // Get context ID from request
232  $request = Application::get()->getRequest();
233  $context = $request->getContext();
234  $contextId = $context == null ? 0 : $context->getId();
235  }
236 
237  $sessionManager = SessionManager::getManager();
238  $session = $sessionManager->getUserSession();
239  $user = $session->getUser();
240 
241  $roleDao = DAORegistry::getDAO('RoleDAO'); /* @var $roleDao RoleDAO */
242  return $roleDao->userHasRole($contextId, $user->getId(), $roleId);
243  }
244 
255  static function encryptCredentials($username, $password, $encryption = false, $legacy = false) {
256  if ($legacy) {
257  $valueToEncrypt = $username . $password;
258 
259  if ($encryption == false) {
260  $encryption = Config::getVar('security', 'encryption');
261  }
262 
263  switch ($encryption) {
264  case 'sha1':
265  if (function_exists('sha1')) {
266  return sha1($valueToEncrypt);
267  }
268  case 'md5':
269  default:
270  return md5($valueToEncrypt);
271  }
272  } else {
273  return password_hash($password, PASSWORD_BCRYPT);
274  }
275  }
276 
283  static function generatePassword($length = null) {
284  if (!$length) {
285  $siteDao = DAORegistry::getDAO('SiteDAO');
286  $site = $siteDao->getSite();
287  $length = $site->getMinPasswordLength();
288  }
289  $letters = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
290  $numbers = '23456789';
291 
292  $password = "";
293  for ($i=0; $i<$length; $i++) {
294  $password .= mt_rand(1, 4) == 4 ? $numbers[mt_rand(0,strlen($numbers)-1)] : $letters[mt_rand(0, strlen($letters)-1)];
295  }
296  return $password;
297  }
298 
305  static function generatePasswordResetHash($userId, $expiry = null) {
306  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
307  if (($user = $userDao->getById($userId)) == null) {
308  // No such user
309  return false;
310  }
311  // create hash payload
312  $salt = Config::getVar('security', 'salt');
313 
314  if (empty($expiry)) {
315  $expires = (int) Config::getVar('security', 'reset_seconds', 7200);
316  $expiry = time() + $expires;
317  }
318 
319  // use last login time to ensure the hash changes when they log in
320  $data = $user->getUsername() . $user->getPassword() . $user->getDateLastLogin() . $expiry;
321 
322  // generate hash and append expiry timestamp
323  $algos = hash_algos();
324 
325  foreach (array('sha256', 'sha1', 'md5') as $algo) {
326  if (in_array($algo, $algos)) {
327  return hash_hmac($algo, $data, $salt) . ':' . $expiry;
328  }
329  }
330 
331  // fallback to MD5
332  return md5($data . $salt) . ':' . $expiry;
333  }
334 
341  static function verifyPasswordResetHash($userId, $hash) {
342  // append ":" to ensure the explode results in at least 2 elements
343  list(, $expiry) = explode(':', $hash . ':');
344 
345  if (empty($expiry) || ((int) $expiry < time())) {
346  // expired
347  return false;
348  }
349 
350  return ($hash === self::generatePasswordResetHash($userId, $expiry));
351  }
352 
359  static function suggestUsername($givenName, $familyName = null) {
360  $name = $givenName;
361  if (!empty($familyName)) {
362  $initial = PKPString::substr($givenName, 0, 1);
363  $name = $initial . $familyName;
364  }
365 
366  $suggestion = PKPString::regexp_replace('/[^a-zA-Z0-9_-]/', '', Stringy\Stringy::create($name)->toAscii()->toLowerCase());
367  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
368  for ($i = ''; $userDao->userExistsByUsername($suggestion . $i); $i++);
369  return $suggestion . $i;
370  }
371 
376  static function isLoggedIn() {
377  $sessionManager = SessionManager::getManager();
378  $session = $sessionManager->getUserSession();
379 
380  $userId = $session->getUserId();
381  return isset($userId) && !empty($userId);
382  }
383 
388  static function isLoggedInAs() {
389  $sessionManager = SessionManager::getManager();
390  $session = $sessionManager->getUserSession();
391  $signedInAs = $session->getSessionVar('signedInAs');
392 
393  return isset($signedInAs) && !empty($signedInAs);
394  }
395 
400  static function isSiteAdmin() {
401  return self::isAuthorized(ROLE_ID_SITE_ADMIN);
402  }
403 
410  static function canAdminister($administeredUserId, $administratorUserId) {
411  $roleDao = DAORegistry::getDAO('RoleDAO'); /* @var $roleDao RoleDAO */
412 
413  // You can administer yourself
414  if ($administeredUserId == $administratorUserId) return true;
415 
416  // You cannot adminster administrators
417  if ($roleDao->userHasRole(CONTEXT_SITE, $administeredUserId, ROLE_ID_SITE_ADMIN)) return false;
418 
419  // Otherwise, administrators can administer everyone
420  if ($roleDao->userHasRole(CONTEXT_SITE, $administratorUserId, ROLE_ID_SITE_ADMIN)) return true;
421 
422  // Check for administered user group assignments in other contexts
423  // that the administrator user doesn't have a manager role in.
424  $userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
425  $userGroups = $userGroupDao->getByUserId($administeredUserId);
426  while ($userGroup = $userGroups->next()) {
427  if ($userGroup->getContextId()!=CONTEXT_SITE && !$roleDao->userHasRole($userGroup->getContextId(), $administratorUserId, ROLE_ID_MANAGER)) {
428  // Found an assignment: disqualified.
429  return false;
430  }
431  }
432 
433  // Make sure the administering user has a manager role somewhere
434  $foundManagerRole = false;
435  $roles = $roleDao->getByUserId($administratorUserId);
436  foreach ($roles as $role) {
437  if ($role->getRoleId() == ROLE_ID_MANAGER) $foundManagerRole = true;
438  }
439  if (!$foundManagerRole) return false;
440 
441  // There were no conflicting roles. Permit administration.
442  return true;
443  }
444 }
SessionManager\getManager
static getManager()
Definition: SessionManager.inc.php:124
Validation\encryptCredentials
static encryptCredentials($username, $password, $encryption=false, $legacy=false)
Definition: Validation.inc.php:255
Validation\isSiteAdmin
static isSiteAdmin()
Definition: Validation.inc.php:400
Validation\isLoggedInAs
static isLoggedInAs()
Definition: Validation.inc.php:388
PKPString\regexp_replace
static regexp_replace($pattern, $replacement, $subject, $limit=-1)
Definition: PKPString.inc.php:279
Validation\redirectLogin
static redirectLogin($message=null)
Definition: Validation.inc.php:168
Validation\isLoggedIn
static isLoggedIn()
Definition: Validation.inc.php:376
Validation\registerUserSession
static registerUserSession($user, &$reason, $remember=false)
Definition: Validation.inc.php:107
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
Validation\login
static login($username, $password, &$reason, $remember=false)
Definition: Validation.inc.php:26
PKPString\substr
static substr($string, $start, $length=null)
Definition: PKPString.inc.php:160
Validation\logout
static logout()
Definition: Validation.inc.php:146
Validation\generatePassword
static generatePassword($length=null)
Definition: Validation.inc.php:283
Validation\checkCredentials
static checkCredentials($username, $password)
Definition: Validation.inc.php:188
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
Validation\verifyPassword
static verifyPassword($username, $password, $hash, &$rehash)
Definition: Validation.inc.php:84
Validation\isAuthorized
static isAuthorized($roleId, $contextId=0)
Definition: Validation.inc.php:225
Validation\verifyPasswordResetHash
static verifyPasswordResetHash($userId, $hash)
Definition: Validation.inc.php:341
Core\getCurrentDate
static getCurrentDate($ts=null)
Definition: Core.inc.php:63
Validation\generatePasswordResetHash
static generatePasswordResetHash($userId, $expiry=null)
Definition: Validation.inc.php:305
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
Validation\canAdminister
static canAdminister($administeredUserId, $administratorUserId)
Definition: Validation.inc.php:410
Validation
Class providing user validation/authentication operations.
Definition: Validation.inc.php:16
Validation\suggestUsername
static suggestUsername($givenName, $familyName=null)
Definition: Validation.inc.php:359