2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A
2N/A#include <syslog.h>
2N/A#include "ldap_common.h"
2N/A
2N/A/* netgroup attributes filters */
2N/A#define _N_TRIPLE "nisnetgrouptriple"
2N/A#define _N_MEMBER "membernisnetgroup"
2N/A
2N/A#define PRINT_VAL(a) (((a).argc == 0) || ((a).argv == NULL) || \
2N/A ((a).argv[0] == NULL)) ? "*" : (a).argv[0]
2N/A#define ISNULL(a) (a == NULL ? "<NULL>" : a)
2N/A#define MAX_DOMAIN_LEN 1024
2N/A#define MAX_TRIPLE_LEN (MAXHOSTNAMELEN + LOGNAME_MAX + \
2N/A MAX_DOMAIN_LEN + 5)
2N/A
2N/A#define _F_SETMEMBER "(&(objectClass=nisNetGroup)(cn=%s))"
2N/A#define _F_SETMEMBER_SSD "(&(%%s)(cn=%s))"
2N/A
2N/A#define N_HASH 257
2N/A#define COMMA ','
2N/A
2N/Astatic const char *netgrent_attrs[] = {
2N/A _N_TRIPLE,
2N/A _N_MEMBER,
2N/A (char *)NULL
2N/A};
2N/A
2N/Atypedef struct netgroup_name {
2N/A char *name;
2N/A struct netgroup_name *next;
2N/A struct netgroup_name *next_hash;
2N/A} netgroup_name_t;
2N/A
2N/Atypedef struct {
2N/A netgroup_name_t *hash_list[N_HASH];
2N/A netgroup_name_t *to_do;
2N/A netgroup_name_t *done;
2N/A} netgroup_table_t;
2N/A
2N/Atypedef struct {
2N/A ns_ldap_result_t *results;
2N/A ns_ldap_entry_t *entry;
2N/A char **attrs;
2N/A char *netgroup;
2N/A netgroup_table_t tab;
2N/A} getnetgrent_cookie_t;
2N/A
2N/Atypedef struct {
2N/A struct nss_innetgr_args *ia;
2N/A const char *ssd_filter;
2N/A const char *netgrname;
2N/A const char *membername;
2N/A netgroup_table_t tab;
2N/A} innetgr_cookie_t;
2N/A
2N/Atypedef unsigned int hash_t;
2N/A
2N/Astatic hash_t
2N/Aget_hash(const char *s)
2N/A{
2N/A unsigned int sum = 0;
2N/A unsigned int i;
2N/A
2N/A for (i = 0; s[i] != '\0'; i++)
2N/A sum += ((unsigned char *)s)[i];
2N/A
2N/A return ((sum + i) % N_HASH);
2N/A}
2N/A
2N/A/*
2N/A * Adds a name to the netgroup table
2N/A *
2N/A * Returns
2N/A * 0 if successfully added or already present
2N/A * -1 if memory allocation error or NULL netgroup_table_t
2N/A * from caller.
2N/A */
2N/A
2N/Astatic int
2N/Aadd_netgroup_name(const char *name, netgroup_table_t *tab)
2N/A{
2N/A hash_t h;
2N/A netgroup_name_t *ng;
2N/A netgroup_name_t *ng_new;
2N/A
2N/A if (tab == NULL) {
2N/A /*
2N/A * Should never happen. But if it does,
2N/A * that's an error condition.
2N/A */
2N/A return (-1);
2N/A }
2N/A if (name == NULL || *name == '\0') {
2N/A /* no name to add means success */
2N/A return (0);
2N/A }
2N/A
2N/A h = get_hash(name);
2N/A ng = tab->hash_list[h];
2N/A
2N/A while (ng != NULL) {
2N/A if (strcmp(name, ng->name) == 0)
2N/A break;
2N/A ng = ng->next_hash;
2N/A }
2N/A
2N/A if (ng == NULL) {
2N/A ng_new = (netgroup_name_t *)
2N/A calloc(1, sizeof (netgroup_name_t));
2N/A if (ng_new == NULL)
2N/A return (-1);
2N/A ng_new->name = strdup(name);
2N/A if (ng_new->name == NULL) {
2N/A free(ng_new);
2N/A return (-1);
2N/A }
2N/A ng_new->next_hash = tab->hash_list[h];
2N/A tab->hash_list[h] = ng_new;
2N/A ng_new->next = tab->to_do;
2N/A tab->to_do = ng_new;
2N/A }
2N/A return (0);
2N/A}
2N/A
2N/Astatic netgroup_name_t *
2N/Aget_next_netgroup(netgroup_table_t *tab)
2N/A{
2N/A netgroup_name_t *ng;
2N/A
2N/A if (tab == NULL)
2N/A return (NULL);
2N/A
2N/A ng = tab->to_do;
2N/A if (ng != NULL) {
2N/A tab->to_do = ng->next;
2N/A ng->next = tab->done;
2N/A tab->done = ng;
2N/A }
2N/A return (ng);
2N/A}
2N/A
2N/Astatic void
2N/Afree_netgroup_table(netgroup_table_t *tab)
2N/A{
2N/A netgroup_name_t *ng, *next;
2N/A
2N/A if (tab == NULL)
2N/A return;
2N/A
2N/A for (ng = tab->to_do; ng != NULL; ng = next) {
2N/A if (ng->name != NULL)
2N/A free(ng->name);
2N/A next = ng->next;
2N/A free(ng);
2N/A }
2N/A
2N/A for (ng = tab->done; ng != NULL; ng = next) {
2N/A if (ng->name != NULL)
2N/A free(ng->name);
2N/A next = ng->next;
2N/A free(ng);
2N/A }
2N/A (void) memset(tab, 0, sizeof (*tab));
2N/A}
2N/A
2N/A/*
2N/A * domain comparing routine
2N/A * n1: See if n1 is n2 or an ancestor of it
2N/A * n2: (in string terms, n1 is a suffix of n2)
2N/A * Returns ZERO for success, -1 for failure.
2N/A */
2N/Astatic int
2N/Adomcmp(const char *n1, const char *n2)
2N/A{
2N/A#define PASS 0
2N/A#define FAIL -1
2N/A
2N/A size_t l1, l2;
2N/A
2N/A if ((n1 == NULL) || (n2 == NULL))
2N/A return (FAIL);
2N/A
2N/A l1 = strlen(n1);
2N/A l2 = strlen(n2);
2N/A
2N/A /* Turn a blind eye to the presence or absence of trailing periods */
2N/A if (l1 != 0 && n1[l1 - 1] == '.') {
2N/A --l1;
2N/A }
2N/A if (l2 != 0 && n2[l2 - 1] == '.') {
2N/A --l2;
2N/A }
2N/A if (l1 > l2) { /* Can't be a suffix */
2N/A return (FAIL);
2N/A } else if (l1 == 0) { /* Trivially a suffix; */
2N/A /* (do we want this case?) */
2N/A return (PASS);
2N/A }
2N/A /* So 0 < l1 <= l2 */
2N/A if (l1 < l2 && n2[l2 - l1 - 1] != '.') {
2N/A return (FAIL);
2N/A }
2N/A if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) {
2N/A return (PASS);
2N/A } else {
2N/A return (FAIL);
2N/A }
2N/A}
2N/A
2N/Astatic int
2N/Asplit_triple(char *triple, char **hostname, char **username, char **domain)
2N/A{
2N/A int i, syntax_err;
2N/A char *splittriple[3];
2N/A char *p = triple;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A if (triple == NULL)
2N/A return (-1);
2N/A
2N/A p++;
2N/A syntax_err = 0;
2N/A for (i = 0; i < 3; i++) {
2N/A char *start;
2N/A char *limit;
2N/A const char *terminators = ",) \t";
2N/A
2N/A if (i == 2) {
2N/A /* Don't allow comma */
2N/A terminators++;
2N/A }
2N/A while (isspace(*p)) {
2N/A p++;
2N/A }
2N/A start = p;
2N/A limit = strpbrk(start, terminators);
2N/A if (limit == 0) {
2N/A syntax_err++;
2N/A break;
2N/A }
2N/A p = limit;
2N/A while (isspace(*p)) {
2N/A p++;
2N/A }
2N/A if (*p == terminators[0]) {
2N/A /*
2N/A * Successfully parsed this name and
2N/A * the separator after it (comma or
2N/A * right paren); leave p ready for
2N/A * next parse.
2N/A */
2N/A p++;
2N/A if (start == limit) {
2N/A /* Wildcard */
2N/A splittriple[i] = NULL;
2N/A } else {
2N/A *limit = '\0';
2N/A splittriple[i] = start;
2N/A }
2N/A } else {
2N/A syntax_err++;
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (syntax_err != 0)
2N/A return (-1);
2N/A
2N/A *hostname = splittriple[0];
2N/A *username = splittriple[1];
2N/A *domain = splittriple[2];
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Test membership in triple
2N/A * return 0 = no match
2N/A * return 1 = match
2N/A */
2N/A
2N/Astatic int
2N/Amatch_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry)
2N/A{
2N/A int ndomains;
2N/A char **pdomains;
2N/A int nhost;
2N/A char **phost;
2N/A int nusers;
2N/A char **pusers;
2N/A char **attr;
2N/A char triple[MAX_TRIPLE_LEN];
2N/A char *tuser, *thost, *tdomain;
2N/A int i;
2N/A char *current, *limit;
2N/A int pulen, phlen;
2N/A char *pusers0, *phost0;
2N/A
2N/A nhost = ia->arg[NSS_NETGR_MACHINE].argc;
2N/A phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv;
2N/A if (phost == NULL || *phost == NULL) {
2N/A nhost = 0;
2N/A } else {
2N/A phost0 = phost[0];
2N/A phlen = strlen(phost0);
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "entering with host: %s", phost0 ? phost0 : "");
2N/A#endif
2N/A }
2N/A nusers = ia->arg[NSS_NETGR_USER].argc;
2N/A pusers = (char **)ia->arg[NSS_NETGR_USER].argv;
2N/A if (pusers == NULL || *pusers == NULL) {
2N/A nusers = 0;
2N/A } else {
2N/A pusers0 = pusers[0];
2N/A pulen = strlen(pusers0);
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "entering with user: %s", pusers0 ? pusers0 : "");
2N/A#endif
2N/A }
2N/A ndomains = ia->arg[NSS_NETGR_DOMAIN].argc;
2N/A pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv;
2N/A if (pdomains == NULL || *pdomains == NULL)
2N/A ndomains = 0;
2N/A#ifdef DEBUG
2N/A else
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "entering with domain: %s", pdomains[0] ? pdomains[0] : "");
2N/A#endif
2N/A
2N/A attr = __ns_ldap_getAttr(entry, _N_TRIPLE);
2N/A if (attr == NULL || *attr == NULL)
2N/A return (0);
2N/A
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "(nusers: %d, nhost:%d, ndomains: %d)",
2N/A nusers, nhost, ndomains);
2N/A#endif
2N/A
2N/A /* Special cases for speedup */
2N/A if (nusers == 1 && nhost == 0 && ndomains == 0) {
2N/A /* Special case for finding a single user in a netgroup */
2N/A for (; *attr; attr++) {
2N/A /* jump to first comma and check next character */
2N/A current = *attr;
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "current is: %s", current);
2N/A#endif
2N/A if ((current = strchr(current, COMMA)) == NULL)
2N/A continue;
2N/A current++;
2N/A
2N/A /* skip whitespaces */
2N/A while (isspace(*current))
2N/A current++;
2N/A
2N/A /* if user part is null, then treat as wildcard */
2N/A if (*current == COMMA)
2N/A return (1);
2N/A
2N/A /* compare first character */
2N/A if (*pusers0 != *current)
2N/A continue;
2N/A
2N/A /* limit username to COMMA */
2N/A if ((limit = strchr(current, COMMA)) == NULL)
2N/A continue;
2N/A *limit = '\0';
2N/A
2N/A /* remove blanks before COMMA */
2N/A if ((limit = strpbrk(current, " \t")) != NULL)
2N/A *limit = '\0';
2N/A
2N/A /* compare size of username */
2N/A if (pulen != strlen(current)) {
2N/A continue;
2N/A }
2N/A
2N/A /* do actual compare */
2N/A if (strncmp(pusers0, current, pulen) == 0) {
2N/A return (1);
2N/A } else {
2N/A continue;
2N/A }
2N/A }
2N/A } else if (nusers == 0 && nhost == 1 && ndomains == 0) {
2N/A /* Special case for finding a single host in a netgroup */
2N/A for (; *attr; attr++) {
2N/A
2N/A /* jump to first character and check */
2N/A current = *attr;
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "current is: %s", current);
2N/A#endif
2N/A current++;
2N/A
2N/A /* skip whitespaces */
2N/A while (isspace(*current))
2N/A current++;
2N/A
2N/A /* if host part is null, then treat as wildcard */
2N/A if (*current == COMMA)
2N/A return (1);
2N/A
2N/A /* limit hostname to COMMA */
2N/A if ((limit = strchr(current, COMMA)) == NULL)
2N/A continue;
2N/A *limit = '\0';
2N/A
2N/A /* remove blanks before COMMA */
2N/A if ((limit = strpbrk(current, " \t")) != NULL)
2N/A *limit = '\0';
2N/A
2N/A /* compare size of hostname */
2N/A if (phlen != strlen(current)) {
2N/A continue;
2N/A }
2N/A
2N/A /* do actual compare */
2N/A if (strncasecmp(phost0, current, phlen) == 0) {
2N/A return (1);
2N/A } else {
2N/A continue;
2N/A }
2N/A }
2N/A } else {
2N/A for (; *attr; attr++) {
2N/A if (strlcpy(triple, *attr,
2N/A sizeof (triple)) >= sizeof (triple))
2N/A continue;
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: match_triple_entry: "
2N/A "triple is: %s", triple);
2N/A#endif
2N/A if (split_triple(triple, &thost, &tuser, &tdomain) != 0)
2N/A continue;
2N/A if (thost != NULL && *thost != '\0' && nhost != 0) {
2N/A for (i = 0; i < nhost; i++)
2N/A if (strcasecmp(thost, phost[i]) == 0)
2N/A break;
2N/A if (i == nhost)
2N/A continue;
2N/A }
2N/A if (tuser != NULL && *tuser != '\0' && nusers != 0) {
2N/A for (i = 0; i < nusers; i++)
2N/A if (strcmp(tuser, pusers[i]) == 0)
2N/A break;
2N/A if (i == nusers)
2N/A continue;
2N/A }
2N/A if (tdomain != NULL && *tdomain != '\0' &&
2N/A ndomains != 0) {
2N/A for (i = 0; i < ndomains; i++)
2N/A if (domcmp(tdomain, pdomains[i]) == 0)
2N/A break;
2N/A if (i == ndomains)
2N/A continue;
2N/A }
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Amatch_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result)
2N/A{
2N/A ns_ldap_entry_t *entry;
2N/A
2N/A for (entry = result->entry; entry != NULL; entry = entry->next)
2N/A if (match_triple_entry(ia, entry) == 1)
2N/A return (1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Aadd_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab)
2N/A{
2N/A char **attrs;
2N/A char **a;
2N/A
2N/A attrs = __ns_ldap_getAttr(entry, _N_MEMBER);
2N/A if (attrs == NULL || *attrs == NULL)
2N/A return (0);
2N/A
2N/A for (a = attrs; *a != NULL; a++) {}
2N/A
2N/A do {
2N/A a--;
2N/A if (add_netgroup_name(*a, tab) != 0)
2N/A return (-1);
2N/A } while (a > attrs);
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Aadd_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab)
2N/A{
2N/A ns_ldap_entry_t *entry;
2N/A int ret = 0;
2N/A
2N/A for (entry = result->entry; entry != NULL; entry = entry->next) {
2N/A ret = add_netgroup_member_entry(entry, tab);
2N/A if (ret != 0)
2N/A break;
2N/A }
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * top_down_search checks only checks the netgroup specified in netgrname
2N/A */
2N/Astatic nss_status_t
2N/Atop_down_search(struct nss_innetgr_args *ia, char *netgrname)
2N/A{
2N/A char searchfilter[SEARCHFILTERLEN];
2N/A char name[SEARCHFILTERLEN];
2N/A char userdata[SEARCHFILTERLEN];
2N/A ns_ldap_result_t *result = NULL;
2N/A ns_ldap_error_t *error = NULL;
2N/A int rc;
2N/A nss_status_t status = NSS_NOTFOUND;
2N/A nss_status_t status1;
2N/A netgroup_table_t tab;
2N/A netgroup_name_t *ng;
2N/A int ret;
2N/A
2N/A (void) memset(&tab, 0, sizeof (tab));
2N/A
2N/A if (add_netgroup_name(netgrname, &tab) != 0)
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A
2N/A while ((ng = get_next_netgroup(&tab)) != NULL) {
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: top_down_search: netgroup loop "
2N/A "(ng->name: %s)", ng->name ? ng->name : "null !");
2N/A#endif
2N/A if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
2N/A break;
2N/A ret = snprintf(searchfilter, sizeof (searchfilter),
2N/A _F_SETMEMBER, name);
2N/A if (ret >= sizeof (searchfilter) || ret < 0)
2N/A break;
2N/A
2N/A ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD,
2N/A name);
2N/A if (ret >= sizeof (userdata) || ret < 0)
2N/A break;
2N/A
2N/A /* searching for current netgroup name entry */
2N/A rc = __ns_ldap_list(_NETGROUP, searchfilter,
2N/A _merge_SSD_filter, netgrent_attrs, NULL, 0, &result,
2N/A &error, NULL, userdata);
2N/A
2N/A if (error != NULL) {
2N/A status1 = switch_err(rc, error);
2N/A if (status1 == NSS_TRYAGAIN) {
2N/A (void) __ns_ldap_freeError(&error);
2N/A free_netgroup_table(&tab);
2N/A return (status1);
2N/A }
2N/A }
2N/A
2N/A (void) __ns_ldap_freeError(&error);
2N/A if (rc == NS_LDAP_SUCCESS) {
2N/A if (match_triple(ia, result) == 1) {
2N/A /* We found a match */
2N/A ia->status = NSS_NETGR_FOUND;
2N/A status = NSS_SUCCESS;
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: top_down_search: "
2N/A "found match");
2N/A#endif
2N/A break;
2N/A }
2N/A
2N/A /*
2N/A * No match found. Check for membernisnetgroup
2N/A * in result and if yes, start again with those.
2N/A */
2N/A rc = add_netgroup_member(result, &tab);
2N/A if (rc != 0)
2N/A break;
2N/A } else if (rc != NS_LDAP_NOTFOUND) {
2N/A break;
2N/A }
2N/A (void) __ns_ldap_freeResult(&result);
2N/A }
2N/A
2N/A (void) __ns_ldap_freeResult(&result);
2N/A free_netgroup_table(&tab);
2N/A return (status);
2N/A}
2N/A
2N/A/*
2N/A * __netgr_in checks only checks the netgroup specified in ngroup
2N/A */
2N/Astatic nss_status_t
2N/A__netgr_in(void *a, char *netgrname)
2N/A{
2N/A struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a;
2N/A nss_status_t status = NSS_NOTFOUND;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n");
2N/A (void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: "
2N/A "argc[%d]='%s',\n\tdomain:argc[%d]='%s' "
2N/A "netgroup: argc[%d]='%s'\n",
2N/A NSS_NETGR_MACHINE,
2N/A PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]),
2N/A NSS_NETGR_USER,
2N/A PRINT_VAL(ia->arg[NSS_NETGR_USER]),
2N/A NSS_NETGR_DOMAIN,
2N/A PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]),
2N/A NSS_NETGR_N,
2N/A PRINT_VAL(ia->arg[NSS_NETGR_N]));
2N/A (void) fprintf(stdout, "\tgroups='%s'\n", netgrname);
2N/A#endif /* DEBUG */
2N/A
2N/A ia->status = NSS_NETGR_NO;
2N/A
2N/A if (netgrname == NULL)
2N/A return (status);
2N/A
2N/A return (top_down_search(ia, netgrname));
2N/A}
2N/A
2N/A/*ARGSUSED0*/
2N/Astatic nss_status_t
2N/Anetgr_in(ldap_backend_ptr be, void *a)
2N/A{
2N/A struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a;
2N/A int i;
2N/A nss_status_t rc = (nss_status_t)NSS_NOTFOUND;
2N/A
2N/A ia->status = NSS_NETGR_NO;
2N/A for (i = 0; i < ia->groups.argc; i++) {
2N/A rc = __netgr_in(a, ia->groups.argv[i]);
2N/A if (ia->status == NSS_NETGR_FOUND)
2N/A return (NSS_SUCCESS);
2N/A }
2N/A return (rc);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A */
2N/A
2N/Astatic nss_status_t
2N/Agetnetgr_ldap_setent(ldap_backend_ptr be, void *a)
2N/A{
2N/A const char *netgroup = (const char *) a;
2N/A getnetgrent_cookie_t *cookie;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A cookie = (getnetgrent_cookie_t *)be->netgroup_cookie;
2N/A if (cookie != NULL && cookie->netgroup != NULL) {
2N/A /* is this another set on the same netgroup */
2N/A if (strcmp(cookie->netgroup, netgroup) == 0)
2N/A return ((nss_status_t)NSS_SUCCESS);
2N/A }
2N/A
2N/A return (NSS_NOTFOUND);
2N/A}
2N/A
2N/Astatic void
2N/Afree_getnetgrent_cookie(getnetgrent_cookie_t **cookie)
2N/A{
2N/A getnetgrent_cookie_t *p = *cookie;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A if (p == NULL)
2N/A return;
2N/A
2N/A (void) __ns_ldap_freeResult(&p->results);
2N/A free_netgroup_table(&p->tab);
2N/A free(p->netgroup);
2N/A free(p);
2N/A *cookie = NULL;
2N/A}
2N/A
2N/A/*ARGSUSED1*/
2N/Astatic nss_status_t
2N/Agetnetgr_ldap_endent(ldap_backend_ptr be, void *a)
2N/A{
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
2N/A
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A}
2N/A
2N/A
2N/A/*ARGSUSED1*/
2N/Astatic nss_status_t
2N/Agetnetgr_ldap_destr(ldap_backend_ptr be, void *a)
2N/A{
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
2N/A free(be);
2N/A
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A}
2N/A
2N/A
2N/Astatic nss_status_t
2N/Agetnetgr_ldap_getent(ldap_backend_ptr be, void *a)
2N/A{
2N/A struct nss_getnetgrent_args *args;
2N/A getnetgrent_cookie_t *p;
2N/A char searchfilter[SEARCHFILTERLEN];
2N/A char userdata[SEARCHFILTERLEN];
2N/A char name[SEARCHFILTERLEN];
2N/A int rc;
2N/A ns_ldap_result_t *result = NULL;
2N/A ns_ldap_error_t *error = NULL;
2N/A char **attrs;
2N/A char *hostname, *username, *domain;
2N/A char *buffer;
2N/A nss_status_t status = NSS_SUCCESS;
2N/A netgroup_name_t *ng;
2N/A int ret;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A args = (struct nss_getnetgrent_args *)a;
2N/A
2N/A args->status = NSS_NETGR_NO;
2N/A
2N/A p = (getnetgrent_cookie_t *)be->netgroup_cookie;
2N/A if (p == NULL)
2N/A return ((nss_status_t)NSS_SUCCESS);
2N/A
2N/A for (;;) {
2N/A /*
2N/A * Search through each netgroup consecutively: only search
2N/A * next netgroup when results from previous netgroup are
2N/A * processed.
2N/A * Needed for nested netgroup (memberNisNetgroup attributes).
2N/A */
2N/A if (p->results == NULL) {
2N/A if ((ng = get_next_netgroup(&p->tab)) != NULL) {
2N/A if (_ldap_filter_name(name, ng->name,
2N/A sizeof (name)) != 0)
2N/A break;
2N/A
2N/A ret = snprintf(searchfilter,
2N/A sizeof (searchfilter),
2N/A _F_SETMEMBER, name);
2N/A if (ret >= sizeof (searchfilter) || ret < 0)
2N/A break;
2N/A
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: "
2N/A "getnetgr_ldap_getent: "
2N/A "netgroup name: %s", name);
2N/A#endif
2N/A ret = snprintf(userdata, sizeof (userdata),
2N/A _F_SETMEMBER_SSD, name);
2N/A if (ret >= sizeof (userdata) || ret < 0)
2N/A break;
2N/A
2N/A result = NULL;
2N/A rc = __ns_ldap_list(_NETGROUP, searchfilter,
2N/A _merge_SSD_filter, netgrent_attrs, NULL,
2N/A 0, &result, &error, NULL, userdata);
2N/A (void) __ns_ldap_freeError(&error);
2N/A
2N/A if (rc == NS_LDAP_SUCCESS && result != NULL) {
2N/A p->results = result;
2N/A } else {
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: "
2N/A "getnetgr_ldap_getent: "
2N/A "__ns_ldap_list() returned %d "
2N/A "(result: 0x%x)", rc, result);
2N/A#endif
2N/A /*
2N/A * Will exit when no more netgroup
2N/A * to search and no more p->results
2N/A * to process.
2N/A */
2N/A (void) __ns_ldap_freeResult(&result);
2N/A }
2N/A } else { /* no more netgroup to process */
2N/A /*
2N/A * If no more results to process, and since
2N/A * there's no more netgroup to process either,
2N/A * then it's time to break and exit the for
2N/A * loop.
2N/A */
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: "
2N/A "getnetgr_ldap_getent: no more netgroup "
2N/A "to process, p->results: 0x%x",
2N/A p->results);
2N/A#endif
2N/A if (p->results == NULL)
2N/A break;
2N/A }
2N/A }
2N/A if (p->results == NULL)
2N/A continue;
2N/A
2N/A if (p->entry == NULL)
2N/A p->entry = p->results->entry;
2N/A
2N/A if (p->entry == NULL)
2N/A continue;
2N/A
2N/A if (p->attrs == NULL) {
2N/A attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE);
2N/A if (attrs != NULL && *attrs != NULL)
2N/A p->attrs = attrs;
2N/A }
2N/A
2N/A if (p->attrs != NULL) {
2N/A attrs = p->attrs;
2N/A buffer = args->buffer;
2N/A
2N/A if (strlcpy(buffer, *attrs, args->buflen) >=
2N/A args->buflen) {
2N/A status = NSS_STR_PARSE_ERANGE;
2N/A break;
2N/A }
2N/A
2N/A rc = split_triple(buffer, &hostname, &username,
2N/A &domain);
2N/A attrs++;
2N/A if (attrs != NULL && *attrs != NULL)
2N/A p->attrs = attrs;
2N/A else
2N/A p->attrs = NULL;
2N/A if (rc == 0) {
2N/A args->retp[NSS_NETGR_MACHINE] = hostname;
2N/A args->retp[NSS_NETGR_USER] = username;
2N/A args->retp[NSS_NETGR_DOMAIN] = domain;
2N/A args->status = NSS_NETGR_FOUND;
2N/A#ifdef DEBUG
2N/A syslog(LOG_DEBUG, "nss_ldap: "
2N/A "getnetgr_ldap_getent: found triple "
2N/A "(%s, %s, %s), 0x%x to process",
2N/A hostname ? hostname : "",
2N/A username ? username : "",
2N/A domain ? domain : "",
2N/A p->attrs);
2N/A#endif
2N/A if (p->attrs != NULL)
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (p->attrs == NULL) {
2N/A rc = add_netgroup_member_entry(p->entry, &p->tab);
2N/A if (rc != 0) {
2N/A args->status = NSS_NETGR_NO;
2N/A break;
2N/A }
2N/A
2N/A p->entry = p->entry->next;
2N/A if (p->entry == NULL)
2N/A (void) __ns_ldap_freeResult(&p->results);
2N/A if (args->status == NSS_NETGR_FOUND)
2N/A break;
2N/A }
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/Astatic ldap_backend_op_t getnetgroup_ops[] = {
2N/A getnetgr_ldap_destr,
2N/A getnetgr_ldap_endent,
2N/A getnetgr_ldap_setent,
2N/A getnetgr_ldap_getent,
2N/A};
2N/A
2N/A/*
2N/A *
2N/A */
2N/A
2N/Astatic nss_status_t
2N/Anetgr_set(ldap_backend_ptr be, void *a)
2N/A{
2N/A struct nss_setnetgrent_args *args =
2N/A (struct nss_setnetgrent_args *)a;
2N/A ldap_backend_ptr get_be;
2N/A getnetgrent_cookie_t *p;
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n");
2N/A (void) fprintf(stdout,
2N/A "\targs->netgroup: %s\n", ISNULL(args->netgroup));
2N/A#endif /* DEBUG */
2N/A
2N/A if (args->netgroup == NULL)
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A
2N/A free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
2N/A p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t));
2N/A if (p == NULL)
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A p->netgroup = strdup(args->netgroup);
2N/A if (p->netgroup == NULL) {
2N/A free(p);
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A }
2N/A if (add_netgroup_name(args->netgroup, &p->tab) == -1) {
2N/A free_getnetgrent_cookie(&p);
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A }
2N/A
2N/A /* now allocate and return iteration backend structure */
2N/A if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL)
2N/A return (NSS_UNAVAIL);
2N/A get_be->ops = getnetgroup_ops;
2N/A get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]);
2N/A get_be->tablename = NULL;
2N/A get_be->attrs = netgrent_attrs;
2N/A get_be->result = NULL;
2N/A get_be->ldapobj2str = NULL;
2N/A get_be->setcalled = 1;
2N/A get_be->filter = NULL;
2N/A get_be->toglue = NULL;
2N/A get_be->enumcookie = NULL;
2N/A get_be->netgroup_cookie = p;
2N/A args->iterator = (nss_backend_t *)get_be;
2N/A
2N/A (void) __ns_ldap_freeResult(&be->result);
2N/A
2N/A return (NSS_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*ARGSUSED1*/
2N/Astatic nss_status_t
2N/Anetgr_ldap_destr(ldap_backend_ptr be, void *a)
2N/A{
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A (void) _clean_ldap_backend(be);
2N/A
2N/A return ((nss_status_t)NSS_NOTFOUND);
2N/A}
2N/A
2N/A
2N/A
2N/A
2N/Astatic ldap_backend_op_t netgroup_ops[] = {
2N/A netgr_ldap_destr,
2N/A 0,
2N/A 0,
2N/A 0,
2N/A netgr_in, /* innetgr() */
2N/A netgr_set /* setnetgrent() */
2N/A};
2N/A
2N/A
2N/A/*
2N/A * _nss_ldap_netgroup_constr is where life begins. This function calls the
2N/A * generic ldap constructor function to define and build the abstract data
2N/A * types required to support ldap operations.
2N/A */
2N/A
2N/A/*ARGSUSED0*/
2N/Anss_backend_t *
2N/A_nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2,
2N/A const char *dummy3)
2N/A{
2N/A
2N/A#ifdef DEBUG
2N/A (void) fprintf(stdout,
2N/A "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n");
2N/A#endif /* DEBUG */
2N/A
2N/A return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops,
2N/A sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP,
2N/A netgrent_attrs, NULL));
2N/A}