user.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <?php
  2. /**
  3. * ownCloud
  4. *
  5. * @author Frank Karlitschek
  6. * @copyright 2012 Frank Karlitschek frank@owncloud.org
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  10. * License as published by the Free Software Foundation; either
  11. * version 3 of the License, or any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public
  19. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * This class provides wrapper methods for user management. Multiple backends are
  24. * supported. User management operations are delegated to the configured backend for
  25. * execution.
  26. *
  27. * Hooks provided:
  28. * pre_createUser(&run, uid, password)
  29. * post_createUser(uid, password)
  30. * pre_deleteUser(&run, uid)
  31. * post_deleteUser(uid)
  32. * pre_setPassword(&run, uid, password)
  33. * post_setPassword(uid, password)
  34. * pre_login(&run, uid)
  35. * post_login(uid)
  36. * logout()
  37. */
  38. class OC_User {
  39. // The backend used for user management
  40. private static $_usedBackends = array();
  41. private static $_setupedBackends = array();
  42. // Backends available (except database)
  43. private static $_backends = array();
  44. /**
  45. * @brief registers backend
  46. * @param $name name of the backend
  47. * @returns true/false
  48. *
  49. * Makes a list of backends that can be used by other modules
  50. */
  51. public static function registerBackend( $backend ) {
  52. self::$_backends[] = $backend;
  53. return true;
  54. }
  55. /**
  56. * @brief gets available backends
  57. * @returns array of backends
  58. *
  59. * Returns the names of all backends.
  60. */
  61. public static function getBackends() {
  62. return self::$_backends;
  63. }
  64. /**
  65. * @brief gets used backends
  66. * @returns array of backends
  67. *
  68. * Returns the names of all used backends.
  69. */
  70. public static function getUsedBackends() {
  71. return array_keys(self::$_usedBackends);
  72. }
  73. /**
  74. * @brief Adds the backend to the list of used backends
  75. * @param $backend default: database The backend to use for user managment
  76. * @returns true/false
  77. *
  78. * Set the User Authentication Module
  79. */
  80. public static function useBackend( $backend = 'database' ) {
  81. if($backend instanceof OC_User_Interface) {
  82. self::$_usedBackends[get_class($backend)]=$backend;
  83. }else{
  84. // You'll never know what happens
  85. if( null === $backend OR !is_string( $backend )) {
  86. $backend = 'database';
  87. }
  88. // Load backend
  89. switch( $backend ) {
  90. case 'database':
  91. case 'mysql':
  92. case 'sqlite':
  93. self::$_usedBackends[$backend] = new OC_User_Database();
  94. break;
  95. default:
  96. $className = 'OC_USER_' . strToUpper($backend);
  97. self::$_usedBackends[$backend] = new $className();
  98. break;
  99. }
  100. }
  101. true;
  102. }
  103. /**
  104. * remove all used backends
  105. */
  106. public static function clearBackends() {
  107. self::$_usedBackends=array();
  108. }
  109. /**
  110. * setup the configured backends in config.php
  111. */
  112. public static function setupBackends() {
  113. $backends=OC_Config::getValue('user_backends',array());
  114. foreach($backends as $i=>$config) {
  115. $class=$config['class'];
  116. $arguments=$config['arguments'];
  117. if(class_exists($class) and array_search($i,self::$_setupedBackends)===false) {
  118. // make a reflection object
  119. $reflectionObj = new ReflectionClass($class);
  120. // use Reflection to create a new instance, using the $args
  121. $backend = $reflectionObj->newInstanceArgs($arguments);
  122. self::useBackend($backend);
  123. $_setupedBackends[]=$i;
  124. }else{
  125. OC_Log::write('core','User backend '.$class.' not found.',OC_Log::ERROR);
  126. }
  127. }
  128. }
  129. /**
  130. * @brief Create a new user
  131. * @param $uid The username of the user to create
  132. * @param $password The password of the new user
  133. * @returns true/false
  134. *
  135. * Creates a new user. Basic checking of username is done in OC_User
  136. * itself, not in its subclasses.
  137. *
  138. * Allowed characters in the username are: "a-z", "A-Z", "0-9" and "_.@-"
  139. */
  140. public static function createUser( $uid, $password ) {
  141. // Check the name for bad characters
  142. // Allowed are: "a-z", "A-Z", "0-9" and "_.@-"
  143. if( preg_match( '/[^a-zA-Z0-9 _\.@\-]/', $uid )) {
  144. throw new Exception('Only the following characters are allowed in a username: "a-z", "A-Z", "0-9", and "_.@-"');
  145. }
  146. // No empty username
  147. if(trim($uid) == '') {
  148. throw new Exception('A valid username must be provided');
  149. }
  150. // No empty password
  151. if(trim($password) == '') {
  152. throw new Exception('A valid password must be provided');
  153. }
  154. // Check if user already exists
  155. if( self::userExists($uid) ) {
  156. throw new Exception('The username is already being used');
  157. }
  158. $run = true;
  159. OC_Hook::emit( "OC_User", "pre_createUser", array( "run" => &$run, "uid" => $uid, "password" => $password ));
  160. if( $run ) {
  161. //create the user in the first backend that supports creating users
  162. foreach(self::$_usedBackends as $backend) {
  163. if(!$backend->implementsActions(OC_USER_BACKEND_CREATE_USER))
  164. continue;
  165. $backend->createUser($uid,$password);
  166. OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => $uid, "password" => $password ));
  167. return true;
  168. }
  169. }
  170. return false;
  171. }
  172. /**
  173. * @brief delete a user
  174. * @param $uid The username of the user to delete
  175. * @returns true/false
  176. *
  177. * Deletes a user
  178. */
  179. public static function deleteUser( $uid ) {
  180. $run = true;
  181. OC_Hook::emit( "OC_User", "pre_deleteUser", array( "run" => &$run, "uid" => $uid ));
  182. if( $run ) {
  183. //delete the user from all backends
  184. foreach(self::$_usedBackends as $backend) {
  185. $backend->deleteUser($uid);
  186. }
  187. // We have to delete the user from all groups
  188. foreach( OC_Group::getUserGroups( $uid ) as $i ) {
  189. OC_Group::removeFromGroup( $uid, $i );
  190. }
  191. // Delete the user's keys in preferences
  192. OC_Preferences::deleteUser($uid);
  193. // Emit and exit
  194. OC_Hook::emit( "OC_User", "post_deleteUser", array( "uid" => $uid ));
  195. return true;
  196. }
  197. else{
  198. return false;
  199. }
  200. }
  201. /**
  202. * @brief Try to login a user
  203. * @param $uid The username of the user to log in
  204. * @param $password The password of the user
  205. * @returns true/false
  206. *
  207. * Log in a user and regenerate a new session - if the password is ok
  208. */
  209. public static function login( $uid, $password ) {
  210. $run = true;
  211. OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid ));
  212. if( $run ) {
  213. $uid = self::checkPassword( $uid, $password );
  214. $enabled = self::isEnabled($uid);
  215. if($uid && $enabled) {
  216. session_regenerate_id(true);
  217. self::setUserId($uid);
  218. OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>$password ));
  219. return true;
  220. }
  221. }
  222. return false;
  223. }
  224. /**
  225. * @brief Sets user id for session and triggers emit
  226. * @returns true
  227. *
  228. */
  229. public static function setUserId($uid) {
  230. $_SESSION['user_id'] = $uid;
  231. return true;
  232. }
  233. /**
  234. * @brief Logs the current user out and kills all the session data
  235. * @returns true
  236. *
  237. * Logout, destroys session
  238. */
  239. public static function logout() {
  240. OC_Hook::emit( "OC_User", "logout", array());
  241. session_unset();
  242. session_destroy();
  243. OC_User::unsetMagicInCookie();
  244. return true;
  245. }
  246. /**
  247. * @brief Check if the user is logged in
  248. * @returns true/false
  249. *
  250. * Checks if the user is logged in
  251. */
  252. public static function isLoggedIn() {
  253. if( isset($_SESSION['user_id']) AND $_SESSION['user_id']) {
  254. OC_App::loadApps(array('authentication'));
  255. self::setupBackends();
  256. if (self::userExists($_SESSION['user_id']) ) {
  257. return true;
  258. }
  259. }
  260. return false;
  261. }
  262. /**
  263. * @brief get the user id of the user currently logged in.
  264. * @return string uid or false
  265. */
  266. public static function getUser() {
  267. if( isset($_SESSION['user_id']) AND $_SESSION['user_id'] ) {
  268. return $_SESSION['user_id'];
  269. }
  270. else{
  271. return false;
  272. }
  273. }
  274. /**
  275. * @brief Autogenerate a password
  276. * @returns string
  277. *
  278. * generates a password
  279. */
  280. public static function generatePassword() {
  281. return uniqId();
  282. }
  283. /**
  284. * @brief Set password
  285. * @param $uid The username
  286. * @param $password The new password
  287. * @returns true/false
  288. *
  289. * Change the password of a user
  290. */
  291. public static function setPassword( $uid, $password ) {
  292. $run = true;
  293. OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password ));
  294. if( $run ) {
  295. $success = false;
  296. foreach(self::$_usedBackends as $backend) {
  297. if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) {
  298. if($backend->userExists($uid)) {
  299. $success |= $backend->setPassword($uid,$password);
  300. }
  301. }
  302. }
  303. OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password ));
  304. return $success;
  305. }
  306. else{
  307. return false;
  308. }
  309. }
  310. /**
  311. * @brief Check if the password is correct
  312. * @param $uid The username
  313. * @param $password The password
  314. * @returns string
  315. *
  316. * Check if the password is correct without logging in the user
  317. * returns the user id or false
  318. */
  319. public static function checkPassword( $uid, $password ) {
  320. foreach(self::$_usedBackends as $backend) {
  321. if($backend->implementsActions(OC_USER_BACKEND_CHECK_PASSWORD)) {
  322. $result=$backend->checkPassword( $uid, $password );
  323. if($result) {
  324. return $result;
  325. }
  326. }
  327. }
  328. }
  329. /**
  330. * @brief Check if the password is correct
  331. * @param $uid The username
  332. * @param $password The password
  333. * @returns string
  334. *
  335. * Check if the password is correct without logging in the user
  336. * returns the user id or false
  337. */
  338. public static function getHome($uid) {
  339. foreach(self::$_usedBackends as $backend) {
  340. if($backend->implementsActions(OC_USER_BACKEND_GET_HOME)) {
  341. $result=$backend->getHome($uid);
  342. if($result) {
  343. return $result;
  344. }
  345. }
  346. }
  347. return OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/' . $uid;
  348. }
  349. /**
  350. * @brief Get a list of all users
  351. * @returns array with all uids
  352. *
  353. * Get a list of all users.
  354. */
  355. public static function getUsers($search = '', $limit = null, $offset = null) {
  356. $users = array();
  357. foreach (self::$_usedBackends as $backend) {
  358. $backendUsers = $backend->getUsers($search, $limit, $offset);
  359. if (is_array($backendUsers)) {
  360. $users = array_merge($users, $backendUsers);
  361. }
  362. }
  363. asort($users);
  364. return $users;
  365. }
  366. /**
  367. * @brief check if a user exists
  368. * @param string $uid the username
  369. * @return boolean
  370. */
  371. public static function userExists($uid) {
  372. foreach(self::$_usedBackends as $backend) {
  373. $result=$backend->userExists($uid);
  374. if($result===true) {
  375. return true;
  376. }
  377. }
  378. return false;
  379. }
  380. /**
  381. * disables a user
  382. * @param string $userid the user to disable
  383. */
  384. public static function disableUser($userid) {
  385. $sql = "INSERT INTO `*PREFIX*preferences` (`userid`, `appid`, `configkey`, `configvalue`) VALUES(?, ?, ?, ?)";
  386. $stmt = OC_DB::prepare($sql);
  387. if ( ! OC_DB::isError($stmt) ) {
  388. $result = $stmt->execute(array($userid, 'core', 'enabled', 'false'));
  389. if ( OC_DB::isError($result) ) {
  390. OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR);
  391. }
  392. } else {
  393. OC_Log::write('OC_User', 'could not disable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR);
  394. }
  395. }
  396. /**
  397. * enable a user
  398. * @param string $userid
  399. */
  400. public static function enableUser($userid) {
  401. $sql = "DELETE FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?";
  402. $stmt = OC_DB::prepare($sql);
  403. if ( ! OC_DB::isError($stmt) ) {
  404. $result = $stmt->execute(array($userid, 'core', 'enabled', 'false'));
  405. if ( OC_DB::isError($result) ) {
  406. OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($result), OC_Log::ERROR);
  407. }
  408. } else {
  409. OC_Log::write('OC_User', 'could not enable user: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR);
  410. }
  411. }
  412. /**
  413. * checks if a user is enabled
  414. * @param string $userid
  415. * @return bool
  416. */
  417. public static function isEnabled($userid) {
  418. $sql = "SELECT `userid` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?";
  419. $stmt = OC_DB::prepare($sql);
  420. if ( ! OC_DB::isError($stmt) ) {
  421. $result = $stmt->execute(array($userid, 'core', 'enabled', 'false'));
  422. if ( ! OC_DB::isError($result) ) {
  423. return $result->numRows() ? false : true;
  424. } else {
  425. OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($result), OC_Log::ERROR);
  426. }
  427. } else {
  428. OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR);
  429. }
  430. return false;
  431. }
  432. /**
  433. * @brief Set cookie value to use in next page load
  434. * @param string $username username to be set
  435. */
  436. public static function setMagicInCookie($username, $token) {
  437. $secure_cookie = OC_Config::getValue("forcessl", false);
  438. setcookie("oc_username", $username, time()+60*60*24*15, '', '', $secure_cookie);
  439. setcookie("oc_token", $token, time()+60*60*24*15, '', '', $secure_cookie);
  440. setcookie("oc_remember_login", true, time()+60*60*24*15, '', '', $secure_cookie);
  441. }
  442. /**
  443. * @brief Remove cookie for "remember username"
  444. */
  445. public static function unsetMagicInCookie() {
  446. unset($_COOKIE["oc_username"]);
  447. unset($_COOKIE["oc_token"]);
  448. unset($_COOKIE["oc_remember_login"]);
  449. setcookie("oc_username", NULL, -1);
  450. setcookie("oc_token", NULL, -1);
  451. setcookie("oc_remember_login", NULL, -1);
  452. }
  453. }