2 * Copyright (c) 1990 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 1998, Marek Michałkiewicz
4 * Copyright (c) 2005 , Tomasz Kłoczko
5 * Copyright (c) 2008 , Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 /* Newer versions of Linux libc already have shadow support. */
36 #if defined(SHADOWGRP) && !defined(HAVE_SHADOWGRP) /*{ */
41 #include "prototypes.h"
44 static char sgrbuf[BUFSIZ * 4];
45 static char **members = NULL;
46 static size_t nmembers = 0;
47 static char **admins = NULL;
48 static size_t nadmins = 0;
49 static struct sgrp sgroup;
55 static bool nis_ignore;
56 static enum { native, start, middle, native2 } nis_state;
57 static bool nis_bound;
58 static char *nis_domain;
60 static int nis_keylen;
62 static int nis_vallen;
64 #define IS_NISCHAR(c) ((c)=='+')
69 * bind_nis - bind to NIS server
72 static int bind_nis (void)
74 if (yp_get_default_domain (&nis_domain))
82 static char **build_list (char *s, char **list[], size_t * nlist)
85 size_t nelem = *nlist, size;
87 while (s != NULL && *s != '\0') {
88 size = (nelem + 1) * sizeof (ptr);
89 if ((ptr = realloc (*list, size)) != NULL) {
101 size = (nelem + 1) * sizeof (ptr);
102 ptr = realloc (*list, size);
115 if (NULL != shadow) {
118 shadow = fopen (SGROUP_FILE, "r");
124 if (NULL != shadow) {
125 (void) fclose (shadow);
131 struct sgrp *sgetsgent (const char *string)
133 char *fields[FIELDS];
137 strncpy (sgrbuf, string, sizeof sgrbuf - 1);
138 sgrbuf[sizeof sgrbuf - 1] = '\0';
140 cp = strrchr (sgrbuf, '\n');
146 * There should be exactly 4 colon separated fields. Find
147 * all 4 of them and save the starting addresses in fields[].
150 for (cp = sgrbuf, i = 0; (i < FIELDS) && (NULL != cp); i++) {
152 cp = strchr (cp, ':');
159 * If there was an extra field somehow, or perhaps not enough,
160 * the line is invalid.
163 if ((NULL != cp) || (i != FIELDS))
165 if (!IS_NISCHAR (fields[0][0])) {
174 sgroup.sg_name = fields[0];
175 sgroup.sg_passwd = fields[1];
186 sgroup.sg_adm = build_list (fields[2], &admins, &nadmins);
187 sgroup.sg_mem = build_list (fields[3], &members, &nmembers);
193 * fgetsgent - convert next line in stream to (struct sgrp)
195 * fgetsgent() reads the next line from the provided stream and
196 * converts it to a (struct sgrp). NULL is returned on EOF.
199 struct sgrp *fgetsgent (FILE * fp)
201 char buf[sizeof sgrbuf];
209 while (fgetsx (buf, (int) sizeof buf, fp) != (char *) 0)
211 if (fgetsx (buf, (int) sizeof buf, fp) != (char *) 0)
214 cp = strchr (buf, '\n');
219 if (nis_ignore && IS_NISCHAR (buf[0])) {
223 return (sgetsgent (buf));
229 * getsgent - get a single shadow group entry
232 struct sgrp *getsgent (void)
235 bool nis_1_group = false;
239 if (NULL == shadow) {
246 * See if we are reading from the local file.
249 if (nis_state == native || nis_state == native2) {
252 * Get the next entry from the shadow group file. Return
253 * NULL right away if there is none.
256 val = fgetsgent (shadow);
262 * If this entry began with a NIS escape character, we have
263 * to see if this is just a single group, or if the entire
264 * map is being asked for.
267 if (IS_NISCHAR (val->sg_name[0])) {
268 if ('\0' != val->sg_name[1]) {
276 * If this isn't a NIS group and this isn't an escape to go
277 * use a NIS map, it must be a regular local group.
280 if (!nis_1_group && (nis_state != start)) {
285 * If this is an escape to use an NIS map, switch over to
286 * that bunch of code.
289 if (nis_state == start) {
294 * NEEDSWORK. Here we substitute pieces-parts of this entry.
305 if (nis_state == start) {
306 if (yp_first (nis_domain, "gshadow.byname", &nis_key,
307 &nis_keylen, &nis_val, &nis_vallen)) {
312 } else if (nis_state == middle) {
313 if (yp_next (nis_domain, "gshadow.byname", nis_key,
314 nis_keylen, &nis_key, &nis_keylen,
315 &nis_val, &nis_vallen)) {
320 return sgetsgent (nis_val);
323 return (fgetsgent (shadow));
328 * getsgnam - get a shadow group entry by name
331 struct sgrp *getsgnam (const char *name)
337 static char save_name[16];
338 int nis_disabled = 0;
348 * Search the gshadow.byname map for this group.
358 if (yp_match (nis_domain, "gshadow.byname", name,
359 strlen (name), &nis_val,
361 cp = strchr (nis_val, '\n');
367 sgrp = sgetsgent (nis_val);
369 strcpy (save_name, sgrp->sg_name);
371 nis_keylen = strlen (save_name);
385 while ((sgrp = getsgent ()) != (struct sgrp *) 0) {
386 if (strcmp (name, sgrp->sg_name) == 0) {
397 * putsgent - output shadow group entry in text form
399 * putsgent() converts the contents of a (struct sgrp) to text and
400 * writes the result to the given stream. This is the logical
401 * opposite of fgetsgent.
404 int putsgent (const struct sgrp *sgrp, FILE * fp)
410 if ((NULL == fp) || (NULL == sgrp)) {
414 /* calculate the required buffer size */
415 size = strlen (sgrp->sg_name) + strlen (sgrp->sg_passwd) + 10;
416 for (i = 0; (NULL != sgrp->sg_adm) && (NULL != sgrp->sg_adm[i]); i++) {
417 size += strlen (sgrp->sg_adm[i]) + 1;
419 for (i = 0; (NULL != sgrp->sg_mem) && (NULL != sgrp->sg_mem[i]); i++) {
420 size += strlen (sgrp->sg_mem[i]) + 1;
430 * Copy the group name and passwd.
433 strcpy (cp, sgrp->sg_name);
437 strcpy (cp, sgrp->sg_passwd);
442 * Copy the administrators, separating each from the other
446 for (i = 0; NULL != sgrp->sg_adm[i]; i++) {
451 strcpy (cp, sgrp->sg_adm[i]);
457 * Now do likewise with the group members.
460 for (i = 0; NULL != sgrp->sg_mem[i]; i++) {
466 strcpy (cp, sgrp->sg_mem[i]);
474 * Output using the function which understands the line
475 * continuation conventions.
478 if (fputsx (buf, fp) == EOF) {
487 extern int errno; /* warning: ANSI C forbids an empty source file */
488 #endif /*} SHADOWGRP */