]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - lib/libc/tests/nss/getpw_test.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / lib / libc / tests / nss / getpw_test.c
1 /*-
2  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <errno.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include <atf-c.h>
39
40 #include "testutil.h"
41
42 enum test_methods {
43         TEST_GETPWENT,
44         TEST_GETPWNAM,
45         TEST_GETPWUID,
46         TEST_GETPWENT_2PASS,
47         TEST_BUILD_SNAPSHOT
48 };
49
50 static enum test_methods method = TEST_BUILD_SNAPSHOT;
51
52 DECLARE_TEST_DATA(passwd)
53 DECLARE_TEST_FILE_SNAPSHOT(passwd)
54 DECLARE_1PASS_TEST(passwd)
55 DECLARE_2PASS_TEST(passwd)
56
57 static void clone_passwd(struct passwd *, struct passwd const *);
58 static int compare_passwd(struct passwd *, struct passwd *, void *);
59 static void free_passwd(struct passwd *);
60
61 static void sdump_passwd(struct passwd *, char *, size_t);
62 static void dump_passwd(struct passwd *);
63
64 static int passwd_read_snapshot_func(struct passwd *, char *);
65
66 static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *);
67 static int passwd_fill_test_data(struct passwd_test_data *);
68 static int passwd_test_correctness(struct passwd *, void *);
69 static int passwd_test_getpwnam(struct passwd *, void *);
70 static int passwd_test_getpwuid(struct passwd *, void *);
71 static int passwd_test_getpwent(struct passwd *, void *);
72
73 IMPLEMENT_TEST_DATA(passwd)
74 IMPLEMENT_TEST_FILE_SNAPSHOT(passwd)
75 IMPLEMENT_1PASS_TEST(passwd)
76 IMPLEMENT_2PASS_TEST(passwd)
77
78 static void
79 clone_passwd(struct passwd *dest, struct passwd const *src)
80 {
81         ATF_REQUIRE(dest != NULL);
82         ATF_REQUIRE(src != NULL);
83
84         memcpy(dest, src, sizeof(struct passwd));
85         if (src->pw_name != NULL)
86                 dest->pw_name = strdup(src->pw_name);
87         if (src->pw_passwd != NULL)
88                 dest->pw_passwd = strdup(src->pw_passwd);
89         if (src->pw_class != NULL)
90                 dest->pw_class = strdup(src->pw_class);
91         if (src->pw_gecos != NULL)
92                 dest->pw_gecos = strdup(src->pw_gecos);
93         if (src->pw_dir != NULL)
94                 dest->pw_dir = strdup(src->pw_dir);
95         if (src->pw_shell != NULL)
96                 dest->pw_shell = strdup(dest->pw_shell);
97 }
98
99 static int
100 compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata)
101 {
102         ATF_REQUIRE(pwd1 != NULL);
103         ATF_REQUIRE(pwd2 != NULL);
104
105         if (pwd1 == pwd2)
106                 return (0);
107
108         if (pwd1->pw_uid != pwd2->pw_uid ||
109             pwd1->pw_gid != pwd2->pw_gid ||
110             pwd1->pw_change != pwd2->pw_change ||
111             pwd1->pw_expire != pwd2->pw_expire ||
112             pwd1->pw_fields != pwd2->pw_fields ||
113             strcmp(pwd1->pw_name, pwd2->pw_name) != 0 ||
114             strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0 ||
115             strcmp(pwd1->pw_class, pwd2->pw_class) != 0 ||
116             strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0 ||
117             strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0 ||
118             strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
119                 return (-1);
120         else
121                 return (0);
122 }
123
124 static void
125 free_passwd(struct passwd *pwd)
126 {
127         free(pwd->pw_name);
128         free(pwd->pw_passwd);
129         free(pwd->pw_class);
130         free(pwd->pw_gecos);
131         free(pwd->pw_dir);
132         free(pwd->pw_shell);
133 }
134
135 static void
136 sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen)
137 {
138         snprintf(buffer, buflen, "%s:%s:%d:%d:%jd:%s:%s:%s:%s:%jd:%d",
139             pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
140             (uintmax_t)pwd->pw_change, pwd->pw_class, pwd->pw_gecos,
141             pwd->pw_dir, pwd->pw_shell, (uintmax_t)pwd->pw_expire,
142             pwd->pw_fields);
143 }
144
145 static void
146 dump_passwd(struct passwd *pwd)
147 {
148         if (pwd != NULL) {
149                 char buffer[2048];
150                 sdump_passwd(pwd, buffer, sizeof(buffer));
151                 printf("%s\n", buffer);
152         } else
153                 printf("(null)\n");
154 }
155
156 static int
157 passwd_read_snapshot_func(struct passwd *pwd, char *line)
158 {
159         char *s, *ps, *ts;
160         int i;
161
162 #ifdef DEBUG
163         printf("1 line read from snapshot:\n%s\n", line);
164 #endif
165
166         i = 0;
167         ps = line;
168         memset(pwd, 0, sizeof(struct passwd));
169         while ((s = strsep(&ps, ":")) != NULL) {
170                 switch (i) {
171                 case 0:
172                         pwd->pw_name = strdup(s);
173                         ATF_REQUIRE(pwd->pw_name != NULL);
174                         break;
175                 case 1:
176                         pwd->pw_passwd = strdup(s);
177                         ATF_REQUIRE(pwd->pw_passwd != NULL);
178                         break;
179                 case 2:
180                         pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
181                         if (*ts != '\0')
182                                 goto fin;
183                         break;
184                 case 3:
185                         pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
186                         if (*ts != '\0')
187                                 goto fin;
188                         break;
189                 case 4:
190                         pwd->pw_change = (time_t)strtol(s, &ts, 10);
191                         if (*ts != '\0')
192                                 goto fin;
193                         break;
194                 case 5:
195                         pwd->pw_class = strdup(s);
196                         ATF_REQUIRE(pwd->pw_class != NULL);
197                         break;
198                 case 6:
199                         pwd->pw_gecos = strdup(s);
200                         ATF_REQUIRE(pwd->pw_gecos != NULL);
201                         break;
202                 case 7:
203                         pwd->pw_dir = strdup(s);
204                         ATF_REQUIRE(pwd->pw_dir != NULL);
205                         break;
206                 case 8:
207                         pwd->pw_shell = strdup(s);
208                         ATF_REQUIRE(pwd->pw_shell != NULL);
209                         break;
210                 case 9:
211                         pwd->pw_expire = (time_t)strtol(s, &ts, 10);
212                         if (*ts != '\0')
213                                 goto fin;
214                         break;
215                 case 10:
216                         pwd->pw_fields = (int)strtol(s, &ts, 10);
217                         if (*ts != '\0')
218                                 goto fin;
219                         break;
220                 default:
221                         break;
222                 }
223                 ++i;
224         }
225
226 fin:
227         if (i != 11) {
228                 free_passwd(pwd);
229                 memset(pwd, 0, sizeof(struct passwd));
230                 return (-1);
231         }
232
233         return (0);
234 }
235
236 static int
237 passwd_fill_test_data(struct passwd_test_data *td)
238 {
239         struct passwd *pwd;
240
241         setpassent(1);
242         while ((pwd = getpwent()) != NULL) {
243                 if (passwd_test_correctness(pwd, NULL) == 0)
244                         TEST_DATA_APPEND(passwd, td, pwd);
245                 else
246                         return (-1);
247         }
248         endpwent();
249
250         return (0);
251 }
252
253 static int
254 passwd_test_correctness(struct passwd *pwd, void *mdata)
255 {
256
257 #ifdef DEBUG
258         printf("testing correctness with the following data:\n");
259         dump_passwd(pwd);
260 #endif
261
262         if (pwd == NULL)
263                 return (-1);
264
265         if (pwd->pw_name == NULL)
266                 goto errfin;
267
268         if (pwd->pw_passwd == NULL)
269                 goto errfin;
270
271         if (pwd->pw_class == NULL)
272                 goto errfin;
273
274         if (pwd->pw_gecos == NULL)
275                 goto errfin;
276
277         if (pwd->pw_dir == NULL)
278                 goto errfin;
279
280         if (pwd->pw_shell == NULL)
281                 goto errfin;
282
283 #ifdef DEBUG
284         printf("correct\n");
285 #endif
286
287         return (0);
288 errfin:
289 #ifdef DEBUG
290         printf("incorrect\n");
291 #endif
292
293         return (-1);
294 }
295
296 /* passwd_check_ambiguity() is needed here because when doing the getpwent()
297  * calls sequence, records from different nsswitch sources can be different,
298  * though having the same pw_name/pw_uid */
299 static int
300 passwd_check_ambiguity(struct passwd_test_data *td, struct passwd *pwd)
301 {
302
303         return (TEST_DATA_FIND(passwd, td, pwd, compare_passwd,
304                 NULL) != NULL ? 0 : -1);
305 }
306
307 static int
308 passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
309 {
310         struct passwd *pwd;
311
312 #ifdef DEBUG
313         printf("testing getpwnam() with the following data:\n");
314         dump_passwd(pwd_model);
315 #endif
316
317         pwd = getpwnam(pwd_model->pw_name);
318         if (passwd_test_correctness(pwd, NULL) != 0)
319                 goto errfin;
320
321         if ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
322             (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
323             !=0))
324             goto errfin;
325
326 #ifdef DEBUG
327         printf("ok\n");
328 #endif
329         return (0);
330
331 errfin:
332 #ifdef DEBUG
333         printf("not ok\n");
334 #endif
335         return (-1);
336 }
337
338 static int
339 passwd_test_getpwuid(struct passwd *pwd_model, void *mdata)
340 {
341         struct passwd *pwd;
342
343 #ifdef DEBUG
344         printf("testing getpwuid() with the following data...\n");
345         dump_passwd(pwd_model);
346 #endif
347
348         pwd = getpwuid(pwd_model->pw_uid);
349         if ((passwd_test_correctness(pwd, NULL) != 0) ||
350             ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
351             (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
352             != 0))) {
353 #ifdef DEBUG
354                 printf("not ok\n");
355 #endif
356                 return (-1);
357         } else {
358 #ifdef DEBUG
359                 printf("ok\n");
360 #endif
361                 return (0);
362         }
363 }
364
365 static int
366 passwd_test_getpwent(struct passwd *pwd, void *mdata)
367 {
368         /* Only correctness can be checked when doing 1-pass test for
369          * getpwent(). */
370         return (passwd_test_correctness(pwd, NULL));
371 }
372
373 static int
374 run_tests(const char *snapshot_file, enum test_methods method)
375 {
376         struct passwd_test_data td, td_snap, td_2pass;
377         int rv;
378
379         TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd);
380         TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd);
381         if (snapshot_file != NULL) {
382                 if (access(snapshot_file, W_OK | R_OK) != 0) {
383                         if (errno == ENOENT)
384                                 method = TEST_BUILD_SNAPSHOT;
385                         else {
386                                 printf("can't access the file %s\n",
387                                     snapshot_file);
388                                 rv = -1;
389                                 goto fin;
390                         }
391                 } else {
392                         if (method == TEST_BUILD_SNAPSHOT) {
393                                 rv = 0;
394                                 goto fin;
395                         }
396
397                         TEST_SNAPSHOT_FILE_READ(passwd, snapshot_file,
398                                 &td_snap, passwd_read_snapshot_func);
399                 }
400         }
401
402         rv = passwd_fill_test_data(&td);
403         if (rv == -1)
404                 return (-1);
405
406         switch (method) {
407         case TEST_GETPWNAM:
408                 if (snapshot_file == NULL)
409                         rv = DO_1PASS_TEST(passwd, &td,
410                                 passwd_test_getpwnam, (void *)&td);
411                 else
412                         rv = DO_1PASS_TEST(passwd, &td_snap,
413                                 passwd_test_getpwnam, (void *)&td_snap);
414                 break;
415         case TEST_GETPWUID:
416                 if (snapshot_file == NULL)
417                         rv = DO_1PASS_TEST(passwd, &td,
418                                 passwd_test_getpwuid, (void *)&td);
419                 else
420                         rv = DO_1PASS_TEST(passwd, &td_snap,
421                                 passwd_test_getpwuid, (void *)&td_snap);
422                 break;
423         case TEST_GETPWENT:
424                 if (snapshot_file == NULL)
425                         rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwent,
426                                 (void *)&td);
427                 else
428                         rv = DO_2PASS_TEST(passwd, &td, &td_snap,
429                                 compare_passwd, NULL);
430                 break;
431         case TEST_GETPWENT_2PASS:
432                 TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd);
433                 rv = passwd_fill_test_data(&td_2pass);
434                 if (rv != -1)
435                         rv = DO_2PASS_TEST(passwd, &td, &td_2pass,
436                             compare_passwd, NULL);
437                 TEST_DATA_DESTROY(passwd, &td_2pass);
438                 break;
439         case TEST_BUILD_SNAPSHOT:
440                 if (snapshot_file != NULL)
441                         rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file,
442                             &td, sdump_passwd);
443                 break;
444         default:
445                 rv = 0;
446                 break;
447         }
448
449 fin:
450         TEST_DATA_DESTROY(passwd, &td_snap);
451         TEST_DATA_DESTROY(passwd, &td);
452
453         return (rv);
454 }
455
456 #define SNAPSHOT_FILE   "snapshot_pwd"
457
458 ATF_TC_WITHOUT_HEAD(build_snapshot);
459 ATF_TC_BODY(build_snapshot, tc)
460 {
461
462         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
463 }
464
465 ATF_TC_WITHOUT_HEAD(getpwent);
466 ATF_TC_BODY(getpwent, tc)
467 {
468
469         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0);
470 }
471
472 ATF_TC_WITHOUT_HEAD(getpwent_with_snapshot);
473 ATF_TC_BODY(getpwent_with_snapshot, tc)
474 {
475
476         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
477         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0);
478 }
479
480 ATF_TC_WITHOUT_HEAD(getpwent_with_two_pass);
481 ATF_TC_BODY(getpwent_with_two_pass, tc)
482 {
483
484         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT_2PASS) == 0);
485 }
486
487 ATF_TC_WITHOUT_HEAD(getpwnam);
488 ATF_TC_BODY(getpwnam, tc)
489 {
490
491         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0);
492 }
493
494 ATF_TC_WITHOUT_HEAD(getpwnam_with_snapshot);
495 ATF_TC_BODY(getpwnam_with_snapshot, tc)
496 {
497
498         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
499         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0);
500 }
501
502 ATF_TC_WITHOUT_HEAD(getpwuid);
503 ATF_TC_BODY(getpwuid, tc)
504 {
505
506         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0);
507 }
508
509 ATF_TC_WITHOUT_HEAD(getpwuid_with_snapshot);
510 ATF_TC_BODY(getpwuid_with_snapshot, tc)
511 {
512
513         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
514         ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0);
515 }
516
517 ATF_TP_ADD_TCS(tp)
518 {
519
520         ATF_TP_ADD_TC(tp, build_snapshot);
521         ATF_TP_ADD_TC(tp, getpwent);
522         ATF_TP_ADD_TC(tp, getpwent_with_snapshot);
523         ATF_TP_ADD_TC(tp, getpwent_with_two_pass);
524         ATF_TP_ADD_TC(tp, getpwnam);
525         ATF_TP_ADD_TC(tp, getpwnam_with_snapshot);
526         ATF_TP_ADD_TC(tp, getpwuid);
527         ATF_TP_ADD_TC(tp, getpwuid_with_snapshot);
528
529         return (atf_no_error());
530 }