1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <unistd.h> 18 19 #include <gtest/gtest.h> 20 21 #include <android-base/file.h> 22 23 #if defined(__BIONIC__) 24 #include "../libc/bionic/grp_pwd_file.cpp" 25 26 template <typename T> 27 class FileUnmapper { 28 public: 29 explicit FileUnmapper(T& file) : file_(file) { 30 } 31 ~FileUnmapper() { 32 file_.Unmap(); 33 } 34 35 private: 36 T& file_; 37 }; 38 39 void FindAndCheckPasswdEntry(PasswdFile* file, const char* name, uid_t uid, gid_t gid, 40 const char* dir, const char* shell) { 41 passwd_state_t name_passwd_state; 42 ASSERT_TRUE(file->FindByName(name, &name_passwd_state)) << name; 43 44 passwd& name_passwd = name_passwd_state.passwd_; 45 EXPECT_STREQ(name, name_passwd.pw_name); 46 EXPECT_EQ(nullptr, name_passwd.pw_passwd); 47 EXPECT_EQ(uid, name_passwd.pw_uid); 48 EXPECT_EQ(gid, name_passwd.pw_gid); 49 EXPECT_EQ(nullptr, name_passwd.pw_gecos); 50 EXPECT_STREQ(dir, name_passwd.pw_dir); 51 EXPECT_STREQ(shell, name_passwd.pw_shell); 52 53 passwd_state_t id_passwd_state; 54 ASSERT_TRUE(file->FindById(uid, &id_passwd_state)) << uid; 55 56 passwd& id_passwd = id_passwd_state.passwd_; 57 EXPECT_STREQ(name, id_passwd.pw_name); 58 EXPECT_EQ(nullptr, id_passwd.pw_passwd); 59 EXPECT_EQ(uid, id_passwd.pw_uid); 60 EXPECT_EQ(gid, id_passwd.pw_gid); 61 EXPECT_EQ(nullptr, id_passwd.pw_gecos); 62 EXPECT_STREQ(dir, id_passwd.pw_dir); 63 EXPECT_STREQ(shell, id_passwd.pw_shell); 64 } 65 66 void FindAndCheckGroupEntry(GroupFile* file, const char* name, gid_t gid) { 67 group_state_t name_group_state; 68 ASSERT_TRUE(file->FindByName(name, &name_group_state)) << name; 69 70 group& name_group = name_group_state.group_; 71 EXPECT_STREQ(name, name_group.gr_name); 72 EXPECT_EQ(nullptr, name_group.gr_passwd); 73 EXPECT_EQ(gid, name_group.gr_gid); 74 EXPECT_EQ(name_group.gr_name, name_group.gr_mem[0]); 75 EXPECT_EQ(nullptr, name_group.gr_mem[1]); 76 77 group_state_t id_group_state; 78 ASSERT_TRUE(file->FindById(gid, &id_group_state)) << gid; 79 80 group& id_group = id_group_state.group_; 81 EXPECT_STREQ(name, id_group.gr_name); 82 EXPECT_EQ(nullptr, id_group.gr_passwd); 83 EXPECT_EQ(gid, id_group.gr_gid); 84 EXPECT_EQ(id_group.gr_name, id_group.gr_mem[0]); 85 EXPECT_EQ(nullptr, id_group.gr_mem[1]); 86 } 87 88 #endif // __BIONIC__ 89 90 TEST(grp_pwd_file, passwd_file_one_entry) { 91 #if defined(__BIONIC__) 92 TemporaryFile file; 93 ASSERT_NE(-1, file.fd); 94 static const char test_string[] = "name:password:1:2:user_info:dir:shell\n"; 95 write(file.fd, test_string, sizeof(test_string) - 1); 96 97 PasswdFile passwd_file(file.path, nullptr); 98 FileUnmapper unmapper(passwd_file); 99 100 FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell"); 101 102 EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr)); 103 EXPECT_FALSE(passwd_file.FindById(3, nullptr)); 104 105 #else // __BIONIC__ 106 GTEST_SKIP() << "bionic-only test"; 107 #endif // __BIONIC__ 108 } 109 110 TEST(grp_pwd_file, group_file_one_entry) { 111 #if defined(__BIONIC__) 112 TemporaryFile file; 113 ASSERT_NE(-1, file.fd); 114 static const char test_string[] = "name:password:1:one,two,three\n"; 115 write(file.fd, test_string, sizeof(test_string) - 1); 116 117 GroupFile group_file(file.path, nullptr); 118 FileUnmapper unmapper(group_file); 119 120 FindAndCheckGroupEntry(&group_file, "name", 1); 121 122 EXPECT_FALSE(group_file.FindByName("not_name", nullptr)); 123 EXPECT_FALSE(group_file.FindById(3, nullptr)); 124 125 #else // __BIONIC__ 126 GTEST_SKIP() << "bionic-only test"; 127 #endif // __BIONIC__ 128 } 129 130 TEST(grp_pwd_file, passwd_file_many_entries) { 131 #if defined(__BIONIC__) 132 TemporaryFile file; 133 ASSERT_NE(-1, file.fd); 134 static const char test_string[] = 135 "first:x:1:2::dir:shell\n" 136 "abc1::3:4::def:abc\n" 137 "abc2::5:4:abc::abc\n" 138 "abc3::7:4:abc:def:\n" 139 "abc4::9:4:::abc\n" 140 "abc5::11:4:abc:def:abc\n" 141 "middle-ish::13:4::/:/system/bin/sh\n" 142 "abc7::15:4:abc::\n" 143 "abc8::17:4:::\n" 144 "abc9::19:4:abc:def:abc\n" 145 "abc10::21:4:abc:def:abc\n" 146 "abc11::23:4:abc:def:abc\n" 147 "abc12::25:4:abc:def:abc\n" 148 "abc13::27:4:abc:def:abc\n" 149 "last::29:4::last_user_dir:last_user_shell\n"; 150 151 write(file.fd, test_string, sizeof(test_string) - 1); 152 153 PasswdFile passwd_file(file.path, nullptr); 154 FileUnmapper unmapper(passwd_file); 155 156 FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell"); 157 FindAndCheckPasswdEntry(&passwd_file, "middle-ish", 13, 4, "/", "/system/bin/sh"); 158 FindAndCheckPasswdEntry(&passwd_file, "last", 29, 4, "last_user_dir", "last_user_shell"); 159 160 EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr)); 161 EXPECT_FALSE(passwd_file.FindById(50, nullptr)); 162 163 #else // __BIONIC__ 164 GTEST_SKIP() << "bionic-only test"; 165 #endif // __BIONIC__ 166 } 167 168 TEST(grp_pwd_file, group_file_many_entries) { 169 #if defined(__BIONIC__) 170 TemporaryFile file; 171 ASSERT_NE(-1, file.fd); 172 static const char test_string[] = 173 "first:password:1:one,two,three\n" 174 "abc:def:2:group1,group2,group3\n" 175 "abc:def:3:\n" 176 "abc:def:4:\n" 177 "abc:def:5:\n" 178 "middle-ish:def_a_password_that_is_over_32_characters_long:6:\n" 179 "abc:def:7:\n" 180 "abc:def:8:\n" 181 "abc:def:20:\n" 182 "abc:def:25:\n" 183 "abc:def:27:\n" 184 "abc:def:52:\n" 185 "last::800:\n"; 186 187 write(file.fd, test_string, sizeof(test_string) - 1); 188 189 GroupFile group_file(file.path, nullptr); 190 FileUnmapper unmapper(group_file); 191 192 FindAndCheckGroupEntry(&group_file, "first", 1); 193 FindAndCheckGroupEntry(&group_file, "middle-ish", 6); 194 FindAndCheckGroupEntry(&group_file, "last", 800); 195 196 EXPECT_FALSE(group_file.FindByName("not_name", nullptr)); 197 EXPECT_FALSE(group_file.FindById(799, nullptr)); 198 199 #else // __BIONIC__ 200 GTEST_SKIP() << "bionic-only test"; 201 #endif // __BIONIC__ 202 } 203 204 TEST(grp_pwd_file, passwd_file_required_prefix) { 205 #if defined(__BIONIC__) 206 TemporaryFile file; 207 ASSERT_NE(-1, file.fd); 208 static const char test_string[] = 209 "name:password:1:2:user_info:dir:shell\n" 210 "vendor_name:password:3:4:user_info:dir:shell\n"; 211 write(file.fd, test_string, sizeof(test_string) - 1); 212 213 PasswdFile passwd_file(file.path, "vendor_"); 214 FileUnmapper unmapper(passwd_file); 215 216 EXPECT_FALSE(passwd_file.FindByName("name", nullptr)); 217 EXPECT_FALSE(passwd_file.FindById(1, nullptr)); 218 219 FindAndCheckPasswdEntry(&passwd_file, "vendor_name", 3, 4, "dir", "shell"); 220 221 #else // __BIONIC__ 222 GTEST_SKIP() << "bionic-only test"; 223 #endif // __BIONIC__ 224 } 225 226 TEST(grp_pwd_file, group_file_required_prefix) { 227 #if defined(__BIONIC__) 228 TemporaryFile file; 229 ASSERT_NE(-1, file.fd); 230 static const char test_string[] = 231 "name:password:1:one,two,three\n" 232 "vendor_name:password:2:one,two,three\n"; 233 write(file.fd, test_string, sizeof(test_string) - 1); 234 235 GroupFile group_file(file.path, "vendor_"); 236 FileUnmapper unmapper(group_file); 237 238 EXPECT_FALSE(group_file.FindByName("name", nullptr)); 239 EXPECT_FALSE(group_file.FindById(1, nullptr)); 240 241 FindAndCheckGroupEntry(&group_file, "vendor_name", 2); 242 243 #else // __BIONIC__ 244 GTEST_SKIP() << "bionic-only test"; 245 #endif // __BIONIC__ 246 } 247