diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | nis/nss_compat/compat-grp.c | 12 | ||||
-rw-r--r-- | nis/nss_compat/compat-initgroups.c | 675 | ||||
-rw-r--r-- | nis/nss_compat/compat-pwd.c | 27 |
4 files changed, 269 insertions, 466 deletions
diff --git a/ChangeLog b/ChangeLog index 4cb0adc8a1..3f6bb16385 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2003-06-07 Thorsten Kukuk <kukuk@suse.de> + + * nis/nss_compat/compat-grp.c: Remove unused nis_first variable + (getgrent_next_file) Don't store group name to early in blacklist. + + * nis/nss_compat/compat-pwd.c (internal_getpwuid_r): Save strlen result + and use memcpy instead of strcpy. + +2003-06-28 Ulrich Drepper <drepper@redhat.com> + + * nis/nss_compat/compat-grp.c: Optimize several little things. Use + stream unlocked. + * nis/nss_compat/compat-initgroups.c: Likewise. + * nis/nss_compat/compat-pwd.c: Likewise. + * nis/nss_compat/compat-spwd.c: Likewise. + +2003-06-27 Thorsten Kukuk <kukuk@suse.de> + + * nis/nss_compat/compat-initgroups.c: Don't use our own NIS/NIS+ + functions, dlopen corresponding NSS module instead. + 2003-06-27 Jeroen Dekkers <jeroen@dekkers.cx> * sysdeps/mach/hurd/alpha/init-first.c: Remove call to __libc_init. diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c index a24db336e2..ff19912a0a 100644 --- a/nis/nss_compat/compat-grp.c +++ b/nis/nss_compat/compat-grp.c @@ -58,14 +58,13 @@ struct blacklist_t struct ent_t { - bool_t nis_first; bool_t files; FILE *stream; struct blacklist_t blacklist; }; typedef struct ent_t ent_t; -static ent_t ext_ent = {0, TRUE, NULL, {NULL, 0, 0}}; +static ent_t ext_ent = {TRUE, NULL, {NULL, 0, 0}}; /* Protect global state against multiple changers. */ __libc_lock_define_initialized (static, lock) @@ -304,13 +303,16 @@ getgrent_next_file (struct group *result, ent_t *ent, if (result->gr_name[0] == '+' && result->gr_name[1] != '\0' && result->gr_name[1] != '@') { + size_t len = strlen (result->gr_name); + char buf[len]; enum nss_status status; /* Store the group in the blacklist for the "+" at the end of /etc/group */ - blacklist_store_name (&result->gr_name[1], ent); + memcpy (buf, &result->gr_name[1], len); status = getgrnam_plusgroup (&result->gr_name[1], result, ent, buffer, buflen, errnop); + blacklist_store_name (buf, ent); if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ break; else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */ @@ -472,7 +474,7 @@ enum nss_status _nss_compat_getgrnam_r (const char *name, struct group *grp, char *buffer, size_t buflen, int *errnop) { - ent_t ent = {0, TRUE, NULL, {NULL, 0, 0}}; + ent_t ent = {TRUE, NULL, {NULL, 0, 0}}; enum nss_status result; if (name[0] == '-' || name[0] == '+') @@ -594,7 +596,7 @@ enum nss_status _nss_compat_getgrgid_r (gid_t gid, struct group *grp, char *buffer, size_t buflen, int *errnop) { - ent_t ent = {0, TRUE, NULL, {NULL, 0, 0}}; + ent_t ent = {TRUE, NULL, {NULL, 0, 0}}; enum nss_status result; __libc_lock_lock (lock); diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c index ed198325d8..d30d4700c0 100644 --- a/nis/nss_compat/compat-initgroups.c +++ b/nis/nss_compat/compat-initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -17,29 +17,39 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if 0 /* XXX this one needs to be rewritten. */ - +#include <alloca.h> +#include <ctype.h> #include <errno.h> #include <fcntl.h> -#include <nss.h> #include <grp.h> -#include <ctype.h> +#include <nss.h> +#include <stdio_ext.h> #include <string.h> #include <unistd.h> -#include <rpcsvc/yp.h> -#include <rpcsvc/ypclnt.h> -#include <rpcsvc/nis.h> +#include <rpc/types.h> #include <sys/param.h> #include <nsswitch.h> - -#include "nss-nis.h" -#include "nss-nisplus.h" -#include "nisplus-parser.h" +#include <bits/libc-lock.h> static service_user *ni; -static bool_t use_nisplus; /* default: group_compat: nis */ -static nis_name grptable; /* Name of the group table */ -static size_t grptablelen; +/* Type of the lookup function. */ +static enum nss_status (*nss_initgroups_dyn) (const char *, gid_t, + long int *, long int *, + gid_t **, long int, int *); +static enum nss_status (*nss_setgrent) (int stayopen); +static enum nss_status (*nss_getgrnam_r) (const char *name, + struct group * grp, char *buffer, + size_t buflen, int *errnop); +static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp, + char *buffer, size_t buflen, + int *errnop); +static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer, + size_t buflen, int *errnop); +static enum nss_status (*nss_endgrent) (void); + +/* Protect global state against multiple changers. */ +__libc_lock_define_initialized (static, lock) + /* Get the declaration of the parser function. */ #define ENTNAME grent @@ -51,29 +61,17 @@ static size_t grptablelen; #define BLACKLIST_INITIAL_SIZE 512 #define BLACKLIST_INCREMENT 256 struct blacklist_t - { - char *data; - int current; - int size; - }; - -struct response_t { - char *val; - struct response_t *next; + char *data; + int current; + int size; }; struct ent_t - { - bool_t nis; - bool_t nis_first; - char *oldkey; - int oldkeylen; - nis_result *result; - FILE *stream; - struct blacklist_t blacklist; - struct response_t *start; - struct response_t *next; +{ + bool_t files; + FILE *stream; + struct blacklist_t blacklist; }; typedef struct ent_t ent_t; @@ -82,68 +80,26 @@ typedef struct ent_t ent_t; static void blacklist_store_name (const char *, ent_t *); static int in_blacklist (const char *, int, ent_t *); -static int -saveit (int instatus, char *inkey, int inkeylen, char *inval, - int invallen, char *indata) -{ - ent_t *intern = (ent_t *) indata; - - if (instatus != YP_TRUE) - return instatus; - - if (inkey && inkeylen > 0 && inval && invallen > 0) - { - if (intern->start == NULL) - { - intern->start = malloc (sizeof (struct response_t)); - if (intern->start == NULL) - return YP_FALSE; - intern->next = intern->start; - } - else - { - intern->next->next = malloc (sizeof (struct response_t)); - if (intern->next->next == NULL) - return YP_FALSE; - intern->next = intern->next->next; - } - intern->next->next = NULL; - intern->next->val = malloc (invallen + 1); - if (intern->next->val == NULL) - return YP_FALSE; - strncpy (intern->next->val, inval, invallen); - intern->next->val[invallen] = '\0'; - } - - return 0; -} - -static enum nss_status -_nss_first_init (void) +/* Initialize the NSS interface/functions. The calling function must + hold the lock. */ +static void +init_nss_interface (void) { - if (ni == NULL) - { - __nss_database_lookup ("group_compat", NULL, "nis", &ni); - use_nisplus = (strcmp (ni->name, "nisplus") == 0); - } + __libc_lock_lock (lock); - if (grptable == NULL) + /* Retest. */ + if (ni == NULL + && __nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) { - static const char key[] = "group.org_dir."; - const char *local_dir = nis_local_directory (); - size_t len_local_dir = strlen (local_dir); - - grptable = malloc (sizeof (key) + len_local_dir); - if (grptable == NULL) - return NSS_STATUS_TRYAGAIN; - - grptablelen = ((char *) mempcpy (mempcpy (grptable, - key, sizeof (key) - 1), - local_dir, len_local_dir + 1) - - grptable) - 1; + nss_initgroups_dyn = __nss_lookup_function (ni, "initgroups_dyn"); + nss_setgrent = __nss_lookup_function (ni, "setgrent"); + nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); + nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r"); + nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r"); + nss_endgrent = __nss_lookup_function (ni, "endgrent"); } - return NSS_STATUS_SUCCESS; + __libc_lock_unlock (lock); } static enum nss_status @@ -151,26 +107,10 @@ internal_setgrent (ent_t *ent) { enum nss_status status = NSS_STATUS_SUCCESS; - ent->nis = ent->nis_first = 0; - - ent->start = NULL; - ent->next = NULL; - - if (_nss_first_init () != NSS_STATUS_SUCCESS) - return NSS_STATUS_UNAVAIL; - - if (ent->oldkey != NULL) - { - free (ent->oldkey); - ent->oldkey = NULL; - ent->oldkeylen = 0; - } + ent->files = TRUE; - if (ent->result != NULL) - { - nis_freeresult (ent->result); - ent->result = NULL; - } + if (ni == NULL) + init_nss_interface (); if (ent->blacklist.data != NULL) { @@ -181,35 +121,33 @@ internal_setgrent (ent_t *ent) else ent->blacklist.current = 0; + ent->stream = fopen ("/etc/group", "rm"); + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else { - ent->stream = fopen ("/etc/group", "r"); + /* We have to make sure the file is `closed on exec'. */ + int result, flags; - if (ent->stream == NULL) - status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; - else + result = flags = fcntl (fileno_unlocked (ent->stream), F_GETFD, 0); + if (result >= 0) { - /* We have to make sure the file is `closed on exec'. */ - int result, flags; - - result = flags = fcntl (fileno (ent->stream), F_GETFD, 0); - if (result >= 0) - { - flags |= FD_CLOEXEC; - result = fcntl (fileno (ent->stream), F_SETFD, flags); - } - if (result < 0) - { - /* Something went wrong. Close the stream and return a - failure. */ - fclose (ent->stream); - ent->stream = NULL; - status = NSS_STATUS_UNAVAIL; - } + flags |= FD_CLOEXEC; + result = fcntl (fileno_unlocked (ent->stream), F_SETFD, flags); + } + if (result < 0) + { + /* Something went wrong. Close the stream and return a + failure. */ + fclose (ent->stream); + ent->stream = NULL; + status = NSS_STATUS_UNAVAIL; } + else + /* We take care of locking ourself. */ + __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); } - else - rewind (ent->stream); return status; } @@ -224,21 +162,6 @@ internal_endgrent (ent_t *ent) ent->stream = NULL; } - ent->nis = ent->nis_first = 0; - - if (ent->oldkey != NULL) - { - free (ent->oldkey); - ent->oldkey = NULL; - ent->oldkeylen = 0; - } - - if (ent->result != NULL) - { - nis_freeresult (ent->result); - ent->result = NULL; - } - if (ent->blacklist.data != NULL) { ent->blacklist.current = 1; @@ -248,222 +171,145 @@ internal_endgrent (ent_t *ent) else ent->blacklist.current = 0; - while (ent->start != NULL) - { - if (ent->start->val != NULL) - free (ent->start->val); - ent->next = ent->start; - ent->start = ent->start->next; - free (ent->next); - } - - return NSS_STATUS_SUCCESS; } -static enum nss_status -getgrent_next_nis (struct group *result, ent_t *ent, char *buffer, - size_t buflen, int *errnop) +/* This function checks, if the user is a member of this group and if + yes, add the group id to the list. */ +static void +check_and_add_group (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, + struct group *grp) { - struct parser_data *data = (void *) buffer; - char *domain, *p; - int parse_res; - - if (yp_get_default_domain (&domain) != YPERR_SUCCESS) - { - ent->nis = 0; - return NSS_STATUS_NOTFOUND; - } - - if (ent->start == NULL) - { - struct ypall_callback ypcb; - enum nss_status status; - - ypcb.foreach = saveit; - ypcb.data = (char *) ent; - status = yperr2nss (yp_all (domain, "group.byname", &ypcb)); - ent->next = ent->start; - - if (ent->start == NULL || status != NSS_STATUS_SUCCESS) - { - ent->nis = 0; - return NSS_STATUS_UNAVAIL; - } - } - + gid_t *groups = *groupsp; + char **member; + + /* Don't add main group to list of groups. */ + if (grp->gr_gid == group) + return; + + for (member = grp->gr_mem; *member != NULL; ++member) + if (strcmp (*member, user) == 0) + { + /* Matches user. Insert this group. */ + if (*start == *size) + { + /* Need a bigger buffer. */ + gid_t *newgroups; + long int newsize; + + if (limit > 0 && *size == limit) + /* We reached the maximum. */ + return; - do - { - if (ent->next == NULL) - { - ent->nis = 0; - return NSS_STATUS_NOTFOUND; - } - - /* Copy the found data to our buffer... */ - p = strncpy (buffer, ent->next->val, buflen); - while (isspace (*p)) - ++p; - - parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop); - if (parse_res == -1) - { - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } + if (limit <= 0) + newsize = 2 * *size; + else + newsize = MIN (limit, 2 * *size); - ent->next = ent->next->next; + newgroups = realloc (groups, newsize * sizeof (*groups)); + if (newgroups == NULL) + return; + *groupsp = groups = newgroups; + *size = newsize; + } - if (parse_res && - in_blacklist (result->gr_name, strlen (result->gr_name), ent)) - parse_res = 0; /* if result->gr_name in blacklist,search next entry */ - } - while (!parse_res); + groups[*start] = grp->gr_gid; + *start += 1; - return NSS_STATUS_SUCCESS; + break; + } } +/* get the next group from NSS (+ entry). If the NSS module supports + initgroups_dyn, get all entries at once. */ static enum nss_status -getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer, - size_t buflen, int *errnop) +getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user, + gid_t group, long int *start, long int *size, + gid_t **groupsp, long int limit, int *errnop) { - int parse_res; + enum nss_status status; + struct group grpbuf; - do + /* if this module does not support getgrent_r and initgroups_dyn, + abort. We cannot find the needed group entries. */ + if (nss_getgrent_r == NULL && nss_initgroups_dyn == NULL) + return NSS_STATUS_UNAVAIL; + + /* Try nss_initgroups_dyn if supported. We also need getgrgid_r. + If this function is not supported, step through the whole group + database with getgrent_r. */ + if (nss_initgroups_dyn && nss_getgrgid_r) { - nis_result *save_oldres; - bool_t save_nis_first; - - if (ent->nis_first) - { - save_oldres = ent->result; - save_nis_first = TRUE; - ent->result = nis_first_entry(grptable); - if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS) - { - ent->nis = 0; - return niserr2nss (ent->result->status); - } - ent->nis_first = FALSE; - } - else - { - nis_result *res; - - save_oldres = ent->result; - save_nis_first = FALSE; - res = nis_next_entry(grptable, &ent->result->cookie); - ent->result = res; - if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS) - { - ent->nis = 0; - return niserr2nss (ent->result->status); - } - } - parse_res = _nss_nisplus_parse_grent (ent->result, 0, result, - buffer, buflen, errnop); - if (parse_res == -1) + long int mystart = 0, mysize = limit; + gid_t *mygroupsp = __alloca (limit * sizeof (gid_t)); + + /* For every gid in the list we get from the NSS module, + get the whole group entry. We need to do this, since we + need the group name to check if it is in the blacklist. + In worst case, this is as twice as slow as stepping with + getgrent_r through the whole group database. But for large + group databases this is faster, since the user can only be + in a limited number of groups. */ + if (nss_initgroups_dyn (user, group, &mystart, &mysize, &mygroupsp, + limit, errnop) == NSS_STATUS_SUCCESS) { - nis_freeresult (ent->result); - ent->result = save_oldres; - ent->nis_first = save_nis_first; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - else - { - if (!save_nis_first) - nis_freeresult (save_oldres); + /* A temporary buffer. We use the normal buffer, until we found + an entry, for which this buffer is to small. In this case, we + overwrite the pointer with one to a bigger buffer. */ + char *tmpbuf = buffer; + size_t tmplen = buflen; + int i; + + for (i = 0; i < mystart; i++) + { + while ((status = nss_getgrgid_r (mygroupsp[i], &grpbuf, tmpbuf, + tmplen, + errnop)) == NSS_STATUS_TRYAGAIN + && *errnop == ERANGE) + if (tmpbuf == buffer) + { + tmplen *= 2; + tmpbuf = __alloca (tmplen); + } + else + tmpbuf = extend_alloca (tmpbuf, tmplen, 2 * tmplen); + + if (!in_blacklist (grpbuf.gr_name, + strlen (grpbuf.gr_name), ent)) + check_and_add_group (user, group, start, size, groupsp, + limit, &grpbuf); + } + return NSS_STATUS_NOTFOUND; } + } - if (parse_res && - in_blacklist (result->gr_name, strlen (result->gr_name), ent)) - parse_res = 0; /* if result->gr_name in blacklist,search next entry */ + /* If we come here, the NSS module does not support initgroups_dyn + and we have to step through the whole list ourself. */ + do + { + if ((status = nss_getgrent_r (&grpbuf, buffer, buflen, errnop)) != + NSS_STATUS_SUCCESS) + return status; } - while (!parse_res); + while (in_blacklist (grpbuf.gr_name, strlen (grpbuf.gr_name), ent)); + check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); return NSS_STATUS_SUCCESS; } -/* This function handle the +group entrys in /etc/group */ static enum nss_status -getgrnam_plusgroup (const char *name, struct group *result, char *buffer, - size_t buflen, int *errnop) +internal_getgrent_r (ent_t *ent, char *buffer, size_t buflen, const char *user, + gid_t group, long int *start, long int *size, + gid_t **groupsp, long int limit, int *errnop) { struct parser_data *data = (void *) buffer; - int parse_res; - - if (use_nisplus) /* Do the NIS+ query here */ - { - nis_result *res; - char buf[strlen (name) + 24 + grptablelen]; - - sprintf(buf, "[name=%s],%s", name, grptable); - res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); - if (niserr2nss (res->status) != NSS_STATUS_SUCCESS) - { - enum nss_status status = niserr2nss (res->status); - - nis_freeresult (res); - return status; - } - parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer, buflen, - errnop); - if (parse_res == -1) - { - nis_freeresult (res); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - nis_freeresult (res); - } - else /* Use NIS */ - { - char *domain, *outval, *p; - int outvallen; + struct group grpbuf; - if (yp_get_default_domain (&domain) != YPERR_SUCCESS) - return NSS_STATUS_NOTFOUND; + if (!ent->files) + return getgrent_next_nss (ent, buffer, buflen, user, group, + start, size, groupsp, limit, errnop); - if (yp_match (domain, "group.byname", name, strlen (name), - &outval, &outvallen) != YPERR_SUCCESS) - return NSS_STATUS_NOTFOUND; - - if (buflen < ((size_t) outvallen + 1)) - { - free (outval); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - /* Copy the found data to our buffer... */ - p = strncpy (buffer, outval, buflen); - - /* ... and free the data. */ - free (outval); - while (isspace (*p)) - ++p; - parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop); - if (parse_res == -1) - { - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - } - - if (parse_res) - /* We found the entry. */ - return NSS_STATUS_SUCCESS; - else - return NSS_STATUS_RETURN; -} - -static enum nss_status -getgrent_next_file (struct group *result, ent_t *ent, - char *buffer, size_t buflen, int *errnop) -{ - struct parser_data *data = (void *) buffer; while (1) { fpos_t pos; @@ -474,8 +320,8 @@ getgrent_next_file (struct group *result, ent_t *ent, { fgetpos (ent->stream, &pos); buffer[buflen - 1] = '\xff'; - p = fgets (buffer, buflen, ent->stream); - if (p == NULL && feof (ent->stream)) + p = fgets_unlocked (buffer, buflen, ent->stream); + if (p == NULL && feof_unlocked (ent->stream)) return NSS_STATUS_NOTFOUND; if (p == NULL || buffer[buflen - 1] != '\xff') @@ -492,10 +338,10 @@ getgrent_next_file (struct group *result, ent_t *ent, while (isspace (*p)) ++p; } - while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ - /* Parse the line. If it is invalid, loop to - get the next line of the file to parse. */ - !(parse_res = _nss_files_parse_grent (p, result, data, buflen, + while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ + /* Parse the line. If it is invalid, loop to + get the next line of the file to parse. */ + !(parse_res = _nss_files_parse_grent (p, &grpbuf, data, buflen, errnop))); if (parse_res == -1) @@ -506,90 +352,64 @@ getgrent_next_file (struct group *result, ent_t *ent, return NSS_STATUS_TRYAGAIN; } - if (result->gr_name[0] != '+' && result->gr_name[0] != '-') + if (grpbuf.gr_name[0] != '+' && grpbuf.gr_name[0] != '-') /* This is a real entry. */ break; /* -group */ - if (result->gr_name[0] == '-' && result->gr_name[1] != '\0' - && result->gr_name[1] != '@') + if (grpbuf.gr_name[0] == '-' && grpbuf.gr_name[1] != '\0' + && grpbuf.gr_name[1] != '@') { - blacklist_store_name (&result->gr_name[1], ent); + blacklist_store_name (&grpbuf.gr_name[1], ent); continue; } /* +group */ - if (result->gr_name[0] == '+' && result->gr_name[1] != '\0' - && result->gr_name[1] != '@') + if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] != '\0' + && grpbuf.gr_name[1] != '@') { - enum nss_status status; - - /* Store the group in the blacklist for the "+" at the end of + if (in_blacklist (&grpbuf.gr_name[1], + strlen (&grpbuf.gr_name[1]), ent)) + continue; + /* Store the group in the blacklist for the "+" at the end of /etc/group */ - blacklist_store_name (&result->gr_name[1], ent); - status = getgrnam_plusgroup (&result->gr_name[1], result, buffer, - buflen, errnop); - if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ - break; - else - if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */ - || status == NSS_STATUS_NOTFOUND) /* No group in NIS */ - continue; - else - { - if (status == NSS_STATUS_TRYAGAIN) - { - /* The parser ran out of space. */ - fsetpos (ent->stream, &pos); - *errnop = ERANGE; - } - return status; - } + blacklist_store_name (&grpbuf.gr_name[1], ent); + if (nss_getgrnam_r == NULL) + return NSS_STATUS_UNAVAIL; + else if (nss_getgrnam_r (&grpbuf.gr_name[1], &grpbuf, buffer, + buflen, errnop) != NSS_STATUS_SUCCESS) + continue; + + check_and_add_group (user, group, start, size, groupsp, + limit, &grpbuf); + + return NSS_STATUS_SUCCESS; } /* +:... */ - if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') + if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] == '\0') { - ent->nis = TRUE; - ent->nis_first = TRUE; - - if (use_nisplus) - return getgrent_next_nisplus (result, ent, buffer, buflen, errnop); - else - return getgrent_next_nis (result, ent, buffer, buflen, errnop); + ent->files = FALSE; + return getgrent_next_nss (ent, buffer, buflen, user, group, + start, size, groupsp, limit, errnop); } } + check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); + return NSS_STATUS_SUCCESS; } -static enum nss_status -internal_getgrent_r (struct group *gr, ent_t *ent, char *buffer, - size_t buflen, int *errnop) -{ - if (ent->nis) - { - if (use_nisplus) - return getgrent_next_nisplus (gr, ent, buffer, buflen, errnop); - else - return getgrent_next_nis (gr, ent, buffer, buflen, errnop); - } - else - return getgrent_next_file (gr, ent, buffer, buflen, errnop); -} - enum nss_status _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop) { - struct group grpbuf, *g; size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *tmpbuf; enum nss_status status; - ent_t intern = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}}; - gid_t *groups = *groupsp; + ent_t intern = { TRUE, NULL, {NULL, 0, 0} }; status = internal_setgrent (&intern); if (status != NSS_STATUS_SUCCESS) @@ -599,59 +419,14 @@ _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, do { - while ((status = - internal_getgrent_r (&grpbuf, &intern, tmpbuf, buflen, - errnop)) == NSS_STATUS_TRYAGAIN - && *errnop == ERANGE) - { - buflen *= 2; - tmpbuf = __alloca (buflen); - } - - if (status != NSS_STATUS_SUCCESS) - goto done; - - g = &grpbuf; - if (g->gr_gid != group) - { - char **m; - - for (m = g->gr_mem; *m != NULL; ++m) - if (strcmp (*m, user) == 0) - { - /* Matches user. Insert this group. */ - if (*start == *size) - { - /* Need a bigger buffer. */ - gid_t *newgroups; - long int newsize; - - if (limit > 0 && *size == limit) - /* We reached the maximum. */ - goto done; - - if (limit <= 0) - newsize = 2 * *size; - else - newsize = MIN (limit, 2 * *size); - - newgroups = realloc (groups, newsize * sizeof (*groups)); - if (newgroups == NULL) - goto done; - *groupsp = groups = newgroups; - *size = newsize; - } - - groups[*start] = g->gr_gid; - *start += 1; - - break; - } - } + while ((status = internal_getgrent_r (&intern, tmpbuf, buflen, + user, group, start, size, + groupsp, limit, errnop)) + == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) + tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen); } while (status == NSS_STATUS_SUCCESS); -done: internal_endgrent (&intern); return NSS_STATUS_SUCCESS; @@ -666,7 +441,7 @@ blacklist_store_name (const char *name, ent_t *ent) int namelen = strlen (name); char *tmp; - /* first call, setup cache */ + /* First call, setup cache. */ if (ent->blacklist.size == 0) { ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); @@ -716,9 +491,7 @@ in_blacklist (const char *name, int namelen, ent_t *ent) buf[0] = '|'; cp = stpcpy (&buf[1], name); - *cp++= '|'; + *cp++ = '|'; *cp = '\0'; return strstr (ent->blacklist.data, buf) != NULL; } - -#endif diff --git a/nis/nss_compat/compat-pwd.c b/nis/nss_compat/compat-pwd.c index d8b9ba18d6..350a638644 100644 --- a/nis/nss_compat/compat-pwd.c +++ b/nis/nss_compat/compat-pwd.c @@ -588,12 +588,13 @@ getpwent_next_file (struct passwd *result, ent_t *ent, if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' && result->pw_name[1] != '@') { - char buf[strlen (result->pw_name)]; + size_t len = strlen (result->pw_name); + char buf[len]; enum nss_status status; /* Store the User in the blacklist for the "+" at the end of /etc/passwd */ - strcpy (buf, &result->pw_name[1]); + memcpy (buf, &result->pw_name[1], len); status = getpwnam_plususer (&result->pw_name[1], result, ent, buffer, buflen, errnop); blacklist_store_name (buf, ent); @@ -942,10 +943,12 @@ internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, if (result->pw_name[0] == '-' && result->pw_name[1] == '@' && result->pw_name[2] != '\0') { - char buf[strlen (result->pw_name)]; + /* -1, because we remove first two character of pw_name. */ + size_t len = strlen (result->pw_name) - 1; + char buf[len]; enum nss_status status; - strcpy (buf, &result->pw_name[2]); + memcpy (buf, &result->pw_name[2], len); status = getpwuid_plususer (uid, result, buffer, buflen, errnop); if (status == NSS_STATUS_SUCCESS && @@ -959,10 +962,12 @@ internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, if (result->pw_name[0] == '+' && result->pw_name[1] == '@' && result->pw_name[2] != '\0') { - char buf[strlen (result->pw_name)]; + /* -1, because we remove first two characters of pw_name. */ + size_t len = strlen (result->pw_name) - 1; + char buf[len]; enum nss_status status; - strcpy (buf, &result->pw_name[2]); + memcpy (buf, &result->pw_name[2], len); status = getpwuid_plususer (uid, result, buffer, buflen, errnop); @@ -986,10 +991,11 @@ internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' && result->pw_name[1] != '@') { - char buf[strlen (result->pw_name)]; + size_t len = strlen (result->pw_name); + char buf[len]; enum nss_status status; - strcpy (buf, &result->pw_name[1]); + memcpy (buf, &result->pw_name[1], len); status = getpwuid_plususer (uid, result, buffer, buflen, errnop); if (status == NSS_STATUS_SUCCESS && @@ -1002,10 +1008,11 @@ internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' && result->pw_name[1] != '@') { - char buf[strlen (result->pw_name)]; + size_t len = strlen (result->pw_name); + char buf[len]; enum nss_status status; - strcpy (buf, &result->pw_name[1]); + memcpy (buf, &result->pw_name[1], len); status = getpwuid_plususer (uid, result, buffer, buflen, errnop); |