diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/nsswitch/ldap/common | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/nsswitch/ldap/common')
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: + *; +}; |
