xref: /onnv-gate/usr/src/cmd/idmap/idmapd/adutils.c (revision 11963)
14520Snw141292 /*
24520Snw141292  * CDDL HEADER START
34520Snw141292  *
44520Snw141292  * The contents of this file are subject to the terms of the
54520Snw141292  * Common Development and Distribution License (the "License").
64520Snw141292  * You may not use this file except in compliance with the License.
74520Snw141292  *
84520Snw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94520Snw141292  * or http://www.opensolaris.org/os/licensing.
104520Snw141292  * See the License for the specific language governing permissions
114520Snw141292  * and limitations under the License.
124520Snw141292  *
134520Snw141292  * When distributing Covered Code, include this CDDL HEADER in each
144520Snw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154520Snw141292  * If applicable, add the following below this CDDL HEADER, with the
164520Snw141292  * fields enclosed by brackets "[]" replaced with your own identifying
174520Snw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
184520Snw141292  *
194520Snw141292  * CDDL HEADER END
204520Snw141292  */
214520Snw141292 
224520Snw141292 /*
23*11963SAfshin.Ardakani@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
244520Snw141292  * Use is subject to license terms.
254520Snw141292  */
264520Snw141292 
274520Snw141292 /*
284520Snw141292  * Processes name2sid & sid2name batched lookups for a given user or
294520Snw141292  * computer from an AD Directory server using GSSAPI authentication
304520Snw141292  */
314520Snw141292 
324520Snw141292 #include <stdio.h>
334520Snw141292 #include <stdlib.h>
344520Snw141292 #include <alloca.h>
354520Snw141292 #include <string.h>
364520Snw141292 #include <strings.h>
374520Snw141292 #include <lber.h>
384520Snw141292 #include <ldap.h>
394520Snw141292 #include <sasl/sasl.h>
404520Snw141292 #include <string.h>
414520Snw141292 #include <ctype.h>
424520Snw141292 #include <pthread.h>
434520Snw141292 #include <synch.h>
444520Snw141292 #include <atomic.h>
454520Snw141292 #include <errno.h>
464520Snw141292 #include <assert.h>
474520Snw141292 #include <limits.h>
488040SBaban.Kenkre@Sun.COM #include <time.h>
495696Snw141292 #include <sys/u8_textprep.h>
508040SBaban.Kenkre@Sun.COM #include "libadutils.h"
516616Sdm199847 #include "nldaputils.h"
524520Snw141292 #include "idmapd.h"
534520Snw141292 
544520Snw141292 /* Attribute names and filter format strings */
555447Snw141292 #define	SAN		"sAMAccountName"
565447Snw141292 #define	OBJSID		"objectSid"
575447Snw141292 #define	OBJCLASS	"objectClass"
5810504SKeyur.Desai@Sun.COM #define	UIDNUMBER	"uidNumber"
5910504SKeyur.Desai@Sun.COM #define	GIDNUMBER	"gidNumber"
6010504SKeyur.Desai@Sun.COM #define	UIDNUMBERFILTER	"(&(objectclass=user)(uidNumber=%u))"
6110504SKeyur.Desai@Sun.COM #define	GIDNUMBERFILTER	"(&(objectclass=group)(gidNumber=%u))"
6210504SKeyur.Desai@Sun.COM #define	SANFILTER	"(sAMAccountName=%s)"
635447Snw141292 #define	OBJSIDFILTER	"(objectSid=%s)"
644520Snw141292 
658040SBaban.Kenkre@Sun.COM void	idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc,
668040SBaban.Kenkre@Sun.COM 		int qid, void *argp);
674520Snw141292 
684520Snw141292 /*
694520Snw141292  * A place to put the results of a batched (async) query
704520Snw141292  *
714520Snw141292  * There is one of these for every query added to a batch object
724520Snw141292  * (idmap_query_state, see below).
734520Snw141292  */
744520Snw141292 typedef struct idmap_q {
755447Snw141292 	/*
765447Snw141292 	 * data used for validating search result entries for name->SID
775731Sbaban 	 * lookups
785447Snw141292 	 */
795696Snw141292 	char			*ecanonname;	/* expected canon name */
805696Snw141292 	char			*edomain;	/* expected domain name */
815731Sbaban 	int			eunixtype;	/* expected unix type */
825447Snw141292 	/* results */
835696Snw141292 	char			**canonname;	/* actual canon name */
844520Snw141292 	char			**domain;	/* name of domain of object */
855731Sbaban 	char			**sid;		/* stringified SID */
865731Sbaban 	rid_t			*rid;		/* RID */
875731Sbaban 	int			*sid_type;	/* user or group SID? */
885731Sbaban 	char			**unixname;	/* unixname for name mapping */
896386Sjp151216 	char			**dn;		/* DN of entry */
906386Sjp151216 	char			**attr;		/* Attr for name mapping */
916386Sjp151216 	char			**value;	/* value for name mapping */
9210504SKeyur.Desai@Sun.COM 	posix_id_t		*pid;		/* Posix ID found via IDMU */
934520Snw141292 	idmap_retcode		*rc;
948040SBaban.Kenkre@Sun.COM 	adutils_rc		ad_rc;
958040SBaban.Kenkre@Sun.COM 	adutils_result_t	*result;
965447Snw141292 
976531Sjp151216 	/*
986531Sjp151216 	 * The LDAP search entry result is placed here to be processed
996531Sjp151216 	 * when the search done result is received.
1006531Sjp151216 	 */
1016531Sjp151216 	LDAPMessage		*search_res;	/* The LDAP search result */
1024520Snw141292 } idmap_q_t;
1034520Snw141292 
1044520Snw141292 /* Batch context structure; typedef is in header file */
1054520Snw141292 struct idmap_query_state {
1068040SBaban.Kenkre@Sun.COM 	adutils_query_state_t	*qs;
1078361SJulian.Pullen@Sun.COM 	int			qsize;		/* Queue size */
1088361SJulian.Pullen@Sun.COM 	uint32_t		qcount;		/* Number of queued requests */
1095731Sbaban 	const char		*ad_unixuser_attr;
1105731Sbaban 	const char		*ad_unixgroup_attr;
11110504SKeyur.Desai@Sun.COM 	int			directory_based_mapping;	/* enum */
11210504SKeyur.Desai@Sun.COM 	char			*default_domain;
1134520Snw141292 	idmap_q_t		queries[1];	/* array of query results */
1144520Snw141292 };
1154520Snw141292 
1164644Sbaban static pthread_t	reaperid = 0;
1174520Snw141292 
1184520Snw141292 /*
1194520Snw141292  * Keep connection management simple for now, extend or replace later
1204520Snw141292  * with updated libsldap code.
1214520Snw141292  */
1224520Snw141292 #define	ADREAPERSLEEP	60
1234520Snw141292 
1244520Snw141292 /*
1254520Snw141292  * Idle connection reaping side of connection management
1264520Snw141292  *
1274520Snw141292  * Every minute wake up and look for connections that have been idle for
1284520Snw141292  * five minutes or more and close them.
1294520Snw141292  */
1304520Snw141292 /*ARGSUSED*/
1314520Snw141292 static
1324520Snw141292 void
1334520Snw141292 adreaper(void *arg)
1344520Snw141292 {
1354520Snw141292 	timespec_t	ts;
1364520Snw141292 
1374520Snw141292 	ts.tv_sec = ADREAPERSLEEP;
1384520Snw141292 	ts.tv_nsec = 0;
1394520Snw141292 
1404520Snw141292 	for (;;) {
1414520Snw141292 		/*
1424520Snw141292 		 * nanosleep(3RT) is thead-safe (no SIGALRM) and more
1434520Snw141292 		 * portable than usleep(3C)
1444520Snw141292 		 */
1454520Snw141292 		(void) nanosleep(&ts, NULL);
1468040SBaban.Kenkre@Sun.COM 		adutils_reap_idle_connections();
1474520Snw141292 	}
1484520Snw141292 }
1494520Snw141292 
1504520Snw141292 /*
1514520Snw141292  * Take ad_host_config_t information, create a ad_host_t,
1524520Snw141292  * populate it and add it to the list of hosts.
1534520Snw141292  */
1544520Snw141292 
1554520Snw141292 int
1568040SBaban.Kenkre@Sun.COM idmap_add_ds(adutils_ad_t *ad, const char *host, int port)
1574520Snw141292 {
1588040SBaban.Kenkre@Sun.COM 	int	ret = -1;
1594520Snw141292 
1608040SBaban.Kenkre@Sun.COM 	if (adutils_add_ds(ad, host, port) == ADUTILS_SUCCESS)
1618040SBaban.Kenkre@Sun.COM 		ret = 0;
1624520Snw141292 
1634520Snw141292 	/* Start reaper if it doesn't exist */
1648040SBaban.Kenkre@Sun.COM 	if (ret == 0 && reaperid == 0)
1654520Snw141292 		(void) pthread_create(&reaperid, NULL,
1664520Snw141292 		    (void *(*)(void *))adreaper, (void *)NULL);
1674520Snw141292 	return (ret);
1684520Snw141292 }
1694520Snw141292 
1704520Snw141292 static
1718040SBaban.Kenkre@Sun.COM idmap_retcode
1728040SBaban.Kenkre@Sun.COM map_adrc2idmaprc(adutils_rc adrc)
1734520Snw141292 {
1748040SBaban.Kenkre@Sun.COM 	switch (adrc) {
1758040SBaban.Kenkre@Sun.COM 	case ADUTILS_SUCCESS:
1768040SBaban.Kenkre@Sun.COM 		return (IDMAP_SUCCESS);
1778040SBaban.Kenkre@Sun.COM 	case ADUTILS_ERR_NOTFOUND:
1788040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_NOTFOUND);
1798040SBaban.Kenkre@Sun.COM 	case ADUTILS_ERR_MEMORY:
1808040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_MEMORY);
1818040SBaban.Kenkre@Sun.COM 	case ADUTILS_ERR_DOMAIN:
1828040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_DOMAIN);
1838040SBaban.Kenkre@Sun.COM 	case ADUTILS_ERR_OTHER:
1848040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_OTHER);
1858040SBaban.Kenkre@Sun.COM 	case ADUTILS_ERR_RETRIABLE_NET_ERR:
1868040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_RETRIABLE_NET_ERR);
1878040SBaban.Kenkre@Sun.COM 	default:
1888040SBaban.Kenkre@Sun.COM 		return (IDMAP_ERR_INTERNAL);
1894520Snw141292 	}
1908040SBaban.Kenkre@Sun.COM 	/* NOTREACHED */
1914520Snw141292 }
1924520Snw141292 
1938040SBaban.Kenkre@Sun.COM idmap_retcode
1948040SBaban.Kenkre@Sun.COM idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
19510504SKeyur.Desai@Sun.COM 	int directory_based_mapping, const char *default_domain,
1968040SBaban.Kenkre@Sun.COM 	idmap_query_state_t **state)
1974520Snw141292 {
1988040SBaban.Kenkre@Sun.COM 	idmap_query_state_t	*new_state;
1998040SBaban.Kenkre@Sun.COM 	adutils_rc		rc;
2004520Snw141292 
2014520Snw141292 	*state = NULL;
2024520Snw141292 
2038361SJulian.Pullen@Sun.COM 	assert(ad != NULL);
2044520Snw141292 
2054520Snw141292 	new_state = calloc(1, sizeof (idmap_query_state_t) +
2064520Snw141292 	    (nqueries - 1) * sizeof (idmap_q_t));
2074520Snw141292 	if (new_state == NULL)
2084520Snw141292 		return (IDMAP_ERR_MEMORY);
2094520Snw141292 
2108040SBaban.Kenkre@Sun.COM 	if ((rc = adutils_lookup_batch_start(ad, nqueries,
2118040SBaban.Kenkre@Sun.COM 	    idmap_ldap_res_search_cb, new_state, &new_state->qs))
2128040SBaban.Kenkre@Sun.COM 	    != ADUTILS_SUCCESS) {
21310504SKeyur.Desai@Sun.COM 		idmap_lookup_release_batch(&new_state);
2148040SBaban.Kenkre@Sun.COM 		return (map_adrc2idmaprc(rc));
2158040SBaban.Kenkre@Sun.COM 	}
2164520Snw141292 
21710504SKeyur.Desai@Sun.COM 	new_state->default_domain = strdup(default_domain);
21810504SKeyur.Desai@Sun.COM 	if (new_state->default_domain == NULL) {
21910504SKeyur.Desai@Sun.COM 		idmap_lookup_release_batch(&new_state);
22010504SKeyur.Desai@Sun.COM 		return (IDMAP_ERR_MEMORY);
22110504SKeyur.Desai@Sun.COM 	}
22210504SKeyur.Desai@Sun.COM 
22310504SKeyur.Desai@Sun.COM 	new_state->directory_based_mapping = directory_based_mapping;
2248361SJulian.Pullen@Sun.COM 	new_state->qsize = nqueries;
2254520Snw141292 	*state = new_state;
2264520Snw141292 	return (IDMAP_SUCCESS);
2274520Snw141292 }
2284520Snw141292 
2294520Snw141292 /*
2305731Sbaban  * Set unixuser_attr and unixgroup_attr for AD-based name mapping
2315731Sbaban  */
2325731Sbaban void
2335731Sbaban idmap_lookup_batch_set_unixattr(idmap_query_state_t *state,
2345908Sjp151216 		const char *unixuser_attr, const char *unixgroup_attr)
2355908Sjp151216 {
2365731Sbaban 	state->ad_unixuser_attr = unixuser_attr;
2375731Sbaban 	state->ad_unixgroup_attr = unixgroup_attr;
2385731Sbaban }
2395731Sbaban 
2405731Sbaban /*
2415696Snw141292  * Take parsed attribute values from a search result entry and check if
2425696Snw141292  * it is the result that was desired and, if so, set the result fields
2435696Snw141292  * of the given idmap_q_t.
2445696Snw141292  *
24510504SKeyur.Desai@Sun.COM  * Except for dn and attr, all strings are consumed, either by transferring
24610504SKeyur.Desai@Sun.COM  * them over into the request results (where the caller will eventually free
24710504SKeyur.Desai@Sun.COM  * them) or by freeing them here.  Note that this aligns with the "const"
24810504SKeyur.Desai@Sun.COM  * declarations below.
2494520Snw141292  */
2504520Snw141292 static
2515696Snw141292 void
25210504SKeyur.Desai@Sun.COM idmap_setqresults(
25310504SKeyur.Desai@Sun.COM     idmap_q_t *q,
25410504SKeyur.Desai@Sun.COM     char *san,
25510504SKeyur.Desai@Sun.COM     const char *dn,
25610504SKeyur.Desai@Sun.COM     const char *attr,
25710504SKeyur.Desai@Sun.COM     char *value,
25810504SKeyur.Desai@Sun.COM     char *sid,
25910504SKeyur.Desai@Sun.COM     rid_t rid,
26010504SKeyur.Desai@Sun.COM     int sid_type,
26110504SKeyur.Desai@Sun.COM     char *unixname,
26210504SKeyur.Desai@Sun.COM     posix_id_t pid)
2634520Snw141292 {
2645696Snw141292 	char *domain;
26510122SJordan.Brown@Sun.COM 	int err1;
2665696Snw141292 
2675696Snw141292 	assert(dn != NULL);
2685696Snw141292 
2698040SBaban.Kenkre@Sun.COM 	if ((domain = adutils_dn2dns(dn)) == NULL)
2705696Snw141292 		goto out;
2715696Snw141292 
2725731Sbaban 	if (q->ecanonname != NULL && san != NULL) {
2735731Sbaban 		/* Check that this is the canonname that we were looking for */
2745696Snw141292 		if (u8_strcmp(q->ecanonname, san, 0,
2755696Snw141292 		    U8_STRCMP_CI_LOWER, /* no normalization, for now */
2765731Sbaban 		    U8_UNICODE_LATEST, &err1) != 0 || err1 != 0)
2775731Sbaban 			goto out;
2785731Sbaban 	}
2795731Sbaban 
2805731Sbaban 	if (q->edomain != NULL) {
2815731Sbaban 		/* Check that this is the domain that we were looking for */
28210122SJordan.Brown@Sun.COM 		if (!domain_eq(q->edomain, domain))
2835696Snw141292 			goto out;
2845696Snw141292 	}
2855696Snw141292 
2866386Sjp151216 	/* Copy the DN and attr and value */
2876386Sjp151216 	if (q->dn != NULL)
2886386Sjp151216 		*q->dn = strdup(dn);
2896386Sjp151216 
2906386Sjp151216 	if (q->attr != NULL && attr != NULL)
2916386Sjp151216 		*q->attr = strdup(attr);
2926386Sjp151216 
29310504SKeyur.Desai@Sun.COM 	if (q->value != NULL && value != NULL) {
29410504SKeyur.Desai@Sun.COM 		*q->value = value;
29510504SKeyur.Desai@Sun.COM 		value = NULL;
29610504SKeyur.Desai@Sun.COM 	}
2976386Sjp151216 
2985731Sbaban 	/* Set results */
2995731Sbaban 	if (q->sid) {
3005731Sbaban 		*q->sid = sid;
3015731Sbaban 		sid = NULL;
3025731Sbaban 	}
3035731Sbaban 	if (q->rid)
3045731Sbaban 		*q->rid = rid;
3055731Sbaban 	if (q->sid_type)
3065731Sbaban 		*q->sid_type = sid_type;
3075731Sbaban 	if (q->unixname) {
3085731Sbaban 		*q->unixname = unixname;
3095731Sbaban 		unixname = NULL;
3105731Sbaban 	}
3115731Sbaban 	if (q->domain != NULL) {
3125731Sbaban 		*q->domain = domain;
3135731Sbaban 		domain = NULL;
3145731Sbaban 	}
3155731Sbaban 	if (q->canonname != NULL) {
3166616Sdm199847 		/*
3176616Sdm199847 		 * The caller may be replacing the given winname by its
3186616Sdm199847 		 * canonical name and therefore free any old name before
3196616Sdm199847 		 * overwriting the field by the canonical name.
3206616Sdm199847 		 */
3216616Sdm199847 		free(*q->canonname);
3225731Sbaban 		*q->canonname = san;
3235731Sbaban 		san = NULL;
3245731Sbaban 	}
3255731Sbaban 
326*11963SAfshin.Ardakani@Sun.COM 	if (q->pid != NULL && pid != IDMAP_SENTINEL_PID) {
32710504SKeyur.Desai@Sun.COM 		*q->pid = pid;
32810504SKeyur.Desai@Sun.COM 	}
32910504SKeyur.Desai@Sun.COM 
3308040SBaban.Kenkre@Sun.COM 	q->ad_rc = ADUTILS_SUCCESS;
3315696Snw141292 
3325696Snw141292 out:
3335696Snw141292 	/* Free unused attribute values */
3345696Snw141292 	free(san);
3355696Snw141292 	free(sid);
3365696Snw141292 	free(domain);
3375731Sbaban 	free(unixname);
33810504SKeyur.Desai@Sun.COM 	free(value);
3394520Snw141292 }
3404520Snw141292 
3414520Snw141292 #define	BVAL_CASEEQ(bv, str) \
3424520Snw141292 		(((*(bv))->bv_len == (sizeof (str) - 1)) && \
3434520Snw141292 		    strncasecmp((*(bv))->bv_val, str, (*(bv))->bv_len) == 0)
3444520Snw141292 
3454520Snw141292 /*
3465696Snw141292  * Extract the class of the result entry.  Returns 1 on success, 0 on
3475696Snw141292  * failure.
3484520Snw141292  */
3494520Snw141292 static
3505447Snw141292 int
3515696Snw141292 idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
3524520Snw141292 {
3534520Snw141292 	BerValue	**cbval;
3544520Snw141292 
3555696Snw141292 	*sid_type = _IDMAP_T_OTHER;
3564520Snw141292 	if (bvalues == NULL)
3575447Snw141292 		return (0);
3584520Snw141292 
3595696Snw141292 	/*
36010504SKeyur.Desai@Sun.COM 	 * We consider Computer to be a subclass of User, so we can just
36110504SKeyur.Desai@Sun.COM 	 * ignore Computer entries and pay attention to the accompanying
36210504SKeyur.Desai@Sun.COM 	 * User entries.
3635696Snw141292 	 */
3644520Snw141292 	for (cbval = bvalues; *cbval != NULL; cbval++) {
36510504SKeyur.Desai@Sun.COM 		if (BVAL_CASEEQ(cbval, "group")) {
3665696Snw141292 			*sid_type = _IDMAP_T_GROUP;
3675696Snw141292 			break;
36810504SKeyur.Desai@Sun.COM 		} else if (BVAL_CASEEQ(cbval, "user")) {
3695696Snw141292 			*sid_type = _IDMAP_T_USER;
37010504SKeyur.Desai@Sun.COM 			break;
3715696Snw141292 		}
3725696Snw141292 		/*
3735696Snw141292 		 * "else if (*sid_type = _IDMAP_T_USER)" then this is a
3745696Snw141292 		 * new sub-class of user -- what to do with it??
3755696Snw141292 		 */
3764520Snw141292 	}
3775447Snw141292 
3785447Snw141292 	return (1);
3794520Snw141292 }
3804520Snw141292 
3814520Snw141292 /*
3824520Snw141292  * Handle a given search result entry
3834520Snw141292  */
3844520Snw141292 static
3854520Snw141292 void
3868040SBaban.Kenkre@Sun.COM idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
3878040SBaban.Kenkre@Sun.COM 	LDAPMessage *res, LDAP *ld)
3884520Snw141292 {
3894520Snw141292 	BerValue		**bvalues;
39010504SKeyur.Desai@Sun.COM 	const char		*attr = NULL;
39110504SKeyur.Desai@Sun.COM 	char			*value = NULL;
39210504SKeyur.Desai@Sun.COM 	char			*unix_name = NULL;
39310504SKeyur.Desai@Sun.COM 	char			*dn;
3945696Snw141292 	char			*san = NULL;
3955696Snw141292 	char			*sid = NULL;
3965696Snw141292 	rid_t			rid = 0;
39710504SKeyur.Desai@Sun.COM 	int			sid_type;
39810504SKeyur.Desai@Sun.COM 	int			ok;
399*11963SAfshin.Ardakani@Sun.COM 	posix_id_t		pid = IDMAP_SENTINEL_PID;
4005447Snw141292 
4015731Sbaban 	assert(q->rc != NULL);
40210504SKeyur.Desai@Sun.COM 	assert(q->domain == NULL || *q->domain == NULL);
4035731Sbaban 
4048040SBaban.Kenkre@Sun.COM 	if ((dn = ldap_get_dn(ld, res)) == NULL)
4054520Snw141292 		return;
4064520Snw141292 
40710504SKeyur.Desai@Sun.COM 	bvalues = ldap_get_values_len(ld, res, OBJCLASS);
40810504SKeyur.Desai@Sun.COM 	if (bvalues == NULL) {
4095731Sbaban 		/*
4105731Sbaban 		 * Didn't find objectclass. Something's wrong with our
4115731Sbaban 		 * AD data.
4125731Sbaban 		 */
41310504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR, "%s has no %s", dn, OBJCLASS);
41410504SKeyur.Desai@Sun.COM 		goto out;
41510504SKeyur.Desai@Sun.COM 	}
41610504SKeyur.Desai@Sun.COM 	ok = idmap_bv_objclass2sidtype(bvalues, &sid_type);
41710504SKeyur.Desai@Sun.COM 	ldap_value_free_len(bvalues);
41810504SKeyur.Desai@Sun.COM 	if (!ok) {
4195731Sbaban 		/*
42010504SKeyur.Desai@Sun.COM 		 * Didn't understand objectclass. Something's wrong with our
42110504SKeyur.Desai@Sun.COM 		 * AD data.
4225731Sbaban 		 */
42310504SKeyur.Desai@Sun.COM 		idmapdlog(LOG_ERR, "%s has unexpected %s", dn, OBJCLASS);
42410504SKeyur.Desai@Sun.COM 		goto out;
42510504SKeyur.Desai@Sun.COM 	}
42610504SKeyur.Desai@Sun.COM 
42710504SKeyur.Desai@Sun.COM 	if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU &&
42810504SKeyur.Desai@Sun.COM 	    q->pid != NULL) {
42910504SKeyur.Desai@Sun.COM 		if (sid_type == _IDMAP_T_USER)
43010504SKeyur.Desai@Sun.COM 			attr = UIDNUMBER;
43110504SKeyur.Desai@Sun.COM 		else if (sid_type == _IDMAP_T_GROUP)
43210504SKeyur.Desai@Sun.COM 			attr = GIDNUMBER;
43310504SKeyur.Desai@Sun.COM 		if (attr != NULL) {
43410504SKeyur.Desai@Sun.COM 			bvalues = ldap_get_values_len(ld, res, attr);
43510504SKeyur.Desai@Sun.COM 			if (bvalues != NULL) {
43610504SKeyur.Desai@Sun.COM 				value = adutils_bv_str(bvalues[0]);
43710504SKeyur.Desai@Sun.COM 				if (!adutils_bv_uint(bvalues[0], &pid)) {
43810504SKeyur.Desai@Sun.COM 					idmapdlog(LOG_ERR,
43910504SKeyur.Desai@Sun.COM 					    "%s has Invalid %s value \"%s\"",
44010504SKeyur.Desai@Sun.COM 					    dn, attr, value);
44110504SKeyur.Desai@Sun.COM 				}
44210504SKeyur.Desai@Sun.COM 				ldap_value_free_len(bvalues);
44310504SKeyur.Desai@Sun.COM 			}
44410504SKeyur.Desai@Sun.COM 		}
4455731Sbaban 	}
4465731Sbaban 
44710504SKeyur.Desai@Sun.COM 	if (state->directory_based_mapping == DIRECTORY_MAPPING_NAME &&
44810504SKeyur.Desai@Sun.COM 	    q->unixname != NULL) {
44910504SKeyur.Desai@Sun.COM 		/*
45010504SKeyur.Desai@Sun.COM 		 * If the caller has requested unixname then determine the
45110504SKeyur.Desai@Sun.COM 		 * AD attribute name that will have the unixname, and retrieve
45210504SKeyur.Desai@Sun.COM 		 * its value.
45310504SKeyur.Desai@Sun.COM 		 */
45410504SKeyur.Desai@Sun.COM 		int unix_type;
45510504SKeyur.Desai@Sun.COM 		/*
45610504SKeyur.Desai@Sun.COM 		 * Determine the target UNIX type.
45710504SKeyur.Desai@Sun.COM 		 *
45810504SKeyur.Desai@Sun.COM 		 * If the caller specified one, use that.  Otherwise, give the
45910504SKeyur.Desai@Sun.COM 		 * same type that as we found for the Windows user.
46010504SKeyur.Desai@Sun.COM 		 */
46110504SKeyur.Desai@Sun.COM 		unix_type = q->eunixtype;
46210504SKeyur.Desai@Sun.COM 		if (unix_type == _IDMAP_T_UNDEF) {
46310504SKeyur.Desai@Sun.COM 			if (sid_type == _IDMAP_T_USER)
46410504SKeyur.Desai@Sun.COM 				unix_type = _IDMAP_T_USER;
46510504SKeyur.Desai@Sun.COM 			else if (sid_type == _IDMAP_T_GROUP)
46610504SKeyur.Desai@Sun.COM 				unix_type = _IDMAP_T_GROUP;
46710504SKeyur.Desai@Sun.COM 		}
46810504SKeyur.Desai@Sun.COM 
46910504SKeyur.Desai@Sun.COM 		if (unix_type == _IDMAP_T_USER)
47010504SKeyur.Desai@Sun.COM 			attr = state->ad_unixuser_attr;
47110504SKeyur.Desai@Sun.COM 		else if (unix_type == _IDMAP_T_GROUP)
47210504SKeyur.Desai@Sun.COM 			attr = state->ad_unixgroup_attr;
4734520Snw141292 
47410504SKeyur.Desai@Sun.COM 		if (attr != NULL) {
47510504SKeyur.Desai@Sun.COM 			bvalues = ldap_get_values_len(ld, res, attr);
47610504SKeyur.Desai@Sun.COM 			if (bvalues != NULL) {
47710504SKeyur.Desai@Sun.COM 				unix_name = adutils_bv_str(bvalues[0]);
47810504SKeyur.Desai@Sun.COM 				ldap_value_free_len(bvalues);
47910504SKeyur.Desai@Sun.COM 				value = strdup(unix_name);
48010504SKeyur.Desai@Sun.COM 			}
48110504SKeyur.Desai@Sun.COM 		}
48210504SKeyur.Desai@Sun.COM 	}
48310504SKeyur.Desai@Sun.COM 
48410504SKeyur.Desai@Sun.COM 	bvalues = ldap_get_values_len(ld, res, SAN);
48510504SKeyur.Desai@Sun.COM 	if (bvalues != NULL) {
48610504SKeyur.Desai@Sun.COM 		san = adutils_bv_str(bvalues[0]);
48710504SKeyur.Desai@Sun.COM 		ldap_value_free_len(bvalues);
48810504SKeyur.Desai@Sun.COM 	}
48910504SKeyur.Desai@Sun.COM 
49010504SKeyur.Desai@Sun.COM 	if (q->sid != NULL) {
49110504SKeyur.Desai@Sun.COM 		bvalues = ldap_get_values_len(ld, res, OBJSID);
49210504SKeyur.Desai@Sun.COM 		if (bvalues != NULL) {
49310504SKeyur.Desai@Sun.COM 			sid = adutils_bv_objsid2sidstr(bvalues[0], &rid);
49410504SKeyur.Desai@Sun.COM 			ldap_value_free_len(bvalues);
49510504SKeyur.Desai@Sun.COM 		}
49610504SKeyur.Desai@Sun.COM 	}
49710504SKeyur.Desai@Sun.COM 
49810504SKeyur.Desai@Sun.COM 	idmap_setqresults(q, san, dn,
49910504SKeyur.Desai@Sun.COM 	    attr, value,
50010504SKeyur.Desai@Sun.COM 	    sid, rid, sid_type,
50110504SKeyur.Desai@Sun.COM 	    unix_name, pid);
50210504SKeyur.Desai@Sun.COM 
50310504SKeyur.Desai@Sun.COM out:
5044520Snw141292 	ldap_memfree(dn);
5054520Snw141292 }
5064520Snw141292 
5078040SBaban.Kenkre@Sun.COM void
5088040SBaban.Kenkre@Sun.COM idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, int qid,
5098040SBaban.Kenkre@Sun.COM 		void *argp)
5104520Snw141292 {
5118040SBaban.Kenkre@Sun.COM 	idmap_query_state_t	*state = (idmap_query_state_t *)argp;
5128040SBaban.Kenkre@Sun.COM 	idmap_q_t		*q = &(state->queries[qid]);
5134520Snw141292 
5144520Snw141292 	switch (rc) {
5154520Snw141292 	case LDAP_RES_SEARCH_RESULT:
5168040SBaban.Kenkre@Sun.COM 		if (q->search_res != NULL) {
5178040SBaban.Kenkre@Sun.COM 			idmap_extract_object(state, q, q->search_res, ld);
5188040SBaban.Kenkre@Sun.COM 			(void) ldap_msgfree(q->search_res);
5198040SBaban.Kenkre@Sun.COM 			q->search_res = NULL;
5208040SBaban.Kenkre@Sun.COM 		} else
5218040SBaban.Kenkre@Sun.COM 			q->ad_rc = ADUTILS_ERR_NOTFOUND;
5224520Snw141292 		break;
5238040SBaban.Kenkre@Sun.COM 	case LDAP_RES_SEARCH_ENTRY:
5248040SBaban.Kenkre@Sun.COM 		if (q->search_res == NULL) {
5258040SBaban.Kenkre@Sun.COM 			q->search_res = *res;
5268040SBaban.Kenkre@Sun.COM 			*res = NULL;
5278040SBaban.Kenkre@Sun.COM 		}
5284520Snw141292 		break;
5294520Snw141292 	default:
5304520Snw141292 		break;
5314520Snw141292 	}
5324884Sjp151216 }
5334884Sjp151216 
5345447Snw141292 static
5355447Snw141292 void
5365447Snw141292 idmap_cleanup_batch(idmap_query_state_t *batch)
5375447Snw141292 {
5385447Snw141292 	int i;
5395447Snw141292 
5405447Snw141292 	for (i = 0; i < batch->qcount; i++) {
5415696Snw141292 		if (batch->queries[i].ecanonname != NULL)
5425696Snw141292 			free(batch->queries[i].ecanonname);
5435696Snw141292 		batch->queries[i].ecanonname = NULL;
5445696Snw141292 		if (batch->queries[i].edomain != NULL)
5455696Snw141292 			free(batch->queries[i].edomain);
5465696Snw141292 		batch->queries[i].edomain = NULL;
5475447Snw141292 	}
5485447Snw141292 }
5495447Snw141292 
5504884Sjp151216 /*
5514884Sjp151216  * This routine frees the idmap_query_state_t structure
5524884Sjp151216  */
5534520Snw141292 void
5544884Sjp151216 idmap_lookup_release_batch(idmap_query_state_t **state)
5554520Snw141292 {
5568040SBaban.Kenkre@Sun.COM 	if (state == NULL || *state == NULL)
5578040SBaban.Kenkre@Sun.COM 		return;
5588040SBaban.Kenkre@Sun.COM 	adutils_lookup_batch_release(&(*state)->qs);
5595447Snw141292 	idmap_cleanup_batch(*state);
56010504SKeyur.Desai@Sun.COM 	free((*state)->default_domain);
5614520Snw141292 	free(*state);
5624520Snw141292 	*state = NULL;
5634520Snw141292 }
5644520Snw141292 
5654520Snw141292 idmap_retcode
5665968Snw141292 idmap_lookup_batch_end(idmap_query_state_t **state)
5674520Snw141292 {
5688040SBaban.Kenkre@Sun.COM 	adutils_rc		ad_rc;
5698040SBaban.Kenkre@Sun.COM 	int			i;
5708040SBaban.Kenkre@Sun.COM 	idmap_query_state_t	*id_qs = *state;
5714520Snw141292 
5728040SBaban.Kenkre@Sun.COM 	ad_rc = adutils_lookup_batch_end(&id_qs->qs);
5734520Snw141292 
5748040SBaban.Kenkre@Sun.COM 	/*
5758040SBaban.Kenkre@Sun.COM 	 * Map adutils rc to idmap_retcode in each
5768040SBaban.Kenkre@Sun.COM 	 * query because consumers in dbutils.c
5778040SBaban.Kenkre@Sun.COM 	 * expects idmap_retcode.
5788040SBaban.Kenkre@Sun.COM 	 */
5798040SBaban.Kenkre@Sun.COM 	for (i = 0; i < id_qs->qcount; i++) {
5808040SBaban.Kenkre@Sun.COM 		*id_qs->queries[i].rc =
5818040SBaban.Kenkre@Sun.COM 		    map_adrc2idmaprc(id_qs->queries[i].ad_rc);
5824520Snw141292 	}
5834884Sjp151216 	idmap_lookup_release_batch(state);
5848040SBaban.Kenkre@Sun.COM 	return (map_adrc2idmaprc(ad_rc));
5854520Snw141292 }
5864520Snw141292 
5874520Snw141292 /*
5884520Snw141292  * Send one prepared search, queue up msgid, process what results are
5894520Snw141292  * available
5904520Snw141292  */
5914520Snw141292 static
5924520Snw141292 idmap_retcode
5936386Sjp151216 idmap_batch_add1(idmap_query_state_t *state, const char *filter,
5946386Sjp151216 	char *ecanonname, char *edomain, int eunixtype,
5956386Sjp151216 	char **dn, char **attr, char **value,
5966386Sjp151216 	char **canonname, char **dname,
5976386Sjp151216 	char **sid, rid_t *rid, int *sid_type, char **unixname,
59810504SKeyur.Desai@Sun.COM 	posix_id_t *pid,
5996386Sjp151216 	idmap_retcode *rc)
6004520Snw141292 {
6018040SBaban.Kenkre@Sun.COM 	adutils_rc	ad_rc;
6028040SBaban.Kenkre@Sun.COM 	int		qid, i;
6034520Snw141292 	idmap_q_t	*q;
60410504SKeyur.Desai@Sun.COM 	char	*attrs[20];	/* Plenty */
6054520Snw141292 
6068361SJulian.Pullen@Sun.COM 	qid = atomic_inc_32_nv(&state->qcount) - 1;
6074520Snw141292 	q = &(state->queries[qid]);
6084520Snw141292 
6098361SJulian.Pullen@Sun.COM 	assert(qid < state->qsize);
6108361SJulian.Pullen@Sun.COM 
6115696Snw141292 	/*
6128040SBaban.Kenkre@Sun.COM 	 * Remember the expected canonname, domainname and unix type
6138040SBaban.Kenkre@Sun.COM 	 * so we can check the results * against it
6145696Snw141292 	 */
6155696Snw141292 	q->ecanonname = ecanonname;
6165696Snw141292 	q->edomain = edomain;
6175731Sbaban 	q->eunixtype = eunixtype;
6185447Snw141292 
6194520Snw141292 	/* Remember where to put the results */
6205696Snw141292 	q->canonname = canonname;
6215731Sbaban 	q->sid = sid;
6224520Snw141292 	q->domain = dname;
6234520Snw141292 	q->rid = rid;
6244520Snw141292 	q->sid_type = sid_type;
6254520Snw141292 	q->rc = rc;
6265731Sbaban 	q->unixname = unixname;
6276386Sjp151216 	q->dn = dn;
6286386Sjp151216 	q->attr = attr;
6296386Sjp151216 	q->value = value;
63010504SKeyur.Desai@Sun.COM 	q->pid = pid;
6315731Sbaban 
63210504SKeyur.Desai@Sun.COM 	/* Add attributes that are not always needed */
63310504SKeyur.Desai@Sun.COM 	i = 0;
63410504SKeyur.Desai@Sun.COM 	attrs[i++] = SAN;
63510504SKeyur.Desai@Sun.COM 	attrs[i++] = OBJSID;
63610504SKeyur.Desai@Sun.COM 	attrs[i++] = OBJCLASS;
63710504SKeyur.Desai@Sun.COM 
6385731Sbaban 	if (unixname != NULL) {
63910504SKeyur.Desai@Sun.COM 		/* Add unixuser/unixgroup attribute names to the attrs list */
6405731Sbaban 		if (eunixtype != _IDMAP_T_GROUP &&
6415731Sbaban 		    state->ad_unixuser_attr != NULL)
6425731Sbaban 			attrs[i++] = (char *)state->ad_unixuser_attr;
6435731Sbaban 		if (eunixtype != _IDMAP_T_USER &&
6445731Sbaban 		    state->ad_unixgroup_attr != NULL)
64510504SKeyur.Desai@Sun.COM 			attrs[i++] = (char *)state->ad_unixgroup_attr;
6465731Sbaban 	}
6474520Snw141292 
64810504SKeyur.Desai@Sun.COM 	if (pid != NULL) {
64910504SKeyur.Desai@Sun.COM 		if (eunixtype != _IDMAP_T_GROUP)
65010504SKeyur.Desai@Sun.COM 			attrs[i++] = UIDNUMBER;
65110504SKeyur.Desai@Sun.COM 		if (eunixtype != _IDMAP_T_USER)
65210504SKeyur.Desai@Sun.COM 			attrs[i++] = GIDNUMBER;
65310504SKeyur.Desai@Sun.COM 	}
65410504SKeyur.Desai@Sun.COM 
65510504SKeyur.Desai@Sun.COM 	attrs[i] = NULL;
65610504SKeyur.Desai@Sun.COM 
6574520Snw141292 	/*
6584520Snw141292 	 * Provide sane defaults for the results in case we never hear
6594520Snw141292 	 * back from the DS before closing the connection.
6605447Snw141292 	 *
6615447Snw141292 	 * In particular we default the result to indicate a retriable
6625447Snw141292 	 * error.  The first complete matching result entry will cause
6635447Snw141292 	 * this to be set to IDMAP_SUCCESS, and the end of the results
6645447Snw141292 	 * for this search will cause this to indicate "not found" if no
6655447Snw141292 	 * result entries arrived or no complete ones matched the lookup
6665447Snw141292 	 * we were doing.
6674520Snw141292 	 */
6684520Snw141292 	*rc = IDMAP_ERR_RETRIABLE_NET_ERR;
6695731Sbaban 	if (sid_type != NULL)
6705731Sbaban 		*sid_type = _IDMAP_T_OTHER;
6715731Sbaban 	if (sid != NULL)
6725731Sbaban 		*sid = NULL;
6734520Snw141292 	if (dname != NULL)
6744520Snw141292 		*dname = NULL;
6754520Snw141292 	if (rid != NULL)
6764520Snw141292 		*rid = 0;
6776386Sjp151216 	if (dn != NULL)
6786386Sjp151216 		*dn = NULL;
6796386Sjp151216 	if (attr != NULL)
6806386Sjp151216 		*attr = NULL;
6816386Sjp151216 	if (value != NULL)
6826386Sjp151216 		*value = NULL;
6834520Snw141292 
6846616Sdm199847 	/*
6856616Sdm199847 	 * Don't set *canonname to NULL because it may be pointing to the
6866616Sdm199847 	 * given winname. Later on if we get a canonical name from AD the
6876616Sdm199847 	 * old name if any will be freed before assigning the new name.
6886616Sdm199847 	 */
6896616Sdm199847 
6904520Snw141292 	/*
6918040SBaban.Kenkre@Sun.COM 	 * Invoke the mother of all APIs i.e. the adutils API
6924520Snw141292 	 */
6938040SBaban.Kenkre@Sun.COM 	ad_rc = adutils_lookup_batch_add(state->qs, filter,
6948040SBaban.Kenkre@Sun.COM 	    (const char **)attrs,
6958040SBaban.Kenkre@Sun.COM 	    edomain, &q->result, &q->ad_rc);
6968040SBaban.Kenkre@Sun.COM 	return (map_adrc2idmaprc(ad_rc));
6974520Snw141292 }
6984520Snw141292 
6994520Snw141292 idmap_retcode
7004520Snw141292 idmap_name2sid_batch_add1(idmap_query_state_t *state,
7015731Sbaban 	const char *name, const char *dname, int eunixtype,
7026386Sjp151216 	char **dn, char **attr, char **value,
7036386Sjp151216 	char **canonname, char **sid, rid_t *rid,
70410504SKeyur.Desai@Sun.COM 	int *sid_type, char **unixname,
70510504SKeyur.Desai@Sun.COM 	posix_id_t *pid, idmap_retcode *rc)
7064520Snw141292 {
7074520Snw141292 	idmap_retcode	retcode;
70810504SKeyur.Desai@Sun.COM 	char		*filter, *s_name;
7095696Snw141292 	char		*ecanonname, *edomain; /* expected canonname */
7104520Snw141292 
7114520Snw141292 	/*
7125447Snw141292 	 * Strategy: search the global catalog for user/group by
7135447Snw141292 	 * sAMAccountName = user/groupname with "" as the base DN and by
7145447Snw141292 	 * userPrincipalName = user/groupname@domain.  The result
7155447Snw141292 	 * entries will be checked to conform to the name and domain
7165447Snw141292 	 * name given here.  The DN, sAMAccountName, userPrincipalName,
7175447Snw141292 	 * objectSid and objectClass of the result entries are all we
7185447Snw141292 	 * need to figure out which entries match the lookup, the SID of
7195447Snw141292 	 * the user/group and whether it is a user or a group.
7204520Snw141292 	 */
7214520Snw141292 
7225696Snw141292 	if ((ecanonname = strdup(name)) == NULL)
7235696Snw141292 		return (IDMAP_ERR_MEMORY);
7244520Snw141292 
7255447Snw141292 	if (dname == NULL || *dname == '\0') {
72610504SKeyur.Desai@Sun.COM 		/* 'name' not qualified and dname not given */
72710504SKeyur.Desai@Sun.COM 		dname = state->default_domain;
72810504SKeyur.Desai@Sun.COM 		edomain = strdup(dname);
72910504SKeyur.Desai@Sun.COM 		if (edomain == NULL) {
73010504SKeyur.Desai@Sun.COM 			free(ecanonname);
73110504SKeyur.Desai@Sun.COM 			return (IDMAP_ERR_MEMORY);
7325696Snw141292 		}
7335696Snw141292 	} else {
7345696Snw141292 		if ((edomain = strdup(dname)) == NULL) {
7355696Snw141292 			free(ecanonname);
7365447Snw141292 			return (IDMAP_ERR_MEMORY);
7375696Snw141292 		}
7385447Snw141292 	}
7394520Snw141292 
7408361SJulian.Pullen@Sun.COM 	if (!adutils_lookup_check_domain(state->qs, dname)) {
7418361SJulian.Pullen@Sun.COM 		free(ecanonname);
7428361SJulian.Pullen@Sun.COM 		free(edomain);
7438361SJulian.Pullen@Sun.COM 		return (IDMAP_ERR_DOMAIN_NOTFOUND);
7448361SJulian.Pullen@Sun.COM 	}
7458361SJulian.Pullen@Sun.COM 
7466616Sdm199847 	s_name = sanitize_for_ldap_filter(name);
7476616Sdm199847 	if (s_name == NULL) {
7486616Sdm199847 		free(ecanonname);
7496616Sdm199847 		free(edomain);
7506616Sdm199847 		return (IDMAP_ERR_MEMORY);
7516616Sdm199847 	}
7526616Sdm199847 
7534520Snw141292 	/* Assemble filter */
75410504SKeyur.Desai@Sun.COM 	(void) asprintf(&filter, SANFILTER, s_name);
75510504SKeyur.Desai@Sun.COM 	if (s_name != name)
75610504SKeyur.Desai@Sun.COM 		free(s_name);
75710504SKeyur.Desai@Sun.COM 	if (filter == NULL) {
7585696Snw141292 		free(ecanonname);
7596616Sdm199847 		free(edomain);
7604520Snw141292 		return (IDMAP_ERR_MEMORY);
7614520Snw141292 	}
7624520Snw141292 
7635696Snw141292 	retcode = idmap_batch_add1(state, filter, ecanonname, edomain,
7646386Sjp151216 	    eunixtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
76510504SKeyur.Desai@Sun.COM 	    unixname, pid, rc);
7664520Snw141292 
7674520Snw141292 	free(filter);
7684520Snw141292 
7694520Snw141292 	return (retcode);
7704520Snw141292 }
7714520Snw141292 
7724520Snw141292 idmap_retcode
7734520Snw141292 idmap_sid2name_batch_add1(idmap_query_state_t *state,
7745731Sbaban 	const char *sid, const rid_t *rid, int eunixtype,
7756386Sjp151216 	char **dn, char **attr, char **value,
7766386Sjp151216 	char **name, char **dname, int *sid_type,
77710504SKeyur.Desai@Sun.COM 	char **unixname, posix_id_t *pid, idmap_retcode *rc)
7784520Snw141292 {
7794520Snw141292 	idmap_retcode	retcode;
78010504SKeyur.Desai@Sun.COM 	int		ret;
78110504SKeyur.Desai@Sun.COM 	char		*filter;
7828040SBaban.Kenkre@Sun.COM 	char		cbinsid[ADUTILS_MAXHEXBINSID + 1];
7834520Snw141292 
7844520Snw141292 	/*
7854520Snw141292 	 * Strategy: search [the global catalog] for user/group by
7864520Snw141292 	 * objectSid = SID with empty base DN.  The DN, sAMAccountName
7874520Snw141292 	 * and objectClass of the result are all we need to figure out
7884520Snw141292 	 * the name of the SID and whether it is a user, a group or a
7894520Snw141292 	 * computer.
7904520Snw141292 	 */
7914520Snw141292 
7928361SJulian.Pullen@Sun.COM 	if (!adutils_lookup_check_sid_prefix(state->qs, sid))
7938361SJulian.Pullen@Sun.COM 		return (IDMAP_ERR_DOMAIN_NOTFOUND);
7948361SJulian.Pullen@Sun.COM 
7958040SBaban.Kenkre@Sun.COM 	ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid));
7964520Snw141292 	if (ret != 0)
7974520Snw141292 		return (IDMAP_ERR_SID);
7984520Snw141292 
7994520Snw141292 	/* Assemble filter */
80010504SKeyur.Desai@Sun.COM 	(void) asprintf(&filter, OBJSIDFILTER, cbinsid);
80110504SKeyur.Desai@Sun.COM 	if (filter == NULL)
8024520Snw141292 		return (IDMAP_ERR_MEMORY);
8034520Snw141292 
8045731Sbaban 	retcode = idmap_batch_add1(state, filter, NULL, NULL, eunixtype,
80510504SKeyur.Desai@Sun.COM 	    dn, attr, value, name, dname, NULL, NULL, sid_type, unixname,
80610504SKeyur.Desai@Sun.COM 	    pid, rc);
8074520Snw141292 
8084520Snw141292 	free(filter);
8094520Snw141292 
8104520Snw141292 	return (retcode);
8114520Snw141292 }
8125731Sbaban 
8135731Sbaban idmap_retcode
8145731Sbaban idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
8155731Sbaban 	const char *unixname, int is_user, int is_wuser,
8166386Sjp151216 	char **dn, char **attr, char **value,
8176386Sjp151216 	char **sid, rid_t *rid, char **name,
8186386Sjp151216 	char **dname, int *sid_type, idmap_retcode *rc)
8195731Sbaban {
8205731Sbaban 	idmap_retcode	retcode;
82110504SKeyur.Desai@Sun.COM 	char		*filter, *s_unixname;
82210504SKeyur.Desai@Sun.COM 	const char	*attrname;
8235731Sbaban 
8245731Sbaban 	/* Get unixuser or unixgroup AD attribute name */
8255731Sbaban 	attrname = (is_user) ?
8265731Sbaban 	    state->ad_unixuser_attr : state->ad_unixgroup_attr;
8275731Sbaban 	if (attrname == NULL)
8285731Sbaban 		return (IDMAP_ERR_NOTFOUND);
8295731Sbaban 
8306616Sdm199847 	s_unixname = sanitize_for_ldap_filter(unixname);
8316616Sdm199847 	if (s_unixname == NULL)
8326616Sdm199847 		return (IDMAP_ERR_MEMORY);
8336616Sdm199847 
8345731Sbaban 	/*  Assemble filter */
83510504SKeyur.Desai@Sun.COM 	(void) asprintf(&filter, "(&(objectclass=%s)(%s=%s))",
83610504SKeyur.Desai@Sun.COM 	    is_wuser ? "user" : "group", attrname, s_unixname);
83710504SKeyur.Desai@Sun.COM 	if (s_unixname != unixname)
83810504SKeyur.Desai@Sun.COM 		free(s_unixname);
83910504SKeyur.Desai@Sun.COM 	if (filter == NULL) {
8405731Sbaban 		return (IDMAP_ERR_MEMORY);
8416616Sdm199847 	}
8425731Sbaban 
8435731Sbaban 	retcode = idmap_batch_add1(state, filter, NULL, NULL,
8446386Sjp151216 	    _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type,
84510504SKeyur.Desai@Sun.COM 	    NULL, NULL, rc);
8466386Sjp151216 
8476386Sjp151216 	if (retcode == IDMAP_SUCCESS && attr != NULL) {
8486386Sjp151216 		if ((*attr = strdup(attrname)) == NULL)
8496386Sjp151216 			retcode = IDMAP_ERR_MEMORY;
8506386Sjp151216 	}
8516386Sjp151216 
8526386Sjp151216 	if (retcode == IDMAP_SUCCESS && value != NULL) {
85310504SKeyur.Desai@Sun.COM 		if ((*value = strdup(unixname)) == NULL)
85410504SKeyur.Desai@Sun.COM 			retcode = IDMAP_ERR_MEMORY;
8556386Sjp151216 	}
8565731Sbaban 
8575731Sbaban 	free(filter);
8585731Sbaban 
8595731Sbaban 	return (retcode);
8605731Sbaban }
86110504SKeyur.Desai@Sun.COM 
86210504SKeyur.Desai@Sun.COM idmap_retcode
86310504SKeyur.Desai@Sun.COM idmap_pid2sid_batch_add1(idmap_query_state_t *state,
86410504SKeyur.Desai@Sun.COM 	posix_id_t pid, int is_user,
86510504SKeyur.Desai@Sun.COM 	char **dn, char **attr, char **value,
86610504SKeyur.Desai@Sun.COM 	char **sid, rid_t *rid, char **name,
86710504SKeyur.Desai@Sun.COM 	char **dname, int *sid_type, idmap_retcode *rc)
86810504SKeyur.Desai@Sun.COM {
86910504SKeyur.Desai@Sun.COM 	idmap_retcode	retcode;
87010504SKeyur.Desai@Sun.COM 	char		*filter;
87110504SKeyur.Desai@Sun.COM 	const char	*attrname;
87210504SKeyur.Desai@Sun.COM 
87310504SKeyur.Desai@Sun.COM 	/*  Assemble filter */
87410504SKeyur.Desai@Sun.COM 	if (is_user) {
87510504SKeyur.Desai@Sun.COM 		(void) asprintf(&filter, UIDNUMBERFILTER, pid);
87610504SKeyur.Desai@Sun.COM 		attrname = UIDNUMBER;
87710504SKeyur.Desai@Sun.COM 	} else {
87810504SKeyur.Desai@Sun.COM 		(void) asprintf(&filter, GIDNUMBERFILTER, pid);
87910504SKeyur.Desai@Sun.COM 		attrname = GIDNUMBER;
88010504SKeyur.Desai@Sun.COM 	}
88110504SKeyur.Desai@Sun.COM 	if (filter == NULL)
88210504SKeyur.Desai@Sun.COM 		return (IDMAP_ERR_MEMORY);
88310504SKeyur.Desai@Sun.COM 
88410504SKeyur.Desai@Sun.COM 	retcode = idmap_batch_add1(state, filter, NULL, NULL,
88510504SKeyur.Desai@Sun.COM 	    _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type,
88610504SKeyur.Desai@Sun.COM 	    NULL, NULL, rc);
88710504SKeyur.Desai@Sun.COM 
88810504SKeyur.Desai@Sun.COM 	if (retcode == IDMAP_SUCCESS && attr != NULL) {
88910504SKeyur.Desai@Sun.COM 		if ((*attr = strdup(attrname)) == NULL)
89010504SKeyur.Desai@Sun.COM 			retcode = IDMAP_ERR_MEMORY;
89110504SKeyur.Desai@Sun.COM 	}
89210504SKeyur.Desai@Sun.COM 
89310504SKeyur.Desai@Sun.COM 	if (retcode == IDMAP_SUCCESS && value != NULL) {
89410504SKeyur.Desai@Sun.COM 		(void) asprintf(value, "%u", pid);
89510504SKeyur.Desai@Sun.COM 		if (*value == NULL)
89610504SKeyur.Desai@Sun.COM 			retcode = IDMAP_ERR_MEMORY;
89710504SKeyur.Desai@Sun.COM 	}
89810504SKeyur.Desai@Sun.COM 
89910504SKeyur.Desai@Sun.COM 	free(filter);
90010504SKeyur.Desai@Sun.COM 
90110504SKeyur.Desai@Sun.COM 	return (retcode);
90210504SKeyur.Desai@Sun.COM }
903