From f1ac7d7859b26f0f36f5e8ffacda609f8ece80e5 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Mon, 23 Aug 2010 11:33:56 -0400 Subject: Rename group.c and passwd.c for clarity Prefixing group.c and passwd.c with "nss_" similar to the way the PAM client sources are prefixed with "pam_" --- Makefile.am | 4 +- po/POTFILES.in | 4 +- src/sss_client/group.c | 446 -------------------------------------------- src/sss_client/nss_group.c | 446 ++++++++++++++++++++++++++++++++++++++++++++ src/sss_client/nss_passwd.c | 378 +++++++++++++++++++++++++++++++++++++ src/sss_client/passwd.c | 378 ------------------------------------- 6 files changed, 828 insertions(+), 828 deletions(-) delete mode 100644 src/sss_client/group.c create mode 100644 src/sss_client/nss_group.c create mode 100644 src/sss_client/nss_passwd.c delete mode 100644 src/sss_client/passwd.c diff --git a/Makefile.am b/Makefile.am index 605b97ad9..0cd39d969 100644 --- a/Makefile.am +++ b/Makefile.am @@ -724,8 +724,8 @@ pam_test_client_LDFLAGS = -lpam -lpam_misc nsslib_LTLIBRARIES = libnss_sss.la libnss_sss_la_SOURCES = \ src/sss_client/common.c \ - src/sss_client/passwd.c \ - src/sss_client/group.c \ + src/sss_client/nss_passwd.c \ + src/sss_client/nss_group.c \ src/sss_client/sss_cli.h libnss_sss_la_LDFLAGS = \ -module \ diff --git a/po/POTFILES.in b/po/POTFILES.in index af2ba9ee5..0c09e253d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -6,10 +6,10 @@ src/providers/krb5/krb5_child.c src/providers/ldap/ldap_child.c src/providers/data_provider_be.c src/sss_client/common.c -src/sss_client/group.c +src/sss_client/nss_group.c +src/sss_client/nss_passwd.c src/sss_client/pam_sss.c src/sss_client/pam_test_client.c -src/sss_client/passwd.c src/tools/sss_useradd.c src/tools/sss_groupadd.c src/tools/sss_groupdel.c diff --git a/src/sss_client/group.c b/src/sss_client/group.c deleted file mode 100644 index 60b4611c2..000000000 --- a/src/sss_client/group.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * System Security Services Daemon. NSS client interface - * - * Copyright (C) Simo Sorce 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* GROUP database NSS interface */ - -#include -#include -#include -#include -#include -#include -#include -#include "sss_cli.h" - -static struct sss_nss_getgrent_data { - size_t len; - size_t ptr; - uint8_t *data; -} sss_nss_getgrent_data; - -static void sss_nss_getgrent_data_clean(void) { - - if (sss_nss_getgrent_data.data != NULL) { - free(sss_nss_getgrent_data.data); - sss_nss_getgrent_data.data = NULL; - } - sss_nss_getgrent_data.len = 0; - sss_nss_getgrent_data.ptr = 0; -} - -/* GETGRNAM Request: - * - * 0-X: string with name - * - * GERTGRGID Request: - * - * 0-7: 32bit number with gid - * - * INITGROUPS Request: - * - * 0-3: 32bit number with gid - * 4-7: 32bit unsigned with max num of entries - * - * Replies: - * - * 0-3: 32bit unsigned number of results - * 4-7: 32bit unsigned (reserved/padding) - * For each result (64bit padded ?): - * 0-3: 32bit number gid - * 4-7: 32bit unsigned number of members - * 8-X: sequence of 0 terminated strings (name, passwd, mem..) - * - * FIXME: do we need to pad so that each result is 32 bit aligned ? - */ -struct sss_nss_gr_rep { - struct group *result; - char *buffer; - size_t buflen; -}; - -static int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr, - uint8_t *buf, size_t *len) -{ - size_t i, l, slen, ptmem, pad; - ssize_t dlen; - char *sbuf; - uint32_t mem_num; - uint32_t c; - - if (*len < 11) { /* not enough space for data, bad packet */ - return EBADMSG; - } - - SAFEALIGN_COPY_UINT32(&c, buf, NULL); - pr->result->gr_gid = c; - SAFEALIGN_COPY_UINT32(&mem_num, buf+sizeof(uint32_t), NULL); - - sbuf = (char *)&buf[8]; - slen = *len - 8; - dlen = pr->buflen; - - pr->result->gr_name = &(pr->buffer[0]); - i = 0; - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - pr->result->gr_passwd = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - /* Make sure pr->buffer[i+pad] is 32 bit aligned */ - pad = 0; - while((i + pad) % 4) { - pad++; - } - - /* now members */ - pr->result->gr_mem = (char **)&(pr->buffer[i+pad]); - ptmem = (sizeof(char *) * (mem_num + 1)) + pad; - if (ptmem > dlen) { - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - dlen -= ptmem; - ptmem += i; - pr->result->gr_mem[mem_num] = NULL; /* terminate array */ - - for (l = 0; l < mem_num; l++) { - pr->result->gr_mem[l] = &(pr->buffer[ptmem]); - while ((slen > i) && (dlen > 0)) { - pr->buffer[ptmem] = sbuf[i]; - if (pr->buffer[ptmem] == '\0') break; - i++; - dlen--; - ptmem++; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - ptmem++; - } - - *len = slen -i; - return 0; -} - -/* INITGROUP Reply: - * - * 0-3: 32bit unsigned number of results - * 4-7: 32bit unsigned (reserved/padding) - * For each result: - * 0-4: 32bit number with gid - */ - - -enum nss_status _nss_sss_initgroups_dyn(const char *user, gid_t group, - long int *start, long int *size, - gid_t **groups, long int limit, - int *errnop) -{ - struct sss_cli_req_data rd; - uint8_t *repbuf; - size_t replen; - enum nss_status nret; - uint32_t *rbuf; - uint32_t num_ret; - long int l, max_ret; - - rd.len = strlen(user) +1; - rd.data = user; - - nret = sss_nss_make_request(SSS_NSS_INITGR, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - /* no results if not found */ - num_ret = ((uint32_t *)repbuf)[0]; - if (num_ret == 0) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - max_ret = num_ret; - - /* check we have enough space in the buffer */ - if ((*size - *start) < num_ret) { - long int newsize; - gid_t *newgroups; - - newsize = *size + num_ret; - if ((limit > 0) && (newsize > limit)) { - newsize = limit; - max_ret = newsize - *start; - } - - newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups)); - if (!newgroups) { - *errnop = ENOMEM; - free(repbuf); - return NSS_STATUS_TRYAGAIN; - } - *groups = newgroups; - *size = newsize; - } - - rbuf = &((uint32_t *)repbuf)[2]; - for (l = 0; l < max_ret; l++) { - (*groups)[*start] = rbuf[l]; - *start += 1; - } - - free(repbuf); - return NSS_STATUS_SUCCESS; -} - - -enum nss_status _nss_sss_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_gr_rep grrep; - uint8_t *repbuf; - size_t replen, len; - enum nss_status nret; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - rd.len = strlen(name) + 1; - rd.data = name; - - nret = sss_nss_make_request(SSS_NSS_GETGRNAM, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - grrep.result = result; - grrep.buffer = buffer; - grrep.buflen = buflen; - - /* no results if not found */ - if (((uint32_t *)repbuf)[0] == 0) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - /* only 1 result is accepted for this function */ - if (((uint32_t *)repbuf)[0] != 1) { - *errnop = EBADMSG; - free(repbuf); - return NSS_STATUS_TRYAGAIN; - } - - len = replen - 8; - ret = sss_nss_getgr_readrep(&grrep, repbuf+8, &len); - free(repbuf); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_getgrgid_r(gid_t gid, struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_gr_rep grrep; - uint8_t *repbuf; - size_t replen, len; - enum nss_status nret; - uint32_t group_gid; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - group_gid = gid; - rd.len = sizeof(uint32_t); - rd.data = &group_gid; - - nret = sss_nss_make_request(SSS_NSS_GETGRGID, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - grrep.result = result; - grrep.buffer = buffer; - grrep.buflen = buflen; - - /* no results if not found */ - if (((uint32_t *)repbuf)[0] == 0) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - /* only 1 result is accepted for this function */ - if (((uint32_t *)repbuf)[0] != 1) { - *errnop = EBADMSG; - free(repbuf); - return NSS_STATUS_TRYAGAIN; - } - - len = replen - 8; - ret = sss_nss_getgr_readrep(&grrep, repbuf+8, &len); - free(repbuf); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_setgrent(void) -{ - enum nss_status nret; - int errnop; - - /* make sure we do not have leftovers, and release memory */ - sss_nss_getgrent_data_clean(); - - nret = sss_nss_make_request(SSS_NSS_SETGRENT, - NULL, NULL, NULL, &errnop); - if (nret != NSS_STATUS_SUCCESS) { - errno = errnop; - return nret; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_gr_rep grrep; - uint8_t *repbuf; - size_t replen; - enum nss_status nret; - uint32_t num_entries; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - /* if there are leftovers return the next one */ - if (sss_nss_getgrent_data.data != NULL && - sss_nss_getgrent_data.ptr < sss_nss_getgrent_data.len) { - - repbuf = (uint8_t *)sss_nss_getgrent_data.data + - sss_nss_getgrent_data.ptr; - replen = sss_nss_getgrent_data.len - - sss_nss_getgrent_data.ptr; - - grrep.result = result; - grrep.buffer = buffer; - grrep.buflen = buflen; - - ret = sss_nss_getgr_readrep(&grrep, repbuf, &replen); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - /* advance buffer pointer */ - sss_nss_getgrent_data.ptr = sss_nss_getgrent_data.len - replen; - - return NSS_STATUS_SUCCESS; - } - - /* release memory if any */ - sss_nss_getgrent_data_clean(); - - /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */ - num_entries = SSS_NSS_MAX_ENTRIES; - rd.len = sizeof(uint32_t); - rd.data = &num_entries; - - nret = sss_nss_make_request(SSS_NSS_GETGRENT, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - /* no results if not found */ - if ((((uint32_t *)repbuf)[0] == 0) || (replen - 8 == 0)) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - sss_nss_getgrent_data.data = repbuf; - sss_nss_getgrent_data.len = replen; - sss_nss_getgrent_data.ptr = 8; /* skip metadata fields */ - - /* call again ourselves, this will return the first result */ - return _nss_sss_getgrent_r(result, buffer, buflen, errnop); -} - -enum nss_status _nss_sss_endgrent(void) -{ - enum nss_status nret; - int errnop; - - /* make sure we do not have leftovers, and release memory */ - sss_nss_getgrent_data_clean(); - - nret = sss_nss_make_request(SSS_NSS_ENDGRENT, - NULL, NULL, NULL, &errnop); - if (nret != NSS_STATUS_SUCCESS) { - errno = errnop; - return nret; - } - - return NSS_STATUS_SUCCESS; -} diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c new file mode 100644 index 000000000..60b4611c2 --- /dev/null +++ b/src/sss_client/nss_group.c @@ -0,0 +1,446 @@ +/* + * System Security Services Daemon. NSS client interface + * + * Copyright (C) Simo Sorce 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* GROUP database NSS interface */ + +#include +#include +#include +#include +#include +#include +#include +#include "sss_cli.h" + +static struct sss_nss_getgrent_data { + size_t len; + size_t ptr; + uint8_t *data; +} sss_nss_getgrent_data; + +static void sss_nss_getgrent_data_clean(void) { + + if (sss_nss_getgrent_data.data != NULL) { + free(sss_nss_getgrent_data.data); + sss_nss_getgrent_data.data = NULL; + } + sss_nss_getgrent_data.len = 0; + sss_nss_getgrent_data.ptr = 0; +} + +/* GETGRNAM Request: + * + * 0-X: string with name + * + * GERTGRGID Request: + * + * 0-7: 32bit number with gid + * + * INITGROUPS Request: + * + * 0-3: 32bit number with gid + * 4-7: 32bit unsigned with max num of entries + * + * Replies: + * + * 0-3: 32bit unsigned number of results + * 4-7: 32bit unsigned (reserved/padding) + * For each result (64bit padded ?): + * 0-3: 32bit number gid + * 4-7: 32bit unsigned number of members + * 8-X: sequence of 0 terminated strings (name, passwd, mem..) + * + * FIXME: do we need to pad so that each result is 32 bit aligned ? + */ +struct sss_nss_gr_rep { + struct group *result; + char *buffer; + size_t buflen; +}; + +static int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr, + uint8_t *buf, size_t *len) +{ + size_t i, l, slen, ptmem, pad; + ssize_t dlen; + char *sbuf; + uint32_t mem_num; + uint32_t c; + + if (*len < 11) { /* not enough space for data, bad packet */ + return EBADMSG; + } + + SAFEALIGN_COPY_UINT32(&c, buf, NULL); + pr->result->gr_gid = c; + SAFEALIGN_COPY_UINT32(&mem_num, buf+sizeof(uint32_t), NULL); + + sbuf = (char *)&buf[8]; + slen = *len - 8; + dlen = pr->buflen; + + pr->result->gr_name = &(pr->buffer[0]); + i = 0; + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + pr->result->gr_passwd = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + /* Make sure pr->buffer[i+pad] is 32 bit aligned */ + pad = 0; + while((i + pad) % 4) { + pad++; + } + + /* now members */ + pr->result->gr_mem = (char **)&(pr->buffer[i+pad]); + ptmem = (sizeof(char *) * (mem_num + 1)) + pad; + if (ptmem > dlen) { + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + dlen -= ptmem; + ptmem += i; + pr->result->gr_mem[mem_num] = NULL; /* terminate array */ + + for (l = 0; l < mem_num; l++) { + pr->result->gr_mem[l] = &(pr->buffer[ptmem]); + while ((slen > i) && (dlen > 0)) { + pr->buffer[ptmem] = sbuf[i]; + if (pr->buffer[ptmem] == '\0') break; + i++; + dlen--; + ptmem++; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + ptmem++; + } + + *len = slen -i; + return 0; +} + +/* INITGROUP Reply: + * + * 0-3: 32bit unsigned number of results + * 4-7: 32bit unsigned (reserved/padding) + * For each result: + * 0-4: 32bit number with gid + */ + + +enum nss_status _nss_sss_initgroups_dyn(const char *user, gid_t group, + long int *start, long int *size, + gid_t **groups, long int limit, + int *errnop) +{ + struct sss_cli_req_data rd; + uint8_t *repbuf; + size_t replen; + enum nss_status nret; + uint32_t *rbuf; + uint32_t num_ret; + long int l, max_ret; + + rd.len = strlen(user) +1; + rd.data = user; + + nret = sss_nss_make_request(SSS_NSS_INITGR, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + /* no results if not found */ + num_ret = ((uint32_t *)repbuf)[0]; + if (num_ret == 0) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + max_ret = num_ret; + + /* check we have enough space in the buffer */ + if ((*size - *start) < num_ret) { + long int newsize; + gid_t *newgroups; + + newsize = *size + num_ret; + if ((limit > 0) && (newsize > limit)) { + newsize = limit; + max_ret = newsize - *start; + } + + newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups)); + if (!newgroups) { + *errnop = ENOMEM; + free(repbuf); + return NSS_STATUS_TRYAGAIN; + } + *groups = newgroups; + *size = newsize; + } + + rbuf = &((uint32_t *)repbuf)[2]; + for (l = 0; l < max_ret; l++) { + (*groups)[*start] = rbuf[l]; + *start += 1; + } + + free(repbuf); + return NSS_STATUS_SUCCESS; +} + + +enum nss_status _nss_sss_getgrnam_r(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_gr_rep grrep; + uint8_t *repbuf; + size_t replen, len; + enum nss_status nret; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + rd.len = strlen(name) + 1; + rd.data = name; + + nret = sss_nss_make_request(SSS_NSS_GETGRNAM, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + grrep.result = result; + grrep.buffer = buffer; + grrep.buflen = buflen; + + /* no results if not found */ + if (((uint32_t *)repbuf)[0] == 0) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + /* only 1 result is accepted for this function */ + if (((uint32_t *)repbuf)[0] != 1) { + *errnop = EBADMSG; + free(repbuf); + return NSS_STATUS_TRYAGAIN; + } + + len = replen - 8; + ret = sss_nss_getgr_readrep(&grrep, repbuf+8, &len); + free(repbuf); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_getgrgid_r(gid_t gid, struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_gr_rep grrep; + uint8_t *repbuf; + size_t replen, len; + enum nss_status nret; + uint32_t group_gid; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + group_gid = gid; + rd.len = sizeof(uint32_t); + rd.data = &group_gid; + + nret = sss_nss_make_request(SSS_NSS_GETGRGID, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + grrep.result = result; + grrep.buffer = buffer; + grrep.buflen = buflen; + + /* no results if not found */ + if (((uint32_t *)repbuf)[0] == 0) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + /* only 1 result is accepted for this function */ + if (((uint32_t *)repbuf)[0] != 1) { + *errnop = EBADMSG; + free(repbuf); + return NSS_STATUS_TRYAGAIN; + } + + len = replen - 8; + ret = sss_nss_getgr_readrep(&grrep, repbuf+8, &len); + free(repbuf); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_setgrent(void) +{ + enum nss_status nret; + int errnop; + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getgrent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_SETGRENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + return nret; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_getgrent_r(struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_gr_rep grrep; + uint8_t *repbuf; + size_t replen; + enum nss_status nret; + uint32_t num_entries; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + /* if there are leftovers return the next one */ + if (sss_nss_getgrent_data.data != NULL && + sss_nss_getgrent_data.ptr < sss_nss_getgrent_data.len) { + + repbuf = (uint8_t *)sss_nss_getgrent_data.data + + sss_nss_getgrent_data.ptr; + replen = sss_nss_getgrent_data.len - + sss_nss_getgrent_data.ptr; + + grrep.result = result; + grrep.buffer = buffer; + grrep.buflen = buflen; + + ret = sss_nss_getgr_readrep(&grrep, repbuf, &replen); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + /* advance buffer pointer */ + sss_nss_getgrent_data.ptr = sss_nss_getgrent_data.len - replen; + + return NSS_STATUS_SUCCESS; + } + + /* release memory if any */ + sss_nss_getgrent_data_clean(); + + /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */ + num_entries = SSS_NSS_MAX_ENTRIES; + rd.len = sizeof(uint32_t); + rd.data = &num_entries; + + nret = sss_nss_make_request(SSS_NSS_GETGRENT, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + /* no results if not found */ + if ((((uint32_t *)repbuf)[0] == 0) || (replen - 8 == 0)) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + sss_nss_getgrent_data.data = repbuf; + sss_nss_getgrent_data.len = replen; + sss_nss_getgrent_data.ptr = 8; /* skip metadata fields */ + + /* call again ourselves, this will return the first result */ + return _nss_sss_getgrent_r(result, buffer, buflen, errnop); +} + +enum nss_status _nss_sss_endgrent(void) +{ + enum nss_status nret; + int errnop; + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getgrent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_ENDGRENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + return nret; + } + + return NSS_STATUS_SUCCESS; +} diff --git a/src/sss_client/nss_passwd.c b/src/sss_client/nss_passwd.c new file mode 100644 index 000000000..95c7de619 --- /dev/null +++ b/src/sss_client/nss_passwd.c @@ -0,0 +1,378 @@ +/* + * System Security Services Daemon. NSS client interface + * + * Copyright (C) Simo Sorce 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* PASSWD database NSS interface */ + +#include +#include +#include +#include +#include +#include +#include +#include "sss_cli.h" + +static struct sss_nss_getpwent_data { + size_t len; + size_t ptr; + uint8_t *data; +} sss_nss_getpwent_data; + +static void sss_nss_getpwent_data_clean(void) { + + if (sss_nss_getpwent_data.data != NULL) { + free(sss_nss_getpwent_data.data); + sss_nss_getpwent_data.data = NULL; + } + sss_nss_getpwent_data.len = 0; + sss_nss_getpwent_data.ptr = 0; +} + +/* GETPWNAM Request: + * + * 0-X: string with name + * + * GERTPWUID Request: + * + * 0-3: 32bit number with uid + * + * Replies: + * + * 0-3: 32bit unsigned number of results + * 4-7: 32bit unsigned (reserved/padding) + * For each result: + * 0-3: 32bit number uid + * 4-7: 32bit number gid + * 8-X: sequence of 5, 0 terminated, strings (name, passwd, gecos, dir, shell) + */ + +struct sss_nss_pw_rep { + struct passwd *result; + char *buffer; + size_t buflen; +}; + +static int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr, + uint8_t *buf, size_t *len) +{ + size_t i, slen, dlen; + char *sbuf; + uint32_t c; + + if (*len < 13) { /* not enough space for data, bad packet */ + return EBADMSG; + } + + SAFEALIGN_COPY_UINT32(&c, buf, NULL); + pr->result->pw_uid = c; + SAFEALIGN_COPY_UINT32(&c, buf+sizeof(uint32_t), NULL); + pr->result->pw_gid = c; + + sbuf = (char *)&buf[8]; + slen = *len - 8; + dlen = pr->buflen; + + i = 0; + pr->result->pw_name = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + pr->result->pw_passwd = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + pr->result->pw_gecos = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + pr->result->pw_dir = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + i++; + dlen--; + + pr->result->pw_shell = &(pr->buffer[i]); + while (slen > i && dlen > 0) { + pr->buffer[i] = sbuf[i]; + if (pr->buffer[i] == '\0') break; + i++; + dlen--; + } + if (slen <= i) { /* premature end of buf */ + return EBADMSG; + } + if (dlen <= 0) { /* not enough memory */ + return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ + } + + *len = slen -i -1; + + return 0; +} + +enum nss_status _nss_sss_getpwnam_r(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_pw_rep pwrep; + uint8_t *repbuf; + size_t replen, len; + enum nss_status nret; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + rd.len = strlen(name) + 1; + rd.data = name; + + nret = sss_nss_make_request(SSS_NSS_GETPWNAM, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + pwrep.result = result; + pwrep.buffer = buffer; + pwrep.buflen = buflen; + + /* no results if not found */ + if (((uint32_t *)repbuf)[0] == 0) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + /* only 1 result is accepted for this function */ + if (((uint32_t *)repbuf)[0] != 1) { + *errnop = EBADMSG; + free(repbuf); + return NSS_STATUS_TRYAGAIN; + } + + len = replen - 8; + ret = sss_nss_getpw_readrep(&pwrep, repbuf+8, &len); + free(repbuf); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_pw_rep pwrep; + uint8_t *repbuf; + size_t replen, len; + enum nss_status nret; + uint32_t user_uid; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + user_uid = uid; + rd.len = sizeof(uint32_t); + rd.data = &user_uid; + + nret = sss_nss_make_request(SSS_NSS_GETPWUID, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + pwrep.result = result; + pwrep.buffer = buffer; + pwrep.buflen = buflen; + + /* no results if not found */ + if (((uint32_t *)repbuf)[0] == 0) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + /* only 1 result is accepted for this function */ + if (((uint32_t *)repbuf)[0] != 1) { + *errnop = EBADMSG; + free(repbuf); + return NSS_STATUS_TRYAGAIN; + } + + len = replen - 8; + ret = sss_nss_getpw_readrep(&pwrep, repbuf+8, &len); + free(repbuf); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_setpwent(void) +{ + enum nss_status nret; + int errnop; + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getpwent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_SETPWENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + return nret; + } + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_sss_getpwent_r(struct passwd *result, + char *buffer, size_t buflen, + int *errnop) +{ + struct sss_cli_req_data rd; + struct sss_nss_pw_rep pwrep; + uint8_t *repbuf; + size_t replen; + enum nss_status nret; + uint32_t num_entries; + int ret; + + /* Caught once glibc passing in buffer == 0x0 */ + if (!buffer || !buflen) return ERANGE; + + /* if there are leftovers return the next one */ + if (sss_nss_getpwent_data.data != NULL && + sss_nss_getpwent_data.ptr < sss_nss_getpwent_data.len) { + + repbuf = sss_nss_getpwent_data.data + sss_nss_getpwent_data.ptr; + replen = sss_nss_getpwent_data.len - sss_nss_getpwent_data.ptr; + + pwrep.result = result; + pwrep.buffer = buffer; + pwrep.buflen = buflen; + + ret = sss_nss_getpw_readrep(&pwrep, repbuf, &replen); + if (ret) { + *errnop = ret; + return NSS_STATUS_TRYAGAIN; + } + + /* advance buffer pointer */ + sss_nss_getpwent_data.ptr = sss_nss_getpwent_data.len - replen; + + return NSS_STATUS_SUCCESS; + } + + /* release memory if any */ + sss_nss_getpwent_data_clean(); + + /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */ + num_entries = SSS_NSS_MAX_ENTRIES; + rd.len = sizeof(uint32_t); + rd.data = &num_entries; + + nret = sss_nss_make_request(SSS_NSS_GETPWENT, &rd, + &repbuf, &replen, errnop); + if (nret != NSS_STATUS_SUCCESS) { + return nret; + } + + /* no results if not found */ + if ((((uint32_t *)repbuf)[0] == 0) || (replen - 8 == 0)) { + free(repbuf); + return NSS_STATUS_NOTFOUND; + } + + sss_nss_getpwent_data.data = repbuf; + sss_nss_getpwent_data.len = replen; + sss_nss_getpwent_data.ptr = 8; /* skip metadata fields */ + + /* call again ourselves, this will return the first result */ + return _nss_sss_getpwent_r(result, buffer, buflen, errnop); +} + +enum nss_status _nss_sss_endpwent(void) +{ + enum nss_status nret; + int errnop; + + /* make sure we do not have leftovers, and release memory */ + sss_nss_getpwent_data_clean(); + + nret = sss_nss_make_request(SSS_NSS_ENDPWENT, + NULL, NULL, NULL, &errnop); + if (nret != NSS_STATUS_SUCCESS) { + errno = errnop; + return nret; + } + + return NSS_STATUS_SUCCESS; +} diff --git a/src/sss_client/passwd.c b/src/sss_client/passwd.c deleted file mode 100644 index 95c7de619..000000000 --- a/src/sss_client/passwd.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * System Security Services Daemon. NSS client interface - * - * Copyright (C) Simo Sorce 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* PASSWD database NSS interface */ - -#include -#include -#include -#include -#include -#include -#include -#include "sss_cli.h" - -static struct sss_nss_getpwent_data { - size_t len; - size_t ptr; - uint8_t *data; -} sss_nss_getpwent_data; - -static void sss_nss_getpwent_data_clean(void) { - - if (sss_nss_getpwent_data.data != NULL) { - free(sss_nss_getpwent_data.data); - sss_nss_getpwent_data.data = NULL; - } - sss_nss_getpwent_data.len = 0; - sss_nss_getpwent_data.ptr = 0; -} - -/* GETPWNAM Request: - * - * 0-X: string with name - * - * GERTPWUID Request: - * - * 0-3: 32bit number with uid - * - * Replies: - * - * 0-3: 32bit unsigned number of results - * 4-7: 32bit unsigned (reserved/padding) - * For each result: - * 0-3: 32bit number uid - * 4-7: 32bit number gid - * 8-X: sequence of 5, 0 terminated, strings (name, passwd, gecos, dir, shell) - */ - -struct sss_nss_pw_rep { - struct passwd *result; - char *buffer; - size_t buflen; -}; - -static int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr, - uint8_t *buf, size_t *len) -{ - size_t i, slen, dlen; - char *sbuf; - uint32_t c; - - if (*len < 13) { /* not enough space for data, bad packet */ - return EBADMSG; - } - - SAFEALIGN_COPY_UINT32(&c, buf, NULL); - pr->result->pw_uid = c; - SAFEALIGN_COPY_UINT32(&c, buf+sizeof(uint32_t), NULL); - pr->result->pw_gid = c; - - sbuf = (char *)&buf[8]; - slen = *len - 8; - dlen = pr->buflen; - - i = 0; - pr->result->pw_name = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - pr->result->pw_passwd = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - pr->result->pw_gecos = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - pr->result->pw_dir = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - i++; - dlen--; - - pr->result->pw_shell = &(pr->buffer[i]); - while (slen > i && dlen > 0) { - pr->buffer[i] = sbuf[i]; - if (pr->buffer[i] == '\0') break; - i++; - dlen--; - } - if (slen <= i) { /* premature end of buf */ - return EBADMSG; - } - if (dlen <= 0) { /* not enough memory */ - return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */ - } - - *len = slen -i -1; - - return 0; -} - -enum nss_status _nss_sss_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_pw_rep pwrep; - uint8_t *repbuf; - size_t replen, len; - enum nss_status nret; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - rd.len = strlen(name) + 1; - rd.data = name; - - nret = sss_nss_make_request(SSS_NSS_GETPWNAM, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - pwrep.result = result; - pwrep.buffer = buffer; - pwrep.buflen = buflen; - - /* no results if not found */ - if (((uint32_t *)repbuf)[0] == 0) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - /* only 1 result is accepted for this function */ - if (((uint32_t *)repbuf)[0] != 1) { - *errnop = EBADMSG; - free(repbuf); - return NSS_STATUS_TRYAGAIN; - } - - len = replen - 8; - ret = sss_nss_getpw_readrep(&pwrep, repbuf+8, &len); - free(repbuf); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_pw_rep pwrep; - uint8_t *repbuf; - size_t replen, len; - enum nss_status nret; - uint32_t user_uid; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - user_uid = uid; - rd.len = sizeof(uint32_t); - rd.data = &user_uid; - - nret = sss_nss_make_request(SSS_NSS_GETPWUID, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - pwrep.result = result; - pwrep.buffer = buffer; - pwrep.buflen = buflen; - - /* no results if not found */ - if (((uint32_t *)repbuf)[0] == 0) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - /* only 1 result is accepted for this function */ - if (((uint32_t *)repbuf)[0] != 1) { - *errnop = EBADMSG; - free(repbuf); - return NSS_STATUS_TRYAGAIN; - } - - len = replen - 8; - ret = sss_nss_getpw_readrep(&pwrep, repbuf+8, &len); - free(repbuf); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_setpwent(void) -{ - enum nss_status nret; - int errnop; - - /* make sure we do not have leftovers, and release memory */ - sss_nss_getpwent_data_clean(); - - nret = sss_nss_make_request(SSS_NSS_SETPWENT, - NULL, NULL, NULL, &errnop); - if (nret != NSS_STATUS_SUCCESS) { - errno = errnop; - return nret; - } - - return NSS_STATUS_SUCCESS; -} - -enum nss_status _nss_sss_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, - int *errnop) -{ - struct sss_cli_req_data rd; - struct sss_nss_pw_rep pwrep; - uint8_t *repbuf; - size_t replen; - enum nss_status nret; - uint32_t num_entries; - int ret; - - /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; - - /* if there are leftovers return the next one */ - if (sss_nss_getpwent_data.data != NULL && - sss_nss_getpwent_data.ptr < sss_nss_getpwent_data.len) { - - repbuf = sss_nss_getpwent_data.data + sss_nss_getpwent_data.ptr; - replen = sss_nss_getpwent_data.len - sss_nss_getpwent_data.ptr; - - pwrep.result = result; - pwrep.buffer = buffer; - pwrep.buflen = buflen; - - ret = sss_nss_getpw_readrep(&pwrep, repbuf, &replen); - if (ret) { - *errnop = ret; - return NSS_STATUS_TRYAGAIN; - } - - /* advance buffer pointer */ - sss_nss_getpwent_data.ptr = sss_nss_getpwent_data.len - replen; - - return NSS_STATUS_SUCCESS; - } - - /* release memory if any */ - sss_nss_getpwent_data_clean(); - - /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */ - num_entries = SSS_NSS_MAX_ENTRIES; - rd.len = sizeof(uint32_t); - rd.data = &num_entries; - - nret = sss_nss_make_request(SSS_NSS_GETPWENT, &rd, - &repbuf, &replen, errnop); - if (nret != NSS_STATUS_SUCCESS) { - return nret; - } - - /* no results if not found */ - if ((((uint32_t *)repbuf)[0] == 0) || (replen - 8 == 0)) { - free(repbuf); - return NSS_STATUS_NOTFOUND; - } - - sss_nss_getpwent_data.data = repbuf; - sss_nss_getpwent_data.len = replen; - sss_nss_getpwent_data.ptr = 8; /* skip metadata fields */ - - /* call again ourselves, this will return the first result */ - return _nss_sss_getpwent_r(result, buffer, buflen, errnop); -} - -enum nss_status _nss_sss_endpwent(void) -{ - enum nss_status nret; - int errnop; - - /* make sure we do not have leftovers, and release memory */ - sss_nss_getpwent_data_clean(); - - nret = sss_nss_make_request(SSS_NSS_ENDPWENT, - NULL, NULL, NULL, &errnop); - if (nret != NSS_STATUS_SUCCESS) { - errno = errnop; - return nret; - } - - return NSS_STATUS_SUCCESS; -} -- cgit