xref: /onnv-gate/usr/src/lib/nsswitch/ad/common/getpwnam.c (revision 12914:e95332bf1454)
18040SBaban.Kenkre@Sun.COM /*
28040SBaban.Kenkre@Sun.COM  * CDDL HEADER START
38040SBaban.Kenkre@Sun.COM  *
48040SBaban.Kenkre@Sun.COM  * The contents of this file are subject to the terms of the
58040SBaban.Kenkre@Sun.COM  * Common Development and Distribution License (the "License").
68040SBaban.Kenkre@Sun.COM  * You may not use this file except in compliance with the License.
78040SBaban.Kenkre@Sun.COM  *
88040SBaban.Kenkre@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98040SBaban.Kenkre@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108040SBaban.Kenkre@Sun.COM  * See the License for the specific language governing permissions
118040SBaban.Kenkre@Sun.COM  * and limitations under the License.
128040SBaban.Kenkre@Sun.COM  *
138040SBaban.Kenkre@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148040SBaban.Kenkre@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158040SBaban.Kenkre@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168040SBaban.Kenkre@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178040SBaban.Kenkre@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188040SBaban.Kenkre@Sun.COM  *
198040SBaban.Kenkre@Sun.COM  * CDDL HEADER END
208040SBaban.Kenkre@Sun.COM  */
218040SBaban.Kenkre@Sun.COM /*
22*12914SJoyce.McIntosh@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
238040SBaban.Kenkre@Sun.COM  */
248040SBaban.Kenkre@Sun.COM 
258040SBaban.Kenkre@Sun.COM #include <pwd.h>
268040SBaban.Kenkre@Sun.COM #include <idmap.h>
278040SBaban.Kenkre@Sun.COM #include <ctype.h>
288040SBaban.Kenkre@Sun.COM #include "ad_common.h"
298040SBaban.Kenkre@Sun.COM 
308040SBaban.Kenkre@Sun.COM /* passwd attributes and filters */
318040SBaban.Kenkre@Sun.COM #define	_PWD_DN			"dn"
328040SBaban.Kenkre@Sun.COM #define	_PWD_SAN		"sAMAccountName"
338040SBaban.Kenkre@Sun.COM #define	_PWD_OBJSID		"objectSid"
348040SBaban.Kenkre@Sun.COM #define	_PWD_PRIMARYGROUPID	"primaryGroupID"
358040SBaban.Kenkre@Sun.COM #define	_PWD_CN			"cn"
368040SBaban.Kenkre@Sun.COM #define	_PWD_HOMEDIRECTORY	"homedirectory"
378040SBaban.Kenkre@Sun.COM #define	_PWD_LOGINSHELL		"loginshell"
388040SBaban.Kenkre@Sun.COM #define	_PWD_OBJCLASS		"objectClass"
398040SBaban.Kenkre@Sun.COM 
408040SBaban.Kenkre@Sun.COM #define	_F_GETPWNAM		"(sAMAccountName=%.*s)"
418040SBaban.Kenkre@Sun.COM #define	_F_GETPWUID		"(objectSid=%s)"
428040SBaban.Kenkre@Sun.COM 
438040SBaban.Kenkre@Sun.COM static const char *pwd_attrs[] = {
448040SBaban.Kenkre@Sun.COM 	_PWD_SAN,
458040SBaban.Kenkre@Sun.COM 	_PWD_OBJSID,
468040SBaban.Kenkre@Sun.COM 	_PWD_PRIMARYGROUPID,
478040SBaban.Kenkre@Sun.COM 	_PWD_CN,
488040SBaban.Kenkre@Sun.COM 	_PWD_HOMEDIRECTORY,
498040SBaban.Kenkre@Sun.COM 	_PWD_LOGINSHELL,
508040SBaban.Kenkre@Sun.COM 	_PWD_OBJCLASS,
518040SBaban.Kenkre@Sun.COM 	(char *)NULL
528040SBaban.Kenkre@Sun.COM };
538040SBaban.Kenkre@Sun.COM 
548040SBaban.Kenkre@Sun.COM static int
update_buffer(ad_backend_ptr be,nss_XbyY_args_t * argp,const char * name,const char * domain,uid_t uid,gid_t gid,const char * gecos,const char * homedir,const char * shell)558040SBaban.Kenkre@Sun.COM update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp,
568040SBaban.Kenkre@Sun.COM 		const char *name, const char *domain,
578040SBaban.Kenkre@Sun.COM 		uid_t uid, gid_t gid, const char *gecos,
588040SBaban.Kenkre@Sun.COM 		const char *homedir, const char *shell)
598040SBaban.Kenkre@Sun.COM {
608040SBaban.Kenkre@Sun.COM 	int	buflen;
618040SBaban.Kenkre@Sun.COM 	char	*buffer;
628040SBaban.Kenkre@Sun.COM 
638040SBaban.Kenkre@Sun.COM 	if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) {
648040SBaban.Kenkre@Sun.COM 		/*
658040SBaban.Kenkre@Sun.COM 		 * The canonical name obtained from AD lookup may not match
668040SBaban.Kenkre@Sun.COM 		 * the case of the name (i.e. key) in the request. Therefore,
678040SBaban.Kenkre@Sun.COM 		 * use the name from the request to construct the result.
688040SBaban.Kenkre@Sun.COM 		 */
698040SBaban.Kenkre@Sun.COM 		buflen = snprintf(NULL, 0, "%s:%s:%u:%u:%s:%s:%s",
708040SBaban.Kenkre@Sun.COM 		    argp->key.name, "x", uid, gid, gecos, homedir, shell) + 1;
718040SBaban.Kenkre@Sun.COM 	} else {
728040SBaban.Kenkre@Sun.COM 		if (domain == NULL)
738040SBaban.Kenkre@Sun.COM 			domain = WK_DOMAIN;
748040SBaban.Kenkre@Sun.COM 		buflen = snprintf(NULL, 0, "%s@%s:%s:%u:%u:%s:%s:%s",
758040SBaban.Kenkre@Sun.COM 		    name, domain, "x", uid, gid, gecos, homedir, shell) + 1;
768040SBaban.Kenkre@Sun.COM 	}
778040SBaban.Kenkre@Sun.COM 
788040SBaban.Kenkre@Sun.COM 
798040SBaban.Kenkre@Sun.COM 	if (argp->buf.result != NULL) {
808040SBaban.Kenkre@Sun.COM 		buffer = be->buffer = malloc(buflen);
818040SBaban.Kenkre@Sun.COM 		if (be->buffer == NULL)
828040SBaban.Kenkre@Sun.COM 			return (-1);
838040SBaban.Kenkre@Sun.COM 		be->buflen = buflen;
848040SBaban.Kenkre@Sun.COM 	} else {
858040SBaban.Kenkre@Sun.COM 		if (buflen > argp->buf.buflen)
868040SBaban.Kenkre@Sun.COM 			return (-1);
878040SBaban.Kenkre@Sun.COM 		buflen = argp->buf.buflen;
888040SBaban.Kenkre@Sun.COM 		buffer = argp->buf.buffer;
898040SBaban.Kenkre@Sun.COM 	}
908040SBaban.Kenkre@Sun.COM 
918040SBaban.Kenkre@Sun.COM 	if (be->db_type == NSS_AD_DB_PASSWD_BYNAME)
928040SBaban.Kenkre@Sun.COM 		(void) snprintf(buffer, buflen, "%s:%s:%u:%u:%s:%s:%s",
938040SBaban.Kenkre@Sun.COM 		    argp->key.name, "x", uid, gid, gecos, homedir, shell);
948040SBaban.Kenkre@Sun.COM 	else
958040SBaban.Kenkre@Sun.COM 		(void) snprintf(buffer, buflen, "%s@%s:%s:%u:%u:%s:%s:%s",
968040SBaban.Kenkre@Sun.COM 		    name, domain, "x", uid, gid, gecos, homedir, shell);
978040SBaban.Kenkre@Sun.COM 	return (0);
988040SBaban.Kenkre@Sun.COM }
998040SBaban.Kenkre@Sun.COM 
1008040SBaban.Kenkre@Sun.COM 
1018040SBaban.Kenkre@Sun.COM #define	NET_SCHEME	"/net"
1028040SBaban.Kenkre@Sun.COM 
1038040SBaban.Kenkre@Sun.COM /*
1048040SBaban.Kenkre@Sun.COM  * 1) If the homeDirectory string is in UNC format then convert it into
1058040SBaban.Kenkre@Sun.COM  * a /net format. This needs to be revisited later but is fine for now
1068040SBaban.Kenkre@Sun.COM  * because Solaris does not support -hosts automount map for CIFS yet.
1078040SBaban.Kenkre@Sun.COM  *
1088040SBaban.Kenkre@Sun.COM  * 2) If homeDirectory contains ':' then return NULL because ':' is the
1098040SBaban.Kenkre@Sun.COM  * delimiter in passwd entries and may break apps that parse these entries.
1108040SBaban.Kenkre@Sun.COM  *
1118040SBaban.Kenkre@Sun.COM  * 3) For all other cases return the same string that was passed to
1128040SBaban.Kenkre@Sun.COM  * this function.
1138040SBaban.Kenkre@Sun.COM  */
1148040SBaban.Kenkre@Sun.COM static
1158040SBaban.Kenkre@Sun.COM char *
process_homedir(char * homedir)1168040SBaban.Kenkre@Sun.COM process_homedir(char *homedir)
1178040SBaban.Kenkre@Sun.COM {
1188040SBaban.Kenkre@Sun.COM 	size_t	len, smb_len;
1198040SBaban.Kenkre@Sun.COM 	char	*smb_homedir;
1208040SBaban.Kenkre@Sun.COM 	int	i, slash = 0;
1218040SBaban.Kenkre@Sun.COM 
1228040SBaban.Kenkre@Sun.COM 	len = strlen(homedir);
1238040SBaban.Kenkre@Sun.COM 
1248040SBaban.Kenkre@Sun.COM 	if (strchr(homedir, ':') != NULL)
1258040SBaban.Kenkre@Sun.COM 		/*
1268040SBaban.Kenkre@Sun.COM 		 * Ignore paths that have colon ':' because ':' is a
1278040SBaban.Kenkre@Sun.COM 		 * delimiter for the passwd entry.
1288040SBaban.Kenkre@Sun.COM 		 */
1298040SBaban.Kenkre@Sun.COM 		return (NULL);
1308040SBaban.Kenkre@Sun.COM 
1318040SBaban.Kenkre@Sun.COM 	if (!(len > 1 && homedir[0] == '\\' && homedir[1] == '\\'))
1328040SBaban.Kenkre@Sun.COM 		/* Keep homedir intact if not in UNC format */
1338040SBaban.Kenkre@Sun.COM 		return (homedir);
1348040SBaban.Kenkre@Sun.COM 
1358040SBaban.Kenkre@Sun.COM 	/*
1368040SBaban.Kenkre@Sun.COM 	 * Convert UNC string into /net format
1378040SBaban.Kenkre@Sun.COM 	 * Example: \\server\abc -> /net/server/abc
1388040SBaban.Kenkre@Sun.COM 	 */
1398040SBaban.Kenkre@Sun.COM 	smb_len = len + 1 + sizeof (NET_SCHEME);
1408040SBaban.Kenkre@Sun.COM 	if ((smb_homedir = calloc(1, smb_len)) == NULL)
1418040SBaban.Kenkre@Sun.COM 		return (NULL);
1428040SBaban.Kenkre@Sun.COM 	(void) strlcpy(smb_homedir, NET_SCHEME, smb_len);
1438040SBaban.Kenkre@Sun.COM 	for (i = strlen(smb_homedir); *homedir != '\0'; homedir++) {
1448040SBaban.Kenkre@Sun.COM 		if (*homedir == '\\') {
1458040SBaban.Kenkre@Sun.COM 			/* Reduce double backslashes into one */
1468040SBaban.Kenkre@Sun.COM 			if (slash)
1478040SBaban.Kenkre@Sun.COM 				slash = 0;
1488040SBaban.Kenkre@Sun.COM 			else {
1498040SBaban.Kenkre@Sun.COM 				slash = 1;
1508040SBaban.Kenkre@Sun.COM 				smb_homedir[i++] = '/';
1518040SBaban.Kenkre@Sun.COM 			}
1528040SBaban.Kenkre@Sun.COM 		} else {
1538040SBaban.Kenkre@Sun.COM 			smb_homedir[i++] = *homedir;
1548040SBaban.Kenkre@Sun.COM 			slash = 0;
1558040SBaban.Kenkre@Sun.COM 		}
1568040SBaban.Kenkre@Sun.COM 	}
1578040SBaban.Kenkre@Sun.COM 	return (smb_homedir);
1588040SBaban.Kenkre@Sun.COM }
1598040SBaban.Kenkre@Sun.COM 
1608040SBaban.Kenkre@Sun.COM /*
1618040SBaban.Kenkre@Sun.COM  * _nss_ad_passwd2str is the data marshaling method for the passwd getXbyY
1628040SBaban.Kenkre@Sun.COM  * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
1638040SBaban.Kenkre@Sun.COM  * called after a successful AD search has been performed. This method will
1648040SBaban.Kenkre@Sun.COM  * parse the AD search values into the file format.
1658040SBaban.Kenkre@Sun.COM  * e.g.
1668040SBaban.Kenkre@Sun.COM  *
1678040SBaban.Kenkre@Sun.COM  * blue@whale:x:123456:10:Blue Whale:/:
1688040SBaban.Kenkre@Sun.COM  *
1698040SBaban.Kenkre@Sun.COM  */
1708040SBaban.Kenkre@Sun.COM static int
_nss_ad_passwd2str(ad_backend_ptr be,nss_XbyY_args_t * argp)1718040SBaban.Kenkre@Sun.COM _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp)
1728040SBaban.Kenkre@Sun.COM {
1738040SBaban.Kenkre@Sun.COM 	int			nss_result;
1748040SBaban.Kenkre@Sun.COM 	adutils_result_t	*result = be->result;
1758040SBaban.Kenkre@Sun.COM 	const adutils_entry_t	*entry;
1768040SBaban.Kenkre@Sun.COM 	char			**sid_v, *ptr, **pgid_v, *end;
1778040SBaban.Kenkre@Sun.COM 	ulong_t			tmp;
1788040SBaban.Kenkre@Sun.COM 	uint32_t		urid, grid;
1798040SBaban.Kenkre@Sun.COM 	uid_t			uid;
1808040SBaban.Kenkre@Sun.COM 	gid_t			gid;
1818040SBaban.Kenkre@Sun.COM 	idmap_stat		gstat;
1828040SBaban.Kenkre@Sun.COM 	idmap_get_handle_t 	*ig = NULL;
1838040SBaban.Kenkre@Sun.COM 	char			**name_v, **dn_v, *domain = NULL;
1848040SBaban.Kenkre@Sun.COM 	char			**gecos_v, **shell_v;
1858040SBaban.Kenkre@Sun.COM 	char			**homedir_v = NULL, *homedir = NULL;
1868040SBaban.Kenkre@Sun.COM 	char			*NULL_STR = "";
1878040SBaban.Kenkre@Sun.COM 
1888040SBaban.Kenkre@Sun.COM 	if (result == NULL)
1898040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
1908040SBaban.Kenkre@Sun.COM 	entry = adutils_getfirstentry(result);
1918040SBaban.Kenkre@Sun.COM 	nss_result = NSS_STR_PARSE_PARSE;
1928040SBaban.Kenkre@Sun.COM 
1938040SBaban.Kenkre@Sun.COM 	/* Create handles for idmap service */
194*12914SJoyce.McIntosh@Sun.COM 	if (idmap_get_create(&ig) != 0)
1958040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
1968040SBaban.Kenkre@Sun.COM 
1978040SBaban.Kenkre@Sun.COM 	/* Get name */
1988040SBaban.Kenkre@Sun.COM 	name_v = adutils_getattr(entry, _PWD_SAN);
1998040SBaban.Kenkre@Sun.COM 	if (name_v == NULL || name_v[0] == NULL || *name_v[0] == '\0')
2008040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2018040SBaban.Kenkre@Sun.COM 
2028040SBaban.Kenkre@Sun.COM 	/* Get domain */
2038040SBaban.Kenkre@Sun.COM 	dn_v = adutils_getattr(entry, _PWD_DN);
2048040SBaban.Kenkre@Sun.COM 	if (dn_v == NULL || dn_v[0] == NULL || *dn_v[0] == '\0')
2058040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2068040SBaban.Kenkre@Sun.COM 	domain = adutils_dn2dns(dn_v[0]);
2078040SBaban.Kenkre@Sun.COM 
2088040SBaban.Kenkre@Sun.COM 	/* Get objectSID (in text format) */
2098040SBaban.Kenkre@Sun.COM 	sid_v = adutils_getattr(entry, _PWD_OBJSID);
2108040SBaban.Kenkre@Sun.COM 	if (sid_v == NULL || sid_v[0] == NULL || *sid_v[0] == '\0')
2118040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2128040SBaban.Kenkre@Sun.COM 
2138040SBaban.Kenkre@Sun.COM 	/* Break SID into prefix and rid */
2148040SBaban.Kenkre@Sun.COM 	if ((ptr = strrchr(sid_v[0], '-')) == NULL)
2158040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2168040SBaban.Kenkre@Sun.COM 	*ptr = '\0';
2178040SBaban.Kenkre@Sun.COM 	end = ++ptr;
2188040SBaban.Kenkre@Sun.COM 	tmp = strtoul(ptr, &end, 10);
2198040SBaban.Kenkre@Sun.COM 	if (end == ptr || tmp > UINT32_MAX)
2208040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2218040SBaban.Kenkre@Sun.COM 	urid = (uint32_t)tmp;
2228040SBaban.Kenkre@Sun.COM 
2238040SBaban.Kenkre@Sun.COM 	/* We already have uid -- no need to call idmapd */
2248040SBaban.Kenkre@Sun.COM 	if (be->db_type == NSS_AD_DB_PASSWD_BYUID)
2258040SBaban.Kenkre@Sun.COM 		uid = argp->key.uid;
2268040SBaban.Kenkre@Sun.COM 	else
2278040SBaban.Kenkre@Sun.COM 		uid = be->uid;
2288040SBaban.Kenkre@Sun.COM 
2298040SBaban.Kenkre@Sun.COM 	/* Get primaryGroupID */
2308040SBaban.Kenkre@Sun.COM 	pgid_v = adutils_getattr(entry, _PWD_PRIMARYGROUPID);
2318040SBaban.Kenkre@Sun.COM 	if (pgid_v == NULL || pgid_v[0] == NULL || *pgid_v[0] == '\0')
2328040SBaban.Kenkre@Sun.COM 		/*
2338040SBaban.Kenkre@Sun.COM 		 * If primaryGroupID is not found then we request
2348040SBaban.Kenkre@Sun.COM 		 * a GID to be mapped to the given user's objectSID
2358040SBaban.Kenkre@Sun.COM 		 * (diagonal mapping) and use this GID as the primary
2368040SBaban.Kenkre@Sun.COM 		 * GID for the entry.
2378040SBaban.Kenkre@Sun.COM 		 */
2388040SBaban.Kenkre@Sun.COM 		grid = urid;
2398040SBaban.Kenkre@Sun.COM 	else {
2408040SBaban.Kenkre@Sun.COM 		end = pgid_v[0];
2418040SBaban.Kenkre@Sun.COM 		tmp = strtoul(pgid_v[0], &end, 10);
2428040SBaban.Kenkre@Sun.COM 		if (end == pgid_v[0] || tmp > UINT32_MAX)
2438040SBaban.Kenkre@Sun.COM 			goto result_pwd2str;
2448040SBaban.Kenkre@Sun.COM 		grid = (uint32_t)tmp;
2458040SBaban.Kenkre@Sun.COM 	}
2468040SBaban.Kenkre@Sun.COM 
2478040SBaban.Kenkre@Sun.COM 	/* Map group SID to GID using idmap service */
2488040SBaban.Kenkre@Sun.COM 	if (idmap_get_gidbysid(ig, sid_v[0], grid, 0, &gid, &gstat) != 0)
2498040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2508040SBaban.Kenkre@Sun.COM 	if (idmap_get_mappings(ig) != 0 || gstat != 0) {
2518040SBaban.Kenkre@Sun.COM 		RESET_ERRNO();
2528040SBaban.Kenkre@Sun.COM 		goto result_pwd2str;
2538040SBaban.Kenkre@Sun.COM 	}
2548040SBaban.Kenkre@Sun.COM 
2558040SBaban.Kenkre@Sun.COM 	/* Get gecos, homedirectory and shell information if available */
2568040SBaban.Kenkre@Sun.COM 	gecos_v = adutils_getattr(entry, _PWD_CN);
2578040SBaban.Kenkre@Sun.COM 	if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
2588040SBaban.Kenkre@Sun.COM 		gecos_v = &NULL_STR;
2598040SBaban.Kenkre@Sun.COM 
2608040SBaban.Kenkre@Sun.COM 	homedir_v = adutils_getattr(entry, _PWD_HOMEDIRECTORY);
2618040SBaban.Kenkre@Sun.COM 	if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
2628040SBaban.Kenkre@Sun.COM 		homedir = NULL_STR;
2638040SBaban.Kenkre@Sun.COM 	else if ((homedir = process_homedir(homedir_v[0])) == NULL)
2648040SBaban.Kenkre@Sun.COM 		homedir = NULL_STR;
2658040SBaban.Kenkre@Sun.COM 
2668040SBaban.Kenkre@Sun.COM 	shell_v = adutils_getattr(entry, _PWD_LOGINSHELL);
2678040SBaban.Kenkre@Sun.COM 	if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
2688040SBaban.Kenkre@Sun.COM 		shell_v = &NULL_STR;
2698040SBaban.Kenkre@Sun.COM 
2708040SBaban.Kenkre@Sun.COM 	if (update_buffer(be, argp, name_v[0], domain, uid, gid,
2718040SBaban.Kenkre@Sun.COM 	    gecos_v[0], homedir, shell_v[0]) < 0)
2728040SBaban.Kenkre@Sun.COM 		nss_result = NSS_STR_PARSE_ERANGE;
2738040SBaban.Kenkre@Sun.COM 	else
2748040SBaban.Kenkre@Sun.COM 		nss_result = NSS_STR_PARSE_SUCCESS;
2758040SBaban.Kenkre@Sun.COM 
2768040SBaban.Kenkre@Sun.COM result_pwd2str:
2778040SBaban.Kenkre@Sun.COM 	idmap_get_destroy(ig);
2788040SBaban.Kenkre@Sun.COM 	(void) adutils_freeresult(&be->result);
2798040SBaban.Kenkre@Sun.COM 	free(domain);
2808040SBaban.Kenkre@Sun.COM 	if (homedir != NULL_STR && homedir_v != NULL &&
2818040SBaban.Kenkre@Sun.COM 	    homedir != homedir_v[0])
2828040SBaban.Kenkre@Sun.COM 		free(homedir);
2838040SBaban.Kenkre@Sun.COM 	return ((int)nss_result);
2848040SBaban.Kenkre@Sun.COM }
2858040SBaban.Kenkre@Sun.COM 
2868040SBaban.Kenkre@Sun.COM /*
2878040SBaban.Kenkre@Sun.COM  * getbyname gets a passwd entry by winname. This function constructs an ldap
2888040SBaban.Kenkre@Sun.COM  * search filter using the name invocation parameter and the getpwnam search
2898040SBaban.Kenkre@Sun.COM  * filter defined. Once the filter is constructed, we search for a matching
2908040SBaban.Kenkre@Sun.COM  * entry and marshal the data results into struct passwd for the frontend
2918040SBaban.Kenkre@Sun.COM  * process. The function _nss_ad_passwd2ent performs the data marshaling.
2928040SBaban.Kenkre@Sun.COM  */
2938040SBaban.Kenkre@Sun.COM 
2948040SBaban.Kenkre@Sun.COM static nss_status_t
getbyname(ad_backend_ptr be,void * a)2958040SBaban.Kenkre@Sun.COM getbyname(ad_backend_ptr be, void *a)
2968040SBaban.Kenkre@Sun.COM {
2978040SBaban.Kenkre@Sun.COM 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2988040SBaban.Kenkre@Sun.COM 	char		*searchfilter;
2998040SBaban.Kenkre@Sun.COM 	char		name[SEARCHFILTERLEN];
3008040SBaban.Kenkre@Sun.COM 	char		*dname;
3018040SBaban.Kenkre@Sun.COM 	int		filterlen, namelen;
3028040SBaban.Kenkre@Sun.COM 	int		flag;
3038040SBaban.Kenkre@Sun.COM 	nss_status_t	stat;
3048040SBaban.Kenkre@Sun.COM 	idmap_stat	idmaprc;
3058040SBaban.Kenkre@Sun.COM 	uid_t		uid;
3068040SBaban.Kenkre@Sun.COM 	gid_t		gid;
3078040SBaban.Kenkre@Sun.COM 	int		is_user, is_wuser, try_idmap;
3088040SBaban.Kenkre@Sun.COM 
3098040SBaban.Kenkre@Sun.COM 	be->db_type = NSS_AD_DB_PASSWD_BYNAME;
3108040SBaban.Kenkre@Sun.COM 
3118040SBaban.Kenkre@Sun.COM 	/* Sanitize name so that it can be used in our LDAP filter */
3128040SBaban.Kenkre@Sun.COM 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
3138040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
3148040SBaban.Kenkre@Sun.COM 
3158040SBaban.Kenkre@Sun.COM 	if ((dname = strchr(name, '@')) == NULL)
3168040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
3178040SBaban.Kenkre@Sun.COM 
3188040SBaban.Kenkre@Sun.COM 	*dname = '\0';
3198040SBaban.Kenkre@Sun.COM 	dname++;
3208040SBaban.Kenkre@Sun.COM 
3218040SBaban.Kenkre@Sun.COM 	/*
3228040SBaban.Kenkre@Sun.COM 	 * Map the given name to UID using idmap service. If idmap
3238040SBaban.Kenkre@Sun.COM 	 * call fails then this will save us doing AD discovery and
3248040SBaban.Kenkre@Sun.COM 	 * AD lookup here.
3258040SBaban.Kenkre@Sun.COM 	 */
3268040SBaban.Kenkre@Sun.COM 	flag = (strcasecmp(dname, WK_DOMAIN) == 0) ?
3278040SBaban.Kenkre@Sun.COM 	    IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0;
3288040SBaban.Kenkre@Sun.COM 	is_wuser = -1;
3298040SBaban.Kenkre@Sun.COM 	is_user = 1;
330*12914SJoyce.McIntosh@Sun.COM 	if (idmap_get_w2u_mapping(NULL, NULL, name,
3318040SBaban.Kenkre@Sun.COM 	    dname, flag, &is_user, &is_wuser, &be->uid, NULL,
3328040SBaban.Kenkre@Sun.COM 	    NULL, NULL) != IDMAP_SUCCESS) {
3338040SBaban.Kenkre@Sun.COM 		RESET_ERRNO();
3348040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
3358040SBaban.Kenkre@Sun.COM 	}
3368040SBaban.Kenkre@Sun.COM 
3378040SBaban.Kenkre@Sun.COM 	/* If this is not a Well-Known SID then try AD lookup. */
3388040SBaban.Kenkre@Sun.COM 	if (strcasecmp(dname, WK_DOMAIN) != 0) {
3398040SBaban.Kenkre@Sun.COM 		/* Assemble filter using the given name */
3408040SBaban.Kenkre@Sun.COM 		namelen = strlen(name);
3418040SBaban.Kenkre@Sun.COM 		filterlen = snprintf(NULL, 0, _F_GETPWNAM, namelen, name) + 1;
3428040SBaban.Kenkre@Sun.COM 		if ((searchfilter = (char *)malloc(filterlen)) == NULL)
3438040SBaban.Kenkre@Sun.COM 			return ((nss_status_t)NSS_NOTFOUND);
3448040SBaban.Kenkre@Sun.COM 		(void) snprintf(searchfilter, filterlen, _F_GETPWNAM,
3458040SBaban.Kenkre@Sun.COM 		    namelen, name);
3468040SBaban.Kenkre@Sun.COM 		stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
3478040SBaban.Kenkre@Sun.COM 		    dname, &try_idmap);
3488040SBaban.Kenkre@Sun.COM 		free(searchfilter);
3498040SBaban.Kenkre@Sun.COM 
350*12914SJoyce.McIntosh@Sun.COM 		if (!try_idmap)
3518040SBaban.Kenkre@Sun.COM 			return (stat);
3528040SBaban.Kenkre@Sun.COM 
3538040SBaban.Kenkre@Sun.COM 	}
3548040SBaban.Kenkre@Sun.COM 
3558040SBaban.Kenkre@Sun.COM 	/*
3568040SBaban.Kenkre@Sun.COM 	 * Either this is a Well-Known SID or AD lookup failed. Map
3578040SBaban.Kenkre@Sun.COM 	 * the given name to GID using idmap service and construct
3588040SBaban.Kenkre@Sun.COM 	 * the passwd entry.
3598040SBaban.Kenkre@Sun.COM 	 */
3608040SBaban.Kenkre@Sun.COM 	is_wuser = -1;
3618040SBaban.Kenkre@Sun.COM 	is_user = 0; /* Map name to primary gid */
362*12914SJoyce.McIntosh@Sun.COM 	idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
3638040SBaban.Kenkre@Sun.COM 	    flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
3648040SBaban.Kenkre@Sun.COM 	if (idmaprc != IDMAP_SUCCESS) {
3658040SBaban.Kenkre@Sun.COM 		RESET_ERRNO();
3668040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
3678040SBaban.Kenkre@Sun.COM 	}
3688040SBaban.Kenkre@Sun.COM 
3698040SBaban.Kenkre@Sun.COM 	/* Create passwd(4) style string */
3708040SBaban.Kenkre@Sun.COM 	if (update_buffer(be, argp, name, dname,
3718040SBaban.Kenkre@Sun.COM 	    be->uid, gid, "", "", "") < 0)
3728040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
3738040SBaban.Kenkre@Sun.COM 
3748040SBaban.Kenkre@Sun.COM 	/* Marshall the data, sanitize the return status and return */
3758040SBaban.Kenkre@Sun.COM 	stat = _nss_ad_marshall_data(be, argp);
3768040SBaban.Kenkre@Sun.COM 	return (_nss_ad_sanitize_status(be, argp, stat));
3778040SBaban.Kenkre@Sun.COM }
3788040SBaban.Kenkre@Sun.COM 
3798040SBaban.Kenkre@Sun.COM 
3808040SBaban.Kenkre@Sun.COM /*
3818040SBaban.Kenkre@Sun.COM  * getbyuid gets a passwd entry by uid number. This function constructs an ldap
3828040SBaban.Kenkre@Sun.COM  * search filter using the uid invocation parameter and the getpwuid search
3838040SBaban.Kenkre@Sun.COM  * filter defined. Once the filter is constructed, we search for a matching
3848040SBaban.Kenkre@Sun.COM  * entry and marshal the data results into struct passwd for the frontend
3858040SBaban.Kenkre@Sun.COM  * process. The function _nss_ad_passwd2ent performs the data marshaling.
3868040SBaban.Kenkre@Sun.COM  */
3878040SBaban.Kenkre@Sun.COM 
3888040SBaban.Kenkre@Sun.COM static nss_status_t
getbyuid(ad_backend_ptr be,void * a)3898040SBaban.Kenkre@Sun.COM getbyuid(ad_backend_ptr be, void *a)
3908040SBaban.Kenkre@Sun.COM {
3918040SBaban.Kenkre@Sun.COM 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
3928040SBaban.Kenkre@Sun.COM 	char			searchfilter[ADUTILS_MAXHEXBINSID + 14];
3938040SBaban.Kenkre@Sun.COM 	char			*sidprefix = NULL;
3948040SBaban.Kenkre@Sun.COM 	idmap_rid_t		rid;
3958040SBaban.Kenkre@Sun.COM 	char			cbinsid[ADUTILS_MAXHEXBINSID + 1];
3968040SBaban.Kenkre@Sun.COM 	char			*winname = NULL, *windomain = NULL;
3978040SBaban.Kenkre@Sun.COM 	int			is_user, is_wuser;
3988040SBaban.Kenkre@Sun.COM 	gid_t			gid;
3998040SBaban.Kenkre@Sun.COM 	idmap_stat		idmaprc;
4008040SBaban.Kenkre@Sun.COM 	int			ret, try_idmap;
4018040SBaban.Kenkre@Sun.COM 	nss_status_t		stat;
4028040SBaban.Kenkre@Sun.COM 
4038040SBaban.Kenkre@Sun.COM 	be->db_type = NSS_AD_DB_PASSWD_BYUID;
4048040SBaban.Kenkre@Sun.COM 
4058040SBaban.Kenkre@Sun.COM 	stat = (nss_status_t)NSS_NOTFOUND;
4068040SBaban.Kenkre@Sun.COM 
4078040SBaban.Kenkre@Sun.COM 	/* nss_ad does not support non ephemeral uids */
4088040SBaban.Kenkre@Sun.COM 	if (argp->key.uid <= MAXUID)
4098040SBaban.Kenkre@Sun.COM 		goto out;
4108040SBaban.Kenkre@Sun.COM 
4118040SBaban.Kenkre@Sun.COM 	/* Map the given UID to a SID using the idmap service */
412*12914SJoyce.McIntosh@Sun.COM 	if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0,
4138040SBaban.Kenkre@Sun.COM 	    1, NULL, &sidprefix, &rid, &winname, &windomain,
4148040SBaban.Kenkre@Sun.COM 	    NULL, NULL) != 0) {
4158040SBaban.Kenkre@Sun.COM 		RESET_ERRNO();
4168040SBaban.Kenkre@Sun.COM 		goto out;
4178040SBaban.Kenkre@Sun.COM 	}
4188040SBaban.Kenkre@Sun.COM 
4198040SBaban.Kenkre@Sun.COM 	/*
4208040SBaban.Kenkre@Sun.COM 	 * NULL winname implies a local SID or unresolvable SID both of
4218040SBaban.Kenkre@Sun.COM 	 * which cannot be used to generated passwd(4) entry
4228040SBaban.Kenkre@Sun.COM 	 */
4238040SBaban.Kenkre@Sun.COM 	if (winname == NULL)
4248040SBaban.Kenkre@Sun.COM 		goto out;
4258040SBaban.Kenkre@Sun.COM 
4268040SBaban.Kenkre@Sun.COM 	/* If this is not a Well-Known SID try AD lookup */
4278040SBaban.Kenkre@Sun.COM 	if (windomain != NULL && strcasecmp(windomain, WK_DOMAIN) != 0) {
4288040SBaban.Kenkre@Sun.COM 		if (adutils_txtsid2hexbinsid(sidprefix, &rid,
4298040SBaban.Kenkre@Sun.COM 		    &cbinsid[0], sizeof (cbinsid)) != 0)
4308040SBaban.Kenkre@Sun.COM 			goto out;
4318040SBaban.Kenkre@Sun.COM 
4328040SBaban.Kenkre@Sun.COM 		ret = snprintf(searchfilter, sizeof (searchfilter),
4338040SBaban.Kenkre@Sun.COM 		    _F_GETPWUID, cbinsid);
4348040SBaban.Kenkre@Sun.COM 		if (ret >= sizeof (searchfilter) || ret < 0)
4358040SBaban.Kenkre@Sun.COM 			goto out;
4368040SBaban.Kenkre@Sun.COM 
4378040SBaban.Kenkre@Sun.COM 		stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
4388040SBaban.Kenkre@Sun.COM 		    windomain, &try_idmap);
4398040SBaban.Kenkre@Sun.COM 
4408040SBaban.Kenkre@Sun.COM 		if (!try_idmap)
4418040SBaban.Kenkre@Sun.COM 			goto out;
4428040SBaban.Kenkre@Sun.COM 	}
4438040SBaban.Kenkre@Sun.COM 
4448040SBaban.Kenkre@Sun.COM 	/* Map winname to primary gid using idmap service */
4458040SBaban.Kenkre@Sun.COM 	is_user = 0;
4468040SBaban.Kenkre@Sun.COM 	is_wuser = -1;
447*12914SJoyce.McIntosh@Sun.COM 	idmaprc = idmap_get_w2u_mapping(NULL, NULL,
4488040SBaban.Kenkre@Sun.COM 	    winname, windomain, 0, &is_user, &is_wuser, &gid,
4498040SBaban.Kenkre@Sun.COM 	    NULL, NULL, NULL);
4508040SBaban.Kenkre@Sun.COM 
4518040SBaban.Kenkre@Sun.COM 	if (idmaprc != IDMAP_SUCCESS) {
4528040SBaban.Kenkre@Sun.COM 		RESET_ERRNO();
4538040SBaban.Kenkre@Sun.COM 		goto out;
4548040SBaban.Kenkre@Sun.COM 	}
4558040SBaban.Kenkre@Sun.COM 
4568040SBaban.Kenkre@Sun.COM 	/* Create passwd(4) style string */
4578040SBaban.Kenkre@Sun.COM 	if (update_buffer(be, argp, winname, windomain,
4588040SBaban.Kenkre@Sun.COM 	    argp->key.uid, gid, "", "", "") < 0)
4598040SBaban.Kenkre@Sun.COM 		goto out;
4608040SBaban.Kenkre@Sun.COM 
4618040SBaban.Kenkre@Sun.COM 	/* Marshall the data, sanitize the return status and return */
4628040SBaban.Kenkre@Sun.COM 	stat = _nss_ad_marshall_data(be, argp);
4638040SBaban.Kenkre@Sun.COM 	stat = _nss_ad_sanitize_status(be, argp, stat);
4648040SBaban.Kenkre@Sun.COM 
4658040SBaban.Kenkre@Sun.COM out:
4668040SBaban.Kenkre@Sun.COM 	idmap_free(sidprefix);
4678040SBaban.Kenkre@Sun.COM 	idmap_free(winname);
4688040SBaban.Kenkre@Sun.COM 	idmap_free(windomain);
4698040SBaban.Kenkre@Sun.COM 	return (stat);
4708040SBaban.Kenkre@Sun.COM }
4718040SBaban.Kenkre@Sun.COM 
4728040SBaban.Kenkre@Sun.COM static ad_backend_op_t passwd_ops[] = {
4738040SBaban.Kenkre@Sun.COM 	_nss_ad_destr,
4748040SBaban.Kenkre@Sun.COM 	_nss_ad_endent,
4758040SBaban.Kenkre@Sun.COM 	_nss_ad_setent,
4768040SBaban.Kenkre@Sun.COM 	_nss_ad_getent,
4778040SBaban.Kenkre@Sun.COM 	getbyname,
4788040SBaban.Kenkre@Sun.COM 	getbyuid
4798040SBaban.Kenkre@Sun.COM };
4808040SBaban.Kenkre@Sun.COM 
4818040SBaban.Kenkre@Sun.COM /*
4828040SBaban.Kenkre@Sun.COM  * _nss_ad_passwd_constr is where life begins. This function calls the
4838040SBaban.Kenkre@Sun.COM  * generic AD constructor function to define and build the abstract
4848040SBaban.Kenkre@Sun.COM  * data types required to support AD operations.
4858040SBaban.Kenkre@Sun.COM  */
4868040SBaban.Kenkre@Sun.COM 
4878040SBaban.Kenkre@Sun.COM /*ARGSUSED0*/
4888040SBaban.Kenkre@Sun.COM nss_backend_t *
_nss_ad_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)4898040SBaban.Kenkre@Sun.COM _nss_ad_passwd_constr(const char *dummy1, const char *dummy2,
4908040SBaban.Kenkre@Sun.COM 			const char *dummy3)
4918040SBaban.Kenkre@Sun.COM {
4928040SBaban.Kenkre@Sun.COM 
4938040SBaban.Kenkre@Sun.COM 	return ((nss_backend_t *)_nss_ad_constr(passwd_ops,
4948040SBaban.Kenkre@Sun.COM 	    sizeof (passwd_ops)/sizeof (passwd_ops[0]),
4958040SBaban.Kenkre@Sun.COM 	    _PASSWD, pwd_attrs, _nss_ad_passwd2str));
4968040SBaban.Kenkre@Sun.COM }
497