|
|
ce426f |
commit ced8f8933673f4efda1d666d26a1a949602035ed
|
|
|
ce426f |
Author: Stephen Gallagher <sgallagh@redhat.com>
|
|
|
ce426f |
Date: Fri Apr 29 22:11:09 2016 -0400
|
|
|
ce426f |
|
|
|
ce426f |
NSS: Implement group merging support.
|
|
|
ce426f |
|
|
|
ce426f |
commit 2413e73c32fc36470885ae548631e081d66f4201
|
|
|
ce426f |
Author: Zack Weinberg <zackw@panix.com>
|
|
|
ce426f |
Date: Mon Jul 18 09:33:21 2016 -0300
|
|
|
ce426f |
|
|
|
ce426f |
Don't install the internal header grp-merge.h
|
|
|
ce426f |
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/Makefile
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/Makefile
|
|
|
ce426f |
@@ -23,7 +23,8 @@
|
|
|
ce426f |
|
|
|
ce426f |
routines := fgetgrent initgroups setgroups \
|
|
|
ce426f |
getgrent getgrgid getgrnam putgrent \
|
|
|
ce426f |
- getgrent_r getgrgid_r getgrnam_r fgetgrent_r
|
|
|
ce426f |
+ getgrent_r getgrgid_r getgrnam_r fgetgrent_r \
|
|
|
ce426f |
+ grp-merge
|
|
|
ce426f |
|
|
|
ce426f |
include ../Makeconfig
|
|
|
ce426f |
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/Versions
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/Versions
|
|
|
ce426f |
@@ -28,4 +28,7 @@
|
|
|
ce426f |
# g*
|
|
|
ce426f |
getgrouplist;
|
|
|
ce426f |
}
|
|
|
ce426f |
+ GLIBC_PRIVATE {
|
|
|
ce426f |
+ __merge_grp; __copy_grp;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
}
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/getgrgid_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/getgrgid_r.c
|
|
|
ce426f |
@@ -18,6 +18,7 @@
|
|
|
ce426f |
|
|
|
ce426f |
#include <grp.h>
|
|
|
ce426f |
|
|
|
ce426f |
+#include <grp-merge.h>
|
|
|
ce426f |
|
|
|
ce426f |
#define LOOKUP_TYPE struct group
|
|
|
ce426f |
#define FUNCTION_NAME getgrgid
|
|
|
ce426f |
@@ -25,5 +26,7 @@
|
|
|
ce426f |
#define ADD_PARAMS gid_t gid
|
|
|
ce426f |
#define ADD_VARIABLES gid
|
|
|
ce426f |
#define BUFLEN NSS_BUFLEN_GROUP
|
|
|
ce426f |
+#define DEEPCOPY_FN __copy_grp
|
|
|
ce426f |
+#define MERGE_FN __merge_grp
|
|
|
ce426f |
|
|
|
ce426f |
#include <nss/getXXbyYY_r.c>
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/getgrnam_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/getgrnam_r.c
|
|
|
ce426f |
@@ -18,6 +18,7 @@
|
|
|
ce426f |
|
|
|
ce426f |
#include <grp.h>
|
|
|
ce426f |
|
|
|
ce426f |
+#include <grp-merge.h>
|
|
|
ce426f |
|
|
|
ce426f |
#define LOOKUP_TYPE struct group
|
|
|
ce426f |
#define FUNCTION_NAME getgrnam
|
|
|
ce426f |
@@ -25,4 +26,7 @@
|
|
|
ce426f |
#define ADD_PARAMS const char *name
|
|
|
ce426f |
#define ADD_VARIABLES name
|
|
|
ce426f |
|
|
|
ce426f |
+#define DEEPCOPY_FN __copy_grp
|
|
|
ce426f |
+#define MERGE_FN __merge_grp
|
|
|
ce426f |
+
|
|
|
ce426f |
#include <nss/getXXbyYY_r.c>
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/grp-merge.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/grp-merge.c
|
|
|
ce426f |
@@ -0,0 +1,186 @@
|
|
|
ce426f |
+/* Group merging implementation.
|
|
|
ce426f |
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
|
|
ce426f |
+ This file is part of the GNU C Library.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
ce426f |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
ce426f |
+ License as published by the Free Software Foundation; either
|
|
|
ce426f |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
ce426f |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
ce426f |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
ce426f |
+ Lesser General Public License for more details.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
ce426f |
+ License along with the GNU C Library; if not, see
|
|
|
ce426f |
+ <http://www.gnu.org/licenses/>. */
|
|
|
ce426f |
+
|
|
|
ce426f |
+#include <errno.h>
|
|
|
ce426f |
+#include <stdlib.h>
|
|
|
ce426f |
+#include <string.h>
|
|
|
ce426f |
+#include <grp.h>
|
|
|
ce426f |
+#include <grp-merge.h>
|
|
|
ce426f |
+
|
|
|
ce426f |
+#define BUFCHECK(size) \
|
|
|
ce426f |
+ ({ \
|
|
|
ce426f |
+ do \
|
|
|
ce426f |
+ { \
|
|
|
ce426f |
+ if (c + (size) > buflen) \
|
|
|
ce426f |
+ { \
|
|
|
ce426f |
+ free (members); \
|
|
|
ce426f |
+ return ERANGE; \
|
|
|
ce426f |
+ } \
|
|
|
ce426f |
+ } \
|
|
|
ce426f |
+ while (0); \
|
|
|
ce426f |
+ })
|
|
|
ce426f |
+
|
|
|
ce426f |
+int
|
|
|
ce426f |
+internal_function
|
|
|
ce426f |
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
|
|
ce426f |
+ struct group *destgrp, char *destbuf, char **endptr)
|
|
|
ce426f |
+{
|
|
|
ce426f |
+ size_t i;
|
|
|
ce426f |
+ size_t c = 0;
|
|
|
ce426f |
+ size_t len;
|
|
|
ce426f |
+ size_t memcount;
|
|
|
ce426f |
+ char **members = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy the GID. */
|
|
|
ce426f |
+ destgrp->gr_gid = srcgrp.gr_gid;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy the name. */
|
|
|
ce426f |
+ len = strlen (srcgrp.gr_name) + 1;
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&destbuf[c], srcgrp.gr_name, len);
|
|
|
ce426f |
+ destgrp->gr_name = &destbuf[c];
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy the password. */
|
|
|
ce426f |
+ len = strlen (srcgrp.gr_passwd) + 1;
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&destbuf[c], srcgrp.gr_passwd, len);
|
|
|
ce426f |
+ destgrp->gr_passwd = &destbuf[c];
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Count all of the members. */
|
|
|
ce426f |
+ for (memcount = 0; srcgrp.gr_mem[memcount]; memcount++)
|
|
|
ce426f |
+ ;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Allocate a temporary holding area for the pointers to the member
|
|
|
ce426f |
+ contents, including space for a NULL-terminator. */
|
|
|
ce426f |
+ members = malloc (sizeof (char *) * (memcount + 1));
|
|
|
ce426f |
+ if (members == NULL)
|
|
|
ce426f |
+ return ENOMEM;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy all of the group members to destbuf and add a pointer to each of
|
|
|
ce426f |
+ them into the 'members' array. */
|
|
|
ce426f |
+ for (i = 0; srcgrp.gr_mem[i]; i++)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ len = strlen (srcgrp.gr_mem[i]) + 1;
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&destbuf[c], srcgrp.gr_mem[i], len);
|
|
|
ce426f |
+ members[i] = &destbuf[c];
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+ members[i] = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy the pointers from the members array into the buffer and assign them
|
|
|
ce426f |
+ to the gr_mem member of destgrp. */
|
|
|
ce426f |
+ destgrp->gr_mem = (char **) &destbuf[c];
|
|
|
ce426f |
+ len = sizeof (char *) * (memcount + 1);
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&destbuf[c], members, len);
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+ free (members);
|
|
|
ce426f |
+ members = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Save the count of members at the end. */
|
|
|
ce426f |
+ BUFCHECK (sizeof (size_t));
|
|
|
ce426f |
+ memcpy (&destbuf[c], &memcount, sizeof (size_t));
|
|
|
ce426f |
+ c += sizeof (size_t);
|
|
|
ce426f |
+
|
|
|
ce426f |
+ if (endptr)
|
|
|
ce426f |
+ *endptr = destbuf + c;
|
|
|
ce426f |
+ return 0;
|
|
|
ce426f |
+}
|
|
|
ce426f |
+libc_hidden_def (__copy_grp)
|
|
|
ce426f |
+
|
|
|
ce426f |
+/* Check that the name, GID and passwd fields match, then
|
|
|
ce426f |
+ copy in the gr_mem array. */
|
|
|
ce426f |
+int
|
|
|
ce426f |
+internal_function
|
|
|
ce426f |
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
|
|
ce426f |
+ size_t buflen, struct group *mergegrp, char *mergebuf)
|
|
|
ce426f |
+{
|
|
|
ce426f |
+ size_t c, i, len;
|
|
|
ce426f |
+ size_t savedmemcount;
|
|
|
ce426f |
+ size_t memcount;
|
|
|
ce426f |
+ size_t membersize;
|
|
|
ce426f |
+ char **members = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* We only support merging members of groups with identical names and
|
|
|
ce426f |
+ GID values. If we hit this case, we need to overwrite the current
|
|
|
ce426f |
+ buffer with the saved one (which is functionally equivalent to
|
|
|
ce426f |
+ treating the new lookup as NSS_STATUS_NOTFOUND). */
|
|
|
ce426f |
+ if (mergegrp->gr_gid != savedgrp->gr_gid
|
|
|
ce426f |
+ || strcmp (mergegrp->gr_name, savedgrp->gr_name))
|
|
|
ce426f |
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Get the count of group members from the last sizeof (size_t) bytes in the
|
|
|
ce426f |
+ mergegrp buffer. */
|
|
|
ce426f |
+ savedmemcount = (size_t) *(savedend - sizeof (size_t));
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Get the count of new members to add. */
|
|
|
ce426f |
+ for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++)
|
|
|
ce426f |
+ ;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Create a temporary array to hold the pointers to the member values from
|
|
|
ce426f |
+ both the saved and merge groups. */
|
|
|
ce426f |
+ membersize = savedmemcount + memcount + 1;
|
|
|
ce426f |
+ members = malloc (sizeof (char *) * membersize);
|
|
|
ce426f |
+ if (members == NULL)
|
|
|
ce426f |
+ return ENOMEM;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy in the existing member pointers from the saved group
|
|
|
ce426f |
+ Note: this is not NULL-terminated yet. */
|
|
|
ce426f |
+ memcpy (members, savedgrp->gr_mem, sizeof (char *) * savedmemcount);
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Back up into the savedbuf until we get back to the NULL-terminator of the
|
|
|
ce426f |
+ group member list. (This means walking back savedmemcount + 1 (char *) pointers
|
|
|
ce426f |
+ and the member count value.
|
|
|
ce426f |
+ The value of c is going to be the used length of the buffer backed up by
|
|
|
ce426f |
+ the member count and further backed up by the size of the pointers. */
|
|
|
ce426f |
+ c = savedend - savedbuf
|
|
|
ce426f |
+ - sizeof (size_t)
|
|
|
ce426f |
+ - sizeof (char *) * (savedmemcount + 1);
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Add all the new group members, overwriting the old NULL-terminator while
|
|
|
ce426f |
+ adding the new pointers to the temporary array. */
|
|
|
ce426f |
+ for (i = 0; mergegrp->gr_mem[i]; i++)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ len = strlen (mergegrp->gr_mem[i]) + 1;
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&savedbuf[c], mergegrp->gr_mem[i], len);
|
|
|
ce426f |
+ members[savedmemcount + i] = &savedbuf[c];
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+ /* Add the NULL-terminator. */
|
|
|
ce426f |
+ members[savedmemcount + memcount] = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Copy the member array back into the buffer after the member list and free
|
|
|
ce426f |
+ the member array. */
|
|
|
ce426f |
+ savedgrp->gr_mem = (char **) &savedbuf[c];
|
|
|
ce426f |
+ len = sizeof (char *) * membersize;
|
|
|
ce426f |
+ BUFCHECK (len);
|
|
|
ce426f |
+ memcpy (&savedbuf[c], members, len);
|
|
|
ce426f |
+ c += len;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ free (members);
|
|
|
ce426f |
+ members = NULL;
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* Finally, copy the results back into mergebuf, since that's the buffer
|
|
|
ce426f |
+ that we were provided by the caller. */
|
|
|
ce426f |
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
|
|
ce426f |
+}
|
|
|
ce426f |
+libc_hidden_def (__merge_grp)
|
|
|
ce426f |
--- glibc-2.17-c758a686/grp/grp-merge.h
|
|
|
ce426f |
+++ glibc-2.17-c758a686/grp/grp-merge.h
|
|
|
ce426f |
@@ -0,0 +1,37 @@
|
|
|
ce426f |
+/* Group merging implementation.
|
|
|
ce426f |
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
|
|
ce426f |
+ This file is part of the GNU C Library.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
ce426f |
+ modify it under the terms of the GNU Lesser General Public
|
|
|
ce426f |
+ License as published by the Free Software Foundation; either
|
|
|
ce426f |
+ version 2.1 of the License, or (at your option) any later version.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
ce426f |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
ce426f |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
ce426f |
+ Lesser General Public License for more details.
|
|
|
ce426f |
+
|
|
|
ce426f |
+ You should have received a copy of the GNU Lesser General Public
|
|
|
ce426f |
+ License along with the GNU C Library; if not, see
|
|
|
ce426f |
+ <http://www.gnu.org/licenses/>. */
|
|
|
ce426f |
+
|
|
|
ce426f |
+#ifndef _GRP_MERGE_H
|
|
|
ce426f |
+#define _GRP_MERGE_H 1
|
|
|
ce426f |
+
|
|
|
ce426f |
+#include <grp.h>
|
|
|
ce426f |
+
|
|
|
ce426f |
+/* Duplicate a grp struct (and its members). When no longer needed, the
|
|
|
ce426f |
+ calling function must free(newbuf). */
|
|
|
ce426f |
+int
|
|
|
ce426f |
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
|
|
ce426f |
+ struct group *destgrp, char *destbuf, char **endptr)
|
|
|
ce426f |
+ internal_function;
|
|
|
ce426f |
+
|
|
|
ce426f |
+/* Merge the member lists of two grp structs together. */
|
|
|
ce426f |
+int
|
|
|
ce426f |
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
|
|
ce426f |
+ size_t buflen, struct group *mergegrp, char *mergebuf)
|
|
|
ce426f |
+ internal_function;
|
|
|
ce426f |
+
|
|
|
ce426f |
+#endif /* _GRP_MERGE_H */
|
|
|
ce426f |
--- glibc-2.17-c758a686/include/grp-merge.h
|
|
|
ce426f |
+++ glibc-2.17-c758a686/include/grp-merge.h
|
|
|
ce426f |
@@ -0,0 +1,7 @@
|
|
|
ce426f |
+#ifndef _GRP_MERGE_H
|
|
|
ce426f |
+#include <grp/grp-merge.h>
|
|
|
ce426f |
+
|
|
|
ce426f |
+libc_hidden_proto (__copy_grp)
|
|
|
ce426f |
+libc_hidden_proto (__merge_grp)
|
|
|
ce426f |
+
|
|
|
ce426f |
+#endif /* _GRP_MERGE_H */
|
|
|
ce426f |
--- glibc-2.17-c758a686/manual/nss.texi
|
|
|
ce426f |
+++ glibc-2.17-c758a686/manual/nss.texi
|
|
|
ce426f |
@@ -180,7 +180,7 @@
|
|
|
ce426f |
|
|
|
ce426f |
The case of the keywords is insignificant. The @var{status}
|
|
|
ce426f |
values are the results of a call to a lookup function of a specific
|
|
|
ce426f |
-service. They mean
|
|
|
ce426f |
+service. They mean:
|
|
|
ce426f |
|
|
|
ce426f |
@ftable @samp
|
|
|
ce426f |
@item success
|
|
|
ce426f |
@@ -204,6 +204,50 @@
|
|
|
ce426f |
@end ftable
|
|
|
ce426f |
|
|
|
ce426f |
@noindent
|
|
|
ce426f |
+The @var{action} values mean:
|
|
|
ce426f |
+
|
|
|
ce426f |
+@ftable @samp
|
|
|
ce426f |
+@item return
|
|
|
ce426f |
+
|
|
|
ce426f |
+If the status matches, stop the lookup process at this service
|
|
|
ce426f |
+specification. If an entry is available, provide it to the application.
|
|
|
ce426f |
+If an error occurred, report it to the application. In case of a prior
|
|
|
ce426f |
+@samp{merge} action, the data is combined with previous lookup results,
|
|
|
ce426f |
+as explained below.
|
|
|
ce426f |
+
|
|
|
ce426f |
+@item continue
|
|
|
ce426f |
+
|
|
|
ce426f |
+If the status matches, proceed with the lookup process at the next
|
|
|
ce426f |
+entry, discarding the result of the current lookup (and any merged
|
|
|
ce426f |
+data). An exception is the @samp{initgroups} database and the
|
|
|
ce426f |
+@samp{success} status, where @samp{continue} acts like @code{merge}
|
|
|
ce426f |
+below.
|
|
|
ce426f |
+
|
|
|
ce426f |
+@item merge
|
|
|
ce426f |
+
|
|
|
ce426f |
+Proceed with the lookup process, retaining the current lookup result.
|
|
|
ce426f |
+This action is useful only with the @samp{success} status. If a
|
|
|
ce426f |
+subsequent service lookup succeeds and has a matching @samp{return}
|
|
|
ce426f |
+specification, the results are merged, the lookup process ends, and the
|
|
|
ce426f |
+merged results are returned to the application. If the following service
|
|
|
ce426f |
+has a matching @samp{merge} action, the lookup process continues,
|
|
|
ce426f |
+retaining the combined data from this and any previous lookups.
|
|
|
ce426f |
+
|
|
|
ce426f |
+After a @code{merge} action, errors from subsequent lookups are ignored,
|
|
|
ce426f |
+and the data gathered so far will be returned.
|
|
|
ce426f |
+
|
|
|
ce426f |
+The @samp{merge} only applies to the @samp{success} status. It is
|
|
|
ce426f |
+currently implemented for the @samp{group} database and its group
|
|
|
ce426f |
+members field, @samp{gr_mem}. If specified for other databases, it
|
|
|
ce426f |
+causes the lookup to fail (if the @var{status} matches).
|
|
|
ce426f |
+
|
|
|
ce426f |
+When processing @samp{merge} for @samp{group} membership, the group GID
|
|
|
ce426f |
+and name must be identical for both entries. If only one or the other is
|
|
|
ce426f |
+a match, the behavior is undefined.
|
|
|
ce426f |
+
|
|
|
ce426f |
+@end ftable
|
|
|
ce426f |
+
|
|
|
ce426f |
+@noindent
|
|
|
ce426f |
If we have a line like
|
|
|
ce426f |
|
|
|
ce426f |
@smallexample
|
|
|
ce426f |
--- glibc-2.17-c758a686/nscd/getgrgid_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nscd/getgrgid_r.c
|
|
|
ce426f |
@@ -17,6 +17,7 @@
|
|
|
ce426f |
|
|
|
ce426f |
#include <grp.h>
|
|
|
ce426f |
|
|
|
ce426f |
+#include <grp-merge.h>
|
|
|
ce426f |
|
|
|
ce426f |
#define LOOKUP_TYPE struct group
|
|
|
ce426f |
#define FUNCTION_NAME getgrgid
|
|
|
ce426f |
@@ -25,6 +26,9 @@
|
|
|
ce426f |
#define ADD_VARIABLES gid
|
|
|
ce426f |
#define BUFLEN NSS_BUFLEN_GROUP
|
|
|
ce426f |
|
|
|
ce426f |
+#define DEEPCOPY_FN __copy_grp
|
|
|
ce426f |
+#define MERGE_FN __merge_grp
|
|
|
ce426f |
+
|
|
|
ce426f |
/* We are nscd, so we don't want to be talking to ourselves. */
|
|
|
ce426f |
#undef USE_NSCD
|
|
|
ce426f |
|
|
|
ce426f |
--- glibc-2.17-c758a686/nscd/getgrnam_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nscd/getgrnam_r.c
|
|
|
ce426f |
@@ -17,6 +17,7 @@
|
|
|
ce426f |
|
|
|
ce426f |
#include <grp.h>
|
|
|
ce426f |
|
|
|
ce426f |
+#include <grp-merge.h>
|
|
|
ce426f |
|
|
|
ce426f |
#define LOOKUP_TYPE struct group
|
|
|
ce426f |
#define FUNCTION_NAME getgrnam
|
|
|
ce426f |
@@ -24,6 +25,9 @@
|
|
|
ce426f |
#define ADD_PARAMS const char *name
|
|
|
ce426f |
#define ADD_VARIABLES name
|
|
|
ce426f |
|
|
|
ce426f |
+#define DEEPCOPY_FN __copy_grp
|
|
|
ce426f |
+#define MERGE_FN __merge_grp
|
|
|
ce426f |
+
|
|
|
ce426f |
/* We are nscd, so we don't want to be talking to ourselves. */
|
|
|
ce426f |
#undef USE_NSCD
|
|
|
ce426f |
|
|
|
ce426f |
--- glibc-2.17-c758a686/nss/getXXbyYY_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nss/getXXbyYY_r.c
|
|
|
ce426f |
@@ -131,6 +131,52 @@
|
|
|
ce426f |
# define AF_VAL AF_INET
|
|
|
ce426f |
#endif
|
|
|
ce426f |
|
|
|
ce426f |
+
|
|
|
ce426f |
+/* Set defaults for merge functions that haven't been defined. */
|
|
|
ce426f |
+#ifndef DEEPCOPY_FN
|
|
|
ce426f |
+static inline int
|
|
|
ce426f |
+__copy_einval (LOOKUP_TYPE a,
|
|
|
ce426f |
+ const size_t b,
|
|
|
ce426f |
+ LOOKUP_TYPE *c,
|
|
|
ce426f |
+ char *d,
|
|
|
ce426f |
+ char **e)
|
|
|
ce426f |
+{
|
|
|
ce426f |
+ return EINVAL;
|
|
|
ce426f |
+}
|
|
|
ce426f |
+# define DEEPCOPY_FN __copy_einval
|
|
|
ce426f |
+#endif
|
|
|
ce426f |
+
|
|
|
ce426f |
+#ifndef MERGE_FN
|
|
|
ce426f |
+static inline int
|
|
|
ce426f |
+__merge_einval (LOOKUP_TYPE *a,
|
|
|
ce426f |
+ char *b,
|
|
|
ce426f |
+ char *c,
|
|
|
ce426f |
+ size_t d,
|
|
|
ce426f |
+ LOOKUP_TYPE *e,
|
|
|
ce426f |
+ char *f)
|
|
|
ce426f |
+{
|
|
|
ce426f |
+ return EINVAL;
|
|
|
ce426f |
+}
|
|
|
ce426f |
+# define MERGE_FN __merge_einval
|
|
|
ce426f |
+#endif
|
|
|
ce426f |
+
|
|
|
ce426f |
+#define CHECK_MERGE(err, status) \
|
|
|
ce426f |
+ ({ \
|
|
|
ce426f |
+ do \
|
|
|
ce426f |
+ { \
|
|
|
ce426f |
+ if (err) \
|
|
|
ce426f |
+ { \
|
|
|
ce426f |
+ __set_errno (err); \
|
|
|
ce426f |
+ if (err == ERANGE) \
|
|
|
ce426f |
+ status = NSS_STATUS_TRYAGAIN; \
|
|
|
ce426f |
+ else \
|
|
|
ce426f |
+ status = NSS_STATUS_UNAVAIL; \
|
|
|
ce426f |
+ break; \
|
|
|
ce426f |
+ } \
|
|
|
ce426f |
+ } \
|
|
|
ce426f |
+ while (0); \
|
|
|
ce426f |
+ })
|
|
|
ce426f |
+
|
|
|
ce426f |
/* Type of the lookup function we need here. */
|
|
|
ce426f |
typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
|
|
|
ce426f |
size_t, int * H_ERRNO_PARM
|
|
|
ce426f |
@@ -152,13 +198,16 @@
|
|
|
ce426f |
static service_user *startp;
|
|
|
ce426f |
static lookup_function start_fct;
|
|
|
ce426f |
service_user *nip;
|
|
|
ce426f |
+ int do_merge = 0;
|
|
|
ce426f |
+ LOOKUP_TYPE mergegrp;
|
|
|
ce426f |
+ char *mergebuf = NULL;
|
|
|
ce426f |
+ char *endptr = NULL;
|
|
|
ce426f |
union
|
|
|
ce426f |
{
|
|
|
ce426f |
lookup_function l;
|
|
|
ce426f |
void *ptr;
|
|
|
ce426f |
} fct;
|
|
|
ce426f |
-
|
|
|
ce426f |
- int no_more;
|
|
|
ce426f |
+ int no_more, err;
|
|
|
ce426f |
enum nss_status status = NSS_STATUS_UNAVAIL;
|
|
|
ce426f |
#ifdef USE_NSCD
|
|
|
ce426f |
int nscd_status;
|
|
|
ce426f |
@@ -278,9 +327,66 @@
|
|
|
ce426f |
&& errno == ERANGE)
|
|
|
ce426f |
break;
|
|
|
ce426f |
|
|
|
ce426f |
+ if (do_merge)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+
|
|
|
ce426f |
+ if (status == NSS_STATUS_SUCCESS)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ /* The previous loop saved a buffer for merging.
|
|
|
ce426f |
+ Perform the merge now. */
|
|
|
ce426f |
+ err = MERGE_FN (&mergegrp, mergebuf, endptr, buflen, resbuf,
|
|
|
ce426f |
+ buffer);
|
|
|
ce426f |
+ CHECK_MERGE (err,status);
|
|
|
ce426f |
+ do_merge = 0;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+ else
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ /* If the result wasn't SUCCESS, copy the saved buffer back
|
|
|
ce426f |
+ into the result buffer and set the status back to
|
|
|
ce426f |
+ NSS_STATUS_SUCCESS to match the previous pass through the
|
|
|
ce426f |
+ loop.
|
|
|
ce426f |
+ * If the next action is CONTINUE, it will overwrite the value
|
|
|
ce426f |
+ currently in the buffer and return the new value.
|
|
|
ce426f |
+ * If the next action is RETURN, we'll return the previously-
|
|
|
ce426f |
+ acquired values.
|
|
|
ce426f |
+ * If the next action is MERGE, then it will be added to the
|
|
|
ce426f |
+ buffer saved from the previous source. */
|
|
|
ce426f |
+ err = DEEPCOPY_FN (mergegrp, buflen, resbuf, buffer, NULL);
|
|
|
ce426f |
+ CHECK_MERGE (err, status);
|
|
|
ce426f |
+ status = NSS_STATUS_SUCCESS;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* If we were are configured to merge this value with the next one,
|
|
|
ce426f |
+ save the current value of the group struct. */
|
|
|
ce426f |
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE
|
|
|
ce426f |
+ && status == NSS_STATUS_SUCCESS)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ /* Copy the current values into a buffer to be merged with the next
|
|
|
ce426f |
+ set of retrieved values. */
|
|
|
ce426f |
+ if (mergebuf == NULL)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ /* Only allocate once and reuse it for as many merges as we need
|
|
|
ce426f |
+ to perform. */
|
|
|
ce426f |
+ mergebuf = malloc (buflen);
|
|
|
ce426f |
+ if (mergebuf == NULL)
|
|
|
ce426f |
+ {
|
|
|
ce426f |
+ __set_errno (ENOMEM);
|
|
|
ce426f |
+ status = NSS_STATUS_UNAVAIL;
|
|
|
ce426f |
+ break;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+
|
|
|
ce426f |
+ err = DEEPCOPY_FN (*resbuf, buflen, &mergegrp, mergebuf, &endptr);
|
|
|
ce426f |
+ CHECK_MERGE (err, status);
|
|
|
ce426f |
+ do_merge = 1;
|
|
|
ce426f |
+ }
|
|
|
ce426f |
+
|
|
|
ce426f |
no_more = __nss_next2 (&nip, REENTRANT_NAME_STRING,
|
|
|
ce426f |
REENTRANT2_NAME_STRING, &fct.ptr, status, 0);
|
|
|
ce426f |
}
|
|
|
ce426f |
+ free (mergebuf);
|
|
|
ce426f |
+ mergebuf = NULL;
|
|
|
ce426f |
|
|
|
ce426f |
#ifdef HANDLE_DIGITS_DOTS
|
|
|
ce426f |
done:
|
|
|
ce426f |
--- glibc-2.17-c758a686/nss/getnssent_r.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nss/getnssent_r.c
|
|
|
ce426f |
@@ -79,7 +79,18 @@
|
|
|
ce426f |
else
|
|
|
ce426f |
status = DL_CALL_FCT (fct.f, (0));
|
|
|
ce426f |
|
|
|
ce426f |
- no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
|
|
ce426f |
+
|
|
|
ce426f |
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
|
|
ce426f |
+ _nss_next2() will skip to the next database. Due to the
|
|
|
ce426f |
+ implementation of that function, we can't know whether we're
|
|
|
ce426f |
+ in an enumeration or an individual lookup, which behaves
|
|
|
ce426f |
+ differently with regards to merging. We'll treat SUCCESS as
|
|
|
ce426f |
+ an indication to start the enumeration at this database. */
|
|
|
ce426f |
+ if (nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
|
|
ce426f |
+ no_more = 1;
|
|
|
ce426f |
+ else
|
|
|
ce426f |
+ no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
|
|
ce426f |
+
|
|
|
ce426f |
if (is_last_nip)
|
|
|
ce426f |
*last_nip = *nip;
|
|
|
ce426f |
}
|
|
|
ce426f |
@@ -175,8 +186,18 @@
|
|
|
ce426f |
|
|
|
ce426f |
do
|
|
|
ce426f |
{
|
|
|
ce426f |
- no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
|
|
ce426f |
- status, 0);
|
|
|
ce426f |
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
|
|
ce426f |
+ _nss_next2() will skip to the next database. Due to the
|
|
|
ce426f |
+ implementation of that function, we can't know whether we're
|
|
|
ce426f |
+ in an enumeration or an individual lookup, which behaves
|
|
|
ce426f |
+ differently with regards to merging. We'll treat SUCCESS as
|
|
|
ce426f |
+ an indication to return the results here. */
|
|
|
ce426f |
+ if (status == NSS_STATUS_SUCCESS
|
|
|
ce426f |
+ && nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
|
|
ce426f |
+ no_more = 1;
|
|
|
ce426f |
+ else
|
|
|
ce426f |
+ no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
|
|
ce426f |
+ status, 0);
|
|
|
ce426f |
|
|
|
ce426f |
if (is_last_nip)
|
|
|
ce426f |
*last_nip = *nip;
|
|
|
ce426f |
--- glibc-2.17-c758a686/nss/nsswitch.c
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nss/nsswitch.c
|
|
|
ce426f |
@@ -712,6 +712,9 @@
|
|
|
ce426f |
else if (line - name == 8
|
|
|
ce426f |
&& __strncasecmp (name, "CONTINUE", 8) == 0)
|
|
|
ce426f |
action = NSS_ACTION_CONTINUE;
|
|
|
ce426f |
+ else if (line - name == 5
|
|
|
ce426f |
+ && __strncasecmp (name, "MERGE", 5) == 0)
|
|
|
ce426f |
+ action = NSS_ACTION_MERGE;
|
|
|
ce426f |
else
|
|
|
ce426f |
goto finish;
|
|
|
ce426f |
|
|
|
ce426f |
--- glibc-2.17-c758a686/nss/nsswitch.h
|
|
|
ce426f |
+++ glibc-2.17-c758a686/nss/nsswitch.h
|
|
|
ce426f |
@@ -32,7 +32,8 @@
|
|
|
ce426f |
typedef enum
|
|
|
ce426f |
{
|
|
|
ce426f |
NSS_ACTION_CONTINUE,
|
|
|
ce426f |
- NSS_ACTION_RETURN
|
|
|
ce426f |
+ NSS_ACTION_RETURN,
|
|
|
ce426f |
+ NSS_ACTION_MERGE
|
|
|
ce426f |
} lookup_actions;
|
|
|
ce426f |
|
|
|
ce426f |
|