]> ruderich.org/simon Gitweb - nsscash/nsscash.git/blob - nss/tests/pw.c
nss: tests: sort included headers
[nsscash/nsscash.git] / nss / tests / pw.c
1 /*
2  * Tests for the NSS cash module
3  *
4  * Copyright (C) 2019  Simon Ruderich
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "../cash_nss.h"
28
29
30 static void test_getpwent(void) {
31     struct passwd p;
32     enum nss_status s;
33     char tmp[1024];
34     char tmp_small[10];
35     int errnop = 0;
36
37     // Test one setpwent/getpwent/endpwent round
38
39     s = _nss_cash_setpwent(0);
40     assert(s == NSS_STATUS_SUCCESS);
41
42     // Multiple calls with too small buffer don't advance any internal indices
43     s = _nss_cash_getpwent_r(&p, tmp_small, sizeof(tmp_small), &errnop);
44     assert(s == NSS_STATUS_TRYAGAIN);
45     assert(errnop == ERANGE);
46     s = _nss_cash_getpwent_r(&p, tmp_small, sizeof(tmp_small), &errnop);
47     assert(s == NSS_STATUS_TRYAGAIN);
48     assert(errnop == ERANGE);
49     s = _nss_cash_getpwent_r(&p, tmp_small, sizeof(tmp_small), &errnop);
50     assert(s == NSS_STATUS_TRYAGAIN);
51     assert(errnop == ERANGE);
52
53     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
54     assert(s == NSS_STATUS_SUCCESS);
55     assert(!strcmp(p.pw_name, "root"));
56     assert(!strcmp(p.pw_passwd, "x"));
57     assert(p.pw_uid == 0);
58     assert(p.pw_gid == 0);
59     assert(!strcmp(p.pw_gecos, "root"));
60     assert(!strcmp(p.pw_dir, "/root"));
61     assert(!strcmp(p.pw_shell, "/bin/bash"));
62
63     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
64     assert(s == NSS_STATUS_SUCCESS);
65     assert(!strcmp(p.pw_name, "daemon"));
66     for (int i = 0; i < 10; i++) {
67         s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
68         assert(s == NSS_STATUS_SUCCESS);
69     }
70     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
71     assert(s == NSS_STATUS_SUCCESS);
72     assert(!strcmp(p.pw_name, "www-data"));
73     for (int i = 0; i < 12; i++) {
74         s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
75         assert(s == NSS_STATUS_SUCCESS);
76     }
77     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
78     assert(s == NSS_STATUS_SUCCESS);
79     assert(!strcmp(p.pw_name, "_rpc"));
80     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
81     assert(s == NSS_STATUS_SUCCESS);
82     assert(!strcmp(p.pw_name, "postfix"));
83     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
84     assert(s == NSS_STATUS_NOTFOUND);
85     assert(errnop == ENOENT);
86
87     s = _nss_cash_endpwent();
88     assert(s == NSS_STATUS_SUCCESS);
89
90
91     // Test proper reset
92
93     s = _nss_cash_setpwent(0);
94     assert(s == NSS_STATUS_SUCCESS);
95
96     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
97     assert(s == NSS_STATUS_SUCCESS);
98     assert(!strcmp(p.pw_name, "root"));
99     assert(!strcmp(p.pw_passwd, "x"));
100     assert(p.pw_uid == 0);
101     assert(p.pw_gid == 0);
102     assert(!strcmp(p.pw_gecos, "root"));
103     assert(!strcmp(p.pw_dir, "/root"));
104     assert(!strcmp(p.pw_shell, "/bin/bash"));
105
106     s = _nss_cash_endpwent();
107     assert(s == NSS_STATUS_SUCCESS);
108
109
110     // Test proper reset the 2nd
111
112     s = _nss_cash_setpwent(0);
113     assert(s == NSS_STATUS_SUCCESS);
114
115     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
116     assert(s == NSS_STATUS_SUCCESS);
117     assert(!strcmp(p.pw_name, "root"));
118     assert(!strcmp(p.pw_passwd, "x"));
119     assert(p.pw_uid == 0);
120     assert(p.pw_gid == 0);
121     assert(!strcmp(p.pw_gecos, "root"));
122     assert(!strcmp(p.pw_dir, "/root"));
123     assert(!strcmp(p.pw_shell, "/bin/bash"));
124
125     s = _nss_cash_endpwent();
126     assert(s == NSS_STATUS_SUCCESS);
127
128
129     // Test many rounds to check for open file leaks
130     for (int i = 0; i < 10000; i++) {
131         s = _nss_cash_setpwent(0);
132         assert(s == NSS_STATUS_SUCCESS);
133
134         s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
135         assert(s == NSS_STATUS_SUCCESS);
136         assert(!strcmp(p.pw_name, "root"));
137
138         s = _nss_cash_endpwent();
139         assert(s == NSS_STATUS_SUCCESS);
140     }
141
142
143     // Test with cash file is not present
144
145     assert(rename("tests/passwd.nsscash", "tests/passwd.nsscash.tmp") == 0);
146     s = _nss_cash_setpwent(0);
147     assert(s == NSS_STATUS_SUCCESS);
148     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
149     assert(s == NSS_STATUS_UNAVAIL);
150     assert(errnop == ENOENT);
151     s = _nss_cash_getpwent_r(&p, tmp, sizeof(tmp), &errnop);
152     assert(s == NSS_STATUS_UNAVAIL);
153     assert(errnop == ENOENT);
154     s = _nss_cash_endpwent();
155     assert(s == NSS_STATUS_SUCCESS);
156     assert(rename("tests/passwd.nsscash.tmp", "tests/passwd.nsscash") == 0);
157 }
158
159 static void test_getpwuid(void) {
160     struct passwd p;
161     enum nss_status s;
162     char tmp[1024];
163     char tmp_small[10];
164     int errnop = 0;
165
166     s = _nss_cash_getpwuid_r(0, &p, tmp_small, sizeof(tmp_small), &errnop);
167     assert(s == NSS_STATUS_TRYAGAIN);
168     assert(errnop == ERANGE);
169     s = _nss_cash_getpwuid_r(42, &p, tmp_small, sizeof(tmp_small), &errnop);
170     assert(s == NSS_STATUS_NOTFOUND); // 42 does not exist
171     assert(errnop == ENOENT);
172     s = _nss_cash_getpwuid_r(65534, &p, tmp_small, sizeof(tmp_small), &errnop);
173     assert(s == NSS_STATUS_TRYAGAIN);
174     assert(errnop == ERANGE);
175
176     s = _nss_cash_getpwuid_r(0, &p, tmp, sizeof(tmp), &errnop);
177     assert(s == NSS_STATUS_SUCCESS);
178     assert(!strcmp(p.pw_name, "root"));
179     assert(!strcmp(p.pw_passwd, "x"));
180     assert(p.pw_uid == 0);
181     assert(p.pw_gid == 0);
182     assert(!strcmp(p.pw_gecos, "root"));
183     assert(!strcmp(p.pw_dir, "/root"));
184     assert(!strcmp(p.pw_shell, "/bin/bash"));
185
186     s = _nss_cash_getpwuid_r(1, &p, tmp, sizeof(tmp), &errnop);
187     assert(s == NSS_STATUS_SUCCESS);
188     assert(!strcmp(p.pw_name, "daemon"));
189     assert(!strcmp(p.pw_passwd, "x"));
190     assert(p.pw_uid == 1);
191     assert(p.pw_gid == 1);
192     assert(!strcmp(p.pw_gecos, "daemon"));
193     assert(!strcmp(p.pw_dir, "/usr/sbin"));
194     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
195
196     s = _nss_cash_getpwuid_r(11, &p, tmp, sizeof(tmp), &errnop);
197     assert(s == NSS_STATUS_NOTFOUND);
198     assert(errnop == ENOENT);
199
200     s = _nss_cash_getpwuid_r(102, &p, tmp, sizeof(tmp), &errnop);
201     assert(s == NSS_STATUS_SUCCESS);
202     assert(!strcmp(p.pw_name, "systemd-network"));
203     assert(!strcmp(p.pw_passwd, "x"));
204     assert(p.pw_uid == 102);
205     assert(p.pw_gid == 103);
206     assert(!strcmp(p.pw_gecos, "systemd Network Management,,,"));
207     assert(!strcmp(p.pw_dir, "/run/systemd"));
208     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
209
210     s = _nss_cash_getpwuid_r(107, &p, tmp, sizeof(tmp), &errnop);
211     assert(s == NSS_STATUS_SUCCESS);
212     assert(!strcmp(p.pw_name, "postfix"));
213     assert(!strcmp(p.pw_passwd, "x"));
214     assert(p.pw_uid == 107);
215     assert(p.pw_gid == 114);
216     assert(!strcmp(p.pw_gecos, ""));
217     assert(!strcmp(p.pw_dir, "/var/spool/postfix"));
218     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
219
220     s = _nss_cash_getpwuid_r(INT_MAX, &p, tmp, sizeof(tmp), &errnop);
221     assert(s == NSS_STATUS_NOTFOUND);
222     assert(errnop == ENOENT);
223
224
225     // Test with cash file is not present
226
227     assert(rename("tests/passwd.nsscash", "tests/passwd.nsscash.tmp") == 0);
228     s = _nss_cash_getpwuid_r(0, &p, tmp, sizeof(tmp), &errnop);
229     assert(s == NSS_STATUS_UNAVAIL);
230     assert(errnop == ENOENT);
231     s = _nss_cash_getpwuid_r(42, &p, tmp, sizeof(tmp), &errnop);
232     assert(s == NSS_STATUS_UNAVAIL);
233     assert(errnop == ENOENT);
234     assert(rename("tests/passwd.nsscash.tmp", "tests/passwd.nsscash") == 0);
235 }
236
237 static void test_getpwnam(void) {
238     struct passwd p;
239     enum nss_status s;
240     char tmp[1024];
241     char tmp_small[10];
242     int errnop = 0;
243
244     s = _nss_cash_getpwnam_r("root", &p, tmp_small, sizeof(tmp_small), &errnop);
245     assert(s == NSS_STATUS_TRYAGAIN);
246     assert(errnop == ERANGE);
247     s = _nss_cash_getpwnam_r("nope", &p, tmp_small, sizeof(tmp_small), &errnop);
248     assert(s == NSS_STATUS_NOTFOUND); // does not exist
249     assert(errnop == ENOENT);
250     s = _nss_cash_getpwnam_r("nobody", &p, tmp_small, sizeof(tmp_small), &errnop);
251     assert(s == NSS_STATUS_TRYAGAIN);
252     assert(errnop == ERANGE);
253
254     s = _nss_cash_getpwnam_r("root", &p, tmp, sizeof(tmp), &errnop);
255     assert(s == NSS_STATUS_SUCCESS);
256     assert(!strcmp(p.pw_name, "root"));
257     assert(!strcmp(p.pw_passwd, "x"));
258     assert(p.pw_uid == 0);
259     assert(p.pw_gid == 0);
260     assert(!strcmp(p.pw_gecos, "root"));
261     assert(!strcmp(p.pw_dir, "/root"));
262     assert(!strcmp(p.pw_shell, "/bin/bash"));
263
264     s = _nss_cash_getpwnam_r("daemon", &p, tmp, sizeof(tmp), &errnop);
265     assert(s == NSS_STATUS_SUCCESS);
266     assert(!strcmp(p.pw_name, "daemon"));
267     assert(!strcmp(p.pw_passwd, "x"));
268     assert(p.pw_uid == 1);
269     assert(p.pw_gid == 1);
270     assert(!strcmp(p.pw_gecos, "daemon"));
271     assert(!strcmp(p.pw_dir, "/usr/sbin"));
272     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
273
274     s = _nss_cash_getpwnam_r("nope2", &p, tmp, sizeof(tmp), &errnop);
275     assert(s == NSS_STATUS_NOTFOUND);
276     assert(errnop == ENOENT);
277
278     s = _nss_cash_getpwnam_r("systemd-network", &p, tmp, sizeof(tmp), &errnop);
279     assert(s == NSS_STATUS_SUCCESS);
280     assert(!strcmp(p.pw_name, "systemd-network"));
281     assert(!strcmp(p.pw_passwd, "x"));
282     assert(p.pw_uid == 102);
283     assert(p.pw_gid == 103);
284     assert(!strcmp(p.pw_gecos, "systemd Network Management,,,"));
285     assert(!strcmp(p.pw_dir, "/run/systemd"));
286     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
287
288     s = _nss_cash_getpwnam_r("postfix", &p, tmp, sizeof(tmp), &errnop);
289     assert(s == NSS_STATUS_SUCCESS);
290     assert(!strcmp(p.pw_name, "postfix"));
291     assert(!strcmp(p.pw_passwd, "x"));
292     assert(p.pw_uid == 107);
293     assert(p.pw_gid == 114);
294     assert(!strcmp(p.pw_gecos, ""));
295     assert(!strcmp(p.pw_dir, "/var/spool/postfix"));
296     assert(!strcmp(p.pw_shell, "/usr/sbin/nologin"));
297
298     s = _nss_cash_getpwnam_r("", &p, tmp, sizeof(tmp), &errnop);
299     assert(s == NSS_STATUS_NOTFOUND);
300     assert(errnop == ENOENT);
301
302
303     // Test with cash file is not present
304
305     assert(rename("tests/passwd.nsscash", "tests/passwd.nsscash.tmp") == 0);
306     s = _nss_cash_getpwnam_r("root", &p, tmp, sizeof(tmp), &errnop);
307     assert(s == NSS_STATUS_UNAVAIL);
308     assert(errnop == ENOENT);
309     s = _nss_cash_getpwnam_r("nope", &p, tmp, sizeof(tmp), &errnop);
310     assert(s == NSS_STATUS_UNAVAIL);
311     assert(errnop == ENOENT);
312     assert(rename("tests/passwd.nsscash.tmp", "tests/passwd.nsscash") == 0);
313 }
314
315 int main(void) {
316     test_getpwent();
317     test_getpwuid();
318     test_getpwnam();
319
320     return EXIT_SUCCESS;
321 }