summaryrefslogtreecommitdiff
path: root/usr/src/lib/nsswitch/ldap/common
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/nsswitch/ldap/common
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/nsswitch/ldap/common')
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getauthattr.c278
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getauuser.c213
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getbootparams.c187
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getether.c283
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getexecattr.c540
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getgrent.c445
-rw-r--r--usr/src/lib/nsswitch/ldap/common/gethostent.c493
-rw-r--r--usr/src/lib/nsswitch/ldap/common/gethostent6.c502
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getkeyent.c262
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetent.c355
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetgrent.c1168
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getnetmasks.c183
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprinter.c308
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprofattr.c253
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprojent.c331
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getprotoent.c327
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getpwnam.c347
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getrpcent.c280
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getservent.c502
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getspent.c298
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getuserattr.c256
-rw-r--r--usr/src/lib/nsswitch/ldap/common/ldap_common.c471
-rw-r--r--usr/src/lib/nsswitch/ldap/common/ldap_common.h146
-rw-r--r--usr/src/lib/nsswitch/ldap/common/ldap_utils.c289
-rw-r--r--usr/src/lib/nsswitch/ldap/common/mapfile-vers66
25 files changed, 8783 insertions, 0 deletions
diff --git a/usr/src/lib/nsswitch/ldap/common/getauthattr.c b/usr/src/lib/nsswitch/ldap/common/getauthattr.c
new file mode 100644
index 0000000000..ea3341bf57
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getauthattr.c
@@ -0,0 +1,278 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <secdb.h>
+#include <auth_attr.h>
+#include "ldap_common.h"
+
+
+/* auth_attr attributes filters */
+#define _AUTH_NAME "cn"
+#define _AUTH_RES1 "SolarisAttrReserved1"
+#define _AUTH_RES2 "SolarisAttrReserved2"
+#define _AUTH_SHORTDES "SolarisAttrShortDesc"
+#define _AUTH_LONGDES "SolarisAttrLongDesc"
+#define _AUTH_ATTRS "SolarisAttrKeyValue"
+#define _AUTH_GETAUTHNAME "(&(objectClass=SolarisAuthAttr)(cn=%s))"
+#define _AUTH_GETAUTHNAME_SSD "(&(%%s)(cn=%s))"
+
+
+static const char *auth_attrs[] = {
+ _AUTH_NAME,
+ _AUTH_RES1,
+ _AUTH_RES2,
+ _AUTH_SHORTDES,
+ _AUTH_LONGDES,
+ _AUTH_ATTRS,
+ (char *)NULL
+};
+
+
+static int
+_nss_ldap_auth2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *nullstring = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ authstr_t *auth = (authstr_t *)NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ auth = (authstr_t *)(argp->buf.result);
+ ceiling = buffer + buflen;
+ auth->name = (char *)NULL;
+ auth->res1 = (char *)NULL;
+ auth->res2 = (char *)NULL;
+ auth->short_desc = (char *)NULL;
+ auth->long_desc = (char *)NULL;
+ auth->attr = (char *)NULL;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_auth2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_auth2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_auth2ent;
+ }
+ auth->name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_RES1) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ auth->res1 = nullstring;
+ } else {
+ auth->res1 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->res1,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_RES2) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ auth->res2 = nullstring;
+ } else {
+ auth->res2 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->res2,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_SHORTDES) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ auth->short_desc = nullstring;
+ } else {
+ auth->short_desc = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->short_desc,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_LONGDES) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ auth->long_desc = nullstring;
+ } else {
+ auth->long_desc = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->long_desc,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AUTH_ATTRS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ auth->attr = nullstring;
+ } else {
+ auth->attr = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_auth2ent;
+ }
+ (void) strcpy(auth->attr,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getauthattr.c: _nss_ldap_auth2ent]\n");
+ (void) fprintf(stdout, " auth-name: [%s]\n", auth->name);
+ if (auth->res1 != (char *)NULL) {
+ (void) fprintf(stdout, " res1: [%s]\n", auth->res1);
+ }
+ if (auth->res2 != (char *)NULL) {
+ (void) fprintf(stdout, " res2: [%s]\n", auth->res2);
+ }
+ if (auth->short_desc != (char *)NULL) {
+ (void) fprintf(stdout, " short_desc: [%s]\n",
+ auth->short_desc);
+ }
+ if (auth->long_desc != (char *)NULL) {
+ (void) fprintf(stdout, " long_desc: [%s]\n",
+ auth->long_desc);
+ }
+ if (auth->attr != (char *)NULL) {
+ (void) fprintf(stdout, " attr: [%s]\n", auth->attr);
+ }
+#endif /* DEBUG */
+
+result_auth2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getauthattr.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, SEARCHFILTERLEN,
+ _AUTH_GETAUTHNAME, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _AUTH_GETAUTHNAME_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _AUTHATTR, searchfilter, NULL, _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t authattr_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_auth_attr_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getauthattr.c: _nss_ldap_auth_attr_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(authattr_ops,
+ sizeof (authattr_ops)/sizeof (authattr_ops[0]), _AUTHATTR,
+ auth_attrs, _nss_ldap_auth2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getauuser.c b/usr/src/lib/nsswitch/ldap/common/getauuser.c
new file mode 100644
index 0000000000..2267b22ba9
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getauuser.c
@@ -0,0 +1,213 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <secdb.h>
+#include "ldap_common.h"
+#include <bsm/libbsm.h>
+
+
+/* audit_user attributes */
+#define _AU_NAME "uid"
+#define _AU_ALWAYS "SolarisAuditAlways"
+#define _AU_NEVER "SolarisAuditNever"
+#define _AU_GETAUUSERNAME "(&(objectClass=SolarisAuditUser)(uid=%s))"
+#define _AU_GETAUUSERNAME_SSD "(&(%%s)(uid=%s))"
+
+
+static const char *auuser_attrs[] = {
+ _AU_NAME,
+ _AU_ALWAYS,
+ _AU_NEVER,
+ (char *)NULL
+};
+
+
+static int
+_nss_ldap_au2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *nullstring = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ au_user_str_t *au_user = (au_user_str_t *)NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_au2ent;
+ }
+ au_user = (au_user_str_t *)(argp->buf.result);
+ ceiling = buffer + buflen;
+ au_user->au_name = (char *)NULL;
+ au_user->au_always = (char *)NULL;
+ au_user->au_never = (char *)NULL;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_au2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_au2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _AU_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_au2ent;
+ }
+ au_user->au_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_au2ent;
+ }
+ (void) strcpy(au_user->au_name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AU_ALWAYS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ au_user->au_always = nullstring;
+ } else {
+ au_user->au_always = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_au2ent;
+ }
+ (void) strcpy(au_user->au_always,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _AU_NEVER) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ au_user->au_never = nullstring;
+ } else {
+ au_user->au_never = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_au2ent;
+ }
+ (void) strcpy(au_user->au_never,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getauuser.c: _nss_ldap_au2ent]\n");
+ (void) fprintf(stdout, " au_name: [%s]\n", au_user->au_name);
+ if (au_user->au_always != (char *)NULL) {
+ (void) fprintf(stdout, " au_always: [%s]\n",
+ au_user->au_always);
+ }
+ if (au_user->au_never != (char *)NULL) {
+ (void) fprintf(stdout, " au_never: [%s]\n",
+ au_user->au_never);
+ }
+#endif /* DEBUG */
+
+result_au2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getauuser.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _AU_GETAUUSERNAME, name);
+
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _AU_GETAUUSERNAME_SSD, name);
+
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return (_nss_ldap_lookup(be, argp, _AUUSER, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t auuser_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_audit_user_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getauuser.c: _nss_ldap_audit_user_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(auuser_ops,
+ sizeof (auuser_ops)/sizeof (auuser_ops[0]), _AUUSER,
+ auuser_attrs, _nss_ldap_au2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getbootparams.c b/usr/src/lib/nsswitch/ldap/common/getbootparams.c
new file mode 100644
index 0000000000..f1426ba4b6
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getbootparams.c
@@ -0,0 +1,187 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ldap_common.h"
+
+/* bootparams attributes filters */
+#define _B_HOSTNAME "cn"
+#define _B_PARAMETER "bootparameter"
+#define _F_GETBOOTPARAMBYNAME "(&(objectClass=bootableDevice)(cn=%s))"
+#define _F_GETBOOTPARAMBYNAME_SSD "(&(%%s)(cn=%s))"
+
+static const char *bootparams_attrs[] = {
+ _B_HOSTNAME,
+ _B_PARAMETER,
+ (char *)NULL
+};
+
+/*
+ * _nss_ldap_bootparams2ent is the data marshaling method for the
+ * bootparams getXbyY (e.g., getbyname()) backend processes. This
+ * method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into argp->buf.buffer
+ * Three error conditions are expected and returned to nsswitch.
+ *
+ * A host's bootparameters are returned on one line separated by white
+ * space. Slapd stores each boot parameter as a separate entry. If more
+ * than one bootparameter is available, a white space separated buffer
+ * must be constructed and returned.
+ */
+
+static int
+_nss_ldap_bootparams2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j, nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char *cp = (char *)NULL;
+ char *buffer = (char *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_bp2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_bp2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _B_PARAMETER) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ *buffer = 0;
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_bp2ent;
+ }
+ if (len > buflen) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_bp2ent;
+ }
+ if (firstime) {
+ (void) strcpy(buffer,
+ attrptr->attrvalue[j]);
+ firstime = (int)0;
+ } else {
+ if ((cp = strrchr(buffer, '\0'))
+ != NULL)
+ *cp = ' ';
+ (void) strcat(buffer,
+ attrptr->attrvalue[j]);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[bootparams_getbyname.c: "
+ "_nss_ldap_bootparams2ent]\n");
+ (void) fprintf(stdout, " bootparameter: [%s]\n", buffer);
+#endif /* DEBUG */
+
+result_bp2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+/*
+ * getbyname gets bootparameters by host name. This function constructs an
+ * ldap search filter using the host name invocation parameter and the
+ * getbootparambyname search filter defined. Once the filter is
+ * constructed, we search for matching entries and marshal the data
+ * results into argp->buf.buffer for the frontend process. The function
+ * _nss_ldap_bootparams2ent performs the data marshaling.
+ *
+ * RFC 2307, An Approach for Using LDAP as a Network Information Service,
+ * indicates that dn's be fully qualified. Host name searches will be on
+ * fully qualified host names (e.g., foo.bar.sun.com).
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char hostname[3 * MAXHOSTNAMELEN];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(hostname, argp->key.name, sizeof (hostname)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETBOOTPARAMBYNAME, hostname);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETBOOTPARAMBYNAME_SSD, hostname);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _BOOTPARAMS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t bootparams_ops[] = {
+ _nss_ldap_destr,
+ getbyname
+};
+
+
+/*
+ * _nss_ldap_bootparams_constr is where life begins. This function calls
+ * the generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_bootparams_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(bootparams_ops,
+ sizeof (bootparams_ops)/sizeof (bootparams_ops[0]),
+ _BOOTPARAMS, bootparams_attrs, _nss_ldap_bootparams2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getether.c b/usr/src/lib/nsswitch/ldap/common/getether.c
new file mode 100644
index 0000000000..01f337dea8
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getether.c
@@ -0,0 +1,283 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <net/if_arp.h>
+#include <netinet/if_ether.h>
+#include "ldap_common.h"
+
+/* ether attributes filters */
+#define _E_HOSTNAME "cn"
+#define _E_MACADDRESS "macaddress"
+#define _F_GETETHERBYHOST "(&(objectClass=ieee802Device)(cn=%s))"
+#define _F_GETETHERBYHOST_SSD "(&(%%s)(cn=%s))"
+#define _F_GETETHERBYETHER "(&(objectClass=ieee802Device)(macAddress=%s))"
+#define _F_GETETHERBYETHER_SSD "(&(%%s)(macAddress=%s))"
+
+static const char *ethers_attrs[] = {
+ _E_HOSTNAME,
+ _E_MACADDRESS,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_ethers2ent is the data marshaling method for the ethers
+ * getXbyY * (e.g., getbyhost(), getbyether()) backend processes. This
+ * method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into uchar_t *ether
+ * = argp->buf.buffer which the frontend process expects. Three error
+ * conditions are expected and returned to nsswitch.
+ *
+ * Place the resulting struct ether_addr from the ldap query into
+ * argp->buf.result only if argp->buf.result is initialized (not NULL).
+ * e.g., it happens for the call ether_hostton.
+ *
+ * Place the resulting hostname into argp->buf.buffer only if
+ * argp->buf.buffer is initialized. I.e. it happens for the call
+ * ether_ntohost.
+ *
+ * argp->buf.buflen does not make sense for ethers. It is always set
+ * to 0 by the frontend. The caller only passes a hostname pointer in
+ * case of ether_ntohost, that is assumed to be big enough. For
+ * ether_hostton, the struct ether_addr passed is a fixed size.
+ *
+ * The interface does not let the caller specify how long is the buffer
+ * pointed by host. We make a safe assumption that the callers will
+ * always give MAXHOSTNAMELEN. In any case, it is the only finite number
+ * we can lay our hands on in case of runaway strings, memory corruption etc.
+ */
+
+static int
+_nss_ldap_ethers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, ip;
+ int nss_result;
+ int buflen = (int)0;
+ unsigned int t[ETHERADDRL];
+ unsigned long len = 0L;
+ char *host = NULL;
+ struct ether_addr *ether = NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+ int etherflag = 0, hostflag = 0;
+
+ if (argp->buf.buffer) {
+ hostflag = 1;
+ host = argp->buf.buffer;
+ }
+
+ buflen = (size_t)argp->buf.buflen;
+
+ if (argp->buf.result) {
+ etherflag = 1;
+ ether = (struct ether_addr *)argp->buf.result;
+ }
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_ea2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_ea2ent;
+ }
+ if (hostflag) {
+ if (strcasecmp(attrptr->attrname, _E_HOSTNAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_ea2ent;
+ }
+ if (len > MAXHOSTNAMELEN) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_ea2ent;
+ }
+ (void) strcpy(host, attrptr->attrvalue[0]);
+ continue;
+ }
+ }
+ if (etherflag) {
+ if (strcasecmp(attrptr->attrname, _E_MACADDRESS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_ea2ent;
+ }
+ ip = (int)sscanf(attrptr->attrvalue[0],
+ "%x:%x:%x:%x:%x:%x", &t[0], &t[1],
+ &t[2], &t[3], &t[4], &t[5]);
+ if (ip != ETHERADDRL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_ea2ent;
+ }
+ for (ip = 0; ip < ETHERADDRL; ip++)
+ ether->ether_addr_octet[ip] =
+ (uchar_t)t[ip];
+ continue;
+ }
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ether_addr.c: _nss_ldap_ethers2ent]\n");
+ if (host != NULL)
+ (void) fprintf(stdout, " hostname: [%s]\n", host);
+ if (ether != NULL)
+ (void) fprintf(stdout,
+ " ether_addr: [%x:%x:%x:%x:%x:%x]\n",
+ ether->ether_addr_octet[0],
+ ether->ether_addr_octet[1],
+ ether->ether_addr_octet[2],
+ ether->ether_addr_octet[3],
+ ether->ether_addr_octet[4],
+ ether->ether_addr_octet[5]);
+#endif /* DEBUG */
+
+result_ea2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+/*
+ * getbyhost gets an ethernet address by hostname. This function
+ * constructs an ldap search filter using the hostname invocation
+ * parameter and the getetherbyhost search filter defined. Once
+ * the filter is constructed, we search for a matching entry and
+ * marshal the data results into uchar_t *ether for the frontend
+ * process. The function _nss_ldap_ethers2ent performs the data
+ * marshaling.
+ *
+ * RFC 2307, An Approach for Using LDAP as a Network Information Service,
+ * indicates that dn's be fully qualified. Host name searches will be on
+ * fully qualified host names (e.g., foo.bar.sun.com).
+ */
+
+static nss_status_t
+getbyhost(ldap_backend_ptr be, void *a)
+{
+ char hostname[3 * MAXHOSTNAMELEN];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(hostname, argp->key.name, sizeof (hostname)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETETHERBYHOST, hostname);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETETHERBYHOST_SSD, hostname);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _ETHERS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbyether gets an ethernet address by ethernet address. This
+ * function constructs an ldap search filter using the ASCII
+ * ethernet address invocation parameter and the getetherbyether
+ * search filter defined. Once the filter is constructed, we
+ * search for a matching entry and marshal the data results into
+ * uchar_t *ether for the frontend process. The function
+ * _nss_ldap_ethers2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbyether(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char etherstr[18];
+ uchar_t *e = argp->key.ether;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ ret = snprintf(etherstr, sizeof (etherstr), "%x:%x:%x:%x:%x:%x",
+ *e, *(e + 1), *(e + 2), *(e + 3), *(e + 4), *(e + 5));
+ if (ret >= sizeof (etherstr) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETETHERBYETHER, etherstr);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETETHERBYETHER_SSD, etherstr);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _ETHERS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t ethers_ops[] = {
+ _nss_ldap_destr,
+ getbyhost,
+ getbyether
+};
+
+
+/*
+ * _nss_ldap_ethers_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_ethers_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(ethers_ops,
+ sizeof (ethers_ops)/sizeof (ethers_ops[0]), _ETHERS,
+ ethers_attrs, _nss_ldap_ethers2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getexecattr.c b/usr/src/lib/nsswitch/ldap/common/getexecattr.c
new file mode 100644
index 0000000000..4dfedc8628
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getexecattr.c
@@ -0,0 +1,540 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <secdb.h>
+#include <exec_attr.h>
+#include "ldap_common.h"
+
+
+/* exec_attr attributes filters */
+#define ISWILD(x) (x == NULL) ? "*" : x
+#define _EXEC_NAME "cn"
+#define _EXEC_POLICY "SolarisKernelSecurityPolicy"
+#define _EXEC_TYPE "SolarisProfileType"
+#define _EXEC_RES1 "SolarisAttrRes1"
+#define _EXEC_RES2 "SolarisAttrRes2"
+#define _EXEC_ID "SolarisProfileId"
+#define _EXEC_ATTRS "SolarisAttrKeyValue"
+#define _EXEC_GETEXECNAME "(&(objectClass=SolarisExecAttr)(cn=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+#define _EXEC_GETEXECNAME_SSD "(&(%%s)(cn=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+#define _EXEC_GETEXECID "(&(objectClass=SolarisExecAttr)"\
+ "(SolarisProfileId=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+#define _EXEC_GETEXECID_SSD "(&(%%s)"\
+ "(SolarisProfileId=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+#define _EXEC_GETEXECNAMEID "(&(objectClass=SolarisExecAttr)(cn=%s)"\
+ "(SolarisProfileId=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+#define _EXEC_GETEXECNAMEID_SSD "(&(%%s)(cn=%s)"\
+ "(SolarisProfileId=%s)"\
+ "(SolarisKernelSecurityPolicy=%s)"\
+ "(SolarisProfileType=%s))"
+
+
+/* from libnsl */
+extern int _doexeclist(nss_XbyY_args_t *);
+extern char *_exec_wild_id(char *, const char *);
+extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *);
+
+
+static const char *exec_attrs[] = {
+ _EXEC_NAME,
+ _EXEC_POLICY,
+ _EXEC_TYPE,
+ _EXEC_RES1,
+ _EXEC_RES2,
+ _EXEC_ID,
+ _EXEC_ATTRS,
+ (char *)NULL
+};
+
+
+#ifdef DEBUG
+static void
+_print_execstr(execstr_t *exec)
+{
+
+ (void) fprintf(stdout, " exec-name: [%s]\n", exec->name);
+ if (exec->policy != (char *)NULL) {
+ (void) fprintf(stdout, " policy: [%s]\n", exec->policy);
+ }
+ if (exec->type != (char *)NULL) {
+ (void) fprintf(stdout, " type: [%s]\n", exec->type);
+ }
+ if (exec->res1 != (char *)NULL) {
+ (void) fprintf(stdout, " res1: [%s]\n", exec->res1);
+ }
+ if (exec->res2 != (char *)NULL) {
+ (void) fprintf(stdout, " res2: [%s]\n", exec->res2);
+ }
+ if (exec->id != (char *)NULL) {
+ (void) fprintf(stdout, " id: [%s]\n", exec->id);
+ }
+ if (exec->attr != (char *)NULL) {
+ (void) fprintf(stdout, " attr: [%s]\n", exec->attr);
+ }
+ if (exec->next != (execstr_t *)NULL) {
+ (void) fprintf(stdout, " next: [%s]\n", exec->next->name);
+ (void) fprintf(stdout, "\n");
+ _print_execstr(exec->next);
+ }
+}
+#endif /* DEBUG */
+
+
+static int
+_exec_ldap_exec2ent(ns_ldap_entry_t *entry, nss_XbyY_args_t *argp)
+{
+
+ int i;
+ unsigned long len = 0L;
+ int buflen = (int)0;
+ char *nullstring = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ execstr_t *exec = (execstr_t *)NULL;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ (void) memset(argp->buf.buffer, 0, buflen);
+ exec = (execstr_t *)(argp->buf.result);
+ ceiling = buffer + buflen;
+ exec->name = (char *)NULL;
+ exec->policy = (char *)NULL;
+ exec->type = (char *)NULL;
+ exec->res1 = (char *)NULL;
+ exec->res2 = (char *)NULL;
+ exec->id = (char *)NULL;
+ exec->attr = (char *)NULL;
+
+ for (i = 0; i < entry->attr_count; i++) {
+ attrptr = entry->attr_pair[i];
+ if (attrptr == NULL) {
+ return ((int)NSS_STR_PARSE_PARSE);
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ return ((int)NSS_STR_PARSE_PARSE);
+ }
+ exec->name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_POLICY) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->policy = nullstring;
+ } else {
+ exec->policy = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->policy,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_TYPE) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->type = nullstring;
+ } else {
+ exec->type = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->type,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_RES1) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->res1 = nullstring;
+ } else {
+ exec->res1 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->res1,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_RES2) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->res2 = nullstring;
+ } else {
+ exec->res2 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->res2,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_ID) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->id = nullstring;
+ } else {
+ exec->id = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->id, attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _EXEC_ATTRS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ exec->attr = nullstring;
+ } else {
+ exec->attr = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ return ((int)NSS_STR_PARSE_ERANGE);
+ }
+ (void) strcpy(exec->attr,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+ exec->next = (execstr_t *)NULL;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getexecattr.c: _exec_ldap_exec2ent]\n");
+ _print_execstr(exec);
+#endif /* DEBUG */
+
+ return ((int)NSS_STR_PARSE_SUCCESS);
+}
+
+
+/*
+ * place the results from ldap object structure into argp->buf.result
+ * returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
+ */
+static int
+_nss_ldap_exec2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int status = (int)NSS_STR_PARSE_SUCCESS;
+ ns_ldap_entry_t *entry;
+ ns_ldap_result_t *result = be->result;
+
+ if (!argp->buf.result) {
+ status = (int)NSS_STR_PARSE_ERANGE;
+ goto result_exec2ent;
+ }
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ status = _exec_ldap_exec2ent(entry, argp);
+ if (status != NSS_STR_PARSE_SUCCESS) {
+ goto result_exec2ent;
+ }
+ }
+
+result_exec2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return (status);
+}
+
+
+static nss_status_t
+_exec_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int status;
+ nss_status_t nss_stat = NSS_UNAVAIL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_entry_t *entry;
+ ns_ldap_result_t *result = be->result;
+ _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getexecattr.c: _exec_process_val]\n");
+#endif /* DEBUG */
+
+ argp->returnval = NULL;
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ (void) __ns_ldap_freeResult(&be->result);
+ return (nss_stat);
+ }
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ status = _exec_ldap_exec2ent(entry, argp);
+ switch (status) {
+ case NSS_STR_PARSE_SUCCESS:
+ argp->returnval = argp->buf.result;
+ nss_stat = NSS_SUCCESS;
+ if (_priv_exec->search_flag == GET_ALL) {
+ if (_doexeclist(argp) == 0) {
+ nss_stat = NSS_UNAVAIL;
+ }
+ }
+ break;
+ case NSS_STR_PARSE_ERANGE:
+ argp->erange = 1;
+ nss_stat = NSS_NOTFOUND;
+ break;
+ case NSS_STR_PARSE_PARSE:
+ nss_stat = NSS_NOTFOUND;
+ break;
+ default:
+ nss_stat = NSS_UNAVAIL;
+ break;
+ }
+
+ if ((_priv_exec->search_flag == GET_ONE) ||
+ (nss_stat != NSS_SUCCESS)) {
+ break;
+ }
+ }
+
+ return (nss_stat);
+}
+
+
+/*
+ * Check if we have either an exact match or a wild-card entry for that id.
+ */
+static nss_status_t
+get_wild(ldap_backend_ptr be, nss_XbyY_args_t *argp, int getby_flag)
+{
+ char *dup_id = NULL;
+ char *wild_id;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ char id[SEARCHFILTERLEN];
+ int ret;
+ nss_status_t nss_stat = NSS_NOTFOUND;
+ _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
+ const char *policy = _priv_exec->policy;
+ const char *type = _priv_exec->type;
+
+ if (strpbrk(policy, "*()\\") != NULL ||
+ type != NULL && strpbrk(type, "*()\\") != NULL)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (_priv_exec->id != NULL)
+ dup_id = strdup(_priv_exec->id);
+
+ switch (getby_flag) {
+ case NSS_DBOP_EXECATTR_BYNAMEID:
+ if (_ldap_filter_name(name, _priv_exec->name,
+ sizeof (name)) != 0)
+ goto go_out;
+ break;
+ }
+
+ wild_id = dup_id;
+ do {
+ if (wild_id != NULL) {
+ if (_ldap_filter_name(id, wild_id, sizeof (id)) != 0)
+ goto go_out;
+ } else
+ (void) strlcpy(id, "*", sizeof (id));
+
+ switch (getby_flag) {
+ case NSS_DBOP_EXECATTR_BYID:
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _EXEC_GETEXECID, id, policy, ISWILD(type));
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ goto go_out;
+ ret = snprintf(userdata, sizeof (userdata),
+ _EXEC_GETEXECID_SSD, id, policy, ISWILD(type));
+ if (ret >= sizeof (userdata) || ret < 0)
+ goto go_out;
+ break;
+
+ case NSS_DBOP_EXECATTR_BYNAMEID:
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _EXEC_GETEXECNAMEID, name, id,
+ policy, ISWILD(type));
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ goto go_out;
+ ret = snprintf(userdata, sizeof (userdata),
+ _EXEC_GETEXECNAMEID_SSD, name, id,
+ policy, ISWILD(type));
+ if (ret >= sizeof (userdata) || ret < 0)
+ goto go_out;
+ break;
+
+ default:
+ goto go_out;
+ }
+ nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR,
+ searchfilter, NULL, _merge_SSD_filter, userdata);
+ if (nss_stat == NSS_SUCCESS)
+ break;
+ } while ((wild_id = _exec_wild_id(wild_id, type)) != NULL);
+
+go_out:
+ free(dup_id);
+
+ return (nss_stat);
+}
+
+static nss_status_t
+getbynam(ldap_backend_ptr be, void *a)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+ nss_status_t nss_stat;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp);
+ const char *policy = _priv_exec->policy;
+ const char *type = _priv_exec->type;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getexecattr.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (strpbrk(policy, "*()\\") != NULL ||
+ type != NULL && strpbrk(type, "*()\\") != NULL ||
+ _ldap_filter_name(name, _priv_exec->name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _EXEC_GETEXECNAME, name, policy, ISWILD(type));
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ ret = snprintf(userdata, sizeof (userdata),
+ _EXEC_GETEXECNAME_SSD, name, policy, ISWILD(type));
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR,
+ searchfilter, NULL, _merge_SSD_filter, userdata);
+
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = _exec_process_val(be, argp);
+
+ _exec_cleanup(nss_stat, argp);
+
+ return (nss_stat);
+}
+
+
+static nss_status_t
+getbyid(ldap_backend_ptr be, void *a)
+{
+ nss_status_t nss_stat;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getexecattr.c: getbyid]\n");
+#endif /* DEBUG */
+
+ nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID);
+
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = _exec_process_val(be, argp);
+
+ _exec_cleanup(nss_stat, argp);
+
+ return (nss_stat);
+}
+
+
+static nss_status_t
+getbynameid(ldap_backend_ptr be, void *a)
+{
+ nss_status_t nss_stat;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getexecattr.c: getbynameid]\n");
+#endif /* DEBUG */
+
+ nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID);
+
+ if (nss_stat == NSS_SUCCESS)
+ nss_stat = _exec_process_val(be, argp);
+
+ _exec_cleanup(nss_stat, argp);
+
+ return (nss_stat);
+}
+
+
+static ldap_backend_op_t execattr_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbynam,
+ getbyid,
+ getbynameid
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_exec_attr_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5,
+ const char *dummy6,
+ const char *dummy7)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getexecattr.c: _nss_ldap_exec_attr_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(execattr_ops,
+ sizeof (execattr_ops)/sizeof (execattr_ops[0]), _EXECATTR,
+ exec_attrs, _nss_ldap_exec2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getgrent.c b/usr/src/lib/nsswitch/ldap/common/getgrent.c
new file mode 100644
index 0000000000..1533ad8b3b
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getgrent.c
@@ -0,0 +1,445 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <grp.h>
+#include "ldap_common.h"
+
+/* String which may need to be removed from beginning of group password */
+#define _CRYPT "{CRYPT}"
+#define _NO_PASSWD_VAL ""
+
+/* Group attributes filters */
+#define _G_NAME "cn"
+#define _G_GID "gidnumber"
+#define _G_PASSWD "userpassword"
+#define _G_MEM "memberuid"
+
+#define _F_GETGRNAM "(&(objectClass=posixGroup)(cn=%s))"
+#define _F_GETGRNAM_SSD "(&(%%s)(cn=%s))"
+#define _F_GETGRGID "(&(objectClass=posixGroup)(gidNumber=%ld))"
+#define _F_GETGRGID_SSD "(&(%%s)(gidNumber=%ld))"
+#define _F_GETGRMEM "(&(objectClass=posixGroup)(memberUid=%s))"
+#define _F_GETGRMEM_SSD "(&(%%s)(memberUid=%s))"
+
+static const char *gr_attrs[] = {
+ _G_NAME,
+ _G_GID,
+ _G_PASSWD,
+ _G_MEM,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_group2ent is the data marshaling method for the group getXbyY
+ * (e.g., getgrnam(), getgrgid(), getgrent()) backend processes. This method
+ * is called after a successful ldap search has been performed. This method
+ * will parse the ldap search values into struct group = argp->buf.buffer
+ * which the frontend process expects. Three error conditions are expected
+ * and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_group2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char **mp = NULL;
+ char *val = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct group *grp = (struct group *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ grp = (struct group *)argp->buf.result;
+ ceiling = buffer + buflen;
+ mp = grp->gr_mem = (char **)NULL;
+
+ /* initialize no group password */
+ grp->gr_passwd = (char *)NULL;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _G_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+ grp->gr_name = buffer;
+ buffer += len + 1;
+ if (buffer > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ (void) strcpy(grp->gr_name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _G_PASSWD) == 0) {
+ val = attrptr->attrvalue[0];
+ /*
+ * Preen "{crypt}" if necessary.
+ * If the password does not include the {crypt} prefix
+ * then the password may be plain text. And thus
+ * perhaps crypt(3c) should be used to encrypt it.
+ * Currently the password is copied verbatim.
+ */
+ if (strncasecmp(val, _CRYPT,
+ (sizeof (_CRYPT) - 1)) == 0)
+ val += (sizeof (_CRYPT) - 1);
+ len = strlen(val);
+ grp->gr_passwd = buffer;
+ buffer += len + 1;
+ if (buffer > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ (void) strcpy(grp->gr_passwd, val);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _G_GID) == 0) {
+ if (strlen(attrptr->attrvalue[0]) == 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+ errno = 0;
+ grp->gr_gid = (gid_t)strtol(attrptr->attrvalue[0],
+ (char **)NULL, 10);
+ if (errno != 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _G_MEM) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstime) {
+ mp = grp->gr_mem =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)grp->gr_mem +
+ sizeof (char *) *
+ (attrptr->value_count + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer > ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ firstime = (int)0;
+ }
+ if (attrptr->attrvalue[j] == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_grp2ent;
+ }
+ len = strlen(attrptr->attrvalue[j]);
+ if (len == 0)
+ continue;
+ *mp = buffer;
+ buffer += len + 1;
+ if (buffer > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ (void) strcpy(*mp++, attrptr->attrvalue[j]);
+ continue;
+ }
+ }
+ }
+ /* Don't leave password as null */
+ if (grp->gr_passwd == (char *)NULL) {
+ /*
+ * The password may be missing; rfc2307bis defines
+ * the 'posixGroup' attributes 'authPassword' and
+ * 'userPassword' as being optional. Or a directory
+ * access control may be preventing us from reading
+ * the password. Currently we don't know which it is.
+ * If it's an access problem then perhaps the password
+ * should be set to "*NP*". But for now a simple empty
+ * string is returned.
+ */
+ grp->gr_passwd = buffer;
+ buffer += sizeof (_NO_PASSWD_VAL);
+ if (buffer > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ (void) strcpy(grp->gr_passwd, _NO_PASSWD_VAL);
+ }
+ if (mp == NULL) {
+ mp = grp->gr_mem = (char **)ROUND_UP(buffer, sizeof (char **));
+ buffer = (char *)grp->gr_mem + sizeof (char *);
+ buffer = (char *)ROUND_UP(buffer, sizeof (char **));
+ if (buffer > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_grp2ent;
+ }
+ }
+ *mp = NULL;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getgrent.c: _nss_ldap_group2ent]\n");
+ (void) fprintf(stdout, " gr_name: [%s]\n", grp->gr_name);
+ if (grp->gr_passwd != (char *)NULL)
+ (void) fprintf(stdout, " gr_passwd: [%s]\n",
+ grp->gr_passwd);
+ (void) fprintf(stdout, " gr_gid: [%ld]\n", grp->gr_gid);
+ if (mp != NULL) {
+ for (mp = grp->gr_mem; *mp != NULL; mp++)
+ (void) fprintf(stdout, " gr_mem: [%s]\n", *mp);
+ }
+#endif /* DEBUG */
+
+result_grp2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbynam gets a group entry by name. This function constructs an ldap
+ * search filter using the name invocation parameter and the getgrnam search
+ * filter defined. Once the filter is constructed, we searche for a matching
+ * entry and marshal the data results into struct group for the frontend
+ * process. The function _nss_ldap_group2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbynam(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char groupname[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getgrent.c: getbyname]\n");
+#endif /* DBEUG */
+ if (_ldap_filter_name(groupname, argp->key.name, sizeof (groupname))
+ != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETGRNAM, groupname);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETGRNAM_SSD, groupname);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _GROUP, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbygid gets a group entry by number. This function constructs an ldap
+ * search filter using the name invocation parameter and the getgrgid search
+ * filter defined. Once the filter is constructed, we searche for a matching
+ * entry and marshal the data results into struct group for the frontend
+ * process. The function _nss_ldap_group2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbygid(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getgrent.c: getbygid]\n");
+#endif /* DBEUG */
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETGRGID, (long)argp->key.uid);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETGRGID_SSD, (long)argp->key.uid);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _GROUP, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+
+}
+
+
+/*
+ * getbymember returns all groups a user is defined in. This function
+ * uses different architectural procedures than the other group backend
+ * system calls because it's a private interface. This function constructs
+ * an ldap search filter using the name invocation parameter. Once the
+ * filter is constructed, we search for all matching groups counting
+ * and storing each group name, gid, etc. Data marshaling is used for
+ * group processing. The function _nss_ldap_group2ent() performs the
+ * data marshaling.
+ *
+ * (const char *)argp->username; (size_t)strlen(argp->username);
+ * (gid_t)argp->gid_array; (int)argp->maxgids;
+ * (int)argp->numgids;
+ */
+
+static nss_status_t
+getbymember(ldap_backend_ptr be, void *a)
+{
+ int i, j, k;
+ int gcnt = (int)0;
+ char **groupvalue, **membervalue;
+ nss_status_t lstat;
+ nss_XbyY_args_t argb;
+ static nss_XbyY_buf_t *gb;
+ struct nss_groupsbymem *argp = (struct nss_groupsbymem *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ ns_ldap_result_t *result;
+ ns_ldap_entry_t *curEntry;
+ char *username;
+ gid_t gid;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getgrent.c: getbymember]\n");
+#endif /* DBEUG */
+
+ NSS_XbyY_ALLOC(&gb, sizeof (struct group), NSS_BUFLEN_GROUP);
+ NSS_XbyY_INIT(&argb, gb->result, gb->buffer, gb->buflen, 0);
+
+ if (strcmp(argp->username, "") == 0 ||
+ strcmp(argp->username, "root") == 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (_ldap_filter_name(name, argp->username, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETGRMEM, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETGRMEM_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ gcnt = (int)argp->numgids;
+ lstat = (nss_status_t)_nss_ldap_nocb_lookup(be, &argb,
+ _GROUP, searchfilter, NULL,
+ _merge_SSD_filter, userdata);
+ if (lstat != (nss_status_t)NS_LDAP_SUCCESS)
+ return ((nss_status_t)lstat);
+ if (be->result == NULL)
+ return (NSS_NOTFOUND);
+ username = (char *)argp->username;
+ result = (ns_ldap_result_t *)be->result;
+ curEntry = (ns_ldap_entry_t *)result->entry;
+ for (i = 0; i < result->entries_count; i++) {
+ membervalue = __ns_ldap_getAttr(curEntry, "memberUid");
+ if (membervalue) {
+ for (j = 0; membervalue[j]; j++) {
+ if (strcmp(membervalue[j], username) == NULL) {
+ groupvalue = __ns_ldap_getAttr(curEntry,
+ "gidnumber");
+ gid = (gid_t)strtol(groupvalue[0],
+ (char **)NULL, 10);
+ if (argp->numgids < argp->maxgids) {
+ for (k = 0; k < argp->numgids;
+ k++) {
+ if (argp->gid_array[k] == gid)
+ /* already exists */
+ break;
+ }
+ if (k == argp->numgids)
+ argp->gid_array[argp->numgids++]
+ = gid;
+ }
+ break;
+ }
+ }
+ }
+ curEntry = curEntry->next;
+ }
+
+ __ns_ldap_freeResult((ns_ldap_result_t **)&be->result);
+ NSS_XbyY_FREE(&gb);
+ if (gcnt == argp->numgids)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+static ldap_backend_op_t gr_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbynam,
+ getbygid,
+ getbymember
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_group_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(gr_ops,
+ sizeof (gr_ops)/sizeof (gr_ops[0]), _GROUP, gr_attrs,
+ _nss_ldap_group2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/gethostent.c b/usr/src/lib/nsswitch/ldap/common/gethostent.c
new file mode 100644
index 0000000000..78b84c785e
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/gethostent.c
@@ -0,0 +1,493 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <sys/systeminfo.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* host attributes filters */
+#define _H_DN "dn"
+#define _H_NAME "cn"
+#define _H_ADDR "iphostnumber"
+#define _F_GETHOSTBYNAME "(&(objectClass=ipHost)(cn=%s))"
+#define _F_GETHOSTBYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETHOSTDOTTEDBYNAME "(&(objectClass=ipHost)(|(cn=%s)(cn=%s)))"
+#define _F_GETHOSTDOTTEDBYNAME_SSD "(&(%%s)(|(cn=%s)(cn=%s)))"
+#define _F_GETHOSTBYADDR "(&(objectClass=ipHost)(ipHostNumber=%s))"
+#define _F_GETHOSTBYADDR_SSD "(&(%%s)(ipHostNumber=%s))"
+
+static const char *hosts_attrs[] = {
+ _H_NAME,
+ _H_ADDR,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_hosts2ent is the data marshaling method for the hosts getXbyY
+ * system call gethostbyname() and gethostbyaddr. The format of this call
+ * is a cononical name and alias (alias is cononical name too) and one or
+ * more IP addresses in support of multihomed hosts. This method is called
+ * after a successful synchronous search has been performed. This method
+ * will parse the search results into struct hostent = argp->buf.buffer
+ * which gets returned to the frontend process. One of three error
+ * conditions is also returned to nsswitch.
+ */
+
+static int
+_nss_ldap_hosts2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstimename = (int)1;
+ int firstimedn = (int)1;
+ int firstimeaddr = (int)1;
+ unsigned long len = 0L;
+ char **hn, **ha, **dp;
+ char *cname = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct hostent *host = (struct hostent *)NULL;
+ in_addr_t addr;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+ in_addr_t inet_addr(const char *cp);
+ int namecount = 0;
+ int addrcount = 0;
+ int aliascount = 0;
+ int validaddress = 0;
+ int gluelen = 0;
+ ns_ldap_entry_t *entry;
+ ns_ldap_attr_t *attr;
+#ifdef DEBUG
+ struct in_addr in;
+#endif /* DEBUG */
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+
+ host = (struct hostent *)argp->buf.result;
+ ceiling = buffer + buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+
+ namecount = 0;
+ addrcount = 0;
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0, attr = entry->attr_pair[i];
+ i < entry->attr_count; i++) {
+ attr = entry->attr_pair[i];
+ if (strcasecmp(attr->attrname, _H_NAME) == 0)
+ namecount += attr->value_count;
+ if (strcasecmp(attr->attrname, _H_ADDR) == 0)
+ addrcount += attr->value_count;
+ }
+ }
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0; i < entry->attr_count; i++) {
+ attrptr = entry->attr_pair[i];
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _H_DN) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimedn) {
+ /* get domain name associated with this dn */
+ be->toglue = _get_domain_name(
+ attrptr->attrvalue[j]);
+ firstimedn = (int)0;
+ }
+ }
+ }
+ if (strcasecmp(attrptr->attrname, _H_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimename) {
+ /* canonical name */
+ cname = __s_api_get_canonical_name(result->entry,
+ attrptr, 1);
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ if (be->toglue != NULL &&
+ !DOTTEDSUBDOMAIN(cname))
+ gluelen = strlen(be->toglue) + 1;
+ else
+ gluelen = 0;
+ host->h_name = buffer;
+ buffer += len + gluelen + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) strcpy(host->h_name, cname);
+ if (gluelen > 0) {
+ (void) strcat(host->h_name, ".");
+ (void) strcat(host->h_name, be->toglue);
+ }
+ /* alias name */
+ aliascount = (namecount >= 1 ? (namecount - 1) : 0);
+ hn = host->h_aliases = (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)host->h_aliases +
+ (sizeof (char *) * (aliascount + 1));
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ firstimename = (int)0;
+ }
+ /* alias list */
+ if (aliascount > 0) {
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ /* skip canonical name */
+ if (strcmp(cname, attrptr->attrvalue[j]) == 0)
+ continue;
+ /* check for duplicates */
+ for (dp = host->h_aliases; *dp != NULL; dp++) {
+ if (strcmp(*dp, attrptr->attrvalue[j]) == 0)
+ goto next_alias;
+ }
+ if (be->toglue != NULL &&
+ !DOTTEDSUBDOMAIN(attrptr->attrvalue[j]))
+ gluelen = strlen(be->toglue) + 1;
+ else
+ gluelen = 0;
+ *hn = buffer;
+ buffer += len + gluelen + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) strcpy(*hn, attrptr->attrvalue[j]);
+ if (gluelen > 0) {
+ (void) strcat(*hn, ".");
+ (void) strcat(*hn, be->toglue);
+ }
+ hn++;
+ }
+next_alias:
+ continue;
+ }
+ }
+ }
+ }
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0; i < entry->attr_count; i++) {
+ attrptr = entry->attr_pair[i];
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _H_ADDR) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimeaddr) {
+ /* allocate 1 address per entry */
+ ha = host->h_addr_list =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)host->h_addr_list +
+ sizeof (char *) *
+ (addrcount + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ firstimeaddr = (int)0;
+ }
+ /* filter out IPV6 addresses */
+ addr = inet_addr(_strip_quotes(attrptr->attrvalue[j]));
+ if (addr == (in_addr_t)-1) {
+ goto next_addr;
+ }
+ validaddress++;
+ /* check for duplicates */
+ for (dp = host->h_addr_list; *dp != NULL; dp++) {
+ if (memcmp(*dp, &addr, (size_t)sizeof (in_addr_t)) == 0)
+ goto next_addr;
+ }
+ *ha = buffer;
+ len = (unsigned long)sizeof (in_addr_t);
+ buffer += len;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) memcpy(*ha++, (char *)&addr, (size_t)len);
+next_addr:
+ continue;
+ }
+ }
+ }
+ }
+
+ if (validaddress == 0) {
+ nss_result = (int)NSS_STR_PARSE_NO_ADDR;
+ goto result_hosts2ent;
+ }
+
+ host->h_addrtype = AF_INET;
+ host->h_length = sizeof (uint_t);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts2ent]\n");
+ (void) fprintf(stdout, " h_name: [%s]\n", host->h_name);
+ if (host->h_aliases != NULL) {
+ for (hn = host->h_aliases; *hn != NULL; hn++)
+ (void) fprintf(stdout, " h_aliases: [%s]\n", *hn);
+ }
+ (void) fprintf(stdout, " h_addrtype: [%d]\n", host->h_addrtype);
+ (void) fprintf(stdout, " h_length: [%d]\n", host->h_length);
+ for (ha = host->h_addr_list; *ha != NULL; ha++) {
+ (void) memcpy(&in.s_addr, *ha, sizeof (in.s_addr));
+ if (inet_ntoa(in) != NULL)
+ (void) fprintf(stdout, " h_addr_list: [%s]\n",
+ inet_ntoa(in));
+ else
+ (void) fprintf(stdout, " h_addr_list: <NULL>\n");
+ }
+#endif /* DEBUG */
+
+result_hosts2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets a struct hostent by hostname. This function constructs
+ * an ldap search filter using the name invocation parameter and the
+ * gethostbyname search filter defined. Once the filter is constructed,
+ * we search for a matching entry and marshal the data results into
+ * struct hostent for the frontend process. Host name searches will be
+ * on fully qualified host names (foo.bar.sun.com)
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char hostname[3 * MAXHOSTNAMELEN];
+ char realdomain[BUFSIZ];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ nss_status_t lstat;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int rc;
+
+ if (_ldap_filter_name(hostname, argp->key.name, sizeof (hostname)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(searchfilter, sizeof (searchfilter), _F_GETHOSTBYNAME,
+ hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata), _F_GETHOSTBYNAME_SSD,
+ hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ /* get the domain we are in */
+ rc = sysinfo(SI_SRPC_DOMAIN, realdomain, BUFSIZ);
+ if (rc <= 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ /* Is this a request for a host.domain */
+ if (DOTTEDSUBDOMAIN(hostname)) {
+ char host[MAXHOSTNAMELEN];
+ char domain[MAXHOSTNAMELEN];
+ char hname[3 * MAXHOSTNAMELEN];
+
+ /* separate host and domain. this function */
+ /* will munge hname, so use argp->keyname */
+ /* from here on for original string */
+
+ (void) strcpy(hname, hostname);
+
+ if (chophostdomain(hname, host, domain) == -1) {
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ /* if domain is a proper subset of realdomain */
+ /* ie. domain = "eng" and realdomain */
+ /* = "eng.wiz.com", we try to lookup both" */
+ /* host.domain and host */
+
+ if (propersubdomain(realdomain, domain) == 1) {
+ /* yes, it is a proper domain */
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTDOTTEDBYNAME, hostname, host);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTDOTTEDBYNAME_SSD, hostname, host);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else {
+ /* it is not a proper domain, so only try to look up */
+ /* host.domain */
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTBYNAME, hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTBYNAME_SSD, hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ } else {
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTBYNAME, hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTBYNAME_SSD, hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ lstat = (nss_status_t)_nss_ldap_lookup(be, argp, _HOSTS,
+ searchfilter, NULL, _merge_SSD_filter,
+ userdata);
+ if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
+ return ((nss_status_t)NSS_SUCCESS);
+
+ argp->h_errno = __nss2herrno(lstat);
+ return ((nss_status_t)lstat);
+}
+
+
+/*
+ * getbyaddr gets a struct hostent by host address. This function
+ * constructs an ldap search filter using the host address invocation
+ * parameter and the gethostbyaddr search filter defined. Once the
+ * filter is constructed, we search for a matching entry and marshal
+ * the data results into struct hostent for the frontend process.
+ *
+ * extern char *inet_ntoa_r() not an advertised function from libnsl.
+ * There is no man page and no prototype.
+ */
+
+static nss_status_t
+getbyaddr(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ struct in_addr addr;
+ char buf[18];
+ nss_status_t lstat;
+ extern char *inet_ntoa_r();
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ argp->h_errno = 0;
+ if ((argp->key.hostaddr.type != AF_INET) ||
+ (argp->key.hostaddr.len != sizeof (addr)))
+ return (NSS_NOTFOUND);
+
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ (void) inet_ntoa_r(addr, buf);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETHOSTBYADDR,
+ buf);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETHOSTBYADDR_SSD, buf);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ lstat = (nss_status_t)_nss_ldap_lookup(be, argp,
+ _HOSTS, searchfilter, NULL, _merge_SSD_filter, userdata);
+ if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
+ return ((nss_status_t)NSS_SUCCESS);
+
+ argp->h_errno = __nss2herrno(lstat);
+ return ((nss_status_t)lstat);
+}
+
+static ldap_backend_op_t hosts_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbyaddr
+};
+
+
+/*
+ * _nss_ldap_hosts_constr is where life begins. This function calls the generic
+ * ldap constructor function to define and build the abstract data types
+ * required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_hosts_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_hosts_constr]\n");
+#endif /* DEBUG */
+ return ((nss_backend_t *)_nss_ldap_constr(hosts_ops,
+ sizeof (hosts_ops)/sizeof (hosts_ops[0]), _HOSTS,
+ hosts_attrs, _nss_ldap_hosts2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/gethostent6.c b/usr/src/lib/nsswitch/ldap/common/gethostent6.c
new file mode 100644
index 0000000000..8b0a453d69
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/gethostent6.c
@@ -0,0 +1,502 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <inet/ip6.h>
+#include <syslog.h>
+#include <sys/systeminfo.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* host attributes filters */
+
+/* probably some change in the ipHostNumber field */
+
+#define _H_DN "dn"
+#define _H_NAME "cn"
+#define _H_ADDR "iphostnumber"
+#define _F_GETHOSTS6BYNAME "(&(objectClass=ipHost)(cn=%s))"
+#define _F_GETHOSTS6BYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETHOSTS6DOTTEDBYNAME \
+ "(&(objectClass=ipHost)(|(cn=%s)(cn=%s)))"
+#define _F_GETHOSTS6DOTTEDBYNAME_SSD \
+ "(&(%%s)(|(cn=%s)(cn=%s)))"
+#define _F_GETHOSTS6BYADDR "(&(objectClass=ipHost)(ipHostNumber=%s))"
+#define _F_GETHOSTS6BYADDR_SSD "(&(%%s)(ipHostNumber=%s))"
+
+static const char *ipnodes_attrs[] = {
+ _H_NAME,
+ _H_ADDR,
+ (char *)NULL
+};
+
+extern int inet_pton(int, const char *, void *);
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+
+/*
+ * _nss_ldap_hosts2ent is the data marshaling method for the ipnodes getXbyY
+ * system call gethostbyname() and gethostbyaddr. The format of this call
+ * is a cononical name and alias (alias is cononical name too) and one or
+ * more IP addresses in support of multihomed hosts. This method is called
+ * after a successful synchronous search has been performed. This method
+ * will parse the search results into struct hostent = argp->buf.buffer
+ * which gets returned to the frontend process. One of three error
+ * conditions is also returned to nsswitch.
+ */
+
+static int
+_nss_ldap_hosts2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstimename = (int)1;
+ int firstimedn = (int)1;
+ int firstimeaddr = (int)1;
+ unsigned long len = 0L;
+ char **hn, **ha, **dp;
+ char *cname = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct hostent *host = (struct hostent *)NULL;
+ struct in6_addr addr6;
+ struct in_addr addr;
+ char *val;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+ int namecount = 0;
+ int addrcount = 0;
+ int aliascount = 0;
+ int gluelen = 0;
+ ns_ldap_entry_t *entry;
+ ns_ldap_attr_t *attr;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ host = (struct hostent *)argp->buf.result;
+ ceiling = buffer + buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0, attr = entry->attr_pair[i];
+ i < entry->attr_count; i++) {
+ attr = entry->attr_pair[i];
+ if (strcasecmp(attr->attrname, _H_NAME) == 0)
+ namecount += attr->value_count;
+ if (strcasecmp(attr->attrname, _H_ADDR) == 0)
+ addrcount += attr->value_count;
+ }
+ }
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0; i < entry->attr_count; i++) {
+ attrptr = entry->attr_pair[i];
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _H_DN) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimedn) {
+ /* get domain name associated with this dn */
+ be->toglue = _get_domain_name(
+ attrptr->attrvalue[j]);
+ firstimedn = (int)0;
+ }
+ }
+ }
+ if (strcasecmp(attrptr->attrname, _H_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimename) {
+ /* canonical name */
+ cname = __s_api_get_canonical_name(result->entry,
+ attrptr, 1);
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ if (be->toglue != NULL &&
+ !DOTTEDSUBDOMAIN(cname))
+ gluelen = strlen(be->toglue) + 1;
+ else
+ gluelen = 0;
+ host->h_name = buffer;
+ buffer += len + gluelen + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) strcpy(host->h_name, cname);
+ if (gluelen > 0) {
+ (void) strcat(host->h_name, ".");
+ (void) strcat(host->h_name, be->toglue);
+ }
+ /* alias name */
+ aliascount = (namecount >= 1 ? (namecount - 1) : 0);
+ hn = host->h_aliases =
+ (char **)ROUND_UP(buffer, sizeof (char **));
+ buffer = (char *)host->h_aliases +
+ sizeof (char *) * (aliascount + 1);
+ buffer = (char *)ROUND_UP(buffer, sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ firstimename = (int)0;
+ }
+ /* alias list */
+ if (aliascount > 0) {
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+ /* skip canonical name */
+ if (strcmp(attrptr->attrvalue[j], cname) == 0)
+ continue;
+ /* check for duplicates */
+ for (dp = host->h_aliases; *dp != NULL; dp++) {
+ if (strcmp(*dp, attrptr->attrvalue[j]) == 0)
+ goto next_alias;
+ }
+ if (be->toglue != NULL &&
+ !DOTTEDSUBDOMAIN(attrptr->attrvalue[j]))
+ gluelen = strlen(be->toglue) + 1;
+ else
+ gluelen = 0;
+ *hn = buffer;
+ buffer += len + gluelen + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) strcpy(*hn, attrptr->attrvalue[j]);
+ if (gluelen > 0) {
+ (void) strcat(*hn, ".");
+ (void) strcat(*hn, be->toglue);
+ }
+ hn++;
+ }
+next_alias:
+ continue;
+ }
+ }
+ }
+ }
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ for (i = 0; i < entry->attr_count; i++) {
+ attrptr = entry->attr_pair[i];
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_hosts2ent;
+ }
+
+ if (strcasecmp(attrptr->attrname, _H_ADDR) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstimeaddr) {
+ /* allocate 1 address per entry */
+ ha = host->h_addr_list = (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)host->h_addr_list +
+ sizeof (char *) * (addrcount + 1);
+ buffer = (char *)ROUND_UP(buffer, sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ firstimeaddr = (int)0;
+ }
+ val = (char *)_strip_quotes(attrptr->attrvalue[j]);
+ if (inet_pton(AF_INET6, val, (void *) &addr6) != 1) {
+ if (inet_pton(AF_INET, val, (void *) &addr) != 1) {
+ goto next_addr;
+ } else {
+ IN6_INADDR_TO_V4MAPPED(&addr, &addr6);
+ }
+ }
+
+ /* check for duplicates */
+ for (dp = host->h_addr_list; *dp != NULL; dp++) {
+ if (memcmp(*dp, &addr6, sizeof (struct in6_addr))
+ == 0)
+ goto next_addr;
+ }
+ *ha = buffer;
+ len = (unsigned long)sizeof (struct in6_addr);
+ buffer += len;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_hosts2ent;
+ }
+ (void) memcpy(*ha++, (char *)&addr6, (size_t)len);
+next_addr:
+ continue;
+ }
+ }
+ }
+ }
+
+ host->h_addrtype = AF_INET6;
+ host->h_length = IPV6_ADDR_LEN;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent.c: _nss_ldap_byname2ent]\n");
+ (void) fprintf(stdout, " h_name: [%s]\n", host->h_name);
+ if (host->h_aliases != NULL) {
+ for (hn = host->h_aliases; *hn != NULL; hn++)
+ (void) fprintf(stdout, " h_aliases: [%s]\n", *hn);
+ }
+ (void) fprintf(stdout, " h_addrtype: [%d]\n", host->h_addrtype);
+ (void) fprintf(stdout, " h_length: [%d]\n", host->h_length);
+
+ for (hn = host->h_addr_list; *hn != NULL; hn++) {
+ char addrbuf[INET6_ADDRSTRLEN + 1];
+ (void) fprintf(stdout, " haddr_list: [%s]\n",
+ inet_ntop(AF_INET6, (void *)hn, (void *)addrbuf,
+ INET6_ADDRSTRLEN));
+ }
+#endif /* DEBUG */
+
+result_hosts2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets a struct hostent by hostname. This function constructs
+ * an ldap search filter using the name invocation parameter and the
+ * gethostbyname search filter defined. Once the filter is constructed,
+ * we search for a matching entry and marshal the data results into
+ * struct hostent for the frontend process. Host name searches will be
+ * on fully qualified host names (foo.bar.sun.com)
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char hostname[3 * MAXHOSTNAMELEN];
+ char realdomain[BUFSIZ];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ nss_status_t lstat;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int rc;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent6.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(hostname, argp->key.ipnode.name,
+ sizeof (hostname)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTS6BYNAME, hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTS6BYNAME_SSD, hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ /* get the domain we are in */
+ rc = sysinfo(SI_SRPC_DOMAIN, realdomain, BUFSIZ);
+ if (rc <= 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ /* Is this a request for a host.domain */
+ if (DOTTEDSUBDOMAIN(hostname)) {
+ char host[MAXHOSTNAMELEN];
+ char domain[MAXHOSTNAMELEN];
+ char hname[3 * MAXHOSTNAMELEN];
+
+ /* separate host and domain. this function */
+ /* will munge hname, so use argp->keyname */
+ /* from here on for original string */
+
+ (void) strcpy(hname, hostname);
+ if (chophostdomain(hname, host, domain) == -1) {
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ /* if domain is a proper subset of realdomain */
+ /* ie. domain = "foo" and realdomain */
+ /* = "foor.bar.sun.com", we try to lookup both" */
+ /* host.domain and host */
+
+ if (propersubdomain(realdomain, domain) == 1) {
+ /* yes, it is a proper domain */
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTS6DOTTEDBYNAME, hostname, host);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTS6DOTTEDBYNAME_SSD, hostname, host);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else {
+ /* it is not a proper domain, so only try to look up */
+ /* host.domain */
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTS6BYNAME, hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTS6BYNAME_SSD, hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ } else {
+ rc = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTS6BYNAME, hostname);
+ if (rc >= sizeof (searchfilter) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTS6BYNAME_SSD, hostname);
+ if (rc >= sizeof (userdata) || rc < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ lstat = (nss_status_t)_nss_ldap_lookup(be, argp, _HOSTS,
+ searchfilter, NULL,
+ _merge_SSD_filter, userdata);
+ if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
+ return ((nss_status_t)NSS_SUCCESS);
+
+ argp->h_errno = __nss2herrno(lstat);
+ return ((nss_status_t)lstat);
+}
+
+
+/*
+ * getbyaddr gets a struct hostent by host address. This function
+ * constructs an ldap search filter using the host address invocation
+ * parameter and the gethostbyaddr search filter defined. Once the
+ * filter is constructed, we search for a matching entry and marshal
+ * the data results into struct hostent for the frontend process.
+ */
+
+static nss_status_t
+getbyaddr(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ struct in6_addr addr;
+ char addrbuf[INET6_ADDRSTRLEN + 1];
+ nss_status_t lstat;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent6.c: getbyaddr]\n");
+#endif /* DEBUG */
+ argp->h_errno = 0;
+ if ((argp->key.hostaddr.type != AF_INET6) ||
+ (argp->key.hostaddr.len != sizeof (addr)))
+ return (NSS_NOTFOUND);
+
+ (void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
+ if (IN6_IS_ADDR_V4MAPPED(&addr)) {
+ if (inet_ntop(AF_INET, (void *) &addr.s6_addr[12],
+ (void *)addrbuf, INET_ADDRSTRLEN) == NULL) {
+ return (NSS_NOTFOUND);
+ }
+ } else {
+ if (inet_ntop(AF_INET6, (void *)&addr, (void *)addrbuf,
+ INET6_ADDRSTRLEN) == NULL)
+ return (NSS_NOTFOUND);
+ }
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETHOSTS6BYADDR, addrbuf);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETHOSTS6BYADDR_SSD, addrbuf);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ lstat = (nss_status_t)_nss_ldap_lookup(be, argp,
+ _HOSTS6, searchfilter, NULL,
+ _merge_SSD_filter, userdata);
+ if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
+ return ((nss_status_t)NSS_SUCCESS);
+
+ argp->h_errno = __nss2herrno(lstat);
+ return ((nss_status_t)lstat);
+}
+
+static ldap_backend_op_t ipnodes_ops[] = {
+ _nss_ldap_destr,
+ 0,
+ 0,
+ 0,
+ getbyname,
+ getbyaddr
+};
+
+
+/*
+ * _nss_ldap_hosts_constr is where life begins. This function calls the generic
+ * ldap constructor function to define and build the abstract data types
+ * required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_ipnodes_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[gethostent6.c: _nss_ldap_host6_constr]\n");
+#endif /* DEBUG */
+ return ((nss_backend_t *)_nss_ldap_constr(ipnodes_ops,
+ sizeof (ipnodes_ops)/sizeof (ipnodes_ops[0]), _HOSTS6,
+ ipnodes_attrs, _nss_ldap_hosts2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getkeyent.c b/usr/src/lib/nsswitch/ldap/common/getkeyent.c
new file mode 100644
index 0000000000..c1c9dbd381
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getkeyent.c
@@ -0,0 +1,262 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <pwd.h>
+#include <ctype.h>
+#include "ldap_common.h"
+
+/* publickey attributes filters */
+#define _KEY_CN "cn"
+#define _KEY_NISPUBLICKEY "nisPublickey"
+#define _KEY_NISSECRETKEY "nisSecretkey"
+#define _KEY_UIDNUMBER "uidnumber"
+
+#define _F_GETKEY_USER "(&(objectClass=nisKeyObject)(uidNumber=%s))"
+#define _F_GETKEY_USER_SSD "(&(%%s)(uidNumber=%s))"
+#define _F_GETKEY_HOST "(&(objectClass=nisKeyObject)(cn=%s))"
+#define _F_GETKEY_HOST_SSD "(&(%%s)(cn=%s))"
+
+static const char *keys_attrs[] = {
+ _KEY_NISPUBLICKEY,
+ _KEY_NISSECRETKEY,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_key2ent is the data marshaling method for the publickey getXbyY
+ * (e.g., getpublickey() and getsecretkey()) backend processes. This method
+ * is called after a successful ldap search has been performed. This method
+ * will parse the ldap search values into "public:secret" key string =
+ * argp->buf.buffer which the frontend process expects. Three error
+ * conditions are expected and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_key2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int nss_result;
+ char *keytype = (char *)argp->key.pkey.keytype;
+ int keytypelen = strlen(keytype);
+ char *key_start = NULL;
+ int key_len;
+ int buflen = (size_t)argp->buf.buflen;
+ char *buffer = (char *)argp->buf.buffer;
+ char *ceiling = (char *)NULL;
+ ns_ldap_result_t *result = be->result;
+ char **key_array;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpublikey.c: _nss_ldap_passwd2ent]\n");
+#endif /* DEBUG */
+
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_key2ent;
+ }
+ ceiling = buffer + buflen;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(buffer, 0, buflen);
+
+ /* get the publickey */
+ key_array = __ns_ldap_getAttr(result->entry, _KEY_NISPUBLICKEY);
+ if (key_array == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_key2ent;
+ }
+ while (*key_array) {
+ if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
+ break;
+ key_array++;
+ }
+ if (*key_array == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_key2ent;
+ }
+
+ key_start = *(key_array) + keytypelen;
+ key_len = strlen(key_start) + 1;
+ if (buffer + key_len + 2 > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_key2ent;
+ }
+ (void) strncpy(buffer, key_start, key_len);
+ (void) strcat(buffer, ":");
+ buffer += strlen(buffer);
+
+ /* get the secretkey */
+ key_array = __ns_ldap_getAttr(result->entry, _KEY_NISSECRETKEY);
+ if (key_array == NULL) {
+ /*
+ * if we got this far, it's possible that the secret
+ * key is actually missing or no permission to read it.
+ * For the current implementation, we assume that the
+ * clients have read permission to the secret key. So,
+ * the only possibility of reaching this here is due to
+ * missing secret key.
+ */
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_key2ent;
+ }
+ while (*key_array) {
+ if (strncasecmp(*key_array, keytype, keytypelen) == NULL)
+ break;
+ key_array++;
+ }
+ if (*key_array == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_key2ent;
+ }
+
+ key_start = *(key_array) + keytypelen;
+ key_len = strlen(key_start);
+ if (buffer + key_len + 1 > ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_key2ent;
+ }
+ (void) strcat(buffer, key_start);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_key2ent]\n");
+ (void) fprintf(stdout, "\treturn: %s\n", buffer);
+#endif /* DEBUG */
+
+result_key2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getkeys gets both the public and secret keys from publickey entry by either
+ * uid name or host name. This function constructs an ldap search filter using
+ * the name invocation parameter and the getpwnam search filter defined. Once
+ * the filter is constructed, we search for a matching entry and marshal the
+ * data results into struct passwd for the frontend process. The function
+ * _nss_ldap_key2ent performs the data marshaling.
+ * The lookups will be done using the proxy credential. We don't want to use
+ * the user's credential for lookup at this point because we don't have any
+ * secure transport.
+ */
+
+static nss_status_t
+getkeys(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char netname[SEARCHFILTERLEN];
+ char *name, *domain, *p;
+ nss_status_t rc;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n");
+#endif /* DEBUG */
+
+ /*
+ * We need to break it down to find if this is a netname for host
+ * or user. We'll pass the domain as is to the LDAP call.
+ */
+ if (_ldap_filter_name(netname, argp->key.pkey.name, sizeof (netname))
+ != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ domain = strchr(netname, '@');
+ if (!domain)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ *domain++ = '\0';
+ if ((p = strchr(netname, '.')) == NULL)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ name = ++p;
+ if (isdigit(*name)) {
+ /* user keys lookup */
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETKEY_USER, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETKEY_USER_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = (nss_status_t)_nss_ldap_lookup(be, argp,
+ _PASSWD, searchfilter, domain,
+ _merge_SSD_filter, userdata);
+ } else {
+ /* host keys lookup */
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETKEY_HOST, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETKEY_HOST_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ rc = (nss_status_t)_nss_ldap_lookup(be, argp,
+ _HOSTS, searchfilter, domain,
+ _merge_SSD_filter, userdata);
+ }
+ return (rc);
+}
+
+
+static ldap_backend_op_t keys_ops[] = {
+ _nss_ldap_destr,
+ 0,
+ 0,
+ 0,
+ getkeys
+};
+
+
+/*
+ * _nss_ldap_publickey_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_publickey_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getkeys.c: _nss_ldap_keys_constr]\n");
+#endif /* DEBUG */
+
+ return ((nss_backend_t *)_nss_ldap_constr(keys_ops,
+ sizeof (keys_ops)/sizeof (keys_ops[0]),
+ _PUBLICKEY, keys_attrs, _nss_ldap_key2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetent.c b/usr/src/lib/nsswitch/ldap/common/getnetent.c
new file mode 100644
index 0000000000..a5afb360ce
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getnetent.c
@@ -0,0 +1,355 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* networks attributes filters */
+#define _N_NAME "cn"
+#define _N_NETWORK "ipnetworknumber"
+#define _F_GETNETBYNAME "(&(objectClass=ipNetwork)(cn=%s))"
+#define _F_GETNETBYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETNETBYADDR "(&(objectClass=ipNetwork)(ipNetworkNumber=%s))"
+#define _F_GETNETBYADDR_SSD "(&(%%s)(ipNetworkNumber=%s))"
+
+static const char *networks_attrs[] = {
+ _N_NAME,
+ _N_NETWORK,
+ (char *)NULL
+};
+
+/*
+ * _nss_ldap_networks2ent is the data marshaling method for the networks
+ * getXbyY * (e.g., getbyname(), getbyaddr(), getnetent() backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into struct netent =
+ * argp->buf.buffer which the frontend process expects. Three error conditions
+ * are expected and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_networks2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char **mp, *cname = NULL;
+#ifdef DEBUG
+ char addrstr[16];
+#endif /* DEBUG */
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct netent *ntk = (struct netent *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_net2ent;
+ }
+ ntk = (struct netent *)argp->buf.result;
+ ceiling = buffer + buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _N_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstime) {
+ /*
+ * The definition of the object class
+ * "ipNetwork" has a descripency between
+ * RFC 2307 and 2307bis.
+ * In 2307, "cn" is a MUST attribute.
+ * In 2307bis, "cn" is a MAY attribute.
+ * If "cn" is a MAY attribute,
+ * it does not appear in RDN and can't
+ * be derived from RDN as a canonical
+ * "cn" name. In that case, use 1st
+ * "cn" value as the official name.
+ */
+ cname = __s_api_get_canonical_name(
+ result->entry, attrptr, 1);
+ if (cname == NULL)
+ /* 2307bis case */
+ cname = attrptr->attrvalue[j];
+
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result =
+ NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+ ntk->n_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_net2ent;
+ }
+ (void) strcpy(ntk->n_name, cname);
+ /* alias list */
+ mp = ntk->n_aliases =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)ntk->n_aliases +
+ sizeof (char *) *
+ (attrptr->value_count + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_net2ent;
+ }
+ firstime = (int)0;
+ }
+ /* alias list */
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+ /* skip canonical name(official name) */
+ if (strcmp(attrptr->attrvalue[j], cname) == 0)
+ continue;
+ *mp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_net2ent;
+ }
+ (void) strcpy(*mp++, attrptr->attrvalue[j]);
+ continue;
+ }
+ }
+ if (strcasecmp(attrptr->attrname, _N_NETWORK) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+ if ((ntk->n_net = (in_addr_t)
+ inet_network(attrptr->attrvalue[0])) ==
+ (in_addr_t)-1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_net2ent;
+ }
+#ifdef DEBUG
+ strlcpy(addrstr, attrptr->attrvalue[0],
+ sizeof (addrstr));
+#endif /* DEBUG */
+ continue;
+ }
+ }
+ ntk->n_addrtype = AF_INET;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetent.c: _nss_ldap_networks2ent]\n");
+ (void) fprintf(stdout, " n_name: [%s]\n", ntk->n_name);
+ if (mp != NULL) {
+ for (mp = ntk->n_aliases; *mp != NULL; mp++)
+ (void) fprintf(stdout, " n_aliases: [%s]\n", *mp);
+ }
+ if (ntk->n_addrtype == AF_INET)
+ (void) fprintf(stdout, " n_addrtype: [AF_INET]\n");
+ else
+ (void) fprintf(stdout, " n_addrtype: [%d]\n",
+ ntk->n_addrtype);
+ (void) fprintf(stdout, " n_net: [%s]\n", addrstr);
+#endif /* DEBUG */
+
+result_net2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * Takes an unsigned integer in host order, and returns a printable
+ * string for it as a network number. To allow for the possibility of
+ * naming subnets, only trailing dot-zeros are truncated.
+ */
+
+static int nettoa(int anet, char *buf, int buflen)
+{
+ int addr;
+ char *p;
+ struct in_addr in;
+
+ if (buf == 0)
+ return ((int)1);
+
+ in = inet_makeaddr(anet, INADDR_ANY);
+ addr = in.s_addr;
+ if (strlcpy(buf, inet_ntoa(in), buflen) >= buflen)
+ return ((int)1);
+ if ((IN_CLASSA_HOST & htonl(addr)) == 0) {
+ p = strchr(buf, '.');
+ if (p == NULL)
+ return ((int)1);
+ *p = 0;
+ } else if ((IN_CLASSB_HOST & htonl(addr)) == 0) {
+ p = strchr(buf, '.');
+ if (p == NULL)
+ return ((int)1);
+ p = strchr(p + 1, '.');
+ if (p == NULL)
+ return ((int)1);
+ *p = 0;
+ } else if ((IN_CLASSC_HOST & htonl(addr)) == 0) {
+ p = strrchr(buf, '.');
+ if (p == NULL)
+ return ((int)1);
+ *p = 0;
+ }
+
+ return ((int)0);
+}
+
+
+/*
+ * getbyname gets a network entry by name. This function constructs an
+ * ldap search filter using the network name invocation parameter and the
+ * getnetbyname search filter defined. Once the filter is constructed, we
+ * search for a matching entry and marshal the data results into struct
+ * netent for the frontend process. The function _nss_ldap_networks2ent
+ * performs the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char netname[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(netname, argp->key.name, sizeof (netname)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETNETBYNAME, netname);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETNETBYNAME_SSD, netname);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _NETWORKS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbyaddr gets a network entry by ip address. This function constructs an
+ * ldap search filter using the name invocation parameter and the getnetbyaddr
+ * search filter defined. Once the filter is constructed, we search for a
+ * matching entry and marshal the data results into struct netent for the
+ * frontend process. The function _nss_ldap_networks2ent performs the data
+ * marshaling.
+ */
+
+static nss_status_t
+getbyaddr(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char addrstr[16];
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ if (nettoa((int)argp->key.netaddr.net, addrstr, 16) != 0)
+ return ((nss_status_t)NSS_UNAVAIL);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETNETBYADDR, addrstr);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETNETBYADDR_SSD, addrstr);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _NETWORKS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+static ldap_backend_op_t net_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbyaddr
+};
+
+
+/*
+ * _nss_ldap_networks_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract data
+ * types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_networks_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(net_ops,
+ sizeof (net_ops)/sizeof (net_ops[0]), _NETWORKS,
+ networks_attrs, _nss_ldap_networks2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetgrent.c b/usr/src/lib/nsswitch/ldap/common/getnetgrent.c
new file mode 100644
index 0000000000..bff4155e64
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getnetgrent.c
@@ -0,0 +1,1168 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <syslog.h>
+#include "ldap_common.h"
+
+/* netgroup attributes filters */
+#define _N_NAME "cn"
+#define _N_TRIPLE "nisnetgrouptriple"
+#define _N_MEMBER "membernisnetgroup"
+
+#define PRINT_VAL(a) (((a).argc == 0) || ((a).argv == NULL) || \
+ ((a).argv[0] == NULL)) ? "*" : (a).argv[0]
+#define ISWILD(a) ((a) == NULL)
+#define GET_ARGV(a) (((a).argc == 0) || ((a).argv == NULL) || \
+ ((a).argv[0] == NULL)) ? NULL : (a).argv[0]
+#define ISNULL(a) (a == NULL ? "<NULL>" : a)
+#define MAX_NETGR_NAME_LEN 256
+#define MAX_DOMAIN_LEN 1024
+#define MAX_TRIPLE_LEN (MAXHOSTNAMELEN + LOGNAME_MAX + \
+ MAX_DOMAIN_LEN + 5)
+
+#define _F_GETNETGR_TRIPLE \
+ "(&(objectClass=nisNetGroup)" \
+ "(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \
+ "(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))"
+#define _F_GETNETGR_TRIPLE_SSD \
+ "(&(%%s)(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \
+ "(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))"
+#define _F_GETNETGR_TRIPLE_MACHINE \
+ "(&(objectClass=nisNetGroup)" \
+ "(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))"
+#define _F_GETNETGR_TRIPLE_MACHINE_SSD \
+ "(&(%%s)(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))"
+#define _F_GETNETGRENT \
+ "(&(objectClass=nisNetGroup)(nisnetgrouptriple=(%s,%s,%s)))"
+#define _F_GETNETGRENT_SSD \
+ "(&(%%s)(nisnetgrouptriple=(%s,%s,%s)))"
+
+/*
+ * Although the filter should include the test for (*,,*), this leads to
+ * an unindexed search. To support this, a plugin should be the directory
+ * server.
+ */
+#define _F_GETNETGR_TRIPLE_USER \
+ "(&(objectClass=nisNetGroup)(nisnetgrouptriple=(*,%s,*)))"
+#define _F_GETNETGR_TRIPLE_USER_SSD \
+ "(&(%%s)(nisnetgrouptriple=(*,%s,*)))"
+
+#define _F_GETMEMBERGRENT \
+ "(&(objectClass=nisNetGroup)(membernisnetgroup=%s))"
+#define _F_GETMEMBERGRENT_SSD \
+ "(&(%%s)(membernisnetgroup=%s))"
+
+#define _F_ISMEMBERGRENT \
+ "(&(objectClass=nisNetGroup)(cn=%s)(membernisnetgroup=%s))"
+#define _F_ISMEMBERGRENT_SSD \
+ "(&(%%s)(cn=%s)(membernisnetgroup=%s))"
+
+#define MAX_INNETGR_FILTER_LEN (2 * MAXHOSTNAMELEN + 2 * LOGNAME_MAX + 140)
+#define MAX_GETMEM_FILTER_LEN (MAX_NETGR_NAME_LEN + 50)
+#define MAX_ISMEM_FILTER_LEN (2 * MAX_NETGR_NAME_LEN + 56)
+
+#define _F_GETMEMBER \
+ "(&(objectClass=nisNetGroup)(membernisnetgroup=%s))"
+#define _F_GETMEMBER_SSD "(&(%%s)(membernisnetgroup=%s))"
+#define _F_SETMEMBER "(&(objectClass=nisNetGroup)(cn=%s))"
+#define _F_SETMEMBER_SSD "(&(%%s)(cn=%s))"
+
+#define N_HASH 257
+
+static const char *netgrent_attrs[] = {
+ _N_TRIPLE,
+ _N_MEMBER,
+ (char *)NULL
+};
+
+static const char *netgr_name_attrs[] = {
+ _N_NAME,
+ (char *)NULL
+};
+
+static const char *netgr_leaf_attrs[] = {
+ _N_NAME,
+ _N_TRIPLE,
+ (char *)NULL
+};
+
+static const char *netgr_node_attrs[] = {
+ _N_NAME,
+ _N_MEMBER,
+ (char *)NULL
+};
+
+typedef struct netgroup_name {
+ char *name;
+ struct netgroup_name *next;
+ struct netgroup_name *next_hash;
+} netgroup_name_t;
+
+typedef struct {
+ netgroup_name_t *hash_list[N_HASH];
+ netgroup_name_t *to_do;
+ netgroup_name_t *done;
+} netgroup_table_t;
+
+typedef struct {
+ ns_ldap_result_t *results;
+ ns_ldap_entry_t *entry;
+ char **attrs;
+ void *cookie;
+ char *netgroup;
+ netgroup_table_t tab;
+} getnetgrent_cookie_t;
+
+typedef struct {
+ struct nss_innetgr_args *ia;
+ const char *ssd_filter;
+ const char *netgrname;
+ const char *membername;
+ netgroup_table_t tab;
+} innetgr_cookie_t;
+
+typedef unsigned int hash_t;
+
+static hash_t
+get_hash(const char *s)
+{
+ unsigned int sum = 0;
+ unsigned int i;
+
+ for (i = 0; s[i] != '\0'; i++)
+ sum += ((unsigned char *)s)[i];
+
+ return ((sum + i) % N_HASH);
+}
+
+static netgroup_name_t *
+in_netgroup_table(const char *name, netgroup_table_t *tab)
+{
+ hash_t h;
+ netgroup_name_t *ret;
+
+ if (tab == NULL || name == NULL || *name == '\0')
+ return (NULL);
+
+ h = get_hash(name);
+ ret = tab->hash_list[h];
+
+ while (ret != NULL) {
+ if (strcmp(name, ret->name) == 0)
+ break;
+ ret = ret->next_hash;
+ }
+
+ return (ret);
+}
+
+/*
+ * Adds a name to the netgroup table
+ *
+ * Returns
+ * 0 if successfully added or already present
+ * -1 if memory allocation error
+ */
+
+static int
+add_netgroup_name(const char *name, netgroup_table_t *tab)
+{
+ hash_t h;
+ netgroup_name_t *ng;
+ netgroup_name_t *ng_new;
+
+ if (tab == NULL || name == NULL || *name == '\0')
+ return (NULL);
+
+ h = get_hash(name);
+ ng = tab->hash_list[h];
+
+ while (ng != NULL) {
+ if (strcmp(name, ng->name) == 0)
+ break;
+ ng = ng->next_hash;
+ }
+
+ if (ng == NULL) {
+ ng_new = (netgroup_name_t *)
+ calloc(1, sizeof (netgroup_name_t));
+ if (ng_new == NULL)
+ return (-1);
+ ng_new->name = strdup(name);
+ if (ng_new->name == NULL) {
+ free(ng_new);
+ return (-1);
+ }
+ ng_new->next_hash = tab->hash_list[h];
+ tab->hash_list[h] = ng_new;
+ ng_new->next = tab->to_do;
+ tab->to_do = ng_new;
+ }
+ return (0);
+}
+
+static netgroup_name_t *
+get_next_netgroup(netgroup_table_t *tab)
+{
+ netgroup_name_t *ng;
+
+ if (tab == NULL)
+ return (NULL);
+
+ ng = tab->to_do;
+ if (ng != NULL) {
+ tab->to_do = ng->next;
+ ng->next = tab->done;
+ tab->done = ng;
+ }
+ return (ng);
+}
+
+static void
+free_netgroup_table(netgroup_table_t *tab)
+{
+ netgroup_name_t *ng, *next;
+
+ if (tab == NULL)
+ return;
+
+ for (ng = tab->to_do; ng != NULL; ng = next) {
+ if (ng->name != NULL)
+ free(ng->name);
+ next = ng->next;
+ free(ng);
+ }
+
+ for (ng = tab->done; ng != NULL; ng = next) {
+ if (ng->name != NULL)
+ free(ng->name);
+ next = ng->next;
+ free(ng);
+ }
+ (void) memset(tab, 0, sizeof (*tab));
+}
+
+/*
+ * domain comparing routine
+ * n1: See if n1 is n2 or an ancestor of it
+ * n2: (in string terms, n1 is a suffix of n2)
+ * Returns ZERO for success, -1 for failure.
+ */
+static int
+domcmp(const char *n1, const char *n2)
+{
+#define PASS 0
+#define FAIL -1
+
+ size_t l1, l2;
+
+ if ((n1 == NULL) || (n2 == NULL))
+ return (FAIL);
+
+ l1 = strlen(n1);
+ l2 = strlen(n2);
+
+ /* Turn a blind eye to the presence or absence of trailing periods */
+ if (l1 != 0 && n1[l1 - 1] == '.') {
+ --l1;
+ }
+ if (l2 != 0 && n2[l2 - 1] == '.') {
+ --l2;
+ }
+ if (l1 > l2) { /* Can't be a suffix */
+ return (FAIL);
+ } else if (l1 == 0) { /* Trivially a suffix; */
+ /* (do we want this case?) */
+ return (PASS);
+ }
+ /* So 0 < l1 <= l2 */
+ if (l1 < l2 && n2[l2 - l1 - 1] != '.') {
+ return (FAIL);
+ }
+ if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) {
+ return (PASS);
+ } else {
+ return (FAIL);
+ }
+}
+
+static int
+split_triple(char *triple, char **hostname, char **username, char **domain)
+{
+ int i, syntax_err;
+ char *splittriple[3];
+ char *p = triple;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n");
+#endif /* DEBUG */
+
+ if (triple == NULL)
+ return (-1);
+
+ p++;
+ syntax_err = 0;
+ for (i = 0; i < 3; i++) {
+ char *start;
+ char *limit;
+ const char *terminators = ",) \t";
+
+ if (i == 2) {
+ /* Don't allow comma */
+ terminators++;
+ }
+ while (isspace(*p)) {
+ p++;
+ }
+ start = p;
+ limit = strpbrk(start, terminators);
+ if (limit == 0) {
+ syntax_err++;
+ break;
+ }
+ p = limit;
+ while (isspace(*p)) {
+ p++;
+ }
+ if (*p == terminators[0]) {
+ /*
+ * Successfully parsed this name and
+ * the separator after it (comma or
+ * right paren); leave p ready for
+ * next parse.
+ */
+ p++;
+ if (start == limit) {
+ /* Wildcard */
+ splittriple[i] = NULL;
+ } else {
+ *limit = '\0';
+ splittriple[i] = start;
+ }
+ } else {
+ syntax_err++;
+ break;
+ }
+ }
+
+ if (syntax_err != 0)
+ return (-1);
+
+ *hostname = splittriple[0];
+ *username = splittriple[1];
+ *domain = splittriple[2];
+
+ return (0);
+}
+
+/*
+ * check the domain part of the triples.
+ * -1 = fails to match, 0 = match
+ */
+
+static int
+match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry)
+{
+ int ndomains;
+ char **pdomains;
+ int nhost;
+ char **phost;
+ int nusers;
+ char **pusers;
+ char **attr;
+ char triple[MAX_TRIPLE_LEN];
+ char *tuser, *thost, *tdomain;
+ int i;
+
+ nhost = ia->arg[NSS_NETGR_MACHINE].argc;
+ phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv;
+ if (phost == NULL || *phost == NULL)
+ nhost = 0;
+ nusers = ia->arg[NSS_NETGR_USER].argc;
+ pusers = (char **)ia->arg[NSS_NETGR_USER].argv;
+ if (pusers == NULL || *pusers == NULL)
+ nusers = 0;
+ ndomains = ia->arg[NSS_NETGR_DOMAIN].argc;
+ pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv;
+ if (pdomains == NULL || *pdomains == NULL)
+ ndomains = 0;
+
+ attr = __ns_ldap_getAttr(entry, _N_TRIPLE);
+ if (attr == NULL || *attr == NULL)
+ return (0);
+
+ for (; *attr; attr++) {
+ if (strlcpy(triple, *attr, sizeof (triple)) >= sizeof (triple))
+ continue;
+ if (split_triple(triple, &thost, &tuser, &tdomain) != 0)
+ continue;
+ if (thost != NULL && *thost != '\0' && nhost != 0) {
+ for (i = 0; i < nhost; i++)
+ if (strcasecmp(thost, phost[i]) == 0)
+ break;
+ if (i == nhost)
+ continue;
+ }
+ if (tuser != NULL && *tuser != '\0' && nusers != 0) {
+ for (i = 0; i < nusers; i++)
+ if (strcmp(tuser, pusers[i]) == 0)
+ break;
+ if (i == nusers)
+ continue;
+ }
+ if (tdomain != NULL && *tdomain != '\0' && ndomains != 0) {
+ for (i = 0; i < ndomains; i++)
+ if (domcmp(tdomain, pdomains[i]) == 0)
+ break;
+ if (i == ndomains)
+ continue;
+ }
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result)
+{
+ ns_ldap_entry_t *entry;
+
+ for (entry = result->entry; entry != NULL; entry = entry->next)
+ if (match_triple_entry(ia, entry) == 1)
+ return (1);
+
+ return (0);
+}
+
+static int
+add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab)
+{
+ char **attrs;
+ char **a;
+
+ attrs = __ns_ldap_getAttr(entry, _N_MEMBER);
+ if (attrs == NULL || *attrs == NULL)
+ return (0);
+
+ for (a = attrs; *a != NULL; a++) {}
+
+ do {
+ a--;
+ if (add_netgroup_name(*a, tab) != 0)
+ return (-1);
+ } while (a > attrs);
+ return (0);
+}
+
+static int
+add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab)
+{
+ ns_ldap_entry_t *entry;
+ int ret = 0;
+
+ for (entry = result->entry; entry != NULL; entry = entry->next) {
+ ret = add_netgroup_member_entry(entry, tab);
+ if (ret != 0)
+ break;
+ }
+ return (ret);
+}
+
+/*
+ * top_down_search checks only checks the netgroup specified in netgrname
+ */
+static nss_status_t
+top_down_search(struct nss_innetgr_args *ia, char *netgrname)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ ns_ldap_result_t *result = NULL;
+ ns_ldap_error_t *error = NULL;
+ int rc;
+ void *cookie = NULL;
+ nss_status_t status = NSS_NOTFOUND;
+ netgroup_table_t tab;
+ netgroup_name_t *ng;
+ int ret;
+
+ (void) memset(&tab, 0, sizeof (tab));
+
+ if (add_netgroup_name(netgrname, &tab) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ while ((ng = get_next_netgroup(&tab)) != NULL) {
+ if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
+ break;
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_SETMEMBER,
+ name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ break;
+
+ ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ break;
+
+ rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter,
+ _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie, &result,
+ &error, userdata);
+
+ (void) __ns_ldap_freeError(&error);
+ while (rc == NS_LDAP_SUCCESS && result != NULL) {
+ if (match_triple(ia, result) == 1) {
+ /* We found a match */
+ ia->status = NSS_NETGR_FOUND;
+ status = NSS_SUCCESS;
+ break;
+ }
+
+ rc = add_netgroup_member(result, &tab);
+ (void) __ns_ldap_freeResult(&result);
+
+ if (rc != NS_LDAP_SUCCESS)
+ break;
+ rc = __ns_ldap_nextEntry(cookie, &result, &error);
+ (void) __ns_ldap_freeError(&error);
+ }
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_endEntry(&cookie, &error);
+ (void) __ns_ldap_freeError(&error);
+
+ if (status == NSS_SUCCESS ||
+ (rc != NS_LDAP_SUCCESS && rc != NS_LDAP_NOTFOUND))
+ break;
+ }
+
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_endEntry(&cookie, &error);
+ (void) __ns_ldap_freeError(&error);
+ free_netgroup_table(&tab);
+ return (status);
+}
+
+static int
+innetgr_SSD_filter(const ns_ldap_search_desc_t *desc, char **realfilter,
+ const void *userdata)
+{
+ const innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata;
+
+ return (_merge_SSD_filter(desc, realfilter, cookie->ssd_filter));
+}
+
+static int process_innetgr_node(const ns_ldap_entry_t *entry,
+ const void *userdata);
+
+/* return 1 when done, 0 otherwise */
+static int
+check_parent(const char *gr_name, innetgr_cookie_t *cookie)
+{
+ ns_ldap_result_t *result = NULL;
+ ns_ldap_error_t *error = NULL;
+ char searchfilter[MAX_GETMEM_FILTER_LEN];
+ char name[MAX_GETMEM_FILTER_LEN];
+ char ssd_filter[MAX_GETMEM_FILTER_LEN];
+ const char *ssd_filter_sav = cookie->ssd_filter;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: check_parent:%s]\n", gr_name);
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, gr_name, sizeof (name)) != 0)
+ return (0);
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETMEMBERGRENT, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return (0);
+
+ ret = snprintf(ssd_filter, sizeof (ssd_filter),
+ _F_GETMEMBERGRENT_SSD, name);
+ if (ret >= sizeof (ssd_filter) || ret < 0)
+ return (0);
+
+ cookie->ssd_filter = ssd_filter;
+ cookie->membername = gr_name;
+
+ (void) __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
+ netgr_node_attrs, NULL, 0, &result, &error,
+ process_innetgr_node, cookie);
+
+ cookie->ssd_filter = ssd_filter_sav;
+
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_freeError(&error);
+
+ return (cookie->ia->status == NSS_NETGR_NO ? 0 : 1);
+}
+
+/* Use the server's matching rule if not a case exact match */
+
+static int
+server_match(innetgr_cookie_t *cookie)
+{
+ ns_ldap_result_t *result = NULL;
+ ns_ldap_error_t *error = NULL;
+ char searchfilter[MAX_ISMEM_FILTER_LEN];
+ char netgrname[MAX_ISMEM_FILTER_LEN];
+ char membername[MAX_ISMEM_FILTER_LEN];
+ char ssd_filter[MAX_ISMEM_FILTER_LEN];
+ const char *ssd_filter_sav = cookie->ssd_filter;
+ int rc;
+ int ret;
+
+ if (_ldap_filter_name(netgrname, cookie->netgrname,
+ sizeof (netgrname)) != 0)
+ return (0);
+ if (_ldap_filter_name(membername, cookie->membername,
+ sizeof (membername)) != 0)
+ return (0);
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_ISMEMBERGRENT,
+ netgrname, membername);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return (0);
+
+ ret = snprintf(ssd_filter, sizeof (ssd_filter), _F_ISMEMBERGRENT_SSD,
+ netgrname, membername);
+ if (ret >= sizeof (ssd_filter) || ret < 0)
+ return (0);
+
+ cookie->ssd_filter = ssd_filter;
+
+ rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
+ netgr_name_attrs, NULL, 0, &result, &error,
+ NULL, &cookie);
+
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_freeError(&error);
+
+ cookie->ssd_filter = ssd_filter_sav;
+ return (rc == NS_LDAP_SUCCESS);
+}
+
+static int
+process_innetgr_node(const ns_ldap_entry_t *entry, const void *userdata)
+{
+ innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata;
+ char **a, **attr;
+
+ attr = __ns_ldap_getAttr(entry, _N_NAME);
+ if (attr == NULL)
+ return (NS_LDAP_CB_NEXT);
+
+ for (a = attr; *a; a++) {
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: process_innetgr_node:%s]\n",
+ *a);
+#endif /* DEBUG */
+
+ if (strcasecmp(*a, cookie->netgrname) == 0) {
+ if (strcmp(*a, cookie->netgrname) == 0 ||
+ server_match(cookie)) {
+ cookie->ia->status = NSS_NETGR_FOUND;
+ return (NS_LDAP_CB_DONE);
+ }
+ }
+ }
+ for (a = attr; *a; a++) {
+ /* check if we have already visited this node */
+ if (in_netgroup_table(*a, &cookie->tab) != NULL)
+ continue;
+ if (add_netgroup_name(*a, &cookie->tab) != 0) {
+ cookie->ia->status = NSS_NETGR_NOMEM;
+ return (NS_LDAP_CB_DONE);
+ }
+ if (check_parent(*a, cookie) == 1)
+ return (NS_LDAP_CB_DONE);
+ }
+ return (NS_LDAP_CB_NEXT);
+}
+
+static int
+process_innetgr_leaf(const ns_ldap_entry_t *entry, const void *userdata)
+{
+ innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata;
+
+ /* Check to see if this entry matches the triple */
+ if (match_triple_entry(cookie->ia, entry) != 1)
+ return (NS_LDAP_CB_NEXT);
+
+ return (process_innetgr_node(entry, userdata));
+}
+
+/*
+ * __netgr_in checks only checks the netgroup specified in ngroup
+ */
+static nss_status_t
+__netgr_in(void *a, char *netgrname)
+{
+ struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a;
+ char searchfilter[MAX_INNETGR_FILTER_LEN];
+ char ssd_filter[MAX_INNETGR_FILTER_LEN];
+ char mach[MAX_INNETGR_FILTER_LEN];
+ char user[MAX_INNETGR_FILTER_LEN];
+ ns_ldap_result_t *result = NULL;
+ ns_ldap_error_t *error = NULL;
+ int rc;
+ nss_status_t status = NSS_NOTFOUND;
+ innetgr_cookie_t cookie = {NULL, NULL, NULL};
+ int user_wild, mach_wild;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n");
+ (void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: "
+ "argc[%d]='%s',\n\tdomain:argc[%d]='%s' "
+ "netgroup: argc[%d]='%s'\n",
+ NSS_NETGR_MACHINE,
+ PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]),
+ NSS_NETGR_USER,
+ PRINT_VAL(ia->arg[NSS_NETGR_USER]),
+ NSS_NETGR_DOMAIN,
+ PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]),
+ NSS_NETGR_N,
+ PRINT_VAL(ia->arg[NSS_NETGR_N]));
+ (void) fprintf(stdout, "\tgroups='%s'\n", netgrname);
+#endif /* DEBUG */
+
+ ia->status = NSS_NETGR_NO;
+
+ if (netgrname == NULL)
+ return (status);
+
+ mach_wild = (ia->arg[NSS_NETGR_MACHINE].argc == 0) ||
+ (ia->arg[NSS_NETGR_MACHINE].argv == NULL) ||
+ (ia->arg[NSS_NETGR_MACHINE].argv[0] == NULL);
+
+ user_wild = (ia->arg[NSS_NETGR_USER].argc == 0) ||
+ (ia->arg[NSS_NETGR_USER].argv == NULL) ||
+ (ia->arg[NSS_NETGR_USER].argv[0] == NULL);
+
+ if (!mach_wild && _ldap_filter_name(mach,
+ ia->arg[NSS_NETGR_MACHINE].argv[0], sizeof (mach)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (!user_wild && _ldap_filter_name(user,
+ ia->arg[NSS_NETGR_USER].argv[0], sizeof (user)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (!mach_wild && !user_wild) {
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETNETGR_TRIPLE, mach, user, mach, user);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(ssd_filter, sizeof (ssd_filter),
+ _F_GETNETGR_TRIPLE_SSD, mach, user, mach, user);
+ if (ret >= sizeof (ssd_filter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else if (!mach_wild && user_wild) {
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETNETGR_TRIPLE_MACHINE, mach);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(ssd_filter, sizeof (ssd_filter),
+ _F_GETNETGR_TRIPLE_MACHINE_SSD, mach);
+ if (ret >= sizeof (ssd_filter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else if (mach_wild && !user_wild) {
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETNETGR_TRIPLE_USER, user);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(ssd_filter, sizeof (ssd_filter),
+ _F_GETNETGR_TRIPLE_USER_SSD, user);
+ if (ret >= sizeof (ssd_filter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else {
+ return (top_down_search(ia, netgrname));
+ }
+
+ cookie.ia = ia;
+ cookie.ssd_filter = ssd_filter;
+ cookie.netgrname = netgrname;
+ (void) memset(&cookie.tab, 0, sizeof (cookie.tab));
+
+ rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter,
+ netgr_leaf_attrs, NULL, 0, &result, &error,
+ process_innetgr_leaf, &cookie);
+ status = switch_err(rc, error);
+
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_freeError(&error);
+ free_netgroup_table(&cookie.tab);
+
+ return (status);
+}
+
+/*ARGSUSED0*/
+static nss_status_t
+netgr_in(ldap_backend_ptr be, void *a)
+{
+ struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a;
+ int i;
+ nss_status_t rc = (nss_status_t)NSS_NOTFOUND;
+
+ ia->status = NSS_NETGR_NO;
+ for (i = 0; i < ia->groups.argc; i++) {
+ rc = __netgr_in(a, ia->groups.argv[i]);
+ if (ia->status == NSS_NETGR_FOUND)
+ return (NSS_SUCCESS);
+ }
+ return (rc);
+}
+
+/*
+ *
+ */
+
+static nss_status_t
+getnetgr_ldap_setent(ldap_backend_ptr be, void *a)
+{
+ const char *netgroup = (const char *) a;
+ getnetgrent_cookie_t *cookie;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n");
+#endif /* DEBUG */
+
+ cookie = (getnetgrent_cookie_t *)be->netgroup_cookie;
+ if (cookie != NULL && cookie->netgroup != NULL) {
+ /* is this another set on the same netgroup */
+ if (strcmp(cookie->netgroup, netgroup) == 0)
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+
+ return (NSS_NOTFOUND);
+}
+
+static void
+free_getnetgrent_cookie(getnetgrent_cookie_t **cookie)
+{
+ ns_ldap_error_t *error = NULL;
+ getnetgrent_cookie_t *p = *cookie;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n");
+#endif /* DEBUG */
+
+ if (p == NULL)
+ return;
+
+ (void) __ns_ldap_freeResult(&p->results);
+ (void) __ns_ldap_endEntry(&p->cookie, &error);
+ (void) __ns_ldap_freeError(&error);
+ free_netgroup_table(&p->tab);
+ free(p->netgroup);
+ free(p);
+ *cookie = NULL;
+}
+
+/*ARGSUSED1*/
+static nss_status_t
+getnetgr_ldap_endent(ldap_backend_ptr be, void *a)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n");
+#endif /* DEBUG */
+
+ free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
+
+ return ((nss_status_t)NSS_NOTFOUND);
+}
+
+
+/*ARGSUSED1*/
+static nss_status_t
+getnetgr_ldap_destr(ldap_backend_ptr be, void *a)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n");
+#endif /* DEBUG */
+
+ free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
+ free(be);
+
+ return ((nss_status_t)NSS_NOTFOUND);
+}
+
+
+static nss_status_t
+getnetgr_ldap_getent(ldap_backend_ptr be, void *a)
+{
+ struct nss_getnetgrent_args *args;
+ getnetgrent_cookie_t *p;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int rc;
+ void *cookie = NULL;
+ ns_ldap_result_t *result = NULL;
+ ns_ldap_error_t *error = NULL;
+ char **attrs;
+ char *hostname, *username, *domain;
+ char *buffer;
+ nss_status_t status = NSS_SUCCESS;
+ netgroup_name_t *ng;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n");
+#endif /* DEBUG */
+
+ args = (struct nss_getnetgrent_args *)a;
+
+ args->status = NSS_NETGR_NO;
+
+ p = (getnetgrent_cookie_t *)be->netgroup_cookie;
+ if (p == NULL)
+ return ((nss_status_t)NSS_SUCCESS);
+
+ for (;;) {
+ while (p->cookie == NULL) {
+ ng = get_next_netgroup(&p->tab);
+ if (ng == NULL) /* no more */
+ break;
+
+ if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0)
+ break;
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_SETMEMBER, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ break;
+
+ ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD,
+ name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ break;
+
+ result = NULL;
+ rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter,
+ _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie,
+ &result, &error, userdata);
+ (void) __ns_ldap_freeError(&error);
+
+ if (rc == NS_LDAP_SUCCESS && result != NULL) {
+ p->cookie = cookie;
+ p->results = result;
+ break;
+ }
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_endEntry(&cookie, &error);
+ (void) __ns_ldap_freeError(&error);
+ }
+ if (p->cookie == NULL)
+ break;
+ if (p->results == NULL) {
+ result = NULL;
+ rc = __ns_ldap_nextEntry(p->cookie, &result, &error);
+ (void) __ns_ldap_freeError(&error);
+ if (rc == NS_LDAP_SUCCESS && result != NULL)
+ p->results = result;
+ else {
+ (void) __ns_ldap_freeResult(&result);
+ (void) __ns_ldap_endEntry(&p->cookie, &error);
+ (void) __ns_ldap_freeError(&error);
+ p->cookie = NULL;
+ }
+ }
+ if (p->results == NULL)
+ continue;
+
+ if (p->entry == NULL)
+ p->entry = p->results->entry;
+
+ if (p->entry == NULL)
+ continue;
+
+ if (p->attrs == NULL) {
+ attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE);
+ if (attrs != NULL && *attrs != NULL)
+ p->attrs = attrs;
+ }
+
+ if (p->attrs != NULL) {
+ attrs = p->attrs;
+ buffer = args->buffer;
+
+ if (strlcpy(buffer, *attrs, args->buflen) >= args->buflen) {
+ status = NSS_STR_PARSE_ERANGE;
+ break;
+ }
+
+ rc = split_triple(buffer, &hostname, &username, &domain);
+ attrs++;
+ if (attrs != NULL && *attrs != NULL)
+ p->attrs = attrs;
+ else
+ p->attrs = NULL;
+ if (rc == 0) {
+ args->retp[NSS_NETGR_MACHINE] = hostname;
+ args->retp[NSS_NETGR_USER] = username;
+ args->retp[NSS_NETGR_DOMAIN] = domain;
+ args->status = NSS_NETGR_FOUND;
+ if (p->attrs != NULL)
+ break;
+ }
+ }
+
+ if (p->attrs == NULL) {
+ rc = add_netgroup_member_entry(p->entry, &p->tab);
+ if (rc != 0) {
+ args->status = NSS_NETGR_NO;
+ break;
+ }
+
+ p->entry = p->entry->next;
+ if (p->entry == NULL)
+ (void) __ns_ldap_freeResult(&p->results);
+ if (args->status == NSS_NETGR_FOUND)
+ break;
+ }
+ }
+
+ return (status);
+}
+
+static ldap_backend_op_t getnetgroup_ops[] = {
+ getnetgr_ldap_destr,
+ getnetgr_ldap_endent,
+ getnetgr_ldap_setent,
+ getnetgr_ldap_getent,
+};
+
+/*
+ *
+ */
+
+static nss_status_t
+netgr_set(ldap_backend_ptr be, void *a)
+{
+ struct nss_setnetgrent_args *args =
+ (struct nss_setnetgrent_args *)a;
+ ldap_backend_ptr get_be;
+ getnetgrent_cookie_t *p;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n");
+ (void) fprintf(stdout,
+ "\targs->netgroup: %s\n", ISNULL(args->netgroup));
+#endif /* DEBUG */
+
+ if (args->netgroup == NULL)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie);
+ p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t));
+ if (p == NULL)
+ return ((nss_status_t)NSS_NOTFOUND);
+ p->netgroup = strdup(args->netgroup);
+ if (p->netgroup == NULL) {
+ free(p);
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ if (add_netgroup_name(args->netgroup, &p->tab) == -1) {
+ free_getnetgrent_cookie(&p);
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ /* now allocate and return iteration backend structure */
+ if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL)
+ return (NSS_UNAVAIL);
+ get_be->ops = getnetgroup_ops;
+ get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]);
+ get_be->tablename = NULL;
+ get_be->attrs = netgrent_attrs;
+ get_be->result = NULL;
+ get_be->ldapobj2ent = NULL;
+ get_be->setcalled = 1;
+ get_be->filter = NULL;
+ get_be->toglue = NULL;
+ get_be->enumcookie = NULL;
+ get_be->netgroup_cookie = p;
+ args->iterator = (nss_backend_t *)get_be;
+
+ (void) __ns_ldap_freeResult(&be->result);
+
+ return (NSS_SUCCESS);
+}
+
+
+/*ARGSUSED1*/
+static nss_status_t
+netgr_ldap_destr(ldap_backend_ptr be, void *a)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n");
+#endif /* DEBUG */
+
+ (void) _clean_ldap_backend(be);
+
+ return ((nss_status_t)NSS_NOTFOUND);
+}
+
+
+
+
+static ldap_backend_op_t netgroup_ops[] = {
+ netgr_ldap_destr,
+ 0,
+ 0,
+ 0,
+ netgr_in, /* innetgr() */
+ netgr_set /* setnetgrent() */
+};
+
+
+/*
+ * _nss_ldap_netgroup_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract data
+ * types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n");
+#endif /* DEBUG */
+
+ return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops,
+ sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP,
+ netgrent_attrs, NULL));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getnetmasks.c b/usr/src/lib/nsswitch/ldap/common/getnetmasks.c
new file mode 100644
index 0000000000..69ef802520
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getnetmasks.c
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include "ldap_common.h"
+
+/* netmasks attributes filters */
+#define _N_NETWORK "ipnetworknumber"
+#define _N_NETMASK "ipnetmasknumber"
+
+#define _F_GETMASKBYNET "(&(objectClass=ipNetwork)(ipNetworkNumber=%s))"
+#define _F_GETMASKBYNET_SSD "(&(%%s)(ipNetworkNumber=%s))"
+
+static const char *netmasks_attrs[] = {
+ _N_NETWORK,
+ _N_NETMASK,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_netmasks2ent is the data marshaling method for the netmasks
+ * getXbyY * (e.g., getbynet()) backend processes. This method is called
+ * after a successful ldap search has been performed. This method will
+ * parse the ldap search values into struct in_addr *mask = argp->buf.result
+ * only if argp->buf.result is initialized (not NULL). Three error
+ * conditions are expected and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_netmasks2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ unsigned long len = 0L;
+#ifdef DEBUG
+ char maskstr[16];
+#endif /* DEBUG */
+ struct in_addr addr;
+ struct in_addr *mask = (struct in_addr *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ mask = (struct in_addr *)argp->buf.result;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_nmks2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_nmks2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _N_NETMASK) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (mask == NULL)
+ continue;
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_nmks2ent;
+ }
+ /* addr a IPv4 address and 32 bits */
+ addr.s_addr = inet_addr(attrptr->attrvalue[j]);
+ if (addr.s_addr == 0xffffffffUL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_nmks2ent;
+ }
+ mask->s_addr = addr.s_addr;
+#ifdef DEBUG
+ strlcpy(maskstr, attrptr->attrvalue[j],
+ sizeof (maskstr));
+#endif /* DEBUG */
+ continue;
+ }
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[netmasks.c: _nss_ldap_netmasks2ent]\n");
+ (void) fprintf(stdout, " netmask: [%s]\n", maskstr);
+#endif /* DEBUG */
+
+result_nmks2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbynet gets a network mask by address. This function constructs an
+ * ldap search filter using the netmask name invocation parameter and the
+ * getmaskbynet search filter defined. Once the filter is constructed, we
+ * search for a matching entry and marshal the data results into struct
+ * in_addr for the frontend process. The function _nss_ldap_netmasks2ent
+ * performs the data marshaling.
+ */
+
+static nss_status_t
+getbynet(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char netnumber[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(netnumber, argp->key.name, sizeof (netnumber))
+ != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETMASKBYNET, netnumber);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETMASKBYNET_SSD, netnumber);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _NETMASKS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t netmasks_ops[] = {
+ _nss_ldap_destr,
+ getbynet
+};
+
+
+/*
+ * _nss_ldap_netmasks_constr is where life begins. This function calls
+ * the generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_netmasks_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(netmasks_ops,
+ sizeof (netmasks_ops)/sizeof (netmasks_ops[0]), _NETMASKS,
+ netmasks_attrs, _nss_ldap_netmasks2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprinter.c b/usr/src/lib/nsswitch/ldap/common/getprinter.c
new file mode 100644
index 0000000000..f4004be41a
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getprinter.c
@@ -0,0 +1,308 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#pragma weak _nss_ldap__printers_constr = _nss_ldap_printers_constr
+
+#include "ldap_common.h"
+
+static void append_attr(char *buf, char *attr);
+
+/* printer attributes filters */
+#define _F_GETPRINTERBYNAME \
+ "(&(objectClass=sunPrinter)(|(printer-name=%s)(printer-aliases=%s)))"
+
+/*
+ * Attributes from the following classes:
+ * printerService
+ * printerAbstact
+ * sunPrinter
+ */
+
+/*
+ * Get all attributes.
+ */
+static const char **printer_attrs = NULL;
+
+
+/*
+ * _nss_ldap_printers2ent is the data marshaling method for the printers
+ * getXbyY backend processes. This method is called after a successful
+ * ldap search has been performed. This method will parse the ldap search
+ * values into argp->buf.buffer. Three error conditions are expected and
+ * returned to nsswitch.
+ */
+
+static int
+_nss_ldap_printers2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *cp = (char *)NULL;
+ char *buffer = (char *)NULL;
+ ns_ldap_attr_t *attr;
+ ns_ldap_result_t *result = be->result;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_printers2ent;
+ }
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ /* Make sure our buffer stays NULL terminated */
+ buflen--;
+
+ attr = getattr(result, 0);
+ if (attr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+
+ /*
+ * Pick out the printer name.
+ */
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attr = getattr(result, i);
+ if (attr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+ if (strcasecmp(attr->attrname, "printer-name") == 0) {
+ len = strlen(attr->attrvalue[0]);
+ if (len < 1 || (attr->attrvalue[0] == '\0')) {
+ *buffer = 0;
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+ if (len > buflen) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_printers2ent;
+ }
+ (void) strcpy(buffer, attr->attrvalue[0]);
+ }
+ }
+
+ /*
+ * Should never happen since it is mandatory but bail if
+ * we don't have a printer name.
+ */
+ if (buffer[0] == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+
+ /*
+ * Add the rest of the attributes
+ */
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attr = getattr(result, i);
+ if (attr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+ /*
+ * The attribute contains key=value
+ */
+ if (strcasecmp(attr->attrname, "sun-printer-kvp") == 0) {
+ for (j = 0; j < attr->value_count; j++) {
+ len = strlen(attr->attrvalue[j]);
+ if (len < 1 ||
+ (attr->attrvalue[j] == '\0')) {
+ *buffer = 0;
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+ len += strlen(buffer) + 1; /* 1 for ':' */
+ if (len > buflen) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_printers2ent;
+ }
+ if ((cp = strrchr(buffer, '\0')) != NULL) {
+ *cp = ':';
+ (void) strcat(buffer,
+ attr->attrvalue[j]);
+ }
+ }
+ } else {
+ /*
+ * Skip the printer name
+ */
+ if (strcmp(attr->attrname, "printer-name") == 0) {
+ continue;
+ }
+ /*
+ * Translate sun-printer-bsdaddr -> bsdaddr
+ */
+ if (strcmp(attr->attrname, "sun-printer-bsdaddr") ==
+ 0) {
+ if (attr->attrname != NULL) {
+ free(attr->attrname);
+ }
+ attr->attrname = strdup("bsdaddr");
+ }
+
+ /*
+ * The attribute name is the key. The attribute
+ * data is the value.
+ */
+ for (j = 0; j < attr->value_count; j++) {
+ int k;
+ char *kp;
+
+ len = strlen(attr->attrvalue[j]);
+ if (len < 1 ||
+ (attr->attrvalue[j] == '\0')) {
+ *buffer = 0;
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_printers2ent;
+ }
+ /*
+ * Add extra for any colons which need to
+ * be backslashed plus ending ':' or ','.
+ */
+ k = 0;
+ for (kp = attr->attrvalue[j]; *kp != NULL; kp++)
+ if (*kp == ':')
+ k++;
+ len += strlen(buffer) + k;
+
+ if (j == 0) {
+ len += strlen(attr->attrname) + 1;
+ }
+ if (len > buflen) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_printers2ent;
+ }
+ if ((cp = strrchr(buffer, '\0')) != NULL) {
+ if (j == 0) {
+ *cp = ':';
+ (void) strcat(buffer,
+ attr->attrname);
+ (void) strcat(buffer, "=");
+ } else {
+ *cp = ',';
+ }
+ (void) append_attr(buffer,
+ attr->attrvalue[j]);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getprinter.c: _nss_ldap_printers2ent]\n");
+ (void) fprintf(stdout, " printers: [%s]\n", buffer);
+#endif
+
+result_printers2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+/*
+ * Attributes which contain colons must be backslashed.
+ */
+static void
+append_attr(char *buf, char *attr)
+{
+ char *cp, *bp;
+
+ if (strchr(attr, ':') == NULL) {
+ (void) strcat(buf, attr);
+ return;
+ }
+ bp = buf + strlen(buf);
+ cp = attr;
+ while (*cp != NULL) {
+ if (*cp == ':') {
+ *bp++ = '\\';
+ }
+ *bp++ = *cp++;
+ }
+}
+
+/*
+ * getbyname gets printer attributes by printer name. This function
+ * constructs an ldap search filter using the printer name invocation
+ * parameter and the getprinterbyname search filter defined. Once the
+ * filter is constructed, we search for matching entries and marshal
+ * the data results into argp->buf.buffer for the frontend process.
+ * The function * _nss_ldap_printers2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char printername[BUFSIZ];
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+
+ (void) strncpy(printername, argp->key.name, BUFSIZ);
+ if (snprintf(searchfilter, SEARCHFILTERLEN,
+ _F_GETPRINTERBYNAME, printername, printername) < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _PRINTERS, searchfilter, NULL, NULL, NULL));
+}
+
+static ldap_backend_op_t printers_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+};
+
+
+/*
+ * _nss_ldap_printers_constr is where life begins. This function calls
+ * the generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_printers_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getprinterent.c: _nss_ldap_printers_constr]\n");
+#endif
+
+ return ((nss_backend_t *)_nss_ldap_constr(printers_ops,
+ sizeof (printers_ops)/sizeof (printers_ops[0]), _PRINTERS,
+ printer_attrs, _nss_ldap_printers2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprofattr.c b/usr/src/lib/nsswitch/ldap/common/getprofattr.c
new file mode 100644
index 0000000000..d4c4adf6d4
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getprofattr.c
@@ -0,0 +1,253 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <secdb.h>
+#include <prof_attr.h>
+#include "ldap_common.h"
+
+
+/* prof_attr attributes filters */
+#define _PROF_NAME "cn"
+#define _PROF_RES1 "SolarisAttrReserved1"
+#define _PROF_RES2 "SolarisAttrReserved2"
+#define _PROF_DESC "SolarisAttrLongDesc"
+#define _PROF_ATTRS "SolarisAttrKeyValue"
+#define _PROF_GETPROFNAME "(&(objectClass=SolarisProfAttr)(cn=%s))"
+#define _PROF_GETPROFNAME_SSD "(&(%%s)(cn=%s))"
+
+static const char *prof_attrs[] = {
+ _PROF_NAME,
+ _PROF_RES1,
+ _PROF_RES2,
+ _PROF_DESC,
+ _PROF_ATTRS,
+ (char *)NULL
+};
+
+
+static int
+_nss_ldap_prof2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *nullstring = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ profstr_t *prof = (profstr_t *)NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ prof = (profstr_t *)(argp->buf.result);
+ ceiling = buffer + buflen;
+ prof->name = (char *)NULL;
+ prof->res1 = (char *)NULL;
+ prof->res2 = (char *)NULL;
+ prof->desc = (char *)NULL;
+ prof->attr = (char *)NULL;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_prof2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_prof2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _PROF_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_prof2ent;
+ }
+ prof->name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ (void) strcpy(prof->name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROF_RES1) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ prof->res1 = nullstring;
+ } else {
+ prof->res1 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ (void) strcpy(prof->res1,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROF_RES2) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ prof->res2 = nullstring;
+ } else {
+ prof->res2 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ (void) strcpy(prof->res2,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROF_DESC) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ prof->desc = nullstring;
+ } else {
+ prof->desc = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ (void) strcpy(prof->desc,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROF_ATTRS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ prof->attr = nullstring;
+ } else {
+ prof->attr = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_prof2ent;
+ }
+ (void) strcpy(prof->attr,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getprofattr.c: _nss_ldap_prof2ent]\n");
+ (void) fprintf(stdout, " prof-name: [%s]\n", prof->name);
+ if (prof->res1 != (char *)NULL) {
+ (void) fprintf(stdout, " res1: [%s]\n", prof->res1);
+ }
+ if (prof->res2 != (char *)NULL) {
+ (void) fprintf(stdout, " res2: [%s]\n", prof->res2);
+ }
+ if (prof->desc != (char *)NULL) {
+ (void) fprintf(stdout, " desc: [%s]\n", prof->desc);
+ }
+ if (prof->attr != (char *)NULL) {
+ (void) fprintf(stdout, " attr: [%s]\n", prof->attr);
+ }
+#endif /* DEBUG */
+
+result_prof2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getprofattr.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _PROF_GETPROFNAME, name);
+ if (ret < 0 || ret >= sizeof (searchfilter))
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _PROF_GETPROFNAME_SSD, name);
+ if (ret < 0 || ret >= sizeof (userdata))
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return (_nss_ldap_lookup(be, argp,
+ _PROFATTR, searchfilter, NULL, _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t profattr_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_prof_attr_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getprofattr.c: _nss_ldap_prof_attr_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(profattr_ops,
+ sizeof (profattr_ops)/sizeof (profattr_ops[0]), _PROFATTR,
+ prof_attrs, _nss_ldap_prof2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprojent.c b/usr/src/lib/nsswitch/ldap/common/getprojent.c
new file mode 100644
index 0000000000..fd332209d8
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getprojent.c
@@ -0,0 +1,331 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <project.h>
+#include "ldap_common.h"
+
+/* Project attributes filters */
+#define _PROJ_NAME "SolarisProjectName"
+#define _PROJ_PROJID "SolarisProjectID"
+#define _PROJ_DESCR "description"
+#define _PROJ_USERS "memberUid"
+#define _PROJ_GROUPS "memberGid"
+#define _PROJ_ATTR "SolarisProjectAttr"
+
+#define _F_GETPROJNAME "(&(objectClass=SolarisProject)(SolarisProjectName=%s))"
+#define _F_GETPROJID "(&(objectClass=SolarisProject)(SolarisProjectID=%ld))"
+
+static const char *project_attrs[] = {
+ _PROJ_NAME,
+ _PROJ_PROJID,
+ _PROJ_DESCR,
+ _PROJ_USERS,
+ _PROJ_GROUPS,
+ _PROJ_ATTR,
+ (char *)NULL
+};
+
+static char *
+gettok(char **nextpp, char sep)
+{
+ char *p = *nextpp;
+ char *q = p;
+ char c;
+
+ if (p == NULL)
+ return (NULL);
+ while ((c = *q) != '\0' && c != sep)
+ q++;
+ if (c == '\0')
+ *nextpp = 0;
+ else {
+ *q++ = '\0';
+ *nextpp = q;
+ }
+ return (p);
+}
+
+/*
+ * _nss_ldap_proj2ent is the data marshalling method for the project getXbyY
+ * (getprojbyname, getprojbyid, getprojent) backend processes. This method
+ * is called after a successful ldap search has been performed. This method
+ * will parse the ldap search values into struct project = argp->buf.buffer
+ * which the frontend routine expects. Three error conditions are expected
+ * and returned to nsswitch.
+ */
+static int
+_nss_ldap_proj2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ unsigned long len = 0;
+ char **uglist;
+ char *buffer, *ceiling;
+ char *users, *groups, *p;
+ struct project *proj;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = argp->buf.buffer;
+ if (!argp->buf.result) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2ent;
+ }
+ nss_result = NSS_STR_PARSE_SUCCESS;
+ proj = argp->buf.result;
+ proj->pj_users = proj->pj_groups = NULL;
+ proj->pj_attr = proj->pj_comment = NULL;
+ ceiling = (char *)ROUND_DOWN(buffer + argp->buf.buflen,
+ sizeof (char *));
+ (void) memset(argp->buf.buffer, 0, argp->buf.buflen);
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2ent;
+ }
+ len = strlen(attrptr->attrvalue[0]);
+ if (strcasecmp(attrptr->attrname, _PROJ_NAME) == 0) {
+ if (len == 0) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2ent;
+ }
+ proj->pj_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ (void) strcpy(proj->pj_name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROJ_PROJID) == 0) {
+ if (len == 0) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2ent;
+ }
+ errno = 0;
+ proj->pj_projid =
+ (projid_t)strtol(attrptr->attrvalue[0],
+ NULL, 10);
+ if (errno != 0) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_proj2ent;
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROJ_DESCR) == 0) {
+ proj->pj_comment = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ (void) strcpy(proj->pj_comment, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROJ_ATTR) == 0) {
+ proj->pj_attr = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ (void) strcpy(proj->pj_attr, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROJ_USERS) == 0) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ users = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ (void) strcpy(users, attrptr->attrvalue[0]);
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_users = uglist = (char **)buffer;
+ *uglist = NULL;
+ while (uglist < (char **)ceiling) {
+ p = gettok(&users, ',');
+ if (p == NULL || *p == '\0') {
+ *uglist++ = 0;
+ break;
+ }
+ *uglist++ = p;
+ }
+ buffer = (char *)uglist;
+ if (buffer >= ceiling)
+ return (NSS_STR_PARSE_ERANGE);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PROJ_GROUPS) == 0) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ groups = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ (void) strcpy(groups, attrptr->attrvalue[0]);
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_groups = uglist = (char **)buffer;
+ *uglist = NULL;
+ while (uglist < (char **)ceiling) {
+ p = gettok(&groups, ',');
+ if (p == NULL || *p == '\0') {
+ *uglist++ = 0;
+ break;
+ }
+ *uglist++ = p;
+ }
+ buffer = (char *)uglist;
+ if (buffer >= ceiling)
+ return (NSS_STR_PARSE_ERANGE);
+ continue;
+ }
+ }
+ if (proj->pj_comment == NULL) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_comment = buffer;
+ *buffer = '\0';
+ buffer++;
+ }
+ if (proj->pj_users == NULL) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_users = (char **)buffer;
+ *buffer = '\0';
+ buffer++;
+ }
+ if (proj->pj_groups == NULL) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_groups = (char **)buffer;
+ *buffer = '\0';
+ buffer++;
+ }
+ if (proj->pj_attr == NULL) {
+ buffer = (char *)ROUND_UP(buffer, sizeof (char *));
+ if (buffer >= ceiling) {
+ nss_result = NSS_STR_PARSE_ERANGE;
+ goto result_proj2ent;
+ }
+ proj->pj_attr = buffer;
+ *buffer = '\0';
+ buffer++;
+ }
+
+result_proj2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets a project entry by name. This function constructs an ldap
+ * search filter using the name invocation parameter and the getprojname search
+ * filter defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into struct project for the frontend
+ * process. The function _nss_ldap_proj2ent performs the data marshaling.
+ */
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+
+ if (snprintf(searchfilter, SEARCHFILTERLEN,
+ _F_GETPROJNAME, argp->key.name) < 0)
+ return (NSS_NOTFOUND);
+ return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL,
+ NULL, NULL));
+}
+
+
+/*
+ * getbyprojid gets a project entry by number. This function constructs an ldap
+ * search filter using the name invocation parameter and the getprojid search
+ * filter defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into struct project for the frontend
+ * process. The function _nss_ldap_proj2ent performs the data marshaling.
+ */
+static nss_status_t
+getbyprojid(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+
+ if (snprintf(searchfilter, SEARCHFILTERLEN,
+ _F_GETPROJID, (long)argp->key.projid) < 0)
+ return (NSS_NOTFOUND);
+ return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL,
+ NULL, NULL));
+}
+
+static ldap_backend_op_t project_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbyprojid
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_project_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+ return (_nss_ldap_constr(project_ops,
+ sizeof (project_ops) / sizeof (project_ops[0]),
+ _PROJECT, project_attrs, _nss_ldap_proj2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getprotoent.c b/usr/src/lib/nsswitch/ldap/common/getprotoent.c
new file mode 100644
index 0000000000..09522445e4
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getprotoent.c
@@ -0,0 +1,327 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <ctype.h>
+#include <netdb.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* protocols attributes filters */
+#define _P_NAME "cn"
+#define _P_PROTO "ipprotocolnumber"
+#define _F_GETPROTOBYNAME "(&(objectClass=ipProtocol)(cn=%s))"
+#define _F_GETPROTOBYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETPROTOBYNUMBER \
+ "(&(objectClass=ipProtocol)(ipProtocolNumber=%d))"
+#define _F_GETPROTOBYNUMBER_SSD \
+ "(&(%%s)(ipProtocolNumber=%d))"
+
+static const char *protocols_attrs[] = {
+ _P_NAME,
+ _P_PROTO,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_protocols2ent is the data marshaling method for the protocols
+ * getXbyY * (e.g., getbyname(), getbynumber(), getent()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into *proto = (struct
+ * protoent *)argp->buf.result which the frontend process expects. Three error
+ * conditions are expected and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_protocols2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char *cp, **mp, *cname = NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct protoent *proto = (struct protoent *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = (char *)argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pls2ent;
+ }
+ proto = (struct protoent *)argp->buf.result;
+ ceiling = buffer + buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _P_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstime) {
+ /* protocol name */
+ cname = __s_api_get_canonical_name(
+ result->entry, attrptr, 1);
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result =
+ NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ proto->p_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_pls2ent;
+ }
+ (void) strcpy(proto->p_name, cname);
+ mp = proto->p_aliases =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)proto->p_aliases +
+ sizeof (char *) *
+ (attrptr->value_count + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_pls2ent;
+ }
+ firstime = (int)0;
+ }
+ /* alias list */
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ /*
+ * When the data is imported by ldapaddent,
+ * it does not save the aliase in the "cn"
+ * that is same as the canonical name but only
+ * differnt in case.
+ * e.g.
+ * icmp 1 ICMP
+ *
+ * is saved as
+ *
+ * dn: cn=icmp, ...
+ * ...
+ * cn: icmp
+ * ...
+ * So it needs to replicate the canonical name
+ * as an aliase of upper case.
+ *
+ * But in the case of
+ * ospf 89 OSPFIGP
+ * it creates a redundant aliase.
+ * e.g.
+ * dn: cn=icmp, ...
+ * ...
+ * cn: ospf
+ * cn: OSPFIGP
+ * ...
+ *
+ * getent services ospf
+ * ==> ospf 89 ospf OSPFIGP
+ *
+ * Some condition check is added to handle this
+ * scenario. Such check also works with
+ * following scenario.
+ * dn: cn=icmp, ...
+ * ...
+ * cn: icmp
+ * cn: ICMP
+ * ...
+ */
+ if (strcmp(proto->p_name,
+ attrptr->attrvalue[j]) == 0) {
+ if (attrptr->value_count > 1)
+ /* Do not replicate */
+ continue;
+ for (cp = attrptr->attrvalue[j];
+ *cp; cp++)
+ *cp = toupper(*cp);
+ }
+ *mp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pls2ent;
+ }
+ (void) strcpy(*mp++, attrptr->attrvalue[j]);
+ continue;
+ }
+ }
+ if (strcasecmp(attrptr->attrname, _P_PROTO) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ errno = 0;
+ proto->p_proto = (int)strtol(attrptr->attrvalue[0],
+ (char **)NULL, 10);
+ if (errno != 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pls2ent;
+ }
+ continue;
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getprotoent.c: _nss_ldap_protocols2ent]\n");
+ (void) fprintf(stdout, " p_name: [%s]\n", proto->p_name);
+ if (mp != NULL) {
+ for (mp = proto->p_aliases; *mp != NULL; mp++)
+ (void) fprintf(stdout, " p_aliases: [%s]\n", *mp);
+ }
+ (void) fprintf(stdout, " p_proto: [%d]\n", proto->p_proto);
+#endif /* DEBUG */
+
+result_pls2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets struct protoent values by protocol name. This
+ * function constructs an ldap search filter using the protocol
+ * name invocation parameter and the getprotobyname search filter
+ * defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into *proto = (struct *
+ * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
+ * performs the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETPROTOBYNAME, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETPROTOBYNAME_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _PROTOCOLS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbynumber gets struct protoent values by protocol number. This
+ * function constructs an ldap search filter using the protocol
+ * name invocation parameter and the getprotobynumber search filter
+ * defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into *proto = (struct *
+ * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
+ * performs the data marshaling.
+ */
+
+static nss_status_t
+getbynumber(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETPROTOBYNUMBER, argp->key.number);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETPROTOBYNUMBER_SSD, argp->key.number);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _PROTOCOLS, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+static ldap_backend_op_t proto_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbynumber
+};
+
+
+/*
+ * _nss_ldap_protocols_constr is where life begins. This function calls
+ * the generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_protocols_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(proto_ops,
+ sizeof (proto_ops)/sizeof (proto_ops[0]), _PROTOCOLS,
+ protocols_attrs, _nss_ldap_protocols2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getpwnam.c b/usr/src/lib/nsswitch/ldap/common/getpwnam.c
new file mode 100644
index 0000000000..205513812a
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getpwnam.c
@@ -0,0 +1,347 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <pwd.h>
+#include "ldap_common.h"
+
+/* passwd attributes filters */
+#define _PWD_CN "cn"
+#define _PWD_UID "uid"
+#define _PWD_USERPASSWORD "userpassword"
+#define _PWD_UIDNUMBER "uidnumber"
+#define _PWD_GIDNUMBER "gidnumber"
+#define _PWD_GECOS "gecos"
+#define _PWD_DESCRIPTION "description"
+#define _PWD_HOMEDIRECTORY "homedirectory"
+#define _PWD_LOGINSHELL "loginshell"
+
+
+#define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))"
+#define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))"
+#define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))"
+#define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))"
+
+static const char *pwd_attrs[] = {
+ _PWD_CN,
+ _PWD_UID,
+ _PWD_UIDNUMBER,
+ _PWD_GIDNUMBER,
+ _PWD_GECOS,
+ _PWD_DESCRIPTION,
+ _PWD_HOMEDIRECTORY,
+ _PWD_LOGINSHELL,
+ (char *)NULL
+};
+
+
+/*
+ * _nss_ldap_passwd2ent is the data marshaling method for the passwd getXbyY
+ * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
+ * called after a successful ldap search has been performed. This method will
+ * parse the ldap search values into struct passwd = argp->buf.buffer which
+ * the frontend process expects. Three error conditions are expected and
+ * returned to nsswitch.
+ */
+
+static int
+_nss_ldap_passwd2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i = 0;
+ int nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *buffer = (char *)NULL;
+ char *ptr2x;
+ char *ceiling = (char *)NULL;
+ char *nullstring = (char *)NULL;
+ struct passwd *pwd = (struct passwd *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+ int have_uid = 0;
+ int have_uidn = 0;
+ int have_gidn = 0;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n");
+#endif /* DEBUG */
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2ent;
+ }
+ pwd = (struct passwd *)argp->buf.result;
+ ceiling = buffer + buflen;
+ nullstring = (buffer + (buflen - 1));
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(buffer, 0, buflen);
+
+ /*
+ * need to always return password as "x"
+ * so put "x" at top of the buffer
+ */
+ ptr2x = buffer;
+ *buffer++ = 'x';
+ *buffer++ = '\0';
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pwd2ent;
+ }
+
+ pwd->pw_gecos = nullstring;
+ pwd->pw_dir = nullstring;
+ pwd->pw_shell = nullstring;
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pwd2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _PWD_UID) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pwd2ent;
+ }
+ pwd->pw_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2ent;
+ }
+ (void) strcpy(pwd->pw_name, attrptr->attrvalue[0]);
+ have_uid = 1;
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PWD_UIDNUMBER) == 0) {
+ if (attrptr->attrvalue[0] == '\0') {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pwd2ent;
+ }
+ pwd->pw_uid = strtol(attrptr->attrvalue[0],
+ (char **)NULL, 10);
+ have_uidn = 1;
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _PWD_GIDNUMBER) == 0) {
+ if (attrptr->attrvalue[0] == '\0') {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_pwd2ent;
+ }
+ pwd->pw_gid = strtol(attrptr->attrvalue[0],
+ (char **)NULL, 10);
+ have_gidn = 1;
+ continue;
+ }
+ if ((strcasecmp(attrptr->attrname, _PWD_GECOS) == 0) &&
+ (attrptr->value_count > 0)) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ pwd->pw_gecos = nullstring;
+ } else {
+ pwd->pw_gecos = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2ent;
+ }
+ (void) strcpy(pwd->pw_gecos,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if ((strcasecmp(attrptr->attrname, _PWD_HOMEDIRECTORY) == 0) &&
+ (attrptr->value_count > 0)) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ pwd->pw_dir = nullstring;
+ } else {
+ pwd->pw_dir = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2ent;
+ }
+ (void) strcpy(pwd->pw_dir,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if ((strcasecmp(attrptr->attrname, _PWD_LOGINSHELL) == 0) &&
+ (attrptr->value_count > 0)) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ pwd->pw_shell = nullstring;
+ } else {
+ pwd->pw_shell = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_pwd2ent;
+ }
+ (void) strcpy(pwd->pw_shell,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+ /* error if missing required attributes */
+ if (have_uid == 0 || have_uidn == 0 || have_gidn == 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ }
+
+ pwd->pw_age = nullstring;
+ pwd->pw_comment = nullstring;
+ pwd->pw_passwd = ptr2x;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n");
+ (void) fprintf(stdout, " pw_name: [%s]\n", pwd->pw_name);
+ (void) fprintf(stdout, " pw_uid: [%ld]\n", pwd->pw_uid);
+ (void) fprintf(stdout, " pw_gid: [%ld]\n", pwd->pw_gid);
+ (void) fprintf(stdout, " pw_gecos: [%s]\n", pwd->pw_gecos);
+ (void) fprintf(stdout, " pw_dir: [%s]\n", pwd->pw_dir);
+ (void) fprintf(stdout, " pw_shell: [%s]\n", pwd->pw_shell);
+#endif /* DEBUG */
+
+result_pwd2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets a passwd entry by uid name. This function constructs an ldap
+ * search filter using the name invocation parameter and the getpwnam search
+ * filter defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into struct passwd for the frontend
+ * process. The function _nss_ldap_passwd2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _PASSWD, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbyuid gets a passwd entry by uid number. This function constructs an ldap
+ * search filter using the uid invocation parameter and the getpwuid search
+ * filter defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into struct passwd for the frontend
+ * process. The function _nss_ldap_passwd2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbyuid(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: getbyuid]\n");
+#endif /* DEBUG */
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETPWUID, (long)argp->key.uid);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETPWUID_SSD, (long)argp->key.uid);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _PASSWD, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+static ldap_backend_op_t passwd_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbyuid
+};
+
+
+/*
+ * _nss_ldap_passwd_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd_constr]\n");
+#endif /* DEBUG */
+
+ return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
+ sizeof (passwd_ops)/sizeof (passwd_ops[0]),
+ _PASSWD, pwd_attrs, _nss_ldap_passwd2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getrpcent.c b/usr/src/lib/nsswitch/ldap/common/getrpcent.c
new file mode 100644
index 0000000000..e8e0d51df3
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getrpcent.c
@@ -0,0 +1,280 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <rpc/rpcent.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* rpc attributes filters */
+#define _R_NAME "cn"
+#define _R_NUMBER "oncrpcnumber"
+
+
+#define _F_GETRPCBYNAME "(&(objectClass=oncRpc)(cn=%s))"
+#define _F_GETRPCBYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETRPCBYNUMBER "(&(objectClass=oncRpc)(oncRpcNumber=%d))"
+#define _F_GETRPCBYNUMBER_SSD "(&(%%s)(oncRpcNumber=%d))"
+
+static const char *rpc_attrs[] = {
+ _R_NAME,
+ _R_NUMBER,
+ (char *)NULL
+};
+
+/*
+ * _nss_ldap_rpc2ent is the data marshaling method for the rpc getXbyY
+ * (e.g., getbyname(), getbynumber(), getrpcent()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into *rpc = (struct
+ * rpcent *)argp->buf.result which the frontend process expects. Three
+ * error conditions are expected and returned to nsswitch.
+ */
+
+static int
+_nss_ldap_rpc2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j;
+ int nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char **mp, *cname = NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct rpcent *rpc = (struct rpcent *)NULL;
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+
+ buffer = (char *)argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_rpc2ent;
+ }
+ rpc = (struct rpcent *)argp->buf.result;
+ ceiling = buffer + buflen;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _R_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ /* traverse for all multivalued values */
+ if (firstime) {
+ /* rpc name */
+ cname = __s_api_get_canonical_name(
+ result->entry, attrptr, 1);
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result =
+ NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ rpc->r_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_rpc2ent;
+ }
+ (void) strcpy(rpc->r_name, cname);
+ /* alias list */
+ mp = rpc->r_aliases =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)rpc->r_aliases +
+ sizeof (char *) *
+ (attrptr->value_count + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_rpc2ent;
+ }
+ firstime = (int)0;
+ }
+ /* alias list */
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ /* skip canonical name */
+ if (strcmp(attrptr->attrvalue[j], cname) == 0)
+ continue;
+ *mp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_rpc2ent;
+ }
+ (void) strcpy(*mp++, attrptr->attrvalue[j]);
+ continue;
+ }
+ }
+ if (strcasecmp(attrptr->attrname, _R_NUMBER) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ errno = 0;
+ rpc->r_number = (int)strtol(attrptr->attrvalue[0],
+ (char **)NULL, 10);
+ if (errno != 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_rpc2ent;
+ }
+ continue;
+ }
+ }
+ if (mp != NULL)
+ *mp = NULL;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getrpcent.c: _nss_ldap_rpc2ent]\n");
+ (void) fprintf(stdout, " r_name: [%s]\n", rpc->r_name);
+ if (mp != NULL) {
+ for (mp = rpc->r_aliases; *mp != NULL; mp++)
+ (void) fprintf(stdout, " r_aliases: [%s]\n", *mp);
+ }
+ (void) fprintf(stdout, " r_number: [%d]\n", rpc->r_number);
+#endif /* DEBUG */
+
+result_rpc2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets struct rpcent values by rpc name. This function
+ * constructs an ldap search filter using the rpc name invocation
+ * parameter and the getrpcbyname search filter defined. Once the
+ * filter is constructed, we search for a matching entry and marshal
+ * the data results into *rpc = (struct rpcent *)argp->buf.result.
+ * The function _nss_ldap_rpc2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETRPCBYNAME,
+ name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETRPCBYNAME_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter,
+ NULL, _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbynumber gets struct rpcent values by rpc number. This function
+ * constructs an ldap search filter using the rpc number invocation
+ * parameter and the getrpcbynumber search filter defined. Once the
+ * filter is constructed, we search for a matching entry and marshal
+ * the data results into *rpc = (struct rpcent *)argp->buf.result.
+ * The function _nss_ldap_rpc2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbynumber(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ int ret;
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETRPCBYNUMBER, argp->key.number);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETRPCBYNUMBER_SSD, argp->key.number);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter,
+ NULL, _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t rpc_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbynumber
+};
+
+
+/*
+ * _nss_ldap_rpc_constr is where life begins. This function calls the generic
+ * ldap constructor function to define and build the abstract data types
+ * required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_rpc_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(rpc_ops,
+ sizeof (rpc_ops)/sizeof (rpc_ops[0]),
+ _RPC, rpc_attrs, _nss_ldap_rpc2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getservent.c b/usr/src/lib/nsswitch/ldap/common/getservent.c
new file mode 100644
index 0000000000..e266a31b42
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getservent.c
@@ -0,0 +1,502 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <ctype.h>
+#include <netdb.h>
+#include "ns_internal.h"
+#include "ldap_common.h"
+
+/* services attributes filters */
+#define _S_NAME "cn"
+#define _S_PORT "ipserviceport"
+#define _S_PROTOCOL "ipserviceprotocol"
+#define _F_GETSERVBYNAME "(&(objectClass=ipService)(cn=%s))"
+#define _F_GETSERVBYNAME_SSD "(&(%%s)(cn=%s))"
+#define _F_GETSERVBYNAMEPROTO \
+ "(&(objectClass=ipService)(cn=%s)(ipServiceProtocol=%s))"
+#define _F_GETSERVBYNAMEPROTO_SSD \
+ "(&(%%s)(cn=%s)(ipServiceProtocol=%s))"
+#define _F_GETSERVBYPORT "(&(objectClass=ipService)(ipServicePort=%ld))"
+#define _F_GETSERVBYPORT_SSD "(&(%%s)(ipServicePort=%ld))"
+#define _F_GETSERVBYPORTPROTO \
+ "(&(objectClass=ipService)(ipServicePort=%ld)(ipServiceProtocol=%s))"
+#define _F_GETSERVBYPORTPROTO_SSD \
+ "(&(%%s)(ipServicePort=%ld)(ipServiceProtocol=%s))"
+
+typedef struct _nss_services_cookie {
+ int index; /* index of ipserviceprotocol */
+ char *cname; /* canonical name, don't free it */
+ ns_ldap_result_t *result;
+} _nss_services_cookie_t;
+
+static const char *services_attrs[] = {
+ _S_NAME,
+ _S_PORT,
+ _S_PROTOCOL,
+ (char *)NULL
+};
+
+void
+_nss_services_cookie_free(void **ckP) {
+ _nss_services_cookie_t **cookieP = (_nss_services_cookie_t **)ckP;
+ if (cookieP && *cookieP) {
+ if ((*cookieP)->result)
+ (void) __ns_ldap_freeResult(&(*cookieP)->result);
+ free(*cookieP);
+ *cookieP = NULL;
+ }
+}
+
+static _nss_services_cookie_t *
+_nss_services_cookie_new(ns_ldap_result_t *result, int index, char *cname) {
+
+ _nss_services_cookie_t *cookie;
+
+ if ((cookie = calloc(1, sizeof (*cookie))) == NULL)
+ return (NULL);
+
+ /*
+ * result has been allocated either by __ns_ldap_firstEntry
+ * or __ns_ldap_nextEntry.
+ */
+ cookie->result = result;
+
+ cookie->index = index;
+ cookie->cname = cname;
+
+ return (cookie);
+}
+
+/*
+ * _nss_ldap_services2ent is the data marshaling method for the services
+ * getXbyY * (e.g., getbyname(), getbyport(), getent()) backend processes.
+ * This method is called after a successful ldap search has been performed.
+ * This method will parse the ldap search values into *serv = (struct
+ * servent *)argp->buf.result which the frontend process expects. Three error
+ * conditions are expected and returned to nsswitch.
+ *
+ * In section 5.5 of RFC 2307, it specifies that a "services" LDAP entry
+ * containing multiple ipserviceprotocol values should be able to be mapped
+ * to multiple "services" entities. Code has been added to support
+ * this one to many mapping feature.
+ */
+
+static int
+_nss_ldap_services2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, j, k;
+ int nss_result;
+ int buflen = (int)0;
+ int firstime = (int)1;
+ unsigned long len = 0L;
+ char **mp, *cname = NULL, *protoval = NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ struct servent *serv = (struct servent *)NULL;
+ ns_ldap_result_t *result;
+ ns_ldap_attr_t *attrptr, *protocol = NULL;
+ _nss_services_cookie_t *cookie = (_nss_services_cookie_t *)
+ be->services_cookie;
+
+ buffer = (char *)argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ serv = (struct servent *)argp->buf.result;
+ ceiling = buffer + buflen;
+#ifdef DEBUG
+ (void) fprintf(stderr, "[getservent.c: _nss_ldap_services2ent]\n");
+#endif /* DEBUG */
+
+ if (cookie) {
+ /*
+ * getservent_r with multiple protocol values and the entry
+ * is enumerated 2nd time or beyond
+ */
+ result = cookie->result;
+ cname = cookie->cname;
+ } else {
+ /*
+ * getservbyname_r, getservbyport_r or
+ * getservent_r with single protocol value or multiple values
+ * and the entry is enumerated 1st time
+ */
+ result = be->result;
+ }
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _S_NAME) == 0) {
+ for (j = 0; j < attrptr->value_count; j++) {
+ if (firstime) {
+ /* service name */
+ if (cname == NULL) {
+ cname = __s_api_get_canonical_name(
+ result->entry, attrptr, 1);
+ }
+ if (cname == NULL ||
+ (len = strlen(cname)) < 1) {
+ nss_result =
+ NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ serv->s_name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_srvs2ent;
+ }
+ (void) strcpy(serv->s_name, cname);
+ /* alias list */
+ mp = serv->s_aliases =
+ (char **)ROUND_UP(buffer,
+ sizeof (char **));
+ buffer = (char *)serv->s_aliases +
+ sizeof (char *) *
+ (attrptr->value_count + 1);
+ buffer = (char *)ROUND_UP(buffer,
+ sizeof (char **));
+ if (buffer >= ceiling) {
+ nss_result =
+ (int)NSS_STR_PARSE_ERANGE;
+ goto result_srvs2ent;
+ }
+ firstime = (int)0;
+ }
+ /* alias list */
+ if ((attrptr->attrvalue[j] == NULL) ||
+ (len = strlen(attrptr->attrvalue[j])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ /* skip canonical name */
+ if (strcmp(cname, attrptr->attrvalue[j]) == 0)
+ continue;
+
+ *mp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_srvs2ent;
+ }
+ (void) strcpy(*mp++, attrptr->attrvalue[j]);
+ continue;
+ }
+ }
+
+ if (strcasecmp(attrptr->attrname, _S_PORT) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ serv->s_port =
+ htons((ushort_t)atoi(attrptr->attrvalue[0]));
+ continue;
+ }
+
+ if (strcasecmp(attrptr->attrname, _S_PROTOCOL) == 0) {
+ /* protocol name */
+ if (attrptr->attrvalue == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ protocol = attrptr;
+ if (cookie) {
+ /*
+ * getservent_r
+ * Get current value then increment index
+ */
+ protoval = attrptr->attrvalue[cookie->index++];
+ } else if (attrptr->value_count > 1 &&
+ argp->key.serv.proto) {
+ /*
+ * getserverbyname_r and getservbyport_r
+ *
+ * If there are more than one value and
+ * it needs to match protocol too,
+ * iterate each value to find matching one.
+ * getservent_r sets key.serv.proto to NULL,
+ * so it wouldn't run this part of code.
+ */
+ for (k = 0; k < attrptr->value_count; k++) {
+ if (attrptr->attrvalue[k] == NULL) {
+ nss_result =
+ NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ if (strcmp(attrptr->attrvalue[k],
+ argp->key.serv.proto) == 0) {
+ protoval =
+ attrptr->attrvalue[k];
+ break;
+ }
+ }
+ } else {
+ /*
+ * 1. getserverbyname_r and getservbyport_r
+ *
+ * It does not need to match protocol or
+ * ipserviceprotocol has single value,
+ * return the first one
+ *
+ * 2. getservent_r with single value
+ * or multiple values and the entry is
+ * enumerated 1st time,
+ * return the first one
+ *
+ */
+ protoval = attrptr->attrvalue[0];
+ }
+
+ if (protoval == NULL || (len = strlen(protoval)) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+ serv->s_proto = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_srvs2ent;
+ }
+ (void) strcpy(serv->s_proto, protoval);
+ continue;
+ }
+ }
+
+ if (be->enumcookie != NULL && cookie == NULL &&
+ protocol->value_count > 1) {
+ /*
+ * getservent_r with multiple ipserviceprotocol values
+ * and the entry is enumerated 1st time
+ *
+ * Create cookie and save result in the cookie
+ * "attrvalue[0]" of ipserviceprotocol is returned,
+ * so it starts with index 1. Also save the canonical name.
+ */
+ be->services_cookie =
+ (void *)_nss_services_cookie_new(be->result, 1, cname);
+ if (be->services_cookie == NULL) {
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_srvs2ent;
+ }
+
+ /* reset be->result so it won't get freed later */
+ be->result = NULL;
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getservent.c: _nss_ldap_services2ent]\n");
+ (void) fprintf(stdout, " s_name: [%s]\n", serv->s_name);
+ if (mp != NULL) {
+ for (mp = serv->s_aliases; *mp != NULL; mp++)
+ (void) fprintf(stdout, " s_aliases: [%s]\n", *mp);
+ }
+ (void) fprintf(stdout, " s_port: [%d]\n", serv->s_port);
+ (void) fprintf(stdout, " s_protocol: [%s]\n", serv->s_proto);
+#endif /* DEBUG */
+
+result_srvs2ent:
+ if (cookie) {
+ /*
+ * getservent_r with multiple ipserviceprotocol values and
+ * the entry is enumerated 2nd time or beyond
+ */
+ if (nss_result != NSS_STR_PARSE_SUCCESS ||
+ cookie->index >= protocol->value_count) {
+ /*
+ * If it's an error case or it has iterated all
+ * ipservicesprotocol value(s) then free cookie and
+ * set it to NULL
+ *
+ */
+ _nss_services_cookie_free(
+ (void **)&be->services_cookie);
+ }
+ } else {
+ /*
+ * getservbyname_r, getservbyport_r, or
+ * getservent_r with single value or can't create cookie
+ */
+ (void) __ns_ldap_freeResult(&be->result);
+ }
+ return ((int)nss_result);
+}
+
+
+/*
+ * getbyname gets struct servent values by service name. This
+ * function constructs an ldap search filter using the service
+ * name invocation parameter and the getservbyname search filter
+ * defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into *serv = (struct servent *)
+ * argp->buf.result. The function _nss_ldap_services2ent performs
+ * the data marshaling.
+ */
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ const char *proto = argp->key.serv.proto;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ char protocol[SEARCHFILTERLEN];
+ int ret;
+
+ if (_ldap_filter_name(name, argp->key.serv.serv.name, sizeof (name))
+ != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (proto == NULL) {
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETSERVBYNAME, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETSERVBYNAME_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else {
+ if (_ldap_filter_name(protocol, proto, sizeof (protocol)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETSERVBYNAMEPROTO, name, protocol);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETSERVBYNAMEPROTO_SSD, name, protocol);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _SERVICES, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+
+/*
+ * getbyport gets struct servent values by service port. This
+ * function constructs an ldap search filter using the service
+ * name invocation parameter and the getservbyport search filter
+ * defined. Once the filter is constructed, we search for a matching
+ * entry and marshal the data results into *serv = (struct servent *)
+ * argp->buf.result. The function _nss_ldap_services2ent performs
+ * the data marshaling.
+ */
+
+static nss_status_t
+getbyport(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ const char *proto = argp->key.serv.proto;
+ char portstr[12];
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char protocol[SEARCHFILTERLEN];
+ int ret;
+
+ ret = snprintf(portstr, sizeof (portstr), " %d",
+ ntohs((ushort_t)argp->key.serv.serv.port));
+ if (ret >= sizeof (portstr) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ if (proto == NULL) {
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETSERVBYPORT, strtol(portstr, (char **)NULL, 10));
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETSERVBYPORT_SSD, strtol(portstr, (char **)NULL, 10));
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ } else {
+ if (_ldap_filter_name(protocol, proto, sizeof (protocol)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _F_GETSERVBYPORTPROTO,
+ strtol(portstr, (char **)NULL, 10), protocol);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _F_GETSERVBYPORTPROTO_SSD,
+ strtol(portstr, (char **)NULL, 10), protocol);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _SERVICES, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+static ldap_backend_op_t serv_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname,
+ getbyport
+};
+
+
+/*
+ * _nss_ldap_services_constr is where life begins. This function calls
+ * the generic ldap constructor function to define and build the
+ * abstract data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_services_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+ return ((nss_backend_t *)_nss_ldap_constr(serv_ops,
+ sizeof (serv_ops)/sizeof (serv_ops[0]), _SERVICES,
+ services_attrs, _nss_ldap_services2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getspent.c b/usr/src/lib/nsswitch/ldap/common/getspent.c
new file mode 100644
index 0000000000..cf5ea84652
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getspent.c
@@ -0,0 +1,298 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <shadow.h>
+#include <stdlib.h>
+#include "ldap_common.h"
+
+/* shadow attributes filters */
+#define _S_CN "cn"
+#define _S_UID "uid"
+#define _S_USERPASSWORD "userpassword"
+#define _S_FLAG "shadowflag"
+
+#define _F_GETSPNAM "(&(objectClass=shadowAccount)(uid=%s))"
+#define _F_GETSPNAM_SSD "(&(%%s)(uid=%s))"
+
+static const char *sp_attrs[] = {
+ _S_UID,
+ _S_USERPASSWORD,
+ _S_FLAG,
+ (char *)NULL
+};
+
+
+extern ns_ldap_attr_t *getattr(ns_ldap_result_t *result, int i);
+
+/*
+ * _nss_ldap_shadow2ent is the data marshaling method for the passwd getXbyY
+ * (e.g., getspnam(), getspent()) backend processes. This method is called after
+ * a successful ldap search has been performed. This method will parse the
+ * ldap search values into struct spwd = argp->buf.buffer which the frontend
+ * process expects. Three error conditions are expected and returned to
+ * nsswitch.
+ */
+
+static int
+_nss_ldap_shadow2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i = 0;
+ int nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ char *pw_passwd = (char *)NULL;
+ char *nullstring = (char *)NULL;
+ char np[] = "*NP*";
+ ns_ldap_result_t *result = be->result;
+ ns_ldap_attr_t *attrptr;
+ long ltmp = (long)0L;
+ struct spwd *spd = (struct spwd *)NULL;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
+#endif /* DEBUG */
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_spd2ent;
+ }
+ spd = (struct spwd *)argp->buf.result;
+ ceiling = buffer + buflen;
+ nullstring = (buffer + (buflen - 1));
+
+ /* Default values */
+ spd->sp_lstchg = -1; spd->sp_min = -1;
+ spd->sp_max = -1; spd->sp_warn = -1;
+ spd->sp_inact = -1; spd->sp_expire = -1;
+ spd->sp_flag = 0; spd->sp_pwdp = NULL;
+
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_spd2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (strcasecmp(attrptr->attrname, _S_UID) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_spd2ent;
+ }
+ spd->sp_namp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_spd2ent;
+ }
+ (void) strcpy(spd->sp_namp, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _S_USERPASSWORD) == 0) {
+ if (attrptr->attrvalue[0] == '\0') {
+ spd->sp_pwdp = nullstring;
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_spd2ent;
+ }
+ pw_passwd = attrptr->attrvalue[0];
+ if (pw_passwd) {
+ char *tmp;
+
+ if ((tmp = strstr(pw_passwd, "{crypt}"))
+ != NULL) {
+ if (tmp != pw_passwd)
+ pw_passwd = np;
+ else
+ pw_passwd += 7;
+ } else if ((tmp = strstr(pw_passwd, "{CRYPT}"))
+ != NULL) {
+ if (tmp != pw_passwd)
+ pw_passwd = np;
+ else
+ pw_passwd += 7;
+ } else {
+ pw_passwd = np;
+ }
+ }
+ len = (unsigned long)strlen(pw_passwd);
+ if (len < 1) {
+ spd->sp_pwdp = nullstring;
+ } else {
+ spd->sp_pwdp = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_spd2ent;
+ }
+ }
+ (void) strcpy(spd->sp_pwdp, pw_passwd);
+ }
+
+ /*
+ * Ignore the following password aging related attributes:
+ * -- shadowlastchange
+ * -- shadowmin
+ * -- shadowmax
+ * -- shadowwarning
+ * -- shadowinactive
+ * -- shadowexpire
+ * This is because the LDAP naming service does not
+ * really support the password aging fields defined
+ * in the shadow structure. These fields, sp_lstchg,
+ * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
+ * have been set to -1.
+ */
+
+ if (strcasecmp(attrptr->attrname, _S_FLAG) == 0) {
+ if (attrptr->attrvalue[0] == '\0') {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_spd2ent;
+ }
+ errno = 0;
+ ltmp = strtol(attrptr->attrvalue[0], (char **)NULL, 10);
+ if (errno != 0) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_spd2ent;
+ }
+ spd->sp_flag = (int)ltmp;
+ continue;
+ }
+ }
+
+ /* we will not allow for an empty password to be */
+ /* returned to the front end as this is not a supported */
+ /* configuration. Since we got to this point without */
+ /* the password being set, we assume that no password was */
+ /* set on the server which is consider a misconfiguration. */
+ /* We will proceed and set the password to *NP* as no password */
+ /* is not supported */
+
+ if (spd->sp_pwdp == NULL) {
+ spd->sp_pwdp = buffer;
+ buffer += strlen(np) + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_spd2ent;
+ }
+ strcpy(spd->sp_pwdp, np);
+ }
+
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow2ent]\n");
+ (void) fprintf(stdout, " sp_namp: [%s]\n", spd->sp_namp);
+ (void) fprintf(stdout, " sp_pwdp: [%s]\n", spd->sp_pwdp);
+ (void) fprintf(stdout, " sp_latchg: [%d]\n", spd->sp_lstchg);
+ (void) fprintf(stdout, " sp_min: [%d]\n", spd->sp_min);
+ (void) fprintf(stdout, " sp_max: [%d]\n", spd->sp_max);
+ (void) fprintf(stdout, " sp_warn: [%d]\n", spd->sp_warn);
+ (void) fprintf(stdout, " sp_inact: [%d]\n", spd->sp_inact);
+ (void) fprintf(stdout, " sp_expire: [%d]\n", spd->sp_expire);
+ (void) fprintf(stdout, " sp_flag: [%d]\n", spd->sp_flag);
+#endif /* DEBUG */
+
+result_spd2ent:
+
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+/*
+ * getbynam gets a passwd entry by uid name. This function constructs an ldap
+ * search filter using the name invocation parameter and the getspnam search
+ * filter defined. Once the filter is constructed we search for a matching
+ * entry and marshal the data results into struct shadow for the frontend
+ * process. The function _nss_ldap_shadow2ent performs the data marshaling.
+ */
+
+static nss_status_t
+getbynam(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN + 1];
+ int len;
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getspent.c: getbynam]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name);
+ if (ret >= sizeof (searchfilter) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL,
+ _merge_SSD_filter, userdata));
+}
+
+static ldap_backend_op_t sp_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbynam
+};
+
+
+/*
+ * _nss_ldap_passwd_constr is where life begins. This function calls the
+ * generic ldap constructor function to define and build the abstract
+ * data types required to support ldap operations.
+ */
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_shadow_constr(const char *dummy1, const char *dummy2,
+ const char *dummy3)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getspent.c: _nss_ldap_shadow_constr]\n");
+#endif /* DEBUG */
+
+ return ((nss_backend_t *)_nss_ldap_constr(sp_ops,
+ sizeof (sp_ops)/sizeof (sp_ops[0]),
+ _SHADOW, sp_attrs, _nss_ldap_shadow2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/getuserattr.c b/usr/src/lib/nsswitch/ldap/common/getuserattr.c
new file mode 100644
index 0000000000..d36194d27e
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/getuserattr.c
@@ -0,0 +1,256 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <secdb.h>
+#include <user_attr.h>
+#include "ldap_common.h"
+
+
+/* user_attr attributes filters */
+#define _USER_NAME "uid"
+#define _USER_QUALIFIER "SolarisUserQualifier"
+#define _USER_RES1 "SolarisAttrReserved1"
+#define _USER_RES2 "SolarisAttrReserved2"
+#define _USER_ATTRS "SolarisAttrKeyValue"
+#define _USER_GETUSERNAME \
+ "(&(objectClass=SolarisUserAttr)(uid=%s))"
+#define _USER_GETUSERNAME_SSD "(&(%%s)(uid=%s))"
+
+
+static const char *user_attrs[] = {
+ _USER_NAME,
+ _USER_QUALIFIER,
+ _USER_RES1,
+ _USER_RES2,
+ _USER_ATTRS,
+ (char *)NULL
+};
+
+
+static int
+_nss_ldap_user2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
+{
+ int i, nss_result;
+ int buflen = (int)0;
+ unsigned long len = 0L;
+ char *nullstring = (char *)NULL;
+ char *buffer = (char *)NULL;
+ char *ceiling = (char *)NULL;
+ userstr_t *user = (userstr_t *)NULL;
+ ns_ldap_attr_t *attrptr;
+ ns_ldap_result_t *result = be->result;
+
+ buffer = argp->buf.buffer;
+ buflen = (size_t)argp->buf.buflen;
+ if (!argp->buf.result) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ user = (userstr_t *)(argp->buf.result);
+ ceiling = buffer + buflen;
+ user->name = (char *)NULL;
+ user->qualifier = (char *)NULL;
+ user->res1 = (char *)NULL;
+ user->res2 = (char *)NULL;
+ user->attr = (char *)NULL;
+ nss_result = (int)NSS_STR_PARSE_SUCCESS;
+ (void) memset(argp->buf.buffer, 0, buflen);
+
+ attrptr = getattr(result, 0);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_user2ent;
+ }
+
+ for (i = 0; i < result->entry->attr_count; i++) {
+ attrptr = getattr(result, i);
+ if (attrptr == NULL) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_user2ent;
+ }
+ if (strcasecmp(attrptr->attrname, _USER_NAME) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ nss_result = (int)NSS_STR_PARSE_PARSE;
+ goto result_user2ent;
+ }
+ user->name = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ (void) strcpy(user->name, attrptr->attrvalue[0]);
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _USER_QUALIFIER) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ user->qualifier = nullstring;
+ } else {
+ user->qualifier = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ (void) strcpy(user->qualifier,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _USER_RES1) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ user->res1 = nullstring;
+ } else {
+ user->res1 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ (void) strcpy(user->res1,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _USER_RES2) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ user->res2 = nullstring;
+ } else {
+ user->res2 = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ (void) strcpy(user->res2,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ if (strcasecmp(attrptr->attrname, _USER_ATTRS) == 0) {
+ if ((attrptr->attrvalue[0] == NULL) ||
+ (len = strlen(attrptr->attrvalue[0])) < 1) {
+ user->attr = nullstring;
+ } else {
+ user->attr = buffer;
+ buffer += len + 1;
+ if (buffer >= ceiling) {
+ nss_result = (int)NSS_STR_PARSE_ERANGE;
+ goto result_user2ent;
+ }
+ (void) strcpy(user->attr,
+ attrptr->attrvalue[0]);
+ }
+ continue;
+ }
+ }
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getuserattr.c: _nss_ldap_user2ent]\n");
+ (void) fprintf(stdout, " user-name: [%s]\n", user->name);
+ if (user->qualifier != (char *)NULL) {
+ (void) fprintf(stdout, " qualifier: [%s]\n",
+ user->qualifier);
+ }
+ if (user->res1 != (char *)NULL) {
+ (void) fprintf(stdout, " res1: [%s]\n", user->res1);
+ }
+ if (user->res2 != (char *)NULL) {
+ (void) fprintf(stdout, " res2: [%s]\n", user->res2);
+ }
+ if (user->attr != (char *)NULL) {
+ (void) fprintf(stdout, " attr: [%s]\n", user->attr);
+ }
+#endif /* DEBUG */
+
+result_user2ent:
+ (void) __ns_ldap_freeResult(&be->result);
+ return ((int)nss_result);
+}
+
+
+static nss_status_t
+getbyname(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ char searchfilter[SEARCHFILTERLEN];
+ char userdata[SEARCHFILTERLEN];
+ char name[SEARCHFILTERLEN];
+ int ret;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[getuserattr.c: getbyname]\n");
+#endif /* DEBUG */
+
+ if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(searchfilter, sizeof (searchfilter),
+ _USER_GETUSERNAME, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ ret = snprintf(userdata, sizeof (userdata),
+ _USER_GETUSERNAME_SSD, name);
+ if (ret >= sizeof (userdata) || ret < 0)
+ return ((nss_status_t)NSS_NOTFOUND);
+
+ return ((nss_status_t)_nss_ldap_lookup(be, argp,
+ _USERATTR, searchfilter, NULL, _merge_SSD_filter, userdata));
+}
+
+
+static ldap_backend_op_t userattr_ops[] = {
+ _nss_ldap_destr,
+ _nss_ldap_endent,
+ _nss_ldap_setent,
+ _nss_ldap_getent,
+ getbyname
+};
+
+
+/*ARGSUSED0*/
+nss_backend_t *
+_nss_ldap_user_attr_constr(const char *dummy1,
+ const char *dummy2,
+ const char *dummy3,
+ const char *dummy4,
+ const char *dummy5)
+{
+#ifdef DEBUG
+ (void) fprintf(stdout,
+ "\n[getuserattr.c: _nss_ldap_user_attr_constr]\n");
+#endif
+ return ((nss_backend_t *)_nss_ldap_constr(userattr_ops,
+ sizeof (userattr_ops)/sizeof (userattr_ops[0]), _USERATTR,
+ user_attrs, _nss_ldap_user2ent));
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.c b/usr/src/lib/nsswitch/ldap/common/ldap_common.c
new file mode 100644
index 0000000000..06acfe2e9b
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.c
@@ -0,0 +1,471 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ldap_common.h"
+#include <malloc.h>
+#include <synch.h>
+#include <syslog.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yp_prot.h>
+#include <thread.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+/* getent attributes filters */
+#define _F_GETALIASENT "(objectClass=rfc822MailGroup)"
+#define _F_GETAUTHNAME "(objectClass=SolarisAuthAttr)"
+#define _F_GETAUUSERNAME "(objectClass=SolarisAuditUser)"
+#define _F_GETEXECNAME "(objectClass=SolarisExecAttr)"
+#define _F_GETGRENT "(objectClass=posixGroup)"
+#define _F_GETHOSTENT "(objectClass=ipHost)"
+#define _F_GETNETENT "(objectClass=ipNetwork)"
+#define _F_GETPROFNAME "(objectClass=SolarisProfAttr)"
+#define _F_GETPROTOENT "(objectClass=ipProtocol)"
+#define _F_GETPWENT "(objectClass=posixAccount)"
+#define _F_GETPRINTERENT "(objectClass=sunPrinter)"
+#define _F_GETRPCENT "(objectClass=oncRpc)"
+#define _F_GETSERVENT "(objectClass=ipService)"
+#define _F_GETSPENT "(objectclass=shadowAccount)"
+#define _F_GETUSERNAME "(objectClass=SolarisUserAttr)"
+#define _F_GETPROJENT "(objectClass=SolarisProject)"
+#define _F_GETENT_SSD "(%s)"
+
+static struct gettablefilter {
+ char *tablename;
+ char *tablefilter;
+} gettablefilterent[] = {
+ {(char *)_PASSWD, (char *)_F_GETPWENT},
+ {(char *)_SHADOW, (char *)_F_GETSPENT},
+ {(char *)_GROUP, (char *)_F_GETGRENT},
+ {(char *)_HOSTS, (char *)_F_GETHOSTENT},
+ {(char *)_NETWORKS, (char *)_F_GETNETENT},
+ {(char *)_PROTOCOLS, (char *)_F_GETPROTOENT},
+ {(char *)_RPC, (char *)_F_GETRPCENT},
+ {(char *)_ALIASES, (char *)_F_GETALIASENT},
+ {(char *)_SERVICES, (char *)_F_GETSERVENT},
+ {(char *)_AUUSER, (char *)_F_GETAUUSERNAME},
+ {(char *)_AUTHATTR, (char *)_F_GETAUTHNAME},
+ {(char *)_EXECATTR, (char *)_F_GETEXECNAME},
+ {(char *)_PROFATTR, (char *)_F_GETPROFNAME},
+ {(char *)_USERATTR, (char *)_F_GETUSERNAME},
+ {(char *)_PROJECT, (char *)_F_GETPROJENT},
+ {(char *)_PRINTERS, (char *)_F_GETPRINTERENT},
+ {(char *)NULL, (char *)NULL}
+};
+
+
+nss_status_t
+switch_err(int rc, ns_ldap_error_t *error)
+{
+ switch (rc) {
+ case NS_LDAP_SUCCESS:
+ return (NSS_SUCCESS);
+
+ case NS_LDAP_NOTFOUND:
+ return (NSS_NOTFOUND);
+
+ case NS_LDAP_PARTIAL:
+ return (NSS_TRYAGAIN);
+
+ case NS_LDAP_INTERNAL:
+ if (error && (error->status == LDAP_SERVER_DOWN ||
+ error->status == LDAP_TIMEOUT))
+ return (NSS_TRYAGAIN);
+ else
+ return (NSS_UNAVAIL);
+
+ default:
+ return (NSS_UNAVAIL);
+ }
+}
+nss_status_t
+_nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
+ char *database, char *searchfilter, char *domain,
+ int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
+ char **realfilter, const void *userdata),
+ const void *userdata)
+{
+ int callbackstat = 0;
+ ns_ldap_error_t *error = NULL;
+ int rc;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
+ (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
+ (void) fprintf(stdout,
+ "\tuserdata: %s\n", userdata ? userdata : "NULL");
+ (void) fprintf(stdout, "\tdatabase: %s\n", database);
+#endif /* DEBUG */
+
+ (void) __ns_ldap_freeResult(&be->result);
+
+ if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
+ be->attrs, NULL, 0, &be->result, &error, NULL,
+ userdata)) != NS_LDAP_SUCCESS) {
+ argp->returnval = 0;
+ rc = switch_err(rc, error);
+ (void) __ns_ldap_freeError(&error);
+ return (rc);
+ }
+ /* callback function */
+ if ((callbackstat =
+ be->ldapobj2ent(be, argp)) == NSS_STR_PARSE_SUCCESS) {
+ argp->returnval = argp->buf.result;
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+ (void) __ns_ldap_freeResult(&be->result);
+
+ /* error */
+ if (callbackstat == NSS_STR_PARSE_PARSE) {
+ argp->returnval = 0;
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ if (callbackstat == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
+ /* No IPV4 address is found */
+ argp->h_errno = HOST_NOT_FOUND;
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ return ((nss_status_t)NSS_UNAVAIL);
+}
+
+
+/*
+ * This function is similar to _nss_ldap_lookup except it does not
+ * do a callback. It is only used by getnetgrent.c
+ */
+
+nss_status_t
+_nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
+ char *database, char *searchfilter, char *domain,
+ int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
+ char **realfilter, const void *userdata),
+ const void *userdata)
+{
+ ns_ldap_error_t *error = NULL;
+ int rc;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
+ (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
+ (void) fprintf(stdout, "\tdatabase: %s\n", database);
+ (void) fprintf(stdout,
+ "\tuserdata: %s\n", userdata ? userdata : "NULL");
+#endif /* DEBUG */
+
+ (void) __ns_ldap_freeResult(&be->result);
+
+ if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
+ be->attrs, NULL, 0, &be->result, &error, NULL,
+ userdata)) != NS_LDAP_SUCCESS) {
+ argp->returnval = 0;
+ rc = switch_err(rc, error);
+ (void) __ns_ldap_freeError(&error);
+ return (rc);
+ }
+
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+
+/*
+ *
+ */
+
+void
+_clean_ldap_backend(ldap_backend_ptr be)
+{
+ ns_ldap_error_t *error;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
+#endif /* DEBUG */
+
+ if (be->tablename != NULL)
+ free(be->tablename);
+ if (be->result != NULL)
+ (void) __ns_ldap_freeResult(&be->result);
+ if (be->enumcookie != NULL)
+ (void) __ns_ldap_endEntry(&be->enumcookie, &error);
+ if (be->services_cookie != NULL)
+ _nss_services_cookie_free((void **)&be->services_cookie);
+ if (be->toglue != NULL) {
+ free(be->toglue);
+ be->toglue = NULL;
+ }
+ free(be);
+}
+
+
+/*
+ * _nss_ldap_destr will free all smalloc'ed variable strings and structures
+ * before exiting this nsswitch shared backend library. This function is
+ * called before returning control back to nsswitch.
+ */
+
+/*ARGSUSED1*/
+nss_status_t
+_nss_ldap_destr(ldap_backend_ptr be, void *a)
+{
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
+#endif /* DEBUG */
+
+ (void) _clean_ldap_backend(be);
+
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+
+/*
+ * _nss_ldap_setent called before _nss_ldap_getent. This function is
+ * required by POSIX.
+ */
+
+nss_status_t
+_nss_ldap_setent(ldap_backend_ptr be, void *a)
+{
+ struct gettablefilter *gtf;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
+#endif /* DEBUG */
+
+ if (be->setcalled == 1)
+ (void) _nss_ldap_endent(be, a);
+ be->filter = NULL;
+ for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
+ if (strcmp(gtf->tablename, be->tablename))
+ continue;
+ be->filter = (char *)gtf->tablefilter;
+ break;
+ }
+
+ be->setcalled = 1;
+ be->enumcookie = NULL;
+ be->result = NULL;
+ be->services_cookie = NULL;
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+
+/*
+ * _nss_ldap_endent called after _nss_ldap_getent. This function is
+ * required by POSIX.
+ */
+
+/*ARGSUSED1*/
+nss_status_t
+_nss_ldap_endent(ldap_backend_ptr be, void *a)
+{
+ ns_ldap_error_t *error = NULL;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
+#endif /* DEBUG */
+
+ be->setcalled = 0;
+ be->filter = NULL;
+ if (be->enumcookie != NULL) {
+ (void) __ns_ldap_endEntry(&be->enumcookie, &error);
+ (void) __ns_ldap_freeError(&error);
+ }
+ if (be->result != NULL) {
+ (void) __ns_ldap_freeResult(&be->result);
+ }
+ if (be->services_cookie != NULL) {
+ _nss_services_cookie_free((void **)&be->services_cookie);
+ }
+
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+
+/*
+ *
+ */
+
+nss_status_t
+_nss_ldap_getent(ldap_backend_ptr be, void *a)
+{
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ ns_ldap_error_t *error = NULL;
+ int parsestat = 0;
+ int retcode = 0;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
+#endif /* DEBUG */
+
+ if (be->setcalled == 0)
+ (void) _nss_ldap_setent(be, a);
+
+next_entry:
+ if (be->enumcookie == NULL) {
+ retcode = __ns_ldap_firstEntry(be->tablename,
+ be->filter, _merge_SSD_filter, be->attrs, NULL,
+ 0, &be->enumcookie,
+ &be->result, &error, _F_GETENT_SSD);
+ } else {
+ if (be->services_cookie == NULL) {
+ retcode = __ns_ldap_nextEntry(be->enumcookie,
+ &be->result, &error);
+ }
+ }
+ if (retcode != NS_LDAP_SUCCESS) {
+ retcode = switch_err(retcode, error);
+ (void) __ns_ldap_freeError(&error);
+ (void) _nss_ldap_endent(be, a);
+ return (retcode);
+ } else {
+ if ((parsestat = be->ldapobj2ent(be, argp))
+ == NSS_STR_PARSE_SUCCESS) {
+ be->result = NULL;
+ argp->returnval = argp->buf.result;
+ return ((nss_status_t)NSS_SUCCESS);
+ }
+ be->result = NULL;
+ if (parsestat == NSS_STR_PARSE_PARSE) {
+ argp->returnval = 0;
+ (void) _nss_ldap_endent(be, a);
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+
+ if (parsestat == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ (void) _nss_ldap_endent(be, a);
+ return ((nss_status_t)NSS_NOTFOUND);
+ }
+ if (parsestat == NSS_STR_PARSE_NO_ADDR)
+ /*
+ * No IPV4 address is found in the current entry.
+ * It indicates that the entry contains IPV6 addresses
+ * only. Instead of calling _nss_ldap_endent to
+ * terminate, get next entry to continue enumeration.
+ * If it returned NSS_NOTFOUND here,
+ * gethostent() would return NULL
+ * and the enumeration would stop prematurely.
+ */
+ goto next_entry;
+ }
+
+ return ((nss_status_t)NSS_SUCCESS);
+}
+
+
+/*
+ *
+ */
+
+nss_backend_t *
+_nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
+ const char **attrs, fnf ldapobj2ent)
+{
+ ldap_backend_ptr be;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
+#endif /* DEBUG */
+
+ if ((be = (ldap_backend_ptr) malloc(sizeof (*be))) == 0)
+ return (0);
+ be->ops = ops;
+ be->nops = (nss_dbop_t)nops;
+ be->tablename = (char *)strdup(tablename);
+ be->attrs = attrs;
+ be->result = NULL;
+ be->ldapobj2ent = ldapobj2ent;
+ be->setcalled = 0;
+ be->filter = NULL;
+ be->enumcookie = NULL;
+ be->netgroup_cookie = NULL;
+ be->services_cookie = NULL;
+ be->toglue = NULL;
+
+ return ((nss_backend_t *)be);
+}
+
+
+/*
+ *
+ */
+int
+chophostdomain(char *string, char *host, char *domain)
+{
+ char *dot;
+
+ if (string == NULL)
+ return (-1);
+
+ if ((dot = strchr(string, '.')) == NULL) {
+ return (0);
+ }
+ *dot = '\0';
+ strcpy(host, string);
+ strcpy(domain, ++dot);
+
+ return (0);
+}
+
+
+/*
+ *
+ */
+int
+propersubdomain(char *domain, char *subdomain)
+{
+ int domainlen, subdomainlen;
+
+ /* sanity check */
+ if (domain == NULL || subdomain == NULL)
+ return (-1);
+
+ domainlen = strlen(domain);
+ subdomainlen = strlen(subdomain);
+
+ /* is afterdot a substring of domain? */
+ if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
+ return (-1);
+
+ if (domainlen == subdomainlen)
+ return (1);
+
+ if (subdomainlen > domainlen)
+ return (-1);
+
+ if (*(domain + subdomainlen) != '.')
+ return (-1);
+
+ return (1);
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.h b/usr/src/lib/nsswitch/ldap/common/ldap_common.h
new file mode 100644
index 0000000000..292abfba54
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.h
@@ -0,0 +1,146 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LDAP_COMMON_H
+#define _LDAP_COMMON_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ctype.h>
+#include <nss_dbdefs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <signal.h>
+#include <lber.h>
+#include <ldap.h>
+#include <pwd.h>
+#include "ns_sldap.h"
+
+#define _ALIASES "aliases"
+#define _AUTOMOUNT "automount"
+#define _AUTHATTR "auth_attr"
+#define _AUUSER "audit_user"
+#define _BOOTPARAMS "bootparams"
+#define _DEFAULT "default"
+#define _ETHERS "ethers"
+#define _EXECATTR "exec_attr"
+#define _GROUP "group"
+#define _PROJECT "project"
+#define _HOSTS "hosts"
+#define _HOSTS6 "hosts"
+#define _NETGROUP "netgroup"
+#define _NETMASKS "netmasks"
+#define _NETWORKS "networks"
+#define _PASSWD "passwd"
+#define _PRINTERS "printers"
+#define _PROFATTR "prof_attr"
+#define _PROTOCOLS "protocols"
+#define _PUBLICKEY "publickey"
+#define _RPC "rpc"
+#define _SERVICES "services"
+#define _SHADOW "shadow"
+#define _USERATTR "user_attr"
+
+#define NSS_STR_PARSE_NO_ADDR (NSS_STR_PARSE_ERANGE + 100)
+
+#define DOTTEDSUBDOMAIN(string) \
+ ((string != NULL) && (strchr(string, '.') != NULL))
+#define SEARCHFILTERLEN 256
+
+/*
+ * Superset the nss_backend_t abstract data type. This ADT has
+ * been extended to include ldap associated data structures.
+ */
+
+typedef struct ldap_backend *ldap_backend_ptr;
+typedef nss_status_t (*ldap_backend_op_t)(ldap_backend_ptr, void *);
+typedef int (*fnf)(ldap_backend_ptr be, nss_XbyY_args_t *argp);
+
+struct ldap_backend {
+ ldap_backend_op_t *ops;
+ nss_dbop_t nops;
+ char *tablename;
+ void *enumcookie;
+ char *filter;
+ int setcalled;
+ const char **attrs;
+ ns_ldap_result_t *result;
+ fnf ldapobj2ent;
+ void *netgroup_cookie;
+ void *services_cookie;
+ char *toglue;
+};
+
+extern nss_status_t _nss_ldap_destr(ldap_backend_ptr be, void *a);
+extern nss_status_t _nss_ldap_endent(ldap_backend_ptr be, void *a);
+extern nss_status_t _nss_ldap_setent(ldap_backend_ptr be, void *a);
+extern nss_status_t _nss_ldap_getent(ldap_backend_ptr be, void *a);
+nss_backend_t *_nss_ldap_constr(ldap_backend_op_t ops[], int nops,
+ char *tablename, const char **attrs, fnf ldapobj2ent);
+extern nss_status_t _nss_ldap_nocb_lookup(ldap_backend_ptr be,
+ nss_XbyY_args_t *argp, char *database,
+ char *searchfilter, char *domain,
+ int (*init_filter_cb)(
+ const ns_ldap_search_desc_t *desc,
+ char **realfilter, const void *userdata),
+ const void *userdata);
+extern nss_status_t _nss_ldap_lookup(ldap_backend_ptr be,
+ nss_XbyY_args_t *argp, char *database,
+ char *searchfilter, char *domain,
+ int (*init_filter_cb)(
+ const ns_ldap_search_desc_t *desc,
+ char **realfilter, const void *userdata),
+ const void *userdata);
+extern void _clean_ldap_backend(ldap_backend_ptr be);
+
+extern ns_ldap_attr_t *getattr(ns_ldap_result_t *result, int i);
+extern const char *_strip_quotes(char *ipaddress);
+extern int __nss2herrno(nss_status_t nsstat);
+extern int propersubdomain(char *domain, char *subdomain);
+extern int chophostdomain(char *string, char *host, char *domain);
+extern char *_get_domain_name(char *cdn);
+extern int _merge_SSD_filter(const ns_ldap_search_desc_t *desc,
+ char **realfilter, const void *userdata);
+extern int _ldap_filter_name(char *filter_name, const char *name,
+ int filter_name_size);
+extern nss_status_t switch_err(int rc, ns_ldap_error_t *error);
+
+extern void _nss_services_cookie_free(void **cookieP);
+
+#ifdef DEBUG
+extern int printresult(ns_ldap_result_t *result);
+#endif /* DEBUG */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LDAP_COMMON_H */
diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_utils.c b/usr/src/lib/nsswitch/ldap/common/ldap_utils.c
new file mode 100644
index 0000000000..e63c800387
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_utils.c
@@ -0,0 +1,289 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/systeminfo.h>
+#include "ldap_common.h"
+
+
+#ifdef DEBUG
+/*
+ * Debugging routine for printing the value of a result
+ * structure
+ */
+int
+printresult(ns_ldap_result_t *result)
+{
+ int i, j, k;
+ ns_ldap_entry_t *curEntry;
+
+ printf("--------------------------------------\n");
+ printf("entries_count %d\n", result->entries_count);
+ curEntry = result->entry;
+ for (i = 0; i < result->entries_count; i++) {
+ printf("entry %d has attr_count = %d \n",
+ i, curEntry->attr_count);
+ for (j = 0; j < curEntry->attr_count; j++) {
+ printf("entry %d has attr_pair[%d] = %s \n",
+ i, j, curEntry->attr_pair[j]->attrname);
+ for (k = 0;
+ (k < curEntry->attr_pair[j]->value_count) &&
+ (curEntry->attr_pair[j]->attrvalue[k]);
+ k++)
+ printf("entry %d has "
+ "attr_pair[%d]->attrvalue[%d] = %s \n",
+ i, j, k,
+ curEntry->attr_pair[j]->attrvalue[k]);
+ }
+ printf("\n--------------------------------------\n");
+ curEntry = curEntry->next;
+ }
+ return (1);
+}
+#endif
+
+
+/*
+ *
+ */
+
+ns_ldap_attr_t *
+getattr(ns_ldap_result_t *result, int i)
+{
+ ns_ldap_entry_t *entry;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_utils.c: getattr]\n");
+#endif /* DEBUG */
+
+ if (result != NULL) {
+ entry = result->entry;
+ } else {
+ return (NULL);
+ }
+ if (result->entries_count == 0) {
+ return (NULL);
+ } else {
+ return (entry->attr_pair[i]);
+ }
+}
+
+/*
+ * _get_domain_name() passes the dn one level up from cdn, e.g.,
+ * a pointer pointing to "ou= ..." for the cdn's listed below:
+ * dn: cn=hostname+ipHostNumber="109.34.54.76", ou= ...
+ * dn: echo+IpServiceProtocol=udp, ou= ...
+ * to __ns_ldap_dn2domain() to retrieve the domain name associated
+ * with cdn.
+ */
+
+char *
+_get_domain_name(char *cdn)
+{
+ char **rdns;
+ char *pdn, *domain = NULL;
+ int nrdns;
+ int len = 0;
+ const ns_cred_t *cred = NULL;
+ ns_ldap_error_t *error;
+
+ /* break the cdn into its components */
+ rdns = ldap_explode_dn(cdn, 0);
+ if (rdns == NULL || *rdns == NULL)
+ return (NULL);
+
+ /* construct parent dn */
+ for (nrdns = 1; rdns[nrdns]; nrdns++)
+ len += strlen(rdns[nrdns]) + 1;
+ if (len == 0)
+ len = strlen(rdns[0]);
+ pdn = (char *)malloc(len + 1);
+ if (pdn == NULL) {
+ ldap_value_free(rdns);
+ return (NULL);
+ }
+
+ *pdn = '\0';
+ if (nrdns == 1)
+ (void) strcat(pdn, rdns[0]);
+ else {
+ for (nrdns = 1; rdns[nrdns]; nrdns++) {
+ (void) strcat(pdn, rdns[nrdns]);
+ (void) strcat(pdn, ",");
+ }
+ /* remove the last ',' */
+ pdn[strlen(pdn) - 1] = '\0';
+ }
+ /* get domain name */
+ (void) __ns_ldap_dn2domain(pdn, &domain, cred, &error);
+
+ ldap_value_free(rdns);
+ free(pdn);
+ return (domain);
+}
+
+
+/*
+ * "109.34.54.76" -> 109.34.54.76
+ */
+
+const char *
+_strip_quotes(char *ipaddress)
+{
+ char *cp = (char *)NULL;
+
+ /* look for first " */
+ if ((cp = strchr(ipaddress, '"')) == NULL)
+ return ((char *)ipaddress);
+ ipaddress++;
+ /* look for last " */
+ if ((cp = strchr(ipaddress, '"')) == NULL)
+ return ((char *)ipaddress);
+ *cp++ = '\0';
+
+ return (ipaddress);
+}
+
+
+/*
+ * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is
+ * here because /etc/lib/nss_ldap.so.1 cannot call routines in
+ * libnsl. Care should be taken to keep the two copies in sync.
+ */
+
+int
+__nss2herrno(nss_status_t nsstat)
+{
+ switch (nsstat) {
+ case NSS_SUCCESS:
+ return (0);
+ case NSS_NOTFOUND:
+ return (HOST_NOT_FOUND);
+ case NSS_TRYAGAIN:
+ return (TRY_AGAIN);
+ case NSS_UNAVAIL:
+ default: /* keep gcc happy */
+ return (NO_RECOVERY);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * This is a generic filter call back function for
+ * merging the filter from service search descriptor with
+ * an existing search filter. This routine expects userdata
+ * contain a format string with a single %s in it, and will
+ * use the format string with sprintf() to insert the SSD filter.
+ *
+ * This routine is passed to the __ns_ldap_list() or
+ * __ns_ldap_firstEntry() APIs as the filter call back
+ * together with the userdata. For example,
+ * the gethostbyname processing may call __ns_ldap_list() with
+ * "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
+ * as the filter call back, and "(&(%s)(cn=sys1))" as the
+ * userdata, this routine will in turn gets call to produce
+ * "(&(department=sds)(cn=sys1))" as the real search
+ * filter, if the input SSD contains a filter "department=sds".
+ */
+int
+_merge_SSD_filter(const ns_ldap_search_desc_t *desc,
+ char **realfilter,
+ const void *userdata)
+{
+ int len;
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[ldap_utils.c: _merge_SSD_filter]\n");
+#endif /* DEBUG */
+
+ /* sanity check */
+ if (realfilter == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+ *realfilter = NULL;
+
+ if (desc == NULL || desc->filter == NULL ||
+ userdata == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata);
+ (void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter);
+#endif /* DEBUG */
+
+ len = strlen(userdata) + strlen(desc->filter) + 1;
+
+ *realfilter = (char *)malloc(len);
+ if (*realfilter == NULL)
+ return (NS_LDAP_MEMORY);
+
+ (void) sprintf(*realfilter, (char *)userdata,
+ desc->filter);
+
+#ifdef DEBUG
+ (void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter);
+#endif /* DEBUG */
+
+ return (NS_LDAP_SUCCESS);
+}
+
+static char
+hex_char(int n)
+{
+ return ("0123456789abcdef"[n & 0xf]);
+}
+
+int
+_ldap_filter_name(char *filter_name, const char *name, int filter_name_size)
+{
+ char *end = filter_name + filter_name_size;
+ char c;
+
+ for (; *name; name++) {
+ c = *name;
+ switch (c) {
+ case '*':
+ case '(':
+ case ')':
+ case '\\':
+ if (end <= filter_name + 3)
+ return (-1);
+ *filter_name++ = '\\';
+ *filter_name++ = hex_char(c >> 4);
+ *filter_name++ = hex_char(c & 0xf);
+ break;
+ default:
+ if (end <= filter_name + 1)
+ return (-1);
+ *filter_name++ = c;
+ break;
+ }
+ }
+ if (end <= filter_name)
+ return (-1);
+ *filter_name = '\0';
+ return (0);
+}
diff --git a/usr/src/lib/nsswitch/ldap/common/mapfile-vers b/usr/src/lib/nsswitch/ldap/common/mapfile-vers
new file mode 100644
index 0000000000..9daed00900
--- /dev/null
+++ b/usr/src/lib/nsswitch/ldap/common/mapfile-vers
@@ -0,0 +1,66 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Generic interface definition for usr/src/lib/nsswitch/ldap.
+#
+# For information regarding the establishment of versioned definitions see:
+# The Linker and Libraries Manual (version 2.5 or greater)
+# This is part of the Developers Guide in the Answerbook. Specifically refer
+# to Chapter 2 under section "Defining Additional Symbols" through section
+# "Reducing Symbol Scope", and Chapter 5 "Versioning".
+#
+# For specific OSNET rules for the modification (evolution) of these version
+# definitions see:
+# Policy for Shared Library Version Names and Interface Definitions
+
+
+SUNWprivate_1.1 {
+ global:
+ _nss_ldap_audit_user_constr;
+ _nss_ldap_auth_attr_constr;
+ _nss_ldap_bootparams_constr;
+ _nss_ldap_ethers_constr;
+ _nss_ldap_exec_attr_constr;
+ _nss_ldap_group_constr;
+ _nss_ldap_hosts_constr;
+ _nss_ldap_ipnodes_constr;
+ _nss_ldap_netgroup_constr;
+ _nss_ldap_netmasks_constr;
+ _nss_ldap_networks_constr;
+ _nss_ldap_passwd_constr;
+ _nss_ldap_printers_constr;
+ _nss_ldap__printers_constr;
+ _nss_ldap_prof_attr_constr;
+ _nss_ldap_project_constr;
+ _nss_ldap_protocols_constr;
+ _nss_ldap_rpc_constr;
+ _nss_ldap_services_constr;
+ _nss_ldap_shadow_constr;
+ _nss_ldap_publickey_constr;
+ _nss_ldap_user_attr_constr;
+ local:
+ *;
+};