17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5cb5caa98Sdjl * Common Development and Distribution License (the "License").
6cb5caa98Sdjl * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*2b4a7802SBaban Kenkre * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <pwd.h>
277c478bd9Sstevel@tonic-gate #include "ldap_common.h"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /* passwd attributes filters */
307c478bd9Sstevel@tonic-gate #define _PWD_CN "cn"
317c478bd9Sstevel@tonic-gate #define _PWD_UID "uid"
327c478bd9Sstevel@tonic-gate #define _PWD_USERPASSWORD "userpassword"
337c478bd9Sstevel@tonic-gate #define _PWD_UIDNUMBER "uidnumber"
347c478bd9Sstevel@tonic-gate #define _PWD_GIDNUMBER "gidnumber"
357c478bd9Sstevel@tonic-gate #define _PWD_GECOS "gecos"
367c478bd9Sstevel@tonic-gate #define _PWD_DESCRIPTION "description"
377c478bd9Sstevel@tonic-gate #define _PWD_HOMEDIRECTORY "homedirectory"
387c478bd9Sstevel@tonic-gate #define _PWD_LOGINSHELL "loginshell"
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))"
427c478bd9Sstevel@tonic-gate #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))"
437c478bd9Sstevel@tonic-gate #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))"
447c478bd9Sstevel@tonic-gate #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate static const char *pwd_attrs[] = {
477c478bd9Sstevel@tonic-gate _PWD_CN,
487c478bd9Sstevel@tonic-gate _PWD_UID,
497c478bd9Sstevel@tonic-gate _PWD_UIDNUMBER,
507c478bd9Sstevel@tonic-gate _PWD_GIDNUMBER,
517c478bd9Sstevel@tonic-gate _PWD_GECOS,
527c478bd9Sstevel@tonic-gate _PWD_DESCRIPTION,
537c478bd9Sstevel@tonic-gate _PWD_HOMEDIRECTORY,
547c478bd9Sstevel@tonic-gate _PWD_LOGINSHELL,
557c478bd9Sstevel@tonic-gate (char *)NULL
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /*
59cb5caa98Sdjl * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY
607c478bd9Sstevel@tonic-gate * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
617c478bd9Sstevel@tonic-gate * called after a successful ldap search has been performed. This method will
62cb5caa98Sdjl * parse the ldap search values into the file format.
63cb5caa98Sdjl * e.g.
64cb5caa98Sdjl *
65cb5caa98Sdjl * nobody:x:60001:60001:Nobody:/:
66cb5caa98Sdjl *
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate static int
_nss_ldap_passwd2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)69cb5caa98Sdjl _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate int nss_result;
72cb5caa98Sdjl int buflen = 0;
73cb5caa98Sdjl unsigned long str_len = 0L;
74cb5caa98Sdjl char *buffer = NULL;
757c478bd9Sstevel@tonic-gate ns_ldap_result_t *result = be->result;
76cb5caa98Sdjl ns_ldap_entry_t *entry;
77cb5caa98Sdjl char **uid_v, **uidn_v, **gidn_v;
78cb5caa98Sdjl char **gecos_v, **homedir_v, **shell_v;
79cb5caa98Sdjl char *NULL_STR = "";
80*2b4a7802SBaban Kenkre char uid_nobody[NOBODY_STR_LEN];
81*2b4a7802SBaban Kenkre char gid_nobody[NOBODY_STR_LEN], *end;
82*2b4a7802SBaban Kenkre char *uid_nobody_v[1], *gid_nobody_v[1];
83*2b4a7802SBaban Kenkre
84*2b4a7802SBaban Kenkre (void) snprintf(uid_nobody, sizeof (uid_nobody), "%u", UID_NOBODY);
85*2b4a7802SBaban Kenkre uid_nobody_v[0] = uid_nobody;
86*2b4a7802SBaban Kenkre (void) snprintf(gid_nobody, sizeof (gid_nobody), "%u", GID_NOBODY);
87*2b4a7802SBaban Kenkre gid_nobody_v[0] = gid_nobody;
887c478bd9Sstevel@tonic-gate
89cb5caa98Sdjl if (result == NULL)
90cb5caa98Sdjl return (NSS_STR_PARSE_PARSE);
917c478bd9Sstevel@tonic-gate
92cb5caa98Sdjl entry = result->entry;
93cb5caa98Sdjl
94cb5caa98Sdjl buflen = argp->buf.buflen;
957c478bd9Sstevel@tonic-gate buffer = argp->buf.buffer;
967c478bd9Sstevel@tonic-gate
97cb5caa98Sdjl nss_result = NSS_STR_PARSE_SUCCESS;
987c478bd9Sstevel@tonic-gate (void) memset(buffer, 0, buflen);
997c478bd9Sstevel@tonic-gate
100cb5caa98Sdjl /* 8 = 6 ':' + 1 '\0' + 1 'x' */
101cb5caa98Sdjl buflen -= 8;
1027c478bd9Sstevel@tonic-gate
103cb5caa98Sdjl uid_v = __ns_ldap_getAttr(entry, _PWD_UID);
104cb5caa98Sdjl uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER);
105cb5caa98Sdjl gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER);
106cb5caa98Sdjl if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL ||
107cb5caa98Sdjl uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) {
108cb5caa98Sdjl nss_result = NSS_STR_PARSE_PARSE;
109cb5caa98Sdjl goto result_pwd2str;
110cb5caa98Sdjl }
111*2b4a7802SBaban Kenkre /* Validate UID and GID */
112*2b4a7802SBaban Kenkre if (strtoul(uidn_v[0], &end, 10) > MAXUID)
113*2b4a7802SBaban Kenkre uidn_v = uid_nobody_v;
114*2b4a7802SBaban Kenkre if (strtoul(gidn_v[0], &end, 10) > MAXUID)
115*2b4a7802SBaban Kenkre gidn_v = gid_nobody_v;
116cb5caa98Sdjl str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]);
117cb5caa98Sdjl if (str_len > buflen) {
118cb5caa98Sdjl nss_result = NSS_STR_PARSE_ERANGE;
119cb5caa98Sdjl goto result_pwd2str;
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate
122cb5caa98Sdjl gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS);
123cb5caa98Sdjl if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
124cb5caa98Sdjl gecos_v = &NULL_STR;
125cb5caa98Sdjl else
126cb5caa98Sdjl str_len += strlen(gecos_v[0]);
1277c478bd9Sstevel@tonic-gate
128cb5caa98Sdjl homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY);
129cb5caa98Sdjl if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
130cb5caa98Sdjl homedir_v = &NULL_STR;
131cb5caa98Sdjl else
132cb5caa98Sdjl str_len += strlen(homedir_v[0]);
133cb5caa98Sdjl
134cb5caa98Sdjl shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL);
135cb5caa98Sdjl if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
136cb5caa98Sdjl shell_v = &NULL_STR;
137cb5caa98Sdjl else
138cb5caa98Sdjl str_len += strlen(shell_v[0]);
139cb5caa98Sdjl
140cb5caa98Sdjl if (str_len > buflen) {
141cb5caa98Sdjl nss_result = NSS_STR_PARSE_ERANGE;
142cb5caa98Sdjl goto result_pwd2str;
1437c478bd9Sstevel@tonic-gate }
144cb5caa98Sdjl
145cb5caa98Sdjl if (argp->buf.result != NULL) {
146cb5caa98Sdjl be->buflen = str_len + 8;
147cb5caa98Sdjl be->buffer = malloc(be->buflen);
148cb5caa98Sdjl if (be->buffer == NULL) {
1497c478bd9Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE;
150cb5caa98Sdjl goto result_pwd2str;
1517c478bd9Sstevel@tonic-gate }
152cb5caa98Sdjl
153cb5caa98Sdjl (void) snprintf(be->buffer, be->buflen,
154cb5caa98Sdjl "%s:%s:%s:%s:%s:%s:%s",
155cb5caa98Sdjl uid_v[0], "x", uidn_v[0], gidn_v[0],
156cb5caa98Sdjl gecos_v[0], homedir_v[0], shell_v[0]);
1577c478bd9Sstevel@tonic-gate } else {
158cb5caa98Sdjl (void) snprintf(argp->buf.buffer, (str_len + 8),
159cb5caa98Sdjl "%s:%s:%s:%s:%s:%s:%s",
160cb5caa98Sdjl uid_v[0], "x", uidn_v[0], gidn_v[0],
161cb5caa98Sdjl gecos_v[0], homedir_v[0], shell_v[0]);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate
164cb5caa98Sdjl result_pwd2str:
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
1677c478bd9Sstevel@tonic-gate return ((int)nss_result);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate * getbyname gets a passwd entry by uid name. This function constructs an ldap
1727c478bd9Sstevel@tonic-gate * search filter using the name invocation parameter and the getpwnam search
1737c478bd9Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching
1747c478bd9Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend
1757c478bd9Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling.
1767c478bd9Sstevel@tonic-gate */
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate static nss_status_t
getbyname(ldap_backend_ptr be,void * a)1797c478bd9Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
1827c478bd9Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
1837c478bd9Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
1847c478bd9Sstevel@tonic-gate char name[SEARCHFILTERLEN];
1857c478bd9Sstevel@tonic-gate int ret;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
1887c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name);
1917c478bd9Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
1927c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name);
1957c478bd9Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
1967c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
199*2b4a7802SBaban Kenkre _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate * getbyuid gets a passwd entry by uid number. This function constructs an ldap
2057c478bd9Sstevel@tonic-gate * search filter using the uid invocation parameter and the getpwuid search
2067c478bd9Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching
2077c478bd9Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend
2087c478bd9Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling.
2097c478bd9Sstevel@tonic-gate */
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate static nss_status_t
getbyuid(ldap_backend_ptr be,void * a)2127c478bd9Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2157c478bd9Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
2167c478bd9Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
2177c478bd9Sstevel@tonic-gate int ret;
2187c478bd9Sstevel@tonic-gate
219*2b4a7802SBaban Kenkre if (argp->key.uid > MAXUID)
220*2b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND);
221*2b4a7802SBaban Kenkre
2227c478bd9Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter),
2237c478bd9Sstevel@tonic-gate _F_GETPWUID, (long)argp->key.uid);
2247c478bd9Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
2257c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata),
2287c478bd9Sstevel@tonic-gate _F_GETPWUID_SSD, (long)argp->key.uid);
2297c478bd9Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
2307c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
233*2b4a7802SBaban Kenkre _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = {
2377c478bd9Sstevel@tonic-gate _nss_ldap_destr,
2387c478bd9Sstevel@tonic-gate _nss_ldap_endent,
2397c478bd9Sstevel@tonic-gate _nss_ldap_setent,
2407c478bd9Sstevel@tonic-gate _nss_ldap_getent,
2417c478bd9Sstevel@tonic-gate getbyname,
2427c478bd9Sstevel@tonic-gate getbyuid
2437c478bd9Sstevel@tonic-gate };
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate * _nss_ldap_passwd_constr is where life begins. This function calls the
2487c478bd9Sstevel@tonic-gate * generic ldap constructor function to define and build the abstract
2497c478bd9Sstevel@tonic-gate * data types required to support ldap operations.
2507c478bd9Sstevel@tonic-gate */
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
2537c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_ldap_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)2547c478bd9Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
2557c478bd9Sstevel@tonic-gate const char *dummy3)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
2597c478bd9Sstevel@tonic-gate sizeof (passwd_ops)/sizeof (passwd_ops[0]),
260cb5caa98Sdjl _PASSWD, pwd_attrs, _nss_ldap_passwd2str));
2617c478bd9Sstevel@tonic-gate }
262