From 426039bdd70a5502d56fbc2a9dcde5817b145c1c Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Sat, 21 Sep 2019 21:17:34 +0000 Subject: Add getgrouplist() support (stubbed in nsssd-nslcd) --- src/libnsss/deps-lib/nsss | 7 ++- src/libnsss/nsss-internal.h | 2 +- src/libnsss/nsss_all_getgrouplist.c | 35 ++++++++++++++ src/libnsss/nsss_grouplist_adjust.c | 24 ++++++++++ src/libnsss/nsss_switch_getgrouplist.c | 30 ++++++++++++ src/libnsss/nsss_switch_grp_getlist.c | 66 ++++++++++++++++++++++++++ src/libnsss/nsss_unix_getgrouplist.c | 34 ++----------- src/libnsss/nsss_unix_getgrouplist_preadjust.c | 22 +++++++++ src/libnsss/nsss_unix_grp_getlist.c | 19 ++++---- 9 files changed, 198 insertions(+), 41 deletions(-) create mode 100644 src/libnsss/nsss_all_getgrouplist.c create mode 100644 src/libnsss/nsss_grouplist_adjust.c create mode 100644 src/libnsss/nsss_switch_getgrouplist.c create mode 100644 src/libnsss/nsss_switch_grp_getlist.c create mode 100644 src/libnsss/nsss_unix_getgrouplist_preadjust.c (limited to 'src/libnsss') diff --git a/src/libnsss/deps-lib/nsss b/src/libnsss/deps-lib/nsss index 1886bdf..e00084e 100644 --- a/src/libnsss/deps-lib/nsss +++ b/src/libnsss/deps-lib/nsss @@ -8,6 +8,7 @@ nsss_all_getgrgid.o nsss_all_getgrgid_r.o nsss_all_getgrnam.o nsss_all_getgrnam_r.o +nsss_all_getgrouplist.o nsss_all_getpwent.o nsss_all_getpwent_r.o nsss_all_getpwnam.o @@ -23,6 +24,7 @@ nsss_all_setpwent.o nsss_all_setspent.o nsss_grp_copy.o nsss_grp_here.o +nsss_grouplist_adjust.o nsss_pwd_copy.o nsss_pwd_here.o nsss_shadow_copy.o @@ -37,6 +39,7 @@ nsss_switch_getgrgid.o nsss_switch_getgrgid_r.o nsss_switch_getgrnam.o nsss_switch_getgrnam_r.o +nsss_switch_getgrouplist.o nsss_switch_getpwent.o nsss_switch_getpwent_r.o nsss_switch_getpwnam.o @@ -51,6 +54,7 @@ nsss_switch_grp_end.o nsss_switch_grp_get.o nsss_switch_grp_getbygid.o nsss_switch_grp_getbyname.o +nsss_switch_grp_getlist.o nsss_switch_grp_read.o nsss_switch_grp_rewind.o nsss_switch_here.o @@ -81,6 +85,8 @@ nsss_unix_getgrgid.o nsss_unix_getgrgid_r.o nsss_unix_getgrnam.o nsss_unix_getgrnam_r.o +nsss_unix_getgrouplist.o +nsss_unix_getgrouplist_preadjust.o nsss_unix_getpwent.o nsss_unix_getpwent_r.o nsss_unix_getpwnam.o @@ -91,7 +97,6 @@ nsss_unix_getspent.o nsss_unix_getspent_r.o nsss_unix_getspnam.o nsss_unix_getspnam_r.o -nsss_unix_getgrouplist.o nsss_unix_grp_get.o nsss_unix_grp_getbygid.o nsss_unix_grp_getbyname.o diff --git a/src/libnsss/nsss-internal.h b/src/libnsss/nsss-internal.h index f9dbeb3..a67b5f7 100644 --- a/src/libnsss/nsss-internal.h +++ b/src/libnsss/nsss-internal.h @@ -24,7 +24,7 @@ extern struct group nsss_grp_here ; extern stralloc nsss_grp_sa_here ; extern genalloc nsss_grp_ga_here ; extern int nsss_grp_copy (struct group *, char *, size_t, struct group const *, char const *, size_t, char *const *, size_t) ; - +extern int nsss_grouplist_adjust (size_t, size_t, gid_t, gid_t *, int *, int) ; /* Shadow */ diff --git a/src/libnsss/nsss_all_getgrouplist.c b/src/libnsss/nsss_all_getgrouplist.c new file mode 100644 index 0000000..0560ba7 --- /dev/null +++ b/src/libnsss/nsss_all_getgrouplist.c @@ -0,0 +1,35 @@ +/* ISC license. */ + +#include +#include + +#include + +#include +#include +#include +#include +#include "nsss-internal.h" + +int nsss_all_getgrouplist (char const *user, gid_t gid, gid_t *gids, int *ngids) +{ + stralloc sa = STRALLOC_ZERO ; + int e = errno ; + size_t r = 0 ; + size_t n ; + nsss_switch_t a = NSSS_SWITCH_ZERO ; + if (*ngids < 0) return (errno = EINVAL, -1) ; + n = *ngids ; + if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ; + if (!nsss_switch_grp_getlist(&a, user, gids, n, &r, &sa, 0, 0)) + { + nsss_switch_end(&a, NSSS_SWITCH_GRP) ; + return -1 ; + } + nsss_switch_end(&a, NSSS_SWITCH_GRP) ; + return nsss_grouplist_adjust(n, r, gid, gids, ngids, e) ; + + fallback: + errno = e ; + return nsss_unix_getgrouplist(user, gid, gids, ngids) ; +} diff --git a/src/libnsss/nsss_grouplist_adjust.c b/src/libnsss/nsss_grouplist_adjust.c new file mode 100644 index 0000000..fda4882 --- /dev/null +++ b/src/libnsss/nsss_grouplist_adjust.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include "nsss-internal.h" + +int nsss_grouplist_adjust (size_t n, size_t r, gid_t gid, gid_t *gids, int *ngids, int e) +{ + if (r > INT_MAX) return (errno = EMSGSIZE, -1) ; + if (r > n) return (*ngids = (int)r, errno = ENOBUFS, -1) ; + for (size_t i = 0 ; i < r ; i++) if (gid == gids[i]) goto ok ; + r++ ; + if (r > INT_MAX) return (errno = EMSGSIZE, -1) ; + if (r > n) return (*ngids = (int)r, errno = ENOBUFS, -1) ; + memmove(gids + 1, gids, (r-1) * sizeof(gid_t)) ; + gids[0] = gid ; + ok: + *ngids = (int)r ; + errno = e ; + return (int)n ; +} diff --git a/src/libnsss/nsss_switch_getgrouplist.c b/src/libnsss/nsss_switch_getgrouplist.c new file mode 100644 index 0000000..73d3fe0 --- /dev/null +++ b/src/libnsss/nsss_switch_getgrouplist.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#include +#include + +#include + +#include +#include +#include +#include "nsss-internal.h" + +int nsss_switch_getgrouplist (char const *user, gid_t gid, gid_t *gids, int *ngids) +{ + stralloc sa = STRALLOC_ZERO ; + int e = errno ; + size_t r = 0 ; + size_t n ; + nsss_switch_t a = NSSS_SWITCH_ZERO ; + if (*ngids < 0) return (errno = EINVAL, -1) ; + n = *ngids ; + if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return -1 ; + if (!nsss_switch_grp_getlist(&a, user, gids, n, &r, &sa, 0, 0)) + { + nsss_switch_end(&a, NSSS_SWITCH_GRP) ; + return -1 ; + } + nsss_switch_end(&a, NSSS_SWITCH_GRP) ; + return nsss_grouplist_adjust(n, r, gid, gids, ngids, e) ; +} diff --git a/src/libnsss/nsss_switch_grp_getlist.c b/src/libnsss/nsss_switch_grp_getlist.c new file mode 100644 index 0000000..70e4486 --- /dev/null +++ b/src/libnsss/nsss_switch_grp_getlist.c @@ -0,0 +1,66 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + /* + Expects: + 8 bytes: n + 8 bytes: r + min(n, r) * sizeof(gid_t) bytes: the list of gids + */ + +static int nsss_switch_grouplist_read (buffer *b, size_t n, size_t *r, gid_t *gids, stralloc *sa, tain_t const *deadline, tain_t *stamp) +{ + size_t rr ; + uint64_t res ; + char buf[8] ; + if (!buffer_timed_get(b, buf, 8, deadline, stamp)) return 0 ; + uint64_unpack_big(buf, &res) ; + if (res != n) return (errno = EPROTO, 0) ; + if (!buffer_timed_get(b, buf, 8, deadline, stamp)) return 0 ; + uint64_unpack_big(buf, &res) ; + rr = res ; + if (res > n) res = n ; + if (res) + { + int sawasnull = !sa->s ; + size_t sabase = sa->len ; + if (!stralloc_readyplus(sa, res * sizeof(gid_t))) return 0 ; + if (!buffer_timed_get(b, sa->s + sabase, res * sizeof(gid_t), deadline, stamp)) + { + if (sawasnull) stralloc_free(sa) ; else sa->len = sabase ; + return 0 ; + } + for (size_t i = 0 ; i < res ; i++) + gid_unpack_big(sa->s + sabase + i * sizeof(gid_t), gids + i) ; + if (sawasnull) stralloc_free(sa) ; else sa->len = sabase ; + } + *r = rr ; + return 1 ; +} + +int nsss_switch_grp_getlist (nsss_switch_t *a, char const *user, gid_t *gids, size_t n, size_t *r, stralloc *sa, tain_t const *deadline, tain_t *stamp) +{ + char buf[13] = { NSSS_SWITCH_GRP_GETLIST } ; + size_t len = strlen(user) ; + struct iovec v[2] = { { .iov_base = buf, .iov_len = 13 }, { .iov_base = (char *)user, .iov_len = len + 1 } } ; + if (len > NSSS_SWITCH_NAME_MAXLEN - 1) return (errno = EINVAL, 0) ; + uint64_pack_big(buf + 1, n) ; + uint32_pack_big(buf + 9, len + 1) ; + if (!ipc_timed_sendv(buffer_fd(&a->b), v, 2, deadline, stamp)) return 0 ; + if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ; + if (buf[0]) return (errno = buf[0], 0) ; + return nsss_switch_grouplist_read(&a->b, n, r, gids, sa, deadline, stamp) ; +} diff --git a/src/libnsss/nsss_unix_getgrouplist.c b/src/libnsss/nsss_unix_getgrouplist.c index e9a11ab..83a8aeb 100644 --- a/src/libnsss/nsss_unix_getgrouplist.c +++ b/src/libnsss/nsss_unix_getgrouplist.c @@ -1,43 +1,19 @@ /* ISC license. */ -#include -#include +#include #include -#include -#include -#include -#include - -#include -#include #include -#include "nsss-unix-internal.h" +#include +#include "nsss-internal.h" int nsss_unix_getgrouplist (char const *user, gid_t gid, gid_t *gids, int *ngids) { - nsss_unix_t a = NSSS_UNIX_ZERO ; - stralloc sa = STRALLOC_ZERO ; - genalloc ga = GENALLOC_ZERO ; /* char * */ int e = errno ; size_t r = 0 ; size_t n ; if (*ngids < 0) return (errno = EINVAL, -1) ; n = *ngids ; - if (!nsss_unix_grp_start(&a)) return -1 ; - if (!nsss_unix_grp_getlist(&a, gids, n, &r, &sa, &ga, user)) return -1 ; - nsss_unix_grp_end(&a) ; - if (r > INT_MAX) return (errno = EMSGSIZE, -1) ; - if (r > n) return (*ngids = (int)r, errno = ENOBUFS, -1) ; - for (size_t i = 0 ; i < r ; i++) - if (gid == gids[i]) goto ok ; - r++ ; - if (r > INT_MAX) return (errno = EMSGSIZE, -1) ; - if (r > n) return (*ngids = (int)r, errno = ENOBUFS, -1) ; - memmove(gids + 1, gids, (r-1) * sizeof(gid_t)) ; - gids[0] = gid ; - ok: - *ngids = (int)r ; - errno = e ; - return (int)n ; + if (!nsss_unix_getgrouplist_preadjust(user, gids, n, &r)) return -1 ; + return nsss_grouplist_adjust(n, r, gid, gids, ngids, e) ; } diff --git a/src/libnsss/nsss_unix_getgrouplist_preadjust.c b/src/libnsss/nsss_unix_getgrouplist_preadjust.c new file mode 100644 index 0000000..a0dc236 --- /dev/null +++ b/src/libnsss/nsss_unix_getgrouplist_preadjust.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include + +#include +#include + +int nsss_unix_getgrouplist_preadjust (char const *user, gid_t *gids, size_t n, size_t *r) +{ + stralloc sa = STRALLOC_ZERO ; + genalloc ga = GENALLOC_ZERO ; /* char * */ + nsss_unix_t a = NSSS_UNIX_ZERO ; + if (!nsss_unix_grp_start(&a)) return 0 ; + if (!nsss_unix_grp_getlist(&a, user, gids, n, r, &sa, &ga)) + { + nsss_unix_grp_end(&a) ; + return 0 ; + } + nsss_unix_grp_end(&a) ; + return 1 ; +} diff --git a/src/libnsss/nsss_unix_grp_getlist.c b/src/libnsss/nsss_unix_grp_getlist.c index 9885a03..65a9117 100644 --- a/src/libnsss/nsss_unix_grp_getlist.c +++ b/src/libnsss/nsss_unix_grp_getlist.c @@ -9,9 +9,8 @@ #include #include -int nsss_unix_grp_getlist (nsss_unix_t *a, gid_t *gids, size_t n, size_t *r, stralloc *sa, genalloc *ga, char const *user) +int nsss_unix_grp_getlist (nsss_unix_t *a, char const *user, gid_t *gids, size_t n, size_t *r, stralloc *sa, genalloc *ga) { - int e = errno ; int sawasnull = !sa->s ; int gawasnull = !genalloc_s(char *, ga) ; size_t sabase = sa->len ; @@ -20,35 +19,35 @@ int nsss_unix_grp_getlist (nsss_unix_t *a, gid_t *gids, size_t n, size_t *r, str for (;;) { - struct group *gr ; + struct group gr ; sa->len = sabase ; genalloc_setlen(char *, ga, gabase) ; errno = 0 ; - if (!nsss_unix_grp_get(a, gr, sa, ga)) + if (!nsss_unix_grp_get(a, &gr, sa, ga)) { if (errno) goto err ; else break ; } - for (char **p = gr->gr_mem ; *p ; p++) + for (char **p = gr.gr_mem ; *p ; p++) if (!strcmp(user, *p)) { - if (m < n) gids[m] = gr->gr_gid ; + if (m < n) gids[m] = gr.gr_gid ; m++ ; break ; } } - if (gawasnull) genalloc_free(char *, &ga) ; + if (gawasnull) genalloc_free(char *, ga) ; else genalloc_setlen(char *, ga, gabase) ; - if (sawasnull) stralloc_free(&sa) ; + if (sawasnull) stralloc_free(sa) ; else sa->len = sabase ; *r = m ; return 1 ; err: - if (gawasnull) genalloc_free(char *, &ga) ; + if (gawasnull) genalloc_free(char *, ga) ; else genalloc_setlen(char *, ga, gabase) ; - if (sawasnull) stralloc_free(&sa) ; + if (sawasnull) stralloc_free(sa) ; else sa->len = sabase ; return 0 ; } -- cgit v1.2.3