1# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import contextlib
6import os
7
8from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros import cryptohome
11
12@contextlib.contextmanager
13def scoped_dir(path):
14    os.mkdir(path)
15    yield
16    os.rmdir(path)
17
18
19class platform_CryptohomeBadPerms(test.test):
20    """Tests Cryptohome's ability to detect directories with bad permissions or
21       ownership in the mount path of a home directory.
22    """
23    version = 1
24
25    def require_mount_fail(self, user):
26        """
27        Raise an error if the mount succeeded.
28        @param user: A random user created in run_once.
29        """
30        try:
31            cryptohome.mount_vault(user, 'test', create=True)
32        except:
33            pass
34        else:
35            raise error.TestFail('Mount unexpectedly succeeded for %s' % user)
36
37    def run_once(self):
38        # Leaf element of user path not owned by user.
39        user = utils.random_username()
40        path = cryptohome.user_path(user)
41        with scoped_dir(path):
42            os.chown(path, 0, 0)
43            self.require_mount_fail(user)
44
45        # Leaf element of system path not owned by root.
46        user = utils.random_username()
47        path = cryptohome.system_path(user)
48        with scoped_dir(path):
49            os.chown(path, 1, 1)
50            self.require_mount_fail(user)
51
52        # Leaf element of path too permissive.
53        user = utils.random_username()
54        path = cryptohome.user_path(user)
55        with scoped_dir(path):
56            os.chmod(path, 0777)
57            self.require_mount_fail(user)
58
59        # Non-leaf element of path not owned by root.
60        user = utils.random_username()
61        path = cryptohome.user_path(user)
62        parent_path = os.path.dirname(path)
63        os.chown(parent_path, 1, 1)
64        try:
65            self.require_mount_fail(user)
66        finally:
67            os.chown(parent_path, 0, 0)
68
69        # Non-leaf element of path too permissive.
70        user = utils.random_username()
71        path = cryptohome.user_path(user)
72        parent_path = os.path.dirname(path)
73        old_perm = os.stat(parent_path).st_mode & 0777
74        os.chmod(parent_path, 0777)
75        try:
76            self.require_mount_fail(user)
77        finally:
78            os.chmod(parent_path, old_perm)
79            os.chown(parent_path, 0, 0)
80