PageRenderTime 26ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/security/Validation.inc.php

https://github.com/mbehiels/omp
PHP | 340 lines | 189 code | 53 blank | 98 comment | 40 complexity | 21bd4001b27f40805855ce3277c8f728 MD5 | raw file
  1. <?php
  2. /**
  3. * @file classes/security/Validation.inc.php
  4. *
  5. * Copyright (c) 2003-2011 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class Validation
  9. * @ingroup security
  10. *
  11. * @brief Class providing user validation/authentication operations.
  12. */
  13. import('lib.pkp.classes.security.UserGroup');
  14. class Validation {
  15. /**
  16. * Authenticate user credentials and mark the user as logged in in the current session.
  17. * @param $username string
  18. * @param $password string unencrypted password
  19. * @param $reason string reference to string to receive the reason an account was disabled; null otherwise
  20. * @param $remember boolean remember a user's session past the current browser session
  21. * @return User the User associated with the login credentials, or false if the credentials are invalid
  22. */
  23. function &login($username, $password, &$reason, $remember = false) {
  24. $implicitAuth = Config::getVar('security', 'implicit_auth');
  25. $reason = null;
  26. $valid = false;
  27. $userDao =& DAORegistry::getDAO('UserDAO');
  28. if ($implicitAuth) { // Implicit auth
  29. if (!Validation::isLoggedIn()) {
  30. PluginRegistry::loadCategory('implicitAuth');
  31. // Call the implicitAuth hook. It will set user.
  32. HookRegistry::call('ImplicitAuthPlugin::implicitAuth', array(&$user));
  33. $valid=true;
  34. }
  35. } else { // Regular Auth
  36. $user =& $userDao->getUserByUsername($username, true);
  37. if (!isset($user)) {
  38. // User does not exist
  39. return $valid;
  40. }
  41. if ($user->getAuthId()) {
  42. $authDao =& DAORegistry::getDAO('AuthSourceDAO');
  43. $auth =& $authDao->getPlugin($user->getAuthId());
  44. }
  45. if (isset($auth)) {
  46. // Validate against remote authentication source
  47. $valid = $auth->authenticate($username, $password);
  48. if ($valid) {
  49. $oldEmail = $user->getEmail();
  50. $auth->doGetUserInfo($user);
  51. if ($user->getEmail() != $oldEmail) {
  52. // FIXME OMP requires email addresses to be unique; if changed email already exists, ignore
  53. if ($userDao->userExistsByEmail($user->getEmail())) {
  54. $user->setEmail($oldEmail);
  55. }
  56. }
  57. }
  58. } else {
  59. // Validate against OMP user database
  60. $valid = ($user->getPassword() === Validation::encryptCredentials($username, $password));
  61. }
  62. }
  63. if (!$valid) {
  64. // Login credentials are invalid
  65. return $valid;
  66. } else {
  67. if ($user->getDisabled()) {
  68. // The user has been disabled.
  69. $reason = $user->getDisabledReason();
  70. if ($reason === null) $reason = '';
  71. $valid = false;
  72. return $valid;
  73. }
  74. // The user is valid, mark user as logged in in current session
  75. $sessionManager =& SessionManager::getManager();
  76. // Regenerate session ID first
  77. $sessionManager->regenerateSessionId();
  78. $session =& $sessionManager->getUserSession();
  79. $session->setSessionVar('userId', $user->getId());
  80. $session->setUserId($user->getId());
  81. $session->setSessionVar('username', $user->getUsername());
  82. $session->setRemember($remember);
  83. if ($remember && Config::getVar('general', 'session_lifetime') > 0) {
  84. // Update session expiration time
  85. $sessionManager->updateSessionLifetime(time() + Config::getVar('general', 'session_lifetime') * 86400);
  86. }
  87. $user->setDateLastLogin(Core::getCurrentDate());
  88. $userDao->updateObject($user);
  89. return $user;
  90. }
  91. }
  92. /**
  93. * Mark the user as logged out in the current session.
  94. * @return boolean
  95. */
  96. function logout() {
  97. $sessionManager =& SessionManager::getManager();
  98. $session =& $sessionManager->getUserSession();
  99. $session->unsetSessionVar('userId');
  100. $session->unsetSessionVar('signedInAs');
  101. $session->setUserId(null);
  102. if ($session->getRemember()) {
  103. $session->setRemember(0);
  104. $sessionManager->updateSessionLifetime(0);
  105. }
  106. $sessionDao =& DAORegistry::getDAO('SessionDAO');
  107. $sessionDao->updateObject($session);
  108. return true;
  109. }
  110. /**
  111. * Redirect to the login page, appending the current URL as the source.
  112. * @param $message string Optional name of locale key to add to login page
  113. */
  114. function redirectLogin($message = null) {
  115. $args = array();
  116. if (isset($_SERVER['REQUEST_URI'])) {
  117. $args['source'] = $_SERVER['REQUEST_URI'];
  118. }
  119. if ($message !== null) {
  120. $args['loginMessage'] = $message;
  121. }
  122. Request::redirect(null, 'login', null, null, $args);
  123. }
  124. /**
  125. * Check if a user's credentials are valid.
  126. * @param $username string username
  127. * @param $password string unencrypted password
  128. * @return boolean
  129. */
  130. function checkCredentials($username, $password) {
  131. $userDao =& DAORegistry::getDAO('UserDAO');
  132. $user =& $userDao->getUserByUsername($username, false);
  133. $valid = false;
  134. if (isset($user)) {
  135. if ($user->getAuthId()) {
  136. $authDao =& DAORegistry::getDAO('AuthSourceDAO');
  137. $auth =& $authDao->getPlugin($user->getAuthId());
  138. }
  139. if (isset($auth)) {
  140. $valid = $auth->authenticate($username, $password);
  141. } else {
  142. $valid = ($user->getPassword() === Validation::encryptCredentials($username, $password));
  143. }
  144. }
  145. return $valid;
  146. }
  147. /**
  148. * Check if a user is authorized to access the specified role in the specified press.
  149. * @param $roleId int
  150. * @param $pressId optional (e.g., for global site admin role), the ID of the press
  151. * @return boolean
  152. */
  153. function isAuthorized($roleId, $pressId = 0) {
  154. if (!Validation::isLoggedIn()) {
  155. return false;
  156. }
  157. if ($pressId === -1) {
  158. // Get press ID from request
  159. $press =& Request::getPress();
  160. $pressId = $press == null ? 0 : $press->getId();
  161. }
  162. $sessionManager =& SessionManager::getManager();
  163. $session =& $sessionManager->getUserSession();
  164. $user =& $session->getUser();
  165. $roleDAO =& DAORegistry::getDAO('RoleDAO');
  166. return $roleDAO->userHasRole($pressId, $user->getId(), $roleId);
  167. }
  168. /**
  169. * Encrypt user passwords for database storage.
  170. * The username is used as a unique salt to make dictionary
  171. * attacks against a compromised database more difficult.
  172. * @param $username string username
  173. * @param $password string unencrypted password
  174. * @param $encryption string optional encryption algorithm to use, defaulting to the value from the site configuration
  175. * @return string encrypted password
  176. */
  177. function encryptCredentials($username, $password, $encryption = false) {
  178. $valueToEncrypt = $username . $password;
  179. if ($encryption == false) {
  180. $encryption = Config::getVar('security', 'encryption');
  181. }
  182. switch ($encryption) {
  183. case 'sha1':
  184. if (function_exists('sha1')) {
  185. return sha1($valueToEncrypt);
  186. }
  187. case 'md5':
  188. default:
  189. return md5($valueToEncrypt);
  190. }
  191. }
  192. /**
  193. * Generate a random password.
  194. * Assumes the random number generator has already been seeded.
  195. * @param $length int the length of the password to generate (default 8)
  196. * @return string
  197. */
  198. function generatePassword($length = 8) {
  199. $letters = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
  200. $numbers = '23456789';
  201. $password = "";
  202. for ($i=0; $i<$length; $i++) {
  203. $password .= mt_rand(1, 4) == 4 ? $numbers[mt_rand(0,strlen($numbers)-1)] : $letters[mt_rand(0, strlen($letters)-1)];
  204. }
  205. return $password;
  206. }
  207. /**
  208. * Generate a hash value to use for confirmation to reset a password.
  209. * @param $userId int
  210. * @return string (boolean false if user is invalid)
  211. */
  212. function generatePasswordResetHash($userId) {
  213. $userDao =& DAORegistry::getDAO('UserDAO');
  214. if (($user = $userDao->getUser($userId)) == null) {
  215. // No such user
  216. return false;
  217. }
  218. return substr(md5($user->getId() . $user->getUsername() . $user->getPassword()), 0, 6);
  219. }
  220. /**
  221. * Suggest a username given the first and last names.
  222. * @return string
  223. */
  224. function suggestUsername($firstName, $lastName) {
  225. $initial = String::substr($firstName, 0, 1);
  226. $suggestion = String::regexp_replace('/[^a-zA-Z0-9_-]/', '', String::strtolower($initial . $lastName));
  227. $userDao =& DAORegistry::getDAO('UserDAO');
  228. for ($i = ''; $userDao->userExistsByUsername($suggestion . $i); $i++);
  229. return $suggestion . $i;
  230. }
  231. /**
  232. * Check if the user must change their password in order to log in.
  233. * @return boolean
  234. */
  235. function isLoggedIn() {
  236. $sessionManager =& SessionManager::getManager();
  237. $session =& $sessionManager->getUserSession();
  238. $userId = $session->getUserId();
  239. return isset($userId) && !empty($userId);
  240. }
  241. /**
  242. * Shortcut for checking authorization as site admin.
  243. * @return boolean
  244. */
  245. function isSiteAdmin() {
  246. return Validation::isAuthorized(ROLE_ID_SITE_ADMIN);
  247. }
  248. /**
  249. * Shortcut for checking authorization as press manager.
  250. * @param $pressId int
  251. * @return boolean
  252. */
  253. function isPressManager($pressId = -1) {
  254. return Validation::isAuthorized(ROLE_ID_PRESS_MANAGER, $pressId);
  255. }
  256. /**
  257. * Check whether a user is allowed to administer another user.
  258. * @param $administeredUserId int
  259. * @param $administratorUserId int
  260. * @return boolean
  261. */
  262. function canAdminister($administeredUserId, $administratorUserId) {
  263. $roleDao =& DAORegistry::getDAO('RoleDAO');
  264. if ($roleDao->userHasRole(0, $administratorUserId, ROLE_ID_SITE_ADMIN)) return true;
  265. // Check for administered user group assignments in other presses
  266. // that the administrator user doesn't have a manager role in.
  267. $pressDao =& DAORegistry::getDao('PressDAO');
  268. $presses =& $pressDao->getPresses();
  269. $userGroupDao =& DAORegistry::getDAO('UserGroupDAO');
  270. while(!$presses->eof()) {
  271. $press = $presses->next();
  272. $userGroups = $userGroupDao->getByUserId($administeredUserId, $press->getId());
  273. while (!$userGroups->eof()) {
  274. $userGroup =& $userGroups->next();
  275. if (!$roleDao->userHasRole($userGroup->getContextId(), $administratorUserId, ROLE_ID_PRESS_MANAGER)) {
  276. // Found an assignment: disqualified.
  277. return false;
  278. }
  279. unset($userGroup);
  280. }
  281. unset($press, $userGroups);
  282. }
  283. // There were no conflicting roles.
  284. return true;
  285. }
  286. }
  287. ?>