xref: /titanic_50/usr/src/cmd/idmap/idmapd/nldaputils.c (revision 08f0d8da054d72c87f9a35f2ea891d2c3541ceb5)
1e8c27ec8Sbaban /*
2e8c27ec8Sbaban  * CDDL HEADER START
3e8c27ec8Sbaban  *
4e8c27ec8Sbaban  * The contents of this file are subject to the terms of the
5e8c27ec8Sbaban  * Common Development and Distribution License (the "License").
6e8c27ec8Sbaban  * You may not use this file except in compliance with the License.
7e8c27ec8Sbaban  *
8e8c27ec8Sbaban  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e8c27ec8Sbaban  * or http://www.opensolaris.org/os/licensing.
10e8c27ec8Sbaban  * See the License for the specific language governing permissions
11e8c27ec8Sbaban  * and limitations under the License.
12e8c27ec8Sbaban  *
13e8c27ec8Sbaban  * When distributing Covered Code, include this CDDL HEADER in each
14e8c27ec8Sbaban  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e8c27ec8Sbaban  * If applicable, add the following below this CDDL HEADER, with the
16e8c27ec8Sbaban  * fields enclosed by brackets "[]" replaced with your own identifying
17e8c27ec8Sbaban  * information: Portions Copyright [yyyy] [name of copyright owner]
18e8c27ec8Sbaban  *
19e8c27ec8Sbaban  * CDDL HEADER END
20e8c27ec8Sbaban  */
21e8c27ec8Sbaban 
22e8c27ec8Sbaban /*
23*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24e8c27ec8Sbaban  * Use is subject to license terms.
25e8c27ec8Sbaban  */
26e8c27ec8Sbaban 
27e8c27ec8Sbaban /*
28e8c27ec8Sbaban  * native LDAP related utility routines
29e8c27ec8Sbaban  */
30e8c27ec8Sbaban 
31e8c27ec8Sbaban #include "idmapd.h"
32479ac375Sdm199847 #include "idmap_priv.h"
33479ac375Sdm199847 #include "ns_sldap.h"
34479ac375Sdm199847 #include "nldaputils.h"
35479ac375Sdm199847 #include <assert.h>
36479ac375Sdm199847 
37479ac375Sdm199847 /*
38479ac375Sdm199847  * The following are format strings used to construct LDAP search filters
39479ac375Sdm199847  * when looking up Native LDAP directory service. The _F_XXX_SSD format
40479ac375Sdm199847  * is used by the libsldap API if a corresponding SSD is defined in
41479ac375Sdm199847  * Native LDAP configuration. The SSD contains a string that replaces
42479ac375Sdm199847  * the first %s in _F_XXX_SSD. If no SSD is defined then the regular
43479ac375Sdm199847  * _F_XXX format is used.
44479ac375Sdm199847  *
45479ac375Sdm199847  * Note that '\\' needs to be represented as "\\5c" in LDAP filters.
46479ac375Sdm199847  */
47479ac375Sdm199847 
48479ac375Sdm199847 /* Native LDAP lookup using UNIX username */
49479ac375Sdm199847 #define	_F_GETPWNAM		"(&(objectClass=posixAccount)(uid=%s))"
50479ac375Sdm199847 #define	_F_GETPWNAM_SSD		"(&(%%s)(uid=%s))"
51479ac375Sdm199847 
52479ac375Sdm199847 /*
53479ac375Sdm199847  * Native LDAP user lookup using names of well-known SIDs
54479ac375Sdm199847  * Note the use of 1$, 2$ in the format string which basically
55479ac375Sdm199847  * allows snprintf to re-use its first two arguments.
56479ac375Sdm199847  */
57479ac375Sdm199847 #define	_F_GETPWWNAMWK \
58479ac375Sdm199847 		"(&(objectClass=posixAccount)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))"
59479ac375Sdm199847 #define	_F_GETPWWNAMWK_SSD	"(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))"
60479ac375Sdm199847 
61479ac375Sdm199847 /* Native LDAP user lookup using winname@windomain OR windomain\winname */
62479ac375Sdm199847 #define	_F_GETPWWNAMDOM \
63479ac375Sdm199847 	"(&(objectClass=posixAccount)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))"
64479ac375Sdm199847 #define	_F_GETPWWNAMDOM_SSD	"(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))"
65479ac375Sdm199847 
66479ac375Sdm199847 /* Native LDAP lookup using UID */
67479ac375Sdm199847 #define	_F_GETPWUID		"(&(objectClass=posixAccount)(uidNumber=%u))"
68479ac375Sdm199847 #define	_F_GETPWUID_SSD		"(&(%%s)(uidNumber=%u))"
69479ac375Sdm199847 
70479ac375Sdm199847 /* Native LDAP lookup using UNIX groupname */
71479ac375Sdm199847 #define	_F_GETGRNAM		"(&(objectClass=posixGroup)(cn=%s))"
72479ac375Sdm199847 #define	_F_GETGRNAM_SSD		"(&(%%s)(cn=%s))"
73479ac375Sdm199847 
74479ac375Sdm199847 /* Native LDAP group lookup using names of well-known SIDs */
75479ac375Sdm199847 #define	_F_GETGRWNAMWK \
76479ac375Sdm199847 		"(&(objectClass=posixGroup)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))"
77479ac375Sdm199847 #define	_F_GETGRWNAMWK_SSD	"(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))"
78479ac375Sdm199847 
79479ac375Sdm199847 /* Native LDAP group lookup using winname@windomain OR windomain\winname */
80479ac375Sdm199847 #define	_F_GETGRWNAMDOM \
81479ac375Sdm199847 		"(&(objectClass=posixGroup)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))"
82479ac375Sdm199847 #define	_F_GETGRWNAMDOM_SSD	"(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))"
83479ac375Sdm199847 
84479ac375Sdm199847 /* Native LDAP lookup using GID */
85479ac375Sdm199847 #define	_F_GETGRGID		"(&(objectClass=posixGroup)(gidNumber=%u))"
86479ac375Sdm199847 #define	_F_GETGRGID_SSD		"(&(%%s)(gidNumber=%u))"
87479ac375Sdm199847 
88479ac375Sdm199847 /* Native LDAP attribute names */
89479ac375Sdm199847 #define	UID			"uid"
90479ac375Sdm199847 #define	CN			"cn"
91479ac375Sdm199847 #define	UIDNUMBER		"uidnumber"
92479ac375Sdm199847 #define	GIDNUMBER		"gidnumber"
93479ac375Sdm199847 #define	DN			"dn"
94479ac375Sdm199847 
95479ac375Sdm199847 #define	IS_NLDAP_RC_FATAL(x)	((x == NS_LDAP_MEMORY) ? 1 : 0)
96479ac375Sdm199847 
97479ac375Sdm199847 typedef struct idmap_nldap_q {
98479ac375Sdm199847 	char			**winname;
99479ac375Sdm199847 	char			**windomain;
100479ac375Sdm199847 	char			**unixname;
101479ac375Sdm199847 	uid_t			*pid;
102479ac375Sdm199847 	char			**dn;
103479ac375Sdm199847 	char			**attr;
104479ac375Sdm199847 	char			**value;
105479ac375Sdm199847 	int			is_user;
106479ac375Sdm199847 	idmap_retcode		*rc;
107479ac375Sdm199847 	int			lrc;
108479ac375Sdm199847 	ns_ldap_result_t	*result;
109479ac375Sdm199847 	ns_ldap_error_t		*errorp;
110479ac375Sdm199847 	char			*filter;
111479ac375Sdm199847 	char			*udata;
112479ac375Sdm199847 } idmap_nldap_q_t;
113479ac375Sdm199847 
114479ac375Sdm199847 typedef struct idmap_nldap_query_state {
115479ac375Sdm199847 	const char		*nldap_winname_attr;
116479ac375Sdm199847 	const char		*defdom;
117479ac375Sdm199847 	int			nqueries;
118479ac375Sdm199847 	int			qid;
119479ac375Sdm199847 	int			flag;
120479ac375Sdm199847 	ns_ldap_list_batch_t	*batch;
121479ac375Sdm199847 	idmap_nldap_q_t		queries[1];
122479ac375Sdm199847 } idmap_nldap_query_state_t;
123479ac375Sdm199847 
124479ac375Sdm199847 /*
125479ac375Sdm199847  * This routine has been copied from lib/nsswitch/ldap/common/ldap_utils.c
126479ac375Sdm199847  * after removing the debug statements.
127479ac375Sdm199847  *
128479ac375Sdm199847  * This is a generic filter callback function for merging the filter
129479ac375Sdm199847  * from service search descriptor with an existing search filter. This
130479ac375Sdm199847  * routine expects userdata to contain a format string with a single %s
131479ac375Sdm199847  * in it, and will use the format string with sprintf() to insert the
132479ac375Sdm199847  * SSD filter.
133479ac375Sdm199847  *
134479ac375Sdm199847  * This routine and userdata are passed to the __ns_ldap_list_batch_add()
135479ac375Sdm199847  * API.
136479ac375Sdm199847  *
137479ac375Sdm199847  * Consider an example that uses __ns_ldap_list_batch_add() to lookup
138479ac375Sdm199847  * native LDAP directory using a given userid 'xy12345'. In this
139479ac375Sdm199847  * example the userdata will contain the filter "(&(%s)(cn=xy1234))".
140479ac375Sdm199847  * If a SSD is defined to replace the rfc2307bis specified filter
141479ac375Sdm199847  * i.e. (objectClass=posixAccount) by a site-specific filter
142479ac375Sdm199847  * say (department=sds) then this routine when called will produce
143479ac375Sdm199847  * "(&(department=sds)(uid=xy1234))" as the real search filter.
144479ac375Sdm199847  */
145479ac375Sdm199847 static
146479ac375Sdm199847 int
147479ac375Sdm199847 merge_SSD_filter(const ns_ldap_search_desc_t *desc,
148479ac375Sdm199847 	char **realfilter, const void *userdata)
149479ac375Sdm199847 {
150479ac375Sdm199847 	int	len;
151479ac375Sdm199847 	if (realfilter == NULL)
152479ac375Sdm199847 		return (NS_LDAP_INVALID_PARAM);
153479ac375Sdm199847 	*realfilter = NULL;
154479ac375Sdm199847 	if (desc == NULL || desc->filter == NULL || userdata == NULL)
155479ac375Sdm199847 		return (NS_LDAP_INVALID_PARAM);
156479ac375Sdm199847 	len = strlen(userdata) + strlen(desc->filter) + 1;
157479ac375Sdm199847 	*realfilter = (char *)malloc(len);
158479ac375Sdm199847 	if (*realfilter == NULL)
159479ac375Sdm199847 		return (NS_LDAP_MEMORY);
160479ac375Sdm199847 	(void) sprintf(*realfilter, (char *)userdata, desc->filter);
161479ac375Sdm199847 	return (NS_LDAP_SUCCESS);
162479ac375Sdm199847 }
163479ac375Sdm199847 
164479ac375Sdm199847 static
165479ac375Sdm199847 char
166479ac375Sdm199847 hex_char(int n)
167479ac375Sdm199847 {
168479ac375Sdm199847 	return ("0123456789abcdef"[n & 0xf]);
169479ac375Sdm199847 }
170479ac375Sdm199847 
171479ac375Sdm199847 /*
172479ac375Sdm199847  * If the input string contains special characters that needs to be
173479ac375Sdm199847  * escaped before the string can be used in a LDAP filter then this
174479ac375Sdm199847  * function will return a new sanitized string. Otherwise this function
175479ac375Sdm199847  * returns the input string (This saves us un-necessary memory allocations
176479ac375Sdm199847  * especially when processing a batch of requests). The caller must free
177479ac375Sdm199847  * the returned string if it isn't the input string.
178479ac375Sdm199847  *
179479ac375Sdm199847  * The escape mechanism for LDAP filter is described in RFC2254 basically
180479ac375Sdm199847  * it's \hh where hh are the two hexadecimal digits representing the ASCII
181479ac375Sdm199847  * value of the encoded character (case of hh is not significant).
182479ac375Sdm199847  * Example: * -> \2a, ( -> \28, ) -> \29, \ -> \5c,
183479ac375Sdm199847  *
184479ac375Sdm199847  * outstring = sanitize_for_ldap_filter(instring);
185479ac375Sdm199847  * if (outstring == NULL)
186479ac375Sdm199847  *	Out of memory
187479ac375Sdm199847  * else
188479ac375Sdm199847  *	Use outstring
189479ac375Sdm199847  *	if (outstring != instring)
190479ac375Sdm199847  *		free(outstring);
191479ac375Sdm199847  * done
192479ac375Sdm199847  */
193479ac375Sdm199847 char *
194479ac375Sdm199847 sanitize_for_ldap_filter(const char *str)
195479ac375Sdm199847 {
196479ac375Sdm199847 	const char	*p;
197479ac375Sdm199847 	char		*q, *s_str = NULL;
198479ac375Sdm199847 	int		n;
199479ac375Sdm199847 
200479ac375Sdm199847 	/* Get a count of special characters */
201479ac375Sdm199847 	for (p = str, n = 0; *p; p++)
202479ac375Sdm199847 		if (*p == '*' || *p == '(' || *p == ')' ||
203479ac375Sdm199847 		    *p == '\\' || *p == '%')
204479ac375Sdm199847 			n++;
205479ac375Sdm199847 	/* If count is zero then no need to sanitize */
206479ac375Sdm199847 	if (n == 0)
207479ac375Sdm199847 		return ((char *)str);
208479ac375Sdm199847 	/* Create output buffer that will contain the sanitized value */
209479ac375Sdm199847 	s_str = calloc(1, n * 2 + strlen(str) + 1);
210479ac375Sdm199847 	if (s_str == NULL)
211479ac375Sdm199847 		return (NULL);
212479ac375Sdm199847 	for (p = str, q = s_str; *p; p++) {
213479ac375Sdm199847 		if (*p == '*' || *p == '(' || *p == ')' ||
214479ac375Sdm199847 		    *p == '\\' || *p == '%') {
215479ac375Sdm199847 			*q++ = '\\';
216479ac375Sdm199847 			*q++ = hex_char(*p >> 4);
217479ac375Sdm199847 			*q++ = hex_char(*p & 0xf);
218479ac375Sdm199847 		} else
219479ac375Sdm199847 			*q++ = *p;
220479ac375Sdm199847 	}
221479ac375Sdm199847 	return (s_str);
222479ac375Sdm199847 }
223479ac375Sdm199847 
224479ac375Sdm199847 /*
225479ac375Sdm199847  * Map libsldap status to idmap  status
226479ac375Sdm199847  */
227479ac375Sdm199847 static
228479ac375Sdm199847 idmap_retcode
229479ac375Sdm199847 nldaprc2retcode(int rc)
230479ac375Sdm199847 {
231479ac375Sdm199847 	switch (rc) {
232479ac375Sdm199847 	case NS_LDAP_SUCCESS:
233479ac375Sdm199847 	case NS_LDAP_SUCCESS_WITH_INFO:
234479ac375Sdm199847 		return (IDMAP_SUCCESS);
235479ac375Sdm199847 	case NS_LDAP_NOTFOUND:
236479ac375Sdm199847 		return (IDMAP_ERR_NOTFOUND);
237479ac375Sdm199847 	case NS_LDAP_MEMORY:
238479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
239479ac375Sdm199847 	case NS_LDAP_CONFIG:
240479ac375Sdm199847 		return (IDMAP_ERR_NS_LDAP_CFG);
241479ac375Sdm199847 	case NS_LDAP_OP_FAILED:
242479ac375Sdm199847 		return (IDMAP_ERR_NS_LDAP_OP_FAILED);
243479ac375Sdm199847 	case NS_LDAP_PARTIAL:
244479ac375Sdm199847 		return (IDMAP_ERR_NS_LDAP_PARTIAL);
245479ac375Sdm199847 	case NS_LDAP_INTERNAL:
246479ac375Sdm199847 		return (IDMAP_ERR_INTERNAL);
247479ac375Sdm199847 	case NS_LDAP_INVALID_PARAM:
248479ac375Sdm199847 		return (IDMAP_ERR_ARG);
249479ac375Sdm199847 	default:
250479ac375Sdm199847 		return (IDMAP_ERR_OTHER);
251479ac375Sdm199847 	}
252479ac375Sdm199847 	/*NOTREACHED*/
253479ac375Sdm199847 }
254479ac375Sdm199847 
255479ac375Sdm199847 /*
256479ac375Sdm199847  * Create a batch for native LDAP lookup.
257479ac375Sdm199847  */
258479ac375Sdm199847 static
259479ac375Sdm199847 idmap_retcode
260479ac375Sdm199847 idmap_nldap_lookup_batch_start(int nqueries, idmap_nldap_query_state_t **qs)
261479ac375Sdm199847 {
262479ac375Sdm199847 	idmap_nldap_query_state_t	*s;
263479ac375Sdm199847 
264479ac375Sdm199847 	s = calloc(1, sizeof (*s) +
265479ac375Sdm199847 	    (nqueries - 1) * sizeof (idmap_nldap_q_t));
266479ac375Sdm199847 	if (s == NULL)
267479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
268479ac375Sdm199847 	if (__ns_ldap_list_batch_start(&s->batch) != NS_LDAP_SUCCESS) {
269479ac375Sdm199847 		free(s);
270479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
271479ac375Sdm199847 	}
272479ac375Sdm199847 	s->nqueries = nqueries;
273479ac375Sdm199847 	s->flag = NS_LDAP_KEEP_CONN;
274479ac375Sdm199847 	*qs = s;
275479ac375Sdm199847 	return (IDMAP_SUCCESS);
276479ac375Sdm199847 }
277479ac375Sdm199847 
278479ac375Sdm199847 /*
279479ac375Sdm199847  * Add a lookup by winname request to the batch.
280479ac375Sdm199847  */
281479ac375Sdm199847 static
282479ac375Sdm199847 idmap_retcode
283479ac375Sdm199847 idmap_nldap_bywinname_batch_add(idmap_nldap_query_state_t *qs,
284479ac375Sdm199847 	const char *winname, const char *windomain, int is_user,
285479ac375Sdm199847 	char **dn, char **attr, char **value,
286479ac375Sdm199847 	char **unixname, uid_t *pid, idmap_retcode *rc)
287479ac375Sdm199847 {
288479ac375Sdm199847 	idmap_nldap_q_t		*q;
289479ac375Sdm199847 	const char		*db, *filter, *udata;
290479ac375Sdm199847 	int			flen, ulen, wksid = 0;
291479ac375Sdm199847 	char			*s_winname, *s_windomain;
292479ac375Sdm199847 	const char		**attrs;
293479ac375Sdm199847 	const char		*pwd_attrs[] = {UID, UIDNUMBER, NULL, NULL};
294479ac375Sdm199847 	const char		*grp_attrs[] = {CN, GIDNUMBER, NULL, NULL};
295479ac375Sdm199847 
296479ac375Sdm199847 	s_winname = s_windomain = NULL;
297479ac375Sdm199847 	q = &(qs->queries[qs->qid++]);
298479ac375Sdm199847 	q->unixname = unixname;
299479ac375Sdm199847 	q->pid = pid;
300479ac375Sdm199847 	q->rc = rc;
301479ac375Sdm199847 	q->is_user = is_user;
302479ac375Sdm199847 	q->dn = dn;
303479ac375Sdm199847 	q->attr = attr;
304479ac375Sdm199847 	q->value = value;
305479ac375Sdm199847 
306479ac375Sdm199847 	if (is_user) {
307479ac375Sdm199847 		db = "passwd";
308*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, NULL,
309*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		    NULL, NULL) == IDMAP_SUCCESS) {
310479ac375Sdm199847 			filter = _F_GETPWWNAMWK;
311479ac375Sdm199847 			udata = _F_GETPWWNAMWK_SSD;
312479ac375Sdm199847 			wksid = 1;
313479ac375Sdm199847 		} else if (windomain != NULL) {
314479ac375Sdm199847 			filter = _F_GETPWWNAMDOM;
315479ac375Sdm199847 			udata = _F_GETPWWNAMDOM_SSD;
316479ac375Sdm199847 		} else {
317479ac375Sdm199847 			*q->rc = IDMAP_ERR_DOMAIN_NOTFOUND;
318479ac375Sdm199847 			goto errout;
319479ac375Sdm199847 		}
320479ac375Sdm199847 		pwd_attrs[2] = qs->nldap_winname_attr;
321479ac375Sdm199847 		attrs = pwd_attrs;
322479ac375Sdm199847 	} else {
323479ac375Sdm199847 		db = "group";
324*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, NULL,
325*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		    NULL, NULL) == IDMAP_SUCCESS) {
326479ac375Sdm199847 			filter = _F_GETGRWNAMWK;
327479ac375Sdm199847 			udata = _F_GETGRWNAMWK_SSD;
328479ac375Sdm199847 			wksid = 1;
329479ac375Sdm199847 		} else if (windomain != NULL) {
330479ac375Sdm199847 			filter = _F_GETGRWNAMDOM;
331479ac375Sdm199847 			udata = _F_GETGRWNAMDOM_SSD;
332479ac375Sdm199847 		} else {
333479ac375Sdm199847 			*q->rc = IDMAP_ERR_DOMAIN_NOTFOUND;
334479ac375Sdm199847 			goto errout;
335479ac375Sdm199847 		}
336479ac375Sdm199847 		grp_attrs[2] = qs->nldap_winname_attr;
337479ac375Sdm199847 		attrs = grp_attrs;
338479ac375Sdm199847 	}
339479ac375Sdm199847 
340479ac375Sdm199847 	/*
341479ac375Sdm199847 	 * Sanitize names. No need to sanitize qs->nldap_winname_attr
342479ac375Sdm199847 	 * because if it contained any of the special characters then
343479ac375Sdm199847 	 * it would have been rejected by the function that reads it
344479ac375Sdm199847 	 * from the SMF config. LDAP attribute names can only contain
345479ac375Sdm199847 	 * letters, digits or hyphens.
346479ac375Sdm199847 	 */
347479ac375Sdm199847 	s_winname = sanitize_for_ldap_filter(winname);
348479ac375Sdm199847 	if (s_winname == NULL) {
349479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
350479ac375Sdm199847 		goto errout;
351479ac375Sdm199847 	}
352479ac375Sdm199847 	/* windomain could be NULL for names of well-known SIDs */
353479ac375Sdm199847 	if (windomain != NULL) {
354479ac375Sdm199847 		s_windomain = sanitize_for_ldap_filter(windomain);
355479ac375Sdm199847 		if (s_windomain == NULL) {
356479ac375Sdm199847 			*q->rc = IDMAP_ERR_MEMORY;
357479ac375Sdm199847 			goto errout;
358479ac375Sdm199847 		}
359479ac375Sdm199847 	}
360479ac375Sdm199847 
361479ac375Sdm199847 	/* Construct the filter and udata using snprintf. */
362479ac375Sdm199847 	if (wksid) {
363479ac375Sdm199847 		flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr,
364479ac375Sdm199847 		    s_winname) + 1;
365479ac375Sdm199847 		ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr,
366479ac375Sdm199847 		    s_winname) + 1;
367479ac375Sdm199847 	} else {
368479ac375Sdm199847 		flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr,
369479ac375Sdm199847 		    s_winname, s_windomain) + 1;
370479ac375Sdm199847 		ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr,
371479ac375Sdm199847 		    s_winname, s_windomain) + 1;
372479ac375Sdm199847 	}
373479ac375Sdm199847 
374479ac375Sdm199847 	q->filter = malloc(flen);
375479ac375Sdm199847 	if (q->filter == NULL) {
376479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
377479ac375Sdm199847 		goto errout;
378479ac375Sdm199847 	}
379479ac375Sdm199847 	q->udata = malloc(ulen);
380479ac375Sdm199847 	if (q->udata == NULL) {
381479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
382479ac375Sdm199847 		goto errout;
383479ac375Sdm199847 	}
384479ac375Sdm199847 
385479ac375Sdm199847 	if (wksid) {
386479ac375Sdm199847 		(void) snprintf(q->filter, flen, filter,
387479ac375Sdm199847 		    qs->nldap_winname_attr, s_winname);
388479ac375Sdm199847 		(void) snprintf(q->udata, ulen, udata,
389479ac375Sdm199847 		    qs->nldap_winname_attr, s_winname);
390479ac375Sdm199847 	} else {
391479ac375Sdm199847 		(void) snprintf(q->filter, flen, filter,
392479ac375Sdm199847 		    qs->nldap_winname_attr, s_winname, s_windomain);
393479ac375Sdm199847 		(void) snprintf(q->udata, ulen, udata,
394479ac375Sdm199847 		    qs->nldap_winname_attr, s_winname, s_windomain);
395479ac375Sdm199847 	}
396479ac375Sdm199847 
397479ac375Sdm199847 	if (s_winname != winname)
398479ac375Sdm199847 		free(s_winname);
399479ac375Sdm199847 	if (s_windomain != windomain)
400479ac375Sdm199847 		free(s_windomain);
401479ac375Sdm199847 
402479ac375Sdm199847 	q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter,
403479ac375Sdm199847 	    merge_SSD_filter, attrs, NULL, qs->flag, &q->result,
404479ac375Sdm199847 	    &q->errorp, &q->lrc, NULL, q->udata);
405479ac375Sdm199847 
406479ac375Sdm199847 	if (IS_NLDAP_RC_FATAL(q->lrc))
407479ac375Sdm199847 		return (nldaprc2retcode(q->lrc));
408479ac375Sdm199847 	return (IDMAP_SUCCESS);
409479ac375Sdm199847 
410479ac375Sdm199847 errout:
411479ac375Sdm199847 	/* query q and its content will be freed by batch_release */
412479ac375Sdm199847 	if (s_winname != winname)
413479ac375Sdm199847 		free(s_winname);
414479ac375Sdm199847 	if (s_windomain != windomain)
415479ac375Sdm199847 		free(s_windomain);
416479ac375Sdm199847 	return (*q->rc);
417479ac375Sdm199847 }
418479ac375Sdm199847 
419479ac375Sdm199847 /*
420479ac375Sdm199847  * Add a lookup by uid/gid request to the batch.
421479ac375Sdm199847  */
422479ac375Sdm199847 static
423479ac375Sdm199847 idmap_retcode
424479ac375Sdm199847 idmap_nldap_bypid_batch_add(idmap_nldap_query_state_t *qs,
425479ac375Sdm199847 	uid_t pid, int is_user, char **dn, char **attr, char **value,
426479ac375Sdm199847 	char **winname, char **windomain,
427479ac375Sdm199847 	char **unixname, idmap_retcode *rc)
428479ac375Sdm199847 {
429479ac375Sdm199847 	idmap_nldap_q_t		*q;
430479ac375Sdm199847 	const char		*db, *filter, *udata;
431479ac375Sdm199847 	int			len;
432479ac375Sdm199847 	const char		**attrs;
433479ac375Sdm199847 	const char		*pwd_attrs[] = {UID, NULL, NULL};
434479ac375Sdm199847 	const char		*grp_attrs[] = {CN, NULL, NULL};
435479ac375Sdm199847 
436479ac375Sdm199847 	q = &(qs->queries[qs->qid++]);
437479ac375Sdm199847 	q->winname = winname;
438479ac375Sdm199847 	q->windomain = windomain;
439479ac375Sdm199847 	q->unixname = unixname;
440479ac375Sdm199847 	q->rc = rc;
441479ac375Sdm199847 	q->is_user = is_user;
442479ac375Sdm199847 	q->dn = dn;
443479ac375Sdm199847 	q->attr = attr;
444479ac375Sdm199847 	q->value = value;
445479ac375Sdm199847 
446479ac375Sdm199847 	if (is_user) {
447479ac375Sdm199847 		db = "passwd";
448479ac375Sdm199847 		filter = _F_GETPWUID;
449479ac375Sdm199847 		udata = _F_GETPWUID_SSD;
450479ac375Sdm199847 		pwd_attrs[1] = qs->nldap_winname_attr;
451479ac375Sdm199847 		attrs = pwd_attrs;
452479ac375Sdm199847 	} else {
453479ac375Sdm199847 		db = "group";
454479ac375Sdm199847 		filter = _F_GETGRGID;
455479ac375Sdm199847 		udata = _F_GETGRGID_SSD;
456479ac375Sdm199847 		grp_attrs[1] = qs->nldap_winname_attr;
457479ac375Sdm199847 		attrs = grp_attrs;
458479ac375Sdm199847 	}
459479ac375Sdm199847 
460479ac375Sdm199847 	len = snprintf(NULL, 0, filter, pid) + 1;
461479ac375Sdm199847 	q->filter = malloc(len);
462479ac375Sdm199847 	if (q->filter == NULL) {
463479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
464479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
465479ac375Sdm199847 	}
466479ac375Sdm199847 	(void) snprintf(q->filter, len, filter, pid);
467479ac375Sdm199847 
468479ac375Sdm199847 	len = snprintf(NULL, 0, udata, pid) + 1;
469479ac375Sdm199847 	q->udata = malloc(len);
470479ac375Sdm199847 	if (q->udata == NULL) {
471479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
472479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
473479ac375Sdm199847 	}
474479ac375Sdm199847 	(void) snprintf(q->udata, len, udata, pid);
475479ac375Sdm199847 
476479ac375Sdm199847 	q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter,
477479ac375Sdm199847 	    merge_SSD_filter, attrs, NULL, qs->flag, &q->result,
478479ac375Sdm199847 	    &q->errorp, &q->lrc, NULL, q->udata);
479479ac375Sdm199847 
480479ac375Sdm199847 	if (IS_NLDAP_RC_FATAL(q->lrc))
481479ac375Sdm199847 		return (nldaprc2retcode(q->lrc));
482479ac375Sdm199847 	return (IDMAP_SUCCESS);
483479ac375Sdm199847 }
484479ac375Sdm199847 
485479ac375Sdm199847 /*
486479ac375Sdm199847  * Add a lookup by user/group name request to the batch.
487479ac375Sdm199847  */
488479ac375Sdm199847 static
489479ac375Sdm199847 idmap_retcode
490479ac375Sdm199847 idmap_nldap_byunixname_batch_add(idmap_nldap_query_state_t *qs,
491479ac375Sdm199847 	const char *unixname, int is_user,
492479ac375Sdm199847 	char **dn, char **attr, char **value,
493479ac375Sdm199847 	char **winname, char **windomain, uid_t *pid, idmap_retcode *rc)
494479ac375Sdm199847 {
495479ac375Sdm199847 	idmap_nldap_q_t		*q;
496479ac375Sdm199847 	const char		*db, *filter, *udata;
497479ac375Sdm199847 	int			len;
498479ac375Sdm199847 	char			*s_unixname = NULL;
499479ac375Sdm199847 	const char		**attrs;
500479ac375Sdm199847 	const char		*pwd_attrs[] = {UIDNUMBER, NULL, NULL};
501479ac375Sdm199847 	const char		*grp_attrs[] = {GIDNUMBER, NULL, NULL};
502479ac375Sdm199847 
503479ac375Sdm199847 	q = &(qs->queries[qs->qid++]);
504479ac375Sdm199847 	q->winname = winname;
505479ac375Sdm199847 	q->windomain = windomain;
506479ac375Sdm199847 	q->pid = pid;
507479ac375Sdm199847 	q->rc = rc;
508479ac375Sdm199847 	q->is_user = is_user;
509479ac375Sdm199847 	q->dn = dn;
510479ac375Sdm199847 	q->attr = attr;
511479ac375Sdm199847 	q->value = value;
512479ac375Sdm199847 
513479ac375Sdm199847 	if (is_user) {
514479ac375Sdm199847 		db = "passwd";
515479ac375Sdm199847 		filter = _F_GETPWNAM;
516479ac375Sdm199847 		udata = _F_GETPWNAM_SSD;
517479ac375Sdm199847 		pwd_attrs[1] = qs->nldap_winname_attr;
518479ac375Sdm199847 		attrs = pwd_attrs;
519479ac375Sdm199847 	} else {
520479ac375Sdm199847 		db = "group";
521479ac375Sdm199847 		filter = _F_GETGRNAM;
522479ac375Sdm199847 		udata = _F_GETGRNAM_SSD;
523479ac375Sdm199847 		grp_attrs[1] = qs->nldap_winname_attr;
524479ac375Sdm199847 		attrs = grp_attrs;
525479ac375Sdm199847 	}
526479ac375Sdm199847 
527479ac375Sdm199847 	s_unixname = sanitize_for_ldap_filter(unixname);
528479ac375Sdm199847 	if (s_unixname == NULL) {
529479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
530479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
531479ac375Sdm199847 	}
532479ac375Sdm199847 
533479ac375Sdm199847 	len = snprintf(NULL, 0, filter, s_unixname) + 1;
534479ac375Sdm199847 	q->filter = malloc(len);
535479ac375Sdm199847 	if (q->filter == NULL) {
536479ac375Sdm199847 		if (s_unixname != unixname)
537479ac375Sdm199847 			free(s_unixname);
538479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
539479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
540479ac375Sdm199847 	}
541479ac375Sdm199847 	(void) snprintf(q->filter, len, filter, s_unixname);
542479ac375Sdm199847 
543479ac375Sdm199847 	len = snprintf(NULL, 0, udata, s_unixname) + 1;
544479ac375Sdm199847 	q->udata = malloc(len);
545479ac375Sdm199847 	if (q->udata == NULL) {
546479ac375Sdm199847 		if (s_unixname != unixname)
547479ac375Sdm199847 			free(s_unixname);
548479ac375Sdm199847 		*q->rc = IDMAP_ERR_MEMORY;
549479ac375Sdm199847 		return (IDMAP_ERR_MEMORY);
550479ac375Sdm199847 	}
551479ac375Sdm199847 	(void) snprintf(q->udata, len, udata, s_unixname);
552479ac375Sdm199847 
553479ac375Sdm199847 	if (s_unixname != unixname)
554479ac375Sdm199847 		free(s_unixname);
555479ac375Sdm199847 
556479ac375Sdm199847 	q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter,
557479ac375Sdm199847 	    merge_SSD_filter, attrs, NULL, qs->flag, &q->result,
558479ac375Sdm199847 	    &q->errorp, &q->lrc, NULL, q->udata);
559479ac375Sdm199847 
560479ac375Sdm199847 	if (IS_NLDAP_RC_FATAL(q->lrc))
561479ac375Sdm199847 		return (nldaprc2retcode(q->lrc));
562479ac375Sdm199847 	return (IDMAP_SUCCESS);
563479ac375Sdm199847 }
564479ac375Sdm199847 
565479ac375Sdm199847 /*
566479ac375Sdm199847  * Free the batch
567479ac375Sdm199847  */
568479ac375Sdm199847 static
569479ac375Sdm199847 void
570479ac375Sdm199847 idmap_nldap_lookup_batch_release(idmap_nldap_query_state_t *qs)
571479ac375Sdm199847 {
572479ac375Sdm199847 	idmap_nldap_q_t		*q;
573479ac375Sdm199847 	int			i;
574479ac375Sdm199847 
575479ac375Sdm199847 	if (qs->batch != NULL)
576479ac375Sdm199847 		(void) __ns_ldap_list_batch_release(qs->batch);
577479ac375Sdm199847 	for (i = 0; i < qs->qid; i++) {
578479ac375Sdm199847 		q = &(qs->queries[i]);
579479ac375Sdm199847 		free(q->filter);
580479ac375Sdm199847 		free(q->udata);
581479ac375Sdm199847 		if (q->errorp != NULL)
582479ac375Sdm199847 			(void) __ns_ldap_freeError(&q->errorp);
583479ac375Sdm199847 		if (q->result != NULL)
584479ac375Sdm199847 			(void) __ns_ldap_freeResult(&q->result);
585479ac375Sdm199847 	}
586479ac375Sdm199847 	free(qs);
587479ac375Sdm199847 }
588479ac375Sdm199847 
589479ac375Sdm199847 /*
590479ac375Sdm199847  * Process all requests added to the batch and then free the batch.
591479ac375Sdm199847  * The results for individual requests will be accessible using the
592479ac375Sdm199847  * pointers passed during idmap_nldap_lookup_batch_end.
593479ac375Sdm199847  */
594479ac375Sdm199847 static
595479ac375Sdm199847 idmap_retcode
596479ac375Sdm199847 idmap_nldap_lookup_batch_end(idmap_nldap_query_state_t *qs)
597479ac375Sdm199847 {
598479ac375Sdm199847 	idmap_nldap_q_t		*q;
599479ac375Sdm199847 	int			i;
600479ac375Sdm199847 	ns_ldap_entry_t		*entry;
601479ac375Sdm199847 	char			**val, *end, *str, *name, *dom;
602479ac375Sdm199847 	idmap_retcode		rc = IDMAP_SUCCESS;
603479ac375Sdm199847 
604479ac375Sdm199847 	(void) __ns_ldap_list_batch_end(qs->batch);
605479ac375Sdm199847 	qs->batch = NULL;
606479ac375Sdm199847 	for (i = 0; i < qs->qid; i++) {
607479ac375Sdm199847 		q = &(qs->queries[i]);
608479ac375Sdm199847 		*q->rc = nldaprc2retcode(q->lrc);
609479ac375Sdm199847 		if (*q->rc != IDMAP_SUCCESS)
610479ac375Sdm199847 			continue;
611479ac375Sdm199847 		if (q->result == NULL ||
612479ac375Sdm199847 		    !q->result->entries_count ||
613479ac375Sdm199847 		    (entry = q->result->entry) == NULL ||
614479ac375Sdm199847 		    !entry->attr_count) {
615479ac375Sdm199847 			*q->rc = IDMAP_ERR_NOTFOUND;
616479ac375Sdm199847 			continue;
617479ac375Sdm199847 		}
618479ac375Sdm199847 		/* Get uid/gid */
619479ac375Sdm199847 		if (q->pid != NULL) {
620479ac375Sdm199847 			val = __ns_ldap_getAttr(entry,
621479ac375Sdm199847 			    (q->is_user) ? UIDNUMBER : GIDNUMBER);
622479ac375Sdm199847 			if (val != NULL && *val != NULL)
623479ac375Sdm199847 				*q->pid = strtoul(*val, &end, 10);
624479ac375Sdm199847 		}
625479ac375Sdm199847 		/* Get unixname */
626479ac375Sdm199847 		if (q->unixname != NULL) {
627479ac375Sdm199847 			val = __ns_ldap_getAttr(entry,
628479ac375Sdm199847 			    (q->is_user) ? UID : CN);
629479ac375Sdm199847 			if (val != NULL && *val != NULL) {
630479ac375Sdm199847 				*q->unixname = strdup(*val);
631479ac375Sdm199847 				if (*q->unixname == NULL) {
632479ac375Sdm199847 					rc = *q->rc = IDMAP_ERR_MEMORY;
633479ac375Sdm199847 					goto out;
634479ac375Sdm199847 				}
635479ac375Sdm199847 			}
636479ac375Sdm199847 		}
637479ac375Sdm199847 		/* Get DN for how info */
638479ac375Sdm199847 		if (q->dn != NULL) {
639479ac375Sdm199847 			val = __ns_ldap_getAttr(entry, DN);
640479ac375Sdm199847 			if (val != NULL && *val != NULL) {
641479ac375Sdm199847 				*q->dn = strdup(*val);
642479ac375Sdm199847 				if (*q->dn == NULL) {
643479ac375Sdm199847 					rc = *q->rc = IDMAP_ERR_MEMORY;
644479ac375Sdm199847 					goto out;
645479ac375Sdm199847 				}
646479ac375Sdm199847 			}
647479ac375Sdm199847 		}
648479ac375Sdm199847 		/* Get nldap name mapping attr name for how info */
649479ac375Sdm199847 		if (q->attr != NULL) {
650479ac375Sdm199847 			*q->attr = strdup(qs->nldap_winname_attr);
651479ac375Sdm199847 			if (*q->attr == NULL) {
652479ac375Sdm199847 				rc = *q->rc = IDMAP_ERR_MEMORY;
653479ac375Sdm199847 				goto out;
654479ac375Sdm199847 			}
655479ac375Sdm199847 		}
656479ac375Sdm199847 		/* Get nldap name mapping attr value for how info */
657479ac375Sdm199847 		val =  __ns_ldap_getAttr(entry, qs->nldap_winname_attr);
658479ac375Sdm199847 		if (val == NULL || *val == NULL)
659479ac375Sdm199847 			continue;
660479ac375Sdm199847 		if (q->value != NULL) {
661479ac375Sdm199847 			*q->value = strdup(*val);
662479ac375Sdm199847 			if (*q->value == NULL) {
663479ac375Sdm199847 				rc = *q->rc = IDMAP_ERR_MEMORY;
664479ac375Sdm199847 				goto out;
665479ac375Sdm199847 			}
666479ac375Sdm199847 		}
667479ac375Sdm199847 
668479ac375Sdm199847 		/* Get winname and windomain */
669479ac375Sdm199847 		if (q->winname == NULL && q->windomain == NULL)
670479ac375Sdm199847 			continue;
671479ac375Sdm199847 		/*
672479ac375Sdm199847 		 * We need to split the value into winname and
673479ac375Sdm199847 		 * windomain. The value could be either in NT4
674479ac375Sdm199847 		 * style (i.e. dom\name) or AD-style (i.e. name@dom).
675479ac375Sdm199847 		 * We choose the first '\\' if it's in NT4 style and
676479ac375Sdm199847 		 * the last '@' if it's in AD-style for the split.
677479ac375Sdm199847 		 */
678479ac375Sdm199847 		name = dom = NULL;
679*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (lookup_wksids_name2sid(*val, NULL, NULL, NULL, NULL, NULL,
680*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 		    NULL) == IDMAP_SUCCESS) {
681479ac375Sdm199847 			name = *val;
682479ac375Sdm199847 			dom = NULL;
683479ac375Sdm199847 		} else if ((str = strchr(*val, '\\')) != NULL) {
684479ac375Sdm199847 			*str = '\0';
685479ac375Sdm199847 			name = str + 1;
686479ac375Sdm199847 			dom = *val;
687479ac375Sdm199847 		} else if ((str = strrchr(*val, '@')) != NULL) {
688479ac375Sdm199847 			*str = '\0';
689479ac375Sdm199847 			name = *val;
690479ac375Sdm199847 			dom = str + 1;
691479ac375Sdm199847 		} else {
692479ac375Sdm199847 			idmapdlog(LOG_INFO, "Domain-less "
693479ac375Sdm199847 			    "winname (%s) found in Native LDAP", *val);
694479ac375Sdm199847 			*q->rc = IDMAP_ERR_NS_LDAP_BAD_WINNAME;
695479ac375Sdm199847 			continue;
696479ac375Sdm199847 		}
697479ac375Sdm199847 		if (q->winname != NULL) {
698479ac375Sdm199847 			*q->winname = strdup(name);
699479ac375Sdm199847 			if (*q->winname == NULL) {
700479ac375Sdm199847 				rc = *q->rc = IDMAP_ERR_MEMORY;
701479ac375Sdm199847 				goto out;
702479ac375Sdm199847 			}
703479ac375Sdm199847 		}
704479ac375Sdm199847 		if (q->windomain != NULL && dom != NULL) {
705479ac375Sdm199847 			*q->windomain = strdup(dom);
706479ac375Sdm199847 			if (*q->windomain == NULL) {
707479ac375Sdm199847 				rc = *q->rc = IDMAP_ERR_MEMORY;
708479ac375Sdm199847 				goto out;
709479ac375Sdm199847 			}
710479ac375Sdm199847 		}
711479ac375Sdm199847 	}
712479ac375Sdm199847 
713479ac375Sdm199847 out:
714479ac375Sdm199847 	(void) idmap_nldap_lookup_batch_release(qs);
715479ac375Sdm199847 	return (rc);
716479ac375Sdm199847 }
717e8c27ec8Sbaban 
718e8c27ec8Sbaban /* ARGSUSED */
719e8c27ec8Sbaban idmap_retcode
720479ac375Sdm199847 nldap_lookup_one(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res)
721e8c27ec8Sbaban {
722479ac375Sdm199847 	idmap_mapping_batch	batch;
723479ac375Sdm199847 	idmap_ids_res		result;
724479ac375Sdm199847 
725479ac375Sdm199847 	/* Using nldap_lookup_batch() */
726479ac375Sdm199847 
727479ac375Sdm199847 	batch.idmap_mapping_batch_len = 1;
728479ac375Sdm199847 	batch.idmap_mapping_batch_val = req;
729479ac375Sdm199847 	result.ids.ids_len = 1;
730479ac375Sdm199847 	result.ids.ids_val = res;
731479ac375Sdm199847 	return (nldap_lookup_batch(state, &batch, &result));
732e8c27ec8Sbaban }
733e8c27ec8Sbaban 
734e8c27ec8Sbaban /* ARGSUSED */
735e8c27ec8Sbaban idmap_retcode
736e8c27ec8Sbaban nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch,
737e8c27ec8Sbaban 		idmap_ids_res *result)
738e8c27ec8Sbaban {
739479ac375Sdm199847 	idmap_retcode			retcode, rc1;
740479ac375Sdm199847 	int				i, add, is_wuser;
741479ac375Sdm199847 	idmap_mapping			*req;
742479ac375Sdm199847 	idmap_id_res			*res;
743479ac375Sdm199847 	idmap_nldap_query_state_t	*qs = NULL;
744479ac375Sdm199847 	idmap_how			*how;
745479ac375Sdm199847 
746479ac375Sdm199847 	if (state->nldap_nqueries == 0)
747479ac375Sdm199847 		return (IDMAP_SUCCESS);
748479ac375Sdm199847 
749479ac375Sdm199847 	/* Create nldap lookup batch */
750479ac375Sdm199847 	retcode = idmap_nldap_lookup_batch_start(state->nldap_nqueries, &qs);
751479ac375Sdm199847 	if (retcode != IDMAP_SUCCESS) {
752479ac375Sdm199847 		idmapdlog(LOG_ERR,
753479ac375Sdm199847 		    "Failed to create batch for native LDAP lookup");
754479ac375Sdm199847 		goto out;
755479ac375Sdm199847 	}
756479ac375Sdm199847 
757479ac375Sdm199847 	qs->nldap_winname_attr = state->nldap_winname_attr;
758479ac375Sdm199847 	qs->defdom = state->defdom;
759479ac375Sdm199847 
760479ac375Sdm199847 	/* Add requests to the batch */
761479ac375Sdm199847 	for (i = 0, add = 0; i < batch->idmap_mapping_batch_len; i++) {
762479ac375Sdm199847 		req = &batch->idmap_mapping_batch_val[i];
763479ac375Sdm199847 		res = &result->ids.ids_val[i];
764479ac375Sdm199847 		retcode = IDMAP_SUCCESS;
765479ac375Sdm199847 
766479ac375Sdm199847 		/* Skip if not marked for nldap lookup */
767479ac375Sdm199847 		if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP))
768479ac375Sdm199847 			continue;
769479ac375Sdm199847 
770479ac375Sdm199847 		if (IS_REQUEST_SID(*req, 1)) {
771479ac375Sdm199847 
772479ac375Sdm199847 			/* win2unix request: */
773479ac375Sdm199847 
774e8c27ec8Sbaban 			/*
775479ac375Sdm199847 			 * When processing a win2unix request, nldap lookup
776479ac375Sdm199847 			 * is performed after AD lookup or a successful
777479ac375Sdm199847 			 * name-cache lookup. Therefore we should already
778479ac375Sdm199847 			 * have sid, winname and sidtype. Note that
779479ac375Sdm199847 			 * windomain could be NULL e.g. well-known SIDs.
780e8c27ec8Sbaban 			 */
781479ac375Sdm199847 			assert(req->id1name != NULL &&
782479ac375Sdm199847 			    (res->id.idtype == IDMAP_UID ||
783479ac375Sdm199847 			    res->id.idtype == IDMAP_GID));
784479ac375Sdm199847 
785479ac375Sdm199847 			/* Skip if we already have pid and unixname */
786479ac375Sdm199847 			if (req->id2name != NULL &&
787479ac375Sdm199847 			    res->id.idmap_id_u.uid != SENTINEL_PID) {
788479ac375Sdm199847 				res->retcode = IDMAP_SUCCESS;
789479ac375Sdm199847 				continue;
790479ac375Sdm199847 			}
791479ac375Sdm199847 
792479ac375Sdm199847 			/* Clear leftover value */
793479ac375Sdm199847 			free(req->id2name);
794479ac375Sdm199847 			req->id2name = NULL;
795479ac375Sdm199847 
796479ac375Sdm199847 			/* Lookup nldap by winname to get pid and unixname */
797479ac375Sdm199847 			add = 1;
798479ac375Sdm199847 			idmap_info_free(&res->info);
799479ac375Sdm199847 			res->info.src = IDMAP_MAP_SRC_NEW;
800479ac375Sdm199847 			how = &res->info.how;
801479ac375Sdm199847 			how->map_type = IDMAP_MAP_TYPE_DS_NLDAP;
802479ac375Sdm199847 			retcode = idmap_nldap_bywinname_batch_add(
803479ac375Sdm199847 			    qs, req->id1name, req->id1domain,
804479ac375Sdm199847 			    (res->id.idtype == IDMAP_UID) ? 1 : 0,
805479ac375Sdm199847 			    &how->idmap_how_u.nldap.dn,
806479ac375Sdm199847 			    &how->idmap_how_u.nldap.attr,
807479ac375Sdm199847 			    &how->idmap_how_u.nldap.value,
808479ac375Sdm199847 			    &req->id2name, &res->id.idmap_id_u.uid,
809479ac375Sdm199847 			    &res->retcode);
810479ac375Sdm199847 
811479ac375Sdm199847 		} else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) {
812479ac375Sdm199847 
813479ac375Sdm199847 			/* unix2win request: */
814479ac375Sdm199847 
815479ac375Sdm199847 			/* Skip if we already have winname */
816479ac375Sdm199847 			if (req->id2name != NULL) {
817479ac375Sdm199847 				res->retcode = IDMAP_SUCCESS;
818479ac375Sdm199847 				continue;
819479ac375Sdm199847 			}
820479ac375Sdm199847 
821479ac375Sdm199847 			/* Clear old value */
822479ac375Sdm199847 			free(req->id2domain);
823479ac375Sdm199847 			req->id2domain = NULL;
824479ac375Sdm199847 
825479ac375Sdm199847 			/* Set how info */
826479ac375Sdm199847 			idmap_info_free(&res->info);
827479ac375Sdm199847 			res->info.src = IDMAP_MAP_SRC_NEW;
828479ac375Sdm199847 			how = &res->info.how;
829479ac375Sdm199847 			how->map_type = IDMAP_MAP_TYPE_DS_NLDAP;
830479ac375Sdm199847 
831479ac375Sdm199847 			/* Lookup nldap by pid or unixname to get winname */
832479ac375Sdm199847 			if (req->id1.idmap_id_u.uid != SENTINEL_PID) {
833479ac375Sdm199847 				add = 1;
834479ac375Sdm199847 				retcode = idmap_nldap_bypid_batch_add(
835479ac375Sdm199847 				    qs, req->id1.idmap_id_u.uid,
836479ac375Sdm199847 				    (req->id1.idtype == IDMAP_UID) ? 1 : 0,
837479ac375Sdm199847 				    &how->idmap_how_u.nldap.dn,
838479ac375Sdm199847 				    &how->idmap_how_u.nldap.attr,
839479ac375Sdm199847 				    &how->idmap_how_u.nldap.value,
840479ac375Sdm199847 				    &req->id2name, &req->id2domain,
841479ac375Sdm199847 				    (req->id1name == NULL) ?
842479ac375Sdm199847 				    &req->id1name : NULL,
843479ac375Sdm199847 				    &res->retcode);
844479ac375Sdm199847 			} else if (req->id1name != NULL) {
845479ac375Sdm199847 				add = 1;
846479ac375Sdm199847 				retcode = idmap_nldap_byunixname_batch_add(
847479ac375Sdm199847 				    qs, req->id1name,
848479ac375Sdm199847 				    (req->id1.idtype == IDMAP_UID) ? 1 : 0,
849479ac375Sdm199847 				    &how->idmap_how_u.nldap.dn,
850479ac375Sdm199847 				    &how->idmap_how_u.nldap.attr,
851479ac375Sdm199847 				    &how->idmap_how_u.nldap.value,
852479ac375Sdm199847 				    &req->id2name, &req->id2domain,
853479ac375Sdm199847 				    &req->id1.idmap_id_u.uid, &res->retcode);
854479ac375Sdm199847 			}
855479ac375Sdm199847 
856479ac375Sdm199847 		}
857479ac375Sdm199847 
858479ac375Sdm199847 		/*
859479ac375Sdm199847 		 * nldap_batch_add API returns error only on fatal failures
860479ac375Sdm199847 		 * otherwise it returns success and the actual status
861479ac375Sdm199847 		 * is stored in the individual request (res->retcode).
862479ac375Sdm199847 		 * Stop adding requests to this batch on fatal failures
863479ac375Sdm199847 		 * (i.e. if retcode != success)
864479ac375Sdm199847 		 */
865479ac375Sdm199847 		if (retcode != IDMAP_SUCCESS)
866479ac375Sdm199847 			break;
867479ac375Sdm199847 	}
868479ac375Sdm199847 
869479ac375Sdm199847 	if (!add)
870479ac375Sdm199847 		idmap_nldap_lookup_batch_release(qs);
871479ac375Sdm199847 	else if (retcode != IDMAP_SUCCESS)
872479ac375Sdm199847 		idmap_nldap_lookup_batch_release(qs);
873479ac375Sdm199847 	else
874479ac375Sdm199847 		retcode = idmap_nldap_lookup_batch_end(qs);
875479ac375Sdm199847 
876479ac375Sdm199847 out:
877479ac375Sdm199847 	for (i = 0; i < batch->idmap_mapping_batch_len; i++) {
878479ac375Sdm199847 		req = &batch->idmap_mapping_batch_val[i];
879479ac375Sdm199847 		res = &result->ids.ids_val[i];
880479ac375Sdm199847 		if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP))
881479ac375Sdm199847 			continue;
882479ac375Sdm199847 
883479ac375Sdm199847 		/* Reset nldap flag */
884479ac375Sdm199847 		req->direction &= ~(_IDMAP_F_LOOKUP_NLDAP);
885479ac375Sdm199847 
886479ac375Sdm199847 		/*
887479ac375Sdm199847 		 * As noted earlier retcode != success if there were fatal
888479ac375Sdm199847 		 * errors during batch_start and batch_adds. If so then set
889479ac375Sdm199847 		 * the status of each nldap request to that error.
890479ac375Sdm199847 		 */
891479ac375Sdm199847 		if (retcode != IDMAP_SUCCESS) {
892479ac375Sdm199847 			res->retcode = retcode;
893479ac375Sdm199847 			continue;
894479ac375Sdm199847 		}
895479ac375Sdm199847 		if (!add)
896479ac375Sdm199847 			continue;
897479ac375Sdm199847 
898479ac375Sdm199847 		/*
899479ac375Sdm199847 		 * If we successfully retrieved winname from nldap entry
900479ac375Sdm199847 		 * then lookup winname2sid locally. If not found locally
901479ac375Sdm199847 		 * then mark this request for AD lookup.
902479ac375Sdm199847 		 */
903479ac375Sdm199847 		if (res->retcode == IDMAP_SUCCESS &&
904479ac375Sdm199847 		    req->id2name != NULL &&
905479ac375Sdm199847 		    res->id.idmap_id_u.sid.prefix == NULL &&
906479ac375Sdm199847 		    (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req))) {
907479ac375Sdm199847 
908479ac375Sdm199847 			is_wuser = -1;
909479ac375Sdm199847 			rc1 = lookup_name2sid(state->cache,
910*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 			    req->id2name, req->id2domain, &is_wuser,
911*08f0d8daSafshin salek ardakani - Sun Microsystems - Irvine United States 			    NULL, NULL,
912479ac375Sdm199847 			    &res->id.idmap_id_u.sid.prefix,
913479ac375Sdm199847 			    &res->id.idmap_id_u.sid.rid, req, 1);
914479ac375Sdm199847 			if (rc1 == IDMAP_SUCCESS)
915479ac375Sdm199847 				res->id.idtype =
916479ac375Sdm199847 				    is_wuser ? IDMAP_USID : IDMAP_GSID;
917479ac375Sdm199847 			else if (rc1 == IDMAP_ERR_NOTFOUND) {
918479ac375Sdm199847 				req->direction |= _IDMAP_F_LOOKUP_AD;
919479ac375Sdm199847 				state->ad_nqueries++;
920479ac375Sdm199847 			} else
921479ac375Sdm199847 				res->retcode = rc1;
922479ac375Sdm199847 		}
923479ac375Sdm199847 
924479ac375Sdm199847 		/*
925479ac375Sdm199847 		 * Unset non-fatal errors in individual request. This allows
926479ac375Sdm199847 		 * the next pass to process other mapping mechanisms for
927479ac375Sdm199847 		 * this request.
928479ac375Sdm199847 		 */
929479ac375Sdm199847 		if (res->retcode != IDMAP_SUCCESS &&
930479ac375Sdm199847 		    res->retcode != IDMAP_ERR_NS_LDAP_BAD_WINNAME &&
931479ac375Sdm199847 		    !(IDMAP_FATAL_ERROR(res->retcode))) {
932479ac375Sdm199847 			idmap_info_free(&res->info);
933479ac375Sdm199847 			res->retcode = IDMAP_SUCCESS;
934479ac375Sdm199847 		}
935479ac375Sdm199847 	}
936479ac375Sdm199847 
937479ac375Sdm199847 	state->nldap_nqueries = 0;
938479ac375Sdm199847 	return (retcode);
939e8c27ec8Sbaban }
940