]> sourceware.org Git - glibc.git/blame - nis/nss_compat/compat-spwd.c
Update.
[glibc.git] / nis / nss_compat / compat-spwd.c
CommitLineData
26dee9c4 1/* Copyright (C) 1996, 1997 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
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20#include <nss.h>
21#include <errno.h>
22#include <ctype.h>
23#include <netdb.h>
24#include <shadow.h>
25#include <string.h>
5107cf1d 26#include <bits/libc-lock.h>
6259ec0d
UD
27#include <rpcsvc/yp.h>
28#include <rpcsvc/ypclnt.h>
26dee9c4
UD
29#include <rpcsvc/nis.h>
30#include <rpcsvc/nislib.h>
31#include <nsswitch.h>
32
33#include "netgroup.h"
34#include "nss-nisplus.h"
35
36static service_user *ni = NULL;
37static bool_t use_nisplus = FALSE; /* default: passwd_compat: nis */
6259ec0d 38
7e3be507
UD
39/* Get the declaration of the parser function. */
40#define ENTNAME spent
41#define STRUCTURE spwd
42#define EXTERN_PARSER
43#include "../../nss/nss_files/files-parse.c"
44
6259ec0d
UD
45/* Structure for remembering -@netgroup and -user members ... */
46#define BLACKLIST_INITIAL_SIZE 512
47#define BLACKLIST_INCREMENT 256
48struct blacklist_t
49 {
50 char *data;
51 int current;
52 int size;
53 };
54
55struct ent_t
56 {
57 bool_t netgroup;
58 bool_t nis;
59 bool_t first;
60 char *oldkey;
61 int oldkeylen;
26dee9c4
UD
62 nis_result *result;
63 nis_name *names;
64 u_long names_nr;
6259ec0d
UD
65 FILE *stream;
66 struct blacklist_t blacklist;
67 struct spwd pwd;
26dee9c4 68 struct __netgrent netgrdata;
6259ec0d
UD
69 };
70typedef struct ent_t ent_t;
71
26dee9c4 72static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, NULL, 0, NULL, {NULL, 0, 0},
6259ec0d
UD
73 {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
74
75/* Protect global state against multiple changers. */
76__libc_lock_define_initialized (static, lock)
77
78/* Prototypes for local functions. */
79static void blacklist_store_name (const char *, ent_t *);
80static int in_blacklist (const char *, int, ent_t *);
26dee9c4
UD
81extern int _nss_nisplus_parse_spent (nis_result *, struct spwd *,
82 char *, size_t);
6259ec0d
UD
83static void
84give_spwd_free (struct spwd *pwd)
85{
86 if (pwd->sp_namp != NULL)
87 free (pwd->sp_namp);
88 if (pwd->sp_pwdp != NULL)
89 free (pwd->sp_pwdp);
90
91 memset (pwd, '\0', sizeof (struct spwd));
92}
93
94static int
95spwd_need_buflen (struct spwd *pwd)
96{
97 int len = 0;
98
99 if (pwd->sp_pwdp != NULL)
100 len += strlen (pwd->sp_pwdp) + 1;
101
102 return len;
103}
104
105static void
106copy_spwd_changes (struct spwd *dest, struct spwd *src,
107 char *buffer, size_t buflen)
108{
109 if (src->sp_pwdp != NULL && strlen (src->sp_pwdp))
110 {
111 if (buffer == NULL)
112 dest->sp_pwdp = strdup (src->sp_pwdp);
113 else if (dest->sp_pwdp &&
114 strlen (dest->sp_pwdp) >= strlen (src->sp_pwdp))
115 strcpy (dest->sp_pwdp, src->sp_pwdp);
116 else
117 {
118 dest->sp_pwdp = buffer;
119 strcpy (dest->sp_pwdp, src->sp_pwdp);
120 buffer += strlen (dest->sp_pwdp) + 1;
121 buflen = buflen - (strlen (dest->sp_pwdp) + 1);
122 }
123 }
124 if (src->sp_lstchg != 0)
125 dest->sp_lstchg = src->sp_lstchg;
126 if (src->sp_min != 0)
127 dest->sp_min = src->sp_min;
128 if (src->sp_max != 0)
129 dest->sp_max = src->sp_max;
130 if (src->sp_warn != 0)
131 dest->sp_warn = src->sp_warn;
132 if (src->sp_inact != 0)
133 dest->sp_inact = src->sp_inact;
134 if (src->sp_expire != 0)
135 dest->sp_expire = src->sp_expire;
136 if (src->sp_flag != 0)
137 dest->sp_flag = src->sp_flag;
138}
139
140static enum nss_status
141internal_setspent (ent_t *ent)
142{
143 enum nss_status status = NSS_STATUS_SUCCESS;
144
145 ent->nis = ent->first = ent->netgroup = 0;
146
26dee9c4
UD
147 /* If something was left over free it. */
148 if (ent->netgroup)
149 __internal_endnetgrent (&ent->netgrdata);
c131718c 150
6259ec0d
UD
151 if (ent->oldkey != NULL)
152 {
153 free (ent->oldkey);
154 ent->oldkey = NULL;
155 ent->oldkeylen = 0;
156 }
157
26dee9c4
UD
158 if (ent->result != NULL)
159 {
160 nis_freeresult (ent->result);
161 ent->result = NULL;
162 }
163 if (ent->names != NULL)
164 {
165 nis_freenames (ent->names);
166 ent->names = NULL;
167 }
168 ent->names_nr = 0;
c131718c 169
6259ec0d
UD
170 ent->blacklist.current = 0;
171 if (ent->blacklist.data != NULL)
172 ent->blacklist.data[0] = '\0';
173
174 if (ent->stream == NULL)
175 {
176 ent->stream = fopen ("/etc/shadow", "r");
177
178 if (ent->stream == NULL)
179 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
180 }
181 else
182 rewind (ent->stream);
183
184 give_spwd_free (&ent->pwd);
185
186 return status;
187}
188
189
190enum nss_status
191_nss_compat_setspent (void)
192{
193 enum nss_status result;
194
195 __libc_lock_lock (lock);
196
26dee9c4
UD
197 if (ni == NULL)
198 {
199 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
200 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
201 }
c131718c 202
6259ec0d
UD
203 result = internal_setspent (&ext_ent);
204
205 __libc_lock_unlock (lock);
206
207 return result;
208}
209
210
211static enum nss_status
212internal_endspent (ent_t *ent)
213{
214 if (ent->stream != NULL)
215 {
216 fclose (ent->stream);
217 ent->stream = NULL;
218 }
219
26dee9c4
UD
220 if (ent->netgroup)
221 __internal_endnetgrent (&ent->netgrdata);
222
6259ec0d
UD
223 ent->nis = ent->first = ent->netgroup = 0;
224
225 if (ent->oldkey != NULL)
226 {
227 free (ent->oldkey);
228 ent->oldkey = NULL;
229 ent->oldkeylen = 0;
230 }
231
26dee9c4
UD
232 if (ent->result != NULL)
233 {
234 nis_freeresult (ent->result);
235 ent->result = NULL;
236 }
237 if (ent->names != NULL)
238 {
239 nis_freenames (ent->names);
240 ent->names = NULL;
241 }
242 ent->names_nr = 0;
c131718c 243
6259ec0d
UD
244 ent->blacklist.current = 0;
245 if (ent->blacklist.data != NULL)
246 ent->blacklist.data[0] = '\0';
c131718c 247
6259ec0d
UD
248 give_spwd_free (&ent->pwd);
249
250 return NSS_STATUS_SUCCESS;
251}
252
253enum nss_status
254_nss_compat_endspent (void)
255{
256 enum nss_status result;
257
258 __libc_lock_lock (lock);
259
260 result = internal_endspent (&ext_ent);
261
262 __libc_lock_unlock (lock);
263
264 return result;
265}
266
267
268static enum nss_status
26dee9c4
UD
269getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
270 char *buffer, size_t buflen)
6259ec0d 271{
7e3be507 272 struct parser_data *data = (void *) buffer;
6259ec0d
UD
273 char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
274 int status, outvallen;
275 size_t p2len;
276
277 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
278 {
279 ent->netgroup = 0;
280 ent->first = 0;
281 give_spwd_free (&ent->pwd);
282 return NSS_STATUS_UNAVAIL;
283 }
284
285 if (ent->first == TRUE)
286 {
26dee9c4
UD
287 bzero (&ent->netgrdata, sizeof (struct __netgrent));
288 __internal_setnetgrent (group, &ent->netgrdata);
6259ec0d
UD
289 ent->first = FALSE;
290 }
291
292 while (1)
293 {
26dee9c4
UD
294 status = __internal_getnetgrent_r (&host, &user, &domain,
295 &ent->netgrdata, buffer, buflen);
296 if (status != 1)
6259ec0d 297 {
26dee9c4 298 __internal_endnetgrent (&ent->netgrdata);
6259ec0d
UD
299 ent->netgroup = 0;
300 give_spwd_free (&ent->pwd);
301 return NSS_STATUS_RETURN;
302 }
303
304 if (user == NULL || user[0] == '-')
305 continue;
306
307 if (domain != NULL && strcmp (ypdomain, domain) != 0)
308 continue;
309
310 if (yp_match (ypdomain, "shadow.byname", user,
311 strlen (user), &outval, &outvallen)
312 != YPERR_SUCCESS)
313 continue;
314
315 p2len = spwd_need_buflen (&ent->pwd);
316 if (p2len > buflen)
317 {
318 __set_errno (ERANGE);
319 return NSS_STATUS_TRYAGAIN;
320 }
321 p2 = buffer + (buflen - p2len);
322 buflen -= p2len;
323 p = strncpy (buffer, outval, buflen);
324 while (isspace (*p))
325 p++;
326 free (outval);
7e3be507 327 if (_nss_files_parse_spent (p, result, data, buflen))
6259ec0d
UD
328 {
329 copy_spwd_changes (result, &ent->pwd, p2, p2len);
330 break;
331 }
332 }
333
334 return NSS_STATUS_SUCCESS;
335}
336
26dee9c4
UD
337static enum nss_status
338getspent_next_nisplus_netgr (struct spwd *result, ent_t *ent, char *group,
339 char *buffer, size_t buflen)
340{
341 char *ypdomain, *host, *user, *domain, *p2;
342 int status, parse_res;
343 size_t p2len;
344 nis_result *nisres;
c131718c
UD
345
346 /* Maybe we should use domainname here ? We need the current
26dee9c4
UD
347 domainname for the domain field in netgroups */
348 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
349 {
350 ent->netgroup = 0;
351 ent->first = 0;
352 give_spwd_free (&ent->pwd);
353 return NSS_STATUS_UNAVAIL;
354 }
355
356 if (ent->first == TRUE)
357 {
358 bzero (&ent->netgrdata, sizeof (struct __netgrent));
359 __internal_setnetgrent (group, &ent->netgrdata);
360 ent->first = FALSE;
361 }
362
363 while (1)
364 {
365 status = __internal_getnetgrent_r (&host, &user, &domain,
366 &ent->netgrdata, buffer, buflen);
367 if (status != 1)
368 {
369 __internal_endnetgrent (&ent->netgrdata);
370 ent->netgroup = 0;
371 give_spwd_free (&ent->pwd);
372 return NSS_STATUS_RETURN;
373 }
374
375 if (user == NULL || user[0] == '-')
376 continue;
377
378 if (domain != NULL && strcmp (ypdomain, domain) != 0)
379 continue;
380
381 p2len = spwd_need_buflen (&ent->pwd);
382 if (p2len > buflen)
383 {
384 __set_errno (ERANGE);
385 return NSS_STATUS_TRYAGAIN;
386 }
387 p2 = buffer + (buflen - p2len);
388 buflen -= p2len;
c131718c 389 {
26dee9c4
UD
390 char buf[strlen (user) + 30];
391 sprintf(buf, "[name=%s],passwd.org_dir", user);
392 nisres = nis_list(buf, EXPAND_NAME, NULL, NULL);
393 }
394 if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS)
395 {
396 nis_freeresult (nisres);
397 continue;
398 }
399 parse_res = _nss_nisplus_parse_spent (nisres, result, buffer, buflen);
400 nis_freeresult (nisres);
c131718c 401
26dee9c4
UD
402 if (parse_res)
403 {
404 copy_spwd_changes (result, &ent->pwd, p2, p2len);
405 break;
406 }
407 }
408
409 return NSS_STATUS_SUCCESS;
410}
411
412static enum nss_status
413getspent_next_netgr (struct spwd *result, ent_t *ent, char *group,
414 char *buffer, size_t buflen)
415{
416 if (use_nisplus)
c131718c 417 return getspent_next_nisplus_netgr (result, ent, group, buffer, buflen);
26dee9c4 418 else
c131718c 419 return getspent_next_nis_netgr (result, ent, group, buffer, buflen);
26dee9c4
UD
420}
421
422static enum nss_status
423getspent_next_nisplus (struct spwd *result, ent_t *ent, char *buffer,
424 size_t buflen)
425{
426 int parse_res;
427 size_t p2len;
428 char *p2;
c131718c 429
26dee9c4
UD
430 if (ent->names == NULL)
431 {
432 ent->names = nis_getnames ("passwd.org_dir");
433 if (ent->names == NULL || ent->names[0] == NULL)
434 {
435 ent->nis = 0;
436 return NSS_STATUS_UNAVAIL;
437 }
438 }
c131718c 439
26dee9c4
UD
440 p2len = spwd_need_buflen (&ent->pwd);
441 if (p2len > buflen)
442 {
443 __set_errno (ERANGE);
444 return NSS_STATUS_TRYAGAIN;
445 }
446 p2 = buffer + (buflen - p2len);
447 buflen -= p2len;
448 do
449 {
450 if (ent->first)
451 {
452 next_name:
453 ent->result = nis_first_entry(ent->names[ent->names_nr]);
454 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
455 {
456 ent->nis = 0;
457 give_spwd_free (&ent->pwd);
458 return niserr2nss (ent->result->status);
459 }
460 ent->first = FALSE;
461 }
462 else
463 {
464 nis_result *res;
c131718c
UD
465
466 res = nis_next_entry(ent->names[ent->names_nr],
26dee9c4
UD
467 &ent->result->cookie);
468 nis_freeresult (ent->result);
469 ent->result = res;
470 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
471 {
472 if ((ent->result->status == NIS_NOTFOUND) &&
473 ent->names[ent->names_nr + 1] != NULL)
474 {
475 nis_freeresult (ent->result);
476 ent->names_nr += 1;
477 goto next_name;
478 }
479 else
480 {
481 ent->nis = 0;
482 give_spwd_free (&ent->pwd);
483 return niserr2nss (ent->result->status);
484 }
485 }
486 }
c131718c 487 parse_res = _nss_nisplus_parse_spent (ent->result, result, buffer,
26dee9c4 488 buflen);
c131718c 489 if (parse_res &&
26dee9c4
UD
490 in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
491 parse_res = 0; /* if result->pw_name in blacklist,search next entry */
492 }
493 while (!parse_res);
c131718c 494
26dee9c4 495 copy_spwd_changes (result, &ent->pwd, p2, p2len);
c131718c 496
26dee9c4
UD
497 return NSS_STATUS_SUCCESS;
498}
499
500
6259ec0d
UD
501static enum nss_status
502getspent_next_nis (struct spwd *result, ent_t *ent,
503 char *buffer, size_t buflen)
504{
7e3be507 505 struct parser_data *data = (void *) buffer;
6259ec0d 506 char *domain, *outkey, *outval, *p, *p2;
26dee9c4 507 int outkeylen, outvallen, parse_res;
6259ec0d
UD
508 size_t p2len;
509
510 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
511 {
512 ent->nis = 0;
513 give_spwd_free (&ent->pwd);
514 return NSS_STATUS_UNAVAIL;
515 }
516
517 p2len = spwd_need_buflen (&ent->pwd);
518 if (p2len > buflen)
519 {
520 __set_errno (ERANGE);
521 return NSS_STATUS_TRYAGAIN;
522 }
523 p2 = buffer + (buflen - p2len);
524 buflen -= p2len;
525 do
526 {
527 if (ent->first)
528 {
529 if (yp_first (domain, "shadow.byname", &outkey, &outkeylen,
530 &outval, &outvallen) != YPERR_SUCCESS)
531 {
532 ent->nis = 0;
533 give_spwd_free (&ent->pwd);
534 return NSS_STATUS_UNAVAIL;
535 }
536
537 ent->oldkey = outkey;
538 ent->oldkeylen = outkeylen;
539 ent->first = FALSE;
540 }
541 else
542 {
543 if (yp_next (domain, "shadow.byname", ent->oldkey, ent->oldkeylen,
544 &outkey, &outkeylen, &outval, &outvallen)
545 != YPERR_SUCCESS)
546 {
547 ent->nis = 0;
548 give_spwd_free (&ent->pwd);
549 return NSS_STATUS_NOTFOUND;
550 }
551
552 free (ent->oldkey);
553 ent->oldkey = outkey;
554 ent->oldkeylen = outkeylen;
555 }
556
557 /* Copy the found data to our buffer */
558 p = strncpy (buffer, outval, buflen);
559
560 /* ...and free the data. */
561 free (outval);
562
563 while (isspace (*p))
564 ++p;
26dee9c4
UD
565 parse_res = _nss_files_parse_spent (p, result, data, buflen);
566 if (parse_res &&
567 in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
568 parse_res = 0;
6259ec0d 569 }
26dee9c4 570 while (!parse_res);
6259ec0d
UD
571
572 copy_spwd_changes (result, &ent->pwd, p2, p2len);
573
26dee9c4 574 return NSS_STATUS_SUCCESS;
6259ec0d
UD
575}
576
26dee9c4
UD
577/* This function handle the +user entrys in /etc/shadow */
578static enum nss_status
c131718c 579getspent_next_file_plususer (struct spwd *result, char *buffer,
26dee9c4
UD
580 size_t buflen)
581{
582 struct parser_data *data = (void *) buffer;
583 struct spwd pwd;
584 int parse_res;
585 char *p;
586 size_t plen;
c131718c 587
26dee9c4 588 memset (&pwd, '\0', sizeof (struct spwd));
c131718c 589
26dee9c4 590 copy_spwd_changes (&pwd, result, NULL, 0);
c131718c 591
26dee9c4
UD
592 plen = spwd_need_buflen (&pwd);
593 if (plen > buflen)
594 {
595 __set_errno (ERANGE);
596 return NSS_STATUS_TRYAGAIN;
597 }
598 p = buffer + (buflen - plen);
599 buflen -= plen;
c131718c 600
26dee9c4
UD
601 if (use_nisplus) /* Do the NIS+ query here */
602 {
603 nis_result *res;
604 char buf[strlen (result->sp_namp) + 24];
c131718c 605
26dee9c4
UD
606 sprintf(buf, "[name=%s],passwd.org_dir",
607 &result->sp_namp[1]);
608 res = nis_list(buf, EXPAND_NAME, NULL, NULL);
609 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
610 {
611 enum nss_status status = niserr2nss (res->status);
c131718c 612
26dee9c4
UD
613 nis_freeresult (res);
614 return status;
615 }
616 parse_res = _nss_nisplus_parse_spent (res, result, buffer, buflen);
617 nis_freeresult (res);
618 }
619 else /* Use NIS */
620 {
621 char *domain;
622 char *outval;
623 int outvallen;
c131718c 624
26dee9c4
UD
625 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
626 return NSS_STATUS_TRYAGAIN;
c131718c 627
26dee9c4
UD
628 if (yp_match (domain, "passwd.byname", &result->sp_namp[1],
629 strlen (result->sp_namp) - 1, &outval, &outvallen)
630 != YPERR_SUCCESS)
631 return NSS_STATUS_TRYAGAIN;
c131718c 632 p = strncpy (buffer, outval,
7799b7b3 633 buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
26dee9c4
UD
634 free (outval);
635 while (isspace (*p))
636 p++;
637 parse_res = _nss_files_parse_spent (p, result, data, buflen);
638 }
c131718c 639
26dee9c4
UD
640 if (parse_res)
641 {
642 copy_spwd_changes (result, &pwd, p, plen);
643 give_spwd_free (&pwd);
644 /* We found the entry. */
645 return NSS_STATUS_SUCCESS;
646 }
647 else
648 {
649 /* Give buffer the old len back */
650 buflen += plen;
651 give_spwd_free (&pwd);
652 }
653 return NSS_STATUS_RETURN;
654}
6259ec0d
UD
655
656static enum nss_status
657getspent_next_file (struct spwd *result, ent_t *ent,
658 char *buffer, size_t buflen)
659{
7e3be507 660 struct parser_data *data = (void *) buffer;
6259ec0d
UD
661 while (1)
662 {
c131718c 663 char *p;
6259ec0d
UD
664
665 do
666 {
667 p = fgets (buffer, buflen, ent->stream);
668 if (p == NULL)
669 return NSS_STATUS_NOTFOUND;
670
671 /* Terminate the line for any case. */
672 buffer[buflen - 1] = '\0';
673
674 /* Skip leading blanks. */
675 while (isspace (*p))
676 ++p;
677 }
c131718c 678 while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */
6259ec0d
UD
679 /* Parse the line. If it is invalid, loop to
680 get the next line of the file to parse. */
c131718c 681 || !_nss_files_parse_spent (p, result, data, buflen));
6259ec0d
UD
682
683 if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
684 /* This is a real entry. */
685 break;
686
687 /* -@netgroup */
688 if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@'
689 && result->sp_namp[2] != '\0')
690 {
c131718c
UD
691 char buf2[1024];
692 char *user, *host, *domain;
693 struct __netgrent netgrdata;
694
695 bzero (&netgrdata, sizeof (struct __netgrent));
696 __internal_setnetgrent (&result->sp_namp[2], &netgrdata);
697 while (__internal_getnetgrent_r (&host, &user, &domain,
698 &netgrdata, buf2, sizeof (buf2)))
6259ec0d
UD
699 {
700 if (user != NULL && user[0] != '-')
701 blacklist_store_name (user, ent);
702 }
c131718c 703 __internal_endnetgrent (&netgrdata);
6259ec0d
UD
704 continue;
705 }
706
707 /* +@netgroup */
708 if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@'
709 && result->sp_namp[2] != '\0')
710 {
711 int status;
712
713 ent->netgroup = TRUE;
714 ent->first = TRUE;
715 copy_spwd_changes (&ent->pwd, result, NULL, 0);
716
717 status = getspent_next_netgr (result, ent, &result->sp_namp[2],
718 buffer, buflen);
719 if (status == NSS_STATUS_RETURN)
720 continue;
721 else
722 return status;
723 }
724
725 /* -user */
726 if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0'
727 && result->sp_namp[1] != '@')
728 {
729 blacklist_store_name (&result->sp_namp[1], ent);
730 continue;
731 }
732
733 /* +user */
734 if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0'
735 && result->sp_namp[1] != '@')
736 {
26dee9c4 737 enum nss_status status;
c131718c 738
26dee9c4
UD
739 status = getspent_next_file_plususer (result, buffer, buflen);
740 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
741 break;
742 else
743 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
744 continue;
745 else
746 return status;
6259ec0d
UD
747 }
748
749 /* +:... */
750 if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
751 {
752 ent->nis = TRUE;
753 ent->first = TRUE;
754 copy_spwd_changes (&ent->pwd, result, NULL, 0);
755
26dee9c4
UD
756 if (use_nisplus)
757 return getspent_next_nisplus (result, ent, buffer, buflen);
758 else
759 return getspent_next_nis (result, ent, buffer, buflen);
6259ec0d
UD
760 }
761 }
762
763 return NSS_STATUS_SUCCESS;
764}
765
766
767static enum nss_status
768internal_getspent_r (struct spwd *pw, ent_t *ent,
769 char *buffer, size_t buflen)
770{
771 if (ent->netgroup)
772 {
773 int status;
774
775 /* We are searching members in a netgroup */
776 /* Since this is not the first call, we don't need the group name */
777 status = getspent_next_netgr (pw, ent, NULL, buffer, buflen);
778 if (status == NSS_STATUS_RETURN)
779 return getspent_next_file (pw, ent, buffer, buflen);
780 else
781 return status;
782 }
783 else if (ent->nis)
26dee9c4
UD
784 {
785 if (use_nisplus)
786 return getspent_next_nisplus (pw, ent, buffer, buflen);
787 else
788 return getspent_next_nis (pw, ent, buffer, buflen);
789 }
6259ec0d
UD
790 else
791 return getspent_next_file (pw, ent, buffer, buflen);
792}
793
794enum nss_status
795_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen)
796{
797 enum nss_status status = NSS_STATUS_SUCCESS;
798
799 __libc_lock_lock (lock);
800
26dee9c4
UD
801 if (ni == NULL)
802 {
803 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
804 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
805 }
c131718c 806
6259ec0d
UD
807 /* Be prepared that the setspent function was not called before. */
808 if (ext_ent.stream == NULL)
809 status = internal_setspent (&ext_ent);
810
811 if (status == NSS_STATUS_SUCCESS)
812 status = internal_getspent_r (pwd, &ext_ent, buffer, buflen);
813
814 __libc_lock_unlock (lock);
815
816 return status;
817}
818
819
820enum nss_status
821_nss_compat_getspnam_r (const char *name, struct spwd *pwd,
822 char *buffer, size_t buflen)
823{
26dee9c4 824 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, 0, NULL, {NULL, 0, 0},
6259ec0d
UD
825 {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
826 enum nss_status status;
827
828 if (name[0] == '-' || name[0] == '+')
829 return NSS_STATUS_NOTFOUND;
830
26dee9c4
UD
831 if (ni == NULL)
832 {
833 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
834 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
835 }
c131718c 836
6259ec0d
UD
837 status = internal_setspent (&ent);
838 if (status != NSS_STATUS_SUCCESS)
839 return status;
840
841 while ((status = internal_getspent_r (pwd, &ent, buffer, buflen))
842 == NSS_STATUS_SUCCESS)
843 if (strcmp (pwd->sp_namp, name) == 0)
844 break;
845
846 internal_endspent (&ent);
847 return status;
848}
849
850/* Support routines for remembering -@netgroup and -user entries.
851 The names are stored in a single string with `|' as separator. */
852static void
853blacklist_store_name (const char *name, ent_t *ent)
854{
855 int namelen = strlen (name);
856 char *tmp;
857
858 /* first call, setup cache */
859 if (ent->blacklist.size == 0)
860 {
861 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
862 ent->blacklist.data = malloc (ent->blacklist.size);
863 if (ent->blacklist.data == NULL)
864 return;
865 ent->blacklist.data[0] = '|';
866 ent->blacklist.data[1] = '\0';
867 ent->blacklist.current = 1;
868 }
869 else
870 {
871 if (in_blacklist (name, namelen, ent))
872 return; /* no duplicates */
873
874 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
875 {
876 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
877 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
878 if (tmp == NULL)
879 {
880 free (ent->blacklist.data);
881 ent->blacklist.size = 0;
882 return;
883 }
884 ent->blacklist.data = tmp;
885 }
886 }
887
888 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
889 *tmp++ = '|';
890 *tmp = '\0';
891 ent->blacklist.current += namelen + 1;
892
893 return;
894}
895
c131718c 896/* Returns TRUE if ent->blacklist contains name, else FALSE. */
6259ec0d
UD
897static bool_t
898in_blacklist (const char *name, int namelen, ent_t *ent)
899{
900 char buf[namelen + 3];
c131718c 901 char *cp;
6259ec0d
UD
902
903 if (ent->blacklist.data == NULL)
904 return FALSE;
905
c131718c
UD
906 buf[0] = '|';
907 cp = stpcpy (&buf[1], name);
908 *cp++= '|';
909 *cp = '\0';
6259ec0d
UD
910 return strstr (ent->blacklist.data, buf) != NULL;
911}
This page took 0.131259 seconds and 5 git commands to generate.