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:
FileUnmapper(T & file)29 explicit FileUnmapper(T& file) : file_(file) {
30 }
~FileUnmapper()31 ~FileUnmapper() {
32 file_.Unmap();
33 }
34
35 private:
36 T& file_;
37 };
38
FindAndCheckPasswdEntry(PasswdFile * file,const char * name,uid_t uid,gid_t gid,const char * dir,const char * shell)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
FindAndCheckGroupEntry(GroupFile * file,const char * name,gid_t gid)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
TEST(grp_pwd_file,passwd_file_one_entry)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
TEST(grp_pwd_file,group_file_one_entry)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
TEST(grp_pwd_file,passwd_file_many_entries)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
TEST(grp_pwd_file,group_file_many_entries)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
TEST(grp_pwd_file,passwd_file_required_prefix)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
TEST(grp_pwd_file,group_file_required_prefix)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