10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2830Sdjl  * Common Development and Distribution License (the "License").
6*2830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2830Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <pwd.h>
290Sstevel@tonic-gate #include "ldap_common.h"
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /* passwd attributes filters */
320Sstevel@tonic-gate #define	_PWD_CN			"cn"
330Sstevel@tonic-gate #define	_PWD_UID		"uid"
340Sstevel@tonic-gate #define	_PWD_USERPASSWORD	"userpassword"
350Sstevel@tonic-gate #define	_PWD_UIDNUMBER		"uidnumber"
360Sstevel@tonic-gate #define	_PWD_GIDNUMBER		"gidnumber"
370Sstevel@tonic-gate #define	_PWD_GECOS		"gecos"
380Sstevel@tonic-gate #define	_PWD_DESCRIPTION	"description"
390Sstevel@tonic-gate #define	_PWD_HOMEDIRECTORY	"homedirectory"
400Sstevel@tonic-gate #define	_PWD_LOGINSHELL		"loginshell"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #define	_F_GETPWNAM		"(&(objectClass=posixAccount)(uid=%s))"
440Sstevel@tonic-gate #define	_F_GETPWNAM_SSD		"(&(%%s)(uid=%s))"
450Sstevel@tonic-gate #define	_F_GETPWUID		"(&(objectClass=posixAccount)(uidNumber=%ld))"
460Sstevel@tonic-gate #define	_F_GETPWUID_SSD		"(&(%%s)(uidNumber=%ld))"
470Sstevel@tonic-gate 
480Sstevel@tonic-gate static const char *pwd_attrs[] = {
490Sstevel@tonic-gate 	_PWD_CN,
500Sstevel@tonic-gate 	_PWD_UID,
510Sstevel@tonic-gate 	_PWD_UIDNUMBER,
520Sstevel@tonic-gate 	_PWD_GIDNUMBER,
530Sstevel@tonic-gate 	_PWD_GECOS,
540Sstevel@tonic-gate 	_PWD_DESCRIPTION,
550Sstevel@tonic-gate 	_PWD_HOMEDIRECTORY,
560Sstevel@tonic-gate 	_PWD_LOGINSHELL,
570Sstevel@tonic-gate 	(char *)NULL
580Sstevel@tonic-gate };
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
61*2830Sdjl  * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY
620Sstevel@tonic-gate  * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
630Sstevel@tonic-gate  * called after a successful ldap search has been performed. This method will
64*2830Sdjl  * parse the ldap search values into the file format.
65*2830Sdjl  * e.g.
66*2830Sdjl  *
67*2830Sdjl  * nobody:x:60001:60001:Nobody:/:
68*2830Sdjl  *
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate static int
71*2830Sdjl _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
720Sstevel@tonic-gate {
730Sstevel@tonic-gate 	int		nss_result;
74*2830Sdjl 	int		buflen = 0;
75*2830Sdjl 	unsigned long	str_len = 0L;
76*2830Sdjl 	char		*buffer = NULL;
770Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
78*2830Sdjl 	ns_ldap_entry_t	*entry;
79*2830Sdjl 	char		**uid_v, **uidn_v, **gidn_v;
80*2830Sdjl 	char		**gecos_v, **homedir_v, **shell_v;
81*2830Sdjl 	char		*NULL_STR = "";
820Sstevel@tonic-gate 
83*2830Sdjl 	if (result == NULL)
84*2830Sdjl 		return (NSS_STR_PARSE_PARSE);
850Sstevel@tonic-gate 
86*2830Sdjl 	entry = result->entry;
87*2830Sdjl 
88*2830Sdjl 	buflen = argp->buf.buflen;
890Sstevel@tonic-gate 	buffer = argp->buf.buffer;
900Sstevel@tonic-gate 
91*2830Sdjl 	nss_result = NSS_STR_PARSE_SUCCESS;
920Sstevel@tonic-gate 	(void) memset(buffer, 0, buflen);
930Sstevel@tonic-gate 
94*2830Sdjl 	/* 8 = 6 ':' + 1 '\0' + 1 'x' */
95*2830Sdjl 	buflen -=  8;
960Sstevel@tonic-gate 
97*2830Sdjl 	uid_v = __ns_ldap_getAttr(entry, _PWD_UID);
98*2830Sdjl 	uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER);
99*2830Sdjl 	gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER);
100*2830Sdjl 	if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL ||
101*2830Sdjl 		uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) {
102*2830Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
103*2830Sdjl 		goto result_pwd2str;
104*2830Sdjl 	}
105*2830Sdjl 	str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]);
106*2830Sdjl 	if (str_len >  buflen) {
107*2830Sdjl 		nss_result = NSS_STR_PARSE_ERANGE;
108*2830Sdjl 		goto result_pwd2str;
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 
111*2830Sdjl 	gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS);
112*2830Sdjl 	if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
113*2830Sdjl 		gecos_v = &NULL_STR;
114*2830Sdjl 	else
115*2830Sdjl 		str_len += strlen(gecos_v[0]);
1160Sstevel@tonic-gate 
117*2830Sdjl 	homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY);
118*2830Sdjl 	if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
119*2830Sdjl 		homedir_v = &NULL_STR;
120*2830Sdjl 	else
121*2830Sdjl 		str_len += strlen(homedir_v[0]);
122*2830Sdjl 
123*2830Sdjl 	shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL);
124*2830Sdjl 	if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
125*2830Sdjl 		shell_v = &NULL_STR;
126*2830Sdjl 	else
127*2830Sdjl 		str_len += strlen(shell_v[0]);
128*2830Sdjl 
129*2830Sdjl 	if (str_len >  buflen) {
130*2830Sdjl 		nss_result = NSS_STR_PARSE_ERANGE;
131*2830Sdjl 		goto result_pwd2str;
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 
134*2830Sdjl 	if (argp->buf.result != NULL) {
135*2830Sdjl 		be->buflen = str_len + 8;
136*2830Sdjl 		be->buffer = malloc(be->buflen);
137*2830Sdjl 		if (be->buffer == NULL) {
138*2830Sdjl 			nss_result = (int)NSS_STR_PARSE_ERANGE;
139*2830Sdjl 			goto result_pwd2str;
140*2830Sdjl 		}
141*2830Sdjl 
142*2830Sdjl 		(void) snprintf(be->buffer, be->buflen,
143*2830Sdjl 				"%s:%s:%s:%s:%s:%s:%s",
144*2830Sdjl 			uid_v[0], "x", uidn_v[0], gidn_v[0],
145*2830Sdjl 			gecos_v[0], homedir_v[0], shell_v[0]);
146*2830Sdjl 	} else {
147*2830Sdjl 		(void) snprintf(argp->buf.buffer, (str_len + 8),
148*2830Sdjl 				"%s:%s:%s:%s:%s:%s:%s",
149*2830Sdjl 			uid_v[0], "x", uidn_v[0], gidn_v[0],
150*2830Sdjl 			gecos_v[0], homedir_v[0], shell_v[0]);
151*2830Sdjl 
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 
154*2830Sdjl result_pwd2str:
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1570Sstevel@tonic-gate 	return ((int)nss_result);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate  * getbyname gets a passwd entry by uid name. This function constructs an ldap
1620Sstevel@tonic-gate  * search filter using the name invocation parameter and the getpwnam search
1630Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we search for a matching
1640Sstevel@tonic-gate  * entry and marshal the data results into struct passwd for the frontend
1650Sstevel@tonic-gate  * process. The function _nss_ldap_passwd2ent performs the data marshaling.
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static nss_status_t
1690Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
1720Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
1730Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
1740Sstevel@tonic-gate 	char		name[SEARCHFILTERLEN];
1750Sstevel@tonic-gate 	int		ret;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
1780Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name);
1810Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
1820Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name);
1850Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
1860Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
1890Sstevel@tonic-gate 		_PASSWD, searchfilter, NULL,
1900Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate /*
1950Sstevel@tonic-gate  * getbyuid gets a passwd entry by uid number. This function constructs an ldap
1960Sstevel@tonic-gate  * search filter using the uid invocation parameter and the getpwuid search
1970Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we search for a matching
1980Sstevel@tonic-gate  * entry and marshal the data results into struct passwd for the frontend
1990Sstevel@tonic-gate  * process. The function _nss_ldap_passwd2ent performs the data marshaling.
2000Sstevel@tonic-gate  */
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate static nss_status_t
2030Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2060Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
2070Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
2080Sstevel@tonic-gate 	int		ret;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
2110Sstevel@tonic-gate 	    _F_GETPWUID, (long)argp->key.uid);
2120Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
2130Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata),
2160Sstevel@tonic-gate 	    _F_GETPWUID_SSD, (long)argp->key.uid);
2170Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
2180Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
2210Sstevel@tonic-gate 		_PASSWD, searchfilter, NULL,
2220Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = {
2260Sstevel@tonic-gate 	_nss_ldap_destr,
2270Sstevel@tonic-gate 	_nss_ldap_endent,
2280Sstevel@tonic-gate 	_nss_ldap_setent,
2290Sstevel@tonic-gate 	_nss_ldap_getent,
2300Sstevel@tonic-gate 	getbyname,
2310Sstevel@tonic-gate 	getbyuid
2320Sstevel@tonic-gate };
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate  * _nss_ldap_passwd_constr is where life begins. This function calls the
2370Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract
2380Sstevel@tonic-gate  * data types required to support ldap operations.
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate /*ARGSUSED0*/
2420Sstevel@tonic-gate nss_backend_t *
2430Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
2440Sstevel@tonic-gate 			const char *dummy3)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
2480Sstevel@tonic-gate 		    sizeof (passwd_ops)/sizeof (passwd_ops[0]),
249*2830Sdjl 		    _PASSWD, pwd_attrs, _nss_ldap_passwd2str));
2500Sstevel@tonic-gate }
251