/* * 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 #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)); }