OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windows.h> | 8 #include <windows.h> |
9 #include <shellapi.h> | 9 #include <shellapi.h> |
10 #include <shlobj.h> | 10 #include <shlobj.h> |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 REPARSE_DATA_BUFFER data = {0}; | 103 REPARSE_DATA_BUFFER data = {0}; |
104 data.ReparseTag = 0xa0000003; | 104 data.ReparseTag = 0xa0000003; |
105 if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0, | 105 if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0, |
106 &returned, NULL)) { | 106 &returned, NULL)) { |
107 return false; | 107 return false; |
108 } | 108 } |
109 return true; | 109 return true; |
110 } | 110 } |
111 #endif | 111 #endif |
112 | 112 |
113 #if defined(OS_POSIX) | |
114 // Provide a simple way to change the permissions bits on |path| in tests. | |
115 // ASSERT failures will return, but not stop the test. Caller should wrap | |
116 // calls to this function in ASSERT_NO_FATAL_FAILURE(). | |
117 void ChangePosixFilePermissions(const FilePath& path, | |
118 mode_t mode_bits_to_set, | |
119 mode_t mode_bits_to_clear) { | |
120 ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear) | |
121 << "Can't set and clear the same bits."; | |
122 | |
123 struct stat stat_buf; | |
124 ASSERT_EQ(0, stat(path.value().c_str(), &stat_buf)); | |
125 | |
126 mode_t new_mode_bits = stat_buf.st_mode; | |
127 new_mode_bits |= mode_bits_to_set; | |
128 new_mode_bits &= ~mode_bits_to_clear; | |
129 | |
130 ASSERT_EQ(0, chmod(path.value().c_str(), new_mode_bits)); | |
131 } | |
132 #endif // defined(OS_POSIX) | |
133 | |
113 const wchar_t bogus_content[] = L"I'm cannon fodder."; | 134 const wchar_t bogus_content[] = L"I'm cannon fodder."; |
114 | 135 |
115 const file_util::FileEnumerator::FileType FILES_AND_DIRECTORIES = | 136 const file_util::FileEnumerator::FileType FILES_AND_DIRECTORIES = |
116 static_cast<file_util::FileEnumerator::FileType>( | 137 static_cast<file_util::FileEnumerator::FileType>( |
117 file_util::FileEnumerator::FILES | | 138 file_util::FileEnumerator::FILES | |
118 file_util::FileEnumerator::DIRECTORIES); | 139 file_util::FileEnumerator::DIRECTORIES); |
119 | 140 |
120 // file_util winds up using autoreleased objects on the Mac, so this needs | 141 // file_util winds up using autoreleased objects on the Mac, so this needs |
121 // to be a PlatformTest | 142 // to be a PlatformTest |
122 class FileUtilTest : public PlatformTest { | 143 class FileUtilTest : public PlatformTest { |
(...skipping 1683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1806 | 1827 |
1807 EXPECT_TRUE(file_util::IsDirectoryEmpty(empty_dir)); | 1828 EXPECT_TRUE(file_util::IsDirectoryEmpty(empty_dir)); |
1808 | 1829 |
1809 FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt"))); | 1830 FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt"))); |
1810 std::string bar("baz"); | 1831 std::string bar("baz"); |
1811 ASSERT_TRUE(file_util::WriteFile(foo, bar.c_str(), bar.length())); | 1832 ASSERT_TRUE(file_util::WriteFile(foo, bar.c_str(), bar.length())); |
1812 | 1833 |
1813 EXPECT_FALSE(file_util::IsDirectoryEmpty(empty_dir)); | 1834 EXPECT_FALSE(file_util::IsDirectoryEmpty(empty_dir)); |
1814 } | 1835 } |
1815 | 1836 |
1837 #if defined(OS_POSIX) | |
1838 | |
1839 // Testing IsPathControlledByAdmin() is hard, because there is no | |
1840 // way a test can make a file owned by root, or change file paths | |
1841 // at the root of the file system. IsPathControlledByAdmin() | |
1842 // is implemented as a call to IsPathControlledByUser, which gives | |
1843 // us the ability to test with paths under the test's temp directory, | |
1844 // using a user id we control. | |
1845 // Pull tests of IsPathControlledByUserTest() into a separate test class | |
1846 // with a common SetUp() method. | |
1847 class IsPathControlledByUserTest : public FileUtilTest { | |
1848 protected: | |
1849 virtual void SetUp() { | |
1850 FileUtilTest::SetUp(); | |
1851 | |
1852 // Create a basic structure used by each test. | |
1853 // base_dir_ | |
1854 // |-> sub_dir_ | |
1855 // |-> text_file_ | |
1856 | |
1857 base_dir_ = temp_dir_.path().AppendASCII("base_dir"); | |
1858 ASSERT_TRUE(file_util::CreateDirectory(base_dir_)); | |
1859 | |
1860 sub_dir_ = base_dir_.AppendASCII("sub_dir"); | |
1861 ASSERT_TRUE(file_util::CreateDirectory(sub_dir_)); | |
1862 | |
1863 text_file_ = sub_dir_.AppendASCII("file.txt"); | |
1864 CreateTextFile(text_file_, L"This text file has some text in it."); | |
Evan Martin
2011/08/30 17:26:38
Are your tests vulnerable to the umask? I wonder
Sam Kerner (Chrome)
2011/09/16 18:12:59
I explicitly set the permissions bits here.
Each
| |
1865 | |
1866 // Our user and group id. | |
1867 uid_ = getuid(); | |
1868 gid_ = getgid(); | |
1869 } | |
1870 | |
1871 FilePath base_dir_; | |
1872 FilePath sub_dir_; | |
1873 FilePath text_file_; | |
1874 uid_t uid_; | |
1875 gid_t gid_; | |
1876 }; | |
1877 | |
1878 TEST_F(IsPathControlledByUserTest, BadPaths) { | |
1879 // File does not exist. | |
1880 FilePath does_not_exist = base_dir_.AppendASCII("does") | |
1881 .AppendASCII("not") | |
1882 .AppendASCII("exist"); | |
1883 | |
1884 EXPECT_FALSE( | |
1885 file_util::IsPathControlledByUser(base_dir_, does_not_exist, uid_, gid_)); | |
1886 | |
1887 // |base| not a subpath of |path|. | |
1888 EXPECT_FALSE( | |
1889 file_util::IsPathControlledByUser(sub_dir_, base_dir_, uid_, gid_)); | |
1890 | |
1891 // An empty base path will fail to be a prefix for any path. | |
1892 FilePath empty; | |
1893 EXPECT_FALSE( | |
1894 file_util::IsPathControlledByUser(empty, base_dir_, uid_, gid_)); | |
1895 | |
1896 // Finding that a bad call fails proves nothing unless a good call succeeds. | |
1897 EXPECT_TRUE( | |
1898 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
1899 } | |
1900 | |
1901 TEST_F(IsPathControlledByUserTest, Symlinks) { | |
1902 // Symlinks in the path should cause failure. | |
1903 | |
1904 // Symlink to the file at the end of the path. | |
1905 FilePath file_link = base_dir_.AppendASCII("file_link"); | |
1906 ASSERT_TRUE(file_util::CreateSymbolicLink(text_file_, file_link)) | |
1907 << "Failed to create symlink."; | |
1908 | |
1909 EXPECT_FALSE( | |
1910 file_util::IsPathControlledByUser(base_dir_, file_link, uid_, gid_)); | |
1911 EXPECT_FALSE( | |
1912 file_util::IsPathControlledByUser(file_link, file_link, uid_, gid_)); | |
1913 | |
1914 // Symlink from one directory to another within the path. | |
1915 FilePath link_to_sub_dir_ = base_dir_.AppendASCII("link_to_sub_dir_"); | |
1916 ASSERT_TRUE(file_util::CreateSymbolicLink(sub_dir_, link_to_sub_dir_)) | |
Evan Martin
2011/08/30 17:26:38
Heh, the trailing underscore bled into the directo
Sam Kerner (Chrome)
2011/09/16 18:12:59
Search and replace was a bit too effective. Fixed
| |
1917 << "Failed to create symlink."; | |
1918 | |
1919 FilePath file_path_with_link = link_to_sub_dir_.AppendASCII("file.txt"); | |
1920 ASSERT_TRUE(file_util::PathExists(file_path_with_link)); | |
1921 | |
1922 EXPECT_FALSE( | |
1923 file_util::IsPathControlledByUser( | |
1924 base_dir_, file_path_with_link, uid_, gid_)); | |
1925 | |
1926 EXPECT_FALSE( | |
1927 file_util::IsPathControlledByUser( | |
1928 link_to_sub_dir_, file_path_with_link, uid_, gid_)); | |
1929 | |
1930 // Symlinks in parents of base path are allowed. | |
1931 EXPECT_TRUE( | |
1932 file_util::IsPathControlledByUser( | |
1933 file_path_with_link, file_path_with_link, uid_, gid_)); | |
1934 } | |
1935 | |
1936 TEST_F(IsPathControlledByUserTest, OwnershipChecks) { | |
1937 // Get a uid that is not the uid of files we create. | |
1938 uid_t bad_uid = uid_ + 1; | |
1939 | |
1940 // Get a gid that is not ours. | |
1941 gid_t bad_gid = gid_ + 1; | |
1942 | |
1943 // Make all files and directories non-world-writable. | |
1944 ASSERT_NO_FATAL_FAILURE( | |
1945 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH)); | |
1946 ASSERT_NO_FATAL_FAILURE( | |
1947 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH)); | |
1948 ASSERT_NO_FATAL_FAILURE( | |
1949 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH)); | |
1950 | |
1951 // We control these paths. | |
1952 EXPECT_TRUE( | |
1953 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
1954 EXPECT_TRUE( | |
1955 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
1956 EXPECT_TRUE( | |
1957 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
1958 | |
1959 // Another user does not control these paths. | |
1960 EXPECT_FALSE( | |
1961 file_util::IsPathControlledByUser(base_dir_, sub_dir_, bad_uid, gid_)); | |
1962 EXPECT_FALSE( | |
1963 file_util::IsPathControlledByUser(base_dir_, text_file_, bad_uid, gid_)); | |
1964 EXPECT_FALSE( | |
1965 file_util::IsPathControlledByUser(sub_dir_, text_file_, bad_uid, gid_)); | |
1966 | |
1967 // Another group does not control the paths. | |
1968 EXPECT_FALSE( | |
1969 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gid)); | |
1970 EXPECT_FALSE( | |
1971 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, bad_gid)); | |
1972 EXPECT_FALSE( | |
1973 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, bad_gid)); | |
1974 } | |
1975 | |
1976 TEST_F(IsPathControlledByUserTest, WriteBitChecks) { | |
1977 | |
1978 // Make all files and directories non-world-writable. | |
1979 ASSERT_NO_FATAL_FAILURE( | |
1980 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH)); | |
1981 ASSERT_NO_FATAL_FAILURE( | |
1982 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH)); | |
1983 ASSERT_NO_FATAL_FAILURE( | |
1984 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH)); | |
1985 | |
1986 // Initialy, we control all parts of teh path. | |
1987 EXPECT_TRUE( | |
1988 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
1989 EXPECT_TRUE( | |
1990 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
1991 EXPECT_TRUE( | |
1992 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
1993 | |
1994 // Make base_dir_ world-writable. | |
1995 ASSERT_NO_FATAL_FAILURE( | |
1996 ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u)); | |
1997 EXPECT_FALSE( | |
1998 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
1999 EXPECT_FALSE( | |
2000 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2001 EXPECT_TRUE( | |
2002 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2003 | |
2004 // Make sub_dir_ world writable. | |
2005 ASSERT_NO_FATAL_FAILURE( | |
2006 ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u)); | |
2007 EXPECT_FALSE( | |
2008 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
2009 EXPECT_FALSE( | |
2010 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2011 EXPECT_FALSE( | |
2012 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2013 | |
2014 // Make text_file_ world writable. | |
2015 ASSERT_NO_FATAL_FAILURE( | |
2016 ChangePosixFilePermissions(text_file_, S_IWOTH, 0u)); | |
2017 EXPECT_FALSE( | |
2018 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
2019 EXPECT_FALSE( | |
2020 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2021 EXPECT_FALSE( | |
2022 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2023 | |
2024 // Make sub_dir_ non-world writable. | |
2025 ASSERT_NO_FATAL_FAILURE( | |
2026 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH)); | |
2027 EXPECT_FALSE( | |
2028 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
2029 EXPECT_FALSE( | |
2030 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2031 EXPECT_FALSE( | |
2032 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2033 | |
2034 // Make base_dir_ non-world-writable. | |
2035 ASSERT_NO_FATAL_FAILURE( | |
2036 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH)); | |
2037 EXPECT_TRUE( | |
2038 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
2039 EXPECT_FALSE( | |
2040 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2041 EXPECT_FALSE( | |
2042 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2043 | |
2044 // Back to the initial state: Nothing is writable, so every path | |
2045 // should pass. | |
2046 ASSERT_NO_FATAL_FAILURE( | |
2047 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH)); | |
2048 EXPECT_TRUE( | |
2049 file_util::IsPathControlledByUser(base_dir_, sub_dir_, uid_, gid_)); | |
2050 EXPECT_TRUE( | |
2051 file_util::IsPathControlledByUser(base_dir_, text_file_, uid_, gid_)); | |
2052 EXPECT_TRUE( | |
2053 file_util::IsPathControlledByUser(sub_dir_, text_file_, uid_, gid_)); | |
2054 } | |
2055 | |
2056 #endif // defined(OS_POSIX) | |
2057 | |
1816 } // namespace | 2058 } // namespace |
OLD | NEW |