diff options
-rw-r--r-- | apps/provisioning_api/lib/Controller/AppsController.php | 6 | ||||
-rw-r--r-- | apps/provisioning_api/lib/Controller/GroupsController.php | 4 | ||||
-rw-r--r-- | apps/provisioning_api/lib/Controller/UsersController.php | 21 | ||||
-rw-r--r-- | lib/private/Setup/AbstractDatabase.php | 1 | ||||
-rw-r--r-- | lib/private/Setup/PostgreSQL.php | 88 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 42 | ||||
-rw-r--r-- | lib/private/User/Session.php | 5 | ||||
-rw-r--r-- | tests/lib/User/SessionTest.php | 101 |
8 files changed, 214 insertions, 54 deletions
diff --git a/apps/provisioning_api/lib/Controller/AppsController.php b/apps/provisioning_api/lib/Controller/AppsController.php index 7d11d92b55a..e384d5af907 100644 --- a/apps/provisioning_api/lib/Controller/AppsController.php +++ b/apps/provisioning_api/lib/Controller/AppsController.php @@ -25,12 +25,10 @@ namespace OCA\Provisioning_API\Controller; -use OC\OCSClient; use \OC_App; use OCP\App\IAppManager; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; -use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\IRequest; @@ -86,7 +84,7 @@ class AppsController extends OCSController { /** * @param string $app * @return DataResponse - * @throws OCSNotFoundException + * @throws OCSException */ public function getAppInfo($app) { $info = \OCP\App::getAppInfo($app); @@ -98,6 +96,7 @@ class AppsController extends OCSController { } /** + * @PasswordConfirmationRequired * @param string $app * @return DataResponse */ @@ -107,6 +106,7 @@ class AppsController extends OCSController { } /** + * @PasswordConfirmationRequired * @param string $app * @return DataResponse */ diff --git a/apps/provisioning_api/lib/Controller/GroupsController.php b/apps/provisioning_api/lib/Controller/GroupsController.php index d36d0de8997..c772076c3d1 100644 --- a/apps/provisioning_api/lib/Controller/GroupsController.php +++ b/apps/provisioning_api/lib/Controller/GroupsController.php @@ -128,7 +128,7 @@ class GroupsController extends OCSController { /** * creates a new group * - * @NoAdminRequired + * @PasswordConfirmationRequired * * @param string $groupid * @return DataResponse @@ -149,6 +149,8 @@ class GroupsController extends OCSController { } /** + * @PasswordConfirmationRequired + * * @param string $groupId * @return DataResponse * @throws OCSException diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 8e5975468b1..cc1d63d2d34 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -93,6 +93,7 @@ class UsersController extends OCSController { */ public function getUsers($search = '', $limit = null, $offset = null) { $user = $this->userSession->getUser(); + $users = []; // Admin? Or SubAdmin? $uid = $user->getUID(); @@ -125,6 +126,7 @@ class UsersController extends OCSController { } /** + * @PasswordConfirmationRequired * @NoAdminRequired * * @param string $userid @@ -218,6 +220,7 @@ class UsersController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * @PasswordConfirmationRequired * * edit users * @@ -308,6 +311,7 @@ class UsersController extends OCSController { } /** + * @PasswordConfirmationRequired * @NoAdminRequired * * @param string $userId @@ -339,20 +343,26 @@ class UsersController extends OCSController { } /** + * @PasswordConfirmationRequired * @NoAdminRequired * * @param string $userId * @return DataResponse + * @throws OCSException + * @throws OCSForbiddenException */ public function disableUser($userId) { return $this->setEnabled($userId, false); } /** + * @PasswordConfirmationRequired * @NoAdminRequired * * @param string $userId * @return DataResponse + * @throws OCSException + * @throws OCSForbiddenException */ public function enableUser($userId) { return $this->setEnabled($userId, true); @@ -390,8 +400,7 @@ class UsersController extends OCSController { * * @param string $userId * @return DataResponse - * @throws OCSForbiddenException - * @throws OCSNotFoundException + * @throws OCSException */ public function getUsersGroups($userId) { $loggedInUser = $this->userSession->getUser(); @@ -430,6 +439,7 @@ class UsersController extends OCSController { } /** + * @PasswordConfirmationRequired * @param string $userId * @param string $groupid * @return DataResponse @@ -455,9 +465,10 @@ class UsersController extends OCSController { } /** + * @PasswordConfirmationRequired * @NoAdminRequired * - * @param string userId + * @param string $userId * @param string $groupid * @return DataResponse * @throws OCSException @@ -511,6 +522,8 @@ class UsersController extends OCSController { /** * Creates a subadmin * + * @PasswordConfirmationRequired + * * @param string $userId * @param string $groupid * @return DataResponse @@ -550,6 +563,8 @@ class UsersController extends OCSController { /** * Removes a subadmin from a group * + * @PasswordConfirmationRequired + * * @param string $userId * @param string $groupid * @return DataResponse diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 2b9d7afb367..dbf46888ffe 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -114,6 +114,7 @@ abstract class AbstractDatabase { 'user' => $this->dbUser, 'password' => $this->dbPassword, 'tablePrefix' => $this->tablePrefix, + 'dbname' => $this->dbName ); // adding port support through installer diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index 85755ea4218..14325a18efe 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -35,50 +35,60 @@ class PostgreSQL extends AbstractDatabase { public $dbprettyname = 'PostgreSQL'; public function setupDatabase($username) { - $connection = $this->connect([ - 'dbname' => 'postgres' - ]); - //check for roles creation rights in postgresql - $builder = $connection->getQueryBuilder(); - $builder->automaticTablePrefix(false); - $query = $builder - ->select('rolname') - ->from('pg_roles') - ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE'))) - ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser))); - + $systemConfig = $this->config->getSystemConfig(); try { - $result = $query->execute(); - $canCreateRoles = $result->rowCount() > 0; - } catch (DatabaseException $e) { - $canCreateRoles = false; - } + $connection = $this->connect([ + 'dbname' => 'postgres' + ]); + //check for roles creation rights in postgresql + $builder = $connection->getQueryBuilder(); + $builder->automaticTablePrefix(false); + $query = $builder + ->select('rolname') + ->from('pg_roles') + ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE'))) + ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser))); - if($canCreateRoles) { - //use the admin login data for the new database user + try { + $result = $query->execute(); + $canCreateRoles = $result->rowCount() > 0; + } catch (DatabaseException $e) { + $canCreateRoles = false; + } - //add prefix to the postgresql user name to prevent collisions - $this->dbUser='oc_'.$username; - //create a new password so we don't need to store the admin config in the config file - $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS); + if ($canCreateRoles) { + //use the admin login data for the new database user - $this->createDBUser($connection); - } + //add prefix to the postgresql user name to prevent collisions + $this->dbUser = 'oc_' . $username; + //create a new password so we don't need to store the admin config in the config file + $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_DIGITS); - $systemConfig = $this->config->getSystemConfig(); - $systemConfig->setValues([ - 'dbuser' => $this->dbUser, - 'dbpassword' => $this->dbPassword, - ]); + $this->createDBUser($connection); + } - //create the database - $this->createDatabase($connection); - $query = $connection->prepare("select count(*) FROM pg_class WHERE relname=? limit 1"); - $query->execute([$this->tablePrefix . "users"]); - $tablesSetup = $query->fetchColumn() > 0; + $systemConfig->setValues([ + 'dbuser' => $this->dbUser, + 'dbpassword' => $this->dbPassword, + ]); - // the connection to dbname=postgres is not needed anymore - $connection->close(); + //create the database + $this->createDatabase($connection); + $query = $connection->prepare("select count(*) FROM pg_class WHERE relname=? limit 1"); + $query->execute([$this->tablePrefix . "users"]); + $tablesSetup = $query->fetchColumn() > 0; + + // the connection to dbname=postgres is not needed anymore + $connection->close(); + } catch (\Exception $e) { + $this->logger->logException($e); + $this->logger->warning('Error trying to connect as "postgres", assuming database is setup and tables need to be created'); + $tablesSetup = false; + $systemConfig->setValues([ + 'dbuser' => $this->dbUser, + 'dbpassword' => $this->dbPassword, + ]); + } // connect to the ownCloud database (dbname=$this->dbname) and check if it needs to be filled $this->dbUser = $systemConfig->getValue('dbuser'); @@ -93,13 +103,13 @@ class PostgreSQL extends AbstractDatabase { } - if(!$tablesSetup) { + if (!$tablesSetup) { \OC_DB::createDbFromStructure($this->dbDefinitionFile); } } private function createDatabase(IDBConnection $connection) { - if(!$this->databaseExists($connection)) { + if (!$this->databaseExists($connection)) { //The database does not exists... let's create it $query = $connection->prepare("CREATE DATABASE " . addslashes($this->dbName) . " OWNER " . addslashes($this->dbUser)); try { diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 0c49d0b6490..c719777ab96 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -924,7 +924,11 @@ class Manager implements IManager { throw new \InvalidArgumentException('invalid path'); } - $provider = $this->factory->getProviderForType($shareType); + try { + $provider = $this->factory->getProviderForType($shareType); + } catch (ProviderException $e) { + return []; + } $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset); @@ -988,7 +992,11 @@ class Manager implements IManager { * @inheritdoc */ public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) { - $provider = $this->factory->getProviderForType($shareType); + try { + $provider = $this->factory->getProviderForType($shareType); + } catch (ProviderException $e) { + return []; + } return $provider->getSharedWith($userId, $shareType, $node, $limit, $offset); } @@ -1002,7 +1010,12 @@ class Manager implements IManager { } list($providerId, $id) = $this->splitFullId($id); - $provider = $this->factory->getProvider($providerId); + + try { + $provider = $this->factory->getProvider($providerId); + } catch (ProviderException $e) { + throw new ShareNotFound(); + } $share = $provider->getShareById($id, $recipient); @@ -1038,7 +1051,10 @@ class Manager implements IManager { * @throws ShareNotFound */ public function getShareByToken($token) { - $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK); + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK); + } catch (ProviderException $e) { + } try { $share = $provider->getShareByToken($token); @@ -1048,7 +1064,10 @@ class Manager implements IManager { // If it is not a link share try to fetch a federated share by token if ($share === null) { - $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE); + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE); + } catch (ProviderException $e) { + } try { $share = $provider->getShareByToken($token); } catch (ShareNotFound $e) { @@ -1058,7 +1077,10 @@ class Manager implements IManager { // If it is not a link share try to fetch a federated share by token if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) { - $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL); + try { + $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL); + } catch (ProviderException $e) { + } $share = $provider->getShareByToken($token); } @@ -1114,10 +1136,14 @@ class Manager implements IManager { * @inheritdoc */ public function userDeleted($uid) { - $types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE]; + $types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL]; foreach ($types as $type) { - $provider = $this->factory->getProviderForType($type); + try { + $provider = $this->factory->getProviderForType($type); + } catch (ProviderException $e) { + continue; + } $provider->userDeleted($uid, $type); } } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index c3561cf64e3..dcda825b9db 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -423,6 +423,7 @@ class Session implements IUserSession, Emitter { * * @todo do not allow basic auth if the user is 2FA enforced * @param IRequest $request + * @param OC\Security\Bruteforce\Throttler $throttler * @return boolean if the login was successful */ public function tryBasicAuthLogin(IRequest $request, @@ -440,6 +441,10 @@ class Session implements IUserSession, Emitter { $this->session->set( Auth::DAV_AUTHENTICATED, $this->getUser()->getUID() ); + + // Set the last-password-confirm session to make the sudo mode work + $this->session->set('last-password-confirm', $this->timeFacory->getTime()); + return true; } } catch (PasswordLoginForbiddenException $ex) { diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index 78b673d10bd..27cb92d6732 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -8,6 +8,7 @@ namespace Test\User; +use OC\AppFramework\Http\Request; use OC\Authentication\Token\DefaultTokenMapper; use OC\Authentication\Token\DefaultTokenProvider; use OC\Authentication\Token\IProvider; @@ -17,6 +18,7 @@ use OC\Session\Memory; use OC\User\Manager; use OC\User\Session; use OC\User\User; +use OCA\DAV\Connector\Sabre\Auth; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\ILogger; @@ -1219,4 +1221,103 @@ class SessionTest extends \Test\TestCase { $this->userSession->createRememberMeToken($user); } + + public function testTryBasicAuthLoginValid() { + $request = $this->createMock(Request::class); + $request->method('__get') + ->willReturn([ + 'PHP_AUTH_USER' => 'username', + 'PHP_AUTH_PW' => 'password', + ]); + $request->method('__isset') + ->with('server') + ->willReturn(true); + + $davAuthenticatedSet = false; + $lastPasswordConfirmSet = false; + + $this->session + ->method('set') + ->will($this->returnCallback(function($k, $v) use (&$davAuthenticatedSet, &$lastPasswordConfirmSet) { + switch ($k) { + case Auth::DAV_AUTHENTICATED: + $davAuthenticatedSet = $v; + return; + case 'last-password-confirm': + $lastPasswordConfirmSet = 1000; + return; + default: + throw new \Exception(); + } + })); + + $userSession = $this->getMockBuilder(Session::class) + ->setConstructorArgs([ + $this->manager, + $this->session, + $this->timeFactory, + $this->tokenProvider, + $this->config, + $this->random, + ]) + ->setMethods([ + 'logClientIn', + 'getUser', + ]) + ->getMock(); + + /** @var Session|\PHPUnit_Framework_MockObject_MockObject */ + $userSession->expects($this->once()) + ->method('logClientIn') + ->with( + $this->equalTo('username'), + $this->equalTo('password'), + $this->equalTo($request), + $this->equalTo($this->throttler) + )->willReturn(true); + + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('username'); + + $userSession->expects($this->once()) + ->method('getUser') + ->willReturn($user); + + $this->assertTrue($userSession->tryBasicAuthLogin($request, $this->throttler)); + + $this->assertSame('username', $davAuthenticatedSet); + $this->assertSame(1000, $lastPasswordConfirmSet); + } + + public function testTryBasicAuthLoginNoLogin() { + $request = $this->createMock(Request::class); + $request->method('__get') + ->willReturn([]); + $request->method('__isset') + ->with('server') + ->willReturn(true); + + $this->session->expects($this->never()) + ->method($this->anything()); + + $userSession = $this->getMockBuilder(Session::class) + ->setConstructorArgs([ + $this->manager, + $this->session, + $this->timeFactory, + $this->tokenProvider, + $this->config, + $this->random, + ]) + ->setMethods([ + 'logClientIn', + ]) + ->getMock(); + + /** @var Session|\PHPUnit_Framework_MockObject_MockObject */ + $userSession->expects($this->never()) + ->method('logClientIn'); + + $this->assertFalse($userSession->tryBasicAuthLogin($request, $this->throttler)); + } } |