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 /*
2212065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
234520Snw141292  */
244520Snw141292 
254520Snw141292 
264520Snw141292 /*
274520Snw141292  * libidmap API
284520Snw141292  */
294520Snw141292 
304520Snw141292 #include <stdlib.h>
316616Sdm199847 #include <sys/varargs.h>
324520Snw141292 #include <inttypes.h>
334520Snw141292 #include <errno.h>
344520Snw141292 #include <strings.h>
354520Snw141292 #include <ctype.h>
364520Snw141292 #include <sys/param.h>
374520Snw141292 #include <sys/types.h>
384520Snw141292 #include <sys/stat.h>
394520Snw141292 #include <dlfcn.h>
404520Snw141292 #include <libintl.h>
415232Snw141292 #include <ucontext.h>
4212065SKeyur.Desai@Sun.COM #include <syslog.h>
43*12508Samw@Sun.COM #include <assert.h>
444520Snw141292 #include "idmap_impl.h"
457369SJulian.Pullen@Sun.COM #include "idmap_cache.h"
464520Snw141292 
474520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
484520Snw141292 
494520Snw141292 static int idmap_stat2errno(idmap_stat);
506616Sdm199847 static idmap_stat	idmap_strdupnull(char **, const char *);
514520Snw141292 
524520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
534520Snw141292 	if (handl == NULL) {\
544520Snw141292 		errno = EINVAL;\
554520Snw141292 		return (IDMAP_ERR_ARG);\
564520Snw141292 	}\
574520Snw141292 	itera = calloc(1, sizeof (*itera));\
584520Snw141292 	if (itera == NULL) {\
594520Snw141292 		errno = ENOMEM;\
604520Snw141292 		return (IDMAP_ERR_MEMORY);\
614520Snw141292 	}\
624520Snw141292 	argu = calloc(1, sizeof (*argu));\
634520Snw141292 	if (argu == NULL) {\
644520Snw141292 		free(itera);\
654520Snw141292 		errno = ENOMEM;\
664520Snw141292 		return (IDMAP_ERR_MEMORY);\
674520Snw141292 	}\
684520Snw141292 	itera->ih = handl;\
694520Snw141292 	itera->type = ityp;\
704520Snw141292 	itera->retcode = IDMAP_NEXT;\
714520Snw141292 	itera->limit = 1024;\
724520Snw141292 	itera->arg = argu;
734520Snw141292 
744520Snw141292 
754520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
764520Snw141292 	if (argu) {\
774520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
784520Snw141292 		free(argu);\
794520Snw141292 	}\
804520Snw141292 	if (itera)\
814520Snw141292 		free(itera);\
824520Snw141292 	return (iretcod);
834520Snw141292 
844520Snw141292 
854520Snw141292 #define	__ITER_CHECK(itera, ityp)\
864520Snw141292 	if (itera == NULL) {\
874520Snw141292 		errno = EINVAL;\
884520Snw141292 		return (IDMAP_ERR_ARG);\
894520Snw141292 	}\
904520Snw141292 	if (itera->type != ityp) {\
914520Snw141292 		errno = EINVAL;\
924520Snw141292 		return (IDMAP_ERR_ARG);\
934520Snw141292 	}
944520Snw141292 
954520Snw141292 /*
964520Snw141292  * Free memory allocated by libidmap API
974520Snw141292  *
984520Snw141292  * Input:
994520Snw141292  * ptr - memory to be freed
1004520Snw141292  */
1014520Snw141292 void
1025696Snw141292 idmap_free(void *ptr)
1035696Snw141292 {
1044520Snw141292 	free(ptr);
1054520Snw141292 }
1064520Snw141292 
1074520Snw141292 
1088040SBaban.Kenkre@Sun.COM #define	MIN_STACK_NEEDS	65536
1095232Snw141292 
1104520Snw141292 /*
1114520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1124520Snw141292  *
1134520Snw141292  * Output:
1144520Snw141292  * handle - idmap handle
1154520Snw141292  */
1164520Snw141292 idmap_stat
1175696Snw141292 idmap_init(idmap_handle_t **handle)
1185696Snw141292 {
1194520Snw141292 	CLIENT			*clnt = NULL;
1204520Snw141292 	struct idmap_handle	*hptr;
1215232Snw141292 	uint_t			sendsz = 0;
1225232Snw141292 	stack_t			st;
1234520Snw141292 
1244520Snw141292 	*handle = NULL;
1254520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1264520Snw141292 	if (hptr == NULL)
1274520Snw141292 		return (IDMAP_ERR_MEMORY);
1284520Snw141292 
1295232Snw141292 	/*
1305232Snw141292 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
1315232Snw141292 	 * the call args buffer and once for the call result buffer), so
1325232Snw141292 	 * we want to pick a sendsz that will be large enough, but not
1335232Snw141292 	 * too large.
1345232Snw141292 	 */
1355232Snw141292 	if (stack_getbounds(&st) == 0) {
1365232Snw141292 		/*
1375232Snw141292 		 * Estimate how much stack space is left;
1385232Snw141292 		 * st.ss_sp is the top of stack.
1395232Snw141292 		 */
1405232Snw141292 		if ((char *)&sendsz < (char *)st.ss_sp)
1415232Snw141292 			/* stack grows up */
1425232Snw141292 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
1435232Snw141292 		else
1445232Snw141292 			/* stack grows down */
1455232Snw141292 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
1465232Snw141292 
1478040SBaban.Kenkre@Sun.COM 		if (sendsz <= MIN_STACK_NEEDS) {
1485232Snw141292 			sendsz = 0;	/* RPC call may fail */
1498040SBaban.Kenkre@Sun.COM 		} else {
1508040SBaban.Kenkre@Sun.COM 			/* Leave 64Kb (just a guess) for our needs */
1518040SBaban.Kenkre@Sun.COM 			sendsz -= MIN_STACK_NEEDS;
1528040SBaban.Kenkre@Sun.COM 
1538040SBaban.Kenkre@Sun.COM 			/* Divide the stack space left by two */
1548040SBaban.Kenkre@Sun.COM 			sendsz = RNDUP(sendsz / 2);
1558040SBaban.Kenkre@Sun.COM 
1568040SBaban.Kenkre@Sun.COM 			/* Limit sendsz to 256KB */
1578040SBaban.Kenkre@Sun.COM 			if (sendsz > IDMAP_MAX_DOOR_RPC)
1588040SBaban.Kenkre@Sun.COM 				sendsz = IDMAP_MAX_DOOR_RPC;
1598040SBaban.Kenkre@Sun.COM 		}
1605232Snw141292 	}
1615232Snw141292 
1625232Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
1634520Snw141292 	if (clnt == NULL) {
1644520Snw141292 		free(hptr);
1654520Snw141292 		return (IDMAP_ERR_RPC);
1664520Snw141292 	}
1674520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1684520Snw141292 	hptr->privhandle = clnt;
1694520Snw141292 	*handle = hptr;
1704520Snw141292 	return (IDMAP_SUCCESS);
1714520Snw141292 }
1724520Snw141292 
1734520Snw141292 
1744520Snw141292 /*
1754520Snw141292  * Finalize idmap handle
1764520Snw141292  *
1774520Snw141292  * Input:
1784520Snw141292  * handle - idmap handle
1794520Snw141292  */
1804520Snw141292 idmap_stat
1815696Snw141292 idmap_fini(idmap_handle_t *handle)
1825696Snw141292 {
1834520Snw141292 	CLIENT			*clnt;
1844520Snw141292 	struct idmap_handle	*hptr;
1854520Snw141292 
1864520Snw141292 	if (handle == NULL)
1874520Snw141292 		return (IDMAP_SUCCESS);
1884520Snw141292 
1894520Snw141292 	hptr = (struct idmap_handle *)handle;
1904520Snw141292 
1914520Snw141292 	switch (hptr->type) {
1924520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
1934520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
1944520Snw141292 		if (clnt) {
1954520Snw141292 			if (clnt->cl_auth)
1964520Snw141292 				auth_destroy(clnt->cl_auth);
1974520Snw141292 			clnt_destroy(clnt);
1984520Snw141292 		}
1994520Snw141292 		break;
2004520Snw141292 	default:
2014520Snw141292 		break;
2024520Snw141292 	}
2034520Snw141292 	free(hptr);
2044520Snw141292 	return (IDMAP_SUCCESS);
2054520Snw141292 }
2064520Snw141292 
2074520Snw141292 
2088361SJulian.Pullen@Sun.COM static idmap_stat
2096616Sdm199847 idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
2106616Sdm199847 {
2116616Sdm199847 	CLIENT			*clnt;
2126616Sdm199847 	enum clnt_stat		clntstat;
2136616Sdm199847 
2146616Sdm199847 
2156616Sdm199847 	(void) memset(res, 0, sizeof (*res));
2166616Sdm199847 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
2176616Sdm199847 
2186616Sdm199847 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
2196616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
2206616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
2216616Sdm199847 
2226616Sdm199847 	if (clntstat != RPC_SUCCESS) {
2236616Sdm199847 		return (_idmap_rpc2stat(clnt));
2246616Sdm199847 	}
2256616Sdm199847 
2266616Sdm199847 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
2276616Sdm199847 }
2286616Sdm199847 
2298361SJulian.Pullen@Sun.COM 
2306616Sdm199847 idmap_stat
2316616Sdm199847 idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
2326616Sdm199847     idmap_ad_disc_ds_t *dc)
2336616Sdm199847 {
2346616Sdm199847 	idmap_prop_res res;
2356616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2366616Sdm199847 
2376616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2386616Sdm199847 	if (rc < 0)
2396616Sdm199847 		return (rc);
2406616Sdm199847 
2416616Sdm199847 	dc->port = res.value.idmap_prop_val_u.dsval.port;
2426616Sdm199847 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
2436616Sdm199847 	    AD_DISC_MAXHOSTNAME);
2446616Sdm199847 
2456616Sdm199847 	/* xdr doesn't guarantee 0-termination of char[]: */
2466616Sdm199847 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
2476616Sdm199847 
2486616Sdm199847 	return (rc);
2496616Sdm199847 }
2506616Sdm199847 
2516616Sdm199847 
2526616Sdm199847 /*
2536616Sdm199847  * Sometimes the property is not set. In that case, str is set to NULL but
2546616Sdm199847  * otherwise IDMAP_SUCCESS is returned.
2556616Sdm199847  */
2566616Sdm199847 idmap_stat
2576616Sdm199847 idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
2586616Sdm199847 {
2596616Sdm199847 	idmap_prop_res res;
2606616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2616616Sdm199847 
2626616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2636616Sdm199847 	if (rc < 0)
2646616Sdm199847 		return (rc);
2656616Sdm199847 
2666616Sdm199847 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
2676616Sdm199847 	return (rc);
2686616Sdm199847 }
2694520Snw141292 
2704520Snw141292 /*
2714520Snw141292  * Create/Initialize handle for updates
2724520Snw141292  *
2734520Snw141292  * Output:
2744520Snw141292  * udthandle - update handle
2754520Snw141292  */
2764520Snw141292 idmap_stat
2775696Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
2785696Snw141292 {
2794520Snw141292 	idmap_udt_handle_t	*tmp;
2804520Snw141292 
2814520Snw141292 	if (handle == NULL || udthandle == NULL) {
2824520Snw141292 		errno = EINVAL;
2834520Snw141292 		return (IDMAP_ERR_ARG);
2844520Snw141292 	}
2854520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
2864520Snw141292 		errno = ENOMEM;
2874520Snw141292 		return (IDMAP_ERR_MEMORY);
2884520Snw141292 	}
2894520Snw141292 
2904520Snw141292 	tmp->ih = handle;
2914520Snw141292 	*udthandle = tmp;
2924520Snw141292 	return (IDMAP_SUCCESS);
2934520Snw141292 }
2944520Snw141292 
2954520Snw141292 
2964520Snw141292 /*
2974520Snw141292  * All the updates specified by the update handle are committed
2984520Snw141292  * in a single transaction. i.e either all succeed or none.
2994520Snw141292  *
3004520Snw141292  * Input:
3014520Snw141292  * udthandle - update handle with the update requests
3024520Snw141292  *
3034520Snw141292  * Return value:
3044520Snw141292  * Status of the commit
3054520Snw141292  */
3064520Snw141292 idmap_stat
3075696Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle)
3085696Snw141292 {
3094520Snw141292 	CLIENT			*clnt;
3104520Snw141292 	enum clnt_stat		clntstat;
3115064Sdm199847 	idmap_update_res	res;
3125064Sdm199847 	idmap_stat		retcode;
3134520Snw141292 
3144520Snw141292 	if (udthandle == NULL) {
3154520Snw141292 		errno = EINVAL;
3164520Snw141292 		return (IDMAP_ERR_ARG);
3174520Snw141292 	}
3185064Sdm199847 
3195064Sdm199847 	(void) memset(&res, 0, sizeof (res));
3205064Sdm199847 
3214520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
3224520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
3235696Snw141292 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
3245696Snw141292 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
3255696Snw141292 	    TIMEOUT);
3264644Sbaban 
3275064Sdm199847 	if (clntstat != RPC_SUCCESS) {
3285064Sdm199847 		retcode = _idmap_rpc2stat(clnt);
3295064Sdm199847 		goto out;
3305064Sdm199847 	}
3315064Sdm199847 
3325064Sdm199847 	retcode = udthandle->commit_stat = res.retcode;
3335064Sdm199847 	udthandle->error_index = res.error_index;
3345064Sdm199847 
3355064Sdm199847 	if (retcode != IDMAP_SUCCESS) {
3365064Sdm199847 
3375064Sdm199847 		if (udthandle->error_index < 0)
3385064Sdm199847 			goto out;
3395064Sdm199847 
3405064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
3415064Sdm199847 		    &res.error_rule);
3425064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3435064Sdm199847 			udthandle->error_index = -2;
3445064Sdm199847 			goto out;
3455064Sdm199847 		}
3465064Sdm199847 
3475064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
3485064Sdm199847 		    &res.conflict_rule);
3495064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3505064Sdm199847 			udthandle->error_index = -2;
3515064Sdm199847 			goto out;
3525064Sdm199847 		}
3535064Sdm199847 	}
3545064Sdm199847 
3555064Sdm199847 	retcode = res.retcode;
3565064Sdm199847 
3575064Sdm199847 
3585064Sdm199847 out:
3594644Sbaban 	/* reset handle so that it can be used again */
3605064Sdm199847 	if (retcode == IDMAP_SUCCESS) {
3615064Sdm199847 		_IDMAP_RESET_UDT_HANDLE(udthandle);
3625064Sdm199847 	}
3635064Sdm199847 
3645064Sdm199847 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3655064Sdm199847 	errno = idmap_stat2errno(retcode);
3665064Sdm199847 	return (retcode);
3675064Sdm199847 }
3685064Sdm199847 
3695064Sdm199847 
3705064Sdm199847 static void
3715064Sdm199847 idmap_namerule_parts_clear(char **windomain, char **winname,
3725696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3735696Snw141292     boolean_t *is_nt4, int *direction)
3745696Snw141292 {
3755064Sdm199847 	if (windomain)
3765064Sdm199847 		*windomain = NULL;
3775064Sdm199847 	if (winname)
3785064Sdm199847 		*winname = NULL;
3795064Sdm199847 	if (unixname)
3805064Sdm199847 		*unixname = NULL;
3815064Sdm199847 
3825064Sdm199847 	if (is_nt4)
3835064Sdm199847 		*is_nt4 = 0;
3845064Sdm199847 	if (is_user)
3855064Sdm199847 		*is_user = -1;
3865696Snw141292 	if (is_wuser)
3875696Snw141292 		*is_wuser = -1;
3885064Sdm199847 	if (direction)
3895064Sdm199847 		*direction = IDMAP_DIRECTION_UNDEF;
3905064Sdm199847 }
3915064Sdm199847 
3925064Sdm199847 static idmap_stat
3935696Snw141292 idmap_namerule2parts(idmap_namerule *rule,
3945064Sdm199847     char **windomain, char **winname,
3955696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3965696Snw141292     boolean_t *is_nt4, int *direction)
3975696Snw141292 {
3985064Sdm199847 	idmap_stat retcode;
3995064Sdm199847 
4005064Sdm199847 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
4015064Sdm199847 		return (IDMAP_ERR_NORESULT);
4025064Sdm199847 
4035064Sdm199847 
4045064Sdm199847 	retcode = idmap_strdupnull(windomain, rule->windomain);
4055064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4065064Sdm199847 		goto errout;
4075064Sdm199847 
4085064Sdm199847 	retcode = idmap_strdupnull(winname, rule->winname);
4095064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4105064Sdm199847 		goto errout;
4115064Sdm199847 
4125064Sdm199847 	retcode = idmap_strdupnull(unixname, rule->unixname);
4135064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4145064Sdm199847 		goto errout;
4155064Sdm199847 
4165064Sdm199847 
4175064Sdm199847 	if (is_user)
4185064Sdm199847 		*is_user = rule->is_user;
4195696Snw141292 	if (is_wuser)
4205696Snw141292 		*is_wuser = rule->is_wuser;
4215064Sdm199847 	if (is_nt4)
4225064Sdm199847 		*is_nt4 = rule->is_nt4;
4235064Sdm199847 	if (direction)
4245064Sdm199847 		*direction = rule->direction;
4255064Sdm199847 
4265064Sdm199847 
4275064Sdm199847 	return (IDMAP_SUCCESS);
4284644Sbaban 
4295064Sdm199847 errout:
4305064Sdm199847 	if (windomain && *windomain)
4315064Sdm199847 		free(*windomain);
4325064Sdm199847 	if (winname && *winname)
4335064Sdm199847 		free(*winname);
4345064Sdm199847 	if (unixname && *unixname)
4355064Sdm199847 		free(*unixname);
4365064Sdm199847 
4375064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4385696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4395064Sdm199847 
4404520Snw141292 	return (retcode);
4415064Sdm199847 
4425064Sdm199847 }
4435064Sdm199847 
4445064Sdm199847 /*
4455064Sdm199847  * Retrieve the index of the failed batch element. error_index == -1
4465064Sdm199847  * indicates failure at the beginning, -2 at the end.
4475064Sdm199847  *
4485064Sdm199847  * If idmap_udt_commit didn't return error, the returned value is undefined.
4495064Sdm199847  *
4505064Sdm199847  * Return value:
4515064Sdm199847  * IDMAP_SUCCESS
4525064Sdm199847  */
4535064Sdm199847 
4545064Sdm199847 idmap_stat
4555064Sdm199847 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
4565696Snw141292     int64_t *error_index)
4575696Snw141292 {
4585064Sdm199847 	if (error_index)
4595064Sdm199847 		*error_index = udthandle->error_index;
4605064Sdm199847 
4615064Sdm199847 	return (IDMAP_SUCCESS);
4625064Sdm199847 }
4635064Sdm199847 
4645064Sdm199847 
4655064Sdm199847 /*
4665064Sdm199847  * Retrieve the rule which caused the batch to fail. If
4675064Sdm199847  * idmap_udt_commit didn't return error or if error_index is < 0, the
4685064Sdm199847  * retrieved rule is undefined.
4695064Sdm199847  *
4705064Sdm199847  * Return value:
4715064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
4725064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
4735064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
4745064Sdm199847  */
4755064Sdm199847 
4765064Sdm199847 idmap_stat
4775064Sdm199847 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
4785064Sdm199847     char **windomain, char **winname,
4795696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4805696Snw141292     boolean_t *is_nt4, int *direction)
4815696Snw141292 {
4825064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4835696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4845064Sdm199847 
4855064Sdm199847 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
4865064Sdm199847 	    udthandle->error_index < 0)
4875064Sdm199847 		return (IDMAP_ERR_NORESULT);
4885064Sdm199847 
4895064Sdm199847 	return (idmap_namerule2parts(
4905696Snw141292 	    &udthandle->error_rule,
4915696Snw141292 	    windomain,
4925696Snw141292 	    winname,
4935696Snw141292 	    unixname,
4945696Snw141292 	    is_user,
4955696Snw141292 	    is_wuser,
4965696Snw141292 	    is_nt4,
4975696Snw141292 	    direction));
4985064Sdm199847 }
4995064Sdm199847 
5005064Sdm199847 /*
5015064Sdm199847  * Retrieve the rule with which there was a conflict. TODO: retrieve
5025064Sdm199847  * the value.
5035064Sdm199847  *
5045064Sdm199847  * Return value:
5055064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
5065064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
5075064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
5085064Sdm199847  */
5095064Sdm199847 
5105064Sdm199847 idmap_stat
5115064Sdm199847 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
5125064Sdm199847     char **windomain, char **winname,
5135696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
5145696Snw141292     boolean_t *is_nt4, int *direction)
5155696Snw141292 {
5165064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
5175696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
5185064Sdm199847 
5195064Sdm199847 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
5205064Sdm199847 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
5215696Snw141292 		return (IDMAP_ERR_NORESULT);
5225064Sdm199847 	}
5235064Sdm199847 
5245064Sdm199847 	return (idmap_namerule2parts(
5255696Snw141292 	    &udthandle->conflict_rule,
5265696Snw141292 	    windomain,
5275696Snw141292 	    winname,
5285696Snw141292 	    unixname,
5295696Snw141292 	    is_user,
5305696Snw141292 	    is_wuser,
5315696Snw141292 	    is_nt4,
5325696Snw141292 	    direction));
5334520Snw141292 }
5344520Snw141292 
5354520Snw141292 
5364520Snw141292 /*
5374520Snw141292  * Destroy the update handle
5384520Snw141292  */
5394520Snw141292 void
5405696Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle)
5415696Snw141292 {
5424520Snw141292 	if (udthandle == NULL)
5434520Snw141292 		return;
5444520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
5455064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
5465064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
5474520Snw141292 	free(udthandle);
5484520Snw141292 }
5494520Snw141292 
5504520Snw141292 
5514520Snw141292 idmap_stat
5524520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
5535696Snw141292     boolean_t is_user, boolean_t is_wuser, const char *winname,
5545696Snw141292     const char *unixname, boolean_t is_nt4, int direction)
5555696Snw141292 {
5564520Snw141292 	idmap_retcode	retcode;
5574644Sbaban 	idmap_namerule	*rule = NULL;
5584520Snw141292 
5594644Sbaban 	retcode = _udt_extend_batch(udthandle);
5604520Snw141292 	if (retcode != IDMAP_SUCCESS)
5614520Snw141292 		goto errout;
5624520Snw141292 
5634520Snw141292 	rule = &udthandle->batch.
5645696Snw141292 	    idmap_update_batch_val[udthandle->next].
5655696Snw141292 	    idmap_update_op_u.rule;
5664520Snw141292 	rule->is_user = is_user;
5675696Snw141292 	rule->is_wuser = is_wuser;
5684520Snw141292 	rule->direction = direction;
5694520Snw141292 	rule->is_nt4 = is_nt4;
5705064Sdm199847 
5715064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
5725064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5735064Sdm199847 		goto errout;
5745064Sdm199847 
5755064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
5765064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5775064Sdm199847 		goto errout;
5785064Sdm199847 
5795064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
5805064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5815064Sdm199847 		goto errout;
5824644Sbaban 
5834644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5844644Sbaban 	    OP_ADD_NAMERULE;
5854520Snw141292 	udthandle->next++;
5864520Snw141292 	return (IDMAP_SUCCESS);
5874520Snw141292 
5884520Snw141292 errout:
5894644Sbaban 	/* The batch should still be usable */
5904644Sbaban 	if (rule)
5914644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5924520Snw141292 	errno = idmap_stat2errno(retcode);
5934520Snw141292 	return (retcode);
5944520Snw141292 }
5954520Snw141292 
5964520Snw141292 
5974520Snw141292 /* ARGSUSED */
5984520Snw141292 idmap_stat
5994520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
6005696Snw141292     boolean_t is_wuser,	const char *windomain, const char *winname,
6015696Snw141292     const char *unixname, int direction)
6025696Snw141292 {
6034520Snw141292 	idmap_retcode	retcode;
6044644Sbaban 	idmap_namerule	*rule = NULL;
6054520Snw141292 
6064644Sbaban 	retcode = _udt_extend_batch(udthandle);
6074520Snw141292 	if (retcode != IDMAP_SUCCESS)
6084520Snw141292 		goto errout;
6094520Snw141292 
6104520Snw141292 	rule = &udthandle->batch.
6115696Snw141292 	    idmap_update_batch_val[udthandle->next].
6125696Snw141292 	    idmap_update_op_u.rule;
6134520Snw141292 	rule->is_user = is_user;
6145696Snw141292 	rule->is_wuser = is_wuser;
6154520Snw141292 	rule->direction = direction;
6165064Sdm199847 
6175064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6185064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6195064Sdm199847 		goto errout;
6205064Sdm199847 
6215064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
6225064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6235064Sdm199847 		goto errout;
6245064Sdm199847 
6255064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6265064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6275064Sdm199847 		goto errout;
6285064Sdm199847 
6294644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6304644Sbaban 	    OP_RM_NAMERULE;
6314520Snw141292 	udthandle->next++;
6324520Snw141292 	return (IDMAP_SUCCESS);
6334520Snw141292 
6344520Snw141292 errout:
6354644Sbaban 	if (rule)
6364644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
6374520Snw141292 	errno = idmap_stat2errno(retcode);
6384520Snw141292 	return (retcode);
6394520Snw141292 }
6404520Snw141292 
6414520Snw141292 
6424520Snw141292 /* ARGSUSED */
6434520Snw141292 idmap_stat
6445696Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
6455696Snw141292 {
6464520Snw141292 	idmap_retcode	retcode;
6474520Snw141292 
6484644Sbaban 	retcode = _udt_extend_batch(udthandle);
6494520Snw141292 	if (retcode != IDMAP_SUCCESS)
6504520Snw141292 		goto errout;
6514520Snw141292 
6524644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6534644Sbaban 	    OP_FLUSH_NAMERULES;
6544520Snw141292 	udthandle->next++;
6554520Snw141292 	return (IDMAP_SUCCESS);
6564520Snw141292 
6574520Snw141292 errout:
6584520Snw141292 	errno = idmap_stat2errno(retcode);
6594520Snw141292 	return (retcode);
6604520Snw141292 }
6614520Snw141292 
6624520Snw141292 
6634520Snw141292 /*
6644520Snw141292  * Set the number of entries requested per batch by the iterator
6654520Snw141292  *
6664520Snw141292  * Input:
6674520Snw141292  * iter  - iterator
6684520Snw141292  * limit - number of entries requested per batch
6694520Snw141292  */
6704520Snw141292 idmap_stat
6715696Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
6725696Snw141292 {
6734520Snw141292 	if (iter == NULL) {
6744520Snw141292 		errno = EINVAL;
6754520Snw141292 		return (IDMAP_ERR_ARG);
6764520Snw141292 	}
6774520Snw141292 	iter->limit = limit;
6784520Snw141292 	return (IDMAP_SUCCESS);
6794520Snw141292 }
6804520Snw141292 
6814520Snw141292 
6824520Snw141292 /*
6834520Snw141292  * Create iterator to get name-based mapping rules
6844520Snw141292  *
6854520Snw141292  * Input:
6864520Snw141292  * windomain - Windows domain
6874520Snw141292  * is_user   - user or group rules
6884520Snw141292  * winname   - Windows user or group name
6894520Snw141292  * unixname  - Unix user or group name
6904520Snw141292  *
6914520Snw141292  * Output:
6924520Snw141292  * iter - iterator
6934520Snw141292  */
6944520Snw141292 idmap_stat
6954520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
6965696Snw141292 		boolean_t is_user, boolean_t is_wuser, const char *winname,
6975696Snw141292 		const char *unixname, idmap_iter_t **iter)
6985696Snw141292 {
6994520Snw141292 
7004520Snw141292 	idmap_iter_t			*tmpiter;
7014520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
7024520Snw141292 	idmap_namerule			*rule;
7034520Snw141292 	idmap_retcode			retcode;
7044520Snw141292 
7054520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
7064520Snw141292 
7074520Snw141292 	rule = &arg->rule;
7084520Snw141292 	rule->is_user = is_user;
7095696Snw141292 	rule->is_wuser = is_wuser;
7104644Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
7115064Sdm199847 
7125064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
7135064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7145064Sdm199847 		goto errout;
7155064Sdm199847 
7165064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
7175064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7185064Sdm199847 		goto errout;
7195064Sdm199847 
7205064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
7215064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7225064Sdm199847 		goto errout;
7234520Snw141292 
7244520Snw141292 	*iter = tmpiter;
7254520Snw141292 	return (IDMAP_SUCCESS);
7264520Snw141292 
7274520Snw141292 errout:
7284520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
7295696Snw141292 	    xdr_idmap_list_namerules_1_argument, retcode);
7304520Snw141292 }
7314520Snw141292 
7324520Snw141292 
7334520Snw141292 /*
7344520Snw141292  * Iterate through the name-based mapping rules
7354520Snw141292  *
7364520Snw141292  * Input:
7374520Snw141292  * iter - iterator
7384520Snw141292  *
7394520Snw141292  * Output:
7404520Snw141292  * windomain - Windows domain
7414520Snw141292  * winname   - Windows user or group name
7424520Snw141292  * unixname  - Unix user or group name
7434520Snw141292  * is_nt4    - NT4 or AD
7444520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
7454520Snw141292  *
7464520Snw141292  * Return value:
7474520Snw141292  * 0   - done
7484520Snw141292  * 1   - more results available
7494520Snw141292  * < 0 - error
7504520Snw141292  */
7514520Snw141292 idmap_stat
7524520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
7535696Snw141292     char **winname, char **unixname,  boolean_t *is_user,
7545696Snw141292     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
7555696Snw141292 {
7564520Snw141292 	idmap_namerules_res		*namerules;
7574520Snw141292 	idmap_list_namerules_1_argument	*arg;
7584520Snw141292 	idmap_retcode			retcode;
7594520Snw141292 
7605696Snw141292 	idmap_namerule_parts_clear(windomain, winname,
7615696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
7625696Snw141292 
7634520Snw141292 
7644520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
7654520Snw141292 
7664520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
7674520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
7685696Snw141292 	    iter->next >= namerules->rules.rules_len)) {
7694520Snw141292 
7704520Snw141292 		if ((arg = iter->arg) == NULL) {
7714520Snw141292 			errno = EINVAL;
7724520Snw141292 			return (IDMAP_ERR_ARG);
7734520Snw141292 		}
7744520Snw141292 		arg->limit = iter->limit;
7754520Snw141292 
7764520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
7775696Snw141292 		    iter, arg,
7785696Snw141292 		    (uchar_t **)&namerules, sizeof (*namerules),
7795696Snw141292 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
7805696Snw141292 		    (xdrproc_t)xdr_idmap_namerules_res);
7814520Snw141292 		if (retcode != IDMAP_SUCCESS)
7824520Snw141292 			return (retcode);
7834520Snw141292 
7844520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
7854520Snw141292 			retcode  = namerules->retcode;
7864520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
7874520Snw141292 			free(namerules);
7884520Snw141292 			iter->retlist = NULL;
7894520Snw141292 			return (retcode);
7904520Snw141292 		}
7914520Snw141292 		iter->retcode = namerules->retcode;
7924520Snw141292 		arg->lastrowid = namerules->lastrowid;
7934520Snw141292 	}
7944520Snw141292 
7954520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
7964520Snw141292 		return (IDMAP_SUCCESS);
7974520Snw141292 
7984520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
7994520Snw141292 		return (IDMAP_ERR_ARG);
8004520Snw141292 	}
8014520Snw141292 
8025064Sdm199847 	retcode = idmap_strdupnull(windomain,
8035064Sdm199847 	    namerules->rules.rules_val[iter->next].windomain);
8045064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8055064Sdm199847 		goto errout;
8065064Sdm199847 
8075064Sdm199847 	retcode = idmap_strdupnull(winname,
8085064Sdm199847 	    namerules->rules.rules_val[iter->next].winname);
8095064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8105064Sdm199847 		goto errout;
8115064Sdm199847 
8125064Sdm199847 	retcode = idmap_strdupnull(unixname,
8135064Sdm199847 	    namerules->rules.rules_val[iter->next].unixname);
8145064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8155064Sdm199847 		goto errout;
8165064Sdm199847 
8174520Snw141292 	if (is_nt4)
8184520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
8195696Snw141292 	if (is_user)
8205696Snw141292 		*is_user = namerules->rules.rules_val[iter->next].is_user;
8215696Snw141292 	if (is_wuser)
8225696Snw141292 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
8234520Snw141292 	if (direction)
8244520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
8254520Snw141292 	iter->next++;
8264520Snw141292 
8274520Snw141292 	if (iter->next == namerules->rules.rules_len)
8284520Snw141292 		return (iter->retcode);
8294520Snw141292 	else
8304520Snw141292 		return (IDMAP_NEXT);
8314520Snw141292 
8324520Snw141292 errout:
8334520Snw141292 	if (windomain && *windomain)
8344520Snw141292 		free(*windomain);
8354520Snw141292 	if (winname && *winname)
8364520Snw141292 		free(*winname);
8374520Snw141292 	if (unixname && *unixname)
8384520Snw141292 		free(*unixname);
8394520Snw141292 	return (retcode);
8404520Snw141292 }
8414520Snw141292 
8424520Snw141292 
8434520Snw141292 /*
8444520Snw141292  * Create iterator to get SID to UID/GID mappings
8454520Snw141292  *
8464520Snw141292  * Output:
8474520Snw141292  * iter - iterator
8484520Snw141292  */
8494520Snw141292 idmap_stat
8506386Sjp151216 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
8515696Snw141292 {
8524520Snw141292 	idmap_iter_t			*tmpiter;
8534520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
8544520Snw141292 
8554520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
8564520Snw141292 
8576386Sjp151216 	arg->flag = flag;
8584520Snw141292 	*iter = tmpiter;
8594520Snw141292 	return (IDMAP_SUCCESS);
8604520Snw141292 }
8614520Snw141292 
8624520Snw141292 
8634520Snw141292 /*
8644520Snw141292  * Iterate through the SID to UID/GID mappings
8654520Snw141292  *
8664520Snw141292  * Input:
8674520Snw141292  * iter - iterator
8684520Snw141292  *
8694520Snw141292  * Output:
8704520Snw141292  * sid - SID in canonical form
8714520Snw141292  * pid - UID or GID
8724520Snw141292  *
8734520Snw141292  * Return value:
8744520Snw141292  * 0   - done
8754520Snw141292  * 1   - more results available
8764520Snw141292  * < 0 - error
8774520Snw141292  */
8784520Snw141292 idmap_stat
8794520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
8805696Snw141292     idmap_rid_t *rid, uid_t *pid, char **winname,
8815696Snw141292     char **windomain, char **unixname, boolean_t *is_user,
8826386Sjp151216     boolean_t *is_wuser, int *direction, idmap_info *info)
8835696Snw141292 {
8844520Snw141292 	idmap_mappings_res		*mappings;
8854520Snw141292 	idmap_list_mappings_1_argument	*arg;
8864520Snw141292 	idmap_retcode			retcode;
8874520Snw141292 	char				*str;
8884520Snw141292 
8894520Snw141292 	if (sidprefix)
8904520Snw141292 		*sidprefix = NULL;
8914520Snw141292 	if (rid)
8924520Snw141292 		*rid = UINT32_MAX;
8934520Snw141292 	if (winname)
8944520Snw141292 		*winname = NULL;
8954520Snw141292 	if (windomain)
8964520Snw141292 		*windomain = NULL;
8974520Snw141292 	if (unixname)
8984520Snw141292 		*unixname = NULL;
8994520Snw141292 	if (pid)
9004520Snw141292 		*pid = UINT32_MAX;
9015696Snw141292 	if (is_user)
9025696Snw141292 		*is_user = -1;
9035696Snw141292 	if (is_wuser)
9045696Snw141292 		*is_wuser = -1;
9054520Snw141292 	if (direction)
9064644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
9074520Snw141292 
9084520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
9094520Snw141292 
9104520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
9114520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
9125696Snw141292 	    iter->next >= mappings->mappings.mappings_len)) {
9134520Snw141292 
9144520Snw141292 		if ((arg = iter->arg) == NULL) {
9154520Snw141292 			errno = EINVAL;
9164520Snw141292 			return (IDMAP_ERR_ARG);
9174520Snw141292 		}
9184520Snw141292 		arg->limit = iter->limit;
9194520Snw141292 
9204520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
9215696Snw141292 		    iter, arg,
9225696Snw141292 		    (uchar_t **)&mappings, sizeof (*mappings),
9235696Snw141292 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
9245696Snw141292 		    (xdrproc_t)xdr_idmap_mappings_res);
9254520Snw141292 		if (retcode != IDMAP_SUCCESS)
9264520Snw141292 			return (retcode);
9274520Snw141292 
9284520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
9294520Snw141292 			retcode  = mappings->retcode;
9304520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
9314520Snw141292 			free(mappings);
9324520Snw141292 			iter->retlist = NULL;
9334520Snw141292 			return (retcode);
9344520Snw141292 		}
9354520Snw141292 		iter->retcode = mappings->retcode;
9364520Snw141292 		arg->lastrowid = mappings->lastrowid;
9374520Snw141292 	}
9384520Snw141292 
9394520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
9404520Snw141292 		return (IDMAP_SUCCESS);
9414520Snw141292 
9424520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
9434520Snw141292 		return (IDMAP_ERR_ARG);
9444520Snw141292 	}
9454520Snw141292 
9464520Snw141292 	if (sidprefix) {
9474520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
9485696Snw141292 		    idmap_id_u.sid.prefix;
9494695Sbaban 		if (str && *str != '\0') {
9504520Snw141292 			*sidprefix = strdup(str);
9514526Sbaban 			if (*sidprefix == NULL) {
9524526Sbaban 				retcode = IDMAP_ERR_MEMORY;
9534526Sbaban 				goto errout;
9544526Sbaban 			}
9554520Snw141292 		}
9564520Snw141292 	}
9574520Snw141292 	if (rid)
9584520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
9595696Snw141292 		    idmap_id_u.sid.rid;
9605064Sdm199847 
9615064Sdm199847 	retcode = idmap_strdupnull(windomain,
9625064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1domain);
9635064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9645064Sdm199847 		goto errout;
9655064Sdm199847 
9665064Sdm199847 	retcode = idmap_strdupnull(winname,
9675064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1name);
9685064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9695064Sdm199847 		goto errout;
9705064Sdm199847 
9715064Sdm199847 	retcode = idmap_strdupnull(unixname,
9725064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id2name);
9735064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9745064Sdm199847 		goto errout;
9755064Sdm199847 
9765064Sdm199847 
9774520Snw141292 	if (pid)
9784520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
9795696Snw141292 		    idmap_id_u.uid;
9804520Snw141292 	if (direction)
9814520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
9825696Snw141292 		    direction;
9835696Snw141292 	if (is_user)
9845696Snw141292 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
9855696Snw141292 		    .idtype == IDMAP_UID)?1:0;
9865696Snw141292 	if (is_wuser)
9875696Snw141292 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
9885696Snw141292 		    .idtype == IDMAP_USID)?1:0;
9895696Snw141292 
9906386Sjp151216 	if (info) {
991*12508Samw@Sun.COM 		idmap_info_mov(info,
9926386Sjp151216 		    &mappings->mappings.mappings_val[iter->next].info);
9936386Sjp151216 	}
9944520Snw141292 	iter->next++;
9954520Snw141292 
9964520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
9974520Snw141292 		return (iter->retcode);
9984520Snw141292 	else
9994520Snw141292 		return (IDMAP_NEXT);
10004520Snw141292 
10014520Snw141292 errout:
10024520Snw141292 	if (sidprefix && *sidprefix)
10034520Snw141292 		free(*sidprefix);
10044520Snw141292 	if (winname && *winname)
10054520Snw141292 		free(*winname);
10064520Snw141292 	if (windomain && *windomain)
10074520Snw141292 		free(*windomain);
10084520Snw141292 	if (unixname && *unixname)
10094520Snw141292 		free(*unixname);
10104520Snw141292 	return (retcode);
10114520Snw141292 }
10124520Snw141292 
10134520Snw141292 
10144520Snw141292 /*
10154520Snw141292  * Destroy the iterator
10164520Snw141292  */
10174520Snw141292 void
10185696Snw141292 idmap_iter_destroy(idmap_iter_t *iter)
10195696Snw141292 {
10204520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
10214520Snw141292 
10224520Snw141292 	if (iter == NULL)
10234520Snw141292 		return;
10244520Snw141292 
10254520Snw141292 	switch (iter->type) {
10264520Snw141292 	case IDMAP_LIST_NAMERULES:
10274520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
10284520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
10294520Snw141292 		break;
10304520Snw141292 	case IDMAP_LIST_MAPPINGS:
10314520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
10324520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
10334520Snw141292 		break;
10344520Snw141292 	default:
10354520Snw141292 		free(iter);
10364520Snw141292 		return;
10374520Snw141292 	};
10384520Snw141292 
10394520Snw141292 	if (iter->arg) {
10404520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
10414520Snw141292 		free(iter->arg);
10424520Snw141292 	}
10434520Snw141292 	if (iter->retlist) {
10444520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
10454520Snw141292 		free(iter->retlist);
10464520Snw141292 	}
10474520Snw141292 	free(iter);
10484520Snw141292 }
10494520Snw141292 
10504520Snw141292 
10514520Snw141292 /*
10524520Snw141292  * Create handle to get SID to UID/GID mapping entries
10534520Snw141292  *
10544520Snw141292  * Input:
10554520Snw141292  * gh - "get mapping" handle
10564520Snw141292  */
10574520Snw141292 idmap_stat
10585696Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
10595696Snw141292 {
10604520Snw141292 	idmap_get_handle_t	*tmp;
10614520Snw141292 
10624520Snw141292 	/* sanity checks */
10634520Snw141292 	if (handle == NULL || gh == NULL) {
10644520Snw141292 		errno = EINVAL;
10654520Snw141292 		return (IDMAP_ERR_ARG);
10664520Snw141292 	}
10674520Snw141292 
10684520Snw141292 	/* allocate the handle */
10694520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
10704520Snw141292 		errno = ENOMEM;
10714520Snw141292 		return (IDMAP_ERR_MEMORY);
10724520Snw141292 	}
10734520Snw141292 
10744520Snw141292 	tmp->ih = handle;
10754520Snw141292 	*gh = tmp;
10764520Snw141292 	return (IDMAP_SUCCESS);
10774520Snw141292 }
10784520Snw141292 
10794520Snw141292 
10804520Snw141292 /*
10814520Snw141292  * Given SID, get UID
10824520Snw141292  *
10834520Snw141292  * Input:
10844520Snw141292  * sidprefix  - SID prefix
10854520Snw141292  * rid        - RID
10864520Snw141292  * flag       - flag
10874520Snw141292  *
10884520Snw141292  * Output:
10894520Snw141292  * stat - status of the get request
10904520Snw141292  * uid  - POSIX UID if stat = 0
10914520Snw141292  *
10924520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
10934520Snw141292  */
10944520Snw141292 idmap_stat
10954520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
10965696Snw141292 		int flag, uid_t *uid, idmap_stat *stat)
10975696Snw141292 {
10986386Sjp151216 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
10996386Sjp151216 	    NULL, stat));
11006386Sjp151216 }
11014520Snw141292 
11026386Sjp151216 /*
11036386Sjp151216  * Given SID, get UID
11046386Sjp151216  *
11056386Sjp151216  * Input:
11066386Sjp151216  * sidprefix  - SID prefix
11076386Sjp151216  * rid        - RID
11086386Sjp151216  * flag       - flag
11096386Sjp151216  *
11106386Sjp151216  * Output:
11116386Sjp151216  * stat - status of the get request
11126386Sjp151216  * uid  - POSIX UID if stat = 0
11136386Sjp151216  * how  - mapping type if stat = 0
11146386Sjp151216  *
11156386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
11166386Sjp151216  */
11176386Sjp151216 
11186386Sjp151216 idmap_stat
11196386Sjp151216 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11206386Sjp151216 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
11216386Sjp151216 {
11224520Snw141292 	idmap_retcode	retcode;
11234644Sbaban 	idmap_mapping	*mapping = NULL;
11244520Snw141292 
11254520Snw141292 	/* sanity checks */
11264520Snw141292 	if (gh == NULL)
11274520Snw141292 		return (IDMAP_ERR_ARG);
11284520Snw141292 	if (uid == NULL || sidprefix == NULL)
11294520Snw141292 		return (IDMAP_ERR_ARG);
11304520Snw141292 
11317369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
11327369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
11337369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid);
11347369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
11357369SJulian.Pullen@Sun.COM 			*stat = retcode;
11367369SJulian.Pullen@Sun.COM 			return (retcode);
11377369SJulian.Pullen@Sun.COM 		}
11387369SJulian.Pullen@Sun.COM 	}
11397369SJulian.Pullen@Sun.COM 
11404520Snw141292 	/* Extend the request array and the return list */
11414520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11424520Snw141292 		goto errout;
11434520Snw141292 
11444520Snw141292 	/* Setup the request */
11454520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11464520Snw141292 	mapping->flag = flag;
11474520Snw141292 	mapping->id1.idtype = IDMAP_SID;
11484520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
11494520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
11504520Snw141292 		retcode = IDMAP_ERR_MEMORY;
11514520Snw141292 		goto errout;
11524520Snw141292 	}
11534520Snw141292 	mapping->id2.idtype = IDMAP_UID;
11544520Snw141292 
11554520Snw141292 	/* Setup pointers for the result */
11564520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
11574520Snw141292 	gh->retlist[gh->next].uid = uid;
11584520Snw141292 	gh->retlist[gh->next].stat = stat;
11596386Sjp151216 	gh->retlist[gh->next].info = info;
11607369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
11614520Snw141292 
11624520Snw141292 	gh->next++;
11634520Snw141292 	return (IDMAP_SUCCESS);
11644520Snw141292 
11654520Snw141292 errout:
11664644Sbaban 	/* Batch created so far should still be usable */
11674644Sbaban 	if (mapping)
11684644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
11694520Snw141292 	errno = idmap_stat2errno(retcode);
11704520Snw141292 	return (retcode);
11714520Snw141292 }
11724520Snw141292 
11734520Snw141292 
11744520Snw141292 /*
11754520Snw141292  * Given SID, get GID
11764520Snw141292  *
11774520Snw141292  * Input:
11784520Snw141292  * sidprefix  - SID prefix
11794520Snw141292  * rid        - rid
11804520Snw141292  * flag       - flag
11814520Snw141292  *
11824520Snw141292  * Output:
11834520Snw141292  * stat - status of the get request
11844520Snw141292  * gid  - POSIX GID if stat = 0
11854520Snw141292  *
11864520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11874520Snw141292  */
11884520Snw141292 idmap_stat
11894520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11905696Snw141292 		int flag, gid_t *gid, idmap_stat *stat)
11915696Snw141292 {
11926386Sjp151216 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
11936386Sjp151216 	    NULL, stat));
11946386Sjp151216 }
11956386Sjp151216 
11966386Sjp151216 
11976386Sjp151216 /*
11986386Sjp151216  * Given SID, get GID
11996386Sjp151216  *
12006386Sjp151216  * Input:
12016386Sjp151216  * sidprefix  - SID prefix
12026386Sjp151216  * rid        - rid
12036386Sjp151216  * flag       - flag
12046386Sjp151216  *
12056386Sjp151216  * Output:
12066386Sjp151216  * stat - status of the get request
12076386Sjp151216  * gid  - POSIX GID if stat = 0
12086386Sjp151216  * how  - mapping type if stat = 0
12096386Sjp151216  *
12106386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
12116386Sjp151216  */
12126386Sjp151216 idmap_stat
12136386Sjp151216 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12146386Sjp151216 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
12156386Sjp151216 {
12164520Snw141292 
12174520Snw141292 	idmap_retcode	retcode;
12184644Sbaban 	idmap_mapping	*mapping = NULL;
12194520Snw141292 
12204520Snw141292 	/* sanity checks */
12214520Snw141292 	if (gh == NULL)
12224520Snw141292 		return (IDMAP_ERR_ARG);
12234520Snw141292 	if (gid == NULL || sidprefix == NULL)
12244520Snw141292 		return (IDMAP_ERR_ARG);
12254520Snw141292 
12267369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
12277369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
12287369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid);
12297369SJulian.Pullen@Sun.COM 		if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
12307369SJulian.Pullen@Sun.COM 			*stat = retcode;
12317369SJulian.Pullen@Sun.COM 			return (retcode);
12327369SJulian.Pullen@Sun.COM 		}
12337369SJulian.Pullen@Sun.COM 	}
12347369SJulian.Pullen@Sun.COM 
12354520Snw141292 	/* Extend the request array and the return list */
12364520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
12374520Snw141292 		goto errout;
12384520Snw141292 
12394520Snw141292 	/* Setup the request */
12404520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
12414520Snw141292 	mapping->flag = flag;
12424520Snw141292 	mapping->id1.idtype = IDMAP_SID;
12434520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
12444520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
12454520Snw141292 		retcode = IDMAP_ERR_MEMORY;
12464520Snw141292 		goto errout;
12474520Snw141292 	}
12484520Snw141292 	mapping->id2.idtype = IDMAP_GID;
12494520Snw141292 
12504520Snw141292 	/* Setup pointers for the result */
12514520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
12524520Snw141292 	gh->retlist[gh->next].gid = gid;
12534520Snw141292 	gh->retlist[gh->next].stat = stat;
12546386Sjp151216 	gh->retlist[gh->next].info = info;
12557369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
12564520Snw141292 
12574520Snw141292 	gh->next++;
12584520Snw141292 	return (IDMAP_SUCCESS);
12594520Snw141292 
12604520Snw141292 errout:
12614644Sbaban 	if (mapping)
12624644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12634520Snw141292 	errno = idmap_stat2errno(retcode);
12644520Snw141292 	return (retcode);
12654520Snw141292 }
12664520Snw141292 
12674520Snw141292 
12686386Sjp151216 
12694520Snw141292 /*
12704520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
12714520Snw141292  *
12724520Snw141292  * Input:
12734520Snw141292  * sidprefix  - SID prefix
12744520Snw141292  * rid        - rid
12754520Snw141292  * flag       - flag
12764520Snw141292  *
12774520Snw141292  * Output:
12784520Snw141292  * stat    - status of the get request
12794520Snw141292  * is_user - user or group
12804520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
12814520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
12824520Snw141292  *
12834520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12844520Snw141292  */
12854520Snw141292 idmap_stat
12864520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12875696Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
12885696Snw141292 {
12896386Sjp151216 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
12906386Sjp151216 	    NULL, stat));
12916386Sjp151216 }
12926386Sjp151216 
12936386Sjp151216 
12946386Sjp151216 
12956386Sjp151216 /*
12966386Sjp151216  * Given SID, get POSIX ID i.e. UID/GID
12976386Sjp151216  *
12986386Sjp151216  * Input:
12996386Sjp151216  * sidprefix  - SID prefix
13006386Sjp151216  * rid        - rid
13016386Sjp151216  * flag       - flag
13026386Sjp151216  *
13036386Sjp151216  * Output:
13046386Sjp151216  * stat    - status of the get request
13056386Sjp151216  * is_user - user or group
13066386Sjp151216  * pid     - POSIX UID if stat = 0 and is_user = 1
13076386Sjp151216  *           POSIX GID if stat = 0 and is_user = 0
13086386Sjp151216  * how     - mapping type if stat = 0
13096386Sjp151216  *
13106386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
13116386Sjp151216  */
13126386Sjp151216 idmap_stat
13136386Sjp151216 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
13146386Sjp151216 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
13156386Sjp151216 {
13164520Snw141292 	idmap_retcode	retcode;
13174644Sbaban 	idmap_mapping	*mapping = NULL;
13184520Snw141292 
13194520Snw141292 	/* sanity checks */
13204520Snw141292 	if (gh == NULL)
13214520Snw141292 		return (IDMAP_ERR_ARG);
13224520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
13234520Snw141292 		return (IDMAP_ERR_ARG);
13244520Snw141292 
13257369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
13267369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
13277369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid,
13287369SJulian.Pullen@Sun.COM 		    is_user);
13297369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
13307369SJulian.Pullen@Sun.COM 			*stat = retcode;
13317369SJulian.Pullen@Sun.COM 			return (retcode);
13327369SJulian.Pullen@Sun.COM 		}
13337369SJulian.Pullen@Sun.COM 	}
13347369SJulian.Pullen@Sun.COM 
13354520Snw141292 	/* Extend the request array and the return list */
13364520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
13374520Snw141292 		goto errout;
13384520Snw141292 
13394520Snw141292 	/* Setup the request */
13404520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
13414520Snw141292 	mapping->flag = flag;
13424520Snw141292 	mapping->id1.idtype = IDMAP_SID;
13434520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
13444520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
13454520Snw141292 		retcode = IDMAP_ERR_MEMORY;
13464520Snw141292 		goto errout;
13474520Snw141292 	}
13484520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
13494520Snw141292 
13504520Snw141292 	/* Setup pointers for the result */
13514520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
13524520Snw141292 	gh->retlist[gh->next].uid = pid;
13534520Snw141292 	gh->retlist[gh->next].gid = pid;
13544520Snw141292 	gh->retlist[gh->next].is_user = is_user;
13554520Snw141292 	gh->retlist[gh->next].stat = stat;
13566386Sjp151216 	gh->retlist[gh->next].info = info;
13577369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
13584520Snw141292 
13594520Snw141292 	gh->next++;
13604520Snw141292 	return (IDMAP_SUCCESS);
13614520Snw141292 
13624520Snw141292 errout:
13634644Sbaban 	if (mapping)
13644644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
13654520Snw141292 	errno = idmap_stat2errno(retcode);
13664520Snw141292 	return (retcode);
13674520Snw141292 }
13684520Snw141292 
13694520Snw141292 
13704520Snw141292 /*
13714520Snw141292  * Given UID, get SID
13724520Snw141292  *
13734520Snw141292  * Input:
13744520Snw141292  * uid  - POSIX UID
13754520Snw141292  * flag - flag
13764520Snw141292  *
13774520Snw141292  * Output:
13784520Snw141292  * stat - status of the get request
13794520Snw141292  * sid  - SID prefix (if stat == 0)
13804520Snw141292  * rid  - rid
13814520Snw141292  *
13824520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
13834520Snw141292  */
13844520Snw141292 idmap_stat
13854520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
13865696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
13875696Snw141292 {
13886386Sjp151216 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
13896386Sjp151216 	    NULL, stat));
13906386Sjp151216 }
13916386Sjp151216 
13926386Sjp151216 
13936386Sjp151216 /*
13946386Sjp151216  * Given UID, get SID
13956386Sjp151216  *
13966386Sjp151216  * Input:
13976386Sjp151216  * uid  - POSIX UID
13986386Sjp151216  * flag - flag
13996386Sjp151216  *
14006386Sjp151216  * Output:
14016386Sjp151216  * stat - status of the get request
14026386Sjp151216  * sid  - SID prefix (if stat == 0)
14036386Sjp151216  * rid  - rid
14046386Sjp151216  * how  - mapping type if stat = 0
14056386Sjp151216  *
14066386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
14076386Sjp151216  */
14086386Sjp151216 idmap_stat
14096386Sjp151216 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
14106386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
14116386Sjp151216 {
14124520Snw141292 
14134520Snw141292 	idmap_retcode	retcode;
14144644Sbaban 	idmap_mapping	*mapping = NULL;
14154520Snw141292 
14164520Snw141292 	/* sanity checks */
14174520Snw141292 	if (gh == NULL)
14184520Snw141292 		return (IDMAP_ERR_ARG);
14194520Snw141292 	if (sidprefix == NULL)
14204520Snw141292 		return (IDMAP_ERR_ARG);
14214520Snw141292 
14227369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
14237369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
14247369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid);
14257369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
14267369SJulian.Pullen@Sun.COM 			*stat = retcode;
14277369SJulian.Pullen@Sun.COM 			return (retcode);
14287369SJulian.Pullen@Sun.COM 		}
14297369SJulian.Pullen@Sun.COM 	}
14307369SJulian.Pullen@Sun.COM 
14314520Snw141292 	/* Extend the request array and the return list */
14324520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
14334520Snw141292 		goto errout;
14344520Snw141292 
14354520Snw141292 	/* Setup the request */
14364520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
14374520Snw141292 	mapping->flag = flag;
14384520Snw141292 	mapping->id1.idtype = IDMAP_UID;
14394520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
14404520Snw141292 	mapping->id2.idtype = IDMAP_SID;
14414520Snw141292 
14424520Snw141292 	/* Setup pointers for the result */
14434520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
14444520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
14454520Snw141292 	gh->retlist[gh->next].rid = rid;
14464520Snw141292 	gh->retlist[gh->next].stat = stat;
14476386Sjp151216 	gh->retlist[gh->next].info = info;
14487369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
14494520Snw141292 
14504520Snw141292 	gh->next++;
14514520Snw141292 	return (IDMAP_SUCCESS);
14524520Snw141292 
14534520Snw141292 errout:
14544644Sbaban 	if (mapping)
14554644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
14564520Snw141292 	errno = idmap_stat2errno(retcode);
14574520Snw141292 	return (retcode);
14584520Snw141292 }
14594520Snw141292 
14604520Snw141292 
14614520Snw141292 /*
14624520Snw141292  * Given GID, get SID
14634520Snw141292  *
14644520Snw141292  * Input:
14654520Snw141292  * gid  - POSIX GID
14664520Snw141292  * flag - flag
14674520Snw141292  *
14684520Snw141292  * Output:
14694520Snw141292  * stat       - status of the get request
14704520Snw141292  * sidprefix  - SID prefix (if stat == 0)
14714520Snw141292  * rid        - rid
14724520Snw141292  *
14734520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
14744520Snw141292  */
14754520Snw141292 idmap_stat
14764520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
14775696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
14785696Snw141292 {
14796386Sjp151216 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
14806386Sjp151216 	    NULL, stat));
14816386Sjp151216 }
14826386Sjp151216 
14836386Sjp151216 
14846386Sjp151216 /*
14856386Sjp151216  * Given GID, get SID
14866386Sjp151216  *
14876386Sjp151216  * Input:
14886386Sjp151216  * gid  - POSIX GID
14896386Sjp151216  * flag - flag
14906386Sjp151216  *
14916386Sjp151216  * Output:
14926386Sjp151216  * stat       - status of the get request
14936386Sjp151216  * sidprefix  - SID prefix (if stat == 0)
14946386Sjp151216  * rid        - rid
14956386Sjp151216  * how        - mapping type if stat = 0
14966386Sjp151216  *
14976386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
14986386Sjp151216  */
14996386Sjp151216 idmap_stat
15006386Sjp151216 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
15016386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
15026386Sjp151216 {
15034520Snw141292 
15044520Snw141292 	idmap_retcode	retcode;
15054644Sbaban 	idmap_mapping	*mapping = NULL;
15064520Snw141292 
15074520Snw141292 	/* sanity checks */
15084520Snw141292 	if (gh == NULL)
15094520Snw141292 		return (IDMAP_ERR_ARG);
15104520Snw141292 	if (sidprefix == NULL)
15114520Snw141292 		return (IDMAP_ERR_ARG);
15124520Snw141292 
15137369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
15147369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
15157369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid);
15167369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
15177369SJulian.Pullen@Sun.COM 			*stat = retcode;
15187369SJulian.Pullen@Sun.COM 			return (retcode);
15197369SJulian.Pullen@Sun.COM 		}
15207369SJulian.Pullen@Sun.COM 	}
15217369SJulian.Pullen@Sun.COM 
15224520Snw141292 	/* Extend the request array and the return list */
15234520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
15244520Snw141292 		goto errout;
15254520Snw141292 
15264520Snw141292 	/* Setup the request */
15274520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
15284520Snw141292 	mapping->flag = flag;
15294520Snw141292 	mapping->id1.idtype = IDMAP_GID;
15304520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
15314520Snw141292 	mapping->id2.idtype = IDMAP_SID;
15324520Snw141292 
15334520Snw141292 	/* Setup pointers for the result */
15344520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
15354520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
15364520Snw141292 	gh->retlist[gh->next].rid = rid;
15374520Snw141292 	gh->retlist[gh->next].stat = stat;
15386386Sjp151216 	gh->retlist[gh->next].info = info;
15397369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
15404520Snw141292 
15414520Snw141292 	gh->next++;
15424520Snw141292 	return (IDMAP_SUCCESS);
15434520Snw141292 
15444520Snw141292 errout:
15454644Sbaban 	if (mapping)
15464644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
15474520Snw141292 	errno = idmap_stat2errno(retcode);
15484520Snw141292 	return (retcode);
15494520Snw141292 }
15504520Snw141292 
15514520Snw141292 
15524520Snw141292 /*
15534520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
15544520Snw141292  * status and identity) will be available in the data areas
15554520Snw141292  * provided by individual requests.
15564520Snw141292  */
15574520Snw141292 idmap_stat
15585696Snw141292 idmap_get_mappings(idmap_get_handle_t *gh)
15595696Snw141292 {
15604520Snw141292 	CLIENT		*clnt;
15614520Snw141292 	enum clnt_stat	clntstat;
15624520Snw141292 	idmap_retcode	retcode;
15634520Snw141292 	idmap_ids_res	res;
15647369SJulian.Pullen@Sun.COM 	idmap_id	*res_id;
15654520Snw141292 	int		i;
15667369SJulian.Pullen@Sun.COM 	idmap_id	*req_id;
15677369SJulian.Pullen@Sun.COM 	int		direction;
15684520Snw141292 
15694520Snw141292 	if (gh == NULL) {
15704520Snw141292 		errno = EINVAL;
15714520Snw141292 		return (IDMAP_ERR_ARG);
15724520Snw141292 	}
15734520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
15744520Snw141292 
15754520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
15764520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
15775696Snw141292 	    (xdrproc_t)xdr_idmap_mapping_batch,
15785696Snw141292 	    (caddr_t)&gh->batch,
15795696Snw141292 	    (xdrproc_t)xdr_idmap_ids_res,
15805696Snw141292 	    (caddr_t)&res,
15815696Snw141292 	    TIMEOUT);
15824520Snw141292 	if (clntstat != RPC_SUCCESS) {
15834644Sbaban 		retcode = _idmap_rpc2stat(clnt);
15844520Snw141292 		goto out;
15854520Snw141292 	}
15864520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
15874520Snw141292 		retcode = res.retcode;
15884520Snw141292 		goto out;
15894520Snw141292 	}
15904520Snw141292 	for (i = 0; i < gh->next; i++) {
15914520Snw141292 		if (i >= res.ids.ids_len) {
15924520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
15934520Snw141292 			continue;
15944520Snw141292 		}
15954520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
15967369SJulian.Pullen@Sun.COM 		res_id = &res.ids.ids_val[i].id;
15977369SJulian.Pullen@Sun.COM 		direction = res.ids.ids_val[i].direction;
15987369SJulian.Pullen@Sun.COM 		req_id = &gh->batch.idmap_mapping_batch_val[i].id1;
15997369SJulian.Pullen@Sun.COM 		switch (res_id->idtype) {
16004520Snw141292 		case IDMAP_UID:
16014520Snw141292 			if (gh->retlist[i].uid)
16027369SJulian.Pullen@Sun.COM 				*gh->retlist[i].uid = res_id->idmap_id_u.uid;
16034520Snw141292 			if (gh->retlist[i].is_user)
16044520Snw141292 				*gh->retlist[i].is_user = 1;
16057369SJulian.Pullen@Sun.COM 
16067369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16077369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16087369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
16097369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
16107369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16117369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16127369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid, 1,
16137369SJulian.Pullen@Sun.COM 					    direction);
16147369SJulian.Pullen@Sun.COM 				else
16157369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
16167369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16177369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16187369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid,
16197369SJulian.Pullen@Sun.COM 					    direction);
16207369SJulian.Pullen@Sun.COM 			}
16214520Snw141292 			break;
16227369SJulian.Pullen@Sun.COM 
16234520Snw141292 		case IDMAP_GID:
16244520Snw141292 			if (gh->retlist[i].gid)
16257369SJulian.Pullen@Sun.COM 				*gh->retlist[i].gid = res_id->idmap_id_u.gid;
16264520Snw141292 			if (gh->retlist[i].is_user)
16274520Snw141292 				*gh->retlist[i].is_user = 0;
16287369SJulian.Pullen@Sun.COM 
16297369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16307369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16317369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
16327369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
16337369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16347369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16357369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid, 0,
16367369SJulian.Pullen@Sun.COM 					    direction);
16377369SJulian.Pullen@Sun.COM 				else
16387369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
16397369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16407369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16417369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid,
16427369SJulian.Pullen@Sun.COM 					    direction);
16437369SJulian.Pullen@Sun.COM 			}
16444520Snw141292 			break;
16457369SJulian.Pullen@Sun.COM 
16464864Sbaban 		case IDMAP_POSIXID:
16474864Sbaban 			if (gh->retlist[i].uid)
16484864Sbaban 				*gh->retlist[i].uid = 60001;
16494864Sbaban 			if (gh->retlist[i].is_user)
16504864Sbaban 				*gh->retlist[i].is_user = -1;
16514864Sbaban 			break;
16527369SJulian.Pullen@Sun.COM 
16534520Snw141292 		case IDMAP_SID:
16545696Snw141292 		case IDMAP_USID:
16555696Snw141292 		case IDMAP_GSID:
16564520Snw141292 			if (gh->retlist[i].rid)
16577369SJulian.Pullen@Sun.COM 				*gh->retlist[i].rid =
16587369SJulian.Pullen@Sun.COM 				    res_id->idmap_id_u.sid.rid;
16594520Snw141292 			if (gh->retlist[i].sidprefix) {
16607369SJulian.Pullen@Sun.COM 				if (res_id->idmap_id_u.sid.prefix == NULL ||
16617369SJulian.Pullen@Sun.COM 				    *res_id->idmap_id_u.sid.prefix == '\0') {
16624520Snw141292 					*gh->retlist[i].sidprefix = NULL;
16634520Snw141292 					break;
16644520Snw141292 				}
16654520Snw141292 				*gh->retlist[i].sidprefix =
16667369SJulian.Pullen@Sun.COM 				    strdup(res_id->idmap_id_u.sid.prefix);
16674520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
16684520Snw141292 					*gh->retlist[i].stat =
16695696Snw141292 					    IDMAP_ERR_MEMORY;
16704520Snw141292 			}
16717369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16727369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16737369SJulian.Pullen@Sun.COM 				if (req_id->idtype == IDMAP_UID)
16747369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
16757369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
16767369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
16777369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.uid,
16787369SJulian.Pullen@Sun.COM 					    direction);
16797369SJulian.Pullen@Sun.COM 				else /* req_id->idtype == IDMAP_GID */
16807369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
16817369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
16827369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
16837369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.gid,
16847369SJulian.Pullen@Sun.COM 					    direction);
16857369SJulian.Pullen@Sun.COM 			}
16864520Snw141292 			break;
16877369SJulian.Pullen@Sun.COM 
16884520Snw141292 		case IDMAP_NONE:
16894520Snw141292 			break;
16907369SJulian.Pullen@Sun.COM 
16914520Snw141292 		default:
16924520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
16934520Snw141292 			break;
16944520Snw141292 		}
1695*12508Samw@Sun.COM 		if (gh->retlist[i].info != NULL) {
1696*12508Samw@Sun.COM 			idmap_info_mov(gh->retlist[i].info,
16976386Sjp151216 			    &res.ids.ids_val[i].info);
1698*12508Samw@Sun.COM 		}
16994520Snw141292 	}
17004520Snw141292 	retcode = IDMAP_SUCCESS;
17014520Snw141292 
17024520Snw141292 out:
17034644Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
17044520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
17054520Snw141292 	errno = idmap_stat2errno(retcode);
17064520Snw141292 	return (retcode);
17074520Snw141292 }
17084520Snw141292 
17094520Snw141292 
17104520Snw141292 /*
17114520Snw141292  * Destroy the "get mapping" handle
17124520Snw141292  */
17134520Snw141292 void
17145696Snw141292 idmap_get_destroy(idmap_get_handle_t *gh)
17155696Snw141292 {
17164520Snw141292 	if (gh == NULL)
17174520Snw141292 		return;
17184520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
17194520Snw141292 	if (gh->retlist)
17204520Snw141292 		free(gh->retlist);
17214520Snw141292 	free(gh);
17224520Snw141292 }
17234520Snw141292 
17244520Snw141292 
17254520Snw141292 /*
17264520Snw141292  * Get windows to unix mapping
17274520Snw141292  */
17284520Snw141292 idmap_stat
17294520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
17304520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
17314520Snw141292 		const char *winname, const char *windomain,
17325696Snw141292 		int flag, int *is_user, int *is_wuser,
17336386Sjp151216 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
17345696Snw141292 {
17354520Snw141292 	CLIENT			*clnt;
17364520Snw141292 	enum clnt_stat		clntstat;
17374520Snw141292 	idmap_mapping		request, *mapping;
17384520Snw141292 	idmap_mappings_res	result;
17394520Snw141292 	idmap_retcode		retcode, rc;
17404520Snw141292 
17414520Snw141292 	if (handle == NULL) {
17424520Snw141292 		errno = EINVAL;
17434520Snw141292 		return (IDMAP_ERR_ARG);
17444520Snw141292 	}
17454520Snw141292 
17464520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
17474520Snw141292 
17484520Snw141292 	(void) memset(&request, 0, sizeof (request));
17494520Snw141292 	(void) memset(&result, 0, sizeof (result));
17504520Snw141292 
17514520Snw141292 	if (pid)
17524520Snw141292 		*pid = UINT32_MAX;
17534520Snw141292 	if (unixname)
17544520Snw141292 		*unixname = NULL;
17554520Snw141292 	if (direction)
17564644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
17574520Snw141292 
17584520Snw141292 	request.flag = flag;
17594520Snw141292 	request.id1.idtype = IDMAP_SID;
17604520Snw141292 	if (sidprefix && rid) {
17614520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
17624520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
17634520Snw141292 	} else if (winname) {
17645064Sdm199847 		retcode = idmap_strdupnull(&request.id1name, winname);
17655247Sbaban 		if (retcode != IDMAP_SUCCESS)
17664520Snw141292 			goto out;
17675064Sdm199847 
17685064Sdm199847 		retcode = idmap_strdupnull(&request.id1domain, windomain);
17695247Sbaban 		if (retcode != IDMAP_SUCCESS)
17705064Sdm199847 			goto out;
17715064Sdm199847 
17724520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
17734520Snw141292 	} else {
17744520Snw141292 		errno = EINVAL;
17754520Snw141292 		return (IDMAP_ERR_ARG);
17764520Snw141292 	}
17774520Snw141292 
17785696Snw141292 	if (*is_user == 1)
17794520Snw141292 		request.id2.idtype = IDMAP_UID;
17804520Snw141292 	else if (*is_user == 0)
17814520Snw141292 		request.id2.idtype = IDMAP_GID;
17824520Snw141292 	else
17834520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
17844520Snw141292 
17855696Snw141292 	if (*is_wuser == 1)
17865696Snw141292 		request.id1.idtype = IDMAP_USID;
17875696Snw141292 	else if (*is_wuser == 0)
17885696Snw141292 		request.id1.idtype = IDMAP_GSID;
17895696Snw141292 	else
17905696Snw141292 		request.id1.idtype = IDMAP_SID;
17915696Snw141292 
17924520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
17935696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
17945696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
17955696Snw141292 	    TIMEOUT);
17964520Snw141292 
17974644Sbaban 	if (clntstat != RPC_SUCCESS)
17984644Sbaban 		return (_idmap_rpc2stat(clnt));
17994520Snw141292 
18004520Snw141292 	retcode = result.retcode;
18014520Snw141292 
18024520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
18034520Snw141292 		if (retcode == IDMAP_SUCCESS)
18044520Snw141292 			retcode = IDMAP_ERR_NORESULT;
18054520Snw141292 		goto out;
18064520Snw141292 	}
18074520Snw141292 
1808*12508Samw@Sun.COM 	if (info != NULL)
1809*12508Samw@Sun.COM 		idmap_info_mov(info, &mapping->info);
1810*12508Samw@Sun.COM 
18114864Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
18125696Snw141292 		*is_user = 1;
18134864Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
18145696Snw141292 		*is_user = 0;
18154864Sbaban 	} else {
18164864Sbaban 		goto out;
18174864Sbaban 	}
18185696Snw141292 
18195696Snw141292 	if (mapping->id1.idtype == IDMAP_USID) {
18205696Snw141292 		*is_wuser = 1;
18215696Snw141292 	} else if (mapping->id1.idtype == IDMAP_GSID) {
18225696Snw141292 		*is_wuser = 0;
18235696Snw141292 	} else {
18245696Snw141292 		goto out;
18255696Snw141292 	}
18265696Snw141292 
18274520Snw141292 	if (direction)
18284520Snw141292 		*direction = mapping->direction;
18294520Snw141292 	if (pid)
18304520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
18315064Sdm199847 
18325064Sdm199847 	rc = idmap_strdupnull(unixname, mapping->id2name);
18335064Sdm199847 	if (rc != IDMAP_SUCCESS)
18345064Sdm199847 		retcode = rc;
18354520Snw141292 
18364520Snw141292 out:
18376966Sjp151216 	if (request.id1name != NULL)
18386966Sjp151216 		free(request.id1name);
18396966Sjp151216 	if (request.id1domain != NULL)
18406966Sjp151216 		free(request.id1domain);
18414520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
18424520Snw141292 	if (retcode != IDMAP_SUCCESS)
18434520Snw141292 		errno = idmap_stat2errno(retcode);
18444520Snw141292 	return (retcode);
18454520Snw141292 }
18464520Snw141292 
18474520Snw141292 
18484520Snw141292 /*
18494520Snw141292  * Get unix to windows mapping
18504520Snw141292  */
18514520Snw141292 idmap_stat
18524520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
18534520Snw141292 		uid_t *pid, const char *unixname,
18545696Snw141292 		int flag, int is_user, int *is_wuser,
18554520Snw141292 		char **sidprefix, idmap_rid_t *rid,
18564520Snw141292 		char **winname, char **windomain,
18576386Sjp151216 		int *direction, idmap_info *info)
18585696Snw141292 {
18594520Snw141292 	CLIENT			*clnt;
18604520Snw141292 	enum clnt_stat		clntstat;
18614520Snw141292 	idmap_mapping		request, *mapping;
18624520Snw141292 	idmap_mappings_res	result;
18634520Snw141292 	idmap_retcode		retcode, rc;
18644520Snw141292 
18654520Snw141292 	if (handle == NULL) {
18664520Snw141292 		errno = EINVAL;
18674520Snw141292 		return (IDMAP_ERR_ARG);
18684520Snw141292 	}
18694520Snw141292 
18704520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
18714520Snw141292 
18724520Snw141292 	if (sidprefix)
18734520Snw141292 		*sidprefix = NULL;
18744520Snw141292 	if (winname)
18754520Snw141292 		*winname = NULL;
18764520Snw141292 	if (windomain)
18774520Snw141292 		*windomain = NULL;
18784520Snw141292 	if (rid)
18794520Snw141292 		*rid = UINT32_MAX;
18804520Snw141292 	if (direction)
18814644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
18824520Snw141292 
18834520Snw141292 	(void) memset(&request, 0, sizeof (request));
18844520Snw141292 	(void) memset(&result, 0, sizeof (result));
18854520Snw141292 
18864520Snw141292 	request.flag = flag;
18874520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
18884520Snw141292 
18894520Snw141292 	if (pid && *pid != UINT32_MAX) {
18904520Snw141292 		request.id1.idmap_id_u.uid = *pid;
18914520Snw141292 	} else if (unixname) {
18925064Sdm199847 		request.id1name = (char *)unixname;
18934520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
18944520Snw141292 	} else {
18954520Snw141292 		errno = EINVAL;
18964520Snw141292 		return (IDMAP_ERR_ARG);
18974520Snw141292 	}
18984520Snw141292 
18995696Snw141292 	if (is_wuser == NULL)
19005696Snw141292 		request.id2.idtype = IDMAP_SID;
19015696Snw141292 	else if (*is_wuser == -1)
19025696Snw141292 		request.id2.idtype = IDMAP_SID;
19035696Snw141292 	else if (*is_wuser == 0)
19045696Snw141292 		request.id2.idtype = IDMAP_GSID;
19055696Snw141292 	else if (*is_wuser == 1)
19065696Snw141292 		request.id2.idtype = IDMAP_USID;
19074520Snw141292 
19084520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
19095696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
19105696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
19115696Snw141292 	    TIMEOUT);
19124520Snw141292 
19134644Sbaban 	if (clntstat != RPC_SUCCESS)
19144644Sbaban 		return (_idmap_rpc2stat(clnt));
19154520Snw141292 
19164520Snw141292 	retcode = result.retcode;
19174520Snw141292 
19184520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
19194520Snw141292 		if (retcode == IDMAP_SUCCESS)
19204520Snw141292 			retcode = IDMAP_ERR_NORESULT;
19214520Snw141292 		goto out;
19224520Snw141292 	}
19234520Snw141292 
1924*12508Samw@Sun.COM 	if (info != NULL)
1925*12508Samw@Sun.COM 		idmap_info_mov(info, &mapping->info);
1926*12508Samw@Sun.COM 
19275696Snw141292 	if (direction != NULL)
19284520Snw141292 		*direction = mapping->direction;
19295696Snw141292 
19306386Sjp151216 	if (is_wuser != NULL) {
19316386Sjp151216 		if (mapping->id2.idtype == IDMAP_USID)
19326386Sjp151216 			*is_wuser = 1;
19336386Sjp151216 		else if (mapping->id2.idtype == IDMAP_GSID)
19346386Sjp151216 			*is_wuser = 0;
19356386Sjp151216 		else
19366386Sjp151216 			*is_wuser = -1;
19376386Sjp151216 	}
19385696Snw141292 
19394695Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
19404695Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
19414520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
19424520Snw141292 		if (*sidprefix == NULL) {
19434520Snw141292 			retcode = IDMAP_ERR_MEMORY;
19444520Snw141292 			goto errout;
19454520Snw141292 		}
19464520Snw141292 	}
19474520Snw141292 	if (rid)
19484520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
19495064Sdm199847 
19505064Sdm199847 	rc = idmap_strdupnull(winname, mapping->id2name);
19515064Sdm199847 	if (rc != IDMAP_SUCCESS)
19525064Sdm199847 		retcode = rc;
19535064Sdm199847 
19545064Sdm199847 	rc = idmap_strdupnull(windomain, mapping->id2domain);
19555064Sdm199847 	if (rc != IDMAP_SUCCESS)
19565064Sdm199847 		retcode = rc;
19574520Snw141292 
19584520Snw141292 	goto out;
19594520Snw141292 
19604520Snw141292 errout:
19614520Snw141292 	if (sidprefix && *sidprefix) {
19624520Snw141292 		free(*sidprefix);
19634520Snw141292 		*sidprefix = NULL;
19644520Snw141292 	}
19654520Snw141292 	if (winname && *winname) {
19664520Snw141292 		free(*winname);
19674520Snw141292 		*winname = NULL;
19684520Snw141292 	}
19694520Snw141292 	if (windomain && *windomain) {
19704520Snw141292 		free(*windomain);
19714520Snw141292 		*windomain = NULL;
19724520Snw141292 	}
19734520Snw141292 
19744520Snw141292 out:
19754520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
19764520Snw141292 	if (retcode != IDMAP_SUCCESS)
19774520Snw141292 		errno = idmap_stat2errno(retcode);
19784520Snw141292 	return (retcode);
19794520Snw141292 }
19804520Snw141292 
19814520Snw141292 
19824520Snw141292 
19834520Snw141292 #define	gettext(s)	s
19844520Snw141292 static stat_table_t stattable[] = {
19854520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
19864520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
19874520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
19884520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
19894520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
19904520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
19914520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
19924520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
19934644Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
19944520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
19954520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
19964520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
19974520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
19984520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
19994520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
20004520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
20014520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
20024520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
20034644Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
20044520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
20054520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
20064644Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
20074695Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
20084520Snw141292 	{IDMAP_ERR_NOMAPPING,
20094520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
20104520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
20114520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
20124520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
20134520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
20144520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
20154520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
20164520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
20174520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
20184520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
20194520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
20204520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
20214520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
20224864Sbaban 		gettext("Windows lookup failed"), EINVAL},
20234864Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
20244864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20254864Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
20264864Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
20274864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20284864Sbaban 		"Unix to Windows name-based rule"), EINVAL},
20295968Snw141292 	{IDMAP_ERR_BAD_UTF8,
20305968Snw141292 		gettext("Invalid or illegal UTF-8 sequence found in "
20315968Snw141292 		"a given Windows entity name or domain name"), EINVAL},
20328361SJulian.Pullen@Sun.COM 	{IDMAP_ERR_NONE_GENERATED,
20336386Sjp151216 		gettext("Mapping not found and none created (see -c option)"),
20346386Sjp151216 		EINVAL},
20356616Sdm199847 	{IDMAP_ERR_PROP_UNKNOWN,
20366616Sdm199847 		gettext("Undefined property"),
20376616Sdm199847 		EINVAL},
20386616Sdm199847 	{IDMAP_ERR_NS_LDAP_CFG,
20396616Sdm199847 		gettext("Native LDAP configuration error"), EINVAL},
20406616Sdm199847 	{IDMAP_ERR_NS_LDAP_PARTIAL,
20416616Sdm199847 		gettext("Partial result from Native LDAP"), EINVAL},
20426616Sdm199847 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
20436616Sdm199847 		gettext("Native LDAP operation failed"), EINVAL},
20446616Sdm199847 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
20456616Sdm199847 		gettext("Improper winname form found in Native LDAP"), EINVAL},
20468361SJulian.Pullen@Sun.COM 	{IDMAP_ERR_NO_ACTIVEDIRECTORY,
20478361SJulian.Pullen@Sun.COM 		gettext("No AD servers"),
20488361SJulian.Pullen@Sun.COM 		EINVAL},
20494520Snw141292 	{-1, NULL, 0}
20504520Snw141292 };
20514520Snw141292 #undef	gettext
20524520Snw141292 
20534520Snw141292 
20544520Snw141292 /*
20554520Snw141292  * Get description of status code
20564520Snw141292  *
20574520Snw141292  * Input:
20584520Snw141292  * status - Status code returned by libidmap API call
20594520Snw141292  *
20604520Snw141292  * Return Value:
20614520Snw141292  * human-readable localized description of idmap_stat
20624520Snw141292  */
20634520Snw141292 /* ARGSUSED */
20644520Snw141292 const char *
20655696Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
20665696Snw141292 {
20674520Snw141292 	int i;
20684520Snw141292 
20694520Snw141292 	for (i = 0; stattable[i].msg; i++) {
20704520Snw141292 		if (stattable[i].retcode == status)
207110122SJordan.Brown@Sun.COM 			return (dgettext(TEXT_DOMAIN, stattable[i].msg));
20724520Snw141292 	}
207310122SJordan.Brown@Sun.COM 	return (dgettext(TEXT_DOMAIN, "Unknown error"));
20744520Snw141292 }
20754520Snw141292 
20764520Snw141292 
20774520Snw141292 static int
20785696Snw141292 idmap_stat2errno(idmap_stat stat)
20795696Snw141292 {
20804520Snw141292 	int i;
20814520Snw141292 	for (i = 0; stattable[i].msg; i++) {
20824520Snw141292 		if (stattable[i].retcode == stat)
20834520Snw141292 			return (stattable[i].errnum);
20844520Snw141292 	}
20854520Snw141292 	return (EINVAL);
20864520Snw141292 }
20874520Snw141292 
20884520Snw141292 
20894520Snw141292 /*
20904520Snw141292  * Get status code from string
20914520Snw141292  */
20924520Snw141292 idmap_stat
20935696Snw141292 idmap_string2stat(const char *str)
20945696Snw141292 {
20954520Snw141292 	if (str == NULL)
20964520Snw141292 		return (IDMAP_ERR_INTERNAL);
20974520Snw141292 
20984520Snw141292 #define	return_cmp(a) \
20994520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
21004520Snw141292 		return (IDMAP_ERR_ ## a);
21014520Snw141292 
21024520Snw141292 	return_cmp(OTHER);
21034520Snw141292 	return_cmp(INTERNAL);
21044520Snw141292 	return_cmp(MEMORY);
21054520Snw141292 	return_cmp(NORESULT);
21064520Snw141292 	return_cmp(NOTUSER);
21074520Snw141292 	return_cmp(NOTGROUP);
21084520Snw141292 	return_cmp(NOTSUPPORTED);
21094520Snw141292 	return_cmp(W2U_NAMERULE);
21104520Snw141292 	return_cmp(U2W_NAMERULE);
21114520Snw141292 	return_cmp(CACHE);
21124520Snw141292 	return_cmp(DB);
21134520Snw141292 	return_cmp(ARG);
21144520Snw141292 	return_cmp(SID);
21154520Snw141292 	return_cmp(IDTYPE);
21164520Snw141292 	return_cmp(RPC_HANDLE);
21174520Snw141292 	return_cmp(RPC);
21184520Snw141292 	return_cmp(CLIENT_HANDLE);
21194520Snw141292 	return_cmp(BUSY);
21204520Snw141292 	return_cmp(PERMISSION_DENIED);
21214520Snw141292 	return_cmp(NOMAPPING);
21224520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
21234520Snw141292 	return_cmp(DOMAIN);
21244520Snw141292 	return_cmp(SECURITY);
21254520Snw141292 	return_cmp(NOTFOUND);
21264520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
21274520Snw141292 	return_cmp(MEMORY);
21284520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
21294520Snw141292 	return_cmp(CFG);
21304520Snw141292 	return_cmp(CFG_CHANGE);
21314520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
21324520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
21334864Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
21344864Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
21356616Sdm199847 	return_cmp(BAD_UTF8);
21368361SJulian.Pullen@Sun.COM 	return_cmp(NONE_GENERATED);
21376616Sdm199847 	return_cmp(PROP_UNKNOWN);
21386616Sdm199847 	return_cmp(NS_LDAP_CFG);
21396616Sdm199847 	return_cmp(NS_LDAP_PARTIAL);
21406616Sdm199847 	return_cmp(NS_LDAP_OP_FAILED);
21416616Sdm199847 	return_cmp(NS_LDAP_BAD_WINNAME);
21428361SJulian.Pullen@Sun.COM 	return_cmp(NO_ACTIVEDIRECTORY);
21434520Snw141292 #undef return_cmp
21444520Snw141292 
21454520Snw141292 	return (IDMAP_ERR_OTHER);
21464520Snw141292 }
21474520Snw141292 
21484520Snw141292 
21494520Snw141292 /*
21504520Snw141292  * Map the given status to one that can be returned by the protocol
21514520Snw141292  */
21524520Snw141292 idmap_stat
21535696Snw141292 idmap_stat4prot(idmap_stat status)
21545696Snw141292 {
21554520Snw141292 	switch (status) {
21564520Snw141292 	case IDMAP_ERR_MEMORY:
21574520Snw141292 	case IDMAP_ERR_CACHE:
21584520Snw141292 		return (IDMAP_ERR_INTERNAL);
21594520Snw141292 	}
21604520Snw141292 	return (status);
21614520Snw141292 }
21625043Sbaban 
21635043Sbaban 
21645043Sbaban /*
21655247Sbaban  * This is a convenience routine which duplicates a string after
21665247Sbaban  * checking for NULL pointers. This function will return success if
21675247Sbaban  * either the 'to' OR 'from' pointers are NULL.
21685064Sdm199847  */
21695064Sdm199847 static idmap_stat
21705696Snw141292 idmap_strdupnull(char **to, const char *from)
21715696Snw141292 {
21725247Sbaban 	if (to == NULL)
21735247Sbaban 		return (IDMAP_SUCCESS);
21745247Sbaban 
21755064Sdm199847 	if (from == NULL || *from == '\0') {
21765064Sdm199847 		*to = NULL;
21775064Sdm199847 		return (IDMAP_SUCCESS);
21785064Sdm199847 	}
21795064Sdm199847 
21805064Sdm199847 	*to = strdup(from);
21815064Sdm199847 	if (*to == NULL)
21825064Sdm199847 		return (IDMAP_ERR_MEMORY);
21835064Sdm199847 	return (IDMAP_SUCCESS);
21845064Sdm199847 }
21855064Sdm199847 
21866386Sjp151216 
21875064Sdm199847 idmap_stat
21885696Snw141292 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
21895696Snw141292 {
21905064Sdm199847 	idmap_stat retval;
21915064Sdm199847 
21926386Sjp151216 	if (to == NULL)
21936386Sjp151216 		return (IDMAP_SUCCESS);
21946386Sjp151216 
21955064Sdm199847 	(void) memcpy(to, from, sizeof (idmap_namerule));
21966386Sjp151216 	to->windomain = NULL;
21976386Sjp151216 	to->winname = NULL;
21986386Sjp151216 	to->unixname = NULL;
21995064Sdm199847 
22005064Sdm199847 	retval = idmap_strdupnull(&to->windomain, from->windomain);
22015064Sdm199847 	if (retval != IDMAP_SUCCESS)
22025064Sdm199847 		return (retval);
22035064Sdm199847 
22045064Sdm199847 	retval = idmap_strdupnull(&to->winname, from->winname);
22056386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22066386Sjp151216 		free(to->windomain);
22076386Sjp151216 		to->windomain = NULL;
22086386Sjp151216 		return (retval);
22096386Sjp151216 	}
22106386Sjp151216 
22116386Sjp151216 	retval = idmap_strdupnull(&to->unixname, from->unixname);
22126386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22136386Sjp151216 		free(to->windomain);
22146386Sjp151216 		to->windomain = NULL;
22156386Sjp151216 		free(to->winname);
22166386Sjp151216 		to->winname = NULL;
22176386Sjp151216 		return (retval);
22186386Sjp151216 	}
22196386Sjp151216 
22206386Sjp151216 	return (retval);
22216386Sjp151216 }
22226386Sjp151216 
22236386Sjp151216 
22246386Sjp151216 /*
2225*12508Samw@Sun.COM  * Move the contents of the "info" structure from "from" to "to".
22266386Sjp151216  */
2227*12508Samw@Sun.COM void
22286386Sjp151216 idmap_info_mov(idmap_info *to, idmap_info *from)
22296386Sjp151216 {
22306386Sjp151216 	(void) memcpy(to, from, sizeof (idmap_info));
22316386Sjp151216 	(void) memset(from, 0, sizeof (idmap_info));
22326386Sjp151216 }
22336386Sjp151216 
22346386Sjp151216 
22356386Sjp151216 void
22366386Sjp151216 idmap_info_free(idmap_info *info)
22376386Sjp151216 {
22386386Sjp151216 	if (info == NULL)
22396386Sjp151216 		return;
22406386Sjp151216 
2241*12508Samw@Sun.COM 	xdr_free(xdr_idmap_info, (caddr_t)info);
2242*12508Samw@Sun.COM 	(void) memset(info, 0, sizeof (idmap_info));
2243*12508Samw@Sun.COM }
22446386Sjp151216 
22456386Sjp151216 
2246*12508Samw@Sun.COM void
2247*12508Samw@Sun.COM idmap_how_clear(idmap_how *how)
2248*12508Samw@Sun.COM {
2249*12508Samw@Sun.COM 	xdr_free(xdr_idmap_how, (caddr_t)how);
2250*12508Samw@Sun.COM 	(void) memset(how, 0, sizeof (*how));
22516386Sjp151216 }
22526386Sjp151216 
22536386Sjp151216 
22545064Sdm199847 /*
22555043Sbaban  * Get uid given Windows name
22565043Sbaban  */
22575043Sbaban idmap_stat
22587369SJulian.Pullen@Sun.COM idmap_getuidbywinname(const char *name, const char *domain, int flag,
22597369SJulian.Pullen@Sun.COM 	uid_t *uid)
22605696Snw141292 {
22615043Sbaban 	idmap_handle_t	*ih;
22625043Sbaban 	idmap_retcode	rc;
22635696Snw141292 	int		is_user = 1;
22645696Snw141292 	int		is_wuser = -1;
22657369SJulian.Pullen@Sun.COM 	int 		direction;
22665043Sbaban 
22675043Sbaban 	if (uid == NULL)
22685043Sbaban 		return (IDMAP_ERR_ARG);
22695043Sbaban 
22707369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
22717369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_uidbywinname(name, domain, uid);
22727369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
22737369SJulian.Pullen@Sun.COM 			return (rc);
22747369SJulian.Pullen@Sun.COM 	}
22755043Sbaban 	/* Get mapping */
22765043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
22775043Sbaban 		return (rc);
22787369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
22797369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
22805043Sbaban 	(void) idmap_fini(ih);
22815043Sbaban 
22827369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
22837369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store UID to winname */
22847369SJulian.Pullen@Sun.COM 		if (domain == NULL)
22857369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
22867369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2uid(name, domain, *uid, direction);
22877369SJulian.Pullen@Sun.COM 	}
22887369SJulian.Pullen@Sun.COM 
22895043Sbaban 	return (rc);
22905043Sbaban }
22915043Sbaban 
22925043Sbaban 
22935043Sbaban /*
22945043Sbaban  * Get gid given Windows name
22955043Sbaban  */
22965043Sbaban idmap_stat
22977369SJulian.Pullen@Sun.COM idmap_getgidbywinname(const char *name, const char *domain, int flag,
22987369SJulian.Pullen@Sun.COM 	gid_t *gid)
22995696Snw141292 {
23005043Sbaban 	idmap_handle_t	*ih;
23015043Sbaban 	idmap_retcode	rc;
23025696Snw141292 	int		is_user = 0;
23035696Snw141292 	int		is_wuser = -1;
23047369SJulian.Pullen@Sun.COM 	int		direction;
23055043Sbaban 
23065043Sbaban 	if (gid == NULL)
23075043Sbaban 		return (IDMAP_ERR_ARG);
23085043Sbaban 
23097369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
23107369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_gidbywinname(name, domain, gid);
23117369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
23127369SJulian.Pullen@Sun.COM 			return (rc);
23137369SJulian.Pullen@Sun.COM 	}
23147369SJulian.Pullen@Sun.COM 
23155043Sbaban 	/* Get mapping */
23165043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
23175043Sbaban 		return (rc);
23187369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
23197369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
23205043Sbaban 	(void) idmap_fini(ih);
23215043Sbaban 
23227369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
23237369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store GID to winname */
23247369SJulian.Pullen@Sun.COM 		if (domain == NULL)
23257369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
23267369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2gid(name, domain, *gid, direction);
23277369SJulian.Pullen@Sun.COM 	}
23287369SJulian.Pullen@Sun.COM 
23295043Sbaban 	return (rc);
23305043Sbaban }
23315043Sbaban 
23325043Sbaban 
23335043Sbaban /*
23345043Sbaban  * Get winname given pid
23355043Sbaban  */
23365043Sbaban static idmap_retcode
23377369SJulian.Pullen@Sun.COM idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
23387369SJulian.Pullen@Sun.COM 	char **domain)
23395696Snw141292 {
23405043Sbaban 	idmap_handle_t	*ih;
23415043Sbaban 	idmap_retcode	rc;
23425043Sbaban 	int		len;
23435043Sbaban 	char		*winname, *windomain;
23447369SJulian.Pullen@Sun.COM 	int		direction;
23455043Sbaban 
23465043Sbaban 	if (name == NULL)
23475043Sbaban 		return (IDMAP_ERR_ARG);
23485043Sbaban 
23497369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
23507369SJulian.Pullen@Sun.COM 		if (is_user)
23517369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebyuid(&winname,
23527369SJulian.Pullen@Sun.COM 			    &windomain, pid);
23537369SJulian.Pullen@Sun.COM 		else
23547369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebygid(&winname,
23557369SJulian.Pullen@Sun.COM 			    &windomain, pid);
23567369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS)
23577369SJulian.Pullen@Sun.COM 			goto out;
23587369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_ERR_MEMORY)
23597369SJulian.Pullen@Sun.COM 			return (rc);
23607369SJulian.Pullen@Sun.COM 	}
23617369SJulian.Pullen@Sun.COM 
23625043Sbaban 	/* Get mapping */
23635043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
23645043Sbaban 		return (rc);
23657369SJulian.Pullen@Sun.COM 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
23667369SJulian.Pullen@Sun.COM 	    NULL, NULL, &winname, &windomain, &direction, NULL);
23675043Sbaban 	(void) idmap_fini(ih);
23685043Sbaban 
23695043Sbaban 	/* Return on error */
23705043Sbaban 	if (rc != IDMAP_SUCCESS)
23715043Sbaban 		return (rc);
23725043Sbaban 
23735043Sbaban 	/*
23745043Sbaban 	 * The given PID may have been mapped to a locally
23755043Sbaban 	 * generated SID in which case there isn't any
23765043Sbaban 	 * Windows name
23775043Sbaban 	 */
23785043Sbaban 	if (winname == NULL || windomain == NULL) {
23795043Sbaban 		idmap_free(winname);
23805043Sbaban 		idmap_free(windomain);
23815043Sbaban 		return (IDMAP_ERR_NORESULT);
23825043Sbaban 	}
23835043Sbaban 
23847369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
23857369SJulian.Pullen@Sun.COM 		if (is_user)
23867369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2uid(winname, windomain,
23877369SJulian.Pullen@Sun.COM 			    pid, direction);
23887369SJulian.Pullen@Sun.COM 		else
23897369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2gid(winname, windomain,
23907369SJulian.Pullen@Sun.COM 			    pid, direction);
23917369SJulian.Pullen@Sun.COM 	}
23927369SJulian.Pullen@Sun.COM 
23937369SJulian.Pullen@Sun.COM out:
23945043Sbaban 	if (domain != NULL) {
23955043Sbaban 		*name = winname;
23965043Sbaban 		*domain = windomain;
23975043Sbaban 	} else {
23985043Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
23995043Sbaban 		if ((*name = malloc(len)) != NULL)
24005043Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
24015043Sbaban 			    windomain);
24025043Sbaban 		else
24035043Sbaban 			rc = IDMAP_ERR_MEMORY;
24045043Sbaban 		idmap_free(winname);
24055043Sbaban 		idmap_free(windomain);
24065043Sbaban 	}
24077369SJulian.Pullen@Sun.COM 
24085043Sbaban 	return (rc);
24095043Sbaban }
24105043Sbaban 
24115043Sbaban 
24125043Sbaban /*
24135043Sbaban  * Get winname given uid
24145043Sbaban  */
24155043Sbaban idmap_stat
24167369SJulian.Pullen@Sun.COM idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain)
24175696Snw141292 {
24187369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(uid, 1, flag, name, domain));
24195043Sbaban }
24205043Sbaban 
24215043Sbaban 
24225043Sbaban /*
24235043Sbaban  * Get winname given gid
24245043Sbaban  */
24255043Sbaban idmap_stat
24267369SJulian.Pullen@Sun.COM idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain)
24275696Snw141292 {
24287369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(gid, 0, flag, name, domain));
24295043Sbaban }
243011963SAfshin.Ardakani@Sun.COM 
243111963SAfshin.Ardakani@Sun.COM idmap_stat
243211963SAfshin.Ardakani@Sun.COM idmap_flush(idmap_handle_t *handle, idmap_flush_op op)
243311963SAfshin.Ardakani@Sun.COM {
243411963SAfshin.Ardakani@Sun.COM 	CLIENT			*clnt;
243511963SAfshin.Ardakani@Sun.COM 	enum clnt_stat		clntstat;
243611963SAfshin.Ardakani@Sun.COM 	idmap_retcode		res;
243711963SAfshin.Ardakani@Sun.COM 
243811963SAfshin.Ardakani@Sun.COM 	res = IDMAP_SUCCESS;
243911963SAfshin.Ardakani@Sun.COM 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
244011963SAfshin.Ardakani@Sun.COM 
244111963SAfshin.Ardakani@Sun.COM 	clntstat = clnt_call(clnt, IDMAP_FLUSH,
244211963SAfshin.Ardakani@Sun.COM 	    (xdrproc_t)xdr_idmap_flush_op, (caddr_t)&op,
244311963SAfshin.Ardakani@Sun.COM 	    (xdrproc_t)xdr_idmap_retcode, (caddr_t)&res, TIMEOUT);
244411963SAfshin.Ardakani@Sun.COM 
244511963SAfshin.Ardakani@Sun.COM 	if (clntstat != RPC_SUCCESS) {
244611963SAfshin.Ardakani@Sun.COM 		return (_idmap_rpc2stat(clnt));
244711963SAfshin.Ardakani@Sun.COM 	}
244811963SAfshin.Ardakani@Sun.COM 	return (res);
244911963SAfshin.Ardakani@Sun.COM }
245012065SKeyur.Desai@Sun.COM 
245112065SKeyur.Desai@Sun.COM 
245212065SKeyur.Desai@Sun.COM /*
245312065SKeyur.Desai@Sun.COM  * syslog is the default logger.
245412065SKeyur.Desai@Sun.COM  * It can be overwritten by supplying a logger
245512065SKeyur.Desai@Sun.COM  * with  idmap_set_logger()
245612065SKeyur.Desai@Sun.COM  */
245712065SKeyur.Desai@Sun.COM idmap_logger_t logger = syslog;
245812065SKeyur.Desai@Sun.COM 
245912065SKeyur.Desai@Sun.COM 
246012065SKeyur.Desai@Sun.COM void
246112065SKeyur.Desai@Sun.COM idmap_set_logger(idmap_logger_t funct)
246212065SKeyur.Desai@Sun.COM {
246312065SKeyur.Desai@Sun.COM 	logger = funct;
246412065SKeyur.Desai@Sun.COM }
2465*12508Samw@Sun.COM 
2466*12508Samw@Sun.COM /*
2467*12508Samw@Sun.COM  * Helper functions that concatenate two parts of a name and then
2468*12508Samw@Sun.COM  * look up a value, so that the same set of functions can be used to
2469*12508Samw@Sun.COM  * process both "in" and "out" parameters.
2470*12508Samw@Sun.COM  */
2471*12508Samw@Sun.COM static
2472*12508Samw@Sun.COM boolean_t
2473*12508Samw@Sun.COM idmap_trace_get_str(nvlist_t *entry, char *n1, char *n2, char **ret)
2474*12508Samw@Sun.COM {
2475*12508Samw@Sun.COM 	char name[IDMAP_TRACE_NAME_MAX+1];	/* Max used is about 11 */
2476*12508Samw@Sun.COM 	int err;
2477*12508Samw@Sun.COM 
2478*12508Samw@Sun.COM 	(void) strlcpy(name, n1, sizeof (name));
2479*12508Samw@Sun.COM 	if (n2 != NULL)
2480*12508Samw@Sun.COM 		(void) strlcat(name, n2, sizeof (name));
2481*12508Samw@Sun.COM 
2482*12508Samw@Sun.COM 	err = nvlist_lookup_string(entry, name, ret);
2483*12508Samw@Sun.COM 	return (err == 0);
2484*12508Samw@Sun.COM }
2485*12508Samw@Sun.COM 
2486*12508Samw@Sun.COM static
2487*12508Samw@Sun.COM boolean_t
2488*12508Samw@Sun.COM idmap_trace_get_int(nvlist_t *entry, char *n1, char *n2, int64_t *ret)
2489*12508Samw@Sun.COM {
2490*12508Samw@Sun.COM 	char name[IDMAP_TRACE_NAME_MAX+1];	/* Max used is about 11 */
2491*12508Samw@Sun.COM 	int err;
2492*12508Samw@Sun.COM 
2493*12508Samw@Sun.COM 	(void) strlcpy(name, n1, sizeof (name));
2494*12508Samw@Sun.COM 	if (n2 != NULL)
2495*12508Samw@Sun.COM 		(void) strlcat(name, n2, sizeof (name));
2496*12508Samw@Sun.COM 
2497*12508Samw@Sun.COM 	err = nvlist_lookup_int64(entry, name, ret);
2498*12508Samw@Sun.COM 	return (err == 0);
2499*12508Samw@Sun.COM }
2500*12508Samw@Sun.COM 
2501*12508Samw@Sun.COM static
2502*12508Samw@Sun.COM void
2503*12508Samw@Sun.COM idmap_trace_print_id(FILE *out, nvlist_t *entry, char *fromto)
2504*12508Samw@Sun.COM {
2505*12508Samw@Sun.COM 	char *s;
2506*12508Samw@Sun.COM 	int64_t i64;
2507*12508Samw@Sun.COM 
2508*12508Samw@Sun.COM 	if (idmap_trace_get_int(entry, fromto, IDMAP_TRACE_TYPE, &i64)) {
2509*12508Samw@Sun.COM 		switch (i64) {
2510*12508Samw@Sun.COM 		case IDMAP_POSIXID:
2511*12508Samw@Sun.COM 			(void) fprintf(out, "unixname ");
2512*12508Samw@Sun.COM 			break;
2513*12508Samw@Sun.COM 		case IDMAP_UID:
2514*12508Samw@Sun.COM 			(void) fprintf(out, "unixuser ");
2515*12508Samw@Sun.COM 			break;
2516*12508Samw@Sun.COM 		case IDMAP_GID:
2517*12508Samw@Sun.COM 			(void) fprintf(out, "unixgroup ");
2518*12508Samw@Sun.COM 			break;
2519*12508Samw@Sun.COM 		case IDMAP_SID:
2520*12508Samw@Sun.COM 			(void) fprintf(out, "winname ");
2521*12508Samw@Sun.COM 			break;
2522*12508Samw@Sun.COM 		case IDMAP_USID:
2523*12508Samw@Sun.COM 			(void) fprintf(out, "winuser ");
2524*12508Samw@Sun.COM 			break;
2525*12508Samw@Sun.COM 		case IDMAP_GSID:
2526*12508Samw@Sun.COM 			(void) fprintf(out, "wingroup ");
2527*12508Samw@Sun.COM 			break;
2528*12508Samw@Sun.COM 		case IDMAP_NONE:
2529*12508Samw@Sun.COM 			(void) fprintf(out, gettext("unknown "));
2530*12508Samw@Sun.COM 			break;
2531*12508Samw@Sun.COM 		default:
2532*12508Samw@Sun.COM 			(void) fprintf(out, gettext("bad %d "), (int)i64);
2533*12508Samw@Sun.COM 			break;
2534*12508Samw@Sun.COM 		}
2535*12508Samw@Sun.COM 	}
2536*12508Samw@Sun.COM 
2537*12508Samw@Sun.COM 	if (idmap_trace_get_str(entry, fromto, IDMAP_TRACE_NAME, &s))
2538*12508Samw@Sun.COM 		(void) fprintf(out, "%s ", s);
2539*12508Samw@Sun.COM 
2540*12508Samw@Sun.COM 	if (idmap_trace_get_str(entry, fromto, IDMAP_TRACE_SID, &s))
2541*12508Samw@Sun.COM 		(void) fprintf(out, "%s ", s);
2542*12508Samw@Sun.COM 
2543*12508Samw@Sun.COM 	if (idmap_trace_get_int(entry, fromto, IDMAP_TRACE_UNIXID, &i64))
2544*12508Samw@Sun.COM 		(void) fprintf(out, "%u ", (uid_t)i64);
2545*12508Samw@Sun.COM }
2546*12508Samw@Sun.COM 
2547*12508Samw@Sun.COM void
2548*12508Samw@Sun.COM idmap_trace_print_1(FILE *out, char *prefix, nvlist_t *entry)
2549*12508Samw@Sun.COM {
2550*12508Samw@Sun.COM 	char *s;
2551*12508Samw@Sun.COM 	int64_t i64;
2552*12508Samw@Sun.COM 
2553*12508Samw@Sun.COM 	(void) fprintf(out, "%s", prefix);
2554*12508Samw@Sun.COM 	idmap_trace_print_id(out, entry, "from");
2555*12508Samw@Sun.COM 	(void) fprintf(out, "-> ");
2556*12508Samw@Sun.COM 	idmap_trace_print_id(out, entry, "to");
2557*12508Samw@Sun.COM 	if (idmap_trace_get_int(entry, IDMAP_TRACE_ERROR, NULL, &i64))
2558*12508Samw@Sun.COM 		(void) fprintf(out, gettext("Error %d "), (int)i64);
2559*12508Samw@Sun.COM 	(void) fprintf(out, "-");
2560*12508Samw@Sun.COM 	if (idmap_trace_get_str(entry, IDMAP_TRACE_MESSAGE, NULL, &s))
2561*12508Samw@Sun.COM 		(void) fprintf(out, " %s", s);
2562*12508Samw@Sun.COM 	(void) fprintf(out, "\n");
2563*12508Samw@Sun.COM }
2564*12508Samw@Sun.COM 
2565*12508Samw@Sun.COM void
2566*12508Samw@Sun.COM idmap_trace_print(FILE *out, char *prefix, nvlist_t *trace)
2567*12508Samw@Sun.COM {
2568*12508Samw@Sun.COM 	nvpair_t *nvp;
2569*12508Samw@Sun.COM 
2570*12508Samw@Sun.COM 	for (nvp = nvlist_next_nvpair(trace, NULL);
2571*12508Samw@Sun.COM 	    nvp != NULL;
2572*12508Samw@Sun.COM 	    nvp = nvlist_next_nvpair(trace, nvp)) {
2573*12508Samw@Sun.COM 		nvlist_t *entry;
2574*12508Samw@Sun.COM 		int err;
2575*12508Samw@Sun.COM 
2576*12508Samw@Sun.COM 		err = nvpair_value_nvlist(nvp, &entry);
2577*12508Samw@Sun.COM 		assert(err == 0);
2578*12508Samw@Sun.COM 
2579*12508Samw@Sun.COM 		idmap_trace_print_1(out, prefix, entry);
2580*12508Samw@Sun.COM 	}
2581*12508Samw@Sun.COM }
2582