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 /*
22*12065SKeyur.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>
42*12065SKeyur.Desai@Sun.COM #include <syslog.h>
434520Snw141292 #include "idmap_impl.h"
447369SJulian.Pullen@Sun.COM #include "idmap_cache.h"
454520Snw141292 
466616Sdm199847 /*LINTLIBRARY*/
476616Sdm199847 
484520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
494520Snw141292 
504520Snw141292 static int idmap_stat2errno(idmap_stat);
516616Sdm199847 static idmap_stat	idmap_strdupnull(char **, const char *);
524520Snw141292 
534520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
544520Snw141292 	if (handl == NULL) {\
554520Snw141292 		errno = EINVAL;\
564520Snw141292 		return (IDMAP_ERR_ARG);\
574520Snw141292 	}\
584520Snw141292 	itera = calloc(1, sizeof (*itera));\
594520Snw141292 	if (itera == NULL) {\
604520Snw141292 		errno = ENOMEM;\
614520Snw141292 		return (IDMAP_ERR_MEMORY);\
624520Snw141292 	}\
634520Snw141292 	argu = calloc(1, sizeof (*argu));\
644520Snw141292 	if (argu == NULL) {\
654520Snw141292 		free(itera);\
664520Snw141292 		errno = ENOMEM;\
674520Snw141292 		return (IDMAP_ERR_MEMORY);\
684520Snw141292 	}\
694520Snw141292 	itera->ih = handl;\
704520Snw141292 	itera->type = ityp;\
714520Snw141292 	itera->retcode = IDMAP_NEXT;\
724520Snw141292 	itera->limit = 1024;\
734520Snw141292 	itera->arg = argu;
744520Snw141292 
754520Snw141292 
764520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
774520Snw141292 	if (argu) {\
784520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
794520Snw141292 		free(argu);\
804520Snw141292 	}\
814520Snw141292 	if (itera)\
824520Snw141292 		free(itera);\
834520Snw141292 	return (iretcod);
844520Snw141292 
854520Snw141292 
864520Snw141292 #define	__ITER_CHECK(itera, ityp)\
874520Snw141292 	if (itera == NULL) {\
884520Snw141292 		errno = EINVAL;\
894520Snw141292 		return (IDMAP_ERR_ARG);\
904520Snw141292 	}\
914520Snw141292 	if (itera->type != ityp) {\
924520Snw141292 		errno = EINVAL;\
934520Snw141292 		return (IDMAP_ERR_ARG);\
944520Snw141292 	}
954520Snw141292 
964520Snw141292 /*
974520Snw141292  * Free memory allocated by libidmap API
984520Snw141292  *
994520Snw141292  * Input:
1004520Snw141292  * ptr - memory to be freed
1014520Snw141292  */
1024520Snw141292 void
1035696Snw141292 idmap_free(void *ptr)
1045696Snw141292 {
1054520Snw141292 	free(ptr);
1064520Snw141292 }
1074520Snw141292 
1084520Snw141292 
1098040SBaban.Kenkre@Sun.COM #define	MIN_STACK_NEEDS	65536
1105232Snw141292 
1114520Snw141292 /*
1124520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1134520Snw141292  *
1144520Snw141292  * Output:
1154520Snw141292  * handle - idmap handle
1164520Snw141292  */
1174520Snw141292 idmap_stat
1185696Snw141292 idmap_init(idmap_handle_t **handle)
1195696Snw141292 {
1204520Snw141292 	CLIENT			*clnt = NULL;
1214520Snw141292 	struct idmap_handle	*hptr;
1225232Snw141292 	uint_t			sendsz = 0;
1235232Snw141292 	stack_t			st;
1244520Snw141292 
1254520Snw141292 	*handle = NULL;
1264520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1274520Snw141292 	if (hptr == NULL)
1284520Snw141292 		return (IDMAP_ERR_MEMORY);
1294520Snw141292 
1305232Snw141292 	/*
1315232Snw141292 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
1325232Snw141292 	 * the call args buffer and once for the call result buffer), so
1335232Snw141292 	 * we want to pick a sendsz that will be large enough, but not
1345232Snw141292 	 * too large.
1355232Snw141292 	 */
1365232Snw141292 	if (stack_getbounds(&st) == 0) {
1375232Snw141292 		/*
1385232Snw141292 		 * Estimate how much stack space is left;
1395232Snw141292 		 * st.ss_sp is the top of stack.
1405232Snw141292 		 */
1415232Snw141292 		if ((char *)&sendsz < (char *)st.ss_sp)
1425232Snw141292 			/* stack grows up */
1435232Snw141292 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
1445232Snw141292 		else
1455232Snw141292 			/* stack grows down */
1465232Snw141292 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
1475232Snw141292 
1488040SBaban.Kenkre@Sun.COM 		if (sendsz <= MIN_STACK_NEEDS) {
1495232Snw141292 			sendsz = 0;	/* RPC call may fail */
1508040SBaban.Kenkre@Sun.COM 		} else {
1518040SBaban.Kenkre@Sun.COM 			/* Leave 64Kb (just a guess) for our needs */
1528040SBaban.Kenkre@Sun.COM 			sendsz -= MIN_STACK_NEEDS;
1538040SBaban.Kenkre@Sun.COM 
1548040SBaban.Kenkre@Sun.COM 			/* Divide the stack space left by two */
1558040SBaban.Kenkre@Sun.COM 			sendsz = RNDUP(sendsz / 2);
1568040SBaban.Kenkre@Sun.COM 
1578040SBaban.Kenkre@Sun.COM 			/* Limit sendsz to 256KB */
1588040SBaban.Kenkre@Sun.COM 			if (sendsz > IDMAP_MAX_DOOR_RPC)
1598040SBaban.Kenkre@Sun.COM 				sendsz = IDMAP_MAX_DOOR_RPC;
1608040SBaban.Kenkre@Sun.COM 		}
1615232Snw141292 	}
1625232Snw141292 
1635232Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
1644520Snw141292 	if (clnt == NULL) {
1654520Snw141292 		free(hptr);
1664520Snw141292 		return (IDMAP_ERR_RPC);
1674520Snw141292 	}
1684520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1694520Snw141292 	hptr->privhandle = clnt;
1704520Snw141292 	*handle = hptr;
1714520Snw141292 	return (IDMAP_SUCCESS);
1724520Snw141292 }
1734520Snw141292 
1744520Snw141292 
1754520Snw141292 /*
1764520Snw141292  * Finalize idmap handle
1774520Snw141292  *
1784520Snw141292  * Input:
1794520Snw141292  * handle - idmap handle
1804520Snw141292  */
1814520Snw141292 idmap_stat
1825696Snw141292 idmap_fini(idmap_handle_t *handle)
1835696Snw141292 {
1844520Snw141292 	CLIENT			*clnt;
1854520Snw141292 	struct idmap_handle	*hptr;
1864520Snw141292 
1874520Snw141292 	if (handle == NULL)
1884520Snw141292 		return (IDMAP_SUCCESS);
1894520Snw141292 
1904520Snw141292 	hptr = (struct idmap_handle *)handle;
1914520Snw141292 
1924520Snw141292 	switch (hptr->type) {
1934520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
1944520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
1954520Snw141292 		if (clnt) {
1964520Snw141292 			if (clnt->cl_auth)
1974520Snw141292 				auth_destroy(clnt->cl_auth);
1984520Snw141292 			clnt_destroy(clnt);
1994520Snw141292 		}
2004520Snw141292 		break;
2014520Snw141292 	default:
2024520Snw141292 		break;
2034520Snw141292 	}
2044520Snw141292 	free(hptr);
2054520Snw141292 	return (IDMAP_SUCCESS);
2064520Snw141292 }
2074520Snw141292 
2084520Snw141292 
2098361SJulian.Pullen@Sun.COM static idmap_stat
2106616Sdm199847 idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
2116616Sdm199847 {
2126616Sdm199847 	CLIENT			*clnt;
2136616Sdm199847 	enum clnt_stat		clntstat;
2146616Sdm199847 
2156616Sdm199847 
2166616Sdm199847 	(void) memset(res, 0, sizeof (*res));
2176616Sdm199847 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
2186616Sdm199847 
2196616Sdm199847 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
2206616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
2216616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
2226616Sdm199847 
2236616Sdm199847 	if (clntstat != RPC_SUCCESS) {
2246616Sdm199847 		return (_idmap_rpc2stat(clnt));
2256616Sdm199847 	}
2266616Sdm199847 
2276616Sdm199847 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
2286616Sdm199847 }
2296616Sdm199847 
2308361SJulian.Pullen@Sun.COM 
2316616Sdm199847 idmap_stat
2326616Sdm199847 idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
2336616Sdm199847     idmap_ad_disc_ds_t *dc)
2346616Sdm199847 {
2356616Sdm199847 	idmap_prop_res res;
2366616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2376616Sdm199847 
2386616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2396616Sdm199847 	if (rc < 0)
2406616Sdm199847 		return (rc);
2416616Sdm199847 
2426616Sdm199847 	dc->port = res.value.idmap_prop_val_u.dsval.port;
2436616Sdm199847 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
2446616Sdm199847 	    AD_DISC_MAXHOSTNAME);
2456616Sdm199847 
2466616Sdm199847 	/* xdr doesn't guarantee 0-termination of char[]: */
2476616Sdm199847 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
2486616Sdm199847 
2496616Sdm199847 	return (rc);
2506616Sdm199847 }
2516616Sdm199847 
2526616Sdm199847 
2536616Sdm199847 /*
2546616Sdm199847  * Sometimes the property is not set. In that case, str is set to NULL but
2556616Sdm199847  * otherwise IDMAP_SUCCESS is returned.
2566616Sdm199847  */
2576616Sdm199847 idmap_stat
2586616Sdm199847 idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
2596616Sdm199847 {
2606616Sdm199847 	idmap_prop_res res;
2616616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2626616Sdm199847 
2636616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2646616Sdm199847 	if (rc < 0)
2656616Sdm199847 		return (rc);
2666616Sdm199847 
2676616Sdm199847 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
2686616Sdm199847 	return (rc);
2696616Sdm199847 }
2704520Snw141292 
2714520Snw141292 /*
2724520Snw141292  * Create/Initialize handle for updates
2734520Snw141292  *
2744520Snw141292  * Output:
2754520Snw141292  * udthandle - update handle
2764520Snw141292  */
2774520Snw141292 idmap_stat
2785696Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
2795696Snw141292 {
2804520Snw141292 	idmap_udt_handle_t	*tmp;
2814520Snw141292 
2824520Snw141292 	if (handle == NULL || udthandle == NULL) {
2834520Snw141292 		errno = EINVAL;
2844520Snw141292 		return (IDMAP_ERR_ARG);
2854520Snw141292 	}
2864520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
2874520Snw141292 		errno = ENOMEM;
2884520Snw141292 		return (IDMAP_ERR_MEMORY);
2894520Snw141292 	}
2904520Snw141292 
2914520Snw141292 	tmp->ih = handle;
2924520Snw141292 	*udthandle = tmp;
2934520Snw141292 	return (IDMAP_SUCCESS);
2944520Snw141292 }
2954520Snw141292 
2964520Snw141292 
2974520Snw141292 /*
2984520Snw141292  * All the updates specified by the update handle are committed
2994520Snw141292  * in a single transaction. i.e either all succeed or none.
3004520Snw141292  *
3014520Snw141292  * Input:
3024520Snw141292  * udthandle - update handle with the update requests
3034520Snw141292  *
3044520Snw141292  * Return value:
3054520Snw141292  * Status of the commit
3064520Snw141292  */
3074520Snw141292 idmap_stat
3085696Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle)
3095696Snw141292 {
3104520Snw141292 	CLIENT			*clnt;
3114520Snw141292 	enum clnt_stat		clntstat;
3125064Sdm199847 	idmap_update_res	res;
3135064Sdm199847 	idmap_stat		retcode;
3144520Snw141292 
3154520Snw141292 	if (udthandle == NULL) {
3164520Snw141292 		errno = EINVAL;
3174520Snw141292 		return (IDMAP_ERR_ARG);
3184520Snw141292 	}
3195064Sdm199847 
3205064Sdm199847 	(void) memset(&res, 0, sizeof (res));
3215064Sdm199847 
3224520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
3234520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
3245696Snw141292 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
3255696Snw141292 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
3265696Snw141292 	    TIMEOUT);
3274644Sbaban 
3285064Sdm199847 	if (clntstat != RPC_SUCCESS) {
3295064Sdm199847 		retcode = _idmap_rpc2stat(clnt);
3305064Sdm199847 		goto out;
3315064Sdm199847 	}
3325064Sdm199847 
3335064Sdm199847 	retcode = udthandle->commit_stat = res.retcode;
3345064Sdm199847 	udthandle->error_index = res.error_index;
3355064Sdm199847 
3365064Sdm199847 	if (retcode != IDMAP_SUCCESS) {
3375064Sdm199847 
3385064Sdm199847 		if (udthandle->error_index < 0)
3395064Sdm199847 			goto out;
3405064Sdm199847 
3415064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
3425064Sdm199847 		    &res.error_rule);
3435064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3445064Sdm199847 			udthandle->error_index = -2;
3455064Sdm199847 			goto out;
3465064Sdm199847 		}
3475064Sdm199847 
3485064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
3495064Sdm199847 		    &res.conflict_rule);
3505064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3515064Sdm199847 			udthandle->error_index = -2;
3525064Sdm199847 			goto out;
3535064Sdm199847 		}
3545064Sdm199847 	}
3555064Sdm199847 
3565064Sdm199847 	retcode = res.retcode;
3575064Sdm199847 
3585064Sdm199847 
3595064Sdm199847 out:
3604644Sbaban 	/* reset handle so that it can be used again */
3615064Sdm199847 	if (retcode == IDMAP_SUCCESS) {
3625064Sdm199847 		_IDMAP_RESET_UDT_HANDLE(udthandle);
3635064Sdm199847 	}
3645064Sdm199847 
3655064Sdm199847 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3665064Sdm199847 	errno = idmap_stat2errno(retcode);
3675064Sdm199847 	return (retcode);
3685064Sdm199847 }
3695064Sdm199847 
3705064Sdm199847 
3715064Sdm199847 static void
3725064Sdm199847 idmap_namerule_parts_clear(char **windomain, char **winname,
3735696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3745696Snw141292     boolean_t *is_nt4, int *direction)
3755696Snw141292 {
3765064Sdm199847 	if (windomain)
3775064Sdm199847 		*windomain = NULL;
3785064Sdm199847 	if (winname)
3795064Sdm199847 		*winname = NULL;
3805064Sdm199847 	if (unixname)
3815064Sdm199847 		*unixname = NULL;
3825064Sdm199847 
3835064Sdm199847 	if (is_nt4)
3845064Sdm199847 		*is_nt4 = 0;
3855064Sdm199847 	if (is_user)
3865064Sdm199847 		*is_user = -1;
3875696Snw141292 	if (is_wuser)
3885696Snw141292 		*is_wuser = -1;
3895064Sdm199847 	if (direction)
3905064Sdm199847 		*direction = IDMAP_DIRECTION_UNDEF;
3915064Sdm199847 }
3925064Sdm199847 
3935064Sdm199847 static idmap_stat
3945696Snw141292 idmap_namerule2parts(idmap_namerule *rule,
3955064Sdm199847     char **windomain, char **winname,
3965696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3975696Snw141292     boolean_t *is_nt4, int *direction)
3985696Snw141292 {
3995064Sdm199847 	idmap_stat retcode;
4005064Sdm199847 
4015064Sdm199847 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
4025064Sdm199847 		return (IDMAP_ERR_NORESULT);
4035064Sdm199847 
4045064Sdm199847 
4055064Sdm199847 	retcode = idmap_strdupnull(windomain, rule->windomain);
4065064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4075064Sdm199847 		goto errout;
4085064Sdm199847 
4095064Sdm199847 	retcode = idmap_strdupnull(winname, rule->winname);
4105064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4115064Sdm199847 		goto errout;
4125064Sdm199847 
4135064Sdm199847 	retcode = idmap_strdupnull(unixname, rule->unixname);
4145064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4155064Sdm199847 		goto errout;
4165064Sdm199847 
4175064Sdm199847 
4185064Sdm199847 	if (is_user)
4195064Sdm199847 		*is_user = rule->is_user;
4205696Snw141292 	if (is_wuser)
4215696Snw141292 		*is_wuser = rule->is_wuser;
4225064Sdm199847 	if (is_nt4)
4235064Sdm199847 		*is_nt4 = rule->is_nt4;
4245064Sdm199847 	if (direction)
4255064Sdm199847 		*direction = rule->direction;
4265064Sdm199847 
4275064Sdm199847 
4285064Sdm199847 	return (IDMAP_SUCCESS);
4294644Sbaban 
4305064Sdm199847 errout:
4315064Sdm199847 	if (windomain && *windomain)
4325064Sdm199847 		free(*windomain);
4335064Sdm199847 	if (winname && *winname)
4345064Sdm199847 		free(*winname);
4355064Sdm199847 	if (unixname && *unixname)
4365064Sdm199847 		free(*unixname);
4375064Sdm199847 
4385064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4395696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4405064Sdm199847 
4414520Snw141292 	return (retcode);
4425064Sdm199847 
4435064Sdm199847 }
4445064Sdm199847 
4455064Sdm199847 /*
4465064Sdm199847  * Retrieve the index of the failed batch element. error_index == -1
4475064Sdm199847  * indicates failure at the beginning, -2 at the end.
4485064Sdm199847  *
4495064Sdm199847  * If idmap_udt_commit didn't return error, the returned value is undefined.
4505064Sdm199847  *
4515064Sdm199847  * Return value:
4525064Sdm199847  * IDMAP_SUCCESS
4535064Sdm199847  */
4545064Sdm199847 
4555064Sdm199847 idmap_stat
4565064Sdm199847 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
4575696Snw141292     int64_t *error_index)
4585696Snw141292 {
4595064Sdm199847 	if (error_index)
4605064Sdm199847 		*error_index = udthandle->error_index;
4615064Sdm199847 
4625064Sdm199847 	return (IDMAP_SUCCESS);
4635064Sdm199847 }
4645064Sdm199847 
4655064Sdm199847 
4665064Sdm199847 /*
4675064Sdm199847  * Retrieve the rule which caused the batch to fail. If
4685064Sdm199847  * idmap_udt_commit didn't return error or if error_index is < 0, the
4695064Sdm199847  * retrieved rule is undefined.
4705064Sdm199847  *
4715064Sdm199847  * Return value:
4725064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
4735064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
4745064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
4755064Sdm199847  */
4765064Sdm199847 
4775064Sdm199847 idmap_stat
4785064Sdm199847 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
4795064Sdm199847     char **windomain, char **winname,
4805696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4815696Snw141292     boolean_t *is_nt4, int *direction)
4825696Snw141292 {
4835064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4845696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4855064Sdm199847 
4865064Sdm199847 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
4875064Sdm199847 	    udthandle->error_index < 0)
4885064Sdm199847 		return (IDMAP_ERR_NORESULT);
4895064Sdm199847 
4905064Sdm199847 	return (idmap_namerule2parts(
4915696Snw141292 	    &udthandle->error_rule,
4925696Snw141292 	    windomain,
4935696Snw141292 	    winname,
4945696Snw141292 	    unixname,
4955696Snw141292 	    is_user,
4965696Snw141292 	    is_wuser,
4975696Snw141292 	    is_nt4,
4985696Snw141292 	    direction));
4995064Sdm199847 }
5005064Sdm199847 
5015064Sdm199847 /*
5025064Sdm199847  * Retrieve the rule with which there was a conflict. TODO: retrieve
5035064Sdm199847  * the value.
5045064Sdm199847  *
5055064Sdm199847  * Return value:
5065064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
5075064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
5085064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
5095064Sdm199847  */
5105064Sdm199847 
5115064Sdm199847 idmap_stat
5125064Sdm199847 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
5135064Sdm199847     char **windomain, char **winname,
5145696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
5155696Snw141292     boolean_t *is_nt4, int *direction)
5165696Snw141292 {
5175064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
5185696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
5195064Sdm199847 
5205064Sdm199847 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
5215064Sdm199847 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
5225696Snw141292 		return (IDMAP_ERR_NORESULT);
5235064Sdm199847 	}
5245064Sdm199847 
5255064Sdm199847 	return (idmap_namerule2parts(
5265696Snw141292 	    &udthandle->conflict_rule,
5275696Snw141292 	    windomain,
5285696Snw141292 	    winname,
5295696Snw141292 	    unixname,
5305696Snw141292 	    is_user,
5315696Snw141292 	    is_wuser,
5325696Snw141292 	    is_nt4,
5335696Snw141292 	    direction));
5344520Snw141292 }
5354520Snw141292 
5364520Snw141292 
5374520Snw141292 /*
5384520Snw141292  * Destroy the update handle
5394520Snw141292  */
5404520Snw141292 void
5415696Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle)
5425696Snw141292 {
5434520Snw141292 	if (udthandle == NULL)
5444520Snw141292 		return;
5454520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
5465064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
5475064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
5484520Snw141292 	free(udthandle);
5494520Snw141292 }
5504520Snw141292 
5514520Snw141292 
5524520Snw141292 idmap_stat
5534520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
5545696Snw141292     boolean_t is_user, boolean_t is_wuser, const char *winname,
5555696Snw141292     const char *unixname, boolean_t is_nt4, int direction)
5565696Snw141292 {
5574520Snw141292 	idmap_retcode	retcode;
5584644Sbaban 	idmap_namerule	*rule = NULL;
5594520Snw141292 
5604644Sbaban 	retcode = _udt_extend_batch(udthandle);
5614520Snw141292 	if (retcode != IDMAP_SUCCESS)
5624520Snw141292 		goto errout;
5634520Snw141292 
5644520Snw141292 	rule = &udthandle->batch.
5655696Snw141292 	    idmap_update_batch_val[udthandle->next].
5665696Snw141292 	    idmap_update_op_u.rule;
5674520Snw141292 	rule->is_user = is_user;
5685696Snw141292 	rule->is_wuser = is_wuser;
5694520Snw141292 	rule->direction = direction;
5704520Snw141292 	rule->is_nt4 = is_nt4;
5715064Sdm199847 
5725064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
5735064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5745064Sdm199847 		goto errout;
5755064Sdm199847 
5765064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
5775064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5785064Sdm199847 		goto errout;
5795064Sdm199847 
5805064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
5815064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5825064Sdm199847 		goto errout;
5834644Sbaban 
5844644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5854644Sbaban 	    OP_ADD_NAMERULE;
5864520Snw141292 	udthandle->next++;
5874520Snw141292 	return (IDMAP_SUCCESS);
5884520Snw141292 
5894520Snw141292 errout:
5904644Sbaban 	/* The batch should still be usable */
5914644Sbaban 	if (rule)
5924644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5934520Snw141292 	errno = idmap_stat2errno(retcode);
5944520Snw141292 	return (retcode);
5954520Snw141292 }
5964520Snw141292 
5974520Snw141292 
5984520Snw141292 /* ARGSUSED */
5994520Snw141292 idmap_stat
6004520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
6015696Snw141292     boolean_t is_wuser,	const char *windomain, const char *winname,
6025696Snw141292     const char *unixname, int direction)
6035696Snw141292 {
6044520Snw141292 	idmap_retcode	retcode;
6054644Sbaban 	idmap_namerule	*rule = NULL;
6064520Snw141292 
6074644Sbaban 	retcode = _udt_extend_batch(udthandle);
6084520Snw141292 	if (retcode != IDMAP_SUCCESS)
6094520Snw141292 		goto errout;
6104520Snw141292 
6114520Snw141292 	rule = &udthandle->batch.
6125696Snw141292 	    idmap_update_batch_val[udthandle->next].
6135696Snw141292 	    idmap_update_op_u.rule;
6144520Snw141292 	rule->is_user = is_user;
6155696Snw141292 	rule->is_wuser = is_wuser;
6164520Snw141292 	rule->direction = direction;
6175064Sdm199847 
6185064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6195064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6205064Sdm199847 		goto errout;
6215064Sdm199847 
6225064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
6235064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6245064Sdm199847 		goto errout;
6255064Sdm199847 
6265064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6275064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6285064Sdm199847 		goto errout;
6295064Sdm199847 
6304644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6314644Sbaban 	    OP_RM_NAMERULE;
6324520Snw141292 	udthandle->next++;
6334520Snw141292 	return (IDMAP_SUCCESS);
6344520Snw141292 
6354520Snw141292 errout:
6364644Sbaban 	if (rule)
6374644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
6384520Snw141292 	errno = idmap_stat2errno(retcode);
6394520Snw141292 	return (retcode);
6404520Snw141292 }
6414520Snw141292 
6424520Snw141292 
6434520Snw141292 /* ARGSUSED */
6444520Snw141292 idmap_stat
6455696Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
6465696Snw141292 {
6474520Snw141292 	idmap_retcode	retcode;
6484520Snw141292 
6494644Sbaban 	retcode = _udt_extend_batch(udthandle);
6504520Snw141292 	if (retcode != IDMAP_SUCCESS)
6514520Snw141292 		goto errout;
6524520Snw141292 
6534644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6544644Sbaban 	    OP_FLUSH_NAMERULES;
6554520Snw141292 	udthandle->next++;
6564520Snw141292 	return (IDMAP_SUCCESS);
6574520Snw141292 
6584520Snw141292 errout:
6594520Snw141292 	errno = idmap_stat2errno(retcode);
6604520Snw141292 	return (retcode);
6614520Snw141292 }
6624520Snw141292 
6634520Snw141292 
6644520Snw141292 /*
6654520Snw141292  * Set the number of entries requested per batch by the iterator
6664520Snw141292  *
6674520Snw141292  * Input:
6684520Snw141292  * iter  - iterator
6694520Snw141292  * limit - number of entries requested per batch
6704520Snw141292  */
6714520Snw141292 idmap_stat
6725696Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
6735696Snw141292 {
6744520Snw141292 	if (iter == NULL) {
6754520Snw141292 		errno = EINVAL;
6764520Snw141292 		return (IDMAP_ERR_ARG);
6774520Snw141292 	}
6784520Snw141292 	iter->limit = limit;
6794520Snw141292 	return (IDMAP_SUCCESS);
6804520Snw141292 }
6814520Snw141292 
6824520Snw141292 
6834520Snw141292 /*
6844520Snw141292  * Create iterator to get name-based mapping rules
6854520Snw141292  *
6864520Snw141292  * Input:
6874520Snw141292  * windomain - Windows domain
6884520Snw141292  * is_user   - user or group rules
6894520Snw141292  * winname   - Windows user or group name
6904520Snw141292  * unixname  - Unix user or group name
6914520Snw141292  *
6924520Snw141292  * Output:
6934520Snw141292  * iter - iterator
6944520Snw141292  */
6954520Snw141292 idmap_stat
6964520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
6975696Snw141292 		boolean_t is_user, boolean_t is_wuser, const char *winname,
6985696Snw141292 		const char *unixname, idmap_iter_t **iter)
6995696Snw141292 {
7004520Snw141292 
7014520Snw141292 	idmap_iter_t			*tmpiter;
7024520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
7034520Snw141292 	idmap_namerule			*rule;
7044520Snw141292 	idmap_retcode			retcode;
7054520Snw141292 
7064520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
7074520Snw141292 
7084520Snw141292 	rule = &arg->rule;
7094520Snw141292 	rule->is_user = is_user;
7105696Snw141292 	rule->is_wuser = is_wuser;
7114644Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
7125064Sdm199847 
7135064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
7145064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7155064Sdm199847 		goto errout;
7165064Sdm199847 
7175064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
7185064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7195064Sdm199847 		goto errout;
7205064Sdm199847 
7215064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
7225064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7235064Sdm199847 		goto errout;
7244520Snw141292 
7254520Snw141292 	*iter = tmpiter;
7264520Snw141292 	return (IDMAP_SUCCESS);
7274520Snw141292 
7284520Snw141292 errout:
7294520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
7305696Snw141292 	    xdr_idmap_list_namerules_1_argument, retcode);
7314520Snw141292 }
7324520Snw141292 
7334520Snw141292 
7344520Snw141292 /*
7354520Snw141292  * Iterate through the name-based mapping rules
7364520Snw141292  *
7374520Snw141292  * Input:
7384520Snw141292  * iter - iterator
7394520Snw141292  *
7404520Snw141292  * Output:
7414520Snw141292  * windomain - Windows domain
7424520Snw141292  * winname   - Windows user or group name
7434520Snw141292  * unixname  - Unix user or group name
7444520Snw141292  * is_nt4    - NT4 or AD
7454520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
7464520Snw141292  *
7474520Snw141292  * Return value:
7484520Snw141292  * 0   - done
7494520Snw141292  * 1   - more results available
7504520Snw141292  * < 0 - error
7514520Snw141292  */
7524520Snw141292 idmap_stat
7534520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
7545696Snw141292     char **winname, char **unixname,  boolean_t *is_user,
7555696Snw141292     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
7565696Snw141292 {
7574520Snw141292 	idmap_namerules_res		*namerules;
7584520Snw141292 	idmap_list_namerules_1_argument	*arg;
7594520Snw141292 	idmap_retcode			retcode;
7604520Snw141292 
7615696Snw141292 	idmap_namerule_parts_clear(windomain, winname,
7625696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
7635696Snw141292 
7644520Snw141292 
7654520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
7664520Snw141292 
7674520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
7684520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
7695696Snw141292 	    iter->next >= namerules->rules.rules_len)) {
7704520Snw141292 
7714520Snw141292 		if ((arg = iter->arg) == NULL) {
7724520Snw141292 			errno = EINVAL;
7734520Snw141292 			return (IDMAP_ERR_ARG);
7744520Snw141292 		}
7754520Snw141292 		arg->limit = iter->limit;
7764520Snw141292 
7774520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
7785696Snw141292 		    iter, arg,
7795696Snw141292 		    (uchar_t **)&namerules, sizeof (*namerules),
7805696Snw141292 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
7815696Snw141292 		    (xdrproc_t)xdr_idmap_namerules_res);
7824520Snw141292 		if (retcode != IDMAP_SUCCESS)
7834520Snw141292 			return (retcode);
7844520Snw141292 
7854520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
7864520Snw141292 			retcode  = namerules->retcode;
7874520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
7884520Snw141292 			free(namerules);
7894520Snw141292 			iter->retlist = NULL;
7904520Snw141292 			return (retcode);
7914520Snw141292 		}
7924520Snw141292 		iter->retcode = namerules->retcode;
7934520Snw141292 		arg->lastrowid = namerules->lastrowid;
7944520Snw141292 	}
7954520Snw141292 
7964520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
7974520Snw141292 		return (IDMAP_SUCCESS);
7984520Snw141292 
7994520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
8004520Snw141292 		return (IDMAP_ERR_ARG);
8014520Snw141292 	}
8024520Snw141292 
8035064Sdm199847 	retcode = idmap_strdupnull(windomain,
8045064Sdm199847 	    namerules->rules.rules_val[iter->next].windomain);
8055064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8065064Sdm199847 		goto errout;
8075064Sdm199847 
8085064Sdm199847 	retcode = idmap_strdupnull(winname,
8095064Sdm199847 	    namerules->rules.rules_val[iter->next].winname);
8105064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8115064Sdm199847 		goto errout;
8125064Sdm199847 
8135064Sdm199847 	retcode = idmap_strdupnull(unixname,
8145064Sdm199847 	    namerules->rules.rules_val[iter->next].unixname);
8155064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8165064Sdm199847 		goto errout;
8175064Sdm199847 
8184520Snw141292 	if (is_nt4)
8194520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
8205696Snw141292 	if (is_user)
8215696Snw141292 		*is_user = namerules->rules.rules_val[iter->next].is_user;
8225696Snw141292 	if (is_wuser)
8235696Snw141292 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
8244520Snw141292 	if (direction)
8254520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
8264520Snw141292 	iter->next++;
8274520Snw141292 
8284520Snw141292 	if (iter->next == namerules->rules.rules_len)
8294520Snw141292 		return (iter->retcode);
8304520Snw141292 	else
8314520Snw141292 		return (IDMAP_NEXT);
8324520Snw141292 
8334520Snw141292 errout:
8344520Snw141292 	if (windomain && *windomain)
8354520Snw141292 		free(*windomain);
8364520Snw141292 	if (winname && *winname)
8374520Snw141292 		free(*winname);
8384520Snw141292 	if (unixname && *unixname)
8394520Snw141292 		free(*unixname);
8404520Snw141292 	return (retcode);
8414520Snw141292 }
8424520Snw141292 
8434520Snw141292 
8444520Snw141292 /*
8454520Snw141292  * Create iterator to get SID to UID/GID mappings
8464520Snw141292  *
8474520Snw141292  * Output:
8484520Snw141292  * iter - iterator
8494520Snw141292  */
8504520Snw141292 idmap_stat
8516386Sjp151216 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
8525696Snw141292 {
8534520Snw141292 	idmap_iter_t			*tmpiter;
8544520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
8554520Snw141292 
8564520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
8574520Snw141292 
8586386Sjp151216 	arg->flag = flag;
8594520Snw141292 	*iter = tmpiter;
8604520Snw141292 	return (IDMAP_SUCCESS);
8614520Snw141292 }
8624520Snw141292 
8634520Snw141292 
8644520Snw141292 /*
8654520Snw141292  * Iterate through the SID to UID/GID mappings
8664520Snw141292  *
8674520Snw141292  * Input:
8684520Snw141292  * iter - iterator
8694520Snw141292  *
8704520Snw141292  * Output:
8714520Snw141292  * sid - SID in canonical form
8724520Snw141292  * pid - UID or GID
8734520Snw141292  *
8744520Snw141292  * Return value:
8754520Snw141292  * 0   - done
8764520Snw141292  * 1   - more results available
8774520Snw141292  * < 0 - error
8784520Snw141292  */
8794520Snw141292 idmap_stat
8804520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
8815696Snw141292     idmap_rid_t *rid, uid_t *pid, char **winname,
8825696Snw141292     char **windomain, char **unixname, boolean_t *is_user,
8836386Sjp151216     boolean_t *is_wuser, int *direction, idmap_info *info)
8845696Snw141292 {
8854520Snw141292 	idmap_mappings_res		*mappings;
8864520Snw141292 	idmap_list_mappings_1_argument	*arg;
8874520Snw141292 	idmap_retcode			retcode;
8884520Snw141292 	char				*str;
8894520Snw141292 
8904520Snw141292 	if (sidprefix)
8914520Snw141292 		*sidprefix = NULL;
8924520Snw141292 	if (rid)
8934520Snw141292 		*rid = UINT32_MAX;
8944520Snw141292 	if (winname)
8954520Snw141292 		*winname = NULL;
8964520Snw141292 	if (windomain)
8974520Snw141292 		*windomain = NULL;
8984520Snw141292 	if (unixname)
8994520Snw141292 		*unixname = NULL;
9004520Snw141292 	if (pid)
9014520Snw141292 		*pid = UINT32_MAX;
9025696Snw141292 	if (is_user)
9035696Snw141292 		*is_user = -1;
9045696Snw141292 	if (is_wuser)
9055696Snw141292 		*is_wuser = -1;
9064520Snw141292 	if (direction)
9074644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
9084520Snw141292 
9094520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
9104520Snw141292 
9114520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
9124520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
9135696Snw141292 	    iter->next >= mappings->mappings.mappings_len)) {
9144520Snw141292 
9154520Snw141292 		if ((arg = iter->arg) == NULL) {
9164520Snw141292 			errno = EINVAL;
9174520Snw141292 			return (IDMAP_ERR_ARG);
9184520Snw141292 		}
9194520Snw141292 		arg->limit = iter->limit;
9204520Snw141292 
9214520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
9225696Snw141292 		    iter, arg,
9235696Snw141292 		    (uchar_t **)&mappings, sizeof (*mappings),
9245696Snw141292 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
9255696Snw141292 		    (xdrproc_t)xdr_idmap_mappings_res);
9264520Snw141292 		if (retcode != IDMAP_SUCCESS)
9274520Snw141292 			return (retcode);
9284520Snw141292 
9294520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
9304520Snw141292 			retcode  = mappings->retcode;
9314520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
9324520Snw141292 			free(mappings);
9334520Snw141292 			iter->retlist = NULL;
9344520Snw141292 			return (retcode);
9354520Snw141292 		}
9364520Snw141292 		iter->retcode = mappings->retcode;
9374520Snw141292 		arg->lastrowid = mappings->lastrowid;
9384520Snw141292 	}
9394520Snw141292 
9404520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
9414520Snw141292 		return (IDMAP_SUCCESS);
9424520Snw141292 
9434520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
9444520Snw141292 		return (IDMAP_ERR_ARG);
9454520Snw141292 	}
9464520Snw141292 
9474520Snw141292 	if (sidprefix) {
9484520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
9495696Snw141292 		    idmap_id_u.sid.prefix;
9504695Sbaban 		if (str && *str != '\0') {
9514520Snw141292 			*sidprefix = strdup(str);
9524526Sbaban 			if (*sidprefix == NULL) {
9534526Sbaban 				retcode = IDMAP_ERR_MEMORY;
9544526Sbaban 				goto errout;
9554526Sbaban 			}
9564520Snw141292 		}
9574520Snw141292 	}
9584520Snw141292 	if (rid)
9594520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
9605696Snw141292 		    idmap_id_u.sid.rid;
9615064Sdm199847 
9625064Sdm199847 	retcode = idmap_strdupnull(windomain,
9635064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1domain);
9645064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9655064Sdm199847 		goto errout;
9665064Sdm199847 
9675064Sdm199847 	retcode = idmap_strdupnull(winname,
9685064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1name);
9695064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9705064Sdm199847 		goto errout;
9715064Sdm199847 
9725064Sdm199847 	retcode = idmap_strdupnull(unixname,
9735064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id2name);
9745064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9755064Sdm199847 		goto errout;
9765064Sdm199847 
9775064Sdm199847 
9784520Snw141292 	if (pid)
9794520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
9805696Snw141292 		    idmap_id_u.uid;
9814520Snw141292 	if (direction)
9824520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
9835696Snw141292 		    direction;
9845696Snw141292 	if (is_user)
9855696Snw141292 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
9865696Snw141292 		    .idtype == IDMAP_UID)?1:0;
9875696Snw141292 	if (is_wuser)
9885696Snw141292 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
9895696Snw141292 		    .idtype == IDMAP_USID)?1:0;
9905696Snw141292 
9916386Sjp151216 	if (info) {
9926386Sjp151216 		retcode = idmap_info_cpy(info,
9936386Sjp151216 		    &mappings->mappings.mappings_val[iter->next].info);
9946386Sjp151216 		if (retcode != IDMAP_SUCCESS)
9956386Sjp151216 			goto errout;
9966386Sjp151216 	}
9974520Snw141292 	iter->next++;
9984520Snw141292 
9994520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
10004520Snw141292 		return (iter->retcode);
10014520Snw141292 	else
10024520Snw141292 		return (IDMAP_NEXT);
10034520Snw141292 
10044520Snw141292 errout:
10054520Snw141292 	if (sidprefix && *sidprefix)
10064520Snw141292 		free(*sidprefix);
10074520Snw141292 	if (winname && *winname)
10084520Snw141292 		free(*winname);
10094520Snw141292 	if (windomain && *windomain)
10104520Snw141292 		free(*windomain);
10114520Snw141292 	if (unixname && *unixname)
10124520Snw141292 		free(*unixname);
10134520Snw141292 	return (retcode);
10144520Snw141292 }
10154520Snw141292 
10164520Snw141292 
10174520Snw141292 /*
10184520Snw141292  * Destroy the iterator
10194520Snw141292  */
10204520Snw141292 void
10215696Snw141292 idmap_iter_destroy(idmap_iter_t *iter)
10225696Snw141292 {
10234520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
10244520Snw141292 
10254520Snw141292 	if (iter == NULL)
10264520Snw141292 		return;
10274520Snw141292 
10284520Snw141292 	switch (iter->type) {
10294520Snw141292 	case IDMAP_LIST_NAMERULES:
10304520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
10314520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
10324520Snw141292 		break;
10334520Snw141292 	case IDMAP_LIST_MAPPINGS:
10344520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
10354520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
10364520Snw141292 		break;
10374520Snw141292 	default:
10384520Snw141292 		free(iter);
10394520Snw141292 		return;
10404520Snw141292 	};
10414520Snw141292 
10424520Snw141292 	if (iter->arg) {
10434520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
10444520Snw141292 		free(iter->arg);
10454520Snw141292 	}
10464520Snw141292 	if (iter->retlist) {
10474520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
10484520Snw141292 		free(iter->retlist);
10494520Snw141292 	}
10504520Snw141292 	free(iter);
10514520Snw141292 }
10524520Snw141292 
10534520Snw141292 
10544520Snw141292 /*
10554520Snw141292  * Create handle to get SID to UID/GID mapping entries
10564520Snw141292  *
10574520Snw141292  * Input:
10584520Snw141292  * gh - "get mapping" handle
10594520Snw141292  */
10604520Snw141292 idmap_stat
10615696Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
10625696Snw141292 {
10634520Snw141292 	idmap_get_handle_t	*tmp;
10644520Snw141292 
10654520Snw141292 	/* sanity checks */
10664520Snw141292 	if (handle == NULL || gh == NULL) {
10674520Snw141292 		errno = EINVAL;
10684520Snw141292 		return (IDMAP_ERR_ARG);
10694520Snw141292 	}
10704520Snw141292 
10714520Snw141292 	/* allocate the handle */
10724520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
10734520Snw141292 		errno = ENOMEM;
10744520Snw141292 		return (IDMAP_ERR_MEMORY);
10754520Snw141292 	}
10764520Snw141292 
10774520Snw141292 	tmp->ih = handle;
10784520Snw141292 	*gh = tmp;
10794520Snw141292 	return (IDMAP_SUCCESS);
10804520Snw141292 }
10814520Snw141292 
10824520Snw141292 
10834520Snw141292 /*
10844520Snw141292  * Given SID, get UID
10854520Snw141292  *
10864520Snw141292  * Input:
10874520Snw141292  * sidprefix  - SID prefix
10884520Snw141292  * rid        - RID
10894520Snw141292  * flag       - flag
10904520Snw141292  *
10914520Snw141292  * Output:
10924520Snw141292  * stat - status of the get request
10934520Snw141292  * uid  - POSIX UID if stat = 0
10944520Snw141292  *
10954520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
10964520Snw141292  */
10974520Snw141292 idmap_stat
10984520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
10995696Snw141292 		int flag, uid_t *uid, idmap_stat *stat)
11005696Snw141292 {
11016386Sjp151216 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
11026386Sjp151216 	    NULL, stat));
11036386Sjp151216 }
11044520Snw141292 
11056386Sjp151216 /*
11066386Sjp151216  * Given SID, get UID
11076386Sjp151216  *
11086386Sjp151216  * Input:
11096386Sjp151216  * sidprefix  - SID prefix
11106386Sjp151216  * rid        - RID
11116386Sjp151216  * flag       - flag
11126386Sjp151216  *
11136386Sjp151216  * Output:
11146386Sjp151216  * stat - status of the get request
11156386Sjp151216  * uid  - POSIX UID if stat = 0
11166386Sjp151216  * how  - mapping type if stat = 0
11176386Sjp151216  *
11186386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
11196386Sjp151216  */
11206386Sjp151216 
11216386Sjp151216 idmap_stat
11226386Sjp151216 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11236386Sjp151216 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
11246386Sjp151216 {
11254520Snw141292 	idmap_retcode	retcode;
11264644Sbaban 	idmap_mapping	*mapping = NULL;
11274520Snw141292 
11284520Snw141292 	/* sanity checks */
11294520Snw141292 	if (gh == NULL)
11304520Snw141292 		return (IDMAP_ERR_ARG);
11314520Snw141292 	if (uid == NULL || sidprefix == NULL)
11324520Snw141292 		return (IDMAP_ERR_ARG);
11334520Snw141292 
11347369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
11357369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
11367369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid);
11377369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
11387369SJulian.Pullen@Sun.COM 			*stat = retcode;
11397369SJulian.Pullen@Sun.COM 			return (retcode);
11407369SJulian.Pullen@Sun.COM 		}
11417369SJulian.Pullen@Sun.COM 	}
11427369SJulian.Pullen@Sun.COM 
11434520Snw141292 	/* Extend the request array and the return list */
11444520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11454520Snw141292 		goto errout;
11464520Snw141292 
11474520Snw141292 	/* Setup the request */
11484520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11494520Snw141292 	mapping->flag = flag;
11504520Snw141292 	mapping->id1.idtype = IDMAP_SID;
11514520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
11524520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
11534520Snw141292 		retcode = IDMAP_ERR_MEMORY;
11544520Snw141292 		goto errout;
11554520Snw141292 	}
11564520Snw141292 	mapping->id2.idtype = IDMAP_UID;
11574520Snw141292 
11584520Snw141292 	/* Setup pointers for the result */
11594520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
11604520Snw141292 	gh->retlist[gh->next].uid = uid;
11614520Snw141292 	gh->retlist[gh->next].stat = stat;
11626386Sjp151216 	gh->retlist[gh->next].info = info;
11637369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
11644520Snw141292 
11654520Snw141292 	gh->next++;
11664520Snw141292 	return (IDMAP_SUCCESS);
11674520Snw141292 
11684520Snw141292 errout:
11694644Sbaban 	/* Batch created so far should still be usable */
11704644Sbaban 	if (mapping)
11714644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
11724520Snw141292 	errno = idmap_stat2errno(retcode);
11734520Snw141292 	return (retcode);
11744520Snw141292 }
11754520Snw141292 
11764520Snw141292 
11774520Snw141292 /*
11784520Snw141292  * Given SID, get GID
11794520Snw141292  *
11804520Snw141292  * Input:
11814520Snw141292  * sidprefix  - SID prefix
11824520Snw141292  * rid        - rid
11834520Snw141292  * flag       - flag
11844520Snw141292  *
11854520Snw141292  * Output:
11864520Snw141292  * stat - status of the get request
11874520Snw141292  * gid  - POSIX GID if stat = 0
11884520Snw141292  *
11894520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11904520Snw141292  */
11914520Snw141292 idmap_stat
11924520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11935696Snw141292 		int flag, gid_t *gid, idmap_stat *stat)
11945696Snw141292 {
11956386Sjp151216 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
11966386Sjp151216 	    NULL, stat));
11976386Sjp151216 }
11986386Sjp151216 
11996386Sjp151216 
12006386Sjp151216 /*
12016386Sjp151216  * Given SID, get GID
12026386Sjp151216  *
12036386Sjp151216  * Input:
12046386Sjp151216  * sidprefix  - SID prefix
12056386Sjp151216  * rid        - rid
12066386Sjp151216  * flag       - flag
12076386Sjp151216  *
12086386Sjp151216  * Output:
12096386Sjp151216  * stat - status of the get request
12106386Sjp151216  * gid  - POSIX GID if stat = 0
12116386Sjp151216  * how  - mapping type if stat = 0
12126386Sjp151216  *
12136386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
12146386Sjp151216  */
12156386Sjp151216 idmap_stat
12166386Sjp151216 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12176386Sjp151216 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
12186386Sjp151216 {
12194520Snw141292 
12204520Snw141292 	idmap_retcode	retcode;
12214644Sbaban 	idmap_mapping	*mapping = NULL;
12224520Snw141292 
12234520Snw141292 	/* sanity checks */
12244520Snw141292 	if (gh == NULL)
12254520Snw141292 		return (IDMAP_ERR_ARG);
12264520Snw141292 	if (gid == NULL || sidprefix == NULL)
12274520Snw141292 		return (IDMAP_ERR_ARG);
12284520Snw141292 
12297369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
12307369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
12317369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid);
12327369SJulian.Pullen@Sun.COM 		if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
12337369SJulian.Pullen@Sun.COM 			*stat = retcode;
12347369SJulian.Pullen@Sun.COM 			return (retcode);
12357369SJulian.Pullen@Sun.COM 		}
12367369SJulian.Pullen@Sun.COM 	}
12377369SJulian.Pullen@Sun.COM 
12384520Snw141292 	/* Extend the request array and the return list */
12394520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
12404520Snw141292 		goto errout;
12414520Snw141292 
12424520Snw141292 	/* Setup the request */
12434520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
12444520Snw141292 	mapping->flag = flag;
12454520Snw141292 	mapping->id1.idtype = IDMAP_SID;
12464520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
12474520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
12484520Snw141292 		retcode = IDMAP_ERR_MEMORY;
12494520Snw141292 		goto errout;
12504520Snw141292 	}
12514520Snw141292 	mapping->id2.idtype = IDMAP_GID;
12524520Snw141292 
12534520Snw141292 	/* Setup pointers for the result */
12544520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
12554520Snw141292 	gh->retlist[gh->next].gid = gid;
12564520Snw141292 	gh->retlist[gh->next].stat = stat;
12576386Sjp151216 	gh->retlist[gh->next].info = info;
12587369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
12594520Snw141292 
12604520Snw141292 	gh->next++;
12614520Snw141292 	return (IDMAP_SUCCESS);
12624520Snw141292 
12634520Snw141292 errout:
12644644Sbaban 	if (mapping)
12654644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12664520Snw141292 	errno = idmap_stat2errno(retcode);
12674520Snw141292 	return (retcode);
12684520Snw141292 }
12694520Snw141292 
12704520Snw141292 
12716386Sjp151216 
12724520Snw141292 /*
12734520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
12744520Snw141292  *
12754520Snw141292  * Input:
12764520Snw141292  * sidprefix  - SID prefix
12774520Snw141292  * rid        - rid
12784520Snw141292  * flag       - flag
12794520Snw141292  *
12804520Snw141292  * Output:
12814520Snw141292  * stat    - status of the get request
12824520Snw141292  * is_user - user or group
12834520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
12844520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
12854520Snw141292  *
12864520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12874520Snw141292  */
12884520Snw141292 idmap_stat
12894520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12905696Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
12915696Snw141292 {
12926386Sjp151216 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
12936386Sjp151216 	    NULL, stat));
12946386Sjp151216 }
12956386Sjp151216 
12966386Sjp151216 
12976386Sjp151216 
12986386Sjp151216 /*
12996386Sjp151216  * Given SID, get POSIX ID i.e. UID/GID
13006386Sjp151216  *
13016386Sjp151216  * Input:
13026386Sjp151216  * sidprefix  - SID prefix
13036386Sjp151216  * rid        - rid
13046386Sjp151216  * flag       - flag
13056386Sjp151216  *
13066386Sjp151216  * Output:
13076386Sjp151216  * stat    - status of the get request
13086386Sjp151216  * is_user - user or group
13096386Sjp151216  * pid     - POSIX UID if stat = 0 and is_user = 1
13106386Sjp151216  *           POSIX GID if stat = 0 and is_user = 0
13116386Sjp151216  * how     - mapping type if stat = 0
13126386Sjp151216  *
13136386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
13146386Sjp151216  */
13156386Sjp151216 idmap_stat
13166386Sjp151216 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
13176386Sjp151216 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
13186386Sjp151216 {
13194520Snw141292 	idmap_retcode	retcode;
13204644Sbaban 	idmap_mapping	*mapping = NULL;
13214520Snw141292 
13224520Snw141292 	/* sanity checks */
13234520Snw141292 	if (gh == NULL)
13244520Snw141292 		return (IDMAP_ERR_ARG);
13254520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
13264520Snw141292 		return (IDMAP_ERR_ARG);
13274520Snw141292 
13287369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
13297369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
13307369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid,
13317369SJulian.Pullen@Sun.COM 		    is_user);
13327369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
13337369SJulian.Pullen@Sun.COM 			*stat = retcode;
13347369SJulian.Pullen@Sun.COM 			return (retcode);
13357369SJulian.Pullen@Sun.COM 		}
13367369SJulian.Pullen@Sun.COM 	}
13377369SJulian.Pullen@Sun.COM 
13384520Snw141292 	/* Extend the request array and the return list */
13394520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
13404520Snw141292 		goto errout;
13414520Snw141292 
13424520Snw141292 	/* Setup the request */
13434520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
13444520Snw141292 	mapping->flag = flag;
13454520Snw141292 	mapping->id1.idtype = IDMAP_SID;
13464520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
13474520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
13484520Snw141292 		retcode = IDMAP_ERR_MEMORY;
13494520Snw141292 		goto errout;
13504520Snw141292 	}
13514520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
13524520Snw141292 
13534520Snw141292 	/* Setup pointers for the result */
13544520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
13554520Snw141292 	gh->retlist[gh->next].uid = pid;
13564520Snw141292 	gh->retlist[gh->next].gid = pid;
13574520Snw141292 	gh->retlist[gh->next].is_user = is_user;
13584520Snw141292 	gh->retlist[gh->next].stat = stat;
13596386Sjp151216 	gh->retlist[gh->next].info = info;
13607369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
13614520Snw141292 
13624520Snw141292 	gh->next++;
13634520Snw141292 	return (IDMAP_SUCCESS);
13644520Snw141292 
13654520Snw141292 errout:
13664644Sbaban 	if (mapping)
13674644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
13684520Snw141292 	errno = idmap_stat2errno(retcode);
13694520Snw141292 	return (retcode);
13704520Snw141292 }
13714520Snw141292 
13724520Snw141292 
13734520Snw141292 /*
13744520Snw141292  * Given UID, get SID
13754520Snw141292  *
13764520Snw141292  * Input:
13774520Snw141292  * uid  - POSIX UID
13784520Snw141292  * flag - flag
13794520Snw141292  *
13804520Snw141292  * Output:
13814520Snw141292  * stat - status of the get request
13824520Snw141292  * sid  - SID prefix (if stat == 0)
13834520Snw141292  * rid  - rid
13844520Snw141292  *
13854520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
13864520Snw141292  */
13874520Snw141292 idmap_stat
13884520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
13895696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
13905696Snw141292 {
13916386Sjp151216 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
13926386Sjp151216 	    NULL, stat));
13936386Sjp151216 }
13946386Sjp151216 
13956386Sjp151216 
13966386Sjp151216 /*
13976386Sjp151216  * Given UID, get SID
13986386Sjp151216  *
13996386Sjp151216  * Input:
14006386Sjp151216  * uid  - POSIX UID
14016386Sjp151216  * flag - flag
14026386Sjp151216  *
14036386Sjp151216  * Output:
14046386Sjp151216  * stat - status of the get request
14056386Sjp151216  * sid  - SID prefix (if stat == 0)
14066386Sjp151216  * rid  - rid
14076386Sjp151216  * how  - mapping type if stat = 0
14086386Sjp151216  *
14096386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
14106386Sjp151216  */
14116386Sjp151216 idmap_stat
14126386Sjp151216 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
14136386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
14146386Sjp151216 {
14154520Snw141292 
14164520Snw141292 	idmap_retcode	retcode;
14174644Sbaban 	idmap_mapping	*mapping = NULL;
14184520Snw141292 
14194520Snw141292 	/* sanity checks */
14204520Snw141292 	if (gh == NULL)
14214520Snw141292 		return (IDMAP_ERR_ARG);
14224520Snw141292 	if (sidprefix == NULL)
14234520Snw141292 		return (IDMAP_ERR_ARG);
14244520Snw141292 
14257369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
14267369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
14277369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid);
14287369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
14297369SJulian.Pullen@Sun.COM 			*stat = retcode;
14307369SJulian.Pullen@Sun.COM 			return (retcode);
14317369SJulian.Pullen@Sun.COM 		}
14327369SJulian.Pullen@Sun.COM 	}
14337369SJulian.Pullen@Sun.COM 
14344520Snw141292 	/* Extend the request array and the return list */
14354520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
14364520Snw141292 		goto errout;
14374520Snw141292 
14384520Snw141292 	/* Setup the request */
14394520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
14404520Snw141292 	mapping->flag = flag;
14414520Snw141292 	mapping->id1.idtype = IDMAP_UID;
14424520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
14434520Snw141292 	mapping->id2.idtype = IDMAP_SID;
14444520Snw141292 
14454520Snw141292 	/* Setup pointers for the result */
14464520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
14474520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
14484520Snw141292 	gh->retlist[gh->next].rid = rid;
14494520Snw141292 	gh->retlist[gh->next].stat = stat;
14506386Sjp151216 	gh->retlist[gh->next].info = info;
14517369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
14524520Snw141292 
14534520Snw141292 	gh->next++;
14544520Snw141292 	return (IDMAP_SUCCESS);
14554520Snw141292 
14564520Snw141292 errout:
14574644Sbaban 	if (mapping)
14584644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
14594520Snw141292 	errno = idmap_stat2errno(retcode);
14604520Snw141292 	return (retcode);
14614520Snw141292 }
14624520Snw141292 
14634520Snw141292 
14644520Snw141292 /*
14654520Snw141292  * Given GID, get SID
14664520Snw141292  *
14674520Snw141292  * Input:
14684520Snw141292  * gid  - POSIX GID
14694520Snw141292  * flag - flag
14704520Snw141292  *
14714520Snw141292  * Output:
14724520Snw141292  * stat       - status of the get request
14734520Snw141292  * sidprefix  - SID prefix (if stat == 0)
14744520Snw141292  * rid        - rid
14754520Snw141292  *
14764520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
14774520Snw141292  */
14784520Snw141292 idmap_stat
14794520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
14805696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
14815696Snw141292 {
14826386Sjp151216 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
14836386Sjp151216 	    NULL, stat));
14846386Sjp151216 }
14856386Sjp151216 
14866386Sjp151216 
14876386Sjp151216 /*
14886386Sjp151216  * Given GID, get SID
14896386Sjp151216  *
14906386Sjp151216  * Input:
14916386Sjp151216  * gid  - POSIX GID
14926386Sjp151216  * flag - flag
14936386Sjp151216  *
14946386Sjp151216  * Output:
14956386Sjp151216  * stat       - status of the get request
14966386Sjp151216  * sidprefix  - SID prefix (if stat == 0)
14976386Sjp151216  * rid        - rid
14986386Sjp151216  * how        - mapping type if stat = 0
14996386Sjp151216  *
15006386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
15016386Sjp151216  */
15026386Sjp151216 idmap_stat
15036386Sjp151216 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
15046386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
15056386Sjp151216 {
15064520Snw141292 
15074520Snw141292 	idmap_retcode	retcode;
15084644Sbaban 	idmap_mapping	*mapping = NULL;
15094520Snw141292 
15104520Snw141292 	/* sanity checks */
15114520Snw141292 	if (gh == NULL)
15124520Snw141292 		return (IDMAP_ERR_ARG);
15134520Snw141292 	if (sidprefix == NULL)
15144520Snw141292 		return (IDMAP_ERR_ARG);
15154520Snw141292 
15167369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
15177369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
15187369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid);
15197369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
15207369SJulian.Pullen@Sun.COM 			*stat = retcode;
15217369SJulian.Pullen@Sun.COM 			return (retcode);
15227369SJulian.Pullen@Sun.COM 		}
15237369SJulian.Pullen@Sun.COM 	}
15247369SJulian.Pullen@Sun.COM 
15254520Snw141292 	/* Extend the request array and the return list */
15264520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
15274520Snw141292 		goto errout;
15284520Snw141292 
15294520Snw141292 	/* Setup the request */
15304520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
15314520Snw141292 	mapping->flag = flag;
15324520Snw141292 	mapping->id1.idtype = IDMAP_GID;
15334520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
15344520Snw141292 	mapping->id2.idtype = IDMAP_SID;
15354520Snw141292 
15364520Snw141292 	/* Setup pointers for the result */
15374520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
15384520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
15394520Snw141292 	gh->retlist[gh->next].rid = rid;
15404520Snw141292 	gh->retlist[gh->next].stat = stat;
15416386Sjp151216 	gh->retlist[gh->next].info = info;
15427369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
15434520Snw141292 
15444520Snw141292 	gh->next++;
15454520Snw141292 	return (IDMAP_SUCCESS);
15464520Snw141292 
15474520Snw141292 errout:
15484644Sbaban 	if (mapping)
15494644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
15504520Snw141292 	errno = idmap_stat2errno(retcode);
15514520Snw141292 	return (retcode);
15524520Snw141292 }
15534520Snw141292 
15544520Snw141292 
15554520Snw141292 /*
15564520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
15574520Snw141292  * status and identity) will be available in the data areas
15584520Snw141292  * provided by individual requests.
15594520Snw141292  */
15604520Snw141292 idmap_stat
15615696Snw141292 idmap_get_mappings(idmap_get_handle_t *gh)
15625696Snw141292 {
15634520Snw141292 	CLIENT		*clnt;
15644520Snw141292 	enum clnt_stat	clntstat;
15654520Snw141292 	idmap_retcode	retcode;
15664520Snw141292 	idmap_ids_res	res;
15677369SJulian.Pullen@Sun.COM 	idmap_id	*res_id;
15684520Snw141292 	int		i;
15697369SJulian.Pullen@Sun.COM 	idmap_id	*req_id;
15707369SJulian.Pullen@Sun.COM 	int		direction;
15714520Snw141292 
15724520Snw141292 	if (gh == NULL) {
15734520Snw141292 		errno = EINVAL;
15744520Snw141292 		return (IDMAP_ERR_ARG);
15754520Snw141292 	}
15764520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
15774520Snw141292 
15784520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
15794520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
15805696Snw141292 	    (xdrproc_t)xdr_idmap_mapping_batch,
15815696Snw141292 	    (caddr_t)&gh->batch,
15825696Snw141292 	    (xdrproc_t)xdr_idmap_ids_res,
15835696Snw141292 	    (caddr_t)&res,
15845696Snw141292 	    TIMEOUT);
15854520Snw141292 	if (clntstat != RPC_SUCCESS) {
15864644Sbaban 		retcode = _idmap_rpc2stat(clnt);
15874520Snw141292 		goto out;
15884520Snw141292 	}
15894520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
15904520Snw141292 		retcode = res.retcode;
15914520Snw141292 		goto out;
15924520Snw141292 	}
15934520Snw141292 	for (i = 0; i < gh->next; i++) {
15944520Snw141292 		if (i >= res.ids.ids_len) {
15954520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
15964520Snw141292 			continue;
15974520Snw141292 		}
15984520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
15997369SJulian.Pullen@Sun.COM 		res_id = &res.ids.ids_val[i].id;
16007369SJulian.Pullen@Sun.COM 		direction = res.ids.ids_val[i].direction;
16017369SJulian.Pullen@Sun.COM 		req_id = &gh->batch.idmap_mapping_batch_val[i].id1;
16027369SJulian.Pullen@Sun.COM 		switch (res_id->idtype) {
16034520Snw141292 		case IDMAP_UID:
16044520Snw141292 			if (gh->retlist[i].uid)
16057369SJulian.Pullen@Sun.COM 				*gh->retlist[i].uid = res_id->idmap_id_u.uid;
16064520Snw141292 			if (gh->retlist[i].is_user)
16074520Snw141292 				*gh->retlist[i].is_user = 1;
16087369SJulian.Pullen@Sun.COM 
16097369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16107369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16117369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
16127369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
16137369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16147369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16157369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid, 1,
16167369SJulian.Pullen@Sun.COM 					    direction);
16177369SJulian.Pullen@Sun.COM 				else
16187369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
16197369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16207369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16217369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid,
16227369SJulian.Pullen@Sun.COM 					    direction);
16237369SJulian.Pullen@Sun.COM 			}
16244520Snw141292 			break;
16257369SJulian.Pullen@Sun.COM 
16264520Snw141292 		case IDMAP_GID:
16274520Snw141292 			if (gh->retlist[i].gid)
16287369SJulian.Pullen@Sun.COM 				*gh->retlist[i].gid = res_id->idmap_id_u.gid;
16294520Snw141292 			if (gh->retlist[i].is_user)
16304520Snw141292 				*gh->retlist[i].is_user = 0;
16317369SJulian.Pullen@Sun.COM 
16327369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16337369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16347369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
16357369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
16367369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16377369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16387369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid, 0,
16397369SJulian.Pullen@Sun.COM 					    direction);
16407369SJulian.Pullen@Sun.COM 				else
16417369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
16427369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
16437369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
16447369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid,
16457369SJulian.Pullen@Sun.COM 					    direction);
16467369SJulian.Pullen@Sun.COM 			}
16474520Snw141292 			break;
16487369SJulian.Pullen@Sun.COM 
16494864Sbaban 		case IDMAP_POSIXID:
16504864Sbaban 			if (gh->retlist[i].uid)
16514864Sbaban 				*gh->retlist[i].uid = 60001;
16524864Sbaban 			if (gh->retlist[i].is_user)
16534864Sbaban 				*gh->retlist[i].is_user = -1;
16544864Sbaban 			break;
16557369SJulian.Pullen@Sun.COM 
16564520Snw141292 		case IDMAP_SID:
16575696Snw141292 		case IDMAP_USID:
16585696Snw141292 		case IDMAP_GSID:
16594520Snw141292 			if (gh->retlist[i].rid)
16607369SJulian.Pullen@Sun.COM 				*gh->retlist[i].rid =
16617369SJulian.Pullen@Sun.COM 				    res_id->idmap_id_u.sid.rid;
16624520Snw141292 			if (gh->retlist[i].sidprefix) {
16637369SJulian.Pullen@Sun.COM 				if (res_id->idmap_id_u.sid.prefix == NULL ||
16647369SJulian.Pullen@Sun.COM 				    *res_id->idmap_id_u.sid.prefix == '\0') {
16654520Snw141292 					*gh->retlist[i].sidprefix = NULL;
16664520Snw141292 					break;
16674520Snw141292 				}
16684520Snw141292 				*gh->retlist[i].sidprefix =
16697369SJulian.Pullen@Sun.COM 				    strdup(res_id->idmap_id_u.sid.prefix);
16704520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
16714520Snw141292 					*gh->retlist[i].stat =
16725696Snw141292 					    IDMAP_ERR_MEMORY;
16734520Snw141292 			}
16747369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
16757369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
16767369SJulian.Pullen@Sun.COM 				if (req_id->idtype == IDMAP_UID)
16777369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
16787369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
16797369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
16807369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.uid,
16817369SJulian.Pullen@Sun.COM 					    direction);
16827369SJulian.Pullen@Sun.COM 				else /* req_id->idtype == IDMAP_GID */
16837369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
16847369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
16857369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
16867369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.gid,
16877369SJulian.Pullen@Sun.COM 					    direction);
16887369SJulian.Pullen@Sun.COM 			}
16894520Snw141292 			break;
16907369SJulian.Pullen@Sun.COM 
16914520Snw141292 		case IDMAP_NONE:
16924520Snw141292 			break;
16937369SJulian.Pullen@Sun.COM 
16944520Snw141292 		default:
16954520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
16964520Snw141292 			break;
16974520Snw141292 		}
16986386Sjp151216 		if (gh->retlist[i].info != NULL)
16996386Sjp151216 			(void) idmap_info_cpy(gh->retlist[i].info,
17006386Sjp151216 			    &res.ids.ids_val[i].info);
17014520Snw141292 	}
17024520Snw141292 	retcode = IDMAP_SUCCESS;
17034520Snw141292 
17044520Snw141292 out:
17054644Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
17064520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
17074520Snw141292 	errno = idmap_stat2errno(retcode);
17084520Snw141292 	return (retcode);
17094520Snw141292 }
17104520Snw141292 
17114520Snw141292 
17124520Snw141292 /*
17134520Snw141292  * Destroy the "get mapping" handle
17144520Snw141292  */
17154520Snw141292 void
17165696Snw141292 idmap_get_destroy(idmap_get_handle_t *gh)
17175696Snw141292 {
17184520Snw141292 	if (gh == NULL)
17194520Snw141292 		return;
17204520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
17214520Snw141292 	if (gh->retlist)
17224520Snw141292 		free(gh->retlist);
17234520Snw141292 	free(gh);
17244520Snw141292 }
17254520Snw141292 
17264520Snw141292 
17274520Snw141292 /*
17284520Snw141292  * Get windows to unix mapping
17294520Snw141292  */
17304520Snw141292 idmap_stat
17314520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
17324520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
17334520Snw141292 		const char *winname, const char *windomain,
17345696Snw141292 		int flag, int *is_user, int *is_wuser,
17356386Sjp151216 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
17365696Snw141292 {
17374520Snw141292 	CLIENT			*clnt;
17384520Snw141292 	enum clnt_stat		clntstat;
17394520Snw141292 	idmap_mapping		request, *mapping;
17404520Snw141292 	idmap_mappings_res	result;
17414520Snw141292 	idmap_retcode		retcode, rc;
17424520Snw141292 
17434520Snw141292 	if (handle == NULL) {
17444520Snw141292 		errno = EINVAL;
17454520Snw141292 		return (IDMAP_ERR_ARG);
17464520Snw141292 	}
17474520Snw141292 
17484520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
17494520Snw141292 
17504520Snw141292 	(void) memset(&request, 0, sizeof (request));
17514520Snw141292 	(void) memset(&result, 0, sizeof (result));
17524520Snw141292 
17534520Snw141292 	if (pid)
17544520Snw141292 		*pid = UINT32_MAX;
17554520Snw141292 	if (unixname)
17564520Snw141292 		*unixname = NULL;
17574520Snw141292 	if (direction)
17584644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
17594520Snw141292 
17604520Snw141292 	request.flag = flag;
17614520Snw141292 	request.id1.idtype = IDMAP_SID;
17624520Snw141292 	if (sidprefix && rid) {
17634520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
17644520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
17654520Snw141292 	} else if (winname) {
17665064Sdm199847 		retcode = idmap_strdupnull(&request.id1name, winname);
17675247Sbaban 		if (retcode != IDMAP_SUCCESS)
17684520Snw141292 			goto out;
17695064Sdm199847 
17705064Sdm199847 		retcode = idmap_strdupnull(&request.id1domain, windomain);
17715247Sbaban 		if (retcode != IDMAP_SUCCESS)
17725064Sdm199847 			goto out;
17735064Sdm199847 
17744520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
17754520Snw141292 	} else {
17764520Snw141292 		errno = EINVAL;
17774520Snw141292 		return (IDMAP_ERR_ARG);
17784520Snw141292 	}
17794520Snw141292 
17805696Snw141292 	if (*is_user == 1)
17814520Snw141292 		request.id2.idtype = IDMAP_UID;
17824520Snw141292 	else if (*is_user == 0)
17834520Snw141292 		request.id2.idtype = IDMAP_GID;
17844520Snw141292 	else
17854520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
17864520Snw141292 
17875696Snw141292 	if (*is_wuser == 1)
17885696Snw141292 		request.id1.idtype = IDMAP_USID;
17895696Snw141292 	else if (*is_wuser == 0)
17905696Snw141292 		request.id1.idtype = IDMAP_GSID;
17915696Snw141292 	else
17925696Snw141292 		request.id1.idtype = IDMAP_SID;
17935696Snw141292 
17944520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
17955696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
17965696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
17975696Snw141292 	    TIMEOUT);
17984520Snw141292 
17994644Sbaban 	if (clntstat != RPC_SUCCESS)
18004644Sbaban 		return (_idmap_rpc2stat(clnt));
18014520Snw141292 
18024520Snw141292 	retcode = result.retcode;
18034520Snw141292 
18044520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
18054520Snw141292 		if (retcode == IDMAP_SUCCESS)
18064520Snw141292 			retcode = IDMAP_ERR_NORESULT;
18074520Snw141292 		goto out;
18084520Snw141292 	}
18094520Snw141292 
18104864Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
18115696Snw141292 		*is_user = 1;
18124864Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
18135696Snw141292 		*is_user = 0;
18144864Sbaban 	} else {
18154864Sbaban 		goto out;
18164864Sbaban 	}
18175696Snw141292 
18185696Snw141292 	if (mapping->id1.idtype == IDMAP_USID) {
18195696Snw141292 		*is_wuser = 1;
18205696Snw141292 	} else if (mapping->id1.idtype == IDMAP_GSID) {
18215696Snw141292 		*is_wuser = 0;
18225696Snw141292 	} else {
18235696Snw141292 		goto out;
18245696Snw141292 	}
18255696Snw141292 
18264520Snw141292 	if (direction)
18274520Snw141292 		*direction = mapping->direction;
18284520Snw141292 	if (pid)
18294520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
18305064Sdm199847 
18315064Sdm199847 	rc = idmap_strdupnull(unixname, mapping->id2name);
18325064Sdm199847 	if (rc != IDMAP_SUCCESS)
18335064Sdm199847 		retcode = rc;
18344520Snw141292 
18356386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
18366386Sjp151216 	if (rc != IDMAP_SUCCESS)
18376386Sjp151216 		retcode = rc;
18386386Sjp151216 
18394520Snw141292 out:
18406966Sjp151216 	if (request.id1name != NULL)
18416966Sjp151216 		free(request.id1name);
18426966Sjp151216 	if (request.id1domain != NULL)
18436966Sjp151216 		free(request.id1domain);
18444520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
18454520Snw141292 	if (retcode != IDMAP_SUCCESS)
18464520Snw141292 		errno = idmap_stat2errno(retcode);
18474520Snw141292 	return (retcode);
18484520Snw141292 }
18494520Snw141292 
18504520Snw141292 
18514520Snw141292 /*
18524520Snw141292  * Get unix to windows mapping
18534520Snw141292  */
18544520Snw141292 idmap_stat
18554520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
18564520Snw141292 		uid_t *pid, const char *unixname,
18575696Snw141292 		int flag, int is_user, int *is_wuser,
18584520Snw141292 		char **sidprefix, idmap_rid_t *rid,
18594520Snw141292 		char **winname, char **windomain,
18606386Sjp151216 		int *direction, idmap_info *info)
18615696Snw141292 {
18624520Snw141292 	CLIENT			*clnt;
18634520Snw141292 	enum clnt_stat		clntstat;
18644520Snw141292 	idmap_mapping		request, *mapping;
18654520Snw141292 	idmap_mappings_res	result;
18664520Snw141292 	idmap_retcode		retcode, rc;
18674520Snw141292 
18684520Snw141292 	if (handle == NULL) {
18694520Snw141292 		errno = EINVAL;
18704520Snw141292 		return (IDMAP_ERR_ARG);
18714520Snw141292 	}
18724520Snw141292 
18734520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
18744520Snw141292 
18754520Snw141292 	if (sidprefix)
18764520Snw141292 		*sidprefix = NULL;
18774520Snw141292 	if (winname)
18784520Snw141292 		*winname = NULL;
18794520Snw141292 	if (windomain)
18804520Snw141292 		*windomain = NULL;
18814520Snw141292 	if (rid)
18824520Snw141292 		*rid = UINT32_MAX;
18834520Snw141292 	if (direction)
18844644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
18854520Snw141292 
18864520Snw141292 	(void) memset(&request, 0, sizeof (request));
18874520Snw141292 	(void) memset(&result, 0, sizeof (result));
18884520Snw141292 
18894520Snw141292 	request.flag = flag;
18904520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
18914520Snw141292 
18924520Snw141292 	if (pid && *pid != UINT32_MAX) {
18934520Snw141292 		request.id1.idmap_id_u.uid = *pid;
18944520Snw141292 	} else if (unixname) {
18955064Sdm199847 		request.id1name = (char *)unixname;
18964520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
18974520Snw141292 	} else {
18984520Snw141292 		errno = EINVAL;
18994520Snw141292 		return (IDMAP_ERR_ARG);
19004520Snw141292 	}
19014520Snw141292 
19025696Snw141292 	if (is_wuser == NULL)
19035696Snw141292 		request.id2.idtype = IDMAP_SID;
19045696Snw141292 	else if (*is_wuser == -1)
19055696Snw141292 		request.id2.idtype = IDMAP_SID;
19065696Snw141292 	else if (*is_wuser == 0)
19075696Snw141292 		request.id2.idtype = IDMAP_GSID;
19085696Snw141292 	else if (*is_wuser == 1)
19095696Snw141292 		request.id2.idtype = IDMAP_USID;
19104520Snw141292 
19114520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
19125696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
19135696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
19145696Snw141292 	    TIMEOUT);
19154520Snw141292 
19164644Sbaban 	if (clntstat != RPC_SUCCESS)
19174644Sbaban 		return (_idmap_rpc2stat(clnt));
19184520Snw141292 
19194520Snw141292 	retcode = result.retcode;
19204520Snw141292 
19214520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
19224520Snw141292 		if (retcode == IDMAP_SUCCESS)
19234520Snw141292 			retcode = IDMAP_ERR_NORESULT;
19244520Snw141292 		goto out;
19254520Snw141292 	}
19264520Snw141292 
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 
19586386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
19596386Sjp151216 	if (rc != IDMAP_SUCCESS)
19606386Sjp151216 		retcode = rc;
19616386Sjp151216 
19624520Snw141292 	goto out;
19634520Snw141292 
19644520Snw141292 errout:
19654520Snw141292 	if (sidprefix && *sidprefix) {
19664520Snw141292 		free(*sidprefix);
19674520Snw141292 		*sidprefix = NULL;
19684520Snw141292 	}
19694520Snw141292 	if (winname && *winname) {
19704520Snw141292 		free(*winname);
19714520Snw141292 		*winname = NULL;
19724520Snw141292 	}
19734520Snw141292 	if (windomain && *windomain) {
19744520Snw141292 		free(*windomain);
19754520Snw141292 		*windomain = NULL;
19764520Snw141292 	}
19774520Snw141292 
19784520Snw141292 out:
19794520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
19804520Snw141292 	if (retcode != IDMAP_SUCCESS)
19814520Snw141292 		errno = idmap_stat2errno(retcode);
19824520Snw141292 	return (retcode);
19834520Snw141292 }
19844520Snw141292 
19854520Snw141292 
19864520Snw141292 
19874520Snw141292 #define	gettext(s)	s
19884520Snw141292 static stat_table_t stattable[] = {
19894520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
19904520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
19914520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
19924520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
19934520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
19944520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
19954520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
19964520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
19974644Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
19984520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
19994520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
20004520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
20014520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
20024520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
20034520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
20044520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
20054520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
20064520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
20074644Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
20084520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
20094520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
20104644Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
20114695Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
20124520Snw141292 	{IDMAP_ERR_NOMAPPING,
20134520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
20144520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
20154520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
20164520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
20174520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
20184520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
20194520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
20204520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
20214520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
20224520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
20234520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
20244520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
20254520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
20264864Sbaban 		gettext("Windows lookup failed"), EINVAL},
20274864Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
20284864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20294864Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
20304864Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
20314864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20324864Sbaban 		"Unix to Windows name-based rule"), EINVAL},
20335968Snw141292 	{IDMAP_ERR_BAD_UTF8,
20345968Snw141292 		gettext("Invalid or illegal UTF-8 sequence found in "
20355968Snw141292 		"a given Windows entity name or domain name"), EINVAL},
20368361SJulian.Pullen@Sun.COM 	{IDMAP_ERR_NONE_GENERATED,
20376386Sjp151216 		gettext("Mapping not found and none created (see -c option)"),
20386386Sjp151216 		EINVAL},
20396616Sdm199847 	{IDMAP_ERR_PROP_UNKNOWN,
20406616Sdm199847 		gettext("Undefined property"),
20416616Sdm199847 		EINVAL},
20426616Sdm199847 	{IDMAP_ERR_NS_LDAP_CFG,
20436616Sdm199847 		gettext("Native LDAP configuration error"), EINVAL},
20446616Sdm199847 	{IDMAP_ERR_NS_LDAP_PARTIAL,
20456616Sdm199847 		gettext("Partial result from Native LDAP"), EINVAL},
20466616Sdm199847 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
20476616Sdm199847 		gettext("Native LDAP operation failed"), EINVAL},
20486616Sdm199847 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
20496616Sdm199847 		gettext("Improper winname form found in Native LDAP"), EINVAL},
20508361SJulian.Pullen@Sun.COM 	{IDMAP_ERR_NO_ACTIVEDIRECTORY,
20518361SJulian.Pullen@Sun.COM 		gettext("No AD servers"),
20528361SJulian.Pullen@Sun.COM 		EINVAL},
20534520Snw141292 	{-1, NULL, 0}
20544520Snw141292 };
20554520Snw141292 #undef	gettext
20564520Snw141292 
20574520Snw141292 
20584520Snw141292 /*
20594520Snw141292  * Get description of status code
20604520Snw141292  *
20614520Snw141292  * Input:
20624520Snw141292  * status - Status code returned by libidmap API call
20634520Snw141292  *
20644520Snw141292  * Return Value:
20654520Snw141292  * human-readable localized description of idmap_stat
20664520Snw141292  */
20674520Snw141292 /* ARGSUSED */
20684520Snw141292 const char *
20695696Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
20705696Snw141292 {
20714520Snw141292 	int i;
20724520Snw141292 
20734520Snw141292 	for (i = 0; stattable[i].msg; i++) {
20744520Snw141292 		if (stattable[i].retcode == status)
207510122SJordan.Brown@Sun.COM 			return (dgettext(TEXT_DOMAIN, stattable[i].msg));
20764520Snw141292 	}
207710122SJordan.Brown@Sun.COM 	return (dgettext(TEXT_DOMAIN, "Unknown error"));
20784520Snw141292 }
20794520Snw141292 
20804520Snw141292 
20814520Snw141292 static int
20825696Snw141292 idmap_stat2errno(idmap_stat stat)
20835696Snw141292 {
20844520Snw141292 	int i;
20854520Snw141292 	for (i = 0; stattable[i].msg; i++) {
20864520Snw141292 		if (stattable[i].retcode == stat)
20874520Snw141292 			return (stattable[i].errnum);
20884520Snw141292 	}
20894520Snw141292 	return (EINVAL);
20904520Snw141292 }
20914520Snw141292 
20924520Snw141292 
20934520Snw141292 /*
20944520Snw141292  * Get status code from string
20954520Snw141292  */
20964520Snw141292 idmap_stat
20975696Snw141292 idmap_string2stat(const char *str)
20985696Snw141292 {
20994520Snw141292 	if (str == NULL)
21004520Snw141292 		return (IDMAP_ERR_INTERNAL);
21014520Snw141292 
21024520Snw141292 #define	return_cmp(a) \
21034520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
21044520Snw141292 		return (IDMAP_ERR_ ## a);
21054520Snw141292 
21064520Snw141292 	return_cmp(OTHER);
21074520Snw141292 	return_cmp(INTERNAL);
21084520Snw141292 	return_cmp(MEMORY);
21094520Snw141292 	return_cmp(NORESULT);
21104520Snw141292 	return_cmp(NOTUSER);
21114520Snw141292 	return_cmp(NOTGROUP);
21124520Snw141292 	return_cmp(NOTSUPPORTED);
21134520Snw141292 	return_cmp(W2U_NAMERULE);
21144520Snw141292 	return_cmp(U2W_NAMERULE);
21154520Snw141292 	return_cmp(CACHE);
21164520Snw141292 	return_cmp(DB);
21174520Snw141292 	return_cmp(ARG);
21184520Snw141292 	return_cmp(SID);
21194520Snw141292 	return_cmp(IDTYPE);
21204520Snw141292 	return_cmp(RPC_HANDLE);
21214520Snw141292 	return_cmp(RPC);
21224520Snw141292 	return_cmp(CLIENT_HANDLE);
21234520Snw141292 	return_cmp(BUSY);
21244520Snw141292 	return_cmp(PERMISSION_DENIED);
21254520Snw141292 	return_cmp(NOMAPPING);
21264520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
21274520Snw141292 	return_cmp(DOMAIN);
21284520Snw141292 	return_cmp(SECURITY);
21294520Snw141292 	return_cmp(NOTFOUND);
21304520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
21314520Snw141292 	return_cmp(MEMORY);
21324520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
21334520Snw141292 	return_cmp(CFG);
21344520Snw141292 	return_cmp(CFG_CHANGE);
21354520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
21364520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
21374864Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
21384864Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
21396616Sdm199847 	return_cmp(BAD_UTF8);
21408361SJulian.Pullen@Sun.COM 	return_cmp(NONE_GENERATED);
21416616Sdm199847 	return_cmp(PROP_UNKNOWN);
21426616Sdm199847 	return_cmp(NS_LDAP_CFG);
21436616Sdm199847 	return_cmp(NS_LDAP_PARTIAL);
21446616Sdm199847 	return_cmp(NS_LDAP_OP_FAILED);
21456616Sdm199847 	return_cmp(NS_LDAP_BAD_WINNAME);
21468361SJulian.Pullen@Sun.COM 	return_cmp(NO_ACTIVEDIRECTORY);
21474520Snw141292 #undef return_cmp
21484520Snw141292 
21494520Snw141292 	return (IDMAP_ERR_OTHER);
21504520Snw141292 }
21514520Snw141292 
21524520Snw141292 
21534520Snw141292 /*
21544520Snw141292  * Map the given status to one that can be returned by the protocol
21554520Snw141292  */
21564520Snw141292 idmap_stat
21575696Snw141292 idmap_stat4prot(idmap_stat status)
21585696Snw141292 {
21594520Snw141292 	switch (status) {
21604520Snw141292 	case IDMAP_ERR_MEMORY:
21614520Snw141292 	case IDMAP_ERR_CACHE:
21624520Snw141292 		return (IDMAP_ERR_INTERNAL);
21634520Snw141292 	}
21644520Snw141292 	return (status);
21654520Snw141292 }
21665043Sbaban 
21675043Sbaban 
21685043Sbaban /*
21695247Sbaban  * This is a convenience routine which duplicates a string after
21705247Sbaban  * checking for NULL pointers. This function will return success if
21715247Sbaban  * either the 'to' OR 'from' pointers are NULL.
21725064Sdm199847  */
21735064Sdm199847 static idmap_stat
21745696Snw141292 idmap_strdupnull(char **to, const char *from)
21755696Snw141292 {
21765247Sbaban 	if (to == NULL)
21775247Sbaban 		return (IDMAP_SUCCESS);
21785247Sbaban 
21795064Sdm199847 	if (from == NULL || *from == '\0') {
21805064Sdm199847 		*to = NULL;
21815064Sdm199847 		return (IDMAP_SUCCESS);
21825064Sdm199847 	}
21835064Sdm199847 
21845064Sdm199847 	*to = strdup(from);
21855064Sdm199847 	if (*to == NULL)
21865064Sdm199847 		return (IDMAP_ERR_MEMORY);
21875064Sdm199847 	return (IDMAP_SUCCESS);
21885064Sdm199847 }
21895064Sdm199847 
21906386Sjp151216 
21915064Sdm199847 idmap_stat
21925696Snw141292 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
21935696Snw141292 {
21945064Sdm199847 	idmap_stat retval;
21955064Sdm199847 
21966386Sjp151216 	if (to == NULL)
21976386Sjp151216 		return (IDMAP_SUCCESS);
21986386Sjp151216 
21995064Sdm199847 	(void) memcpy(to, from, sizeof (idmap_namerule));
22006386Sjp151216 	to->windomain = NULL;
22016386Sjp151216 	to->winname = NULL;
22026386Sjp151216 	to->unixname = NULL;
22035064Sdm199847 
22045064Sdm199847 	retval = idmap_strdupnull(&to->windomain, from->windomain);
22055064Sdm199847 	if (retval != IDMAP_SUCCESS)
22065064Sdm199847 		return (retval);
22075064Sdm199847 
22085064Sdm199847 	retval = idmap_strdupnull(&to->winname, from->winname);
22096386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22106386Sjp151216 		free(to->windomain);
22116386Sjp151216 		to->windomain = NULL;
22126386Sjp151216 		return (retval);
22136386Sjp151216 	}
22146386Sjp151216 
22156386Sjp151216 	retval = idmap_strdupnull(&to->unixname, from->unixname);
22166386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22176386Sjp151216 		free(to->windomain);
22186386Sjp151216 		to->windomain = NULL;
22196386Sjp151216 		free(to->winname);
22206386Sjp151216 		to->winname = NULL;
22216386Sjp151216 		return (retval);
22226386Sjp151216 	}
22236386Sjp151216 
22246386Sjp151216 	return (retval);
22256386Sjp151216 }
22266386Sjp151216 
22276386Sjp151216 
22286386Sjp151216 static
22296386Sjp151216 idmap_stat
22306386Sjp151216 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
22316386Sjp151216 {
22326386Sjp151216 	idmap_stat retval;
22336386Sjp151216 
22346386Sjp151216 	if (to == NULL)
22356386Sjp151216 		return (IDMAP_SUCCESS);
22366386Sjp151216 
22376386Sjp151216 	retval = idmap_strdupnull(&to->dn, from->dn);
22385064Sdm199847 	if (retval != IDMAP_SUCCESS)
22395064Sdm199847 		return (retval);
22405064Sdm199847 
22416386Sjp151216 	retval = idmap_strdupnull(&to->attr, from->attr);
22426386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22436386Sjp151216 		free(to->dn);
22446386Sjp151216 		to->dn = NULL;
22456386Sjp151216 		return (retval);
22466386Sjp151216 	}
22476386Sjp151216 
22486386Sjp151216 	retval = idmap_strdupnull(&to->value, from->value);
22496386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22506386Sjp151216 		free(to->dn);
22516386Sjp151216 		to->dn = NULL;
22526386Sjp151216 		free(to->attr);
22536386Sjp151216 		to->attr = NULL;
22546386Sjp151216 		return (retval);
22556386Sjp151216 	}
22565064Sdm199847 
22575064Sdm199847 	return (retval);
22585064Sdm199847 }
22595064Sdm199847 
22606386Sjp151216 idmap_stat
22616386Sjp151216 idmap_info_cpy(idmap_info *to, idmap_info *from)
22626386Sjp151216 {
22636386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
22646386Sjp151216 
22656386Sjp151216 	if (to == NULL)
22666386Sjp151216 		return (IDMAP_SUCCESS);
22676386Sjp151216 
22686386Sjp151216 	(void) memset(to, 0, sizeof (idmap_info));
22696386Sjp151216 
22706386Sjp151216 	to->src = from->src;
22716386Sjp151216 	to->how.map_type = from->how.map_type;
22726386Sjp151216 	switch (to->how.map_type) {
22736386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
22746386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
22756386Sjp151216 		    &from->how.idmap_how_u.ad);
22766386Sjp151216 		break;
22776386Sjp151216 
22786386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
22796386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
22806386Sjp151216 		    &from->how.idmap_how_u.nldap);
22816386Sjp151216 		break;
22826386Sjp151216 
22836386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
22846386Sjp151216 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
22856386Sjp151216 		    &from->how.idmap_how_u.rule);
22866386Sjp151216 		break;
22876386Sjp151216 
22886386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
22896386Sjp151216 		break;
22906386Sjp151216 
22916386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
22926386Sjp151216 		break;
22936386Sjp151216 
22946386Sjp151216 	case IDMAP_MAP_TYPE_KNOWN_SID:
22956386Sjp151216 		break;
229610504SKeyur.Desai@Sun.COM 
229710504SKeyur.Desai@Sun.COM 	case IDMAP_MAP_TYPE_IDMU:
229810504SKeyur.Desai@Sun.COM 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.idmu,
229910504SKeyur.Desai@Sun.COM 		    &from->how.idmap_how_u.idmu);
230010504SKeyur.Desai@Sun.COM 		break;
23016386Sjp151216 	}
23026386Sjp151216 	return (retval);
23036386Sjp151216 }
23046386Sjp151216 
23056386Sjp151216 
23066386Sjp151216 /*
23076386Sjp151216  * This routine is similar to idmap_info_cpy, but the strings
23086386Sjp151216  * are moved from the "from" info to the "to" info.
230910966SJordan.Brown@Sun.COM  * This routine is equivalent to:
23106386Sjp151216  *
23116386Sjp151216  *	idmap_info_cpy(to,from);
23126386Sjp151216  *	idmap_info_free(from);
23136386Sjp151216  */
23146386Sjp151216 idmap_stat
23156386Sjp151216 idmap_info_mov(idmap_info *to, idmap_info *from)
23166386Sjp151216 {
23176386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
23186386Sjp151216 
23196386Sjp151216 	if (to == NULL) {
23206386Sjp151216 		idmap_info_free(from);
23216386Sjp151216 		return (IDMAP_SUCCESS);
23226386Sjp151216 	}
23236386Sjp151216 	(void) memcpy(to, from, sizeof (idmap_info));
23246386Sjp151216 
23256386Sjp151216 	(void) memset(from, 0, sizeof (idmap_info));
23266386Sjp151216 
23276386Sjp151216 	return (retval);
23286386Sjp151216 }
23296386Sjp151216 
23306386Sjp151216 
23316386Sjp151216 void
23326386Sjp151216 idmap_info_free(idmap_info *info)
23336386Sjp151216 {
23346386Sjp151216 	idmap_how *how;
23356386Sjp151216 
23366386Sjp151216 	if (info == NULL)
23376386Sjp151216 		return;
23386386Sjp151216 
23396386Sjp151216 	how = &info->how;
23406386Sjp151216 	switch (how->map_type) {
23416386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
23426386Sjp151216 		free(how->idmap_how_u.ad.dn);
23436386Sjp151216 		how->idmap_how_u.ad.dn = NULL;
23446386Sjp151216 		free(how->idmap_how_u.ad.attr);
23456386Sjp151216 		how->idmap_how_u.ad.attr = NULL;
23466386Sjp151216 		free(how->idmap_how_u.ad.value);
23476386Sjp151216 		how->idmap_how_u.ad.value = NULL;
23486386Sjp151216 		break;
23496386Sjp151216 
23506386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
23516386Sjp151216 		free(how->idmap_how_u.nldap.dn);
23526386Sjp151216 		how->idmap_how_u.nldap.dn = NULL;
23536386Sjp151216 		free(how->idmap_how_u.nldap.attr);
23546386Sjp151216 		how->idmap_how_u.nldap.attr = NULL;
23556386Sjp151216 		free(how->idmap_how_u.nldap.value);
23566386Sjp151216 		how->idmap_how_u.nldap.value = NULL;
23576386Sjp151216 		break;
23586386Sjp151216 
23596386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
23606386Sjp151216 		free(how->idmap_how_u.rule.windomain);
23616386Sjp151216 		how->idmap_how_u.rule.windomain = NULL;
23626386Sjp151216 		free(how->idmap_how_u.rule.winname);
23636386Sjp151216 		how->idmap_how_u.rule.winname = NULL;
23646386Sjp151216 		free(how->idmap_how_u.rule.unixname);
23656386Sjp151216 		how->idmap_how_u.rule.unixname = NULL;
23666386Sjp151216 		break;
23676386Sjp151216 
23686386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
23696386Sjp151216 		break;
23706386Sjp151216 
23716386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
23726386Sjp151216 		break;
237310504SKeyur.Desai@Sun.COM 
237410504SKeyur.Desai@Sun.COM 	case IDMAP_MAP_TYPE_IDMU:
237510504SKeyur.Desai@Sun.COM 		free(how->idmap_how_u.idmu.dn);
237610504SKeyur.Desai@Sun.COM 		how->idmap_how_u.idmu.dn = NULL;
237710504SKeyur.Desai@Sun.COM 		free(how->idmap_how_u.idmu.attr);
237810504SKeyur.Desai@Sun.COM 		how->idmap_how_u.idmu.attr = NULL;
237910504SKeyur.Desai@Sun.COM 		free(how->idmap_how_u.idmu.value);
238010504SKeyur.Desai@Sun.COM 		how->idmap_how_u.idmu.value = NULL;
238110504SKeyur.Desai@Sun.COM 		break;
23826386Sjp151216 	}
23836386Sjp151216 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
23846386Sjp151216 	info->src = IDMAP_MAP_SRC_UNKNOWN;
23856386Sjp151216 }
23866386Sjp151216 
23876386Sjp151216 
23885064Sdm199847 /*
23895043Sbaban  * Get uid given Windows name
23905043Sbaban  */
23915043Sbaban idmap_stat
23927369SJulian.Pullen@Sun.COM idmap_getuidbywinname(const char *name, const char *domain, int flag,
23937369SJulian.Pullen@Sun.COM 	uid_t *uid)
23945696Snw141292 {
23955043Sbaban 	idmap_handle_t	*ih;
23965043Sbaban 	idmap_retcode	rc;
23975696Snw141292 	int		is_user = 1;
23985696Snw141292 	int		is_wuser = -1;
23997369SJulian.Pullen@Sun.COM 	int 		direction;
24005043Sbaban 
24015043Sbaban 	if (uid == NULL)
24025043Sbaban 		return (IDMAP_ERR_ARG);
24035043Sbaban 
24047369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
24057369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_uidbywinname(name, domain, uid);
24067369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
24077369SJulian.Pullen@Sun.COM 			return (rc);
24087369SJulian.Pullen@Sun.COM 	}
24095043Sbaban 	/* Get mapping */
24105043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
24115043Sbaban 		return (rc);
24127369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
24137369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
24145043Sbaban 	(void) idmap_fini(ih);
24155043Sbaban 
24167369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
24177369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store UID to winname */
24187369SJulian.Pullen@Sun.COM 		if (domain == NULL)
24197369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
24207369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2uid(name, domain, *uid, direction);
24217369SJulian.Pullen@Sun.COM 	}
24227369SJulian.Pullen@Sun.COM 
24235043Sbaban 	return (rc);
24245043Sbaban }
24255043Sbaban 
24265043Sbaban 
24275043Sbaban /*
24285043Sbaban  * Get gid given Windows name
24295043Sbaban  */
24305043Sbaban idmap_stat
24317369SJulian.Pullen@Sun.COM idmap_getgidbywinname(const char *name, const char *domain, int flag,
24327369SJulian.Pullen@Sun.COM 	gid_t *gid)
24335696Snw141292 {
24345043Sbaban 	idmap_handle_t	*ih;
24355043Sbaban 	idmap_retcode	rc;
24365696Snw141292 	int		is_user = 0;
24375696Snw141292 	int		is_wuser = -1;
24387369SJulian.Pullen@Sun.COM 	int		direction;
24395043Sbaban 
24405043Sbaban 	if (gid == NULL)
24415043Sbaban 		return (IDMAP_ERR_ARG);
24425043Sbaban 
24437369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
24447369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_gidbywinname(name, domain, gid);
24457369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
24467369SJulian.Pullen@Sun.COM 			return (rc);
24477369SJulian.Pullen@Sun.COM 	}
24487369SJulian.Pullen@Sun.COM 
24495043Sbaban 	/* Get mapping */
24505043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
24515043Sbaban 		return (rc);
24527369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
24537369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
24545043Sbaban 	(void) idmap_fini(ih);
24555043Sbaban 
24567369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
24577369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store GID to winname */
24587369SJulian.Pullen@Sun.COM 		if (domain == NULL)
24597369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
24607369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2gid(name, domain, *gid, direction);
24617369SJulian.Pullen@Sun.COM 	}
24627369SJulian.Pullen@Sun.COM 
24635043Sbaban 	return (rc);
24645043Sbaban }
24655043Sbaban 
24665043Sbaban 
24675043Sbaban /*
24685043Sbaban  * Get winname given pid
24695043Sbaban  */
24705043Sbaban static idmap_retcode
24717369SJulian.Pullen@Sun.COM idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
24727369SJulian.Pullen@Sun.COM 	char **domain)
24735696Snw141292 {
24745043Sbaban 	idmap_handle_t	*ih;
24755043Sbaban 	idmap_retcode	rc;
24765043Sbaban 	int		len;
24775043Sbaban 	char		*winname, *windomain;
24787369SJulian.Pullen@Sun.COM 	int		direction;
24795043Sbaban 
24805043Sbaban 	if (name == NULL)
24815043Sbaban 		return (IDMAP_ERR_ARG);
24825043Sbaban 
24837369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
24847369SJulian.Pullen@Sun.COM 		if (is_user)
24857369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebyuid(&winname,
24867369SJulian.Pullen@Sun.COM 			    &windomain, pid);
24877369SJulian.Pullen@Sun.COM 		else
24887369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebygid(&winname,
24897369SJulian.Pullen@Sun.COM 			    &windomain, pid);
24907369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS)
24917369SJulian.Pullen@Sun.COM 			goto out;
24927369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_ERR_MEMORY)
24937369SJulian.Pullen@Sun.COM 			return (rc);
24947369SJulian.Pullen@Sun.COM 	}
24957369SJulian.Pullen@Sun.COM 
24965043Sbaban 	/* Get mapping */
24975043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
24985043Sbaban 		return (rc);
24997369SJulian.Pullen@Sun.COM 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
25007369SJulian.Pullen@Sun.COM 	    NULL, NULL, &winname, &windomain, &direction, NULL);
25015043Sbaban 	(void) idmap_fini(ih);
25025043Sbaban 
25035043Sbaban 	/* Return on error */
25045043Sbaban 	if (rc != IDMAP_SUCCESS)
25055043Sbaban 		return (rc);
25065043Sbaban 
25075043Sbaban 	/*
25085043Sbaban 	 * The given PID may have been mapped to a locally
25095043Sbaban 	 * generated SID in which case there isn't any
25105043Sbaban 	 * Windows name
25115043Sbaban 	 */
25125043Sbaban 	if (winname == NULL || windomain == NULL) {
25135043Sbaban 		idmap_free(winname);
25145043Sbaban 		idmap_free(windomain);
25155043Sbaban 		return (IDMAP_ERR_NORESULT);
25165043Sbaban 	}
25175043Sbaban 
25187369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
25197369SJulian.Pullen@Sun.COM 		if (is_user)
25207369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2uid(winname, windomain,
25217369SJulian.Pullen@Sun.COM 			    pid, direction);
25227369SJulian.Pullen@Sun.COM 		else
25237369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2gid(winname, windomain,
25247369SJulian.Pullen@Sun.COM 			    pid, direction);
25257369SJulian.Pullen@Sun.COM 	}
25267369SJulian.Pullen@Sun.COM 
25277369SJulian.Pullen@Sun.COM out:
25285043Sbaban 	if (domain != NULL) {
25295043Sbaban 		*name = winname;
25305043Sbaban 		*domain = windomain;
25315043Sbaban 	} else {
25325043Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
25335043Sbaban 		if ((*name = malloc(len)) != NULL)
25345043Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
25355043Sbaban 			    windomain);
25365043Sbaban 		else
25375043Sbaban 			rc = IDMAP_ERR_MEMORY;
25385043Sbaban 		idmap_free(winname);
25395043Sbaban 		idmap_free(windomain);
25405043Sbaban 	}
25417369SJulian.Pullen@Sun.COM 
25425043Sbaban 	return (rc);
25435043Sbaban }
25445043Sbaban 
25455043Sbaban 
25465043Sbaban /*
25475043Sbaban  * Get winname given uid
25485043Sbaban  */
25495043Sbaban idmap_stat
25507369SJulian.Pullen@Sun.COM idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain)
25515696Snw141292 {
25527369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(uid, 1, flag, name, domain));
25535043Sbaban }
25545043Sbaban 
25555043Sbaban 
25565043Sbaban /*
25575043Sbaban  * Get winname given gid
25585043Sbaban  */
25595043Sbaban idmap_stat
25607369SJulian.Pullen@Sun.COM idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain)
25615696Snw141292 {
25627369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(gid, 0, flag, name, domain));
25635043Sbaban }
256411963SAfshin.Ardakani@Sun.COM 
256511963SAfshin.Ardakani@Sun.COM idmap_stat
256611963SAfshin.Ardakani@Sun.COM idmap_flush(idmap_handle_t *handle, idmap_flush_op op)
256711963SAfshin.Ardakani@Sun.COM {
256811963SAfshin.Ardakani@Sun.COM 	CLIENT			*clnt;
256911963SAfshin.Ardakani@Sun.COM 	enum clnt_stat		clntstat;
257011963SAfshin.Ardakani@Sun.COM 	idmap_retcode		res;
257111963SAfshin.Ardakani@Sun.COM 
257211963SAfshin.Ardakani@Sun.COM 	res = IDMAP_SUCCESS;
257311963SAfshin.Ardakani@Sun.COM 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
257411963SAfshin.Ardakani@Sun.COM 
257511963SAfshin.Ardakani@Sun.COM 	clntstat = clnt_call(clnt, IDMAP_FLUSH,
257611963SAfshin.Ardakani@Sun.COM 	    (xdrproc_t)xdr_idmap_flush_op, (caddr_t)&op,
257711963SAfshin.Ardakani@Sun.COM 	    (xdrproc_t)xdr_idmap_retcode, (caddr_t)&res, TIMEOUT);
257811963SAfshin.Ardakani@Sun.COM 
257911963SAfshin.Ardakani@Sun.COM 	if (clntstat != RPC_SUCCESS) {
258011963SAfshin.Ardakani@Sun.COM 		return (_idmap_rpc2stat(clnt));
258111963SAfshin.Ardakani@Sun.COM 	}
258211963SAfshin.Ardakani@Sun.COM 	return (res);
258311963SAfshin.Ardakani@Sun.COM }
2584*12065SKeyur.Desai@Sun.COM 
2585*12065SKeyur.Desai@Sun.COM 
2586*12065SKeyur.Desai@Sun.COM /*
2587*12065SKeyur.Desai@Sun.COM  * syslog is the default logger.
2588*12065SKeyur.Desai@Sun.COM  * It can be overwritten by supplying a logger
2589*12065SKeyur.Desai@Sun.COM  * with  idmap_set_logger()
2590*12065SKeyur.Desai@Sun.COM  */
2591*12065SKeyur.Desai@Sun.COM idmap_logger_t logger = syslog;
2592*12065SKeyur.Desai@Sun.COM 
2593*12065SKeyur.Desai@Sun.COM 
2594*12065SKeyur.Desai@Sun.COM void
2595*12065SKeyur.Desai@Sun.COM idmap_set_logger(idmap_logger_t funct)
2596*12065SKeyur.Desai@Sun.COM {
2597*12065SKeyur.Desai@Sun.COM 	logger = funct;
2598*12065SKeyur.Desai@Sun.COM }
2599