]>
Commit | Line | Data |
---|---|---|
34816665 | 1 | /* Copyright (C) 1996,1997,1998,1999,2001,2002 Free Software Foundation, Inc. |
6259ec0d UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
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. | |
6259ec0d UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
6259ec0d | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
6259ec0d UD |
19 | |
20 | #include <nss.h> | |
21 | #include <pwd.h> | |
22 | #include <errno.h> | |
23 | #include <ctype.h> | |
3996f34b | 24 | #include <fcntl.h> |
6259ec0d UD |
25 | #include <netdb.h> |
26 | #include <string.h> | |
5107cf1d | 27 | #include <bits/libc-lock.h> |
6259ec0d UD |
28 | #include <rpcsvc/yp.h> |
29 | #include <rpcsvc/ypclnt.h> | |
26dee9c4 | 30 | #include <rpcsvc/nis.h> |
26dee9c4 | 31 | #include <nsswitch.h> |
6259ec0d UD |
32 | |
33 | #include "netgroup.h" | |
26dee9c4 | 34 | #include "nss-nisplus.h" |
2d7da676 | 35 | #include "nisplus-parser.h" |
26dee9c4 | 36 | |
fc9f33e3 UD |
37 | static service_user *ni; |
38 | static bool_t use_nisplus; /* default: passwd_compat: nis */ | |
39 | static nis_name pwdtable; /* Name of the pwd table */ | |
40 | static size_t pwdtablelen; | |
6259ec0d | 41 | |
7e3be507 UD |
42 | /* Get the declaration of the parser function. */ |
43 | #define ENTNAME pwent | |
44 | #define STRUCTURE passwd | |
45 | #define EXTERN_PARSER | |
cc3fa755 | 46 | #include <nss/nss_files/files-parse.c> |
7e3be507 | 47 | |
6259ec0d UD |
48 | /* Structure for remembering -@netgroup and -user members ... */ |
49 | #define BLACKLIST_INITIAL_SIZE 512 | |
50 | #define BLACKLIST_INCREMENT 256 | |
51 | struct blacklist_t | |
52 | { | |
53 | char *data; | |
54 | int current; | |
55 | int size; | |
56 | }; | |
57 | ||
58 | struct ent_t | |
59 | { | |
60 | bool_t netgroup; | |
61 | bool_t nis; | |
62 | bool_t first; | |
63 | char *oldkey; | |
64 | int oldkeylen; | |
26dee9c4 | 65 | nis_result *result; |
6259ec0d UD |
66 | FILE *stream; |
67 | struct blacklist_t blacklist; | |
68 | struct passwd pwd; | |
69 | struct __netgrent netgrdata; | |
70 | }; | |
71 | typedef struct ent_t ent_t; | |
72 | ||
2d7da676 | 73 | static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}, |
6259ec0d UD |
74 | {NULL, NULL, 0, 0, NULL, NULL, NULL}}; |
75 | ||
76 | /* Protect global state against multiple changers. */ | |
77 | __libc_lock_define_initialized (static, lock) | |
78 | ||
79 | /* Prototypes for local functions. */ | |
80 | static void blacklist_store_name (const char *, ent_t *); | |
81 | static int in_blacklist (const char *, int, ent_t *); | |
2d7da676 | 82 | |
6259ec0d UD |
83 | static void |
84 | give_pwd_free (struct passwd *pwd) | |
85 | { | |
86 | if (pwd->pw_name != NULL) | |
87 | free (pwd->pw_name); | |
88 | if (pwd->pw_passwd != NULL) | |
89 | free (pwd->pw_passwd); | |
90 | if (pwd->pw_gecos != NULL) | |
91 | free (pwd->pw_gecos); | |
92 | if (pwd->pw_dir != NULL) | |
93 | free (pwd->pw_dir); | |
94 | if (pwd->pw_shell != NULL) | |
95 | free (pwd->pw_shell); | |
96 | ||
97 | memset (pwd, '\0', sizeof (struct passwd)); | |
98 | } | |
99 | ||
100 | static size_t | |
101 | pwd_need_buflen (struct passwd *pwd) | |
102 | { | |
103 | size_t len = 0; | |
104 | ||
105 | if (pwd->pw_passwd != NULL) | |
106 | len += strlen (pwd->pw_passwd) + 1; | |
107 | ||
108 | if (pwd->pw_gecos != NULL) | |
109 | len += strlen (pwd->pw_gecos) + 1; | |
110 | ||
111 | if (pwd->pw_dir != NULL) | |
112 | len += strlen (pwd->pw_dir) + 1; | |
113 | ||
114 | if (pwd->pw_shell != NULL) | |
115 | len += strlen (pwd->pw_shell) + 1; | |
116 | ||
117 | return len; | |
118 | } | |
119 | ||
120 | static void | |
121 | copy_pwd_changes (struct passwd *dest, struct passwd *src, | |
122 | char *buffer, size_t buflen) | |
123 | { | |
124 | if (src->pw_passwd != NULL && strlen (src->pw_passwd)) | |
125 | { | |
126 | if (buffer == NULL) | |
127 | dest->pw_passwd = strdup (src->pw_passwd); | |
128 | else if (dest->pw_passwd && | |
129 | strlen (dest->pw_passwd) >= strlen (src->pw_passwd)) | |
130 | strcpy (dest->pw_passwd, src->pw_passwd); | |
131 | else | |
132 | { | |
133 | dest->pw_passwd = buffer; | |
134 | strcpy (dest->pw_passwd, src->pw_passwd); | |
135 | buffer += strlen (dest->pw_passwd) + 1; | |
136 | buflen = buflen - (strlen (dest->pw_passwd) + 1); | |
137 | } | |
138 | } | |
139 | ||
140 | if (src->pw_gecos != NULL && strlen (src->pw_gecos)) | |
141 | { | |
142 | if (buffer == NULL) | |
143 | dest->pw_gecos = strdup (src->pw_gecos); | |
144 | else if (dest->pw_gecos && | |
145 | strlen (dest->pw_gecos) >= strlen (src->pw_gecos)) | |
146 | strcpy (dest->pw_gecos, src->pw_gecos); | |
147 | else | |
148 | { | |
149 | dest->pw_gecos = buffer; | |
150 | strcpy (dest->pw_gecos, src->pw_gecos); | |
151 | buffer += strlen (dest->pw_gecos) + 1; | |
152 | buflen = buflen - (strlen (dest->pw_gecos) + 1); | |
153 | } | |
154 | } | |
155 | if (src->pw_dir != NULL && strlen (src->pw_dir)) | |
156 | { | |
157 | if (buffer == NULL) | |
158 | dest->pw_dir = strdup (src->pw_dir); | |
159 | else if (dest->pw_dir && | |
160 | strlen (dest->pw_dir) >= strlen (src->pw_dir)) | |
161 | strcpy (dest->pw_dir, src->pw_dir); | |
162 | else | |
163 | { | |
164 | dest->pw_dir = buffer; | |
165 | strcpy (dest->pw_dir, src->pw_dir); | |
166 | buffer += strlen (dest->pw_dir) + 1; | |
167 | buflen = buflen - (strlen (dest->pw_dir) + 1); | |
168 | } | |
169 | } | |
170 | ||
171 | if (src->pw_shell != NULL && strlen (src->pw_shell)) | |
172 | { | |
173 | if (buffer == NULL) | |
174 | dest->pw_shell = strdup (src->pw_shell); | |
175 | else if (dest->pw_shell && | |
176 | strlen (dest->pw_shell) >= strlen (src->pw_shell)) | |
177 | strcpy (dest->pw_shell, src->pw_shell); | |
178 | else | |
179 | { | |
180 | dest->pw_shell = buffer; | |
181 | strcpy (dest->pw_shell, src->pw_shell); | |
182 | buffer += strlen (dest->pw_shell) + 1; | |
183 | buflen = buflen - (strlen (dest->pw_shell) + 1); | |
184 | } | |
185 | } | |
186 | } | |
187 | ||
7ef90c15 UD |
188 | static enum nss_status |
189 | insert_passwd_adjunct (char **result, int *len, char *domain, int *errnop) | |
190 | { | |
191 | char *p1, *p2, *result2, *res; | |
192 | int len2; | |
193 | size_t namelen; | |
194 | ||
195 | /* Check for adjunct style secret passwords. They can be | |
196 | recognized by a password starting with "##". */ | |
197 | p1 = strchr (*result, ':'); | |
198 | if (p1 == NULL || p1[1] != '#' || p1[2] != '#') | |
199 | return NSS_STATUS_SUCCESS; | |
200 | p2 = strchr (p1 + 3, ':'); | |
201 | ||
202 | namelen = p2 - p1 - 3; | |
203 | ||
204 | if (yp_match (domain, "passwd.adjunct.byname", &p1[3], namelen, | |
205 | &result2, &len2) == YPERR_SUCCESS) | |
206 | { | |
207 | /* We found a passwd.adjunct entry. Merge encrypted | |
208 | password therein into original result. */ | |
209 | char *encrypted = strchr (result2, ':'); | |
210 | char *endp; | |
211 | size_t restlen; | |
212 | ||
213 | if (encrypted == NULL || (endp = strchr (++encrypted, ':')) == NULL) | |
214 | { | |
215 | /* Invalid format of the entry. This never should happen | |
216 | unless the data from which the NIS table is generated is | |
217 | wrong. We simply ignore it. */ | |
218 | free (result2); | |
219 | return NSS_STATUS_SUCCESS; | |
220 | } | |
221 | ||
222 | restlen = *len - (p2 - *result); | |
223 | if ((res = malloc (namelen + restlen + (endp - encrypted) + 2)) == NULL) | |
224 | { | |
225 | free (result2); | |
7ef90c15 UD |
226 | return NSS_STATUS_TRYAGAIN; |
227 | } | |
228 | ||
229 | __mempcpy (__mempcpy (__mempcpy (__mempcpy | |
230 | (res, *result, (p1 - *result)), | |
231 | ":", 1), | |
232 | encrypted, endp - encrypted), | |
233 | p2, restlen + 1); | |
234 | ||
235 | free (result2); | |
236 | free (*result); | |
237 | *result = res; | |
238 | *len = strlen (res); | |
239 | } | |
240 | return NSS_STATUS_SUCCESS; | |
241 | } | |
242 | ||
6259ec0d UD |
243 | static enum nss_status |
244 | internal_setpwent (ent_t *ent) | |
245 | { | |
246 | enum nss_status status = NSS_STATUS_SUCCESS; | |
247 | ||
248 | ent->nis = ent->first = ent->netgroup = 0; | |
249 | ||
250 | /* If something was left over free it. */ | |
251 | if (ent->netgroup) | |
252 | __internal_endnetgrent (&ent->netgrdata); | |
253 | ||
254 | if (ent->oldkey != NULL) | |
255 | { | |
256 | free (ent->oldkey); | |
257 | ent->oldkey = NULL; | |
258 | ent->oldkeylen = 0; | |
259 | } | |
260 | ||
26dee9c4 UD |
261 | if (ent->result != NULL) |
262 | { | |
263 | nis_freeresult (ent->result); | |
264 | ent->result = NULL; | |
265 | } | |
266 | ||
2d7da676 | 267 | if (pwdtable == NULL) |
26dee9c4 | 268 | { |
cc3fa755 UD |
269 | static const char key[] = "passwd.org_dir."; |
270 | const char *local_dir = nis_local_directory (); | |
271 | size_t len_local_dir = strlen (local_dir); | |
2d7da676 | 272 | |
cc3fa755 | 273 | pwdtable = malloc (sizeof (key) + len_local_dir); |
2d7da676 | 274 | if (pwdtable == NULL) |
cc3fa755 UD |
275 | return NSS_STATUS_TRYAGAIN; |
276 | ||
277 | pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable, | |
278 | key, sizeof (key) - 1), | |
279 | local_dir, len_local_dir + 1) | |
280 | - pwdtable) - 1; | |
26dee9c4 | 281 | } |
2d7da676 | 282 | |
6259ec0d | 283 | if (ent->blacklist.data != NULL) |
bd355af0 UD |
284 | { |
285 | ent->blacklist.current = 1; | |
286 | ent->blacklist.data[0] = '|'; | |
287 | ent->blacklist.data[1] = '\0'; | |
288 | } | |
289 | else | |
290 | ent->blacklist.current = 0; | |
6259ec0d UD |
291 | |
292 | if (ent->stream == NULL) | |
293 | { | |
294 | ent->stream = fopen ("/etc/passwd", "r"); | |
295 | ||
296 | if (ent->stream == NULL) | |
297 | status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; | |
3996f34b UD |
298 | else |
299 | { | |
300 | /* We have to make sure the file is `closed on exec'. */ | |
301 | int result, flags; | |
302 | ||
303 | result = flags = fcntl (fileno (ent->stream), F_GETFD, 0); | |
304 | if (result >= 0) | |
305 | { | |
306 | flags |= FD_CLOEXEC; | |
307 | result = fcntl (fileno (ent->stream), F_SETFD, flags); | |
308 | } | |
309 | if (result < 0) | |
310 | { | |
311 | /* Something went wrong. Close the stream and return a | |
312 | failure. */ | |
313 | fclose (ent->stream); | |
314 | ent->stream = NULL; | |
315 | status = NSS_STATUS_UNAVAIL; | |
316 | } | |
317 | } | |
6259ec0d UD |
318 | } |
319 | else | |
320 | rewind (ent->stream); | |
321 | ||
322 | give_pwd_free (&ent->pwd); | |
323 | ||
324 | return status; | |
325 | } | |
326 | ||
327 | ||
328 | enum nss_status | |
51eecc4a | 329 | _nss_compat_setpwent (int stayopen) |
6259ec0d UD |
330 | { |
331 | enum nss_status result; | |
332 | ||
333 | __libc_lock_lock (lock); | |
334 | ||
26dee9c4 UD |
335 | if (ni == NULL) |
336 | { | |
337 | __nss_database_lookup ("passwd_compat", NULL, "nis", &ni); | |
338 | use_nisplus = (strcmp (ni->name, "nisplus") == 0); | |
339 | } | |
340 | ||
6259ec0d UD |
341 | result = internal_setpwent (&ext_ent); |
342 | ||
343 | __libc_lock_unlock (lock); | |
344 | ||
345 | return result; | |
346 | } | |
347 | ||
348 | ||
349 | static enum nss_status | |
350 | internal_endpwent (ent_t *ent) | |
351 | { | |
352 | if (ent->stream != NULL) | |
353 | { | |
354 | fclose (ent->stream); | |
355 | ent->stream = NULL; | |
356 | } | |
357 | ||
60c96635 UD |
358 | if (ent->netgroup) |
359 | __internal_endnetgrent (&ent->netgrdata); | |
3996f34b | 360 | |
6259ec0d UD |
361 | ent->nis = ent->first = ent->netgroup = 0; |
362 | ||
363 | if (ent->oldkey != NULL) | |
364 | { | |
365 | free (ent->oldkey); | |
366 | ent->oldkey = NULL; | |
367 | ent->oldkeylen = 0; | |
368 | } | |
369 | ||
26dee9c4 UD |
370 | if (ent->result != NULL) |
371 | { | |
372 | nis_freeresult (ent->result); | |
373 | ent->result = NULL; | |
374 | } | |
375 | ||
6259ec0d | 376 | if (ent->blacklist.data != NULL) |
bd355af0 UD |
377 | { |
378 | ent->blacklist.current = 1; | |
379 | ent->blacklist.data[0] = '|'; | |
380 | ent->blacklist.data[1] = '\0'; | |
381 | } | |
382 | else | |
383 | ent->blacklist.current = 0; | |
6259ec0d UD |
384 | |
385 | give_pwd_free (&ent->pwd); | |
386 | ||
387 | return NSS_STATUS_SUCCESS; | |
388 | } | |
389 | ||
390 | enum nss_status | |
391 | _nss_compat_endpwent (void) | |
392 | { | |
393 | enum nss_status result; | |
394 | ||
395 | __libc_lock_lock (lock); | |
396 | ||
6259ec0d UD |
397 | result = internal_endpwent (&ext_ent); |
398 | ||
399 | __libc_lock_unlock (lock); | |
400 | ||
401 | return result; | |
402 | } | |
403 | ||
404 | static enum nss_status | |
cc3fa755 | 405 | getpwent_next_nis_netgr (const char *name, struct passwd *result, ent_t *ent, |
d71b808a | 406 | char *group, char *buffer, size_t buflen, int *errnop) |
6259ec0d | 407 | { |
7e3be507 | 408 | struct parser_data *data = (void *) buffer; |
6259ec0d | 409 | char *ypdomain, *host, *user, *domain, *outval, *p, *p2; |
f8b87ef0 UD |
410 | int status, outvallen; |
411 | size_t p2len; | |
c131718c | 412 | |
6259ec0d UD |
413 | if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS) |
414 | { | |
415 | ent->netgroup = 0; | |
416 | ent->first = 0; | |
417 | give_pwd_free (&ent->pwd); | |
418 | return NSS_STATUS_UNAVAIL; | |
419 | } | |
420 | ||
421 | if (ent->first == TRUE) | |
422 | { | |
63551311 | 423 | memset (&ent->netgrdata, 0, sizeof (struct __netgrent)); |
6259ec0d UD |
424 | __internal_setnetgrent (group, &ent->netgrdata); |
425 | ent->first = FALSE; | |
426 | } | |
427 | ||
428 | while (1) | |
429 | { | |
60c96635 UD |
430 | char *saved_cursor; |
431 | int parse_res; | |
432 | ||
433 | saved_cursor = ent->netgrdata.cursor; | |
7e3be507 | 434 | status = __internal_getnetgrent_r (&host, &user, &domain, |
d71b808a UD |
435 | &ent->netgrdata, buffer, buflen, |
436 | errnop); | |
6259ec0d UD |
437 | if (status != 1) |
438 | { | |
439 | __internal_endnetgrent (&ent->netgrdata); | |
440 | ent->netgroup = 0; | |
441 | give_pwd_free (&ent->pwd); | |
442 | return NSS_STATUS_RETURN; | |
443 | } | |
444 | ||
445 | if (user == NULL || user[0] == '-') | |
446 | continue; | |
447 | ||
448 | if (domain != NULL && strcmp (ypdomain, domain) != 0) | |
449 | continue; | |
450 | ||
6591c335 | 451 | /* If name != NULL, we are called from getpwnam. */ |
cc3fa755 UD |
452 | if (name != NULL) |
453 | if (strcmp (user, name) != 0) | |
454 | continue; | |
455 | ||
6259ec0d UD |
456 | if (yp_match (ypdomain, "passwd.byname", user, |
457 | strlen (user), &outval, &outvallen) | |
458 | != YPERR_SUCCESS) | |
459 | continue; | |
460 | ||
7ef90c15 UD |
461 | if (insert_passwd_adjunct (&outval, &outvallen, ypdomain, errnop) |
462 | != NSS_STATUS_SUCCESS) | |
463 | { | |
464 | free (outval); | |
465 | return NSS_STATUS_TRYAGAIN; | |
466 | } | |
467 | ||
6259ec0d UD |
468 | p2len = pwd_need_buflen (&ent->pwd); |
469 | if (p2len > buflen) | |
470 | { | |
6591c335 | 471 | free (outval); |
d71b808a | 472 | *errnop = ERANGE; |
6259ec0d UD |
473 | return NSS_STATUS_TRYAGAIN; |
474 | } | |
475 | p2 = buffer + (buflen - p2len); | |
476 | buflen -= p2len; | |
6591c335 UD |
477 | |
478 | if (buflen < ((size_t) outvallen + 1)) | |
479 | { | |
480 | free (outval); | |
481 | *errnop = ERANGE; | |
482 | return NSS_STATUS_TRYAGAIN; | |
483 | } | |
6259ec0d | 484 | p = strncpy (buffer, outval, buflen); |
6591c335 | 485 | |
6259ec0d UD |
486 | while (isspace (*p)) |
487 | p++; | |
488 | free (outval); | |
d71b808a UD |
489 | parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop); |
490 | if (parse_res == -1) | |
60c96635 UD |
491 | { |
492 | ent->netgrdata.cursor = saved_cursor; | |
493 | return NSS_STATUS_TRYAGAIN; | |
494 | } | |
495 | ||
04c216a8 UD |
496 | if (parse_res && !in_blacklist (result->pw_name, |
497 | strlen (result->pw_name), ent)) | |
6259ec0d | 498 | { |
cc3fa755 UD |
499 | /* Store the User in the blacklist for the "+" at the end of |
500 | /etc/passwd */ | |
501 | blacklist_store_name (result->pw_name, ent); | |
6259ec0d UD |
502 | copy_pwd_changes (result, &ent->pwd, p2, p2len); |
503 | break; | |
504 | } | |
505 | } | |
506 | ||
507 | return NSS_STATUS_SUCCESS; | |
508 | } | |
509 | ||
26dee9c4 | 510 | static enum nss_status |
cc3fa755 UD |
511 | getpwent_next_nisplus_netgr (const char *name, struct passwd *result, |
512 | ent_t *ent, char *group, char *buffer, | |
d71b808a | 513 | size_t buflen, int *errnop) |
26dee9c4 UD |
514 | { |
515 | char *ypdomain, *host, *user, *domain, *p2; | |
516 | int status, parse_res; | |
517 | size_t p2len; | |
518 | nis_result *nisres; | |
c131718c UD |
519 | |
520 | /* Maybe we should use domainname here ? We need the current | |
26dee9c4 UD |
521 | domainname for the domain field in netgroups */ |
522 | if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS) | |
523 | { | |
524 | ent->netgroup = 0; | |
525 | ent->first = 0; | |
526 | give_pwd_free (&ent->pwd); | |
527 | return NSS_STATUS_UNAVAIL; | |
528 | } | |
529 | ||
530 | if (ent->first == TRUE) | |
531 | { | |
532 | bzero (&ent->netgrdata, sizeof (struct __netgrent)); | |
533 | __internal_setnetgrent (group, &ent->netgrdata); | |
534 | ent->first = FALSE; | |
535 | } | |
536 | ||
537 | while (1) | |
538 | { | |
60c96635 UD |
539 | char *saved_cursor; |
540 | ||
541 | saved_cursor = ent->netgrdata.cursor; | |
26dee9c4 | 542 | status = __internal_getnetgrent_r (&host, &user, &domain, |
d71b808a UD |
543 | &ent->netgrdata, buffer, buflen, |
544 | errnop); | |
26dee9c4 UD |
545 | if (status != 1) |
546 | { | |
547 | __internal_endnetgrent (&ent->netgrdata); | |
548 | ent->netgroup = 0; | |
549 | give_pwd_free (&ent->pwd); | |
550 | return NSS_STATUS_RETURN; | |
551 | } | |
3996f34b | 552 | |
26dee9c4 UD |
553 | if (user == NULL || user[0] == '-') |
554 | continue; | |
3996f34b | 555 | |
26dee9c4 UD |
556 | if (domain != NULL && strcmp (ypdomain, domain) != 0) |
557 | continue; | |
3996f34b | 558 | |
cc3fa755 UD |
559 | /* If name != NULL, we are called from getpwnam */ |
560 | if (name != NULL) | |
561 | if (strcmp (user, name) != 0) | |
562 | continue; | |
563 | ||
26dee9c4 UD |
564 | p2len = pwd_need_buflen (&ent->pwd); |
565 | if (p2len > buflen) | |
566 | { | |
d71b808a | 567 | *errnop = ERANGE; |
26dee9c4 UD |
568 | return NSS_STATUS_TRYAGAIN; |
569 | } | |
570 | p2 = buffer + (buflen - p2len); | |
571 | buflen -= p2len; | |
c131718c | 572 | { |
2d7da676 UD |
573 | char buf[strlen (user) + 30 + pwdtablelen]; |
574 | sprintf(buf, "[name=%s],%s", user, pwdtable); | |
575 | nisres = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); | |
26dee9c4 UD |
576 | } |
577 | if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS) | |
578 | { | |
579 | nis_freeresult (nisres); | |
580 | continue; | |
581 | } | |
d71b808a UD |
582 | parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer, |
583 | buflen, errnop); | |
584 | if (parse_res == -1) | |
60c96635 UD |
585 | { |
586 | nis_freeresult (nisres); | |
587 | ent->netgrdata.cursor = saved_cursor; | |
d71b808a | 588 | *errnop = ERANGE; |
60c96635 UD |
589 | return NSS_STATUS_TRYAGAIN; |
590 | } | |
26dee9c4 | 591 | nis_freeresult (nisres); |
c131718c | 592 | |
04c216a8 UD |
593 | if (parse_res && !in_blacklist (result->pw_name, |
594 | strlen (result->pw_name), ent)) | |
26dee9c4 | 595 | { |
cc3fa755 UD |
596 | /* Store the User in the blacklist for the "+" at the end of |
597 | /etc/passwd */ | |
598 | blacklist_store_name (result->pw_name, ent); | |
26dee9c4 UD |
599 | copy_pwd_changes (result, &ent->pwd, p2, p2len); |
600 | break; | |
601 | } | |
602 | } | |
603 | ||
604 | return NSS_STATUS_SUCCESS; | |
605 | } | |
606 | ||
bd355af0 | 607 | /* get the next user from NIS+ (+ entry) */ |
26dee9c4 UD |
608 | static enum nss_status |
609 | getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer, | |
d71b808a | 610 | size_t buflen, int *errnop) |
26dee9c4 UD |
611 | { |
612 | int parse_res; | |
613 | size_t p2len; | |
614 | char *p2; | |
615 | ||
26dee9c4 UD |
616 | p2len = pwd_need_buflen (&ent->pwd); |
617 | if (p2len > buflen) | |
618 | { | |
d71b808a | 619 | *errnop = ERANGE; |
26dee9c4 UD |
620 | return NSS_STATUS_TRYAGAIN; |
621 | } | |
622 | p2 = buffer + (buflen - p2len); | |
623 | buflen -= p2len; | |
624 | do | |
625 | { | |
60c96635 UD |
626 | bool_t saved_first; |
627 | nis_result *saved_res; | |
628 | ||
26dee9c4 UD |
629 | if (ent->first) |
630 | { | |
60c96635 UD |
631 | saved_first = TRUE; |
632 | saved_res = ent->result; | |
633 | ||
d71b808a | 634 | ent->result = nis_first_entry (pwdtable); |
26dee9c4 UD |
635 | if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS) |
636 | { | |
637 | ent->nis = 0; | |
638 | give_pwd_free (&ent->pwd); | |
639 | return niserr2nss (ent->result->status); | |
640 | } | |
641 | ent->first = FALSE; | |
642 | } | |
643 | else | |
644 | { | |
645 | nis_result *res; | |
c131718c | 646 | |
d71b808a | 647 | res = nis_next_entry (pwdtable, &ent->result->cookie); |
60c96635 UD |
648 | saved_res = ent->result; |
649 | saved_first = FALSE; | |
26dee9c4 UD |
650 | ent->result = res; |
651 | if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS) | |
652 | { | |
2d7da676 | 653 | ent->nis = 0; |
60c96635 | 654 | nis_freeresult (saved_res); |
2d7da676 UD |
655 | give_pwd_free (&ent->pwd); |
656 | return niserr2nss (ent->result->status); | |
26dee9c4 UD |
657 | } |
658 | } | |
d71b808a UD |
659 | parse_res = _nss_nisplus_parse_pwent (ent->result, result, buffer, |
660 | buflen, errnop); | |
661 | if (parse_res == -1) | |
60c96635 UD |
662 | { |
663 | nis_freeresult (ent->result); | |
664 | ent->result = saved_res; | |
665 | ent->first = saved_first; | |
d71b808a | 666 | *errnop = ERANGE; |
60c96635 UD |
667 | return NSS_STATUS_TRYAGAIN; |
668 | } | |
669 | else | |
670 | { | |
671 | if (!saved_first) | |
672 | nis_freeresult (saved_res); | |
673 | } | |
3996f34b | 674 | |
c131718c | 675 | if (parse_res && |
26dee9c4 UD |
676 | in_blacklist (result->pw_name, strlen (result->pw_name), ent)) |
677 | parse_res = 0; /* if result->pw_name in blacklist,search next entry */ | |
678 | } | |
679 | while (!parse_res); | |
c131718c | 680 | |
26dee9c4 | 681 | copy_pwd_changes (result, &ent->pwd, p2, p2len); |
c131718c | 682 | |
26dee9c4 UD |
683 | return NSS_STATUS_SUCCESS; |
684 | } | |
685 | ||
6259ec0d UD |
686 | static enum nss_status |
687 | getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer, | |
d71b808a | 688 | size_t buflen, int *errnop) |
6259ec0d | 689 | { |
7e3be507 | 690 | struct parser_data *data = (void *) buffer; |
6259ec0d | 691 | char *domain, *outkey, *outval, *p, *p2; |
26dee9c4 | 692 | int outkeylen, outvallen, parse_res; |
f8b87ef0 | 693 | size_t p2len; |
6259ec0d UD |
694 | |
695 | if (yp_get_default_domain (&domain) != YPERR_SUCCESS) | |
696 | { | |
697 | ent->nis = 0; | |
698 | give_pwd_free (&ent->pwd); | |
699 | return NSS_STATUS_UNAVAIL; | |
700 | } | |
701 | ||
702 | p2len = pwd_need_buflen (&ent->pwd); | |
703 | if (p2len > buflen) | |
704 | { | |
d71b808a | 705 | *errnop = ERANGE; |
6259ec0d UD |
706 | return NSS_STATUS_TRYAGAIN; |
707 | } | |
708 | p2 = buffer + (buflen - p2len); | |
709 | buflen -= p2len; | |
710 | do | |
711 | { | |
60c96635 UD |
712 | bool_t saved_first; |
713 | char *saved_oldkey; | |
714 | int saved_oldlen; | |
3996f34b | 715 | |
6259ec0d UD |
716 | if (ent->first) |
717 | { | |
718 | if (yp_first (domain, "passwd.byname", &outkey, &outkeylen, | |
719 | &outval, &outvallen) != YPERR_SUCCESS) | |
720 | { | |
721 | ent->nis = 0; | |
722 | give_pwd_free (&ent->pwd); | |
723 | return NSS_STATUS_UNAVAIL; | |
724 | } | |
3996f34b | 725 | |
7ef90c15 UD |
726 | if (insert_passwd_adjunct (&outval, &outvallen, domain, errnop) != |
727 | NSS_STATUS_SUCCESS) | |
728 | { | |
729 | free (outval); | |
730 | return NSS_STATUS_TRYAGAIN; | |
731 | } | |
732 | ||
6591c335 UD |
733 | if (buflen < ((size_t) outvallen + 1)) |
734 | { | |
735 | free (outval); | |
736 | *errnop = ERANGE; | |
737 | return NSS_STATUS_TRYAGAIN; | |
738 | } | |
739 | ||
60c96635 UD |
740 | saved_first = TRUE; |
741 | saved_oldkey = ent->oldkey; | |
742 | saved_oldlen = ent->oldkeylen; | |
6259ec0d UD |
743 | ent->oldkey = outkey; |
744 | ent->oldkeylen = outkeylen; | |
745 | ent->first = FALSE; | |
746 | } | |
747 | else | |
748 | { | |
749 | if (yp_next (domain, "passwd.byname", ent->oldkey, ent->oldkeylen, | |
750 | &outkey, &outkeylen, &outval, &outvallen) | |
751 | != YPERR_SUCCESS) | |
752 | { | |
753 | ent->nis = 0; | |
754 | give_pwd_free (&ent->pwd); | |
755 | return NSS_STATUS_NOTFOUND; | |
756 | } | |
757 | ||
7ef90c15 UD |
758 | if (insert_passwd_adjunct (&outval, &outvallen, domain, errnop) |
759 | != NSS_STATUS_SUCCESS) | |
760 | { | |
761 | free (outval); | |
762 | return NSS_STATUS_TRYAGAIN; | |
763 | } | |
764 | ||
6591c335 UD |
765 | if (buflen < ((size_t) outvallen + 1)) |
766 | { | |
767 | free (outval); | |
768 | *errnop = ERANGE; | |
769 | return NSS_STATUS_TRYAGAIN; | |
770 | } | |
771 | ||
60c96635 UD |
772 | saved_first = FALSE; |
773 | saved_oldkey = ent->oldkey; | |
774 | saved_oldlen = ent->oldkeylen; | |
6259ec0d UD |
775 | ent->oldkey = outkey; |
776 | ent->oldkeylen = outkeylen; | |
777 | } | |
778 | ||
779 | /* Copy the found data to our buffer */ | |
780 | p = strncpy (buffer, outval, buflen); | |
781 | ||
782 | /* ...and free the data. */ | |
783 | free (outval); | |
784 | ||
785 | while (isspace (*p)) | |
786 | ++p; | |
d71b808a UD |
787 | parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop); |
788 | if (parse_res == -1) | |
60c96635 UD |
789 | { |
790 | free (ent->oldkey); | |
791 | ent->oldkey = saved_oldkey; | |
792 | ent->oldkeylen = saved_oldlen; | |
793 | ent->first = saved_first; | |
d71b808a | 794 | *errnop = ERANGE; |
60c96635 UD |
795 | return NSS_STATUS_TRYAGAIN; |
796 | } | |
797 | else | |
798 | { | |
799 | if (!saved_first) | |
800 | free (saved_oldkey); | |
801 | } | |
d71b808a UD |
802 | if (parse_res |
803 | && in_blacklist (result->pw_name, strlen (result->pw_name), ent)) | |
26dee9c4 | 804 | parse_res = 0; |
6259ec0d | 805 | } |
26dee9c4 | 806 | while (!parse_res); |
6259ec0d UD |
807 | |
808 | copy_pwd_changes (result, &ent->pwd, p2, p2len); | |
809 | ||
26dee9c4 | 810 | return NSS_STATUS_SUCCESS; |
6259ec0d UD |
811 | } |
812 | ||
26dee9c4 UD |
813 | /* This function handle the +user entrys in /etc/passwd */ |
814 | static enum nss_status | |
04c216a8 UD |
815 | getpwnam_plususer (const char *name, struct passwd *result, ent_t *ent, |
816 | char *buffer, size_t buflen, int *errnop) | |
26dee9c4 UD |
817 | { |
818 | struct parser_data *data = (void *) buffer; | |
819 | struct passwd pwd; | |
820 | int parse_res; | |
821 | char *p; | |
822 | size_t plen; | |
c131718c | 823 | |
26dee9c4 | 824 | memset (&pwd, '\0', sizeof (struct passwd)); |
c131718c | 825 | |
26dee9c4 | 826 | copy_pwd_changes (&pwd, result, NULL, 0); |
c131718c | 827 | |
26dee9c4 UD |
828 | plen = pwd_need_buflen (&pwd); |
829 | if (plen > buflen) | |
830 | { | |
d71b808a | 831 | *errnop = ERANGE; |
26dee9c4 UD |
832 | return NSS_STATUS_TRYAGAIN; |
833 | } | |
834 | p = buffer + (buflen - plen); | |
835 | buflen -= plen; | |
c131718c | 836 | |
26dee9c4 UD |
837 | if (use_nisplus) /* Do the NIS+ query here */ |
838 | { | |
839 | nis_result *res; | |
cc3fa755 | 840 | char buf[strlen (name) + 24 + pwdtablelen]; |
c131718c | 841 | |
cc3fa755 | 842 | sprintf(buf, "[name=%s],%s", name, pwdtable); |
2d7da676 | 843 | res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
26dee9c4 UD |
844 | if (niserr2nss (res->status) != NSS_STATUS_SUCCESS) |
845 | { | |
846 | enum nss_status status = niserr2nss (res->status); | |
c131718c | 847 | |
26dee9c4 UD |
848 | nis_freeresult (res); |
849 | return status; | |
850 | } | |
d71b808a UD |
851 | parse_res = _nss_nisplus_parse_pwent (res, result, buffer, |
852 | buflen, errnop); | |
04c216a8 UD |
853 | |
854 | nis_freeresult (res); | |
855 | ||
d71b808a | 856 | if (parse_res == -1) |
60c96635 | 857 | { |
d71b808a | 858 | *errnop = ERANGE; |
60c96635 UD |
859 | return NSS_STATUS_TRYAGAIN; |
860 | } | |
04c216a8 UD |
861 | |
862 | if (in_blacklist (result->pw_name, strlen (result->pw_name), ent)) | |
34816665 | 863 | return NSS_STATUS_NOTFOUND; |
26dee9c4 UD |
864 | } |
865 | else /* Use NIS */ | |
866 | { | |
cc3fa755 | 867 | char *domain, *outval, *ptr; |
26dee9c4 | 868 | int outvallen; |
3996f34b | 869 | |
26dee9c4 | 870 | if (yp_get_default_domain (&domain) != YPERR_SUCCESS) |
34816665 | 871 | return NSS_STATUS_NOTFOUND; |
3996f34b | 872 | |
cc3fa755 | 873 | if (yp_match (domain, "passwd.byname", name, strlen (name), |
bd355af0 | 874 | &outval, &outvallen) != YPERR_SUCCESS) |
34816665 | 875 | return NSS_STATUS_NOTFOUND; |
bd355af0 | 876 | |
7ef90c15 UD |
877 | if (insert_passwd_adjunct (&outval, &outvallen, domain, errnop) |
878 | != NSS_STATUS_SUCCESS) | |
879 | { | |
880 | free (outval); | |
881 | return NSS_STATUS_TRYAGAIN; | |
882 | } | |
883 | ||
6591c335 UD |
884 | if (buflen < ((size_t) outvallen + 1)) |
885 | { | |
886 | free (outval); | |
887 | *errnop = ERANGE; | |
888 | return NSS_STATUS_TRYAGAIN; | |
889 | } | |
04c216a8 | 890 | |
6591c335 | 891 | ptr = strncpy (buffer, outval, buflen); |
26dee9c4 | 892 | free (outval); |
04c216a8 | 893 | |
cc3fa755 UD |
894 | while (isspace (*ptr)) |
895 | ptr++; | |
04c216a8 | 896 | |
d71b808a UD |
897 | parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop); |
898 | if (parse_res == -1) | |
899 | return NSS_STATUS_TRYAGAIN; | |
04c216a8 UD |
900 | |
901 | if (in_blacklist (result->pw_name, strlen (result->pw_name), ent)) | |
34816665 | 902 | return NSS_STATUS_NOTFOUND; |
26dee9c4 | 903 | } |
c131718c | 904 | |
60c96635 | 905 | if (parse_res > 0) |
26dee9c4 UD |
906 | { |
907 | copy_pwd_changes (result, &pwd, p, plen); | |
908 | give_pwd_free (&pwd); | |
909 | /* We found the entry. */ | |
910 | return NSS_STATUS_SUCCESS; | |
911 | } | |
912 | else | |
913 | { | |
914 | /* Give buffer the old len back */ | |
915 | buflen += plen; | |
916 | give_pwd_free (&pwd); | |
917 | } | |
918 | return NSS_STATUS_RETURN; | |
919 | } | |
6259ec0d UD |
920 | |
921 | static enum nss_status | |
922 | getpwent_next_file (struct passwd *result, ent_t *ent, | |
d71b808a | 923 | char *buffer, size_t buflen, int *errnop) |
6259ec0d | 924 | { |
7e3be507 | 925 | struct parser_data *data = (void *) buffer; |
6259ec0d UD |
926 | while (1) |
927 | { | |
60c96635 | 928 | fpos_t pos; |
26dee9c4 | 929 | char *p; |
60c96635 | 930 | int parse_res; |
6259ec0d UD |
931 | |
932 | do | |
933 | { | |
60c96635 | 934 | fgetpos (ent->stream, &pos); |
af69217f | 935 | buffer[buflen - 1] = '\xff'; |
6259ec0d | 936 | p = fgets (buffer, buflen, ent->stream); |
af69217f | 937 | if (p == NULL && feof (ent->stream)) |
34816665 UD |
938 | return NSS_STATUS_NOTFOUND; |
939 | ||
af69217f | 940 | if (p == NULL || buffer[buflen - 1] != '\xff') |
d71b808a | 941 | { |
af69217f UD |
942 | fsetpos (ent->stream, &pos); |
943 | *errnop = ERANGE; | |
944 | return NSS_STATUS_TRYAGAIN; | |
d71b808a | 945 | } |
6259ec0d UD |
946 | |
947 | /* Terminate the line for any case. */ | |
948 | buffer[buflen - 1] = '\0'; | |
949 | ||
950 | /* Skip leading blanks. */ | |
951 | while (isspace (*p)) | |
952 | ++p; | |
953 | } | |
954 | while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ | |
955 | /* Parse the line. If it is invalid, loop to | |
956 | get the next line of the file to parse. */ | |
d71b808a UD |
957 | !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, |
958 | errnop))); | |
60c96635 UD |
959 | |
960 | if (parse_res == -1) | |
961 | { | |
962 | /* The parser ran out of space. */ | |
963 | fsetpos (ent->stream, &pos); | |
d71b808a | 964 | *errnop = ERANGE; |
60c96635 UD |
965 | return NSS_STATUS_TRYAGAIN; |
966 | } | |
6259ec0d UD |
967 | |
968 | if (result->pw_name[0] != '+' && result->pw_name[0] != '-') | |
969 | /* This is a real entry. */ | |
970 | break; | |
971 | ||
972 | /* -@netgroup */ | |
973 | if (result->pw_name[0] == '-' && result->pw_name[1] == '@' | |
974 | && result->pw_name[2] != '\0') | |
975 | { | |
d71b808a | 976 | /* XXX Do not use fixed length buffer. */ |
c131718c | 977 | char buf2[1024]; |
6259ec0d | 978 | char *user, *host, *domain; |
c131718c | 979 | struct __netgrent netgrdata; |
6259ec0d | 980 | |
c131718c UD |
981 | bzero (&netgrdata, sizeof (struct __netgrent)); |
982 | __internal_setnetgrent (&result->pw_name[2], &netgrdata); | |
d71b808a UD |
983 | while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata, |
984 | buf2, sizeof (buf2), errnop)) | |
6259ec0d UD |
985 | { |
986 | if (user != NULL && user[0] != '-') | |
987 | blacklist_store_name (user, ent); | |
988 | } | |
c131718c | 989 | __internal_endnetgrent (&netgrdata); |
6259ec0d UD |
990 | continue; |
991 | } | |
992 | ||
993 | /* +@netgroup */ | |
994 | if (result->pw_name[0] == '+' && result->pw_name[1] == '@' | |
995 | && result->pw_name[2] != '\0') | |
996 | { | |
04c216a8 | 997 | enum nss_status status; |
6259ec0d UD |
998 | |
999 | ent->netgroup = TRUE; | |
1000 | ent->first = TRUE; | |
1001 | copy_pwd_changes (&ent->pwd, result, NULL, 0); | |
1002 | ||
cc3fa755 UD |
1003 | if (use_nisplus) |
1004 | status = getpwent_next_nisplus_netgr (NULL, result, ent, | |
1005 | &result->pw_name[2], | |
d71b808a | 1006 | buffer, buflen, errnop); |
cc3fa755 UD |
1007 | else |
1008 | status = getpwent_next_nis_netgr (NULL, result, ent, | |
1009 | &result->pw_name[2], | |
d71b808a | 1010 | buffer, buflen, errnop); |
6259ec0d UD |
1011 | if (status == NSS_STATUS_RETURN) |
1012 | continue; | |
1013 | else | |
34816665 | 1014 | return status; |
6259ec0d UD |
1015 | } |
1016 | ||
1017 | /* -user */ | |
1018 | if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' | |
1019 | && result->pw_name[1] != '@') | |
1020 | { | |
1021 | blacklist_store_name (&result->pw_name[1], ent); | |
1022 | continue; | |
1023 | } | |
1024 | ||
1025 | /* +user */ | |
1026 | if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' | |
1027 | && result->pw_name[1] != '@') | |
1028 | { | |
04c216a8 | 1029 | char buf[strlen (result->pw_name)]; |
26dee9c4 | 1030 | enum nss_status status; |
c131718c | 1031 | |
cc3fa755 UD |
1032 | /* Store the User in the blacklist for the "+" at the end of |
1033 | /etc/passwd */ | |
04c216a8 UD |
1034 | strcpy (buf, &result->pw_name[1]); |
1035 | status = getpwnam_plususer (&result->pw_name[1], result, ent, | |
1036 | buffer, buflen, errnop); | |
1037 | blacklist_store_name (buf, ent); | |
1038 | ||
26dee9c4 UD |
1039 | if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ |
1040 | break; | |
6259ec0d | 1041 | else |
bd355af0 UD |
1042 | if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */ |
1043 | || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */ | |
26dee9c4 UD |
1044 | continue; |
1045 | else | |
d71b808a UD |
1046 | { |
1047 | if (status == NSS_STATUS_TRYAGAIN) | |
1048 | { | |
1049 | /* The parser ran out of space */ | |
1050 | fsetpos (ent->stream, &pos); | |
1051 | *errnop = ERANGE; | |
1052 | } | |
1053 | return status; | |
1054 | } | |
6259ec0d UD |
1055 | } |
1056 | ||
1057 | /* +:... */ | |
1058 | if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') | |
1059 | { | |
1060 | ent->nis = TRUE; | |
1061 | ent->first = TRUE; | |
1062 | copy_pwd_changes (&ent->pwd, result, NULL, 0); | |
1063 | ||
26dee9c4 | 1064 | if (use_nisplus) |
d71b808a | 1065 | return getpwent_next_nisplus (result, ent, buffer, buflen, errnop); |
26dee9c4 | 1066 | else |
d71b808a | 1067 | return getpwent_next_nis (result, ent, buffer, buflen, errnop); |
6259ec0d UD |
1068 | } |
1069 | } | |
1070 | ||
1071 | return NSS_STATUS_SUCCESS; | |
1072 | } | |
1073 | ||
1074 | ||
1075 | static enum nss_status | |
1076 | internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer, | |
d71b808a | 1077 | size_t buflen, int *errnop) |
6259ec0d UD |
1078 | { |
1079 | if (ent->netgroup) | |
1080 | { | |
04c216a8 | 1081 | enum nss_status status; |
6259ec0d UD |
1082 | |
1083 | /* We are searching members in a netgroup */ | |
1084 | /* Since this is not the first call, we don't need the group name */ | |
cc3fa755 UD |
1085 | if (use_nisplus) |
1086 | status = getpwent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer, | |
d71b808a | 1087 | buflen, errnop); |
cc3fa755 | 1088 | else |
d71b808a UD |
1089 | status = getpwent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen, |
1090 | errnop); | |
6259ec0d | 1091 | if (status == NSS_STATUS_RETURN) |
d71b808a | 1092 | return getpwent_next_file (pw, ent, buffer, buflen, errnop); |
6259ec0d UD |
1093 | else |
1094 | return status; | |
1095 | } | |
6259ec0d | 1096 | else |
cc3fa755 UD |
1097 | if (ent->nis) |
1098 | { | |
1099 | if (use_nisplus) | |
d71b808a | 1100 | return getpwent_next_nisplus (pw, ent, buffer, buflen, errnop); |
cc3fa755 | 1101 | else |
d71b808a | 1102 | return getpwent_next_nis (pw, ent, buffer, buflen, errnop); |
cc3fa755 UD |
1103 | } |
1104 | else | |
d71b808a | 1105 | return getpwent_next_file (pw, ent, buffer, buflen, errnop); |
6259ec0d UD |
1106 | } |
1107 | ||
1108 | enum nss_status | |
d71b808a UD |
1109 | _nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, |
1110 | int *errnop) | |
6259ec0d UD |
1111 | { |
1112 | enum nss_status status = NSS_STATUS_SUCCESS; | |
1113 | ||
1114 | __libc_lock_lock (lock); | |
1115 | ||
26dee9c4 UD |
1116 | if (ni == NULL) |
1117 | { | |
1118 | __nss_database_lookup ("passwd_compat", NULL, "nis", &ni); | |
1119 | use_nisplus = (strcmp (ni->name, "nisplus") == 0); | |
1120 | } | |
1121 | ||
6259ec0d UD |
1122 | /* Be prepared that the setpwent function was not called before. */ |
1123 | if (ext_ent.stream == NULL) | |
1124 | status = internal_setpwent (&ext_ent); | |
1125 | ||
1126 | if (status == NSS_STATUS_SUCCESS) | |
d71b808a | 1127 | status = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop); |
6259ec0d UD |
1128 | |
1129 | __libc_lock_unlock (lock); | |
1130 | ||
1131 | return status; | |
1132 | } | |
1133 | ||
cc3fa755 UD |
1134 | /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ |
1135 | static enum nss_status | |
1136 | internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent, | |
d71b808a | 1137 | char *buffer, size_t buflen, int *errnop) |
cc3fa755 UD |
1138 | { |
1139 | struct parser_data *data = (void *) buffer; | |
1140 | ||
1141 | while (1) | |
1142 | { | |
1143 | fpos_t pos; | |
1144 | char *p; | |
1145 | int parse_res; | |
1146 | ||
1147 | do | |
1148 | { | |
1149 | fgetpos (ent->stream, &pos); | |
af69217f | 1150 | buffer[buflen - 1] = '\xff'; |
cc3fa755 | 1151 | p = fgets (buffer, buflen, ent->stream); |
af69217f | 1152 | if (p == NULL && feof (ent->stream)) |
0c6cee5d | 1153 | { |
0c6cee5d UD |
1154 | return NSS_STATUS_NOTFOUND; |
1155 | } | |
af69217f | 1156 | if (p == NULL || buffer[buflen - 1] != '\xff') |
cc3fa755 | 1157 | { |
af69217f UD |
1158 | fsetpos (ent->stream, &pos); |
1159 | *errnop = ERANGE; | |
1160 | return NSS_STATUS_TRYAGAIN; | |
cc3fa755 UD |
1161 | } |
1162 | ||
1163 | /* Terminate the line for any case. */ | |
1164 | buffer[buflen - 1] = '\0'; | |
1165 | ||
1166 | /* Skip leading blanks. */ | |
1167 | while (isspace (*p)) | |
1168 | ++p; | |
1169 | } | |
1170 | while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ | |
1171 | /* Parse the line. If it is invalid, loop to | |
1172 | get the next line of the file to parse. */ | |
d71b808a UD |
1173 | !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, |
1174 | errnop))); | |
cc3fa755 UD |
1175 | |
1176 | if (parse_res == -1) | |
1177 | { | |
1178 | /* The parser ran out of space. */ | |
1179 | fsetpos (ent->stream, &pos); | |
d71b808a | 1180 | *errnop = ERANGE; |
cc3fa755 UD |
1181 | return NSS_STATUS_TRYAGAIN; |
1182 | } | |
1183 | ||
1184 | /* This is a real entry. */ | |
1185 | if (result->pw_name[0] != '+' && result->pw_name[0] != '-') | |
1186 | { | |
1187 | if (strcmp (result->pw_name, name) == 0) | |
1188 | return NSS_STATUS_SUCCESS; | |
1189 | else | |
1190 | continue; | |
1191 | } | |
1192 | ||
1193 | /* -@netgroup */ | |
1194 | if (result->pw_name[0] == '-' && result->pw_name[1] == '@' | |
1195 | && result->pw_name[2] != '\0') | |
1196 | { | |
04c216a8 UD |
1197 | if (innetgr (&result->pw_name[2], NULL, name, NULL)) |
1198 | return NSS_STATUS_NOTFOUND; | |
cc3fa755 UD |
1199 | continue; |
1200 | } | |
1201 | ||
1202 | /* +@netgroup */ | |
1203 | if (result->pw_name[0] == '+' && result->pw_name[1] == '@' | |
1204 | && result->pw_name[2] != '\0') | |
1205 | { | |
04c216a8 | 1206 | enum nss_status status; |
cc3fa755 | 1207 | |
04c216a8 | 1208 | if (innetgr (&result->pw_name[2], NULL, name, NULL)) |
cc3fa755 | 1209 | { |
04c216a8 UD |
1210 | status = getpwnam_plususer (name, result, ent, buffer, |
1211 | buflen, errnop); | |
cc3fa755 | 1212 | |
04c216a8 UD |
1213 | if (status == NSS_STATUS_RETURN) |
1214 | continue; | |
1215 | ||
1216 | return status; | |
1217 | } | |
cc3fa755 UD |
1218 | continue; |
1219 | } | |
1220 | ||
1221 | /* -user */ | |
1222 | if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' | |
1223 | && result->pw_name[1] != '@') | |
1224 | { | |
1225 | if (strcmp (&result->pw_name[1], name) == 0) | |
34816665 | 1226 | return NSS_STATUS_NOTFOUND; |
cc3fa755 UD |
1227 | else |
1228 | continue; | |
1229 | } | |
1230 | ||
1231 | /* +user */ | |
1232 | if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' | |
1233 | && result->pw_name[1] != '@') | |
1234 | { | |
1235 | if (strcmp (name, &result->pw_name[1]) == 0) | |
1236 | { | |
1237 | enum nss_status status; | |
1238 | ||
04c216a8 | 1239 | status = getpwnam_plususer (name, result, ent, buffer, buflen, |
d71b808a | 1240 | errnop); |
cc3fa755 UD |
1241 | if (status == NSS_STATUS_RETURN) |
1242 | /* We couldn't parse the entry */ | |
1243 | return NSS_STATUS_NOTFOUND; | |
1244 | else | |
1245 | return status; | |
1246 | } | |
1247 | } | |
1248 | ||
1249 | /* +:... */ | |
1250 | if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') | |
1251 | { | |
1252 | enum nss_status status; | |
1253 | ||
04c216a8 UD |
1254 | status = getpwnam_plususer (name, result, ent, |
1255 | buffer, buflen, errnop); | |
cc3fa755 UD |
1256 | if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ |
1257 | break; | |
1258 | else | |
1259 | if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ | |
1260 | return NSS_STATUS_NOTFOUND; | |
1261 | else | |
1262 | return status; | |
1263 | } | |
1264 | } | |
1265 | return NSS_STATUS_SUCCESS; | |
1266 | } | |
6259ec0d UD |
1267 | |
1268 | enum nss_status | |
1269 | _nss_compat_getpwnam_r (const char *name, struct passwd *pwd, | |
d71b808a | 1270 | char *buffer, size_t buflen, int *errnop) |
6259ec0d | 1271 | { |
2d7da676 | 1272 | ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}, |
6259ec0d UD |
1273 | {NULL, NULL, 0, 0, NULL, NULL, NULL}}; |
1274 | enum nss_status status; | |
1275 | ||
1276 | if (name[0] == '-' || name[0] == '+') | |
34816665 | 1277 | return NSS_STATUS_NOTFOUND; |
6259ec0d | 1278 | |
26dee9c4 UD |
1279 | __libc_lock_lock (lock); |
1280 | ||
1281 | if (ni == NULL) | |
1282 | { | |
1283 | __nss_database_lookup ("passwd_compat", NULL, "nis", &ni); | |
1284 | use_nisplus = (strcmp (ni->name, "nisplus") == 0); | |
1285 | } | |
c131718c | 1286 | |
26dee9c4 | 1287 | __libc_lock_unlock (lock); |
6259ec0d UD |
1288 | |
1289 | status = internal_setpwent (&ent); | |
1290 | if (status != NSS_STATUS_SUCCESS) | |
1291 | return status; | |
1292 | ||
d71b808a | 1293 | status = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop); |
6259ec0d UD |
1294 | |
1295 | internal_endpwent (&ent); | |
cc3fa755 | 1296 | |
6259ec0d UD |
1297 | return status; |
1298 | } | |
1299 | ||
cc3fa755 UD |
1300 | /* This function handle the + entry in /etc/passwd for getpwuid */ |
1301 | static enum nss_status | |
1302 | getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer, | |
04c216a8 | 1303 | size_t buflen, int *errnop) |
cc3fa755 UD |
1304 | { |
1305 | struct parser_data *data = (void *) buffer; | |
1306 | struct passwd pwd; | |
1307 | int parse_res; | |
1308 | char *p; | |
1309 | size_t plen; | |
1310 | ||
1311 | memset (&pwd, '\0', sizeof (struct passwd)); | |
1312 | ||
1313 | copy_pwd_changes (&pwd, result, NULL, 0); | |
1314 | ||
1315 | plen = pwd_need_buflen (&pwd); | |
1316 | if (plen > buflen) | |
1317 | { | |
d71b808a | 1318 | *errnop = ERANGE; |
cc3fa755 UD |
1319 | return NSS_STATUS_TRYAGAIN; |
1320 | } | |
1321 | p = buffer + (buflen - plen); | |
1322 | buflen -= plen; | |
1323 | ||
1324 | if (use_nisplus) /* Do the NIS+ query here */ | |
1325 | { | |
1326 | nis_result *res; | |
1327 | char buf[1024 + pwdtablelen]; | |
1328 | ||
8e9b2075 UD |
1329 | snprintf (buf, sizeof (buf), "[uid=%lu],%s", (unsigned long int) uid, |
1330 | pwdtable); | |
1331 | res = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); | |
cc3fa755 | 1332 | if (niserr2nss (res->status) != NSS_STATUS_SUCCESS) |
04c216a8 UD |
1333 | { |
1334 | enum nss_status status = niserr2nss (res->status); | |
cc3fa755 | 1335 | |
04c216a8 UD |
1336 | nis_freeresult (res); |
1337 | return status; | |
1338 | } | |
cc3fa755 | 1339 | if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer, |
04c216a8 UD |
1340 | buflen, errnop)) == -1) |
1341 | { | |
1342 | nis_freeresult (res); | |
1343 | *errnop = ERANGE; | |
1344 | return NSS_STATUS_TRYAGAIN; | |
1345 | } | |
cc3fa755 UD |
1346 | nis_freeresult (res); |
1347 | } | |
1348 | else /* Use NIS */ | |
1349 | { | |
1350 | char buf[1024]; | |
1351 | char *domain, *outval, *ptr; | |
1352 | int outvallen; | |
1353 | ||
1354 | if (yp_get_default_domain (&domain) != YPERR_SUCCESS) | |
34816665 | 1355 | return NSS_STATUS_NOTFOUND; |
cc3fa755 | 1356 | |
8e9b2075 | 1357 | sprintf (buf, "%lu", (unsigned long int) uid); |
cc3fa755 | 1358 | if (yp_match (domain, "passwd.byuid", buf, strlen (buf), |
04c216a8 UD |
1359 | &outval, &outvallen) |
1360 | != YPERR_SUCCESS) | |
34816665 | 1361 | return NSS_STATUS_NOTFOUND; |
6591c335 | 1362 | |
7ef90c15 | 1363 | if (insert_passwd_adjunct (&outval, &outvallen, domain, errnop) |
04c216a8 UD |
1364 | != NSS_STATUS_SUCCESS) |
1365 | { | |
1366 | free (outval); | |
1367 | return NSS_STATUS_TRYAGAIN; | |
1368 | } | |
7ef90c15 UD |
1369 | |
1370 | if (buflen < ((size_t) outvallen + 1)) | |
04c216a8 UD |
1371 | { |
1372 | free (outval); | |
1373 | *errnop = ERANGE; | |
1374 | return NSS_STATUS_TRYAGAIN; | |
1375 | } | |
6591c335 UD |
1376 | |
1377 | ptr = strncpy (buffer, outval, buflen); | |
cc3fa755 | 1378 | free (outval); |
6591c335 | 1379 | |
cc3fa755 | 1380 | while (isspace (*ptr)) |
04c216a8 | 1381 | ptr++; |
d71b808a UD |
1382 | parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop); |
1383 | if (parse_res == -1) | |
04c216a8 | 1384 | return NSS_STATUS_TRYAGAIN; |
cc3fa755 UD |
1385 | } |
1386 | ||
1387 | if (parse_res > 0) | |
1388 | { | |
1389 | copy_pwd_changes (result, &pwd, p, plen); | |
1390 | give_pwd_free (&pwd); | |
1391 | /* We found the entry. */ | |
1392 | return NSS_STATUS_SUCCESS; | |
1393 | } | |
1394 | else | |
1395 | { | |
1396 | /* Give buffer the old len back */ | |
1397 | buflen += plen; | |
1398 | give_pwd_free (&pwd); | |
1399 | } | |
1400 | return NSS_STATUS_RETURN; | |
1401 | } | |
1402 | ||
1403 | /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */ | |
1404 | static enum nss_status | |
1405 | internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, | |
04c216a8 | 1406 | char *buffer, size_t buflen, int *errnop) |
cc3fa755 UD |
1407 | { |
1408 | struct parser_data *data = (void *) buffer; | |
1409 | ||
1410 | while (1) | |
1411 | { | |
1412 | fpos_t pos; | |
1413 | char *p; | |
1414 | int parse_res; | |
1415 | ||
1416 | do | |
04c216a8 UD |
1417 | { |
1418 | fgetpos (ent->stream, &pos); | |
1419 | buffer[buflen - 1] = '\xff'; | |
1420 | p = fgets (buffer, buflen, ent->stream); | |
1421 | if (p == NULL && feof (ent->stream)) | |
34816665 UD |
1422 | return NSS_STATUS_NOTFOUND; |
1423 | ||
04c216a8 UD |
1424 | if (p == NULL || buffer[buflen - 1] != '\xff') |
1425 | { | |
1426 | fsetpos (ent->stream, &pos); | |
1427 | *errnop = ERANGE; | |
1428 | return NSS_STATUS_TRYAGAIN; | |
1429 | } | |
1430 | ||
1431 | /* Terminate the line for any case. */ | |
1432 | buffer[buflen - 1] = '\0'; | |
1433 | ||
1434 | /* Skip leading blanks. */ | |
1435 | while (isspace (*p)) | |
1436 | ++p; | |
1437 | } | |
cc3fa755 | 1438 | while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ |
04c216a8 UD |
1439 | /* Parse the line. If it is invalid, loop to |
1440 | get the next line of the file to parse. */ | |
1441 | !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, | |
1442 | errnop))); | |
cc3fa755 UD |
1443 | |
1444 | if (parse_res == -1) | |
04c216a8 UD |
1445 | { |
1446 | /* The parser ran out of space. */ | |
1447 | fsetpos (ent->stream, &pos); | |
1448 | *errnop = ERANGE; | |
1449 | return NSS_STATUS_TRYAGAIN; | |
1450 | } | |
cc3fa755 UD |
1451 | |
1452 | /* This is a real entry. */ | |
1453 | if (result->pw_name[0] != '+' && result->pw_name[0] != '-') | |
04c216a8 UD |
1454 | { |
1455 | if (result->pw_uid == uid) | |
1456 | return NSS_STATUS_SUCCESS; | |
1457 | else | |
1458 | continue; | |
1459 | } | |
cc3fa755 UD |
1460 | |
1461 | /* -@netgroup */ | |
1462 | if (result->pw_name[0] == '-' && result->pw_name[1] == '@' | |
04c216a8 UD |
1463 | && result->pw_name[2] != '\0') |
1464 | { | |
1465 | char buf[strlen (result->pw_name)]; | |
1466 | enum nss_status status; | |
cc3fa755 | 1467 | |
04c216a8 UD |
1468 | strcpy (buf, &result->pw_name[2]); |
1469 | ||
1470 | status = getpwuid_plususer (uid, result, buffer, buflen, errnop); | |
1471 | if (status == NSS_STATUS_SUCCESS && | |
1472 | innetgr (buf, NULL, result->pw_name, NULL)) | |
34816665 UD |
1473 | return NSS_STATUS_NOTFOUND; |
1474 | ||
04c216a8 UD |
1475 | continue; |
1476 | } | |
cc3fa755 UD |
1477 | |
1478 | /* +@netgroup */ | |
1479 | if (result->pw_name[0] == '+' && result->pw_name[1] == '@' | |
04c216a8 UD |
1480 | && result->pw_name[2] != '\0') |
1481 | { | |
cc3fa755 | 1482 | char buf[strlen (result->pw_name)]; |
04c216a8 | 1483 | enum nss_status status; |
cc3fa755 UD |
1484 | |
1485 | strcpy (buf, &result->pw_name[2]); | |
cc3fa755 | 1486 | |
04c216a8 UD |
1487 | status = getpwuid_plususer (uid, result, buffer, buflen, errnop); |
1488 | ||
1489 | if (status == NSS_STATUS_RETURN) | |
1490 | continue; | |
cc3fa755 | 1491 | |
04c216a8 UD |
1492 | if (status == NSS_STATUS_SUCCESS) |
1493 | { | |
1494 | if (innetgr (buf, NULL, result->pw_name, NULL)) | |
cc3fa755 | 1495 | return NSS_STATUS_SUCCESS; |
04c216a8 UD |
1496 | } |
1497 | else | |
1498 | if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ | |
34816665 | 1499 | return NSS_STATUS_NOTFOUND; |
04c216a8 UD |
1500 | else |
1501 | return status; | |
1502 | ||
1503 | continue; | |
cc3fa755 UD |
1504 | } |
1505 | ||
1506 | /* -user */ | |
1507 | if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' | |
04c216a8 UD |
1508 | && result->pw_name[1] != '@') |
1509 | { | |
1510 | char buf[strlen (result->pw_name)]; | |
1511 | enum nss_status status; | |
1512 | ||
1513 | strcpy (buf, &result->pw_name[1]); | |
1514 | ||
1515 | status = getpwuid_plususer (uid, result, buffer, buflen, errnop); | |
1516 | if (status == NSS_STATUS_SUCCESS && | |
1517 | innetgr (buf, NULL, result->pw_name, NULL)) | |
34816665 | 1518 | return NSS_STATUS_NOTFOUND; |
cc3fa755 | 1519 | continue; |
04c216a8 | 1520 | } |
cc3fa755 UD |
1521 | |
1522 | /* +user */ | |
1523 | if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' | |
04c216a8 UD |
1524 | && result->pw_name[1] != '@') |
1525 | { | |
1526 | char buf[strlen (result->pw_name)]; | |
cc3fa755 UD |
1527 | enum nss_status status; |
1528 | ||
04c216a8 UD |
1529 | strcpy (buf, &result->pw_name[1]); |
1530 | ||
1531 | status = getpwuid_plususer (uid, result, buffer, buflen, errnop); | |
1532 | ||
1533 | if (status == NSS_STATUS_RETURN) | |
cc3fa755 | 1534 | continue; |
04c216a8 UD |
1535 | |
1536 | if (status == NSS_STATUS_SUCCESS) | |
1537 | { | |
1538 | if (strcmp (buf, result->pw_name) == 0) | |
1539 | return NSS_STATUS_SUCCESS; | |
1540 | } | |
1541 | else | |
1542 | if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ | |
34816665 | 1543 | return NSS_STATUS_NOTFOUND; |
04c216a8 UD |
1544 | else |
1545 | return status; | |
1546 | ||
1547 | continue; | |
1548 | } | |
cc3fa755 UD |
1549 | |
1550 | /* +:... */ | |
1551 | if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') | |
04c216a8 UD |
1552 | { |
1553 | enum nss_status status; | |
1554 | ||
1555 | status = getpwuid_plususer (uid, result, buffer, buflen, errnop); | |
1556 | if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ | |
1557 | break; | |
1558 | else | |
1559 | if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ | |
34816665 | 1560 | return NSS_STATUS_NOTFOUND; |
04c216a8 UD |
1561 | else |
1562 | return status; | |
1563 | } | |
cc3fa755 UD |
1564 | } |
1565 | return NSS_STATUS_SUCCESS; | |
1566 | } | |
6259ec0d UD |
1567 | |
1568 | enum nss_status | |
1569 | _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, | |
04c216a8 | 1570 | char *buffer, size_t buflen, int *errnop) |
6259ec0d | 1571 | { |
2d7da676 | 1572 | ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}, |
04c216a8 | 1573 | {NULL, NULL, 0, 0, NULL, NULL, NULL}}; |
6259ec0d | 1574 | enum nss_status status; |
c131718c | 1575 | |
26dee9c4 | 1576 | __libc_lock_lock (lock); |
c131718c | 1577 | |
26dee9c4 UD |
1578 | if (ni == NULL) |
1579 | { | |
1580 | __nss_database_lookup ("passwd_compat", NULL, "nis", &ni); | |
1581 | use_nisplus = (strcmp (ni->name, "nisplus") == 0); | |
1582 | } | |
c131718c | 1583 | |
26dee9c4 | 1584 | __libc_lock_unlock (lock); |
c131718c | 1585 | |
6259ec0d UD |
1586 | status = internal_setpwent (&ent); |
1587 | if (status != NSS_STATUS_SUCCESS) | |
1588 | return status; | |
1589 | ||
d71b808a | 1590 | status = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop); |
6259ec0d UD |
1591 | |
1592 | internal_endpwent (&ent); | |
cc3fa755 | 1593 | |
6259ec0d UD |
1594 | return status; |
1595 | } | |
1596 | ||
1597 | ||
1598 | /* Support routines for remembering -@netgroup and -user entries. | |
1599 | The names are stored in a single string with `|' as separator. */ | |
1600 | static void | |
1601 | blacklist_store_name (const char *name, ent_t *ent) | |
1602 | { | |
1603 | int namelen = strlen (name); | |
1604 | char *tmp; | |
1605 | ||
1606 | /* first call, setup cache */ | |
1607 | if (ent->blacklist.size == 0) | |
1608 | { | |
1609 | ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); | |
1610 | ent->blacklist.data = malloc (ent->blacklist.size); | |
1611 | if (ent->blacklist.data == NULL) | |
1612 | return; | |
1613 | ent->blacklist.data[0] = '|'; | |
1614 | ent->blacklist.data[1] = '\0'; | |
1615 | ent->blacklist.current = 1; | |
1616 | } | |
1617 | else | |
1618 | { | |
1619 | if (in_blacklist (name, namelen, ent)) | |
1620 | return; /* no duplicates */ | |
1621 | ||
1622 | if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) | |
1623 | { | |
1624 | ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); | |
1625 | tmp = realloc (ent->blacklist.data, ent->blacklist.size); | |
1626 | if (tmp == NULL) | |
1627 | { | |
1628 | free (ent->blacklist.data); | |
1629 | ent->blacklist.size = 0; | |
1630 | return; | |
1631 | } | |
1632 | ent->blacklist.data = tmp; | |
1633 | } | |
1634 | } | |
1635 | ||
1636 | tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); | |
1637 | *tmp++ = '|'; | |
1638 | *tmp = '\0'; | |
1639 | ent->blacklist.current += namelen + 1; | |
1640 | ||
1641 | return; | |
1642 | } | |
1643 | ||
1644 | /* returns TRUE if ent->blacklist contains name, else FALSE */ | |
1645 | static bool_t | |
1646 | in_blacklist (const char *name, int namelen, ent_t *ent) | |
1647 | { | |
1648 | char buf[namelen + 3]; | |
c131718c | 1649 | char *cp; |
6259ec0d UD |
1650 | |
1651 | if (ent->blacklist.data == NULL) | |
1652 | return FALSE; | |
1653 | ||
c131718c UD |
1654 | buf[0] = '|'; |
1655 | cp = stpcpy (&buf[1], name); | |
1656 | *cp++= '|'; | |
1657 | *cp = '\0'; | |
6259ec0d UD |
1658 | return strstr (ent->blacklist.data, buf) != NULL; |
1659 | } |