1 | /* Copyright (C) 2015-2022 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <nss.h> |
19 | #include <pwd.h> |
20 | #include <stdbool.h> |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
23 | #include <string.h> |
24 | |
25 | #include <support/support.h> |
26 | |
27 | int |
28 | do_test (void) |
29 | { |
30 | __nss_configure_lookup (dbname: "passwd" , string: "files" ); |
31 | |
32 | /* Count the number of entries in the password database, and fetch |
33 | data from the first and last entries. */ |
34 | size_t count = 0; |
35 | struct passwd * pw; |
36 | char *first_name = NULL; |
37 | uid_t first_uid = 0; |
38 | char *last_name = NULL; |
39 | uid_t last_uid = 0; |
40 | setpwent (); |
41 | while ((pw = getpwent ()) != NULL) |
42 | { |
43 | if (first_name == NULL) |
44 | { |
45 | first_name = xstrdup (pw->pw_name); |
46 | first_uid = pw->pw_uid; |
47 | } |
48 | |
49 | free (ptr: last_name); |
50 | last_name = xstrdup (pw->pw_name); |
51 | last_uid = pw->pw_uid; |
52 | ++count; |
53 | } |
54 | endpwent (); |
55 | |
56 | if (count == 0) |
57 | { |
58 | printf (format: "No entries in the password database.\n" ); |
59 | return 0; |
60 | } |
61 | |
62 | /* Try again, this time interleaving with name-based and UID-based |
63 | lookup operations. The counts do not match if the interleaved |
64 | lookups affected the enumeration. */ |
65 | size_t new_count = 0; |
66 | setpwent (); |
67 | while ((pw = getpwent ()) != NULL) |
68 | { |
69 | if (new_count == count) |
70 | { |
71 | printf (format: "Additional entry in the password database.\n" ); |
72 | return 1; |
73 | } |
74 | ++new_count; |
75 | struct passwd *pw2 = getpwnam (name: first_name); |
76 | if (pw2 == NULL) |
77 | { |
78 | printf (format: "getpwnam (%s) failed: %m\n" , first_name); |
79 | return 1; |
80 | } |
81 | pw2 = getpwnam (name: last_name); |
82 | if (pw2 == NULL) |
83 | { |
84 | printf (format: "getpwnam (%s) failed: %m\n" , last_name); |
85 | return 1; |
86 | } |
87 | pw2 = getpwuid (uid: first_uid); |
88 | if (pw2 == NULL) |
89 | { |
90 | printf (format: "getpwuid (%llu) failed: %m\n" , |
91 | (unsigned long long) first_uid); |
92 | return 1; |
93 | } |
94 | pw2 = getpwuid (uid: last_uid); |
95 | if (pw2 == NULL) |
96 | { |
97 | printf (format: "getpwuid (%llu) failed: %m\n" , |
98 | (unsigned long long) last_uid); |
99 | return 1; |
100 | } |
101 | } |
102 | endpwent (); |
103 | if (new_count < count) |
104 | { |
105 | printf (format: "Missing entry in the password database.\n" ); |
106 | return 1; |
107 | } |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | #define TIMEOUT 300 |
113 | #include <support/test-driver.c> |
114 | |