]> source.dussan.org Git - nextcloud-server.git/commitdiff
Validate if the user part of a "cloud id" can even be a valid user id
authorJoas Schilling <coding@schilljs.com>
Fri, 11 Nov 2022 08:37:26 +0000 (09:37 +0100)
committerJoas Schilling <coding@schilljs.com>
Fri, 9 Dec 2022 21:40:46 +0000 (22:40 +0100)
Signed-off-by: Joas Schilling <coding@schilljs.com>
lib/private/Federation/CloudIdManager.php
lib/private/User/Manager.php
lib/public/IUserManager.php

index e4e42cb129331a4c48e45c6f79a3d8b3bdd1cf2e..85aae8e5ec5293987040db0df809eb254372d592 100644 (file)
@@ -125,6 +125,9 @@ class CloudIdManager implements ICloudIdManager {
                if ($lastValidAtPos !== false) {
                        $user = substr($id, 0, $lastValidAtPos);
                        $remote = substr($id, $lastValidAtPos + 1);
+
+                       $this->userManager->validateUserId($user);
+
                        if (!empty($user) && !empty($remote)) {
                                return new CloudId($id, $user, $remote, $this->getDisplayNameFromContact($id));
                        }
index dc31eece414102e2680da4f4d8ef2544f9d59a73..82fc4d818ad96edd5133b4a2b93e09ebf18ab8a1 100644 (file)
@@ -44,6 +44,8 @@ use OCP\IGroup;
 use OCP\IUser;
 use OCP\IUserBackend;
 use OCP\IUserManager;
+use OCP\L10N\IFactory;
+use OCP\Server;
 use OCP\Support\Subscription\IAssertion;
 use OCP\User\Backend\IGetRealUIDBackend;
 use OCP\User\Backend\ISearchKnownUsersBackend;
@@ -427,31 +429,7 @@ class Manager extends PublicEmitter implements IUserManager {
        public function createUserFromBackend($uid, $password, UserInterface $backend) {
                $l = \OC::$server->getL10N('lib');
 
-               // Check the name for bad characters
-               // Allowed are: "a-z", "A-Z", "0-9" and "_.@-'"
-               if (preg_match('/[^a-zA-Z0-9 _.@\-\']/', $uid)) {
-                       throw new \InvalidArgumentException($l->t('Only the following characters are allowed in a username:'
-                               . ' "a-z", "A-Z", "0-9", and "_.@-\'"'));
-               }
-
-               // No empty username
-               if (trim($uid) === '') {
-                       throw new \InvalidArgumentException($l->t('A valid username must be provided'));
-               }
-
-               // No whitespace at the beginning or at the end
-               if (trim($uid) !== $uid) {
-                       throw new \InvalidArgumentException($l->t('Username contains whitespace at the beginning or at the end'));
-               }
-
-               // Username only consists of 1 or 2 dots (directory traversal)
-               if ($uid === '.' || $uid === '..') {
-                       throw new \InvalidArgumentException($l->t('Username must not consist of dots only'));
-               }
-
-               if (!$this->verifyUid($uid)) {
-                       throw new \InvalidArgumentException($l->t('Username is invalid because files already exist for this user'));
-               }
+               $this->validateUserId($uid, true);
 
                // No empty password
                if (trim($password) === '') {
@@ -726,7 +704,43 @@ class Manager extends PublicEmitter implements IUserManager {
                }));
        }
 
-       private function verifyUid(string $uid): bool {
+       /**
+        * @param string $uid
+        * @param bool $checkDataDirectory
+        * @throws \InvalidArgumentException Message is an already translated string with a reason why the id is not valid
+        * @since 26.0.0
+        */
+       public function validateUserId(string $uid, bool $checkDataDirectory = false): void {
+               $l = Server::get(IFactory::class)->get('lib');
+
+               // Check the name for bad characters
+               // Allowed are: "a-z", "A-Z", "0-9" and "_.@-'"
+               if (preg_match('/[^a-zA-Z0-9 _.@\-\']/', $uid)) {
+                       throw new \InvalidArgumentException($l->t('Only the following characters are allowed in a username:'
+                               . ' "a-z", "A-Z", "0-9", and "_.@-\'"'));
+               }
+
+               // No empty username
+               if (trim($uid) === '') {
+                       throw new \InvalidArgumentException($l->t('A valid username must be provided'));
+               }
+
+               // No whitespace at the beginning or at the end
+               if (trim($uid) !== $uid) {
+                       throw new \InvalidArgumentException($l->t('Username contains whitespace at the beginning or at the end'));
+               }
+
+               // Username only consists of 1 or 2 dots (directory traversal)
+               if ($uid === '.' || $uid === '..') {
+                       throw new \InvalidArgumentException($l->t('Username must not consist of dots only'));
+               }
+
+               if (!$this->verifyUid($uid, $checkDataDirectory)) {
+                       throw new \InvalidArgumentException($l->t('Username is invalid because files already exist for this user'));
+               }
+       }
+
+       private function verifyUid(string $uid, bool $checkDataDirectory = false): bool {
                $appdata = 'appdata_' . $this->config->getSystemValueString('instanceid');
 
                if (\in_array($uid, [
@@ -740,6 +754,10 @@ class Manager extends PublicEmitter implements IUserManager {
                        return false;
                }
 
+               if (!$checkDataDirectory) {
+                       return true;
+               }
+
                $dataDirectory = $this->config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data');
 
                return !file_exists(rtrim($dataDirectory, '/') . '/' . $uid);
index af0d5f08809a8d0522cf3513abe168f0bdeb099e..8caa027468bb39d4520c6ced3ef8a610db36b40f 100644 (file)
@@ -212,4 +212,12 @@ interface IUserManager {
         * @since 9.1.0
         */
        public function getByEmail($email);
+
+       /**
+        * @param string $uid The user ID to validate
+        * @param bool $checkDataDirectory Whether it should be checked if files for the ID exist inside the data directory
+        * @throws \InvalidArgumentException Message is an already translated string with a reason why the ID is not valid
+        * @since 26.0.0
+        */
+       public function validateUserId(string $uid, bool $checkDataDirectory = false): void;
 }