xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getpwnam.c (revision 8040:42abce45ef67)
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
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * 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*8040SBaban.Kenkre@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <pwd.h>
270Sstevel@tonic-gate #include "ldap_common.h"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /* passwd attributes filters */
300Sstevel@tonic-gate #define	_PWD_CN			"cn"
310Sstevel@tonic-gate #define	_PWD_UID		"uid"
320Sstevel@tonic-gate #define	_PWD_USERPASSWORD	"userpassword"
330Sstevel@tonic-gate #define	_PWD_UIDNUMBER		"uidnumber"
340Sstevel@tonic-gate #define	_PWD_GIDNUMBER		"gidnumber"
350Sstevel@tonic-gate #define	_PWD_GECOS		"gecos"
360Sstevel@tonic-gate #define	_PWD_DESCRIPTION	"description"
370Sstevel@tonic-gate #define	_PWD_HOMEDIRECTORY	"homedirectory"
380Sstevel@tonic-gate #define	_PWD_LOGINSHELL		"loginshell"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define	_F_GETPWNAM		"(&(objectClass=posixAccount)(uid=%s))"
420Sstevel@tonic-gate #define	_F_GETPWNAM_SSD		"(&(%%s)(uid=%s))"
430Sstevel@tonic-gate #define	_F_GETPWUID		"(&(objectClass=posixAccount)(uidNumber=%ld))"
440Sstevel@tonic-gate #define	_F_GETPWUID_SSD		"(&(%%s)(uidNumber=%ld))"
450Sstevel@tonic-gate 
460Sstevel@tonic-gate static const char *pwd_attrs[] = {
470Sstevel@tonic-gate 	_PWD_CN,
480Sstevel@tonic-gate 	_PWD_UID,
490Sstevel@tonic-gate 	_PWD_UIDNUMBER,
500Sstevel@tonic-gate 	_PWD_GIDNUMBER,
510Sstevel@tonic-gate 	_PWD_GECOS,
520Sstevel@tonic-gate 	_PWD_DESCRIPTION,
530Sstevel@tonic-gate 	_PWD_HOMEDIRECTORY,
540Sstevel@tonic-gate 	_PWD_LOGINSHELL,
550Sstevel@tonic-gate 	(char *)NULL
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
592830Sdjl  * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY
600Sstevel@tonic-gate  * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
610Sstevel@tonic-gate  * called after a successful ldap search has been performed. This method will
622830Sdjl  * parse the ldap search values into the file format.
632830Sdjl  * e.g.
642830Sdjl  *
652830Sdjl  * nobody:x:60001:60001:Nobody:/:
662830Sdjl  *
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate static int
_nss_ldap_passwd2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)692830Sdjl _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	int		nss_result;
722830Sdjl 	int		buflen = 0;
732830Sdjl 	unsigned long	str_len = 0L;
742830Sdjl 	char		*buffer = NULL;
750Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
762830Sdjl 	ns_ldap_entry_t	*entry;
772830Sdjl 	char		**uid_v, **uidn_v, **gidn_v;
782830Sdjl 	char		**gecos_v, **homedir_v, **shell_v;
792830Sdjl 	char		*NULL_STR = "";
80*8040SBaban.Kenkre@Sun.COM 	char		uid_nobody[NOBODY_STR_LEN];
81*8040SBaban.Kenkre@Sun.COM 	char		gid_nobody[NOBODY_STR_LEN], *end;
82*8040SBaban.Kenkre@Sun.COM 	char		*uid_nobody_v[1], *gid_nobody_v[1];
83*8040SBaban.Kenkre@Sun.COM 
84*8040SBaban.Kenkre@Sun.COM 	(void) snprintf(uid_nobody, sizeof (uid_nobody), "%u", UID_NOBODY);
85*8040SBaban.Kenkre@Sun.COM 	uid_nobody_v[0] = uid_nobody;
86*8040SBaban.Kenkre@Sun.COM 	(void) snprintf(gid_nobody, sizeof (gid_nobody), "%u", GID_NOBODY);
87*8040SBaban.Kenkre@Sun.COM 	gid_nobody_v[0] = gid_nobody;
880Sstevel@tonic-gate 
892830Sdjl 	if (result == NULL)
902830Sdjl 		return (NSS_STR_PARSE_PARSE);
910Sstevel@tonic-gate 
922830Sdjl 	entry = result->entry;
932830Sdjl 
942830Sdjl 	buflen = argp->buf.buflen;
950Sstevel@tonic-gate 	buffer = argp->buf.buffer;
960Sstevel@tonic-gate 
972830Sdjl 	nss_result = NSS_STR_PARSE_SUCCESS;
980Sstevel@tonic-gate 	(void) memset(buffer, 0, buflen);
990Sstevel@tonic-gate 
1002830Sdjl 	/* 8 = 6 ':' + 1 '\0' + 1 'x' */
1012830Sdjl 	buflen -=  8;
1020Sstevel@tonic-gate 
1032830Sdjl 	uid_v = __ns_ldap_getAttr(entry, _PWD_UID);
1042830Sdjl 	uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER);
1052830Sdjl 	gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER);
1062830Sdjl 	if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL ||
107*8040SBaban.Kenkre@Sun.COM 	    uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) {
1082830Sdjl 		nss_result = NSS_STR_PARSE_PARSE;
1092830Sdjl 		goto result_pwd2str;
1102830Sdjl 	}
111*8040SBaban.Kenkre@Sun.COM 	/* Validate UID and GID */
112*8040SBaban.Kenkre@Sun.COM 	if (strtoul(uidn_v[0], &end, 10) > MAXUID)
113*8040SBaban.Kenkre@Sun.COM 		uidn_v = uid_nobody_v;
114*8040SBaban.Kenkre@Sun.COM 	if (strtoul(gidn_v[0], &end, 10) > MAXUID)
115*8040SBaban.Kenkre@Sun.COM 		gidn_v = gid_nobody_v;
1162830Sdjl 	str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]);
1172830Sdjl 	if (str_len >  buflen) {
1182830Sdjl 		nss_result = NSS_STR_PARSE_ERANGE;
1192830Sdjl 		goto result_pwd2str;
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 
1222830Sdjl 	gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS);
1232830Sdjl 	if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
1242830Sdjl 		gecos_v = &NULL_STR;
1252830Sdjl 	else
1262830Sdjl 		str_len += strlen(gecos_v[0]);
1270Sstevel@tonic-gate 
1282830Sdjl 	homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY);
1292830Sdjl 	if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
1302830Sdjl 		homedir_v = &NULL_STR;
1312830Sdjl 	else
1322830Sdjl 		str_len += strlen(homedir_v[0]);
1332830Sdjl 
1342830Sdjl 	shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL);
1352830Sdjl 	if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
1362830Sdjl 		shell_v = &NULL_STR;
1372830Sdjl 	else
1382830Sdjl 		str_len += strlen(shell_v[0]);
1392830Sdjl 
1402830Sdjl 	if (str_len >  buflen) {
1412830Sdjl 		nss_result = NSS_STR_PARSE_ERANGE;
1422830Sdjl 		goto result_pwd2str;
1430Sstevel@tonic-gate 	}
1440Sstevel@tonic-gate 
1452830Sdjl 	if (argp->buf.result != NULL) {
1462830Sdjl 		be->buflen = str_len + 8;
1472830Sdjl 		be->buffer = malloc(be->buflen);
1482830Sdjl 		if (be->buffer == NULL) {
1492830Sdjl 			nss_result = (int)NSS_STR_PARSE_ERANGE;
1502830Sdjl 			goto result_pwd2str;
1512830Sdjl 		}
1522830Sdjl 
1532830Sdjl 		(void) snprintf(be->buffer, be->buflen,
154*8040SBaban.Kenkre@Sun.COM 		    "%s:%s:%s:%s:%s:%s:%s",
155*8040SBaban.Kenkre@Sun.COM 		    uid_v[0], "x", uidn_v[0], gidn_v[0],
156*8040SBaban.Kenkre@Sun.COM 		    gecos_v[0], homedir_v[0], shell_v[0]);
1572830Sdjl 	} else {
1582830Sdjl 		(void) snprintf(argp->buf.buffer, (str_len + 8),
159*8040SBaban.Kenkre@Sun.COM 		    "%s:%s:%s:%s:%s:%s:%s",
160*8040SBaban.Kenkre@Sun.COM 		    uid_v[0], "x", uidn_v[0], gidn_v[0],
161*8040SBaban.Kenkre@Sun.COM 		    gecos_v[0], homedir_v[0], shell_v[0]);
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 
1642830Sdjl result_pwd2str:
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
1670Sstevel@tonic-gate 	return ((int)nss_result);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate  * getbyname gets a passwd entry by uid name. This function constructs an ldap
1720Sstevel@tonic-gate  * search filter using the name invocation parameter and the getpwnam search
1730Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we search for a matching
1740Sstevel@tonic-gate  * entry and marshal the data results into struct passwd for the frontend
1750Sstevel@tonic-gate  * process. The function _nss_ldap_passwd2ent performs the data marshaling.
1760Sstevel@tonic-gate  */
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate static nss_status_t
getbyname(ldap_backend_ptr be,void * a)1790Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
1800Sstevel@tonic-gate {
1810Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
1820Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
1830Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
1840Sstevel@tonic-gate 	char		name[SEARCHFILTERLEN];
1850Sstevel@tonic-gate 	int		ret;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
1880Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name);
1910Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
1920Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name);
1950Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
1960Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
199*8040SBaban.Kenkre@Sun.COM 	    _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate  * getbyuid gets a passwd entry by uid number. This function constructs an ldap
2050Sstevel@tonic-gate  * search filter using the uid invocation parameter and the getpwuid search
2060Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we search for a matching
2070Sstevel@tonic-gate  * entry and marshal the data results into struct passwd for the frontend
2080Sstevel@tonic-gate  * process. The function _nss_ldap_passwd2ent performs the data marshaling.
2090Sstevel@tonic-gate  */
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate static nss_status_t
getbyuid(ldap_backend_ptr be,void * a)2120Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2150Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
2160Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
2170Sstevel@tonic-gate 	int		ret;
2180Sstevel@tonic-gate 
219*8040SBaban.Kenkre@Sun.COM 	if (argp->key.uid > MAXUID)
220*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
221*8040SBaban.Kenkre@Sun.COM 
2220Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
2230Sstevel@tonic-gate 	    _F_GETPWUID, (long)argp->key.uid);
2240Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
2250Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata),
2280Sstevel@tonic-gate 	    _F_GETPWUID_SSD, (long)argp->key.uid);
2290Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
2300Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
233*8040SBaban.Kenkre@Sun.COM 	    _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata));
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = {
2370Sstevel@tonic-gate 	_nss_ldap_destr,
2380Sstevel@tonic-gate 	_nss_ldap_endent,
2390Sstevel@tonic-gate 	_nss_ldap_setent,
2400Sstevel@tonic-gate 	_nss_ldap_getent,
2410Sstevel@tonic-gate 	getbyname,
2420Sstevel@tonic-gate 	getbyuid
2430Sstevel@tonic-gate };
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate  * _nss_ldap_passwd_constr is where life begins. This function calls the
2480Sstevel@tonic-gate  * generic ldap constructor function to define and build the abstract
2490Sstevel@tonic-gate  * data types required to support ldap operations.
2500Sstevel@tonic-gate  */
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate /*ARGSUSED0*/
2530Sstevel@tonic-gate nss_backend_t *
_nss_ldap_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)2540Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2,
2550Sstevel@tonic-gate 			const char *dummy3)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(passwd_ops,
259*8040SBaban.Kenkre@Sun.COM 	    sizeof (passwd_ops)/sizeof (passwd_ops[0]),
260*8040SBaban.Kenkre@Sun.COM 	    _PASSWD, pwd_attrs, _nss_ldap_passwd2str));
2610Sstevel@tonic-gate }
262