]> sourceware.org Git - glibc.git/blame - nis/nss_compat/compat-grp.c
update.
[glibc.git] / nis / nss_compat / compat-grp.c
CommitLineData
c131718c 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 <errno.h>
21#include <nss.h>
22#include <grp.h>
23#include <ctype.h>
5107cf1d 24#include <bits/libc-lock.h>
6259ec0d
UD
25#include <string.h>
26#include <rpcsvc/yp.h>
27#include <rpcsvc/ypclnt.h>
26dee9c4
UD
28#include <rpcsvc/nis.h>
29#include <rpcsvc/nislib.h>
30#include <nsswitch.h>
31
32#include "nss-nisplus.h"
2d7da676 33#include "nisplus-parser.h"
26dee9c4
UD
34
35static service_user *ni = NULL;
36static bool_t use_nisplus = FALSE; /* default: group_compat: nis */
2d7da676
UD
37static nis_name grptable = NULL; /* Name of the group table */
38static size_t grptablelen = 0;
6259ec0d 39
7e3be507
UD
40/* Get the declaration of the parser function. */
41#define ENTNAME grent
42#define STRUCTURE group
43#define EXTERN_PARSER
44#include "../../nss/nss_files/files-parse.c"
45
26dee9c4 46/* Structure for remembering -group members ... */
6259ec0d
UD
47#define BLACKLIST_INITIAL_SIZE 512
48#define BLACKLIST_INCREMENT 256
49struct blacklist_t
50 {
51 char *data;
52 int current;
53 int size;
54 };
55
56struct ent_t
57 {
58 bool_t nis;
59 bool_t nis_first;
60 char *oldkey;
61 int oldkeylen;
26dee9c4 62 nis_result *result;
6259ec0d
UD
63 FILE *stream;
64 struct blacklist_t blacklist;
26dee9c4 65};
6259ec0d
UD
66typedef struct ent_t ent_t;
67
2d7da676 68static ent_t ext_ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}};
6259ec0d
UD
69
70/* Protect global state against multiple changers. */
71__libc_lock_define_initialized (static, lock)
72
73/* Prototypes for local functions. */
74static void blacklist_store_name (const char *, ent_t *);
75static int in_blacklist (const char *, int, ent_t *);
2d7da676
UD
76
77static enum nss_status
78_nss_first_init (void)
79{
80 if (ni == NULL)
81 {
82 __nss_database_lookup ("group_compat", NULL, "nis", &ni);
83 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
84 }
85
86 if (grptable == NULL)
87 {
88 char buf [20 + strlen (nis_local_directory ())];
89 char *p;
90
91 p = stpcpy (buf, "group.org_dir.");
92 p = stpcpy (p, nis_local_directory ());
93 grptable = strdup (buf);
94 if (grptable == NULL)
95 return NSS_STATUS_TRYAGAIN;
96 grptablelen = strlen (grptable);
97 }
98
99 return NSS_STATUS_SUCCESS;
100}
6259ec0d
UD
101
102static enum nss_status
103internal_setgrent (ent_t *ent)
104{
105 enum nss_status status = NSS_STATUS_SUCCESS;
106
107 ent->nis = ent->nis_first = 0;
108
2d7da676
UD
109 if (_nss_first_init () != NSS_STATUS_SUCCESS)
110 return NSS_STATUS_UNAVAIL;
111
6259ec0d
UD
112 if (ent->oldkey != NULL)
113 {
114 free (ent->oldkey);
115 ent->oldkey = NULL;
116 ent->oldkeylen = 0;
117 }
c131718c 118
26dee9c4
UD
119 if (ent->result != NULL)
120 {
121 nis_freeresult (ent->result);
122 ent->result = NULL;
123 }
c131718c 124
6259ec0d
UD
125 ent->blacklist.current = 0;
126 if (ent->blacklist.data != NULL)
127 ent->blacklist.data[0] = '\0';
c131718c 128
6259ec0d
UD
129 if (ent->stream == NULL)
130 {
131 ent->stream = fopen ("/etc/group", "r");
c131718c 132
6259ec0d
UD
133 if (ent->stream == NULL)
134 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
135 }
136 else
137 rewind (ent->stream);
138
139 return status;
140}
141
142
143enum nss_status
144_nss_compat_setgrent (void)
145{
146 enum nss_status result;
147
148 __libc_lock_lock (lock);
149
150 result = internal_setgrent (&ext_ent);
151
152 __libc_lock_unlock (lock);
153
154 return result;
155}
156
157
158static enum nss_status
159internal_endgrent (ent_t *ent)
160{
161 if (ent->stream != NULL)
162 {
163 fclose (ent->stream);
164 ent->stream = NULL;
165 }
166
167 ent->nis = ent->nis_first = 0;
168
169 if (ent->oldkey != NULL)
170 {
171 free (ent->oldkey);
172 ent->oldkey = NULL;
173 ent->oldkeylen = 0;
174 }
175
26dee9c4
UD
176 if (ent->result != NULL)
177 {
178 nis_freeresult (ent->result);
179 ent->result = NULL;
180 }
c131718c 181
6259ec0d
UD
182 ent->blacklist.current = 0;
183 if (ent->blacklist.data != NULL)
184 ent->blacklist.data[0] = '\0';
185
186 return NSS_STATUS_SUCCESS;
187}
188
189enum nss_status
190_nss_compat_endgrent (void)
191{
192 enum nss_status result;
193
194 __libc_lock_lock (lock);
195
196 result = internal_endgrent (&ext_ent);
197
198 __libc_lock_unlock (lock);
199
200 return result;
201}
202
203static enum nss_status
204getgrent_next_nis (struct group *result, ent_t *ent, char *buffer,
205 size_t buflen)
206{
7e3be507 207 struct parser_data *data = (void *) buffer;
6259ec0d
UD
208 char *domain;
209 char *outkey, *outval;
26dee9c4 210 int outkeylen, outvallen, parse_res;
6259ec0d
UD
211 char *p;
212
213 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
214 {
215 ent->nis = 0;
216 return NSS_STATUS_NOTFOUND;
217 }
218
219 do
220 {
221 if (ent->nis_first)
222 {
223 if (yp_first (domain, "group.byname", &outkey, &outkeylen,
224 &outval, &outvallen) != YPERR_SUCCESS)
225 {
226 ent->nis = 0;
227 return NSS_STATUS_UNAVAIL;
228 }
229
230 ent->oldkey = outkey;
231 ent->oldkeylen = outkeylen;
232 ent->nis_first = FALSE;
233 }
234 else
235 {
236 if (yp_next (domain, "group.byname", ent->oldkey, ent->oldkeylen,
237 &outkey, &outkeylen, &outval, &outvallen)
238 != YPERR_SUCCESS)
239 {
240 ent->nis = 0;
241 return NSS_STATUS_NOTFOUND;
242 }
243
244 free (ent->oldkey);
245 ent->oldkey = outkey;
246 ent->oldkeylen = outkeylen;
247 }
248
249 /* Copy the found data to our buffer */
250 p = strncpy (buffer, outval, buflen);
251
252 /* ...and free the data. */
253 free (outval);
254
255 while (isspace (*p))
256 ++p;
c131718c 257
26dee9c4 258 parse_res = _nss_files_parse_grent (p, result, data, buflen);
c131718c
UD
259
260 if (parse_res &&
26dee9c4
UD
261 in_blacklist (result->gr_name, strlen (result->gr_name), ent))
262 parse_res = 0; /* if result->gr_name in blacklist,search next entry */
263 }
264 while (!parse_res);
c131718c 265
26dee9c4
UD
266 return NSS_STATUS_SUCCESS;
267}
268
269static enum nss_status
270getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
271 size_t buflen)
272{
273 int parse_res;
c131718c 274
26dee9c4
UD
275 do
276 {
277 if (ent->nis_first)
278 {
2d7da676 279 ent->result = nis_first_entry(grptable);
26dee9c4
UD
280 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
281 {
282 ent->nis = 0;
283 return niserr2nss (ent->result->status);
284 }
285 ent->nis_first = FALSE;
286 }
287 else
288 {
289 nis_result *res;
c131718c 290
2d7da676 291 res = nis_next_entry(grptable, &ent->result->cookie);
26dee9c4
UD
292 nis_freeresult (ent->result);
293 ent->result = res;
294 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
295 {
2d7da676
UD
296 ent->nis = 0;
297 return niserr2nss (ent->result->status);
26dee9c4
UD
298 }
299 }
2d7da676 300 parse_res = _nss_nisplus_parse_grent (ent->result, 0, result, buffer,
26dee9c4 301 buflen);
c131718c 302 if (parse_res &&
26dee9c4
UD
303 in_blacklist (result->gr_name, strlen (result->gr_name), ent))
304 parse_res = 0; /* if result->gr_name in blacklist,search next entry */
305 }
306 while (!parse_res);
c131718c 307
26dee9c4
UD
308 return NSS_STATUS_SUCCESS;
309}
6259ec0d 310
26dee9c4
UD
311/* This function handle the +group entrys in /etc/group */
312static enum nss_status
313getgrent_next_file_plusgroup (struct group *result, char *buffer,
314 size_t buflen)
315{
316 struct parser_data *data = (void *) buffer;
317 int parse_res;
c131718c 318
26dee9c4
UD
319 if (use_nisplus) /* Do the NIS+ query here */
320 {
321 nis_result *res;
2d7da676 322 char buf[strlen (result->gr_name) + 24 + grptablelen];
26dee9c4 323
2d7da676
UD
324 sprintf(buf, "[name=%s],%s", &result->gr_name[1], grptable);
325 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
26dee9c4
UD
326 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
327 {
328 enum nss_status status = niserr2nss (res->status);
c131718c 329
26dee9c4
UD
330 nis_freeresult (res);
331 return status;
332 }
2d7da676 333 parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer, buflen);
26dee9c4
UD
334 nis_freeresult (res);
335 }
336 else /* Use NIS */
337 {
338 char *domain, *outval, *p;
339 int outvallen;
340
341 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
342 return NSS_STATUS_TRYAGAIN;
c131718c 343
26dee9c4
UD
344 if (yp_match (domain, "group.byname", &result->gr_name[1],
345 strlen (result->gr_name) - 1, &outval, &outvallen)
346 != YPERR_SUCCESS)
347 return NSS_STATUS_TRYAGAIN;
348 p = strncpy (buffer, outval,
7799b7b3 349 buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
26dee9c4
UD
350 free (outval);
351 while (isspace (*p))
352 p++;
353 parse_res = _nss_files_parse_grent (p, result, data, buflen);
354 }
355
356 if (parse_res)
357 /* We found the entry. */
6259ec0d
UD
358 return NSS_STATUS_SUCCESS;
359 else
26dee9c4 360 return NSS_STATUS_RETURN;
6259ec0d
UD
361}
362
363
364static enum nss_status
365getgrent_next_file (struct group *result, ent_t *ent,
366 char *buffer, size_t buflen)
367{
7e3be507 368 struct parser_data *data = (void *) buffer;
6259ec0d
UD
369 while (1)
370 {
371 char *p;
372
373 do
374 {
375 p = fgets (buffer, buflen, ent->stream);
376 if (p == NULL)
377 return NSS_STATUS_NOTFOUND;
378
379 /* Terminate the line for any case. */
380 buffer[buflen - 1] = '\0';
381
382 /* Skip leading blanks. */
383 while (isspace (*p))
384 ++p;
385 }
386 /* Ignore empty and comment lines. */
387 while (*p == '\0' || *p == '#' ||
388 /* Parse the line. If it is invalid, loop to
389 get the next line of the file to parse. */
7e3be507 390 !_nss_files_parse_grent (p, result, data, buflen));
6259ec0d
UD
391
392 if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
393 /* This is a real entry. */
394 break;
395
396 /* -group */
397 if (result->gr_name[0] == '-' && result->gr_name[1] != '\0'
398 && result->gr_name[1] != '@')
399 {
400 blacklist_store_name (&result->gr_name[1], ent);
401 continue;
402 }
403
404 /* +group */
405 if (result->gr_name[0] == '+' && result->gr_name[1] != '\0'
406 && result->gr_name[1] != '@')
407 {
26dee9c4 408 enum nss_status status;
c131718c 409
26dee9c4
UD
410 status = getgrent_next_file_plusgroup (result, buffer, buflen);
411 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
412 break;
413 else
414 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
415 continue;
416 else
417 return status;
6259ec0d
UD
418 }
419
420 /* +:... */
421 if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
422 {
423 ent->nis = TRUE;
424 ent->nis_first = TRUE;
425
26dee9c4
UD
426 if (use_nisplus)
427 return getgrent_next_nisplus (result, ent, buffer, buflen);
428 else
429 return getgrent_next_nis (result, ent, buffer, buflen);
6259ec0d
UD
430 }
431 }
432
433 return NSS_STATUS_SUCCESS;
434}
435
436
437static enum nss_status
438internal_getgrent_r (struct group *gr, ent_t *ent, char *buffer,
439 size_t buflen)
440{
441 if (ent->nis)
26dee9c4
UD
442 {
443 if (use_nisplus)
444 return getgrent_next_nisplus (gr, ent, buffer, buflen);
445 else
446 return getgrent_next_nis (gr, ent, buffer, buflen);
447 }
6259ec0d
UD
448 else
449 return getgrent_next_file (gr, ent, buffer, buflen);
450}
451
452enum nss_status
453_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen)
454{
455 enum nss_status status = NSS_STATUS_SUCCESS;
456
457 __libc_lock_lock (lock);
458
459 /* Be prepared that the setgrent function was not called before. */
460 if (ext_ent.stream == NULL)
461 status = internal_setgrent (&ext_ent);
462
463 if (status == NSS_STATUS_SUCCESS)
464 status = internal_getgrent_r (grp, &ext_ent, buffer, buflen);
465
466 __libc_lock_unlock (lock);
467
468 return status;
469}
470
471
472enum nss_status
473_nss_compat_getgrnam_r (const char *name, struct group *grp,
474 char *buffer, size_t buflen)
475{
2d7da676 476 ent_t ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}};
6259ec0d
UD
477 enum nss_status status;
478
479 if (name[0] == '-' || name[0] == '+')
480 return NSS_STATUS_NOTFOUND;
481
26dee9c4
UD
482 __libc_lock_lock (lock);
483
2d7da676 484 status = internal_setgrent (&ent);
c131718c 485
26dee9c4 486 __libc_lock_unlock (lock);
6259ec0d 487
6259ec0d
UD
488 if (status != NSS_STATUS_SUCCESS)
489 return status;
490
491 while ((status = internal_getgrent_r (grp, &ent, buffer, buflen))
492 == NSS_STATUS_SUCCESS)
493 if (strcmp (grp->gr_name, name) == 0)
494 break;
495
496 internal_endgrent (&ent);
497 return status;
498}
499
500
501enum nss_status
502_nss_compat_getgrgid_r (gid_t gid, struct group *grp,
503 char *buffer, size_t buflen)
504{
2d7da676 505 ent_t ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}};
6259ec0d
UD
506 enum nss_status status;
507
26dee9c4 508 __libc_lock_lock (lock);
c131718c 509
2d7da676 510 status = internal_setgrent (&ent);
c131718c 511
26dee9c4
UD
512 __libc_lock_unlock (lock);
513
6259ec0d
UD
514 if (status != NSS_STATUS_SUCCESS)
515 return status;
516
517 while ((status = internal_getgrent_r (grp, &ent, buffer, buflen))
518 == NSS_STATUS_SUCCESS)
519 if (grp->gr_gid == gid && grp->gr_name[0] != '+' && grp->gr_name[0] != '-')
520 break;
521
522 internal_endgrent (&ent);
523 return status;
524}
525
526
527/* Support routines for remembering -@netgroup and -user entries.
528 The names are stored in a single string with `|' as separator. */
529static void
530blacklist_store_name (const char *name, ent_t *ent)
531{
532 int namelen = strlen (name);
533 char *tmp;
534
535 /* first call, setup cache */
536 if (ent->blacklist.size == 0)
537 {
538 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
539 ent->blacklist.data = malloc (ent->blacklist.size);
540 if (ent->blacklist.data == NULL)
541 return;
542 ent->blacklist.data[0] = '|';
543 ent->blacklist.data[1] = '\0';
544 ent->blacklist.current = 1;
545 }
546 else
547 {
548 if (in_blacklist (name, namelen, ent))
549 return; /* no duplicates */
550
551 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
552 {
553 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
554 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
555 if (tmp == NULL)
556 {
557 free (ent->blacklist.data);
558 ent->blacklist.size = 0;
559 return;
560 }
561 ent->blacklist.data = tmp;
562 }
563 }
564
565 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
566 *tmp++ = '|';
567 *tmp = '\0';
568 ent->blacklist.current += namelen + 1;
569
570 return;
571}
572
573/* returns TRUE if ent->blacklist contains name, else FALSE */
574static bool_t
575in_blacklist (const char *name, int namelen, ent_t *ent)
576{
577 char buf[namelen + 3];
c131718c 578 char *cp;
6259ec0d
UD
579
580 if (ent->blacklist.data == NULL)
581 return FALSE;
582
c131718c
UD
583 buf[0] = '|';
584 cp = stpcpy (&buf[1], name);
585 *cp++= '|';
586 *cp = '\0';
6259ec0d
UD
587 return strstr (ent->blacklist.data, buf) != NULL;
588}
This page took 0.0982229999999999 seconds and 5 git commands to generate.