12b4a7802SBaban Kenkre /*
22b4a7802SBaban Kenkre  * CDDL HEADER START
32b4a7802SBaban Kenkre  *
42b4a7802SBaban Kenkre  * The contents of this file are subject to the terms of the
52b4a7802SBaban Kenkre  * Common Development and Distribution License (the "License").
62b4a7802SBaban Kenkre  * You may not use this file except in compliance with the License.
72b4a7802SBaban Kenkre  *
82b4a7802SBaban Kenkre  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92b4a7802SBaban Kenkre  * or http://www.opensolaris.org/os/licensing.
102b4a7802SBaban Kenkre  * See the License for the specific language governing permissions
112b4a7802SBaban Kenkre  * and limitations under the License.
122b4a7802SBaban Kenkre  *
132b4a7802SBaban Kenkre  * When distributing Covered Code, include this CDDL HEADER in each
142b4a7802SBaban Kenkre  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152b4a7802SBaban Kenkre  * If applicable, add the following below this CDDL HEADER, with the
162b4a7802SBaban Kenkre  * fields enclosed by brackets "[]" replaced with your own identifying
172b4a7802SBaban Kenkre  * information: Portions Copyright [yyyy] [name of copyright owner]
182b4a7802SBaban Kenkre  *
192b4a7802SBaban Kenkre  * CDDL HEADER END
202b4a7802SBaban Kenkre  */
212b4a7802SBaban Kenkre /*
221fdeec65Sjoyce mcintosh  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
232b4a7802SBaban Kenkre  */
242b4a7802SBaban Kenkre 
252b4a7802SBaban Kenkre #include <pwd.h>
262b4a7802SBaban Kenkre #include <idmap.h>
272b4a7802SBaban Kenkre #include <ctype.h>
282b4a7802SBaban Kenkre #include "ad_common.h"
292b4a7802SBaban Kenkre 
302b4a7802SBaban Kenkre /* passwd attributes and filters */
312b4a7802SBaban Kenkre #define	_PWD_DN			"dn"
322b4a7802SBaban Kenkre #define	_PWD_SAN		"sAMAccountName"
332b4a7802SBaban Kenkre #define	_PWD_OBJSID		"objectSid"
342b4a7802SBaban Kenkre #define	_PWD_PRIMARYGROUPID	"primaryGroupID"
352b4a7802SBaban Kenkre #define	_PWD_CN			"cn"
362b4a7802SBaban Kenkre #define	_PWD_HOMEDIRECTORY	"homedirectory"
372b4a7802SBaban Kenkre #define	_PWD_LOGINSHELL		"loginshell"
382b4a7802SBaban Kenkre #define	_PWD_OBJCLASS		"objectClass"
392b4a7802SBaban Kenkre 
402b4a7802SBaban Kenkre #define	_F_GETPWNAM		"(sAMAccountName=%.*s)"
412b4a7802SBaban Kenkre #define	_F_GETPWUID		"(objectSid=%s)"
422b4a7802SBaban Kenkre 
432b4a7802SBaban Kenkre static const char *pwd_attrs[] = {
442b4a7802SBaban Kenkre 	_PWD_SAN,
452b4a7802SBaban Kenkre 	_PWD_OBJSID,
462b4a7802SBaban Kenkre 	_PWD_PRIMARYGROUPID,
472b4a7802SBaban Kenkre 	_PWD_CN,
482b4a7802SBaban Kenkre 	_PWD_HOMEDIRECTORY,
492b4a7802SBaban Kenkre 	_PWD_LOGINSHELL,
502b4a7802SBaban Kenkre 	_PWD_OBJCLASS,
512b4a7802SBaban Kenkre 	(char *)NULL
522b4a7802SBaban Kenkre };
532b4a7802SBaban Kenkre 
542b4a7802SBaban Kenkre 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)552b4a7802SBaban Kenkre update_buffer(ad_backend_ptr be, nss_XbyY_args_t *argp,
562b4a7802SBaban Kenkre 		const char *name, const char *domain,
572b4a7802SBaban Kenkre 		uid_t uid, gid_t gid, const char *gecos,
582b4a7802SBaban Kenkre 		const char *homedir, const char *shell)
592b4a7802SBaban Kenkre {
602b4a7802SBaban Kenkre 	int	buflen;
612b4a7802SBaban Kenkre 	char	*buffer;
622b4a7802SBaban Kenkre 
632b4a7802SBaban Kenkre 	if (be->db_type == NSS_AD_DB_PASSWD_BYNAME) {
642b4a7802SBaban Kenkre 		/*
652b4a7802SBaban Kenkre 		 * The canonical name obtained from AD lookup may not match
662b4a7802SBaban Kenkre 		 * the case of the name (i.e. key) in the request. Therefore,
672b4a7802SBaban Kenkre 		 * use the name from the request to construct the result.
682b4a7802SBaban Kenkre 		 */
692b4a7802SBaban Kenkre 		buflen = snprintf(NULL, 0, "%s:%s:%u:%u:%s:%s:%s",
702b4a7802SBaban Kenkre 		    argp->key.name, "x", uid, gid, gecos, homedir, shell) + 1;
712b4a7802SBaban Kenkre 	} else {
722b4a7802SBaban Kenkre 		if (domain == NULL)
732b4a7802SBaban Kenkre 			domain = WK_DOMAIN;
742b4a7802SBaban Kenkre 		buflen = snprintf(NULL, 0, "%s@%s:%s:%u:%u:%s:%s:%s",
752b4a7802SBaban Kenkre 		    name, domain, "x", uid, gid, gecos, homedir, shell) + 1;
762b4a7802SBaban Kenkre 	}
772b4a7802SBaban Kenkre 
782b4a7802SBaban Kenkre 
792b4a7802SBaban Kenkre 	if (argp->buf.result != NULL) {
802b4a7802SBaban Kenkre 		buffer = be->buffer = malloc(buflen);
812b4a7802SBaban Kenkre 		if (be->buffer == NULL)
822b4a7802SBaban Kenkre 			return (-1);
832b4a7802SBaban Kenkre 		be->buflen = buflen;
842b4a7802SBaban Kenkre 	} else {
852b4a7802SBaban Kenkre 		if (buflen > argp->buf.buflen)
862b4a7802SBaban Kenkre 			return (-1);
872b4a7802SBaban Kenkre 		buflen = argp->buf.buflen;
882b4a7802SBaban Kenkre 		buffer = argp->buf.buffer;
892b4a7802SBaban Kenkre 	}
902b4a7802SBaban Kenkre 
912b4a7802SBaban Kenkre 	if (be->db_type == NSS_AD_DB_PASSWD_BYNAME)
922b4a7802SBaban Kenkre 		(void) snprintf(buffer, buflen, "%s:%s:%u:%u:%s:%s:%s",
932b4a7802SBaban Kenkre 		    argp->key.name, "x", uid, gid, gecos, homedir, shell);
942b4a7802SBaban Kenkre 	else
952b4a7802SBaban Kenkre 		(void) snprintf(buffer, buflen, "%s@%s:%s:%u:%u:%s:%s:%s",
962b4a7802SBaban Kenkre 		    name, domain, "x", uid, gid, gecos, homedir, shell);
972b4a7802SBaban Kenkre 	return (0);
982b4a7802SBaban Kenkre }
992b4a7802SBaban Kenkre 
1002b4a7802SBaban Kenkre 
1012b4a7802SBaban Kenkre #define	NET_SCHEME	"/net"
1022b4a7802SBaban Kenkre 
1032b4a7802SBaban Kenkre /*
1042b4a7802SBaban Kenkre  * 1) If the homeDirectory string is in UNC format then convert it into
1052b4a7802SBaban Kenkre  * a /net format. This needs to be revisited later but is fine for now
1062b4a7802SBaban Kenkre  * because Solaris does not support -hosts automount map for CIFS yet.
1072b4a7802SBaban Kenkre  *
1082b4a7802SBaban Kenkre  * 2) If homeDirectory contains ':' then return NULL because ':' is the
1092b4a7802SBaban Kenkre  * delimiter in passwd entries and may break apps that parse these entries.
1102b4a7802SBaban Kenkre  *
1112b4a7802SBaban Kenkre  * 3) For all other cases return the same string that was passed to
1122b4a7802SBaban Kenkre  * this function.
1132b4a7802SBaban Kenkre  */
1142b4a7802SBaban Kenkre static
1152b4a7802SBaban Kenkre char *
process_homedir(char * homedir)1162b4a7802SBaban Kenkre process_homedir(char *homedir)
1172b4a7802SBaban Kenkre {
1182b4a7802SBaban Kenkre 	size_t	len, smb_len;
1192b4a7802SBaban Kenkre 	char	*smb_homedir;
1202b4a7802SBaban Kenkre 	int	i, slash = 0;
1212b4a7802SBaban Kenkre 
1222b4a7802SBaban Kenkre 	len = strlen(homedir);
1232b4a7802SBaban Kenkre 
1242b4a7802SBaban Kenkre 	if (strchr(homedir, ':') != NULL)
1252b4a7802SBaban Kenkre 		/*
1262b4a7802SBaban Kenkre 		 * Ignore paths that have colon ':' because ':' is a
1272b4a7802SBaban Kenkre 		 * delimiter for the passwd entry.
1282b4a7802SBaban Kenkre 		 */
1292b4a7802SBaban Kenkre 		return (NULL);
1302b4a7802SBaban Kenkre 
1312b4a7802SBaban Kenkre 	if (!(len > 1 && homedir[0] == '\\' && homedir[1] == '\\'))
1322b4a7802SBaban Kenkre 		/* Keep homedir intact if not in UNC format */
1332b4a7802SBaban Kenkre 		return (homedir);
1342b4a7802SBaban Kenkre 
1352b4a7802SBaban Kenkre 	/*
1362b4a7802SBaban Kenkre 	 * Convert UNC string into /net format
1372b4a7802SBaban Kenkre 	 * Example: \\server\abc -> /net/server/abc
1382b4a7802SBaban Kenkre 	 */
1392b4a7802SBaban Kenkre 	smb_len = len + 1 + sizeof (NET_SCHEME);
1402b4a7802SBaban Kenkre 	if ((smb_homedir = calloc(1, smb_len)) == NULL)
1412b4a7802SBaban Kenkre 		return (NULL);
1422b4a7802SBaban Kenkre 	(void) strlcpy(smb_homedir, NET_SCHEME, smb_len);
1432b4a7802SBaban Kenkre 	for (i = strlen(smb_homedir); *homedir != '\0'; homedir++) {
1442b4a7802SBaban Kenkre 		if (*homedir == '\\') {
1452b4a7802SBaban Kenkre 			/* Reduce double backslashes into one */
1462b4a7802SBaban Kenkre 			if (slash)
1472b4a7802SBaban Kenkre 				slash = 0;
1482b4a7802SBaban Kenkre 			else {
1492b4a7802SBaban Kenkre 				slash = 1;
1502b4a7802SBaban Kenkre 				smb_homedir[i++] = '/';
1512b4a7802SBaban Kenkre 			}
1522b4a7802SBaban Kenkre 		} else {
1532b4a7802SBaban Kenkre 			smb_homedir[i++] = *homedir;
1542b4a7802SBaban Kenkre 			slash = 0;
1552b4a7802SBaban Kenkre 		}
1562b4a7802SBaban Kenkre 	}
1572b4a7802SBaban Kenkre 	return (smb_homedir);
1582b4a7802SBaban Kenkre }
1592b4a7802SBaban Kenkre 
1602b4a7802SBaban Kenkre /*
1612b4a7802SBaban Kenkre  * _nss_ad_passwd2str is the data marshaling method for the passwd getXbyY
1622b4a7802SBaban Kenkre  * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is
1632b4a7802SBaban Kenkre  * called after a successful AD search has been performed. This method will
1642b4a7802SBaban Kenkre  * parse the AD search values into the file format.
1652b4a7802SBaban Kenkre  * e.g.
1662b4a7802SBaban Kenkre  *
1672b4a7802SBaban Kenkre  * blue@whale:x:123456:10:Blue Whale:/:
1682b4a7802SBaban Kenkre  *
1692b4a7802SBaban Kenkre  */
1702b4a7802SBaban Kenkre static int
_nss_ad_passwd2str(ad_backend_ptr be,nss_XbyY_args_t * argp)1712b4a7802SBaban Kenkre _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp)
1722b4a7802SBaban Kenkre {
1732b4a7802SBaban Kenkre 	int			nss_result;
1742b4a7802SBaban Kenkre 	adutils_result_t	*result = be->result;
1752b4a7802SBaban Kenkre 	const adutils_entry_t	*entry;
1762b4a7802SBaban Kenkre 	char			**sid_v, *ptr, **pgid_v, *end;
1772b4a7802SBaban Kenkre 	ulong_t			tmp;
1782b4a7802SBaban Kenkre 	uint32_t		urid, grid;
1792b4a7802SBaban Kenkre 	uid_t			uid;
1802b4a7802SBaban Kenkre 	gid_t			gid;
1812b4a7802SBaban Kenkre 	idmap_stat		gstat;
1822b4a7802SBaban Kenkre 	idmap_get_handle_t 	*ig = NULL;
1832b4a7802SBaban Kenkre 	char			**name_v, **dn_v, *domain = NULL;
1842b4a7802SBaban Kenkre 	char			**gecos_v, **shell_v;
1852b4a7802SBaban Kenkre 	char			**homedir_v = NULL, *homedir = NULL;
1862b4a7802SBaban Kenkre 	char			*NULL_STR = "";
1872b4a7802SBaban Kenkre 
1882b4a7802SBaban Kenkre 	if (result == NULL)
1892b4a7802SBaban Kenkre 		return (NSS_STR_PARSE_PARSE);
1902b4a7802SBaban Kenkre 	entry = adutils_getfirstentry(result);
1912b4a7802SBaban Kenkre 	nss_result = NSS_STR_PARSE_PARSE;
1922b4a7802SBaban Kenkre 
1932b4a7802SBaban Kenkre 	/* Create handles for idmap service */
1941fdeec65Sjoyce mcintosh 	if (idmap_get_create(&ig) != 0)
1952b4a7802SBaban Kenkre 		goto result_pwd2str;
1962b4a7802SBaban Kenkre 
1972b4a7802SBaban Kenkre 	/* Get name */
1982b4a7802SBaban Kenkre 	name_v = adutils_getattr(entry, _PWD_SAN);
1992b4a7802SBaban Kenkre 	if (name_v == NULL || name_v[0] == NULL || *name_v[0] == '\0')
2002b4a7802SBaban Kenkre 		goto result_pwd2str;
2012b4a7802SBaban Kenkre 
2022b4a7802SBaban Kenkre 	/* Get domain */
2032b4a7802SBaban Kenkre 	dn_v = adutils_getattr(entry, _PWD_DN);
2042b4a7802SBaban Kenkre 	if (dn_v == NULL || dn_v[0] == NULL || *dn_v[0] == '\0')
2052b4a7802SBaban Kenkre 		goto result_pwd2str;
2062b4a7802SBaban Kenkre 	domain = adutils_dn2dns(dn_v[0]);
2072b4a7802SBaban Kenkre 
2082b4a7802SBaban Kenkre 	/* Get objectSID (in text format) */
2092b4a7802SBaban Kenkre 	sid_v = adutils_getattr(entry, _PWD_OBJSID);
2102b4a7802SBaban Kenkre 	if (sid_v == NULL || sid_v[0] == NULL || *sid_v[0] == '\0')
2112b4a7802SBaban Kenkre 		goto result_pwd2str;
2122b4a7802SBaban Kenkre 
2132b4a7802SBaban Kenkre 	/* Break SID into prefix and rid */
2142b4a7802SBaban Kenkre 	if ((ptr = strrchr(sid_v[0], '-')) == NULL)
2152b4a7802SBaban Kenkre 		goto result_pwd2str;
2162b4a7802SBaban Kenkre 	*ptr = '\0';
2172b4a7802SBaban Kenkre 	end = ++ptr;
2182b4a7802SBaban Kenkre 	tmp = strtoul(ptr, &end, 10);
2192b4a7802SBaban Kenkre 	if (end == ptr || tmp > UINT32_MAX)
2202b4a7802SBaban Kenkre 		goto result_pwd2str;
2212b4a7802SBaban Kenkre 	urid = (uint32_t)tmp;
2222b4a7802SBaban Kenkre 
2232b4a7802SBaban Kenkre 	/* We already have uid -- no need to call idmapd */
2242b4a7802SBaban Kenkre 	if (be->db_type == NSS_AD_DB_PASSWD_BYUID)
2252b4a7802SBaban Kenkre 		uid = argp->key.uid;
2262b4a7802SBaban Kenkre 	else
2272b4a7802SBaban Kenkre 		uid = be->uid;
2282b4a7802SBaban Kenkre 
2292b4a7802SBaban Kenkre 	/* Get primaryGroupID */
2302b4a7802SBaban Kenkre 	pgid_v = adutils_getattr(entry, _PWD_PRIMARYGROUPID);
2312b4a7802SBaban Kenkre 	if (pgid_v == NULL || pgid_v[0] == NULL || *pgid_v[0] == '\0')
2322b4a7802SBaban Kenkre 		/*
2332b4a7802SBaban Kenkre 		 * If primaryGroupID is not found then we request
2342b4a7802SBaban Kenkre 		 * a GID to be mapped to the given user's objectSID
2352b4a7802SBaban Kenkre 		 * (diagonal mapping) and use this GID as the primary
2362b4a7802SBaban Kenkre 		 * GID for the entry.
2372b4a7802SBaban Kenkre 		 */
2382b4a7802SBaban Kenkre 		grid = urid;
2392b4a7802SBaban Kenkre 	else {
2402b4a7802SBaban Kenkre 		end = pgid_v[0];
2412b4a7802SBaban Kenkre 		tmp = strtoul(pgid_v[0], &end, 10);
2422b4a7802SBaban Kenkre 		if (end == pgid_v[0] || tmp > UINT32_MAX)
2432b4a7802SBaban Kenkre 			goto result_pwd2str;
2442b4a7802SBaban Kenkre 		grid = (uint32_t)tmp;
2452b4a7802SBaban Kenkre 	}
2462b4a7802SBaban Kenkre 
2472b4a7802SBaban Kenkre 	/* Map group SID to GID using idmap service */
2482b4a7802SBaban Kenkre 	if (idmap_get_gidbysid(ig, sid_v[0], grid, 0, &gid, &gstat) != 0)
2492b4a7802SBaban Kenkre 		goto result_pwd2str;
2502b4a7802SBaban Kenkre 	if (idmap_get_mappings(ig) != 0 || gstat != 0) {
2512b4a7802SBaban Kenkre 		RESET_ERRNO();
2522b4a7802SBaban Kenkre 		goto result_pwd2str;
2532b4a7802SBaban Kenkre 	}
2542b4a7802SBaban Kenkre 
2552b4a7802SBaban Kenkre 	/* Get gecos, homedirectory and shell information if available */
2562b4a7802SBaban Kenkre 	gecos_v = adutils_getattr(entry, _PWD_CN);
2572b4a7802SBaban Kenkre 	if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0')
2582b4a7802SBaban Kenkre 		gecos_v = &NULL_STR;
2592b4a7802SBaban Kenkre 
2602b4a7802SBaban Kenkre 	homedir_v = adutils_getattr(entry, _PWD_HOMEDIRECTORY);
2612b4a7802SBaban Kenkre 	if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0')
2622b4a7802SBaban Kenkre 		homedir = NULL_STR;
2632b4a7802SBaban Kenkre 	else if ((homedir = process_homedir(homedir_v[0])) == NULL)
2642b4a7802SBaban Kenkre 		homedir = NULL_STR;
2652b4a7802SBaban Kenkre 
2662b4a7802SBaban Kenkre 	shell_v = adutils_getattr(entry, _PWD_LOGINSHELL);
2672b4a7802SBaban Kenkre 	if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0')
2682b4a7802SBaban Kenkre 		shell_v = &NULL_STR;
2692b4a7802SBaban Kenkre 
2702b4a7802SBaban Kenkre 	if (update_buffer(be, argp, name_v[0], domain, uid, gid,
2712b4a7802SBaban Kenkre 	    gecos_v[0], homedir, shell_v[0]) < 0)
2722b4a7802SBaban Kenkre 		nss_result = NSS_STR_PARSE_ERANGE;
2732b4a7802SBaban Kenkre 	else
2742b4a7802SBaban Kenkre 		nss_result = NSS_STR_PARSE_SUCCESS;
2752b4a7802SBaban Kenkre 
2762b4a7802SBaban Kenkre result_pwd2str:
2772b4a7802SBaban Kenkre 	idmap_get_destroy(ig);
2782b4a7802SBaban Kenkre 	(void) adutils_freeresult(&be->result);
2792b4a7802SBaban Kenkre 	free(domain);
2802b4a7802SBaban Kenkre 	if (homedir != NULL_STR && homedir_v != NULL &&
2812b4a7802SBaban Kenkre 	    homedir != homedir_v[0])
2822b4a7802SBaban Kenkre 		free(homedir);
2832b4a7802SBaban Kenkre 	return ((int)nss_result);
2842b4a7802SBaban Kenkre }
2852b4a7802SBaban Kenkre 
2862b4a7802SBaban Kenkre /*
2872b4a7802SBaban Kenkre  * getbyname gets a passwd entry by winname. This function constructs an ldap
2882b4a7802SBaban Kenkre  * search filter using the name invocation parameter and the getpwnam search
2892b4a7802SBaban Kenkre  * filter defined. Once the filter is constructed, we search for a matching
2902b4a7802SBaban Kenkre  * entry and marshal the data results into struct passwd for the frontend
2912b4a7802SBaban Kenkre  * process. The function _nss_ad_passwd2ent performs the data marshaling.
2922b4a7802SBaban Kenkre  */
2932b4a7802SBaban Kenkre 
2942b4a7802SBaban Kenkre static nss_status_t
getbyname(ad_backend_ptr be,void * a)2952b4a7802SBaban Kenkre getbyname(ad_backend_ptr be, void *a)
2962b4a7802SBaban Kenkre {
2972b4a7802SBaban Kenkre 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2982b4a7802SBaban Kenkre 	char		*searchfilter;
2992b4a7802SBaban Kenkre 	char		name[SEARCHFILTERLEN];
3002b4a7802SBaban Kenkre 	char		*dname;
3012b4a7802SBaban Kenkre 	int		filterlen, namelen;
3022b4a7802SBaban Kenkre 	int		flag;
3032b4a7802SBaban Kenkre 	nss_status_t	stat;
3042b4a7802SBaban Kenkre 	idmap_stat	idmaprc;
3052b4a7802SBaban Kenkre 	uid_t		uid;
3062b4a7802SBaban Kenkre 	gid_t		gid;
3072b4a7802SBaban Kenkre 	int		is_user, is_wuser, try_idmap;
3082b4a7802SBaban Kenkre 
3092b4a7802SBaban Kenkre 	be->db_type = NSS_AD_DB_PASSWD_BYNAME;
3102b4a7802SBaban Kenkre 
3112b4a7802SBaban Kenkre 	/* Sanitize name so that it can be used in our LDAP filter */
3122b4a7802SBaban Kenkre 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
3132b4a7802SBaban Kenkre 		return ((nss_status_t)NSS_NOTFOUND);
3142b4a7802SBaban Kenkre 
3152b4a7802SBaban Kenkre 	if ((dname = strchr(name, '@')) == NULL)
3162b4a7802SBaban Kenkre 		return ((nss_status_t)NSS_NOTFOUND);
3172b4a7802SBaban Kenkre 
3182b4a7802SBaban Kenkre 	*dname = '\0';
3192b4a7802SBaban Kenkre 	dname++;
3202b4a7802SBaban Kenkre 
3212b4a7802SBaban Kenkre 	/*
3222b4a7802SBaban Kenkre 	 * Map the given name to UID using idmap service. If idmap
3232b4a7802SBaban Kenkre 	 * call fails then this will save us doing AD discovery and
3242b4a7802SBaban Kenkre 	 * AD lookup here.
3252b4a7802SBaban Kenkre 	 */
3262b4a7802SBaban Kenkre 	flag = (strcasecmp(dname, WK_DOMAIN) == 0) ?
3272b4a7802SBaban Kenkre 	    IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0;
3282b4a7802SBaban Kenkre 	is_wuser = -1;
3292b4a7802SBaban Kenkre 	is_user = 1;
3301fdeec65Sjoyce mcintosh 	if (idmap_get_w2u_mapping(NULL, NULL, name,
3312b4a7802SBaban Kenkre 	    dname, flag, &is_user, &is_wuser, &be->uid, NULL,
3322b4a7802SBaban Kenkre 	    NULL, NULL) != IDMAP_SUCCESS) {
3332b4a7802SBaban Kenkre 		RESET_ERRNO();
3342b4a7802SBaban Kenkre 		return ((nss_status_t)NSS_NOTFOUND);
3352b4a7802SBaban Kenkre 	}
3362b4a7802SBaban Kenkre 
3372b4a7802SBaban Kenkre 	/* If this is not a Well-Known SID then try AD lookup. */
3382b4a7802SBaban Kenkre 	if (strcasecmp(dname, WK_DOMAIN) != 0) {
3392b4a7802SBaban Kenkre 		/* Assemble filter using the given name */
3402b4a7802SBaban Kenkre 		namelen = strlen(name);
3412b4a7802SBaban Kenkre 		filterlen = snprintf(NULL, 0, _F_GETPWNAM, namelen, name) + 1;
3422b4a7802SBaban Kenkre 		if ((searchfilter = (char *)malloc(filterlen)) == NULL)
3432b4a7802SBaban Kenkre 			return ((nss_status_t)NSS_NOTFOUND);
3442b4a7802SBaban Kenkre 		(void) snprintf(searchfilter, filterlen, _F_GETPWNAM,
3452b4a7802SBaban Kenkre 		    namelen, name);
3462b4a7802SBaban Kenkre 		stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
3472b4a7802SBaban Kenkre 		    dname, &try_idmap);
3482b4a7802SBaban Kenkre 		free(searchfilter);
3492b4a7802SBaban Kenkre 
3501fdeec65Sjoyce mcintosh 		if (!try_idmap)
3512b4a7802SBaban Kenkre 			return (stat);
3522b4a7802SBaban Kenkre 
3532b4a7802SBaban Kenkre 	}
3542b4a7802SBaban Kenkre 
3552b4a7802SBaban Kenkre 	/*
3562b4a7802SBaban Kenkre 	 * Either this is a Well-Known SID or AD lookup failed. Map
3572b4a7802SBaban Kenkre 	 * the given name to GID using idmap service and construct
3582b4a7802SBaban Kenkre 	 * the passwd entry.
3592b4a7802SBaban Kenkre 	 */
3602b4a7802SBaban Kenkre 	is_wuser = -1;
3612b4a7802SBaban Kenkre 	is_user = 0; /* Map name to primary gid */
3621fdeec65Sjoyce mcintosh 	idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname,
3632b4a7802SBaban Kenkre 	    flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL);
3642b4a7802SBaban Kenkre 	if (idmaprc != IDMAP_SUCCESS) {
3652b4a7802SBaban Kenkre 		RESET_ERRNO();
3662b4a7802SBaban Kenkre 		return ((nss_status_t)NSS_NOTFOUND);
3672b4a7802SBaban Kenkre 	}
3682b4a7802SBaban Kenkre 
369*bbf21555SRichard Lowe 	/* Create passwd(5) style string */
3702b4a7802SBaban Kenkre 	if (update_buffer(be, argp, name, dname,
3712b4a7802SBaban Kenkre 	    be->uid, gid, "", "", "") < 0)
3722b4a7802SBaban Kenkre 		return ((nss_status_t)NSS_NOTFOUND);
3732b4a7802SBaban Kenkre 
3742b4a7802SBaban Kenkre 	/* Marshall the data, sanitize the return status and return */
3752b4a7802SBaban Kenkre 	stat = _nss_ad_marshall_data(be, argp);
3762b4a7802SBaban Kenkre 	return (_nss_ad_sanitize_status(be, argp, stat));
3772b4a7802SBaban Kenkre }
3782b4a7802SBaban Kenkre 
3792b4a7802SBaban Kenkre 
3802b4a7802SBaban Kenkre /*
3812b4a7802SBaban Kenkre  * getbyuid gets a passwd entry by uid number. This function constructs an ldap
3822b4a7802SBaban Kenkre  * search filter using the uid invocation parameter and the getpwuid search
3832b4a7802SBaban Kenkre  * filter defined. Once the filter is constructed, we search for a matching
3842b4a7802SBaban Kenkre  * entry and marshal the data results into struct passwd for the frontend
3852b4a7802SBaban Kenkre  * process. The function _nss_ad_passwd2ent performs the data marshaling.
3862b4a7802SBaban Kenkre  */
3872b4a7802SBaban Kenkre 
3882b4a7802SBaban Kenkre static nss_status_t
getbyuid(ad_backend_ptr be,void * a)3892b4a7802SBaban Kenkre getbyuid(ad_backend_ptr be, void *a)
3902b4a7802SBaban Kenkre {
3912b4a7802SBaban Kenkre 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
3922b4a7802SBaban Kenkre 	char			searchfilter[ADUTILS_MAXHEXBINSID + 14];
3932b4a7802SBaban Kenkre 	char			*sidprefix = NULL;
3942b4a7802SBaban Kenkre 	idmap_rid_t		rid;
3952b4a7802SBaban Kenkre 	char			cbinsid[ADUTILS_MAXHEXBINSID + 1];
3962b4a7802SBaban Kenkre 	char			*winname = NULL, *windomain = NULL;
3972b4a7802SBaban Kenkre 	int			is_user, is_wuser;
3982b4a7802SBaban Kenkre 	gid_t			gid;
3992b4a7802SBaban Kenkre 	idmap_stat		idmaprc;
4002b4a7802SBaban Kenkre 	int			ret, try_idmap;
4012b4a7802SBaban Kenkre 	nss_status_t		stat;
4022b4a7802SBaban Kenkre 
4032b4a7802SBaban Kenkre 	be->db_type = NSS_AD_DB_PASSWD_BYUID;
4042b4a7802SBaban Kenkre 
4052b4a7802SBaban Kenkre 	stat = (nss_status_t)NSS_NOTFOUND;
4062b4a7802SBaban Kenkre 
4072b4a7802SBaban Kenkre 	/* nss_ad does not support non ephemeral uids */
4082b4a7802SBaban Kenkre 	if (argp->key.uid <= MAXUID)
4092b4a7802SBaban Kenkre 		goto out;
4102b4a7802SBaban Kenkre 
4112b4a7802SBaban Kenkre 	/* Map the given UID to a SID using the idmap service */
4121fdeec65Sjoyce mcintosh 	if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0,
4132b4a7802SBaban Kenkre 	    1, NULL, &sidprefix, &rid, &winname, &windomain,
4142b4a7802SBaban Kenkre 	    NULL, NULL) != 0) {
4152b4a7802SBaban Kenkre 		RESET_ERRNO();
4162b4a7802SBaban Kenkre 		goto out;
4172b4a7802SBaban Kenkre 	}
4182b4a7802SBaban Kenkre 
4192b4a7802SBaban Kenkre 	/*
4202b4a7802SBaban Kenkre 	 * NULL winname implies a local SID or unresolvable SID both of
421*bbf21555SRichard Lowe 	 * which cannot be used to generated passwd(5) entry
4222b4a7802SBaban Kenkre 	 */
4232b4a7802SBaban Kenkre 	if (winname == NULL)
4242b4a7802SBaban Kenkre 		goto out;
4252b4a7802SBaban Kenkre 
4262b4a7802SBaban Kenkre 	/* If this is not a Well-Known SID try AD lookup */
4272b4a7802SBaban Kenkre 	if (windomain != NULL && strcasecmp(windomain, WK_DOMAIN) != 0) {
4282b4a7802SBaban Kenkre 		if (adutils_txtsid2hexbinsid(sidprefix, &rid,
4292b4a7802SBaban Kenkre 		    &cbinsid[0], sizeof (cbinsid)) != 0)
4302b4a7802SBaban Kenkre 			goto out;
4312b4a7802SBaban Kenkre 
4322b4a7802SBaban Kenkre 		ret = snprintf(searchfilter, sizeof (searchfilter),
4332b4a7802SBaban Kenkre 		    _F_GETPWUID, cbinsid);
4342b4a7802SBaban Kenkre 		if (ret >= sizeof (searchfilter) || ret < 0)
4352b4a7802SBaban Kenkre 			goto out;
4362b4a7802SBaban Kenkre 
4372b4a7802SBaban Kenkre 		stat = _nss_ad_lookup(be, argp, _PASSWD, searchfilter,
4382b4a7802SBaban Kenkre 		    windomain, &try_idmap);
4392b4a7802SBaban Kenkre 
4402b4a7802SBaban Kenkre 		if (!try_idmap)
4412b4a7802SBaban Kenkre 			goto out;
4422b4a7802SBaban Kenkre 	}
4432b4a7802SBaban Kenkre 
4442b4a7802SBaban Kenkre 	/* Map winname to primary gid using idmap service */
4452b4a7802SBaban Kenkre 	is_user = 0;
4462b4a7802SBaban Kenkre 	is_wuser = -1;
4471fdeec65Sjoyce mcintosh 	idmaprc = idmap_get_w2u_mapping(NULL, NULL,
4482b4a7802SBaban Kenkre 	    winname, windomain, 0, &is_user, &is_wuser, &gid,
4492b4a7802SBaban Kenkre 	    NULL, NULL, NULL);
4502b4a7802SBaban Kenkre 
4512b4a7802SBaban Kenkre 	if (idmaprc != IDMAP_SUCCESS) {
4522b4a7802SBaban Kenkre 		RESET_ERRNO();
4532b4a7802SBaban Kenkre 		goto out;
4542b4a7802SBaban Kenkre 	}
4552b4a7802SBaban Kenkre 
456*bbf21555SRichard Lowe 	/* Create passwd(5) style string */
4572b4a7802SBaban Kenkre 	if (update_buffer(be, argp, winname, windomain,
4582b4a7802SBaban Kenkre 	    argp->key.uid, gid, "", "", "") < 0)
4592b4a7802SBaban Kenkre 		goto out;
4602b4a7802SBaban Kenkre 
4612b4a7802SBaban Kenkre 	/* Marshall the data, sanitize the return status and return */
4622b4a7802SBaban Kenkre 	stat = _nss_ad_marshall_data(be, argp);
4632b4a7802SBaban Kenkre 	stat = _nss_ad_sanitize_status(be, argp, stat);
4642b4a7802SBaban Kenkre 
4652b4a7802SBaban Kenkre out:
4662b4a7802SBaban Kenkre 	idmap_free(sidprefix);
4672b4a7802SBaban Kenkre 	idmap_free(winname);
4682b4a7802SBaban Kenkre 	idmap_free(windomain);
4692b4a7802SBaban Kenkre 	return (stat);
4702b4a7802SBaban Kenkre }
4712b4a7802SBaban Kenkre 
4722b4a7802SBaban Kenkre static ad_backend_op_t passwd_ops[] = {
4732b4a7802SBaban Kenkre 	_nss_ad_destr,
4742b4a7802SBaban Kenkre 	_nss_ad_endent,
4752b4a7802SBaban Kenkre 	_nss_ad_setent,
4762b4a7802SBaban Kenkre 	_nss_ad_getent,
4772b4a7802SBaban Kenkre 	getbyname,
4782b4a7802SBaban Kenkre 	getbyuid
4792b4a7802SBaban Kenkre };
4802b4a7802SBaban Kenkre 
4812b4a7802SBaban Kenkre /*
4822b4a7802SBaban Kenkre  * _nss_ad_passwd_constr is where life begins. This function calls the
4832b4a7802SBaban Kenkre  * generic AD constructor function to define and build the abstract
4842b4a7802SBaban Kenkre  * data types required to support AD operations.
4852b4a7802SBaban Kenkre  */
4862b4a7802SBaban Kenkre 
4872b4a7802SBaban Kenkre /*ARGSUSED0*/
4882b4a7802SBaban Kenkre nss_backend_t *
_nss_ad_passwd_constr(const char * dummy1,const char * dummy2,const char * dummy3)4892b4a7802SBaban Kenkre _nss_ad_passwd_constr(const char *dummy1, const char *dummy2,
4902b4a7802SBaban Kenkre 			const char *dummy3)
4912b4a7802SBaban Kenkre {
4922b4a7802SBaban Kenkre 
4932b4a7802SBaban Kenkre 	return ((nss_backend_t *)_nss_ad_constr(passwd_ops,
4942b4a7802SBaban Kenkre 	    sizeof (passwd_ops)/sizeof (passwd_ops[0]),
4952b4a7802SBaban Kenkre 	    _PASSWD, pwd_attrs, _nss_ad_passwd2str));
4962b4a7802SBaban Kenkre }
497