]> ruderich.org/simon Gitweb - nsscash/nsscash.git/blob - nss/tests/gr.c
nss: tests: sort included headers
[nsscash/nsscash.git] / nss / tests / gr.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_getgrent(void) {
31     struct group g;
32     enum nss_status s;
33     char tmp[1024];
34     char tmp_small[10];
35     int errnop = 0;
36
37     // Test one setgrent/getgrent/endgrent round
38
39     s = _nss_cash_setgrent(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_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
44     assert(s == NSS_STATUS_TRYAGAIN);
45     assert(errnop == ERANGE);
46     s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
47     assert(s == NSS_STATUS_TRYAGAIN);
48     assert(errnop == ERANGE);
49     s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
50     assert(s == NSS_STATUS_TRYAGAIN);
51     assert(errnop == ERANGE);
52
53     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
54     assert(s == NSS_STATUS_SUCCESS);
55     assert(!strcmp(g.gr_name, "root"));
56     assert(!strcmp(g.gr_passwd, "x"));
57     assert(g.gr_gid == 0);
58     assert(g.gr_mem != NULL);
59     assert(g.gr_mem[0] == NULL);
60
61     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
62     assert(s == NSS_STATUS_SUCCESS);
63     assert(!strcmp(g.gr_name, "daemon"));
64     assert(g.gr_gid == 1);
65     assert(g.gr_mem != NULL);
66     assert(!strcmp(g.gr_mem[0], "andariel"));
67     assert(!strcmp(g.gr_mem[1], "duriel"));
68     assert(!strcmp(g.gr_mem[2], "mephisto"));
69     assert(!strcmp(g.gr_mem[3], "diablo"));
70     assert(!strcmp(g.gr_mem[4], "baal"));
71     assert(g.gr_mem[5] == NULL);
72     for (int i = 0; i < 21; i++) {
73         s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
74         assert(s == NSS_STATUS_SUCCESS);
75     }
76     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
77     assert(s == NSS_STATUS_SUCCESS);
78     assert(!strcmp(g.gr_name, "www-data"));
79     assert(!strcmp(g.gr_passwd, "x"));
80     assert(g.gr_gid == 33);
81     assert(g.gr_mem != NULL);
82     assert(!strcmp(g.gr_mem[0], "nobody"));
83     assert(g.gr_mem[1] == NULL);
84     for (int i = 0; i < 29; i++) {
85         s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
86         assert(s == NSS_STATUS_SUCCESS);
87     }
88     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
89     assert(s == NSS_STATUS_SUCCESS);
90     assert(!strcmp(g.gr_name, "postfix"));
91     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
92     assert(s == NSS_STATUS_SUCCESS);
93     assert(!strcmp(g.gr_name, "postdrop"));
94     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
95     assert(s == NSS_STATUS_NOTFOUND);
96     assert(errnop == ENOENT);
97
98     s = _nss_cash_endgrent();
99     assert(s == NSS_STATUS_SUCCESS);
100
101
102     // Test proper reset
103
104     s = _nss_cash_setgrent(0);
105     assert(s == NSS_STATUS_SUCCESS);
106
107     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
108     assert(s == NSS_STATUS_SUCCESS);
109     assert(!strcmp(g.gr_name, "root"));
110     assert(!strcmp(g.gr_passwd, "x"));
111     assert(g.gr_gid == 0);
112     assert(g.gr_mem != NULL);
113     assert(g.gr_mem[0] == NULL);
114
115     s = _nss_cash_endgrent();
116     assert(s == NSS_STATUS_SUCCESS);
117
118
119     // Test proper reset the 2nd
120
121     s = _nss_cash_setgrent(0);
122     assert(s == NSS_STATUS_SUCCESS);
123
124     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
125     assert(s == NSS_STATUS_SUCCESS);
126     assert(!strcmp(g.gr_name, "root"));
127     assert(!strcmp(g.gr_passwd, "x"));
128     assert(g.gr_gid == 0);
129     assert(g.gr_mem != NULL);
130     assert(g.gr_mem[0] == NULL);
131
132     s = _nss_cash_endgrent();
133     assert(s == NSS_STATUS_SUCCESS);
134
135
136     // Test many rounds to check for open file leaks
137     for (int i = 0; i < 10000; i++) {
138         s = _nss_cash_setgrent(0);
139         assert(s == NSS_STATUS_SUCCESS);
140
141         s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
142         assert(s == NSS_STATUS_SUCCESS);
143         assert(!strcmp(g.gr_name, "root"));
144
145         s = _nss_cash_endgrent();
146         assert(s == NSS_STATUS_SUCCESS);
147     }
148
149
150     // Test with cash file is not present
151
152     assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
153     s = _nss_cash_setgrent(0);
154     assert(s == NSS_STATUS_SUCCESS);
155     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
156     assert(s == NSS_STATUS_UNAVAIL);
157     assert(errnop == ENOENT);
158     s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
159     assert(s == NSS_STATUS_UNAVAIL);
160     assert(errnop == ENOENT);
161     s = _nss_cash_endgrent();
162     assert(s == NSS_STATUS_SUCCESS);
163     assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
164 }
165
166 static void test_getgrgid(void) {
167     struct group g;
168     enum nss_status s;
169     char tmp[1024];
170     char tmp_small[10];
171     int errnop = 0;
172
173     s = _nss_cash_getgrgid_r(0, &g, tmp_small, sizeof(tmp_small), &errnop);
174     assert(s == NSS_STATUS_TRYAGAIN);
175     assert(errnop == ERANGE);
176     s = _nss_cash_getgrgid_r(14, &g, tmp_small, sizeof(tmp_small), &errnop);
177     assert(s == NSS_STATUS_NOTFOUND); // 14 does not exist
178     assert(errnop == ENOENT);
179     s = _nss_cash_getgrgid_r(65534, &g, tmp_small, sizeof(tmp_small), &errnop);
180     assert(s == NSS_STATUS_TRYAGAIN);
181     assert(errnop == ERANGE);
182
183     s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
184     assert(s == NSS_STATUS_SUCCESS);
185     assert(!strcmp(g.gr_name, "root"));
186     assert(!strcmp(g.gr_passwd, "x"));
187     assert(g.gr_gid == 0);
188     assert(g.gr_mem != NULL);
189     assert(g.gr_mem[0] == NULL);
190
191     s = _nss_cash_getgrgid_r(1, &g, tmp, sizeof(tmp), &errnop);
192     assert(s == NSS_STATUS_SUCCESS);
193     assert(!strcmp(g.gr_name, "daemon"));
194     assert(g.gr_gid == 1);
195     assert(g.gr_mem != NULL);
196     assert(!strcmp(g.gr_mem[0], "andariel"));
197     assert(!strcmp(g.gr_mem[1], "duriel"));
198     assert(!strcmp(g.gr_mem[2], "mephisto"));
199     assert(!strcmp(g.gr_mem[3], "diablo"));
200     assert(!strcmp(g.gr_mem[4], "baal"));
201     assert(g.gr_mem[5] == NULL);
202
203     s = _nss_cash_getgrgid_r(11, &g, tmp, sizeof(tmp), &errnop);
204     assert(s == NSS_STATUS_NOTFOUND);
205     assert(errnop == ENOENT);
206
207     s = _nss_cash_getgrgid_r(103, &g, tmp, sizeof(tmp), &errnop);
208     assert(s == NSS_STATUS_SUCCESS);
209     assert(!strcmp(g.gr_name, "systemd-network"));
210     assert(!strcmp(g.gr_passwd, "x"));
211     assert(g.gr_gid == 103);
212     assert(g.gr_mem != NULL);
213     assert(g.gr_mem[0] == NULL);
214
215     s = _nss_cash_getgrgid_r(107, &g, tmp, sizeof(tmp), &errnop);
216     assert(s == NSS_STATUS_SUCCESS);
217     assert(!strcmp(g.gr_name, "kvm"));
218     assert(!strcmp(g.gr_passwd, "x"));
219     assert(g.gr_gid == 107);
220     assert(g.gr_mem != NULL);
221     assert(g.gr_mem[0] == NULL);
222
223     s = _nss_cash_getgrgid_r(65534, &g, tmp, sizeof(tmp), &errnop);
224     assert(s == NSS_STATUS_SUCCESS);
225     assert(!strcmp(g.gr_name, "nogroup"));
226     assert(!strcmp(g.gr_passwd, "x"));
227     assert(g.gr_gid == 65534);
228     assert(g.gr_mem != NULL);
229     assert(g.gr_mem[0] == NULL);
230
231     s = _nss_cash_getgrgid_r(INT_MAX, &g, tmp, sizeof(tmp), &errnop);
232     assert(s == NSS_STATUS_NOTFOUND);
233     assert(errnop == ENOENT);
234
235
236     // Test with cash file is not present
237
238     assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
239     s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
240     assert(s == NSS_STATUS_UNAVAIL);
241     assert(errnop == ENOENT);
242     s = _nss_cash_getgrgid_r(14, &g, tmp, sizeof(tmp), &errnop);
243     assert(s == NSS_STATUS_UNAVAIL);
244     assert(errnop == ENOENT);
245     assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
246 }
247
248 static void test_getgrnam(void) {
249     struct group g;
250     enum nss_status s;
251     char tmp[1024];
252     char tmp_small[10];
253     int errnop = 0;
254
255     s = _nss_cash_getgrnam_r("root", &g, tmp_small, sizeof(tmp_small), &errnop);
256     assert(s == NSS_STATUS_TRYAGAIN);
257     assert(errnop == ERANGE);
258     s = _nss_cash_getgrnam_r("nope", &g, tmp_small, sizeof(tmp_small), &errnop);
259     assert(s == NSS_STATUS_NOTFOUND); // does not exist
260     assert(errnop == ENOENT);
261     s = _nss_cash_getgrnam_r("nogroup", &g, tmp_small, sizeof(tmp_small), &errnop);
262     assert(s == NSS_STATUS_TRYAGAIN);
263     assert(errnop == ERANGE);
264
265     s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
266     assert(s == NSS_STATUS_SUCCESS);
267     assert(!strcmp(g.gr_name, "root"));
268     assert(!strcmp(g.gr_passwd, "x"));
269     assert(g.gr_gid == 0);
270     assert(g.gr_mem != NULL);
271     assert(g.gr_mem[0] == NULL);
272
273     s = _nss_cash_getgrnam_r("daemon", &g, tmp, sizeof(tmp), &errnop);
274     assert(s == NSS_STATUS_SUCCESS);
275     assert(!strcmp(g.gr_name, "daemon"));
276     assert(g.gr_gid == 1);
277     assert(g.gr_mem != NULL);
278     assert(!strcmp(g.gr_mem[0], "andariel"));
279     assert(!strcmp(g.gr_mem[1], "duriel"));
280     assert(!strcmp(g.gr_mem[2], "mephisto"));
281     assert(!strcmp(g.gr_mem[3], "diablo"));
282     assert(!strcmp(g.gr_mem[4], "baal"));
283     assert(g.gr_mem[5] == NULL);
284
285     s = _nss_cash_getgrnam_r("nope2", &g, tmp, sizeof(tmp), &errnop);
286     assert(s == NSS_STATUS_NOTFOUND);
287     assert(errnop == ENOENT);
288
289     s = _nss_cash_getgrnam_r("systemd-network", &g, tmp, sizeof(tmp), &errnop);
290     assert(s == NSS_STATUS_SUCCESS);
291     assert(!strcmp(g.gr_name, "systemd-network"));
292     assert(!strcmp(g.gr_passwd, "x"));
293     assert(g.gr_gid == 103);
294     assert(g.gr_mem != NULL);
295     assert(g.gr_mem[0] == NULL);
296
297     s = _nss_cash_getgrnam_r("postfix", &g, tmp, sizeof(tmp), &errnop);
298     assert(s == NSS_STATUS_SUCCESS);
299     assert(!strcmp(g.gr_name, "postfix"));
300     assert(!strcmp(g.gr_passwd, "x"));
301     assert(g.gr_gid == 114);
302     assert(g.gr_mem != NULL);
303     assert(g.gr_mem[0] == NULL);
304
305     s = _nss_cash_getgrnam_r("", &g, tmp, sizeof(tmp), &errnop);
306     assert(s == NSS_STATUS_NOTFOUND);
307     assert(errnop == ENOENT);
308
309
310     // Test with cash file is not present
311
312     assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
313     s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
314     assert(s == NSS_STATUS_UNAVAIL);
315     assert(errnop == ENOENT);
316     s = _nss_cash_getgrnam_r("nope", &g, tmp, sizeof(tmp), &errnop);
317     assert(s == NSS_STATUS_UNAVAIL);
318     assert(errnop == ENOENT);
319     assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
320 }
321
322 int main(void) {
323     test_getgrent();
324     test_getgrgid();
325     test_getgrnam();
326
327     return EXIT_SUCCESS;
328 }