xref: /titanic_52/usr/src/cmd/idmap/idmapd/adutils.c (revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327)
1c5c4113dSnw141292 /*
2c5c4113dSnw141292  * CDDL HEADER START
3c5c4113dSnw141292  *
4c5c4113dSnw141292  * The contents of this file are subject to the terms of the
5c5c4113dSnw141292  * Common Development and Distribution License (the "License").
6c5c4113dSnw141292  * You may not use this file except in compliance with the License.
7c5c4113dSnw141292  *
8c5c4113dSnw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw141292  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw141292  * See the License for the specific language governing permissions
11c5c4113dSnw141292  * and limitations under the License.
12c5c4113dSnw141292  *
13c5c4113dSnw141292  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw141292  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw141292  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw141292  *
19c5c4113dSnw141292  * CDDL HEADER END
20c5c4113dSnw141292  */
21c5c4113dSnw141292 
22c5c4113dSnw141292 /*
23*148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24c5c4113dSnw141292  */
25c5c4113dSnw141292 
26c5c4113dSnw141292 /*
27c5c4113dSnw141292  * Processes name2sid & sid2name batched lookups for a given user or
28c5c4113dSnw141292  * computer from an AD Directory server using GSSAPI authentication
29c5c4113dSnw141292  */
30c5c4113dSnw141292 
31c5c4113dSnw141292 #include <stdio.h>
32c5c4113dSnw141292 #include <stdlib.h>
33c5c4113dSnw141292 #include <alloca.h>
34c5c4113dSnw141292 #include <string.h>
35c5c4113dSnw141292 #include <strings.h>
36c5c4113dSnw141292 #include <lber.h>
37c5c4113dSnw141292 #include <ldap.h>
38c5c4113dSnw141292 #include <sasl/sasl.h>
39c5c4113dSnw141292 #include <string.h>
40c5c4113dSnw141292 #include <ctype.h>
41c5c4113dSnw141292 #include <pthread.h>
42c5c4113dSnw141292 #include <synch.h>
43c5c4113dSnw141292 #include <atomic.h>
44c5c4113dSnw141292 #include <errno.h>
45c5c4113dSnw141292 #include <assert.h>
46c5c4113dSnw141292 #include <limits.h>
472b4a7802SBaban Kenkre #include <time.h>
48cd37da74Snw141292 #include <sys/u8_textprep.h>
492b4a7802SBaban Kenkre #include "libadutils.h"
50479ac375Sdm199847 #include "nldaputils.h"
51c5c4113dSnw141292 #include "idmapd.h"
52c5c4113dSnw141292 
53c5c4113dSnw141292 /* Attribute names and filter format strings */
54e3c2d6aaSnw141292 #define	SAN		"sAMAccountName"
55e3c2d6aaSnw141292 #define	OBJSID		"objectSid"
56e3c2d6aaSnw141292 #define	OBJCLASS	"objectClass"
57e3f2c991SKeyur Desai #define	UIDNUMBER	"uidNumber"
58e3f2c991SKeyur Desai #define	GIDNUMBER	"gidNumber"
59e3f2c991SKeyur Desai #define	UIDNUMBERFILTER	"(&(objectclass=user)(uidNumber=%u))"
60e3f2c991SKeyur Desai #define	GIDNUMBERFILTER	"(&(objectclass=group)(gidNumber=%u))"
61e3f2c991SKeyur Desai #define	SANFILTER	"(sAMAccountName=%s)"
62e3c2d6aaSnw141292 #define	OBJSIDFILTER	"(objectSid=%s)"
63c5c4113dSnw141292 
642b4a7802SBaban Kenkre void	idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc,
652b4a7802SBaban Kenkre 		int qid, void *argp);
66c5c4113dSnw141292 
67c5c4113dSnw141292 /*
68c5c4113dSnw141292  * A place to put the results of a batched (async) query
69c5c4113dSnw141292  *
70c5c4113dSnw141292  * There is one of these for every query added to a batch object
71c5c4113dSnw141292  * (idmap_query_state, see below).
72c5c4113dSnw141292  */
73c5c4113dSnw141292 typedef struct idmap_q {
74e3c2d6aaSnw141292 	/*
75e3c2d6aaSnw141292 	 * data used for validating search result entries for name->SID
76e8c27ec8Sbaban 	 * lookups
77e3c2d6aaSnw141292 	 */
78cd37da74Snw141292 	char			*ecanonname;	/* expected canon name */
79cd37da74Snw141292 	char			*edomain;	/* expected domain name */
80*148c5f43SAlan Wright 	idmap_id_type		esidtype;	/* expected SID type */
81e3c2d6aaSnw141292 	/* results */
82cd37da74Snw141292 	char			**canonname;	/* actual canon name */
83c5c4113dSnw141292 	char			**domain;	/* name of domain of object */
84e8c27ec8Sbaban 	char			**sid;		/* stringified SID */
85e8c27ec8Sbaban 	rid_t			*rid;		/* RID */
86*148c5f43SAlan Wright 	idmap_id_type		*sid_type;	/* user or group SID? */
87e8c27ec8Sbaban 	char			**unixname;	/* unixname for name mapping */
8848258c6bSjp151216 	char			**dn;		/* DN of entry */
8948258c6bSjp151216 	char			**attr;		/* Attr for name mapping */
9048258c6bSjp151216 	char			**value;	/* value for name mapping */
91e3f2c991SKeyur Desai 	posix_id_t		*pid;		/* Posix ID found via IDMU */
92c5c4113dSnw141292 	idmap_retcode		*rc;
932b4a7802SBaban Kenkre 	adutils_rc		ad_rc;
942b4a7802SBaban Kenkre 	adutils_result_t	*result;
95e3c2d6aaSnw141292 
96bcced03bSjp151216 	/*
97bcced03bSjp151216 	 * The LDAP search entry result is placed here to be processed
98bcced03bSjp151216 	 * when the search done result is received.
99bcced03bSjp151216 	 */
100bcced03bSjp151216 	LDAPMessage		*search_res;	/* The LDAP search result */
101c5c4113dSnw141292 } idmap_q_t;
102c5c4113dSnw141292 
103c5c4113dSnw141292 /* Batch context structure; typedef is in header file */
104c5c4113dSnw141292 struct idmap_query_state {
1052b4a7802SBaban Kenkre 	adutils_query_state_t	*qs;
1064d61c878SJulian Pullen 	int			qsize;		/* Queue size */
1074d61c878SJulian Pullen 	uint32_t		qcount;		/* Number of queued requests */
108e8c27ec8Sbaban 	const char		*ad_unixuser_attr;
109e8c27ec8Sbaban 	const char		*ad_unixgroup_attr;
110e3f2c991SKeyur Desai 	int			directory_based_mapping;	/* enum */
111e3f2c991SKeyur Desai 	char			*default_domain;
112c5c4113dSnw141292 	idmap_q_t		queries[1];	/* array of query results */
113c5c4113dSnw141292 };
114c5c4113dSnw141292 
115651c0131Sbaban static pthread_t	reaperid = 0;
116c5c4113dSnw141292 
117c5c4113dSnw141292 /*
118c5c4113dSnw141292  * Keep connection management simple for now, extend or replace later
119c5c4113dSnw141292  * with updated libsldap code.
120c5c4113dSnw141292  */
121c5c4113dSnw141292 #define	ADREAPERSLEEP	60
122c5c4113dSnw141292 
123c5c4113dSnw141292 /*
124c5c4113dSnw141292  * Idle connection reaping side of connection management
125c5c4113dSnw141292  *
126c5c4113dSnw141292  * Every minute wake up and look for connections that have been idle for
127c5c4113dSnw141292  * five minutes or more and close them.
128c5c4113dSnw141292  */
129c5c4113dSnw141292 /*ARGSUSED*/
130c5c4113dSnw141292 static
131c5c4113dSnw141292 void
132c5c4113dSnw141292 adreaper(void *arg)
133c5c4113dSnw141292 {
134c5c4113dSnw141292 	timespec_t	ts;
135c5c4113dSnw141292 
136c5c4113dSnw141292 	ts.tv_sec = ADREAPERSLEEP;
137c5c4113dSnw141292 	ts.tv_nsec = 0;
138c5c4113dSnw141292 
139c5c4113dSnw141292 	for (;;) {
140c5c4113dSnw141292 		/*
141c5c4113dSnw141292 		 * nanosleep(3RT) is thead-safe (no SIGALRM) and more
142c5c4113dSnw141292 		 * portable than usleep(3C)
143c5c4113dSnw141292 		 */
144c5c4113dSnw141292 		(void) nanosleep(&ts, NULL);
1452b4a7802SBaban Kenkre 		adutils_reap_idle_connections();
146c5c4113dSnw141292 	}
147c5c4113dSnw141292 }
148c5c4113dSnw141292 
149c5c4113dSnw141292 /*
150c5c4113dSnw141292  * Take ad_host_config_t information, create a ad_host_t,
151c5c4113dSnw141292  * populate it and add it to the list of hosts.
152c5c4113dSnw141292  */
153c5c4113dSnw141292 
154c5c4113dSnw141292 int
1552b4a7802SBaban Kenkre idmap_add_ds(adutils_ad_t *ad, const char *host, int port)
156c5c4113dSnw141292 {
157c5c4113dSnw141292 	int	ret = -1;
158c5c4113dSnw141292 
1592b4a7802SBaban Kenkre 	if (adutils_add_ds(ad, host, port) == ADUTILS_SUCCESS)
160c8e26105Sjp151216 		ret = 0;
161c5c4113dSnw141292 
162c5c4113dSnw141292 	/* Start reaper if it doesn't exist */
1632b4a7802SBaban Kenkre 	if (ret == 0 && reaperid == 0)
164c5c4113dSnw141292 		(void) pthread_create(&reaperid, NULL,
165c5c4113dSnw141292 		    (void *(*)(void *))adreaper, (void *)NULL);
166c5c4113dSnw141292 	return (ret);
167c5c4113dSnw141292 }
168c5c4113dSnw141292 
169c5c4113dSnw141292 static
1702b4a7802SBaban Kenkre idmap_retcode
1712b4a7802SBaban Kenkre map_adrc2idmaprc(adutils_rc adrc)
172c5c4113dSnw141292 {
1732b4a7802SBaban Kenkre 	switch (adrc) {
1742b4a7802SBaban Kenkre 	case ADUTILS_SUCCESS:
1752b4a7802SBaban Kenkre 		return (IDMAP_SUCCESS);
1762b4a7802SBaban Kenkre 	case ADUTILS_ERR_NOTFOUND:
1772b4a7802SBaban Kenkre 		return (IDMAP_ERR_NOTFOUND);
1782b4a7802SBaban Kenkre 	case ADUTILS_ERR_MEMORY:
1792b4a7802SBaban Kenkre 		return (IDMAP_ERR_MEMORY);
1802b4a7802SBaban Kenkre 	case ADUTILS_ERR_DOMAIN:
1812b4a7802SBaban Kenkre 		return (IDMAP_ERR_DOMAIN);
1822b4a7802SBaban Kenkre 	case ADUTILS_ERR_OTHER:
1832b4a7802SBaban Kenkre 		return (IDMAP_ERR_OTHER);
1842b4a7802SBaban Kenkre 	case ADUTILS_ERR_RETRIABLE_NET_ERR:
1852b4a7802SBaban Kenkre 		return (IDMAP_ERR_RETRIABLE_NET_ERR);
1862b4a7802SBaban Kenkre 	default:
1872b4a7802SBaban Kenkre 		return (IDMAP_ERR_INTERNAL);
188c5c4113dSnw141292 	}
1892b4a7802SBaban Kenkre 	/* NOTREACHED */
190c5c4113dSnw141292 }
191c5c4113dSnw141292 
192c5c4113dSnw141292 idmap_retcode
1932b4a7802SBaban Kenkre idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
194e3f2c991SKeyur Desai 	int directory_based_mapping, const char *default_domain,
1952b4a7802SBaban Kenkre 	idmap_query_state_t **state)
196c5c4113dSnw141292 {
197c5c4113dSnw141292 	idmap_query_state_t	*new_state;
1982b4a7802SBaban Kenkre 	adutils_rc		rc;
199c5c4113dSnw141292 
200c5c4113dSnw141292 	*state = NULL;
201c5c4113dSnw141292 
2024d61c878SJulian Pullen 	assert(ad != NULL);
203c5c4113dSnw141292 
204c5c4113dSnw141292 	new_state = calloc(1, sizeof (idmap_query_state_t) +
205c5c4113dSnw141292 	    (nqueries - 1) * sizeof (idmap_q_t));
206c5c4113dSnw141292 	if (new_state == NULL)
207c5c4113dSnw141292 		return (IDMAP_ERR_MEMORY);
208c5c4113dSnw141292 
2092b4a7802SBaban Kenkre 	if ((rc = adutils_lookup_batch_start(ad, nqueries,
2102b4a7802SBaban Kenkre 	    idmap_ldap_res_search_cb, new_state, &new_state->qs))
2112b4a7802SBaban Kenkre 	    != ADUTILS_SUCCESS) {
212e3f2c991SKeyur Desai 		idmap_lookup_release_batch(&new_state);
2132b4a7802SBaban Kenkre 		return (map_adrc2idmaprc(rc));
2142b4a7802SBaban Kenkre 	}
2152b4a7802SBaban Kenkre 
216e3f2c991SKeyur Desai 	new_state->default_domain = strdup(default_domain);
217e3f2c991SKeyur Desai 	if (new_state->default_domain == NULL) {
218e3f2c991SKeyur Desai 		idmap_lookup_release_batch(&new_state);
219e3f2c991SKeyur Desai 		return (IDMAP_ERR_MEMORY);
220e3f2c991SKeyur Desai 	}
221e3f2c991SKeyur Desai 
222e3f2c991SKeyur Desai 	new_state->directory_based_mapping = directory_based_mapping;
2234d61c878SJulian Pullen 	new_state->qsize = nqueries;
224c5c4113dSnw141292 	*state = new_state;
225c5c4113dSnw141292 	return (IDMAP_SUCCESS);
226c5c4113dSnw141292 }
227c5c4113dSnw141292 
228c5c4113dSnw141292 /*
229e8c27ec8Sbaban  * Set unixuser_attr and unixgroup_attr for AD-based name mapping
230e8c27ec8Sbaban  */
231e8c27ec8Sbaban void
232e8c27ec8Sbaban idmap_lookup_batch_set_unixattr(idmap_query_state_t *state,
2334edd44c5Sjp151216 		const char *unixuser_attr, const char *unixgroup_attr)
2344edd44c5Sjp151216 {
235e8c27ec8Sbaban 	state->ad_unixuser_attr = unixuser_attr;
236e8c27ec8Sbaban 	state->ad_unixgroup_attr = unixgroup_attr;
237e8c27ec8Sbaban }
238e8c27ec8Sbaban 
239e8c27ec8Sbaban /*
240cd37da74Snw141292  * Take parsed attribute values from a search result entry and check if
241cd37da74Snw141292  * it is the result that was desired and, if so, set the result fields
242cd37da74Snw141292  * of the given idmap_q_t.
243cd37da74Snw141292  *
244e3f2c991SKeyur Desai  * Except for dn and attr, all strings are consumed, either by transferring
245e3f2c991SKeyur Desai  * them over into the request results (where the caller will eventually free
246e3f2c991SKeyur Desai  * them) or by freeing them here.  Note that this aligns with the "const"
247e3f2c991SKeyur Desai  * declarations below.
248c5c4113dSnw141292  */
249c5c4113dSnw141292 static
250cd37da74Snw141292 void
251e3f2c991SKeyur Desai idmap_setqresults(
252e3f2c991SKeyur Desai     idmap_q_t *q,
253e3f2c991SKeyur Desai     char *san,
254e3f2c991SKeyur Desai     const char *dn,
255e3f2c991SKeyur Desai     const char *attr,
256e3f2c991SKeyur Desai     char *value,
257e3f2c991SKeyur Desai     char *sid,
258e3f2c991SKeyur Desai     rid_t rid,
259e3f2c991SKeyur Desai     int sid_type,
260e3f2c991SKeyur Desai     char *unixname,
261e3f2c991SKeyur Desai     posix_id_t pid)
262c5c4113dSnw141292 {
263cd37da74Snw141292 	char *domain;
2641fcced4cSJordan Brown 	int err1;
265cd37da74Snw141292 
266cd37da74Snw141292 	assert(dn != NULL);
267cd37da74Snw141292 
2682b4a7802SBaban Kenkre 	if ((domain = adutils_dn2dns(dn)) == NULL)
269cd37da74Snw141292 		goto out;
270cd37da74Snw141292 
271e8c27ec8Sbaban 	if (q->ecanonname != NULL && san != NULL) {
272e8c27ec8Sbaban 		/* Check that this is the canonname that we were looking for */
273cd37da74Snw141292 		if (u8_strcmp(q->ecanonname, san, 0,
274cd37da74Snw141292 		    U8_STRCMP_CI_LOWER, /* no normalization, for now */
275e8c27ec8Sbaban 		    U8_UNICODE_LATEST, &err1) != 0 || err1 != 0)
276e8c27ec8Sbaban 			goto out;
277e8c27ec8Sbaban 	}
278e8c27ec8Sbaban 
279e8c27ec8Sbaban 	if (q->edomain != NULL) {
280e8c27ec8Sbaban 		/* Check that this is the domain that we were looking for */
2811fcced4cSJordan Brown 		if (!domain_eq(q->edomain, domain))
282cd37da74Snw141292 			goto out;
283e8c27ec8Sbaban 	}
284cd37da74Snw141292 
28548258c6bSjp151216 	/* Copy the DN and attr and value */
28648258c6bSjp151216 	if (q->dn != NULL)
28748258c6bSjp151216 		*q->dn = strdup(dn);
28848258c6bSjp151216 
28948258c6bSjp151216 	if (q->attr != NULL && attr != NULL)
29048258c6bSjp151216 		*q->attr = strdup(attr);
29148258c6bSjp151216 
292e3f2c991SKeyur Desai 	if (q->value != NULL && value != NULL) {
293e3f2c991SKeyur Desai 		*q->value = value;
294e3f2c991SKeyur Desai 		value = NULL;
295e3f2c991SKeyur Desai 	}
29648258c6bSjp151216 
297e8c27ec8Sbaban 	/* Set results */
298e8c27ec8Sbaban 	if (q->sid) {
299e8c27ec8Sbaban 		*q->sid = sid;
300cd37da74Snw141292 		sid = NULL;
301e8c27ec8Sbaban 	}
302e8c27ec8Sbaban 	if (q->rid)
303e8c27ec8Sbaban 		*q->rid = rid;
304e8c27ec8Sbaban 	if (q->sid_type)
305cd37da74Snw141292 		*q->sid_type = sid_type;
306e8c27ec8Sbaban 	if (q->unixname) {
307e8c27ec8Sbaban 		*q->unixname = unixname;
308e8c27ec8Sbaban 		unixname = NULL;
309e8c27ec8Sbaban 	}
310cd37da74Snw141292 	if (q->domain != NULL) {
311cd37da74Snw141292 		*q->domain = domain;
312cd37da74Snw141292 		domain = NULL;
313e8c27ec8Sbaban 	}
314e8c27ec8Sbaban 	if (q->canonname != NULL) {
315479ac375Sdm199847 		/*
316479ac375Sdm199847 		 * The caller may be replacing the given winname by its
317479ac375Sdm199847 		 * canonical name and therefore free any old name before
318479ac375Sdm199847 		 * overwriting the field by the canonical name.
319479ac375Sdm199847 		 */
320479ac375Sdm199847 		free(*q->canonname);
321e8c27ec8Sbaban 		*q->canonname = san;
322cd37da74Snw141292 		san = NULL;
323cd37da74Snw141292 	}
324cd37da74Snw141292 
3259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (q->pid != NULL && pid != IDMAP_SENTINEL_PID) {
326e3f2c991SKeyur Desai 		*q->pid = pid;
327e3f2c991SKeyur Desai 	}
328e3f2c991SKeyur Desai 
3292b4a7802SBaban Kenkre 	q->ad_rc = ADUTILS_SUCCESS;
330cd37da74Snw141292 
331cd37da74Snw141292 out:
332cd37da74Snw141292 	/* Free unused attribute values */
333cd37da74Snw141292 	free(san);
334cd37da74Snw141292 	free(sid);
335cd37da74Snw141292 	free(domain);
336e8c27ec8Sbaban 	free(unixname);
337e3f2c991SKeyur Desai 	free(value);
338c5c4113dSnw141292 }
339c5c4113dSnw141292 
340c5c4113dSnw141292 #define	BVAL_CASEEQ(bv, str) \
341c5c4113dSnw141292 		(((*(bv))->bv_len == (sizeof (str) - 1)) && \
342c5c4113dSnw141292 		    strncasecmp((*(bv))->bv_val, str, (*(bv))->bv_len) == 0)
343c5c4113dSnw141292 
344c5c4113dSnw141292 /*
345cd37da74Snw141292  * Extract the class of the result entry.  Returns 1 on success, 0 on
346cd37da74Snw141292  * failure.
347c5c4113dSnw141292  */
348c5c4113dSnw141292 static
349e3c2d6aaSnw141292 int
350cd37da74Snw141292 idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
351c5c4113dSnw141292 {
352c5c4113dSnw141292 	BerValue	**cbval;
353c5c4113dSnw141292 
354*148c5f43SAlan Wright 	*sid_type = IDMAP_SID;
355c5c4113dSnw141292 	if (bvalues == NULL)
356e3c2d6aaSnw141292 		return (0);
357c5c4113dSnw141292 
358cd37da74Snw141292 	/*
359e3f2c991SKeyur Desai 	 * We consider Computer to be a subclass of User, so we can just
360e3f2c991SKeyur Desai 	 * ignore Computer entries and pay attention to the accompanying
361e3f2c991SKeyur Desai 	 * User entries.
362cd37da74Snw141292 	 */
363c5c4113dSnw141292 	for (cbval = bvalues; *cbval != NULL; cbval++) {
364e3f2c991SKeyur Desai 		if (BVAL_CASEEQ(cbval, "group")) {
365*148c5f43SAlan Wright 			*sid_type = IDMAP_GSID;
366cd37da74Snw141292 			break;
367e3f2c991SKeyur Desai 		} else if (BVAL_CASEEQ(cbval, "user")) {
368*148c5f43SAlan Wright 			*sid_type = IDMAP_USID;
369e3f2c991SKeyur Desai 			break;
370cd37da74Snw141292 		}
371cd37da74Snw141292 		/*
372*148c5f43SAlan Wright 		 * "else if (*sid_type = IDMAP_USID)" then this is a
373cd37da74Snw141292 		 * new sub-class of user -- what to do with it??
374cd37da74Snw141292 		 */
375c5c4113dSnw141292 	}
376e3c2d6aaSnw141292 
377e3c2d6aaSnw141292 	return (1);
378c5c4113dSnw141292 }
379c5c4113dSnw141292 
380c5c4113dSnw141292 /*
381c5c4113dSnw141292  * Handle a given search result entry
382c5c4113dSnw141292  */
383c5c4113dSnw141292 static
384c5c4113dSnw141292 void
3852b4a7802SBaban Kenkre idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
3862b4a7802SBaban Kenkre 	LDAPMessage *res, LDAP *ld)
387c5c4113dSnw141292 {
388c5c4113dSnw141292 	BerValue		**bvalues;
389e3f2c991SKeyur Desai 	const char		*attr = NULL;
390e3f2c991SKeyur Desai 	char			*value = NULL;
391e3f2c991SKeyur Desai 	char			*unix_name = NULL;
392e3f2c991SKeyur Desai 	char			*dn;
393cd37da74Snw141292 	char			*san = NULL;
394cd37da74Snw141292 	char			*sid = NULL;
395cd37da74Snw141292 	rid_t			rid = 0;
396e3f2c991SKeyur Desai 	int			sid_type;
397e3f2c991SKeyur Desai 	int			ok;
3989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	posix_id_t		pid = IDMAP_SENTINEL_PID;
399e3c2d6aaSnw141292 
400e8c27ec8Sbaban 	assert(q->rc != NULL);
401e3f2c991SKeyur Desai 	assert(q->domain == NULL || *q->domain == NULL);
402e8c27ec8Sbaban 
4032b4a7802SBaban Kenkre 	if ((dn = ldap_get_dn(ld, res)) == NULL)
404c5c4113dSnw141292 		return;
405c5c4113dSnw141292 
406e3f2c991SKeyur Desai 	bvalues = ldap_get_values_len(ld, res, OBJCLASS);
407e3f2c991SKeyur Desai 	if (bvalues == NULL) {
408e8c27ec8Sbaban 		/*
409e8c27ec8Sbaban 		 * Didn't find objectclass. Something's wrong with our
410e8c27ec8Sbaban 		 * AD data.
411e8c27ec8Sbaban 		 */
412e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "%s has no %s", dn, OBJCLASS);
413e3f2c991SKeyur Desai 		goto out;
414e3f2c991SKeyur Desai 	}
415e3f2c991SKeyur Desai 	ok = idmap_bv_objclass2sidtype(bvalues, &sid_type);
416e3f2c991SKeyur Desai 	ldap_value_free_len(bvalues);
417e3f2c991SKeyur Desai 	if (!ok) {
418e8c27ec8Sbaban 		/*
419e3f2c991SKeyur Desai 		 * Didn't understand objectclass. Something's wrong with our
420e3f2c991SKeyur Desai 		 * AD data.
421e8c27ec8Sbaban 		 */
422e3f2c991SKeyur Desai 		idmapdlog(LOG_ERR, "%s has unexpected %s", dn, OBJCLASS);
423e3f2c991SKeyur Desai 		goto out;
424e8c27ec8Sbaban 	}
425e8c27ec8Sbaban 
426e3f2c991SKeyur Desai 	if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU &&
427e3f2c991SKeyur Desai 	    q->pid != NULL) {
428*148c5f43SAlan Wright 		if (sid_type == IDMAP_USID)
429e3f2c991SKeyur Desai 			attr = UIDNUMBER;
430*148c5f43SAlan Wright 		else if (sid_type == IDMAP_GSID)
431e3f2c991SKeyur Desai 			attr = GIDNUMBER;
432e3f2c991SKeyur Desai 		if (attr != NULL) {
433e3f2c991SKeyur Desai 			bvalues = ldap_get_values_len(ld, res, attr);
434e3f2c991SKeyur Desai 			if (bvalues != NULL) {
435e3f2c991SKeyur Desai 				value = adutils_bv_str(bvalues[0]);
436e3f2c991SKeyur Desai 				if (!adutils_bv_uint(bvalues[0], &pid)) {
437e3f2c991SKeyur Desai 					idmapdlog(LOG_ERR,
438e3f2c991SKeyur Desai 					    "%s has Invalid %s value \"%s\"",
439e3f2c991SKeyur Desai 					    dn, attr, value);
440e3f2c991SKeyur Desai 				}
441e3f2c991SKeyur Desai 				ldap_value_free_len(bvalues);
442e3f2c991SKeyur Desai 			}
443e3f2c991SKeyur Desai 		}
444e3f2c991SKeyur Desai 	}
445c5c4113dSnw141292 
446e3f2c991SKeyur Desai 	if (state->directory_based_mapping == DIRECTORY_MAPPING_NAME &&
447e3f2c991SKeyur Desai 	    q->unixname != NULL) {
448e3f2c991SKeyur Desai 		/*
449e3f2c991SKeyur Desai 		 * If the caller has requested unixname then determine the
450e3f2c991SKeyur Desai 		 * AD attribute name that will have the unixname, and retrieve
451e3f2c991SKeyur Desai 		 * its value.
452e3f2c991SKeyur Desai 		 */
453*148c5f43SAlan Wright 		idmap_id_type esidtype;
454e3f2c991SKeyur Desai 		/*
455*148c5f43SAlan Wright 		 * Determine the target type.
456e3f2c991SKeyur Desai 		 *
457e3f2c991SKeyur Desai 		 * If the caller specified one, use that.  Otherwise, give the
458e3f2c991SKeyur Desai 		 * same type that as we found for the Windows user.
459e3f2c991SKeyur Desai 		 */
460*148c5f43SAlan Wright 		esidtype = q->esidtype;
461*148c5f43SAlan Wright 		if (esidtype == IDMAP_SID)
462*148c5f43SAlan Wright 			esidtype = sid_type;
463e3f2c991SKeyur Desai 
464*148c5f43SAlan Wright 		if (esidtype == IDMAP_USID)
465e3f2c991SKeyur Desai 			attr = state->ad_unixuser_attr;
466*148c5f43SAlan Wright 		else if (esidtype == IDMAP_GSID)
467e3f2c991SKeyur Desai 			attr = state->ad_unixgroup_attr;
468e3f2c991SKeyur Desai 
469e3f2c991SKeyur Desai 		if (attr != NULL) {
470e3f2c991SKeyur Desai 			bvalues = ldap_get_values_len(ld, res, attr);
471e3f2c991SKeyur Desai 			if (bvalues != NULL) {
472e3f2c991SKeyur Desai 				unix_name = adutils_bv_str(bvalues[0]);
473e3f2c991SKeyur Desai 				ldap_value_free_len(bvalues);
474e3f2c991SKeyur Desai 				value = strdup(unix_name);
475e3f2c991SKeyur Desai 			}
476e3f2c991SKeyur Desai 		}
477e3f2c991SKeyur Desai 	}
478e3f2c991SKeyur Desai 
479e3f2c991SKeyur Desai 	bvalues = ldap_get_values_len(ld, res, SAN);
480e3f2c991SKeyur Desai 	if (bvalues != NULL) {
481e3f2c991SKeyur Desai 		san = adutils_bv_str(bvalues[0]);
482e3f2c991SKeyur Desai 		ldap_value_free_len(bvalues);
483e3f2c991SKeyur Desai 	}
484e3f2c991SKeyur Desai 
485e3f2c991SKeyur Desai 	if (q->sid != NULL) {
486e3f2c991SKeyur Desai 		bvalues = ldap_get_values_len(ld, res, OBJSID);
487e3f2c991SKeyur Desai 		if (bvalues != NULL) {
488e3f2c991SKeyur Desai 			sid = adutils_bv_objsid2sidstr(bvalues[0], &rid);
489e3f2c991SKeyur Desai 			ldap_value_free_len(bvalues);
490e3f2c991SKeyur Desai 		}
491e3f2c991SKeyur Desai 	}
492e3f2c991SKeyur Desai 
493e3f2c991SKeyur Desai 	idmap_setqresults(q, san, dn,
494e3f2c991SKeyur Desai 	    attr, value,
495e3f2c991SKeyur Desai 	    sid, rid, sid_type,
496e3f2c991SKeyur Desai 	    unix_name, pid);
497e3f2c991SKeyur Desai 
498e3f2c991SKeyur Desai out:
499c5c4113dSnw141292 	ldap_memfree(dn);
500c5c4113dSnw141292 }
501c5c4113dSnw141292 
5022b4a7802SBaban Kenkre void
5032b4a7802SBaban Kenkre idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, int qid,
5042b4a7802SBaban Kenkre 		void *argp)
505c5c4113dSnw141292 {
5062b4a7802SBaban Kenkre 	idmap_query_state_t	*state = (idmap_query_state_t *)argp;
5072b4a7802SBaban Kenkre 	idmap_q_t		*q = &(state->queries[qid]);
508c5c4113dSnw141292 
509c5c4113dSnw141292 	switch (rc) {
510c5c4113dSnw141292 	case LDAP_RES_SEARCH_RESULT:
5112b4a7802SBaban Kenkre 		if (q->search_res != NULL) {
5122b4a7802SBaban Kenkre 			idmap_extract_object(state, q, q->search_res, ld);
5132b4a7802SBaban Kenkre 			(void) ldap_msgfree(q->search_res);
5142b4a7802SBaban Kenkre 			q->search_res = NULL;
515bcced03bSjp151216 		} else
5162b4a7802SBaban Kenkre 			q->ad_rc = ADUTILS_ERR_NOTFOUND;
517c5c4113dSnw141292 		break;
518c5c4113dSnw141292 	case LDAP_RES_SEARCH_ENTRY:
5192b4a7802SBaban Kenkre 		if (q->search_res == NULL) {
5202b4a7802SBaban Kenkre 			q->search_res = *res;
5212b4a7802SBaban Kenkre 			*res = NULL;
522bcced03bSjp151216 		}
523c5c4113dSnw141292 		break;
524c5c4113dSnw141292 	default:
525c5c4113dSnw141292 		break;
526c5c4113dSnw141292 	}
52784decf41Sjp151216 }
52884decf41Sjp151216 
529e3c2d6aaSnw141292 static
530e3c2d6aaSnw141292 void
531e3c2d6aaSnw141292 idmap_cleanup_batch(idmap_query_state_t *batch)
532e3c2d6aaSnw141292 {
533e3c2d6aaSnw141292 	int i;
534e3c2d6aaSnw141292 
535e3c2d6aaSnw141292 	for (i = 0; i < batch->qcount; i++) {
536cd37da74Snw141292 		if (batch->queries[i].ecanonname != NULL)
537cd37da74Snw141292 			free(batch->queries[i].ecanonname);
538cd37da74Snw141292 		batch->queries[i].ecanonname = NULL;
539cd37da74Snw141292 		if (batch->queries[i].edomain != NULL)
540cd37da74Snw141292 			free(batch->queries[i].edomain);
541cd37da74Snw141292 		batch->queries[i].edomain = NULL;
542e3c2d6aaSnw141292 	}
543e3c2d6aaSnw141292 }
544e3c2d6aaSnw141292 
54584decf41Sjp151216 /*
54684decf41Sjp151216  * This routine frees the idmap_query_state_t structure
54784decf41Sjp151216  */
548c5c4113dSnw141292 void
54984decf41Sjp151216 idmap_lookup_release_batch(idmap_query_state_t **state)
550c5c4113dSnw141292 {
5512b4a7802SBaban Kenkre 	if (state == NULL || *state == NULL)
5522b4a7802SBaban Kenkre 		return;
5532b4a7802SBaban Kenkre 	adutils_lookup_batch_release(&(*state)->qs);
554e3c2d6aaSnw141292 	idmap_cleanup_batch(*state);
555e3f2c991SKeyur Desai 	free((*state)->default_domain);
556c5c4113dSnw141292 	free(*state);
557c5c4113dSnw141292 	*state = NULL;
558c5c4113dSnw141292 }
559c5c4113dSnw141292 
560c5c4113dSnw141292 idmap_retcode
5610dcc7149Snw141292 idmap_lookup_batch_end(idmap_query_state_t **state)
562c5c4113dSnw141292 {
5632b4a7802SBaban Kenkre 	adutils_rc		ad_rc;
5642b4a7802SBaban Kenkre 	int			i;
5652b4a7802SBaban Kenkre 	idmap_query_state_t	*id_qs = *state;
566c5c4113dSnw141292 
5672b4a7802SBaban Kenkre 	ad_rc = adutils_lookup_batch_end(&id_qs->qs);
568c5c4113dSnw141292 
5692b4a7802SBaban Kenkre 	/*
5702b4a7802SBaban Kenkre 	 * Map adutils rc to idmap_retcode in each
5712b4a7802SBaban Kenkre 	 * query because consumers in dbutils.c
5722b4a7802SBaban Kenkre 	 * expects idmap_retcode.
5732b4a7802SBaban Kenkre 	 */
5742b4a7802SBaban Kenkre 	for (i = 0; i < id_qs->qcount; i++) {
5752b4a7802SBaban Kenkre 		*id_qs->queries[i].rc =
5762b4a7802SBaban Kenkre 		    map_adrc2idmaprc(id_qs->queries[i].ad_rc);
577c5c4113dSnw141292 	}
57884decf41Sjp151216 	idmap_lookup_release_batch(state);
5792b4a7802SBaban Kenkre 	return (map_adrc2idmaprc(ad_rc));
580c5c4113dSnw141292 }
581c5c4113dSnw141292 
582c5c4113dSnw141292 /*
583c5c4113dSnw141292  * Send one prepared search, queue up msgid, process what results are
584c5c4113dSnw141292  * available
585c5c4113dSnw141292  */
586c5c4113dSnw141292 static
587c5c4113dSnw141292 idmap_retcode
58848258c6bSjp151216 idmap_batch_add1(idmap_query_state_t *state, const char *filter,
589*148c5f43SAlan Wright 	char *ecanonname, char *edomain, idmap_id_type esidtype,
59048258c6bSjp151216 	char **dn, char **attr, char **value,
59148258c6bSjp151216 	char **canonname, char **dname,
592*148c5f43SAlan Wright 	char **sid, rid_t *rid, idmap_id_type *sid_type, char **unixname,
593e3f2c991SKeyur Desai 	posix_id_t *pid,
59448258c6bSjp151216 	idmap_retcode *rc)
595c5c4113dSnw141292 {
5962b4a7802SBaban Kenkre 	adutils_rc	ad_rc;
5972b4a7802SBaban Kenkre 	int		qid, i;
598c5c4113dSnw141292 	idmap_q_t	*q;
599e3f2c991SKeyur Desai 	char	*attrs[20];	/* Plenty */
600c5c4113dSnw141292 
6014d61c878SJulian Pullen 	qid = atomic_inc_32_nv(&state->qcount) - 1;
602c5c4113dSnw141292 	q = &(state->queries[qid]);
603c5c4113dSnw141292 
6044d61c878SJulian Pullen 	assert(qid < state->qsize);
6054d61c878SJulian Pullen 
606cd37da74Snw141292 	/*
6072b4a7802SBaban Kenkre 	 * Remember the expected canonname, domainname and unix type
6082b4a7802SBaban Kenkre 	 * so we can check the results * against it
609cd37da74Snw141292 	 */
610cd37da74Snw141292 	q->ecanonname = ecanonname;
611cd37da74Snw141292 	q->edomain = edomain;
612*148c5f43SAlan Wright 	q->esidtype = esidtype;
613e3c2d6aaSnw141292 
614c5c4113dSnw141292 	/* Remember where to put the results */
615cd37da74Snw141292 	q->canonname = canonname;
616e8c27ec8Sbaban 	q->sid = sid;
617c5c4113dSnw141292 	q->domain = dname;
618c5c4113dSnw141292 	q->rid = rid;
619c5c4113dSnw141292 	q->sid_type = sid_type;
620c5c4113dSnw141292 	q->rc = rc;
621e8c27ec8Sbaban 	q->unixname = unixname;
62248258c6bSjp151216 	q->dn = dn;
62348258c6bSjp151216 	q->attr = attr;
62448258c6bSjp151216 	q->value = value;
625e3f2c991SKeyur Desai 	q->pid = pid;
626e8c27ec8Sbaban 
627e3f2c991SKeyur Desai 	/* Add attributes that are not always needed */
628e3f2c991SKeyur Desai 	i = 0;
629e3f2c991SKeyur Desai 	attrs[i++] = SAN;
630e3f2c991SKeyur Desai 	attrs[i++] = OBJSID;
631e3f2c991SKeyur Desai 	attrs[i++] = OBJCLASS;
632e3f2c991SKeyur Desai 
633e8c27ec8Sbaban 	if (unixname != NULL) {
634e3f2c991SKeyur Desai 		/* Add unixuser/unixgroup attribute names to the attrs list */
635*148c5f43SAlan Wright 		if (esidtype != IDMAP_GSID &&
636e8c27ec8Sbaban 		    state->ad_unixuser_attr != NULL)
637e8c27ec8Sbaban 			attrs[i++] = (char *)state->ad_unixuser_attr;
638*148c5f43SAlan Wright 		if (esidtype != IDMAP_USID &&
639e8c27ec8Sbaban 		    state->ad_unixgroup_attr != NULL)
640e3f2c991SKeyur Desai 			attrs[i++] = (char *)state->ad_unixgroup_attr;
641e8c27ec8Sbaban 	}
642c5c4113dSnw141292 
643e3f2c991SKeyur Desai 	if (pid != NULL) {
644*148c5f43SAlan Wright 		if (esidtype != IDMAP_GSID)
645e3f2c991SKeyur Desai 			attrs[i++] = UIDNUMBER;
646*148c5f43SAlan Wright 		if (esidtype != IDMAP_USID)
647e3f2c991SKeyur Desai 			attrs[i++] = GIDNUMBER;
648e3f2c991SKeyur Desai 	}
649e3f2c991SKeyur Desai 
650e3f2c991SKeyur Desai 	attrs[i] = NULL;
651e3f2c991SKeyur Desai 
652c5c4113dSnw141292 	/*
653c5c4113dSnw141292 	 * Provide sane defaults for the results in case we never hear
654c5c4113dSnw141292 	 * back from the DS before closing the connection.
655e3c2d6aaSnw141292 	 *
656e3c2d6aaSnw141292 	 * In particular we default the result to indicate a retriable
657e3c2d6aaSnw141292 	 * error.  The first complete matching result entry will cause
658e3c2d6aaSnw141292 	 * this to be set to IDMAP_SUCCESS, and the end of the results
659e3c2d6aaSnw141292 	 * for this search will cause this to indicate "not found" if no
660e3c2d6aaSnw141292 	 * result entries arrived or no complete ones matched the lookup
661e3c2d6aaSnw141292 	 * we were doing.
662c5c4113dSnw141292 	 */
663c5c4113dSnw141292 	*rc = IDMAP_ERR_RETRIABLE_NET_ERR;
664e8c27ec8Sbaban 	if (sid_type != NULL)
665*148c5f43SAlan Wright 		*sid_type = IDMAP_SID;
666e8c27ec8Sbaban 	if (sid != NULL)
667e8c27ec8Sbaban 		*sid = NULL;
668c5c4113dSnw141292 	if (dname != NULL)
669c5c4113dSnw141292 		*dname = NULL;
670c5c4113dSnw141292 	if (rid != NULL)
671c5c4113dSnw141292 		*rid = 0;
67248258c6bSjp151216 	if (dn != NULL)
67348258c6bSjp151216 		*dn = NULL;
67448258c6bSjp151216 	if (attr != NULL)
67548258c6bSjp151216 		*attr = NULL;
67648258c6bSjp151216 	if (value != NULL)
67748258c6bSjp151216 		*value = NULL;
678c5c4113dSnw141292 
679479ac375Sdm199847 	/*
680479ac375Sdm199847 	 * Don't set *canonname to NULL because it may be pointing to the
681479ac375Sdm199847 	 * given winname. Later on if we get a canonical name from AD the
682479ac375Sdm199847 	 * old name if any will be freed before assigning the new name.
683479ac375Sdm199847 	 */
684479ac375Sdm199847 
685c5c4113dSnw141292 	/*
6862b4a7802SBaban Kenkre 	 * Invoke the mother of all APIs i.e. the adutils API
687c5c4113dSnw141292 	 */
6882b4a7802SBaban Kenkre 	ad_rc = adutils_lookup_batch_add(state->qs, filter,
6892b4a7802SBaban Kenkre 	    (const char **)attrs,
6902b4a7802SBaban Kenkre 	    edomain, &q->result, &q->ad_rc);
6912b4a7802SBaban Kenkre 	return (map_adrc2idmaprc(ad_rc));
692c5c4113dSnw141292 }
693c5c4113dSnw141292 
694c5c4113dSnw141292 idmap_retcode
695c5c4113dSnw141292 idmap_name2sid_batch_add1(idmap_query_state_t *state,
696*148c5f43SAlan Wright 	const char *name, const char *dname, idmap_id_type esidtype,
69748258c6bSjp151216 	char **dn, char **attr, char **value,
69848258c6bSjp151216 	char **canonname, char **sid, rid_t *rid,
699*148c5f43SAlan Wright 	idmap_id_type *sid_type, char **unixname,
700e3f2c991SKeyur Desai 	posix_id_t *pid, idmap_retcode *rc)
701c5c4113dSnw141292 {
702c5c4113dSnw141292 	idmap_retcode	retcode;
703e3f2c991SKeyur Desai 	char		*filter, *s_name;
704cd37da74Snw141292 	char		*ecanonname, *edomain; /* expected canonname */
705c5c4113dSnw141292 
706c5c4113dSnw141292 	/*
707e3c2d6aaSnw141292 	 * Strategy: search the global catalog for user/group by
708e3c2d6aaSnw141292 	 * sAMAccountName = user/groupname with "" as the base DN and by
709e3c2d6aaSnw141292 	 * userPrincipalName = user/groupname@domain.  The result
710e3c2d6aaSnw141292 	 * entries will be checked to conform to the name and domain
711e3c2d6aaSnw141292 	 * name given here.  The DN, sAMAccountName, userPrincipalName,
712e3c2d6aaSnw141292 	 * objectSid and objectClass of the result entries are all we
713e3c2d6aaSnw141292 	 * need to figure out which entries match the lookup, the SID of
714e3c2d6aaSnw141292 	 * the user/group and whether it is a user or a group.
715c5c4113dSnw141292 	 */
716c5c4113dSnw141292 
717cd37da74Snw141292 	if ((ecanonname = strdup(name)) == NULL)
718e3c2d6aaSnw141292 		return (IDMAP_ERR_MEMORY);
719cd37da74Snw141292 
720cd37da74Snw141292 	if (dname == NULL || *dname == '\0') {
7212b4a7802SBaban Kenkre 		/* 'name' not qualified and dname not given */
722e3f2c991SKeyur Desai 		dname = state->default_domain;
7232b4a7802SBaban Kenkre 		edomain = strdup(dname);
724cd37da74Snw141292 		if (edomain == NULL) {
725cd37da74Snw141292 			free(ecanonname);
726e3c2d6aaSnw141292 			return (IDMAP_ERR_MEMORY);
727cd37da74Snw141292 		}
728cd37da74Snw141292 	} else {
729cd37da74Snw141292 		if ((edomain = strdup(dname)) == NULL) {
730cd37da74Snw141292 			free(ecanonname);
731cd37da74Snw141292 			return (IDMAP_ERR_MEMORY);
732cd37da74Snw141292 		}
733e3c2d6aaSnw141292 	}
734c5c4113dSnw141292 
7354d61c878SJulian Pullen 	if (!adutils_lookup_check_domain(state->qs, dname)) {
7364d61c878SJulian Pullen 		free(ecanonname);
7374d61c878SJulian Pullen 		free(edomain);
7384d61c878SJulian Pullen 		return (IDMAP_ERR_DOMAIN_NOTFOUND);
7394d61c878SJulian Pullen 	}
7404d61c878SJulian Pullen 
741479ac375Sdm199847 	s_name = sanitize_for_ldap_filter(name);
742479ac375Sdm199847 	if (s_name == NULL) {
743cd37da74Snw141292 		free(ecanonname);
744479ac375Sdm199847 		free(edomain);
745c5c4113dSnw141292 		return (IDMAP_ERR_MEMORY);
746c5c4113dSnw141292 	}
747479ac375Sdm199847 
748479ac375Sdm199847 	/* Assemble filter */
749e3f2c991SKeyur Desai 	(void) asprintf(&filter, SANFILTER, s_name);
750e3f2c991SKeyur Desai 	if (s_name != name)
751e3f2c991SKeyur Desai 		free(s_name);
752e3f2c991SKeyur Desai 	if (filter == NULL) {
753479ac375Sdm199847 		free(ecanonname);
754479ac375Sdm199847 		free(edomain);
755479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
756479ac375Sdm199847 	}
757c5c4113dSnw141292 
758cd37da74Snw141292 	retcode = idmap_batch_add1(state, filter, ecanonname, edomain,
759*148c5f43SAlan Wright 	    esidtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
760e3f2c991SKeyur Desai 	    unixname, pid, rc);
761c5c4113dSnw141292 
762c5c4113dSnw141292 	free(filter);
763c5c4113dSnw141292 
764c5c4113dSnw141292 	return (retcode);
765c5c4113dSnw141292 }
766c5c4113dSnw141292 
767c5c4113dSnw141292 idmap_retcode
768c5c4113dSnw141292 idmap_sid2name_batch_add1(idmap_query_state_t *state,
769*148c5f43SAlan Wright 	const char *sid, const rid_t *rid, idmap_id_type esidtype,
77048258c6bSjp151216 	char **dn, char **attr, char **value,
771*148c5f43SAlan Wright 	char **name, char **dname, idmap_id_type *sid_type,
772e3f2c991SKeyur Desai 	char **unixname, posix_id_t *pid, idmap_retcode *rc)
773c5c4113dSnw141292 {
774c5c4113dSnw141292 	idmap_retcode	retcode;
775e3f2c991SKeyur Desai 	int		ret;
776e3f2c991SKeyur Desai 	char		*filter;
7772b4a7802SBaban Kenkre 	char		cbinsid[ADUTILS_MAXHEXBINSID + 1];
778c5c4113dSnw141292 
779c5c4113dSnw141292 	/*
780c5c4113dSnw141292 	 * Strategy: search [the global catalog] for user/group by
781c5c4113dSnw141292 	 * objectSid = SID with empty base DN.  The DN, sAMAccountName
782c5c4113dSnw141292 	 * and objectClass of the result are all we need to figure out
783c5c4113dSnw141292 	 * the name of the SID and whether it is a user, a group or a
784c5c4113dSnw141292 	 * computer.
785c5c4113dSnw141292 	 */
786c5c4113dSnw141292 
7874d61c878SJulian Pullen 	if (!adutils_lookup_check_sid_prefix(state->qs, sid))
7884d61c878SJulian Pullen 		return (IDMAP_ERR_DOMAIN_NOTFOUND);
7894d61c878SJulian Pullen 
7902b4a7802SBaban Kenkre 	ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid));
791c5c4113dSnw141292 	if (ret != 0)
792c5c4113dSnw141292 		return (IDMAP_ERR_SID);
793c5c4113dSnw141292 
794c5c4113dSnw141292 	/* Assemble filter */
795e3f2c991SKeyur Desai 	(void) asprintf(&filter, OBJSIDFILTER, cbinsid);
796e3f2c991SKeyur Desai 	if (filter == NULL)
797c5c4113dSnw141292 		return (IDMAP_ERR_MEMORY);
798c5c4113dSnw141292 
799*148c5f43SAlan Wright 	retcode = idmap_batch_add1(state, filter, NULL, NULL, esidtype,
800e3f2c991SKeyur Desai 	    dn, attr, value, name, dname, NULL, NULL, sid_type, unixname,
801e3f2c991SKeyur Desai 	    pid, rc);
802e8c27ec8Sbaban 
803e8c27ec8Sbaban 	free(filter);
804e8c27ec8Sbaban 
805e8c27ec8Sbaban 	return (retcode);
806e8c27ec8Sbaban }
807e8c27ec8Sbaban 
808e8c27ec8Sbaban idmap_retcode
809e8c27ec8Sbaban idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
810e8c27ec8Sbaban 	const char *unixname, int is_user, int is_wuser,
81148258c6bSjp151216 	char **dn, char **attr, char **value,
81248258c6bSjp151216 	char **sid, rid_t *rid, char **name,
813*148c5f43SAlan Wright 	char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
814e8c27ec8Sbaban {
815e8c27ec8Sbaban 	idmap_retcode	retcode;
816e3f2c991SKeyur Desai 	char		*filter, *s_unixname;
817e3f2c991SKeyur Desai 	const char	*attrname;
818e8c27ec8Sbaban 
819e8c27ec8Sbaban 	/* Get unixuser or unixgroup AD attribute name */
820e8c27ec8Sbaban 	attrname = (is_user) ?
821e8c27ec8Sbaban 	    state->ad_unixuser_attr : state->ad_unixgroup_attr;
822e8c27ec8Sbaban 	if (attrname == NULL)
823e8c27ec8Sbaban 		return (IDMAP_ERR_NOTFOUND);
824e8c27ec8Sbaban 
825479ac375Sdm199847 	s_unixname = sanitize_for_ldap_filter(unixname);
826479ac375Sdm199847 	if (s_unixname == NULL)
827479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
828479ac375Sdm199847 
829e8c27ec8Sbaban 	/*  Assemble filter */
830e3f2c991SKeyur Desai 	(void) asprintf(&filter, "(&(objectclass=%s)(%s=%s))",
831e3f2c991SKeyur Desai 	    is_wuser ? "user" : "group", attrname, s_unixname);
832479ac375Sdm199847 	if (s_unixname != unixname)
833479ac375Sdm199847 		free(s_unixname);
834e3f2c991SKeyur Desai 	if (filter == NULL) {
835e8c27ec8Sbaban 		return (IDMAP_ERR_MEMORY);
836479ac375Sdm199847 	}
837e8c27ec8Sbaban 
838e8c27ec8Sbaban 	retcode = idmap_batch_add1(state, filter, NULL, NULL,
839*148c5f43SAlan Wright 	    IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
840e3f2c991SKeyur Desai 	    NULL, NULL, rc);
84148258c6bSjp151216 
84248258c6bSjp151216 	if (retcode == IDMAP_SUCCESS && attr != NULL) {
84348258c6bSjp151216 		if ((*attr = strdup(attrname)) == NULL)
84448258c6bSjp151216 			retcode = IDMAP_ERR_MEMORY;
84548258c6bSjp151216 	}
84648258c6bSjp151216 
84748258c6bSjp151216 	if (retcode == IDMAP_SUCCESS && value != NULL) {
84848258c6bSjp151216 		if ((*value = strdup(unixname)) == NULL)
84948258c6bSjp151216 			retcode = IDMAP_ERR_MEMORY;
85048258c6bSjp151216 	}
851e3f2c991SKeyur Desai 
852e3f2c991SKeyur Desai 	free(filter);
853e3f2c991SKeyur Desai 
854e3f2c991SKeyur Desai 	return (retcode);
855e3f2c991SKeyur Desai }
856e3f2c991SKeyur Desai 
857e3f2c991SKeyur Desai idmap_retcode
858e3f2c991SKeyur Desai idmap_pid2sid_batch_add1(idmap_query_state_t *state,
859e3f2c991SKeyur Desai 	posix_id_t pid, int is_user,
860e3f2c991SKeyur Desai 	char **dn, char **attr, char **value,
861e3f2c991SKeyur Desai 	char **sid, rid_t *rid, char **name,
862*148c5f43SAlan Wright 	char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
863e3f2c991SKeyur Desai {
864e3f2c991SKeyur Desai 	idmap_retcode	retcode;
865e3f2c991SKeyur Desai 	char		*filter;
866e3f2c991SKeyur Desai 	const char	*attrname;
867e3f2c991SKeyur Desai 
868e3f2c991SKeyur Desai 	/*  Assemble filter */
869e3f2c991SKeyur Desai 	if (is_user) {
870e3f2c991SKeyur Desai 		(void) asprintf(&filter, UIDNUMBERFILTER, pid);
871e3f2c991SKeyur Desai 		attrname = UIDNUMBER;
872e3f2c991SKeyur Desai 	} else {
873e3f2c991SKeyur Desai 		(void) asprintf(&filter, GIDNUMBERFILTER, pid);
874e3f2c991SKeyur Desai 		attrname = GIDNUMBER;
875e3f2c991SKeyur Desai 	}
876e3f2c991SKeyur Desai 	if (filter == NULL)
877e3f2c991SKeyur Desai 		return (IDMAP_ERR_MEMORY);
878e3f2c991SKeyur Desai 
879e3f2c991SKeyur Desai 	retcode = idmap_batch_add1(state, filter, NULL, NULL,
880*148c5f43SAlan Wright 	    IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
881e3f2c991SKeyur Desai 	    NULL, NULL, rc);
882e3f2c991SKeyur Desai 
883e3f2c991SKeyur Desai 	if (retcode == IDMAP_SUCCESS && attr != NULL) {
884e3f2c991SKeyur Desai 		if ((*attr = strdup(attrname)) == NULL)
885e3f2c991SKeyur Desai 			retcode = IDMAP_ERR_MEMORY;
886e3f2c991SKeyur Desai 	}
887e3f2c991SKeyur Desai 
888e3f2c991SKeyur Desai 	if (retcode == IDMAP_SUCCESS && value != NULL) {
889e3f2c991SKeyur Desai 		(void) asprintf(value, "%u", pid);
890e3f2c991SKeyur Desai 		if (*value == NULL)
891e3f2c991SKeyur Desai 			retcode = IDMAP_ERR_MEMORY;
89248258c6bSjp151216 	}
893c5c4113dSnw141292 
894c5c4113dSnw141292 	free(filter);
895c5c4113dSnw141292 
896c5c4113dSnw141292 	return (retcode);
897c5c4113dSnw141292 }
898