]>
Commit | Line | Data |
---|---|---|
ae5c498d | 1 | /* Template generic NSS service provider. See nss_test.h for usage. |
04277e02 | 2 | Copyright (C) 2017-2019 Free Software Foundation, Inc. |
ae5c498d DD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
ae5c498d | 18 | |
c3e2f19b UD |
19 | #include <errno.h> |
20 | #include <nss.h> | |
21 | #include <pthread.h> | |
22 | #include <string.h> | |
ae5c498d DD |
23 | #include <stdio.h> |
24 | #include <alloc_buffer.h> | |
c3e2f19b UD |
25 | |
26 | ||
ae5c498d DD |
27 | /* We need to be able to handle NULLs "properly" within the testsuite, |
28 | to test known bad data. */ | |
29 | #define alloc_buffer_maybe_copy_string(b,s) s ? alloc_buffer_copy_string (b, s) : NULL; | |
c3e2f19b | 30 | |
ae5c498d DD |
31 | /* This file is the master template. Other instances of this test |
32 | module should define NAME(x) to have their name instead of "test1", | |
33 | then include this file. | |
34 | */ | |
35 | #define NAME_(x,n) _nss_##n##_##x | |
36 | #ifndef NAME | |
37 | #define NAME(x) NAME_(x,test1) | |
38 | #endif | |
39 | #define NAMESTR__(x) #x | |
40 | #define NAMESTR_(x) NAMESTR__(x) | |
41 | #define NAMESTR(x) NAMESTR_(NAME(x)) | |
c3e2f19b | 42 | |
ae5c498d DD |
43 | #include "nss_test.h" |
44 | ||
45 | /* -------------------------------------------------- */ | |
46 | /* Default Data. */ | |
c3e2f19b | 47 | |
ae5c498d | 48 | static struct passwd default_pwd_data[] = |
c3e2f19b UD |
49 | { |
50 | #define PWD(u) \ | |
51 | { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \ | |
52 | .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \ | |
53 | .pw_shell = (char *) "*" } | |
c3e2f19b | 54 | PWD (30), |
ae5c498d | 55 | PWD (100), |
c3e2f19b UD |
56 | PWD (200), |
57 | PWD (60), | |
58 | PWD (20000) | |
59 | }; | |
cb62108e SE |
60 | #define default_npwd_data \ |
61 | (sizeof (default_pwd_data) / sizeof (default_pwd_data[0])) | |
ae5c498d DD |
62 | |
63 | static struct passwd *pwd_data = default_pwd_data; | |
64 | static int npwd_data = default_npwd_data; | |
65 | ||
66 | static struct group *grp_data = NULL; | |
67 | static int ngrp_data = 0; | |
68 | ||
69 | /* This function will get called, and once per session, look back into | |
70 | the test case's executable for an init hook function, and call | |
71 | it. */ | |
72 | ||
73 | static int initted = 0; | |
74 | static void | |
75 | init(void) | |
76 | { | |
77 | test_tables t; | |
78 | int i; | |
79 | ||
80 | if (initted) | |
81 | return; | |
82 | if (NAME(init_hook)) | |
83 | { | |
c4f50205 | 84 | memset (&t, 0, sizeof (t)); |
ae5c498d DD |
85 | NAME(init_hook)(&t); |
86 | ||
87 | if (t.pwd_table) | |
88 | { | |
89 | pwd_data = t.pwd_table; | |
90 | for (i=0; ! PWD_ISLAST(& pwd_data[i]); i++) | |
91 | ; | |
92 | npwd_data = i; | |
93 | } | |
94 | ||
95 | if (t.grp_table) | |
96 | { | |
97 | grp_data = t.grp_table; | |
98 | for (i=0; ! GRP_ISLAST(& grp_data[i]); i++) | |
99 | ; | |
100 | ngrp_data = i; | |
101 | } | |
102 | } | |
103 | initted = 1; | |
104 | } | |
105 | ||
106 | /* -------------------------------------------------- */ | |
107 | /* Password handling. */ | |
c3e2f19b UD |
108 | |
109 | static size_t pwd_iter; | |
110 | #define CURPWD pwd_data[pwd_iter] | |
111 | ||
112 | static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER; | |
113 | ||
c3e2f19b | 114 | enum nss_status |
ae5c498d | 115 | NAME(setpwent) (int stayopen) |
c3e2f19b | 116 | { |
ae5c498d | 117 | init(); |
c3e2f19b UD |
118 | pwd_iter = 0; |
119 | return NSS_STATUS_SUCCESS; | |
120 | } | |
121 | ||
122 | ||
123 | enum nss_status | |
ae5c498d | 124 | NAME(endpwent) (void) |
c3e2f19b | 125 | { |
ae5c498d | 126 | init(); |
c3e2f19b UD |
127 | return NSS_STATUS_SUCCESS; |
128 | } | |
129 | ||
ae5c498d DD |
130 | static enum nss_status |
131 | copy_passwd (struct passwd *result, struct passwd *local, | |
132 | char *buffer, size_t buflen, int *errnop) | |
133 | { | |
134 | struct alloc_buffer buf = alloc_buffer_create (buffer, buflen); | |
135 | ||
136 | result->pw_name = alloc_buffer_maybe_copy_string (&buf, local->pw_name); | |
137 | result->pw_passwd = alloc_buffer_maybe_copy_string (&buf, local->pw_passwd); | |
138 | result->pw_uid = local->pw_uid; | |
139 | result->pw_gid = local->pw_gid; | |
140 | result->pw_gecos = alloc_buffer_maybe_copy_string (&buf, local->pw_gecos); | |
141 | result->pw_dir = alloc_buffer_maybe_copy_string (&buf, local->pw_dir); | |
142 | result->pw_shell = alloc_buffer_maybe_copy_string (&buf, local->pw_shell); | |
143 | ||
144 | if (alloc_buffer_has_failed (&buf)) | |
145 | { | |
146 | *errnop = ERANGE; | |
147 | return NSS_STATUS_TRYAGAIN; | |
148 | } | |
149 | ||
150 | return NSS_STATUS_SUCCESS; | |
151 | } | |
c3e2f19b UD |
152 | |
153 | enum nss_status | |
ae5c498d | 154 | NAME(getpwent_r) (struct passwd *result, char *buffer, size_t buflen, |
c3e2f19b UD |
155 | int *errnop) |
156 | { | |
c3e2f19b UD |
157 | int res = NSS_STATUS_SUCCESS; |
158 | ||
ae5c498d | 159 | init(); |
c3e2f19b UD |
160 | pthread_mutex_lock (&pwd_lock); |
161 | ||
162 | if (pwd_iter >= npwd_data) | |
163 | res = NSS_STATUS_NOTFOUND; | |
164 | else | |
165 | { | |
ae5c498d | 166 | res = copy_passwd (result, &CURPWD, buffer, buflen, errnop); |
c3e2f19b UD |
167 | ++pwd_iter; |
168 | } | |
169 | ||
170 | pthread_mutex_unlock (&pwd_lock); | |
171 | ||
172 | return res; | |
173 | } | |
174 | ||
175 | ||
176 | enum nss_status | |
ae5c498d | 177 | NAME(getpwuid_r) (uid_t uid, struct passwd *result, char *buffer, |
c3e2f19b UD |
178 | size_t buflen, int *errnop) |
179 | { | |
ae5c498d | 180 | init(); |
c3e2f19b UD |
181 | for (size_t idx = 0; idx < npwd_data; ++idx) |
182 | if (pwd_data[idx].pw_uid == uid) | |
ae5c498d | 183 | return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop); |
c3e2f19b UD |
184 | |
185 | return NSS_STATUS_NOTFOUND; | |
186 | } | |
187 | ||
188 | ||
189 | enum nss_status | |
ae5c498d | 190 | NAME(getpwnam_r) (const char *name, struct passwd *result, char *buffer, |
c3e2f19b UD |
191 | size_t buflen, int *errnop) |
192 | { | |
ae5c498d | 193 | init(); |
c3e2f19b | 194 | for (size_t idx = 0; idx < npwd_data; ++idx) |
ae5c498d DD |
195 | if (strcmp (pwd_data[idx].pw_name, name) == 0) |
196 | return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop); | |
197 | ||
198 | return NSS_STATUS_NOTFOUND; | |
199 | } | |
200 | ||
201 | /* -------------------------------------------------- */ | |
202 | /* Group handling. */ | |
203 | ||
204 | static size_t grp_iter; | |
205 | #define CURGRP grp_data[grp_iter] | |
206 | ||
207 | static pthread_mutex_t grp_lock = PTHREAD_MUTEX_INITIALIZER; | |
208 | ||
209 | enum nss_status | |
210 | NAME(setgrent) (int stayopen) | |
211 | { | |
212 | init(); | |
213 | grp_iter = 0; | |
214 | return NSS_STATUS_SUCCESS; | |
215 | } | |
216 | ||
217 | ||
218 | enum nss_status | |
219 | NAME(endgrent) (void) | |
220 | { | |
221 | init(); | |
222 | return NSS_STATUS_SUCCESS; | |
223 | } | |
224 | ||
225 | static enum nss_status | |
226 | copy_group (struct group *result, struct group *local, | |
227 | char *buffer, size_t buflen, int *errnop) | |
228 | { | |
229 | struct alloc_buffer buf = alloc_buffer_create (buffer, buflen); | |
230 | char **memlist; | |
231 | int i; | |
232 | ||
233 | if (local->gr_mem) | |
234 | { | |
235 | i = 0; | |
236 | while (local->gr_mem[i]) | |
237 | ++i; | |
238 | ||
239 | memlist = alloc_buffer_alloc_array (&buf, char *, i + 1); | |
240 | ||
241 | if (memlist) { | |
242 | for (i = 0; local->gr_mem[i]; ++i) | |
243 | memlist[i] = alloc_buffer_maybe_copy_string (&buf, local->gr_mem[i]); | |
244 | memlist[i] = NULL; | |
245 | } | |
246 | ||
247 | result->gr_mem = memlist; | |
248 | } | |
249 | else | |
250 | result->gr_mem = NULL; | |
251 | ||
252 | result->gr_name = alloc_buffer_maybe_copy_string (&buf, local->gr_name); | |
253 | result->gr_passwd = alloc_buffer_maybe_copy_string (&buf, local->gr_passwd); | |
254 | result->gr_gid = local->gr_gid; | |
255 | ||
256 | if (alloc_buffer_has_failed (&buf)) | |
257 | { | |
258 | *errnop = ERANGE; | |
259 | return NSS_STATUS_TRYAGAIN; | |
260 | } | |
261 | ||
262 | return NSS_STATUS_SUCCESS; | |
263 | } | |
264 | ||
265 | ||
266 | enum nss_status | |
267 | NAME(getgrent_r) (struct group *result, char *buffer, size_t buflen, | |
268 | int *errnop) | |
269 | { | |
270 | int res = NSS_STATUS_SUCCESS; | |
271 | ||
272 | init(); | |
273 | pthread_mutex_lock (&grp_lock); | |
274 | ||
275 | if (grp_iter >= ngrp_data) | |
276 | res = NSS_STATUS_NOTFOUND; | |
277 | else | |
278 | { | |
279 | res = copy_group (result, &CURGRP, buffer, buflen, errnop); | |
280 | ++grp_iter; | |
281 | } | |
282 | ||
283 | pthread_mutex_unlock (&pwd_lock); | |
284 | ||
285 | return res; | |
286 | } | |
287 | ||
288 | ||
289 | enum nss_status | |
290 | NAME(getgrgid_r) (gid_t gid, struct group *result, char *buffer, | |
291 | size_t buflen, int *errnop) | |
292 | { | |
293 | init(); | |
294 | for (size_t idx = 0; idx < ngrp_data; ++idx) | |
295 | if (grp_data[idx].gr_gid == gid) | |
296 | return copy_group (result, &grp_data[idx], buffer, buflen, errnop); | |
297 | ||
298 | return NSS_STATUS_NOTFOUND; | |
299 | } | |
300 | ||
301 | ||
302 | enum nss_status | |
303 | NAME(getgrnam_r) (const char *name, struct group *result, char *buffer, | |
304 | size_t buflen, int *errnop) | |
305 | { | |
306 | init(); | |
307 | for (size_t idx = 0; idx < ngrp_data; ++idx) | |
c3e2f19b UD |
308 | if (strcmp (pwd_data[idx].pw_name, name) == 0) |
309 | { | |
ae5c498d | 310 | return copy_group (result, &grp_data[idx], buffer, buflen, errnop); |
c3e2f19b UD |
311 | } |
312 | ||
313 | return NSS_STATUS_NOTFOUND; | |
314 | } |