From: Thomas Müller Date: Tue, 1 Oct 2013 22:21:11 +0000 (+0200) Subject: Merge branch 'master' into apache-auth-master X-Git-Tag: v6.0.0alpha2~72^2~11 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7e9e23f2100f10bffd6ee5eaa6c1778b4a335676;p=nextcloud-server.git Merge branch 'master' into apache-auth-master --- 7e9e23f2100f10bffd6ee5eaa6c1778b4a335676 diff --cc lib/private/connector/sabre/auth.php index 00000000000,bf3a49593cb..9b5663998ff mode 000000,100644..100644 --- a/lib/private/connector/sabre/auth.php +++ b/lib/private/connector/sabre/auth.php @@@ -1,0 -1,84 +1,88 @@@ + . + * + */ + + class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { + /** + * Validates a username and password + * + * This method should return true or false depending on if login + * succeeded. + * + * @return bool + */ + protected function validateUserPass($username, $password) { + if (OC_User::isLoggedIn()) { + OC_Util::setupFS(OC_User::getUser()); + return true; + } else { + OC_Util::setUpFS();//login hooks may need early access to the filesystem + if(OC_User::login($username, $password)) { + OC_Util::setUpFS(OC_User::getUser()); + return true; + } + else{ + return false; + } + } + } + + /** + * Returns information about the currently logged in username. + * + * If nobody is currently logged in, this method should return null. + * + * @return string|null + */ + public function getCurrentUser() { + $user = OC_User::getUser(); + if(!$user) { + return null; + } + return $user; + } + + /** + * Override function here. We want to cache authentication cookies + * in the syncing client to avoid HTTP-401 roundtrips. + * If the sync client supplies the cookies, then OC_User::isLoggedIn() + * will return true and we can see this WebDAV request as already authenticated, + * even if there are no HTTP Basic Auth headers. + * In other case, just fallback to the parent implementation. + * + * @return bool + */ + public function authenticate(Sabre_DAV_Server $server, $realm) { ++ if (OC_User::handleApacheAuth(true)) { ++ return true; ++ } ++ + if (OC_User::isLoggedIn()) { + $user = OC_User::getUser(); + OC_Util::setupFS($user); + $this->currentUser = $user; + return true; + } + + return parent::authenticate($server, $realm); + } + } diff --cc lib/private/user.php index 00000000000,15e807088b4..a4ad3278142 mode 000000,100644..100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@@ -1,0 -1,500 +1,576 @@@ + . + * + */ + + /** + * This class provides wrapper methods for user management. Multiple backends are + * supported. User management operations are delegated to the configured backend for + * execution. + * + * Hooks provided: + * pre_createUser(&run, uid, password) + * post_createUser(uid, password) + * pre_deleteUser(&run, uid) + * post_deleteUser(uid) + * pre_setPassword(&run, uid, password, recoveryPassword) + * post_setPassword(uid, password, recoveryPassword) + * pre_login(&run, uid, password) + * post_login(uid) + * logout() + */ + class OC_User { + public static function getUserSession() { + return OC::$server->getUserSession(); + } + + /** + * @return \OC\User\Manager + */ + public static function getManager() { + return OC::$server->getUserManager(); + } + + private static $_backends = array(); + + private static $_usedBackends = array(); + + private static $_setupedBackends = array(); + + /** + * @brief registers backend + * @param string $backend name of the backend + * @deprecated Add classes by calling useBackend with a class instance instead + * @return bool + * + * Makes a list of backends that can be used by other modules + */ + public static function registerBackend($backend) { + self::$_backends[] = $backend; + return true; + } + + /** + * @brief gets available backends + * @deprecated + * @returns array of backends + * + * Returns the names of all backends. + */ + public static function getBackends() { + return self::$_backends; + } + + /** + * @brief gets used backends + * @deprecated + * @returns array of backends + * + * Returns the names of all used backends. + */ + public static function getUsedBackends() { + return array_keys(self::$_usedBackends); + } + + /** + * @brief Adds the backend to the list of used backends + * @param string | OC_User_Backend $backend default: database The backend to use for user management + * @return bool + * + * Set the User Authentication Module + */ + public static function useBackend($backend = 'database') { + if ($backend instanceof OC_User_Interface) { + self::$_usedBackends[get_class($backend)] = $backend; + self::getManager()->registerBackend($backend); + } else { + // You'll never know what happens + if (null === $backend OR !is_string($backend)) { + $backend = 'database'; + } + + // Load backend + switch ($backend) { + case 'database': + case 'mysql': + case 'sqlite': + OC_Log::write('core', 'Adding user backend ' . $backend . '.', OC_Log::DEBUG); + self::$_usedBackends[$backend] = new OC_User_Database(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); + break; + default: + OC_Log::write('core', 'Adding default user backend ' . $backend . '.', OC_Log::DEBUG); + $className = 'OC_USER_' . strToUpper($backend); + self::$_usedBackends[$backend] = new $className(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); + break; + } + } + return true; + } + + /** + * remove all used backends + */ + public static function clearBackends() { + self::$_usedBackends = array(); + self::getManager()->clearBackends(); + } + + /** + * setup the configured backends in config.php + */ + public static function setupBackends() { + OC_App::loadApps(array('prelogin')); + $backends = OC_Config::getValue('user_backends', array()); + foreach ($backends as $i => $config) { + $class = $config['class']; + $arguments = $config['arguments']; + if (class_exists($class)) { + if (array_search($i, self::$_setupedBackends) === false) { + // make a reflection object + $reflectionObj = new ReflectionClass($class); + + // use Reflection to create a new instance, using the $args + $backend = $reflectionObj->newInstanceArgs($arguments); + self::useBackend($backend); + self::$_setupedBackends[] = $i; + } else { + OC_Log::write('core', 'User backend ' . $class . ' already initialized.', OC_Log::DEBUG); + } + } else { + OC_Log::write('core', 'User backend ' . $class . ' not found.', OC_Log::ERROR); + } + } + } + + /** + * @brief Create a new user + * @param string $uid The username of the user to create + * @param string $password The password of the new user + * @throws Exception + * @return bool true/false + * + * Creates a new user. Basic checking of username is done in OC_User + * itself, not in its subclasses. + * + * Allowed characters in the username are: "a-z", "A-Z", "0-9" and "_.@-" + */ + public static function createUser($uid, $password) { + return self::getManager()->createUser($uid, $password); + } + + /** + * @brief delete a user + * @param string $uid The username of the user to delete + * @return bool + * + * Deletes a user + */ + public static function deleteUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->delete(); + + // We have to delete the user from all groups + foreach (OC_Group::getUserGroups($uid) as $i) { + OC_Group::removeFromGroup($uid, $i); + } + // Delete the user's keys in preferences + OC_Preferences::deleteUser($uid); + + // Delete user files in /data/ + OC_Helper::rmdirr(OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid . '/'); + } + } + + /** + * @brief Try to login a user + * @param $uid The username of the user to log in + * @param $password The password of the user + * @return bool + * + * Log in a user and regenerate a new session - if the password is ok + */ + public static function login($uid, $password) { + return self::getUserSession()->login($uid, $password); + } + ++ /** ++ * @brief Try to login a user, assuming authentication ++ * has already happened (e.g. via SSO). ++ * ++ * Log in a user and regenerate a new session. ++ */ ++ public static function loginWithApache(\OCP\ApacheBackend $backend) { ++ ++ $uid = $backend->getCurrentUserId(); ++ $run = true; ++ OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid )); ++ ++ if($uid) { ++ session_regenerate_id(true); ++ self::setUserId($uid); ++ self::setDisplayName($uid); ++ OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>'' )); ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * @brief Verify with Apache whether user is authenticated. ++ * @note Currently supports only Shibboleth. ++ * ++ * @param $isWebdav Is this request done using webdav. ++ * @return true: authenticated - false: not authenticated ++ */ ++ public static function handleApacheAuth($isWebdav = false) { ++ foreach (self::$_usedBackends as $backend) { ++ if ($backend instanceof OCP\ApacheBackend) { ++ if ($backend->isSessionActive()) { ++ OC_App::loadApps(); ++ ++ //setup extra user backends ++ self::setupBackends(); ++ self::unsetMagicInCookie(); ++ ++ if (self::loginWithApache($backend)) { ++ if (! $isWebdav) { ++ $_REQUEST['redirect_url'] = \OC_Request::requestUri(); ++ OC_Util::redirectToDefaultPage(); ++ return true; ++ } ++ else { ++ return true; ++ } ++ } ++ } ++ } ++ } ++ ++ return false; ++ } ++ ++ + /** + * @brief Sets user id for session and triggers emit + */ + public static function setUserId($uid) { + OC::$session->set('user_id', $uid); + } + + /** + * @brief Sets user display name for session + */ + public static function setDisplayName($uid, $displayName = null) { + if (is_null($displayName)) { + $displayName = $uid; + } + $user = self::getManager()->get($uid); + if ($user) { + return $user->setDisplayName($displayName); + } else { + return false; + } + } + + /** + * @brief Logs the current user out and kills all the session data + * + * Logout, destroys session + */ + public static function logout() { + self::getUserSession()->logout(); + } + + /** + * @brief Check if the user is logged in + * @returns bool + * + * Checks if the user is logged in + */ + public static function isLoggedIn() { + if (\OC::$session->get('user_id')) { + OC_App::loadApps(array('authentication')); + self::setupBackends(); + return self::userExists(\OC::$session->get('user_id')); + } + return false; + } + ++ /** ++ * Supplies an attribute to the logout hyperlink. The default behaviuour ++ * is to return an href with '?logout=true' appended. However, it can ++ * supply any attribute(s) which are valid for . ++ * ++ * @return String with one or more HTML attributes. ++ */ ++ public static function getLogoutAttribute() { ++ foreach (self::$_usedBackends as $backend) { ++ if ($backend instanceof OCP\ApacheBackend) { ++ if ($backend->isSessionActive()) { ++ return $backend->getLogoutAttribute(); ++ } ++ } ++ } ++ ++ return print_unescaped("href=".link_to('', 'index.php'))."?logout=true"; ++ } ++ + /** + * @brief Check if the user is an admin user + * @param string $uid uid of the admin + * @return bool + */ + public static function isAdminUser($uid) { + if (OC_Group::inGroup($uid, 'admin')) { + return true; + } + return false; + } + + + /** + * @brief get the user id of the user currently logged in. + * @return string uid or false + */ + public static function getUser() { + $uid = OC::$session ? OC::$session->get('user_id') : null; + if (!is_null($uid)) { + return $uid; + } else { + return false; + } + } + + /** + * @brief get the display name of the user currently logged in. + * @param string $uid + * @return string uid or false + */ + public static function getDisplayName($uid = null) { + if ($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->getDisplayName(); + } else { + return $uid; + } + } else { + $user = self::getUserSession()->getUser(); + if ($user) { + return $user->getDisplayName(); + } else { + return false; + } + } + } + + /** + * @brief Autogenerate a password + * @return string + * + * generates a password + */ + public static function generatePassword() { + return OC_Util::generateRandomBytes(30); + } + + /** + * @brief Set password + * @param string $uid The username + * @param string $password The new password + * @param string $recoveryPassword for the encryption app to reset encryption keys + * @return bool + * + * Change the password of a user + */ + public static function setPassword($uid, $password, $recoveryPassword = null) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->setPassword($password, $recoveryPassword); + } else { + return false; + } + } + + /** + * @brief Check whether user can change his password + * @param string $uid The username + * @return bool + * + * Check whether a specified user can change his password + */ + public static function canUserChangePassword($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangePassword(); + } else { + return false; + } + } + + /** + * @brief Check whether user can change his display name + * @param string $uid The username + * @return bool + * + * Check whether a specified user can change his display name + */ + public static function canUserChangeDisplayName($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangeDisplayName(); + } else { + return false; + } + } + + /** + * @brief Check if the password is correct + * @param string $uid The username + * @param string $password The password + * @return mixed user id a string on success, false otherwise + * + * Check if the password is correct without logging in the user + * returns the user id or false + */ + public static function checkPassword($uid, $password) { + $manager = self::getManager(); + $username = $manager->checkPassword($uid, $password); + if ($username !== false) { + return $username->getUID(); + } + return false; + } + + /** + * @param string $uid The username + * @return string + * + * returns the path to the users home directory + */ + public static function getHome($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->getHome(); + } else { + return OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid; + } + } + + /** + * @brief Get a list of all users + * @returns array with all uids + * + * Get a list of all users. + */ + public static function getUsers($search = '', $limit = null, $offset = null) { + $users = self::getManager()->search($search, $limit, $offset); + $uids = array(); + foreach ($users as $user) { + $uids[] = $user->getUID(); + } + return $uids; + } + + /** + * @brief Get a list of all users display name + * @param string $search + * @param int $limit + * @param int $offset + * @return array associative array with all display names (value) and corresponding uids (key) + * + * Get a list of all display names and user ids. + */ + public static function getDisplayNames($search = '', $limit = null, $offset = null) { + $displayNames = array(); + $users = self::getManager()->searchDisplayName($search, $limit, $offset); + foreach ($users as $user) { + $displayNames[$user->getUID()] = $user->getDisplayName(); + } + return $displayNames; + } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public static function userExists($uid) { + return self::getManager()->userExists($uid); + } + + /** + * disables a user + * + * @param string $uid the user to disable + */ + public static function disableUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->setEnabled(false); + } + } + + /** + * enable a user + * + * @param string $uid + */ + public static function enableUser($uid) { + $user = self::getManager()->get($uid); + if ($user) { + $user->setEnabled(true); + } + } + + /** + * checks if a user is enabled + * + * @param string $uid + * @return bool + */ + public static function isEnabled($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->isEnabled(); + } else { + return false; + } + } + + /** + * @brief Set cookie value to use in next page load + * @param string $username username to be set + * @param string $token + */ + public static function setMagicInCookie($username, $token) { + self::getUserSession()->setMagicInCookie($username, $token); + } + + /** + * @brief Remove cookie for "remember username" + */ + public static function unsetMagicInCookie() { + self::getUserSession()->unsetMagicInCookie(); + } + }