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 /*
225968Snw141292  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
234520Snw141292  * Use is subject to license terms.
244520Snw141292  */
254520Snw141292 
264520Snw141292 
274520Snw141292 /*
284520Snw141292  * libidmap API
294520Snw141292  */
304520Snw141292 
314520Snw141292 #include <stdlib.h>
326616Sdm199847 #include <sys/varargs.h>
334520Snw141292 #include <inttypes.h>
344520Snw141292 #include <errno.h>
354520Snw141292 #include <strings.h>
364520Snw141292 #include <ctype.h>
374520Snw141292 #include <sys/param.h>
384520Snw141292 #include <sys/types.h>
394520Snw141292 #include <sys/stat.h>
404520Snw141292 #include <dlfcn.h>
414520Snw141292 #include <libintl.h>
425232Snw141292 #include <ucontext.h>
434520Snw141292 #include "idmap_impl.h"
44*7369SJulian.Pullen@Sun.COM #include "idmap_cache.h"
454520Snw141292 
466616Sdm199847 /*LINTLIBRARY*/
476616Sdm199847 
486616Sdm199847 /*
496616Sdm199847  * The following structure determines where the log messages from idmapdlog()
506616Sdm199847  * go to. It can be stderr (idmap, idmapd -d) and/or syslog (idmapd).
516616Sdm199847  *
526616Sdm199847  * logstate.max_pri is integer cutoff necessary to silence low-priority
536616Sdm199847  * messages to stderr. Syslog has its own means so there a boolean
546616Sdm199847  * logstate.write_syslog is enough.
556616Sdm199847  *
566616Sdm199847  * logstate.degraded is a mode used by idmapd in its degraded state.
576616Sdm199847  */
586616Sdm199847 
596616Sdm199847 static struct {
606616Sdm199847 	bool_t write_syslog;
616616Sdm199847 	int max_pri; /* Max priority written to stderr */
626616Sdm199847 	bool_t degraded;
636616Sdm199847 } logstate = {FALSE, LOG_DEBUG, FALSE};
646616Sdm199847 
656616Sdm199847 
664520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
674520Snw141292 
684520Snw141292 static int idmap_stat2errno(idmap_stat);
696616Sdm199847 static idmap_stat	idmap_strdupnull(char **, const char *);
704520Snw141292 
714520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
724520Snw141292 	if (handl == NULL) {\
734520Snw141292 		errno = EINVAL;\
744520Snw141292 		return (IDMAP_ERR_ARG);\
754520Snw141292 	}\
764520Snw141292 	itera = calloc(1, sizeof (*itera));\
774520Snw141292 	if (itera == NULL) {\
784520Snw141292 		errno = ENOMEM;\
794520Snw141292 		return (IDMAP_ERR_MEMORY);\
804520Snw141292 	}\
814520Snw141292 	argu = calloc(1, sizeof (*argu));\
824520Snw141292 	if (argu == NULL) {\
834520Snw141292 		free(itera);\
844520Snw141292 		errno = ENOMEM;\
854520Snw141292 		return (IDMAP_ERR_MEMORY);\
864520Snw141292 	}\
874520Snw141292 	itera->ih = handl;\
884520Snw141292 	itera->type = ityp;\
894520Snw141292 	itera->retcode = IDMAP_NEXT;\
904520Snw141292 	itera->limit = 1024;\
914520Snw141292 	itera->arg = argu;
924520Snw141292 
934520Snw141292 
944520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
954520Snw141292 	if (argu) {\
964520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
974520Snw141292 		free(argu);\
984520Snw141292 	}\
994520Snw141292 	if (itera)\
1004520Snw141292 		free(itera);\
1014520Snw141292 	return (iretcod);
1024520Snw141292 
1034520Snw141292 
1044520Snw141292 #define	__ITER_CHECK(itera, ityp)\
1054520Snw141292 	if (itera == NULL) {\
1064520Snw141292 		errno = EINVAL;\
1074520Snw141292 		return (IDMAP_ERR_ARG);\
1084520Snw141292 	}\
1094520Snw141292 	if (itera->type != ityp) {\
1104520Snw141292 		errno = EINVAL;\
1114520Snw141292 		return (IDMAP_ERR_ARG);\
1124520Snw141292 	}
1134520Snw141292 
1144520Snw141292 /*
1154520Snw141292  * Free memory allocated by libidmap API
1164520Snw141292  *
1174520Snw141292  * Input:
1184520Snw141292  * ptr - memory to be freed
1194520Snw141292  */
1204520Snw141292 void
1215696Snw141292 idmap_free(void *ptr)
1225696Snw141292 {
1234520Snw141292 	free(ptr);
1244520Snw141292 }
1254520Snw141292 
1264520Snw141292 
1275232Snw141292 #define	MIN_STACK_NEEDS	16384
1285232Snw141292 
1294520Snw141292 /*
1304520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1314520Snw141292  *
1324520Snw141292  * Output:
1334520Snw141292  * handle - idmap handle
1344520Snw141292  */
1354520Snw141292 idmap_stat
1365696Snw141292 idmap_init(idmap_handle_t **handle)
1375696Snw141292 {
1384520Snw141292 	CLIENT			*clnt = NULL;
1394520Snw141292 	struct idmap_handle	*hptr;
1405232Snw141292 	uint_t			sendsz = 0;
1415232Snw141292 	stack_t			st;
1424520Snw141292 
1434520Snw141292 	*handle = NULL;
1444520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1454520Snw141292 	if (hptr == NULL)
1464520Snw141292 		return (IDMAP_ERR_MEMORY);
1474520Snw141292 
1485232Snw141292 	/*
1495232Snw141292 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
1505232Snw141292 	 * the call args buffer and once for the call result buffer), so
1515232Snw141292 	 * we want to pick a sendsz that will be large enough, but not
1525232Snw141292 	 * too large.
1535232Snw141292 	 */
1545232Snw141292 	if (stack_getbounds(&st) == 0) {
1555232Snw141292 		/*
1565232Snw141292 		 * Estimate how much stack space is left;
1575232Snw141292 		 * st.ss_sp is the top of stack.
1585232Snw141292 		 */
1595232Snw141292 		if ((char *)&sendsz < (char *)st.ss_sp)
1605232Snw141292 			/* stack grows up */
1615232Snw141292 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
1625232Snw141292 		else
1635232Snw141292 			/* stack grows down */
1645232Snw141292 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
1655232Snw141292 
1665232Snw141292 		/*
1675232Snw141292 		 * Take much of the stack space left, divided by two,
1685232Snw141292 		 * but leave enough for our needs (just a guess!), and
1695232Snw141292 		 * if we can't, then roll the dice.
1705232Snw141292 		 */
1715232Snw141292 		sendsz = RNDUP(sendsz / 2);
1725232Snw141292 		if (sendsz < MIN_STACK_NEEDS)
1735232Snw141292 			sendsz = 0;	/* RPC call may fail */
1745232Snw141292 		else if (sendsz > IDMAP_MAX_DOOR_RPC)
1755232Snw141292 			sendsz = IDMAP_MAX_DOOR_RPC;
1765232Snw141292 	}
1775232Snw141292 
1785232Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
1794520Snw141292 	if (clnt == NULL) {
1804520Snw141292 		free(hptr);
1814520Snw141292 		return (IDMAP_ERR_RPC);
1824520Snw141292 	}
1834520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1844520Snw141292 	hptr->privhandle = clnt;
1854520Snw141292 	*handle = hptr;
1864520Snw141292 	return (IDMAP_SUCCESS);
1874520Snw141292 }
1884520Snw141292 
1894520Snw141292 
1904520Snw141292 /*
1914520Snw141292  * Finalize idmap handle
1924520Snw141292  *
1934520Snw141292  * Input:
1944520Snw141292  * handle - idmap handle
1954520Snw141292  */
1964520Snw141292 idmap_stat
1975696Snw141292 idmap_fini(idmap_handle_t *handle)
1985696Snw141292 {
1994520Snw141292 	CLIENT			*clnt;
2004520Snw141292 	struct idmap_handle	*hptr;
2014520Snw141292 
2024520Snw141292 	if (handle == NULL)
2034520Snw141292 		return (IDMAP_SUCCESS);
2044520Snw141292 
2054520Snw141292 	hptr = (struct idmap_handle *)handle;
2064520Snw141292 
2074520Snw141292 	switch (hptr->type) {
2084520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
2094520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
2104520Snw141292 		if (clnt) {
2114520Snw141292 			if (clnt->cl_auth)
2124520Snw141292 				auth_destroy(clnt->cl_auth);
2134520Snw141292 			clnt_destroy(clnt);
2144520Snw141292 		}
2154520Snw141292 		break;
2164520Snw141292 	default:
2174520Snw141292 		break;
2184520Snw141292 	}
2194520Snw141292 	free(hptr);
2204520Snw141292 	return (IDMAP_SUCCESS);
2214520Snw141292 }
2224520Snw141292 
2234520Snw141292 
2246616Sdm199847 idmap_stat
2256616Sdm199847 idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
2266616Sdm199847 {
2276616Sdm199847 	CLIENT			*clnt;
2286616Sdm199847 	enum clnt_stat		clntstat;
2296616Sdm199847 
2306616Sdm199847 
2316616Sdm199847 	(void) memset(res, 0, sizeof (*res));
2326616Sdm199847 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
2336616Sdm199847 
2346616Sdm199847 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
2356616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
2366616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
2376616Sdm199847 
2386616Sdm199847 	if (clntstat != RPC_SUCCESS) {
2396616Sdm199847 		return (_idmap_rpc2stat(clnt));
2406616Sdm199847 	}
2416616Sdm199847 
2426616Sdm199847 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
2436616Sdm199847 
2446616Sdm199847 #if 0
2456616Sdm199847 	(void) memset(&res, 0, sizeof (res));
2466616Sdm199847 	pr = PROP_DOMAIN_CONTROLLER;
2476616Sdm199847 
2486616Sdm199847 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
2496616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
2506616Sdm199847 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)&res, TIMEOUT);
2516616Sdm199847 
2526616Sdm199847 	if (clntstat != RPC_SUCCESS) {
2536616Sdm199847 		fprintf(stderr, "clntstat != RPC_SUCCESS\n");
2546616Sdm199847 		rc = _idmap_rpc2stat(clnt);
2556616Sdm199847 		goto cleanup;
2566616Sdm199847 	}
2576616Sdm199847 #endif
2586616Sdm199847 
2596616Sdm199847 }
2606616Sdm199847 
2616616Sdm199847 idmap_stat
2626616Sdm199847 idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
2636616Sdm199847     idmap_ad_disc_ds_t *dc)
2646616Sdm199847 {
2656616Sdm199847 	idmap_prop_res res;
2666616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2676616Sdm199847 
2686616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2696616Sdm199847 	if (rc < 0)
2706616Sdm199847 		return (rc);
2716616Sdm199847 
2726616Sdm199847 	dc->port = res.value.idmap_prop_val_u.dsval.port;
2736616Sdm199847 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
2746616Sdm199847 	    AD_DISC_MAXHOSTNAME);
2756616Sdm199847 
2766616Sdm199847 	/* xdr doesn't guarantee 0-termination of char[]: */
2776616Sdm199847 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
2786616Sdm199847 
2796616Sdm199847 	return (rc);
2806616Sdm199847 }
2816616Sdm199847 
2826616Sdm199847 
2836616Sdm199847 /*
2846616Sdm199847  * Sometimes the property is not set. In that case, str is set to NULL but
2856616Sdm199847  * otherwise IDMAP_SUCCESS is returned.
2866616Sdm199847  */
2876616Sdm199847 idmap_stat
2886616Sdm199847 idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
2896616Sdm199847 {
2906616Sdm199847 	idmap_prop_res res;
2916616Sdm199847 	idmap_stat rc = IDMAP_SUCCESS;
2926616Sdm199847 
2936616Sdm199847 	rc = idmap_get_prop(handle, pr, &res);
2946616Sdm199847 	if (rc < 0)
2956616Sdm199847 		return (rc);
2966616Sdm199847 
2976616Sdm199847 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
2986616Sdm199847 	return (rc);
2996616Sdm199847 }
3004520Snw141292 
3014520Snw141292 /*
3024520Snw141292  * Create/Initialize handle for updates
3034520Snw141292  *
3044520Snw141292  * Output:
3054520Snw141292  * udthandle - update handle
3064520Snw141292  */
3074520Snw141292 idmap_stat
3085696Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
3095696Snw141292 {
3104520Snw141292 	idmap_udt_handle_t	*tmp;
3114520Snw141292 
3124520Snw141292 	if (handle == NULL || udthandle == NULL) {
3134520Snw141292 		errno = EINVAL;
3144520Snw141292 		return (IDMAP_ERR_ARG);
3154520Snw141292 	}
3164520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
3174520Snw141292 		errno = ENOMEM;
3184520Snw141292 		return (IDMAP_ERR_MEMORY);
3194520Snw141292 	}
3204520Snw141292 
3214520Snw141292 	tmp->ih = handle;
3224520Snw141292 	*udthandle = tmp;
3234520Snw141292 	return (IDMAP_SUCCESS);
3244520Snw141292 }
3254520Snw141292 
3264520Snw141292 
3274520Snw141292 /*
3284520Snw141292  * All the updates specified by the update handle are committed
3294520Snw141292  * in a single transaction. i.e either all succeed or none.
3304520Snw141292  *
3314520Snw141292  * Input:
3324520Snw141292  * udthandle - update handle with the update requests
3334520Snw141292  *
3344520Snw141292  * Return value:
3354520Snw141292  * Status of the commit
3364520Snw141292  */
3374520Snw141292 idmap_stat
3385696Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle)
3395696Snw141292 {
3404520Snw141292 	CLIENT			*clnt;
3414520Snw141292 	enum clnt_stat		clntstat;
3425064Sdm199847 	idmap_update_res	res;
3435064Sdm199847 	idmap_stat		retcode;
3444520Snw141292 
3454520Snw141292 	if (udthandle == NULL) {
3464520Snw141292 		errno = EINVAL;
3474520Snw141292 		return (IDMAP_ERR_ARG);
3484520Snw141292 	}
3495064Sdm199847 
3505064Sdm199847 	(void) memset(&res, 0, sizeof (res));
3515064Sdm199847 
3524520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
3534520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
3545696Snw141292 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
3555696Snw141292 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
3565696Snw141292 	    TIMEOUT);
3574644Sbaban 
3585064Sdm199847 	if (clntstat != RPC_SUCCESS) {
3595064Sdm199847 		retcode = _idmap_rpc2stat(clnt);
3605064Sdm199847 		goto out;
3615064Sdm199847 	}
3625064Sdm199847 
3635064Sdm199847 	retcode = udthandle->commit_stat = res.retcode;
3645064Sdm199847 	udthandle->error_index = res.error_index;
3655064Sdm199847 
3665064Sdm199847 	if (retcode != IDMAP_SUCCESS) {
3675064Sdm199847 
3685064Sdm199847 		if (udthandle->error_index < 0)
3695064Sdm199847 			goto out;
3705064Sdm199847 
3715064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
3725064Sdm199847 		    &res.error_rule);
3735064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3745064Sdm199847 			udthandle->error_index = -2;
3755064Sdm199847 			goto out;
3765064Sdm199847 		}
3775064Sdm199847 
3785064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
3795064Sdm199847 		    &res.conflict_rule);
3805064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
3815064Sdm199847 			udthandle->error_index = -2;
3825064Sdm199847 			goto out;
3835064Sdm199847 		}
3845064Sdm199847 	}
3855064Sdm199847 
3865064Sdm199847 	retcode = res.retcode;
3875064Sdm199847 
3885064Sdm199847 
3895064Sdm199847 out:
3904644Sbaban 	/* reset handle so that it can be used again */
3915064Sdm199847 	if (retcode == IDMAP_SUCCESS) {
3925064Sdm199847 		_IDMAP_RESET_UDT_HANDLE(udthandle);
3935064Sdm199847 	}
3945064Sdm199847 
3955064Sdm199847 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3965064Sdm199847 	errno = idmap_stat2errno(retcode);
3975064Sdm199847 	return (retcode);
3985064Sdm199847 }
3995064Sdm199847 
4005064Sdm199847 
4015064Sdm199847 static void
4025064Sdm199847 idmap_namerule_parts_clear(char **windomain, char **winname,
4035696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4045696Snw141292     boolean_t *is_nt4, int *direction)
4055696Snw141292 {
4065064Sdm199847 	if (windomain)
4075064Sdm199847 		*windomain = NULL;
4085064Sdm199847 	if (winname)
4095064Sdm199847 		*winname = NULL;
4105064Sdm199847 	if (unixname)
4115064Sdm199847 		*unixname = NULL;
4125064Sdm199847 
4135064Sdm199847 	if (is_nt4)
4145064Sdm199847 		*is_nt4 = 0;
4155064Sdm199847 	if (is_user)
4165064Sdm199847 		*is_user = -1;
4175696Snw141292 	if (is_wuser)
4185696Snw141292 		*is_wuser = -1;
4195064Sdm199847 	if (direction)
4205064Sdm199847 		*direction = IDMAP_DIRECTION_UNDEF;
4215064Sdm199847 }
4225064Sdm199847 
4235064Sdm199847 static idmap_stat
4245696Snw141292 idmap_namerule2parts(idmap_namerule *rule,
4255064Sdm199847     char **windomain, char **winname,
4265696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4275696Snw141292     boolean_t *is_nt4, int *direction)
4285696Snw141292 {
4295064Sdm199847 	idmap_stat retcode;
4305064Sdm199847 
4315064Sdm199847 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
4325064Sdm199847 		return (IDMAP_ERR_NORESULT);
4335064Sdm199847 
4345064Sdm199847 
4355064Sdm199847 	retcode = idmap_strdupnull(windomain, rule->windomain);
4365064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4375064Sdm199847 		goto errout;
4385064Sdm199847 
4395064Sdm199847 	retcode = idmap_strdupnull(winname, rule->winname);
4405064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4415064Sdm199847 		goto errout;
4425064Sdm199847 
4435064Sdm199847 	retcode = idmap_strdupnull(unixname, rule->unixname);
4445064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4455064Sdm199847 		goto errout;
4465064Sdm199847 
4475064Sdm199847 
4485064Sdm199847 	if (is_user)
4495064Sdm199847 		*is_user = rule->is_user;
4505696Snw141292 	if (is_wuser)
4515696Snw141292 		*is_wuser = rule->is_wuser;
4525064Sdm199847 	if (is_nt4)
4535064Sdm199847 		*is_nt4 = rule->is_nt4;
4545064Sdm199847 	if (direction)
4555064Sdm199847 		*direction = rule->direction;
4565064Sdm199847 
4575064Sdm199847 
4585064Sdm199847 	return (IDMAP_SUCCESS);
4594644Sbaban 
4605064Sdm199847 errout:
4615064Sdm199847 	if (windomain && *windomain)
4625064Sdm199847 		free(*windomain);
4635064Sdm199847 	if (winname && *winname)
4645064Sdm199847 		free(*winname);
4655064Sdm199847 	if (unixname && *unixname)
4665064Sdm199847 		free(*unixname);
4675064Sdm199847 
4685064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4695696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4705064Sdm199847 
4714520Snw141292 	return (retcode);
4725064Sdm199847 
4735064Sdm199847 }
4745064Sdm199847 
4755064Sdm199847 /*
4765064Sdm199847  * Retrieve the index of the failed batch element. error_index == -1
4775064Sdm199847  * indicates failure at the beginning, -2 at the end.
4785064Sdm199847  *
4795064Sdm199847  * If idmap_udt_commit didn't return error, the returned value is undefined.
4805064Sdm199847  *
4815064Sdm199847  * Return value:
4825064Sdm199847  * IDMAP_SUCCESS
4835064Sdm199847  */
4845064Sdm199847 
4855064Sdm199847 idmap_stat
4865064Sdm199847 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
4875696Snw141292     int64_t *error_index)
4885696Snw141292 {
4895064Sdm199847 	if (error_index)
4905064Sdm199847 		*error_index = udthandle->error_index;
4915064Sdm199847 
4925064Sdm199847 	return (IDMAP_SUCCESS);
4935064Sdm199847 }
4945064Sdm199847 
4955064Sdm199847 
4965064Sdm199847 /*
4975064Sdm199847  * Retrieve the rule which caused the batch to fail. If
4985064Sdm199847  * idmap_udt_commit didn't return error or if error_index is < 0, the
4995064Sdm199847  * retrieved rule is undefined.
5005064Sdm199847  *
5015064Sdm199847  * Return value:
5025064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
5035064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
5045064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
5055064Sdm199847  */
5065064Sdm199847 
5075064Sdm199847 idmap_stat
5085064Sdm199847 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
5095064Sdm199847     char **windomain, char **winname,
5105696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
5115696Snw141292     boolean_t *is_nt4, int *direction)
5125696Snw141292 {
5135064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
5145696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
5155064Sdm199847 
5165064Sdm199847 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
5175064Sdm199847 	    udthandle->error_index < 0)
5185064Sdm199847 		return (IDMAP_ERR_NORESULT);
5195064Sdm199847 
5205064Sdm199847 	return (idmap_namerule2parts(
5215696Snw141292 	    &udthandle->error_rule,
5225696Snw141292 	    windomain,
5235696Snw141292 	    winname,
5245696Snw141292 	    unixname,
5255696Snw141292 	    is_user,
5265696Snw141292 	    is_wuser,
5275696Snw141292 	    is_nt4,
5285696Snw141292 	    direction));
5295064Sdm199847 }
5305064Sdm199847 
5315064Sdm199847 /*
5325064Sdm199847  * Retrieve the rule with which there was a conflict. TODO: retrieve
5335064Sdm199847  * the value.
5345064Sdm199847  *
5355064Sdm199847  * Return value:
5365064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
5375064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
5385064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
5395064Sdm199847  */
5405064Sdm199847 
5415064Sdm199847 idmap_stat
5425064Sdm199847 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
5435064Sdm199847     char **windomain, char **winname,
5445696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
5455696Snw141292     boolean_t *is_nt4, int *direction)
5465696Snw141292 {
5475064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
5485696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
5495064Sdm199847 
5505064Sdm199847 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
5515064Sdm199847 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
5525696Snw141292 		return (IDMAP_ERR_NORESULT);
5535064Sdm199847 	}
5545064Sdm199847 
5555064Sdm199847 	return (idmap_namerule2parts(
5565696Snw141292 	    &udthandle->conflict_rule,
5575696Snw141292 	    windomain,
5585696Snw141292 	    winname,
5595696Snw141292 	    unixname,
5605696Snw141292 	    is_user,
5615696Snw141292 	    is_wuser,
5625696Snw141292 	    is_nt4,
5635696Snw141292 	    direction));
5644520Snw141292 }
5654520Snw141292 
5664520Snw141292 
5674520Snw141292 /*
5684520Snw141292  * Destroy the update handle
5694520Snw141292  */
5704520Snw141292 void
5715696Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle)
5725696Snw141292 {
5734520Snw141292 	if (udthandle == NULL)
5744520Snw141292 		return;
5754520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
5765064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
5775064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
5784520Snw141292 	free(udthandle);
5794520Snw141292 }
5804520Snw141292 
5814520Snw141292 
5824520Snw141292 idmap_stat
5834520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
5845696Snw141292     boolean_t is_user, boolean_t is_wuser, const char *winname,
5855696Snw141292     const char *unixname, boolean_t is_nt4, int direction)
5865696Snw141292 {
5874520Snw141292 	idmap_retcode	retcode;
5884644Sbaban 	idmap_namerule	*rule = NULL;
5894520Snw141292 
5904644Sbaban 	retcode = _udt_extend_batch(udthandle);
5914520Snw141292 	if (retcode != IDMAP_SUCCESS)
5924520Snw141292 		goto errout;
5934520Snw141292 
5944520Snw141292 	rule = &udthandle->batch.
5955696Snw141292 	    idmap_update_batch_val[udthandle->next].
5965696Snw141292 	    idmap_update_op_u.rule;
5974520Snw141292 	rule->is_user = is_user;
5985696Snw141292 	rule->is_wuser = is_wuser;
5994520Snw141292 	rule->direction = direction;
6004520Snw141292 	rule->is_nt4 = is_nt4;
6015064Sdm199847 
6025064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6035064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6045064Sdm199847 		goto errout;
6055064Sdm199847 
6065064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
6075064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6085064Sdm199847 		goto errout;
6095064Sdm199847 
6105064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6115064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6125064Sdm199847 		goto errout;
6134644Sbaban 
6144644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6154644Sbaban 	    OP_ADD_NAMERULE;
6164520Snw141292 	udthandle->next++;
6174520Snw141292 	return (IDMAP_SUCCESS);
6184520Snw141292 
6194520Snw141292 errout:
6204644Sbaban 	/* The batch should still be usable */
6214644Sbaban 	if (rule)
6224644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
6234520Snw141292 	errno = idmap_stat2errno(retcode);
6244520Snw141292 	return (retcode);
6254520Snw141292 }
6264520Snw141292 
6274520Snw141292 
6284520Snw141292 /* ARGSUSED */
6294520Snw141292 idmap_stat
6304520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
6315696Snw141292     boolean_t is_wuser,	const char *windomain, const char *winname,
6325696Snw141292     const char *unixname, int direction)
6335696Snw141292 {
6344520Snw141292 	idmap_retcode	retcode;
6354644Sbaban 	idmap_namerule	*rule = NULL;
6364520Snw141292 
6374644Sbaban 	retcode = _udt_extend_batch(udthandle);
6384520Snw141292 	if (retcode != IDMAP_SUCCESS)
6394520Snw141292 		goto errout;
6404520Snw141292 
6414520Snw141292 	rule = &udthandle->batch.
6425696Snw141292 	    idmap_update_batch_val[udthandle->next].
6435696Snw141292 	    idmap_update_op_u.rule;
6444520Snw141292 	rule->is_user = is_user;
6455696Snw141292 	rule->is_wuser = is_wuser;
6464520Snw141292 	rule->direction = direction;
6475064Sdm199847 
6485064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6495064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6505064Sdm199847 		goto errout;
6515064Sdm199847 
6525064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
6535064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6545064Sdm199847 		goto errout;
6555064Sdm199847 
6565064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6575064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6585064Sdm199847 		goto errout;
6595064Sdm199847 
6604644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6614644Sbaban 	    OP_RM_NAMERULE;
6624520Snw141292 	udthandle->next++;
6634520Snw141292 	return (IDMAP_SUCCESS);
6644520Snw141292 
6654520Snw141292 errout:
6664644Sbaban 	if (rule)
6674644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
6684520Snw141292 	errno = idmap_stat2errno(retcode);
6694520Snw141292 	return (retcode);
6704520Snw141292 }
6714520Snw141292 
6724520Snw141292 
6734520Snw141292 /* ARGSUSED */
6744520Snw141292 idmap_stat
6755696Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
6765696Snw141292 {
6774520Snw141292 	idmap_retcode	retcode;
6784520Snw141292 
6794644Sbaban 	retcode = _udt_extend_batch(udthandle);
6804520Snw141292 	if (retcode != IDMAP_SUCCESS)
6814520Snw141292 		goto errout;
6824520Snw141292 
6834644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
6844644Sbaban 	    OP_FLUSH_NAMERULES;
6854520Snw141292 	udthandle->next++;
6864520Snw141292 	return (IDMAP_SUCCESS);
6874520Snw141292 
6884520Snw141292 errout:
6894520Snw141292 	errno = idmap_stat2errno(retcode);
6904520Snw141292 	return (retcode);
6914520Snw141292 }
6924520Snw141292 
6934520Snw141292 
6944520Snw141292 /*
6954520Snw141292  * Set the number of entries requested per batch by the iterator
6964520Snw141292  *
6974520Snw141292  * Input:
6984520Snw141292  * iter  - iterator
6994520Snw141292  * limit - number of entries requested per batch
7004520Snw141292  */
7014520Snw141292 idmap_stat
7025696Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
7035696Snw141292 {
7044520Snw141292 	if (iter == NULL) {
7054520Snw141292 		errno = EINVAL;
7064520Snw141292 		return (IDMAP_ERR_ARG);
7074520Snw141292 	}
7084520Snw141292 	iter->limit = limit;
7094520Snw141292 	return (IDMAP_SUCCESS);
7104520Snw141292 }
7114520Snw141292 
7124520Snw141292 
7134520Snw141292 /*
7144520Snw141292  * Create iterator to get name-based mapping rules
7154520Snw141292  *
7164520Snw141292  * Input:
7174520Snw141292  * windomain - Windows domain
7184520Snw141292  * is_user   - user or group rules
7194520Snw141292  * winname   - Windows user or group name
7204520Snw141292  * unixname  - Unix user or group name
7214520Snw141292  *
7224520Snw141292  * Output:
7234520Snw141292  * iter - iterator
7244520Snw141292  */
7254520Snw141292 idmap_stat
7264520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
7275696Snw141292 		boolean_t is_user, boolean_t is_wuser, const char *winname,
7285696Snw141292 		const char *unixname, idmap_iter_t **iter)
7295696Snw141292 {
7304520Snw141292 
7314520Snw141292 	idmap_iter_t			*tmpiter;
7324520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
7334520Snw141292 	idmap_namerule			*rule;
7344520Snw141292 	idmap_retcode			retcode;
7354520Snw141292 
7364520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
7374520Snw141292 
7384520Snw141292 	rule = &arg->rule;
7394520Snw141292 	rule->is_user = is_user;
7405696Snw141292 	rule->is_wuser = is_wuser;
7414644Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
7425064Sdm199847 
7435064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
7445064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7455064Sdm199847 		goto errout;
7465064Sdm199847 
7475064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
7485064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7495064Sdm199847 		goto errout;
7505064Sdm199847 
7515064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
7525064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7535064Sdm199847 		goto errout;
7544520Snw141292 
7554520Snw141292 	*iter = tmpiter;
7564520Snw141292 	return (IDMAP_SUCCESS);
7574520Snw141292 
7584520Snw141292 errout:
7594520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
7605696Snw141292 	    xdr_idmap_list_namerules_1_argument, retcode);
7614520Snw141292 }
7624520Snw141292 
7634520Snw141292 
7644520Snw141292 /*
7654520Snw141292  * Iterate through the name-based mapping rules
7664520Snw141292  *
7674520Snw141292  * Input:
7684520Snw141292  * iter - iterator
7694520Snw141292  *
7704520Snw141292  * Output:
7714520Snw141292  * windomain - Windows domain
7724520Snw141292  * winname   - Windows user or group name
7734520Snw141292  * unixname  - Unix user or group name
7744520Snw141292  * is_nt4    - NT4 or AD
7754520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
7764520Snw141292  *
7774520Snw141292  * Return value:
7784520Snw141292  * 0   - done
7794520Snw141292  * 1   - more results available
7804520Snw141292  * < 0 - error
7814520Snw141292  */
7824520Snw141292 idmap_stat
7834520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
7845696Snw141292     char **winname, char **unixname,  boolean_t *is_user,
7855696Snw141292     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
7865696Snw141292 {
7874520Snw141292 	idmap_namerules_res		*namerules;
7884520Snw141292 	idmap_list_namerules_1_argument	*arg;
7894520Snw141292 	idmap_retcode			retcode;
7904520Snw141292 
7915696Snw141292 	idmap_namerule_parts_clear(windomain, winname,
7925696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
7935696Snw141292 
7944520Snw141292 
7954520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
7964520Snw141292 
7974520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
7984520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
7995696Snw141292 	    iter->next >= namerules->rules.rules_len)) {
8004520Snw141292 
8014520Snw141292 		if ((arg = iter->arg) == NULL) {
8024520Snw141292 			errno = EINVAL;
8034520Snw141292 			return (IDMAP_ERR_ARG);
8044520Snw141292 		}
8054520Snw141292 		arg->limit = iter->limit;
8064520Snw141292 
8074520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
8085696Snw141292 		    iter, arg,
8095696Snw141292 		    (uchar_t **)&namerules, sizeof (*namerules),
8105696Snw141292 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
8115696Snw141292 		    (xdrproc_t)xdr_idmap_namerules_res);
8124520Snw141292 		if (retcode != IDMAP_SUCCESS)
8134520Snw141292 			return (retcode);
8144520Snw141292 
8154520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
8164520Snw141292 			retcode  = namerules->retcode;
8174520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
8184520Snw141292 			free(namerules);
8194520Snw141292 			iter->retlist = NULL;
8204520Snw141292 			return (retcode);
8214520Snw141292 		}
8224520Snw141292 		iter->retcode = namerules->retcode;
8234520Snw141292 		arg->lastrowid = namerules->lastrowid;
8244520Snw141292 	}
8254520Snw141292 
8264520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
8274520Snw141292 		return (IDMAP_SUCCESS);
8284520Snw141292 
8294520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
8304520Snw141292 		return (IDMAP_ERR_ARG);
8314520Snw141292 	}
8324520Snw141292 
8335064Sdm199847 	retcode = idmap_strdupnull(windomain,
8345064Sdm199847 	    namerules->rules.rules_val[iter->next].windomain);
8355064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8365064Sdm199847 		goto errout;
8375064Sdm199847 
8385064Sdm199847 	retcode = idmap_strdupnull(winname,
8395064Sdm199847 	    namerules->rules.rules_val[iter->next].winname);
8405064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8415064Sdm199847 		goto errout;
8425064Sdm199847 
8435064Sdm199847 	retcode = idmap_strdupnull(unixname,
8445064Sdm199847 	    namerules->rules.rules_val[iter->next].unixname);
8455064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8465064Sdm199847 		goto errout;
8475064Sdm199847 
8484520Snw141292 	if (is_nt4)
8494520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
8505696Snw141292 	if (is_user)
8515696Snw141292 		*is_user = namerules->rules.rules_val[iter->next].is_user;
8525696Snw141292 	if (is_wuser)
8535696Snw141292 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
8544520Snw141292 	if (direction)
8554520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
8564520Snw141292 	iter->next++;
8574520Snw141292 
8584520Snw141292 	if (iter->next == namerules->rules.rules_len)
8594520Snw141292 		return (iter->retcode);
8604520Snw141292 	else
8614520Snw141292 		return (IDMAP_NEXT);
8624520Snw141292 
8634520Snw141292 errout:
8644520Snw141292 	if (windomain && *windomain)
8654520Snw141292 		free(*windomain);
8664520Snw141292 	if (winname && *winname)
8674520Snw141292 		free(*winname);
8684520Snw141292 	if (unixname && *unixname)
8694520Snw141292 		free(*unixname);
8704520Snw141292 	return (retcode);
8714520Snw141292 }
8724520Snw141292 
8734520Snw141292 
8744520Snw141292 /*
8754520Snw141292  * Create iterator to get SID to UID/GID mappings
8764520Snw141292  *
8774520Snw141292  * Output:
8784520Snw141292  * iter - iterator
8794520Snw141292  */
8804520Snw141292 idmap_stat
8816386Sjp151216 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
8825696Snw141292 {
8834520Snw141292 	idmap_iter_t			*tmpiter;
8844520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
8854520Snw141292 
8864520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
8874520Snw141292 
8886386Sjp151216 	arg->flag = flag;
8894520Snw141292 	*iter = tmpiter;
8904520Snw141292 	return (IDMAP_SUCCESS);
8914520Snw141292 }
8924520Snw141292 
8934520Snw141292 
8944520Snw141292 /*
8954520Snw141292  * Iterate through the SID to UID/GID mappings
8964520Snw141292  *
8974520Snw141292  * Input:
8984520Snw141292  * iter - iterator
8994520Snw141292  *
9004520Snw141292  * Output:
9014520Snw141292  * sid - SID in canonical form
9024520Snw141292  * pid - UID or GID
9034520Snw141292  *
9044520Snw141292  * Return value:
9054520Snw141292  * 0   - done
9064520Snw141292  * 1   - more results available
9074520Snw141292  * < 0 - error
9084520Snw141292  */
9094520Snw141292 idmap_stat
9104520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
9115696Snw141292     idmap_rid_t *rid, uid_t *pid, char **winname,
9125696Snw141292     char **windomain, char **unixname, boolean_t *is_user,
9136386Sjp151216     boolean_t *is_wuser, int *direction, idmap_info *info)
9145696Snw141292 {
9154520Snw141292 	idmap_mappings_res		*mappings;
9164520Snw141292 	idmap_list_mappings_1_argument	*arg;
9174520Snw141292 	idmap_retcode			retcode;
9184520Snw141292 	char				*str;
9194520Snw141292 
9204520Snw141292 	if (sidprefix)
9214520Snw141292 		*sidprefix = NULL;
9224520Snw141292 	if (rid)
9234520Snw141292 		*rid = UINT32_MAX;
9244520Snw141292 	if (winname)
9254520Snw141292 		*winname = NULL;
9264520Snw141292 	if (windomain)
9274520Snw141292 		*windomain = NULL;
9284520Snw141292 	if (unixname)
9294520Snw141292 		*unixname = NULL;
9304520Snw141292 	if (pid)
9314520Snw141292 		*pid = UINT32_MAX;
9325696Snw141292 	if (is_user)
9335696Snw141292 		*is_user = -1;
9345696Snw141292 	if (is_wuser)
9355696Snw141292 		*is_wuser = -1;
9364520Snw141292 	if (direction)
9374644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
9384520Snw141292 
9394520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
9404520Snw141292 
9414520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
9424520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
9435696Snw141292 	    iter->next >= mappings->mappings.mappings_len)) {
9444520Snw141292 
9454520Snw141292 		if ((arg = iter->arg) == NULL) {
9464520Snw141292 			errno = EINVAL;
9474520Snw141292 			return (IDMAP_ERR_ARG);
9484520Snw141292 		}
9494520Snw141292 		arg->limit = iter->limit;
9504520Snw141292 
9514520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
9525696Snw141292 		    iter, arg,
9535696Snw141292 		    (uchar_t **)&mappings, sizeof (*mappings),
9545696Snw141292 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
9555696Snw141292 		    (xdrproc_t)xdr_idmap_mappings_res);
9564520Snw141292 		if (retcode != IDMAP_SUCCESS)
9574520Snw141292 			return (retcode);
9584520Snw141292 
9594520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
9604520Snw141292 			retcode  = mappings->retcode;
9614520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
9624520Snw141292 			free(mappings);
9634520Snw141292 			iter->retlist = NULL;
9644520Snw141292 			return (retcode);
9654520Snw141292 		}
9664520Snw141292 		iter->retcode = mappings->retcode;
9674520Snw141292 		arg->lastrowid = mappings->lastrowid;
9684520Snw141292 	}
9694520Snw141292 
9704520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
9714520Snw141292 		return (IDMAP_SUCCESS);
9724520Snw141292 
9734520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
9744520Snw141292 		return (IDMAP_ERR_ARG);
9754520Snw141292 	}
9764520Snw141292 
9774520Snw141292 	if (sidprefix) {
9784520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
9795696Snw141292 		    idmap_id_u.sid.prefix;
9804695Sbaban 		if (str && *str != '\0') {
9814520Snw141292 			*sidprefix = strdup(str);
9824526Sbaban 			if (*sidprefix == NULL) {
9834526Sbaban 				retcode = IDMAP_ERR_MEMORY;
9844526Sbaban 				goto errout;
9854526Sbaban 			}
9864520Snw141292 		}
9874520Snw141292 	}
9884520Snw141292 	if (rid)
9894520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
9905696Snw141292 		    idmap_id_u.sid.rid;
9915064Sdm199847 
9925064Sdm199847 	retcode = idmap_strdupnull(windomain,
9935064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1domain);
9945064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9955064Sdm199847 		goto errout;
9965064Sdm199847 
9975064Sdm199847 	retcode = idmap_strdupnull(winname,
9985064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1name);
9995064Sdm199847 	if (retcode != IDMAP_SUCCESS)
10005064Sdm199847 		goto errout;
10015064Sdm199847 
10025064Sdm199847 	retcode = idmap_strdupnull(unixname,
10035064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id2name);
10045064Sdm199847 	if (retcode != IDMAP_SUCCESS)
10055064Sdm199847 		goto errout;
10065064Sdm199847 
10075064Sdm199847 
10084520Snw141292 	if (pid)
10094520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
10105696Snw141292 		    idmap_id_u.uid;
10114520Snw141292 	if (direction)
10124520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
10135696Snw141292 		    direction;
10145696Snw141292 	if (is_user)
10155696Snw141292 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
10165696Snw141292 		    .idtype == IDMAP_UID)?1:0;
10175696Snw141292 	if (is_wuser)
10185696Snw141292 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
10195696Snw141292 		    .idtype == IDMAP_USID)?1:0;
10205696Snw141292 
10216386Sjp151216 	if (info) {
10226386Sjp151216 		retcode = idmap_info_cpy(info,
10236386Sjp151216 		    &mappings->mappings.mappings_val[iter->next].info);
10246386Sjp151216 		if (retcode != IDMAP_SUCCESS)
10256386Sjp151216 			goto errout;
10266386Sjp151216 	}
10274520Snw141292 	iter->next++;
10284520Snw141292 
10294520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
10304520Snw141292 		return (iter->retcode);
10314520Snw141292 	else
10324520Snw141292 		return (IDMAP_NEXT);
10334520Snw141292 
10344520Snw141292 errout:
10354520Snw141292 	if (sidprefix && *sidprefix)
10364520Snw141292 		free(*sidprefix);
10374520Snw141292 	if (winname && *winname)
10384520Snw141292 		free(*winname);
10394520Snw141292 	if (windomain && *windomain)
10404520Snw141292 		free(*windomain);
10414520Snw141292 	if (unixname && *unixname)
10424520Snw141292 		free(*unixname);
10434520Snw141292 	return (retcode);
10444520Snw141292 }
10454520Snw141292 
10464520Snw141292 
10474520Snw141292 /*
10484520Snw141292  * Destroy the iterator
10494520Snw141292  */
10504520Snw141292 void
10515696Snw141292 idmap_iter_destroy(idmap_iter_t *iter)
10525696Snw141292 {
10534520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
10544520Snw141292 
10554520Snw141292 	if (iter == NULL)
10564520Snw141292 		return;
10574520Snw141292 
10584520Snw141292 	switch (iter->type) {
10594520Snw141292 	case IDMAP_LIST_NAMERULES:
10604520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
10614520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
10624520Snw141292 		break;
10634520Snw141292 	case IDMAP_LIST_MAPPINGS:
10644520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
10654520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
10664520Snw141292 		break;
10674520Snw141292 	default:
10684520Snw141292 		free(iter);
10694520Snw141292 		return;
10704520Snw141292 	};
10714520Snw141292 
10724520Snw141292 	if (iter->arg) {
10734520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
10744520Snw141292 		free(iter->arg);
10754520Snw141292 	}
10764520Snw141292 	if (iter->retlist) {
10774520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
10784520Snw141292 		free(iter->retlist);
10794520Snw141292 	}
10804520Snw141292 	free(iter);
10814520Snw141292 }
10824520Snw141292 
10834520Snw141292 
10844520Snw141292 /*
10854520Snw141292  * Create handle to get SID to UID/GID mapping entries
10864520Snw141292  *
10874520Snw141292  * Input:
10884520Snw141292  * gh - "get mapping" handle
10894520Snw141292  */
10904520Snw141292 idmap_stat
10915696Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
10925696Snw141292 {
10934520Snw141292 	idmap_get_handle_t	*tmp;
10944520Snw141292 
10954520Snw141292 	/* sanity checks */
10964520Snw141292 	if (handle == NULL || gh == NULL) {
10974520Snw141292 		errno = EINVAL;
10984520Snw141292 		return (IDMAP_ERR_ARG);
10994520Snw141292 	}
11004520Snw141292 
11014520Snw141292 	/* allocate the handle */
11024520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
11034520Snw141292 		errno = ENOMEM;
11044520Snw141292 		return (IDMAP_ERR_MEMORY);
11054520Snw141292 	}
11064520Snw141292 
11074520Snw141292 	tmp->ih = handle;
11084520Snw141292 	*gh = tmp;
11094520Snw141292 	return (IDMAP_SUCCESS);
11104520Snw141292 }
11114520Snw141292 
11124520Snw141292 
11134520Snw141292 /*
11144520Snw141292  * Given SID, get UID
11154520Snw141292  *
11164520Snw141292  * Input:
11174520Snw141292  * sidprefix  - SID prefix
11184520Snw141292  * rid        - RID
11194520Snw141292  * flag       - flag
11204520Snw141292  *
11214520Snw141292  * Output:
11224520Snw141292  * stat - status of the get request
11234520Snw141292  * uid  - POSIX UID if stat = 0
11244520Snw141292  *
11254520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11264520Snw141292  */
11274520Snw141292 idmap_stat
11284520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11295696Snw141292 		int flag, uid_t *uid, idmap_stat *stat)
11305696Snw141292 {
11316386Sjp151216 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
11326386Sjp151216 	    NULL, stat));
11336386Sjp151216 }
11344520Snw141292 
11356386Sjp151216 /*
11366386Sjp151216  * Given SID, get UID
11376386Sjp151216  *
11386386Sjp151216  * Input:
11396386Sjp151216  * sidprefix  - SID prefix
11406386Sjp151216  * rid        - RID
11416386Sjp151216  * flag       - flag
11426386Sjp151216  *
11436386Sjp151216  * Output:
11446386Sjp151216  * stat - status of the get request
11456386Sjp151216  * uid  - POSIX UID if stat = 0
11466386Sjp151216  * how  - mapping type if stat = 0
11476386Sjp151216  *
11486386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
11496386Sjp151216  */
11506386Sjp151216 
11516386Sjp151216 idmap_stat
11526386Sjp151216 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11536386Sjp151216 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
11546386Sjp151216 {
11554520Snw141292 	idmap_retcode	retcode;
11564644Sbaban 	idmap_mapping	*mapping = NULL;
11574520Snw141292 
11584520Snw141292 	/* sanity checks */
11594520Snw141292 	if (gh == NULL)
11604520Snw141292 		return (IDMAP_ERR_ARG);
11614520Snw141292 	if (uid == NULL || sidprefix == NULL)
11624520Snw141292 		return (IDMAP_ERR_ARG);
11634520Snw141292 
1164*7369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1165*7369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1166*7369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid);
1167*7369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1168*7369SJulian.Pullen@Sun.COM 			*stat = retcode;
1169*7369SJulian.Pullen@Sun.COM 			return (retcode);
1170*7369SJulian.Pullen@Sun.COM 		}
1171*7369SJulian.Pullen@Sun.COM 	}
1172*7369SJulian.Pullen@Sun.COM 
11734520Snw141292 	/* Extend the request array and the return list */
11744520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11754520Snw141292 		goto errout;
11764520Snw141292 
11774520Snw141292 	/* Setup the request */
11784520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11794520Snw141292 	mapping->flag = flag;
11804520Snw141292 	mapping->id1.idtype = IDMAP_SID;
11814520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
11824520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
11834520Snw141292 		retcode = IDMAP_ERR_MEMORY;
11844520Snw141292 		goto errout;
11854520Snw141292 	}
11864520Snw141292 	mapping->id2.idtype = IDMAP_UID;
11874520Snw141292 
11884520Snw141292 	/* Setup pointers for the result */
11894520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
11904520Snw141292 	gh->retlist[gh->next].uid = uid;
11914520Snw141292 	gh->retlist[gh->next].stat = stat;
11926386Sjp151216 	gh->retlist[gh->next].info = info;
1193*7369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
11944520Snw141292 
11954520Snw141292 	gh->next++;
11964520Snw141292 	return (IDMAP_SUCCESS);
11974520Snw141292 
11984520Snw141292 errout:
11994644Sbaban 	/* Batch created so far should still be usable */
12004644Sbaban 	if (mapping)
12014644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12024520Snw141292 	errno = idmap_stat2errno(retcode);
12034520Snw141292 	return (retcode);
12044520Snw141292 }
12054520Snw141292 
12064520Snw141292 
12074520Snw141292 /*
12084520Snw141292  * Given SID, get GID
12094520Snw141292  *
12104520Snw141292  * Input:
12114520Snw141292  * sidprefix  - SID prefix
12124520Snw141292  * rid        - rid
12134520Snw141292  * flag       - flag
12144520Snw141292  *
12154520Snw141292  * Output:
12164520Snw141292  * stat - status of the get request
12174520Snw141292  * gid  - POSIX GID if stat = 0
12184520Snw141292  *
12194520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12204520Snw141292  */
12214520Snw141292 idmap_stat
12224520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12235696Snw141292 		int flag, gid_t *gid, idmap_stat *stat)
12245696Snw141292 {
12256386Sjp151216 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
12266386Sjp151216 	    NULL, stat));
12276386Sjp151216 }
12286386Sjp151216 
12296386Sjp151216 
12306386Sjp151216 /*
12316386Sjp151216  * Given SID, get GID
12326386Sjp151216  *
12336386Sjp151216  * Input:
12346386Sjp151216  * sidprefix  - SID prefix
12356386Sjp151216  * rid        - rid
12366386Sjp151216  * flag       - flag
12376386Sjp151216  *
12386386Sjp151216  * Output:
12396386Sjp151216  * stat - status of the get request
12406386Sjp151216  * gid  - POSIX GID if stat = 0
12416386Sjp151216  * how  - mapping type if stat = 0
12426386Sjp151216  *
12436386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
12446386Sjp151216  */
12456386Sjp151216 idmap_stat
12466386Sjp151216 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12476386Sjp151216 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
12486386Sjp151216 {
12494520Snw141292 
12504520Snw141292 	idmap_retcode	retcode;
12514644Sbaban 	idmap_mapping	*mapping = NULL;
12524520Snw141292 
12534520Snw141292 	/* sanity checks */
12544520Snw141292 	if (gh == NULL)
12554520Snw141292 		return (IDMAP_ERR_ARG);
12564520Snw141292 	if (gid == NULL || sidprefix == NULL)
12574520Snw141292 		return (IDMAP_ERR_ARG);
12584520Snw141292 
1259*7369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1260*7369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1261*7369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid);
1262*7369SJulian.Pullen@Sun.COM 		if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1263*7369SJulian.Pullen@Sun.COM 			*stat = retcode;
1264*7369SJulian.Pullen@Sun.COM 			return (retcode);
1265*7369SJulian.Pullen@Sun.COM 		}
1266*7369SJulian.Pullen@Sun.COM 	}
1267*7369SJulian.Pullen@Sun.COM 
12684520Snw141292 	/* Extend the request array and the return list */
12694520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
12704520Snw141292 		goto errout;
12714520Snw141292 
12724520Snw141292 	/* Setup the request */
12734520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
12744520Snw141292 	mapping->flag = flag;
12754520Snw141292 	mapping->id1.idtype = IDMAP_SID;
12764520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
12774520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
12784520Snw141292 		retcode = IDMAP_ERR_MEMORY;
12794520Snw141292 		goto errout;
12804520Snw141292 	}
12814520Snw141292 	mapping->id2.idtype = IDMAP_GID;
12824520Snw141292 
12834520Snw141292 	/* Setup pointers for the result */
12844520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
12854520Snw141292 	gh->retlist[gh->next].gid = gid;
12864520Snw141292 	gh->retlist[gh->next].stat = stat;
12876386Sjp151216 	gh->retlist[gh->next].info = info;
1288*7369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
12894520Snw141292 
12904520Snw141292 	gh->next++;
12914520Snw141292 	return (IDMAP_SUCCESS);
12924520Snw141292 
12934520Snw141292 errout:
12944644Sbaban 	if (mapping)
12954644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12964520Snw141292 	errno = idmap_stat2errno(retcode);
12974520Snw141292 	return (retcode);
12984520Snw141292 }
12994520Snw141292 
13004520Snw141292 
13016386Sjp151216 
13024520Snw141292 /*
13034520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
13044520Snw141292  *
13054520Snw141292  * Input:
13064520Snw141292  * sidprefix  - SID prefix
13074520Snw141292  * rid        - rid
13084520Snw141292  * flag       - flag
13094520Snw141292  *
13104520Snw141292  * Output:
13114520Snw141292  * stat    - status of the get request
13124520Snw141292  * is_user - user or group
13134520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
13144520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
13154520Snw141292  *
13164520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
13174520Snw141292  */
13184520Snw141292 idmap_stat
13194520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
13205696Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
13215696Snw141292 {
13226386Sjp151216 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
13236386Sjp151216 	    NULL, stat));
13246386Sjp151216 }
13256386Sjp151216 
13266386Sjp151216 
13276386Sjp151216 
13286386Sjp151216 /*
13296386Sjp151216  * Given SID, get POSIX ID i.e. UID/GID
13306386Sjp151216  *
13316386Sjp151216  * Input:
13326386Sjp151216  * sidprefix  - SID prefix
13336386Sjp151216  * rid        - rid
13346386Sjp151216  * flag       - flag
13356386Sjp151216  *
13366386Sjp151216  * Output:
13376386Sjp151216  * stat    - status of the get request
13386386Sjp151216  * is_user - user or group
13396386Sjp151216  * pid     - POSIX UID if stat = 0 and is_user = 1
13406386Sjp151216  *           POSIX GID if stat = 0 and is_user = 0
13416386Sjp151216  * how     - mapping type if stat = 0
13426386Sjp151216  *
13436386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
13446386Sjp151216  */
13456386Sjp151216 idmap_stat
13466386Sjp151216 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
13476386Sjp151216 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
13486386Sjp151216 {
13494520Snw141292 	idmap_retcode	retcode;
13504644Sbaban 	idmap_mapping	*mapping = NULL;
13514520Snw141292 
13524520Snw141292 	/* sanity checks */
13534520Snw141292 	if (gh == NULL)
13544520Snw141292 		return (IDMAP_ERR_ARG);
13554520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
13564520Snw141292 		return (IDMAP_ERR_ARG);
13574520Snw141292 
1358*7369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1359*7369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1360*7369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid,
1361*7369SJulian.Pullen@Sun.COM 		    is_user);
1362*7369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1363*7369SJulian.Pullen@Sun.COM 			*stat = retcode;
1364*7369SJulian.Pullen@Sun.COM 			return (retcode);
1365*7369SJulian.Pullen@Sun.COM 		}
1366*7369SJulian.Pullen@Sun.COM 	}
1367*7369SJulian.Pullen@Sun.COM 
13684520Snw141292 	/* Extend the request array and the return list */
13694520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
13704520Snw141292 		goto errout;
13714520Snw141292 
13724520Snw141292 	/* Setup the request */
13734520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
13744520Snw141292 	mapping->flag = flag;
13754520Snw141292 	mapping->id1.idtype = IDMAP_SID;
13764520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
13774520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
13784520Snw141292 		retcode = IDMAP_ERR_MEMORY;
13794520Snw141292 		goto errout;
13804520Snw141292 	}
13814520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
13824520Snw141292 
13834520Snw141292 	/* Setup pointers for the result */
13844520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
13854520Snw141292 	gh->retlist[gh->next].uid = pid;
13864520Snw141292 	gh->retlist[gh->next].gid = pid;
13874520Snw141292 	gh->retlist[gh->next].is_user = is_user;
13884520Snw141292 	gh->retlist[gh->next].stat = stat;
13896386Sjp151216 	gh->retlist[gh->next].info = info;
1390*7369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
13914520Snw141292 
13924520Snw141292 	gh->next++;
13934520Snw141292 	return (IDMAP_SUCCESS);
13944520Snw141292 
13954520Snw141292 errout:
13964644Sbaban 	if (mapping)
13974644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
13984520Snw141292 	errno = idmap_stat2errno(retcode);
13994520Snw141292 	return (retcode);
14004520Snw141292 }
14014520Snw141292 
14024520Snw141292 
14034520Snw141292 /*
14044520Snw141292  * Given UID, get SID
14054520Snw141292  *
14064520Snw141292  * Input:
14074520Snw141292  * uid  - POSIX UID
14084520Snw141292  * flag - flag
14094520Snw141292  *
14104520Snw141292  * Output:
14114520Snw141292  * stat - status of the get request
14124520Snw141292  * sid  - SID prefix (if stat == 0)
14134520Snw141292  * rid  - rid
14144520Snw141292  *
14154520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
14164520Snw141292  */
14174520Snw141292 idmap_stat
14184520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
14195696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
14205696Snw141292 {
14216386Sjp151216 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
14226386Sjp151216 	    NULL, stat));
14236386Sjp151216 }
14246386Sjp151216 
14256386Sjp151216 
14266386Sjp151216 /*
14276386Sjp151216  * Given UID, get SID
14286386Sjp151216  *
14296386Sjp151216  * Input:
14306386Sjp151216  * uid  - POSIX UID
14316386Sjp151216  * flag - flag
14326386Sjp151216  *
14336386Sjp151216  * Output:
14346386Sjp151216  * stat - status of the get request
14356386Sjp151216  * sid  - SID prefix (if stat == 0)
14366386Sjp151216  * rid  - rid
14376386Sjp151216  * how  - mapping type if stat = 0
14386386Sjp151216  *
14396386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
14406386Sjp151216  */
14416386Sjp151216 idmap_stat
14426386Sjp151216 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
14436386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
14446386Sjp151216 {
14454520Snw141292 
14464520Snw141292 	idmap_retcode	retcode;
14474644Sbaban 	idmap_mapping	*mapping = NULL;
14484520Snw141292 
14494520Snw141292 	/* sanity checks */
14504520Snw141292 	if (gh == NULL)
14514520Snw141292 		return (IDMAP_ERR_ARG);
14524520Snw141292 	if (sidprefix == NULL)
14534520Snw141292 		return (IDMAP_ERR_ARG);
14544520Snw141292 
1455*7369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1456*7369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1457*7369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid);
1458*7369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1459*7369SJulian.Pullen@Sun.COM 			*stat = retcode;
1460*7369SJulian.Pullen@Sun.COM 			return (retcode);
1461*7369SJulian.Pullen@Sun.COM 		}
1462*7369SJulian.Pullen@Sun.COM 	}
1463*7369SJulian.Pullen@Sun.COM 
14644520Snw141292 	/* Extend the request array and the return list */
14654520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
14664520Snw141292 		goto errout;
14674520Snw141292 
14684520Snw141292 	/* Setup the request */
14694520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
14704520Snw141292 	mapping->flag = flag;
14714520Snw141292 	mapping->id1.idtype = IDMAP_UID;
14724520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
14734520Snw141292 	mapping->id2.idtype = IDMAP_SID;
14744520Snw141292 
14754520Snw141292 	/* Setup pointers for the result */
14764520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
14774520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
14784520Snw141292 	gh->retlist[gh->next].rid = rid;
14794520Snw141292 	gh->retlist[gh->next].stat = stat;
14806386Sjp151216 	gh->retlist[gh->next].info = info;
1481*7369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
14824520Snw141292 
14834520Snw141292 	gh->next++;
14844520Snw141292 	return (IDMAP_SUCCESS);
14854520Snw141292 
14864520Snw141292 errout:
14874644Sbaban 	if (mapping)
14884644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
14894520Snw141292 	errno = idmap_stat2errno(retcode);
14904520Snw141292 	return (retcode);
14914520Snw141292 }
14924520Snw141292 
14934520Snw141292 
14944520Snw141292 /*
14954520Snw141292  * Given GID, get SID
14964520Snw141292  *
14974520Snw141292  * Input:
14984520Snw141292  * gid  - POSIX GID
14994520Snw141292  * flag - flag
15004520Snw141292  *
15014520Snw141292  * Output:
15024520Snw141292  * stat       - status of the get request
15034520Snw141292  * sidprefix  - SID prefix (if stat == 0)
15044520Snw141292  * rid        - rid
15054520Snw141292  *
15064520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
15074520Snw141292  */
15084520Snw141292 idmap_stat
15094520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
15105696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
15115696Snw141292 {
15126386Sjp151216 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
15136386Sjp151216 	    NULL, stat));
15146386Sjp151216 }
15156386Sjp151216 
15166386Sjp151216 
15176386Sjp151216 /*
15186386Sjp151216  * Given GID, get SID
15196386Sjp151216  *
15206386Sjp151216  * Input:
15216386Sjp151216  * gid  - POSIX GID
15226386Sjp151216  * flag - flag
15236386Sjp151216  *
15246386Sjp151216  * Output:
15256386Sjp151216  * stat       - status of the get request
15266386Sjp151216  * sidprefix  - SID prefix (if stat == 0)
15276386Sjp151216  * rid        - rid
15286386Sjp151216  * how        - mapping type if stat = 0
15296386Sjp151216  *
15306386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
15316386Sjp151216  */
15326386Sjp151216 idmap_stat
15336386Sjp151216 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
15346386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
15356386Sjp151216 {
15364520Snw141292 
15374520Snw141292 	idmap_retcode	retcode;
15384644Sbaban 	idmap_mapping	*mapping = NULL;
15394520Snw141292 
15404520Snw141292 	/* sanity checks */
15414520Snw141292 	if (gh == NULL)
15424520Snw141292 		return (IDMAP_ERR_ARG);
15434520Snw141292 	if (sidprefix == NULL)
15444520Snw141292 		return (IDMAP_ERR_ARG);
15454520Snw141292 
1546*7369SJulian.Pullen@Sun.COM 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1547*7369SJulian.Pullen@Sun.COM 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1548*7369SJulian.Pullen@Sun.COM 		retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid);
1549*7369SJulian.Pullen@Sun.COM 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1550*7369SJulian.Pullen@Sun.COM 			*stat = retcode;
1551*7369SJulian.Pullen@Sun.COM 			return (retcode);
1552*7369SJulian.Pullen@Sun.COM 		}
1553*7369SJulian.Pullen@Sun.COM 	}
1554*7369SJulian.Pullen@Sun.COM 
15554520Snw141292 	/* Extend the request array and the return list */
15564520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
15574520Snw141292 		goto errout;
15584520Snw141292 
15594520Snw141292 	/* Setup the request */
15604520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
15614520Snw141292 	mapping->flag = flag;
15624520Snw141292 	mapping->id1.idtype = IDMAP_GID;
15634520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
15644520Snw141292 	mapping->id2.idtype = IDMAP_SID;
15654520Snw141292 
15664520Snw141292 	/* Setup pointers for the result */
15674520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
15684520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
15694520Snw141292 	gh->retlist[gh->next].rid = rid;
15704520Snw141292 	gh->retlist[gh->next].stat = stat;
15716386Sjp151216 	gh->retlist[gh->next].info = info;
1572*7369SJulian.Pullen@Sun.COM 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
15734520Snw141292 
15744520Snw141292 	gh->next++;
15754520Snw141292 	return (IDMAP_SUCCESS);
15764520Snw141292 
15774520Snw141292 errout:
15784644Sbaban 	if (mapping)
15794644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
15804520Snw141292 	errno = idmap_stat2errno(retcode);
15814520Snw141292 	return (retcode);
15824520Snw141292 }
15834520Snw141292 
15844520Snw141292 
15854520Snw141292 /*
15864520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
15874520Snw141292  * status and identity) will be available in the data areas
15884520Snw141292  * provided by individual requests.
15894520Snw141292  */
15904520Snw141292 idmap_stat
15915696Snw141292 idmap_get_mappings(idmap_get_handle_t *gh)
15925696Snw141292 {
15934520Snw141292 	CLIENT		*clnt;
15944520Snw141292 	enum clnt_stat	clntstat;
15954520Snw141292 	idmap_retcode	retcode;
15964520Snw141292 	idmap_ids_res	res;
1597*7369SJulian.Pullen@Sun.COM 	idmap_id	*res_id;
15984520Snw141292 	int		i;
1599*7369SJulian.Pullen@Sun.COM 	idmap_id	*req_id;
1600*7369SJulian.Pullen@Sun.COM 	int		direction;
16014520Snw141292 
16024520Snw141292 	if (gh == NULL) {
16034520Snw141292 		errno = EINVAL;
16044520Snw141292 		return (IDMAP_ERR_ARG);
16054520Snw141292 	}
16064520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
16074520Snw141292 
16084520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
16094520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
16105696Snw141292 	    (xdrproc_t)xdr_idmap_mapping_batch,
16115696Snw141292 	    (caddr_t)&gh->batch,
16125696Snw141292 	    (xdrproc_t)xdr_idmap_ids_res,
16135696Snw141292 	    (caddr_t)&res,
16145696Snw141292 	    TIMEOUT);
16154520Snw141292 	if (clntstat != RPC_SUCCESS) {
16164644Sbaban 		retcode = _idmap_rpc2stat(clnt);
16174520Snw141292 		goto out;
16184520Snw141292 	}
16194520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
16204520Snw141292 		retcode = res.retcode;
16214520Snw141292 		goto out;
16224520Snw141292 	}
16234520Snw141292 	for (i = 0; i < gh->next; i++) {
16244520Snw141292 		if (i >= res.ids.ids_len) {
16254520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
16264520Snw141292 			continue;
16274520Snw141292 		}
16284520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
1629*7369SJulian.Pullen@Sun.COM 		res_id = &res.ids.ids_val[i].id;
1630*7369SJulian.Pullen@Sun.COM 		direction = res.ids.ids_val[i].direction;
1631*7369SJulian.Pullen@Sun.COM 		req_id = &gh->batch.idmap_mapping_batch_val[i].id1;
1632*7369SJulian.Pullen@Sun.COM 		switch (res_id->idtype) {
16334520Snw141292 		case IDMAP_UID:
16344520Snw141292 			if (gh->retlist[i].uid)
1635*7369SJulian.Pullen@Sun.COM 				*gh->retlist[i].uid = res_id->idmap_id_u.uid;
16364520Snw141292 			if (gh->retlist[i].is_user)
16374520Snw141292 				*gh->retlist[i].is_user = 1;
1638*7369SJulian.Pullen@Sun.COM 
1639*7369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1640*7369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
1641*7369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
1642*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
1643*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
1644*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
1645*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid, 1,
1646*7369SJulian.Pullen@Sun.COM 					    direction);
1647*7369SJulian.Pullen@Sun.COM 				else
1648*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
1649*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
1650*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
1651*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.uid,
1652*7369SJulian.Pullen@Sun.COM 					    direction);
1653*7369SJulian.Pullen@Sun.COM 			}
16544520Snw141292 			break;
1655*7369SJulian.Pullen@Sun.COM 
16564520Snw141292 		case IDMAP_GID:
16574520Snw141292 			if (gh->retlist[i].gid)
1658*7369SJulian.Pullen@Sun.COM 				*gh->retlist[i].gid = res_id->idmap_id_u.gid;
16594520Snw141292 			if (gh->retlist[i].is_user)
16604520Snw141292 				*gh->retlist[i].is_user = 0;
1661*7369SJulian.Pullen@Sun.COM 
1662*7369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1663*7369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
1664*7369SJulian.Pullen@Sun.COM 				if (gh->retlist[i].is_user != NULL)
1665*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2pid(
1666*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
1667*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
1668*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid, 0,
1669*7369SJulian.Pullen@Sun.COM 					    direction);
1670*7369SJulian.Pullen@Sun.COM 				else
1671*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
1672*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.prefix,
1673*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.sid.rid,
1674*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.gid,
1675*7369SJulian.Pullen@Sun.COM 					    direction);
1676*7369SJulian.Pullen@Sun.COM 			}
16774520Snw141292 			break;
1678*7369SJulian.Pullen@Sun.COM 
16794864Sbaban 		case IDMAP_POSIXID:
16804864Sbaban 			if (gh->retlist[i].uid)
16814864Sbaban 				*gh->retlist[i].uid = 60001;
16824864Sbaban 			if (gh->retlist[i].is_user)
16834864Sbaban 				*gh->retlist[i].is_user = -1;
16844864Sbaban 			break;
1685*7369SJulian.Pullen@Sun.COM 
16864520Snw141292 		case IDMAP_SID:
16875696Snw141292 		case IDMAP_USID:
16885696Snw141292 		case IDMAP_GSID:
16894520Snw141292 			if (gh->retlist[i].rid)
1690*7369SJulian.Pullen@Sun.COM 				*gh->retlist[i].rid =
1691*7369SJulian.Pullen@Sun.COM 				    res_id->idmap_id_u.sid.rid;
16924520Snw141292 			if (gh->retlist[i].sidprefix) {
1693*7369SJulian.Pullen@Sun.COM 				if (res_id->idmap_id_u.sid.prefix == NULL ||
1694*7369SJulian.Pullen@Sun.COM 				    *res_id->idmap_id_u.sid.prefix == '\0') {
16954520Snw141292 					*gh->retlist[i].sidprefix = NULL;
16964520Snw141292 					break;
16974520Snw141292 				}
16984520Snw141292 				*gh->retlist[i].sidprefix =
1699*7369SJulian.Pullen@Sun.COM 				    strdup(res_id->idmap_id_u.sid.prefix);
17004520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
17014520Snw141292 					*gh->retlist[i].stat =
17025696Snw141292 					    IDMAP_ERR_MEMORY;
17034520Snw141292 			}
1704*7369SJulian.Pullen@Sun.COM 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1705*7369SJulian.Pullen@Sun.COM 			    gh->retlist[i].cache_res) {
1706*7369SJulian.Pullen@Sun.COM 				if (req_id->idtype == IDMAP_UID)
1707*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2uid(
1708*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
1709*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
1710*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.uid,
1711*7369SJulian.Pullen@Sun.COM 					    direction);
1712*7369SJulian.Pullen@Sun.COM 				else /* req_id->idtype == IDMAP_GID */
1713*7369SJulian.Pullen@Sun.COM 					idmap_cache_add_sid2gid(
1714*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.prefix,
1715*7369SJulian.Pullen@Sun.COM 					    res_id->idmap_id_u.sid.rid,
1716*7369SJulian.Pullen@Sun.COM 					    req_id->idmap_id_u.gid,
1717*7369SJulian.Pullen@Sun.COM 					    direction);
1718*7369SJulian.Pullen@Sun.COM 			}
17194520Snw141292 			break;
1720*7369SJulian.Pullen@Sun.COM 
17214520Snw141292 		case IDMAP_NONE:
17224520Snw141292 			break;
1723*7369SJulian.Pullen@Sun.COM 
17244520Snw141292 		default:
17254520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
17264520Snw141292 			break;
17274520Snw141292 		}
17286386Sjp151216 		if (gh->retlist[i].info != NULL)
17296386Sjp151216 			(void) idmap_info_cpy(gh->retlist[i].info,
17306386Sjp151216 			    &res.ids.ids_val[i].info);
17314520Snw141292 	}
17324520Snw141292 	retcode = IDMAP_SUCCESS;
17334520Snw141292 
17344520Snw141292 out:
17354644Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
17364520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
17374520Snw141292 	errno = idmap_stat2errno(retcode);
17384520Snw141292 	return (retcode);
17394520Snw141292 }
17404520Snw141292 
17414520Snw141292 
17424520Snw141292 /*
17434520Snw141292  * Destroy the "get mapping" handle
17444520Snw141292  */
17454520Snw141292 void
17465696Snw141292 idmap_get_destroy(idmap_get_handle_t *gh)
17475696Snw141292 {
17484520Snw141292 	if (gh == NULL)
17494520Snw141292 		return;
17504520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
17514520Snw141292 	if (gh->retlist)
17524520Snw141292 		free(gh->retlist);
17534520Snw141292 	free(gh);
17544520Snw141292 }
17554520Snw141292 
17564520Snw141292 
17574520Snw141292 /*
17584520Snw141292  * Get windows to unix mapping
17594520Snw141292  */
17604520Snw141292 idmap_stat
17614520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
17624520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
17634520Snw141292 		const char *winname, const char *windomain,
17645696Snw141292 		int flag, int *is_user, int *is_wuser,
17656386Sjp151216 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
17665696Snw141292 {
17674520Snw141292 	CLIENT			*clnt;
17684520Snw141292 	enum clnt_stat		clntstat;
17694520Snw141292 	idmap_mapping		request, *mapping;
17704520Snw141292 	idmap_mappings_res	result;
17714520Snw141292 	idmap_retcode		retcode, rc;
17724520Snw141292 
17734520Snw141292 	if (handle == NULL) {
17744520Snw141292 		errno = EINVAL;
17754520Snw141292 		return (IDMAP_ERR_ARG);
17764520Snw141292 	}
17774520Snw141292 
17784520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
17794520Snw141292 
17804520Snw141292 	(void) memset(&request, 0, sizeof (request));
17814520Snw141292 	(void) memset(&result, 0, sizeof (result));
17824520Snw141292 
17834520Snw141292 	if (pid)
17844520Snw141292 		*pid = UINT32_MAX;
17854520Snw141292 	if (unixname)
17864520Snw141292 		*unixname = NULL;
17874520Snw141292 	if (direction)
17884644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
17894520Snw141292 
17904520Snw141292 	request.flag = flag;
17914520Snw141292 	request.id1.idtype = IDMAP_SID;
17924520Snw141292 	if (sidprefix && rid) {
17934520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
17944520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
17954520Snw141292 	} else if (winname) {
17965064Sdm199847 		retcode = idmap_strdupnull(&request.id1name, winname);
17975247Sbaban 		if (retcode != IDMAP_SUCCESS)
17984520Snw141292 			goto out;
17995064Sdm199847 
18005064Sdm199847 		retcode = idmap_strdupnull(&request.id1domain, windomain);
18015247Sbaban 		if (retcode != IDMAP_SUCCESS)
18025064Sdm199847 			goto out;
18035064Sdm199847 
18044520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
18054520Snw141292 	} else {
18064520Snw141292 		errno = EINVAL;
18074520Snw141292 		return (IDMAP_ERR_ARG);
18084520Snw141292 	}
18094520Snw141292 
18105696Snw141292 	if (*is_user == 1)
18114520Snw141292 		request.id2.idtype = IDMAP_UID;
18124520Snw141292 	else if (*is_user == 0)
18134520Snw141292 		request.id2.idtype = IDMAP_GID;
18144520Snw141292 	else
18154520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
18164520Snw141292 
18175696Snw141292 	if (*is_wuser == 1)
18185696Snw141292 		request.id1.idtype = IDMAP_USID;
18195696Snw141292 	else if (*is_wuser == 0)
18205696Snw141292 		request.id1.idtype = IDMAP_GSID;
18215696Snw141292 	else
18225696Snw141292 		request.id1.idtype = IDMAP_SID;
18235696Snw141292 
18244520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
18255696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
18265696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
18275696Snw141292 	    TIMEOUT);
18284520Snw141292 
18294644Sbaban 	if (clntstat != RPC_SUCCESS)
18304644Sbaban 		return (_idmap_rpc2stat(clnt));
18314520Snw141292 
18324520Snw141292 	retcode = result.retcode;
18334520Snw141292 
18344520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
18354520Snw141292 		if (retcode == IDMAP_SUCCESS)
18364520Snw141292 			retcode = IDMAP_ERR_NORESULT;
18374520Snw141292 		goto out;
18384520Snw141292 	}
18394520Snw141292 
18404864Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
18415696Snw141292 		*is_user = 1;
18424864Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
18435696Snw141292 		*is_user = 0;
18444864Sbaban 	} else {
18454864Sbaban 		goto out;
18464864Sbaban 	}
18475696Snw141292 
18485696Snw141292 	if (mapping->id1.idtype == IDMAP_USID) {
18495696Snw141292 		*is_wuser = 1;
18505696Snw141292 	} else if (mapping->id1.idtype == IDMAP_GSID) {
18515696Snw141292 		*is_wuser = 0;
18525696Snw141292 	} else {
18535696Snw141292 		goto out;
18545696Snw141292 	}
18555696Snw141292 
18564520Snw141292 	if (direction)
18574520Snw141292 		*direction = mapping->direction;
18584520Snw141292 	if (pid)
18594520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
18605064Sdm199847 
18615064Sdm199847 	rc = idmap_strdupnull(unixname, mapping->id2name);
18625064Sdm199847 	if (rc != IDMAP_SUCCESS)
18635064Sdm199847 		retcode = rc;
18644520Snw141292 
18656386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
18666386Sjp151216 	if (rc != IDMAP_SUCCESS)
18676386Sjp151216 		retcode = rc;
18686386Sjp151216 
18694520Snw141292 out:
18706966Sjp151216 	if (request.id1name != NULL)
18716966Sjp151216 		free(request.id1name);
18726966Sjp151216 	if (request.id1domain != NULL)
18736966Sjp151216 		free(request.id1domain);
18744520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
18754520Snw141292 	if (retcode != IDMAP_SUCCESS)
18764520Snw141292 		errno = idmap_stat2errno(retcode);
18774520Snw141292 	return (retcode);
18784520Snw141292 }
18794520Snw141292 
18804520Snw141292 
18814520Snw141292 /*
18824520Snw141292  * Get unix to windows mapping
18834520Snw141292  */
18844520Snw141292 idmap_stat
18854520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
18864520Snw141292 		uid_t *pid, const char *unixname,
18875696Snw141292 		int flag, int is_user, int *is_wuser,
18884520Snw141292 		char **sidprefix, idmap_rid_t *rid,
18894520Snw141292 		char **winname, char **windomain,
18906386Sjp151216 		int *direction, idmap_info *info)
18915696Snw141292 {
18924520Snw141292 	CLIENT			*clnt;
18934520Snw141292 	enum clnt_stat		clntstat;
18944520Snw141292 	idmap_mapping		request, *mapping;
18954520Snw141292 	idmap_mappings_res	result;
18964520Snw141292 	idmap_retcode		retcode, rc;
18974520Snw141292 
18984520Snw141292 	if (handle == NULL) {
18994520Snw141292 		errno = EINVAL;
19004520Snw141292 		return (IDMAP_ERR_ARG);
19014520Snw141292 	}
19024520Snw141292 
19034520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
19044520Snw141292 
19054520Snw141292 	if (sidprefix)
19064520Snw141292 		*sidprefix = NULL;
19074520Snw141292 	if (winname)
19084520Snw141292 		*winname = NULL;
19094520Snw141292 	if (windomain)
19104520Snw141292 		*windomain = NULL;
19114520Snw141292 	if (rid)
19124520Snw141292 		*rid = UINT32_MAX;
19134520Snw141292 	if (direction)
19144644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
19154520Snw141292 
19164520Snw141292 	(void) memset(&request, 0, sizeof (request));
19174520Snw141292 	(void) memset(&result, 0, sizeof (result));
19184520Snw141292 
19194520Snw141292 	request.flag = flag;
19204520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
19214520Snw141292 
19224520Snw141292 	if (pid && *pid != UINT32_MAX) {
19234520Snw141292 		request.id1.idmap_id_u.uid = *pid;
19244520Snw141292 	} else if (unixname) {
19255064Sdm199847 		request.id1name = (char *)unixname;
19264520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
19274520Snw141292 	} else {
19284520Snw141292 		errno = EINVAL;
19294520Snw141292 		return (IDMAP_ERR_ARG);
19304520Snw141292 	}
19314520Snw141292 
19325696Snw141292 	if (is_wuser == NULL)
19335696Snw141292 		request.id2.idtype = IDMAP_SID;
19345696Snw141292 	else if (*is_wuser == -1)
19355696Snw141292 		request.id2.idtype = IDMAP_SID;
19365696Snw141292 	else if (*is_wuser == 0)
19375696Snw141292 		request.id2.idtype = IDMAP_GSID;
19385696Snw141292 	else if (*is_wuser == 1)
19395696Snw141292 		request.id2.idtype = IDMAP_USID;
19404520Snw141292 
19414520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
19425696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
19435696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
19445696Snw141292 	    TIMEOUT);
19454520Snw141292 
19464644Sbaban 	if (clntstat != RPC_SUCCESS)
19474644Sbaban 		return (_idmap_rpc2stat(clnt));
19484520Snw141292 
19494520Snw141292 	retcode = result.retcode;
19504520Snw141292 
19514520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
19524520Snw141292 		if (retcode == IDMAP_SUCCESS)
19534520Snw141292 			retcode = IDMAP_ERR_NORESULT;
19544520Snw141292 		goto out;
19554520Snw141292 	}
19564520Snw141292 
19575696Snw141292 	if (direction != NULL)
19584520Snw141292 		*direction = mapping->direction;
19595696Snw141292 
19606386Sjp151216 	if (is_wuser != NULL) {
19616386Sjp151216 		if (mapping->id2.idtype == IDMAP_USID)
19626386Sjp151216 			*is_wuser = 1;
19636386Sjp151216 		else if (mapping->id2.idtype == IDMAP_GSID)
19646386Sjp151216 			*is_wuser = 0;
19656386Sjp151216 		else
19666386Sjp151216 			*is_wuser = -1;
19676386Sjp151216 	}
19685696Snw141292 
19694695Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
19704695Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
19714520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
19724520Snw141292 		if (*sidprefix == NULL) {
19734520Snw141292 			retcode = IDMAP_ERR_MEMORY;
19744520Snw141292 			goto errout;
19754520Snw141292 		}
19764520Snw141292 	}
19774520Snw141292 	if (rid)
19784520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
19795064Sdm199847 
19805064Sdm199847 	rc = idmap_strdupnull(winname, mapping->id2name);
19815064Sdm199847 	if (rc != IDMAP_SUCCESS)
19825064Sdm199847 		retcode = rc;
19835064Sdm199847 
19845064Sdm199847 	rc = idmap_strdupnull(windomain, mapping->id2domain);
19855064Sdm199847 	if (rc != IDMAP_SUCCESS)
19865064Sdm199847 		retcode = rc;
19874520Snw141292 
19886386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
19896386Sjp151216 	if (rc != IDMAP_SUCCESS)
19906386Sjp151216 		retcode = rc;
19916386Sjp151216 
19924520Snw141292 	goto out;
19934520Snw141292 
19944520Snw141292 errout:
19954520Snw141292 	if (sidprefix && *sidprefix) {
19964520Snw141292 		free(*sidprefix);
19974520Snw141292 		*sidprefix = NULL;
19984520Snw141292 	}
19994520Snw141292 	if (winname && *winname) {
20004520Snw141292 		free(*winname);
20014520Snw141292 		*winname = NULL;
20024520Snw141292 	}
20034520Snw141292 	if (windomain && *windomain) {
20044520Snw141292 		free(*windomain);
20054520Snw141292 		*windomain = NULL;
20064520Snw141292 	}
20074520Snw141292 
20084520Snw141292 out:
20094520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
20104520Snw141292 	if (retcode != IDMAP_SUCCESS)
20114520Snw141292 		errno = idmap_stat2errno(retcode);
20124520Snw141292 	return (retcode);
20134520Snw141292 }
20144520Snw141292 
20154520Snw141292 
20164520Snw141292 
20174520Snw141292 #define	gettext(s)	s
20184520Snw141292 static stat_table_t stattable[] = {
20194520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
20204520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
20214520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
20224520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
20234520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
20244520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
20254520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
20264520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
20274644Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
20284520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
20294520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
20304520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
20314520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
20324520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
20334520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
20344520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
20354520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
20364520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
20374644Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
20384520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
20394520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
20404644Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
20414695Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
20424520Snw141292 	{IDMAP_ERR_NOMAPPING,
20434520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
20444520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
20454520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
20464520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
20474520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
20484520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
20494520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
20504520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
20514520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
20524520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
20534520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
20544520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
20554520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
20564864Sbaban 		gettext("Windows lookup failed"), EINVAL},
20574864Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
20584864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20594864Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
20604864Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
20614864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
20624864Sbaban 		"Unix to Windows name-based rule"), EINVAL},
20635968Snw141292 	{IDMAP_ERR_BAD_UTF8,
20645968Snw141292 		gettext("Invalid or illegal UTF-8 sequence found in "
20655968Snw141292 		"a given Windows entity name or domain name"), EINVAL},
20666386Sjp151216 	{IDMAP_ERR_NONEGENERATED,
20676386Sjp151216 		gettext("Mapping not found and none created (see -c option)"),
20686386Sjp151216 		EINVAL},
20696616Sdm199847 	{IDMAP_ERR_PROP_UNKNOWN,
20706616Sdm199847 		gettext("Undefined property"),
20716616Sdm199847 		EINVAL},
20726616Sdm199847 	{IDMAP_ERR_NS_LDAP_CFG,
20736616Sdm199847 		gettext("Native LDAP configuration error"), EINVAL},
20746616Sdm199847 	{IDMAP_ERR_NS_LDAP_PARTIAL,
20756616Sdm199847 		gettext("Partial result from Native LDAP"), EINVAL},
20766616Sdm199847 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
20776616Sdm199847 		gettext("Native LDAP operation failed"), EINVAL},
20786616Sdm199847 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
20796616Sdm199847 		gettext("Improper winname form found in Native LDAP"), EINVAL},
20804520Snw141292 	{-1, NULL, 0}
20814520Snw141292 };
20824520Snw141292 #undef	gettext
20834520Snw141292 
20844520Snw141292 
20854520Snw141292 /*
20864520Snw141292  * Get description of status code
20874520Snw141292  *
20884520Snw141292  * Input:
20894520Snw141292  * status - Status code returned by libidmap API call
20904520Snw141292  *
20914520Snw141292  * Return Value:
20924520Snw141292  * human-readable localized description of idmap_stat
20934520Snw141292  */
20944520Snw141292 /* ARGSUSED */
20954520Snw141292 const char *
20965696Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
20975696Snw141292 {
20984520Snw141292 	int i;
20994520Snw141292 
21004520Snw141292 	for (i = 0; stattable[i].msg; i++) {
21014520Snw141292 		if (stattable[i].retcode == status)
21024526Sbaban 			return (gettext(stattable[i].msg));
21034520Snw141292 	}
21044520Snw141292 	return (gettext("Unknown error"));
21054520Snw141292 }
21064520Snw141292 
21074520Snw141292 
21084520Snw141292 static int
21095696Snw141292 idmap_stat2errno(idmap_stat stat)
21105696Snw141292 {
21114520Snw141292 	int i;
21124520Snw141292 	for (i = 0; stattable[i].msg; i++) {
21134520Snw141292 		if (stattable[i].retcode == stat)
21144520Snw141292 			return (stattable[i].errnum);
21154520Snw141292 	}
21164520Snw141292 	return (EINVAL);
21174520Snw141292 }
21184520Snw141292 
21194520Snw141292 
21204520Snw141292 /*
21214520Snw141292  * Get status code from string
21224520Snw141292  */
21234520Snw141292 idmap_stat
21245696Snw141292 idmap_string2stat(const char *str)
21255696Snw141292 {
21264520Snw141292 	if (str == NULL)
21274520Snw141292 		return (IDMAP_ERR_INTERNAL);
21284520Snw141292 
21294520Snw141292 #define	return_cmp(a) \
21304520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
21314520Snw141292 		return (IDMAP_ERR_ ## a);
21324520Snw141292 
21334520Snw141292 	return_cmp(OTHER);
21344520Snw141292 	return_cmp(INTERNAL);
21354520Snw141292 	return_cmp(MEMORY);
21364520Snw141292 	return_cmp(NORESULT);
21374520Snw141292 	return_cmp(NOTUSER);
21384520Snw141292 	return_cmp(NOTGROUP);
21394520Snw141292 	return_cmp(NOTSUPPORTED);
21404520Snw141292 	return_cmp(W2U_NAMERULE);
21414520Snw141292 	return_cmp(U2W_NAMERULE);
21424520Snw141292 	return_cmp(CACHE);
21434520Snw141292 	return_cmp(DB);
21444520Snw141292 	return_cmp(ARG);
21454520Snw141292 	return_cmp(SID);
21464520Snw141292 	return_cmp(IDTYPE);
21474520Snw141292 	return_cmp(RPC_HANDLE);
21484520Snw141292 	return_cmp(RPC);
21494520Snw141292 	return_cmp(CLIENT_HANDLE);
21504520Snw141292 	return_cmp(BUSY);
21514520Snw141292 	return_cmp(PERMISSION_DENIED);
21524520Snw141292 	return_cmp(NOMAPPING);
21534520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
21544520Snw141292 	return_cmp(DOMAIN);
21554520Snw141292 	return_cmp(SECURITY);
21564520Snw141292 	return_cmp(NOTFOUND);
21574520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
21584520Snw141292 	return_cmp(MEMORY);
21594520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
21604520Snw141292 	return_cmp(CFG);
21614520Snw141292 	return_cmp(CFG_CHANGE);
21624520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
21634520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
21644864Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
21654864Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
21666616Sdm199847 	return_cmp(BAD_UTF8);
21676616Sdm199847 	return_cmp(NONEGENERATED);
21686616Sdm199847 	return_cmp(PROP_UNKNOWN);
21696616Sdm199847 	return_cmp(NS_LDAP_CFG);
21706616Sdm199847 	return_cmp(NS_LDAP_PARTIAL);
21716616Sdm199847 	return_cmp(NS_LDAP_OP_FAILED);
21726616Sdm199847 	return_cmp(NS_LDAP_BAD_WINNAME);
21734520Snw141292 #undef return_cmp
21744520Snw141292 
21754520Snw141292 	return (IDMAP_ERR_OTHER);
21764520Snw141292 }
21774520Snw141292 
21784520Snw141292 
21794520Snw141292 /*
21804520Snw141292  * Map the given status to one that can be returned by the protocol
21814520Snw141292  */
21824520Snw141292 idmap_stat
21835696Snw141292 idmap_stat4prot(idmap_stat status)
21845696Snw141292 {
21854520Snw141292 	switch (status) {
21864520Snw141292 	case IDMAP_ERR_MEMORY:
21874520Snw141292 	case IDMAP_ERR_CACHE:
21884520Snw141292 		return (IDMAP_ERR_INTERNAL);
21894520Snw141292 	}
21904520Snw141292 	return (status);
21914520Snw141292 }
21925043Sbaban 
21935043Sbaban 
21945043Sbaban /*
21955247Sbaban  * This is a convenience routine which duplicates a string after
21965247Sbaban  * checking for NULL pointers. This function will return success if
21975247Sbaban  * either the 'to' OR 'from' pointers are NULL.
21985064Sdm199847  */
21995064Sdm199847 static idmap_stat
22005696Snw141292 idmap_strdupnull(char **to, const char *from)
22015696Snw141292 {
22025247Sbaban 	if (to == NULL)
22035247Sbaban 		return (IDMAP_SUCCESS);
22045247Sbaban 
22055064Sdm199847 	if (from == NULL || *from == '\0') {
22065064Sdm199847 		*to = NULL;
22075064Sdm199847 		return (IDMAP_SUCCESS);
22085064Sdm199847 	}
22095064Sdm199847 
22105064Sdm199847 	*to = strdup(from);
22115064Sdm199847 	if (*to == NULL)
22125064Sdm199847 		return (IDMAP_ERR_MEMORY);
22135064Sdm199847 	return (IDMAP_SUCCESS);
22145064Sdm199847 }
22155064Sdm199847 
22166386Sjp151216 
22175064Sdm199847 idmap_stat
22185696Snw141292 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
22195696Snw141292 {
22205064Sdm199847 	idmap_stat retval;
22215064Sdm199847 
22226386Sjp151216 	if (to == NULL)
22236386Sjp151216 		return (IDMAP_SUCCESS);
22246386Sjp151216 
22255064Sdm199847 	(void) memcpy(to, from, sizeof (idmap_namerule));
22266386Sjp151216 	to->windomain = NULL;
22276386Sjp151216 	to->winname = NULL;
22286386Sjp151216 	to->unixname = NULL;
22295064Sdm199847 
22305064Sdm199847 	retval = idmap_strdupnull(&to->windomain, from->windomain);
22315064Sdm199847 	if (retval != IDMAP_SUCCESS)
22325064Sdm199847 		return (retval);
22335064Sdm199847 
22345064Sdm199847 	retval = idmap_strdupnull(&to->winname, from->winname);
22356386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22366386Sjp151216 		free(to->windomain);
22376386Sjp151216 		to->windomain = NULL;
22386386Sjp151216 		return (retval);
22396386Sjp151216 	}
22406386Sjp151216 
22416386Sjp151216 	retval = idmap_strdupnull(&to->unixname, from->unixname);
22426386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22436386Sjp151216 		free(to->windomain);
22446386Sjp151216 		to->windomain = NULL;
22456386Sjp151216 		free(to->winname);
22466386Sjp151216 		to->winname = NULL;
22476386Sjp151216 		return (retval);
22486386Sjp151216 	}
22496386Sjp151216 
22506386Sjp151216 	return (retval);
22516386Sjp151216 }
22526386Sjp151216 
22536386Sjp151216 
22546386Sjp151216 static
22556386Sjp151216 idmap_stat
22566386Sjp151216 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
22576386Sjp151216 {
22586386Sjp151216 	idmap_stat retval;
22596386Sjp151216 
22606386Sjp151216 	if (to == NULL)
22616386Sjp151216 		return (IDMAP_SUCCESS);
22626386Sjp151216 
22636386Sjp151216 	retval = idmap_strdupnull(&to->dn, from->dn);
22645064Sdm199847 	if (retval != IDMAP_SUCCESS)
22655064Sdm199847 		return (retval);
22665064Sdm199847 
22676386Sjp151216 	retval = idmap_strdupnull(&to->attr, from->attr);
22686386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22696386Sjp151216 		free(to->dn);
22706386Sjp151216 		to->dn = NULL;
22716386Sjp151216 		return (retval);
22726386Sjp151216 	}
22736386Sjp151216 
22746386Sjp151216 	retval = idmap_strdupnull(&to->value, from->value);
22756386Sjp151216 	if (retval != IDMAP_SUCCESS) {
22766386Sjp151216 		free(to->dn);
22776386Sjp151216 		to->dn = NULL;
22786386Sjp151216 		free(to->attr);
22796386Sjp151216 		to->attr = NULL;
22806386Sjp151216 		return (retval);
22816386Sjp151216 	}
22825064Sdm199847 
22835064Sdm199847 	return (retval);
22845064Sdm199847 }
22855064Sdm199847 
22865064Sdm199847 
22876386Sjp151216 idmap_stat
22886386Sjp151216 idmap_info_cpy(idmap_info *to, idmap_info *from)
22896386Sjp151216 {
22906386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
22916386Sjp151216 
22926386Sjp151216 	if (to == NULL)
22936386Sjp151216 		return (IDMAP_SUCCESS);
22946386Sjp151216 
22956386Sjp151216 	(void) memset(to, 0, sizeof (idmap_info));
22966386Sjp151216 
22976386Sjp151216 	to->src = from->src;
22986386Sjp151216 	to->how.map_type = from->how.map_type;
22996386Sjp151216 	switch (to->how.map_type) {
23006386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
23016386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
23026386Sjp151216 		    &from->how.idmap_how_u.ad);
23036386Sjp151216 		break;
23046386Sjp151216 
23056386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
23066386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
23076386Sjp151216 		    &from->how.idmap_how_u.nldap);
23086386Sjp151216 		break;
23096386Sjp151216 
23106386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
23116386Sjp151216 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
23126386Sjp151216 		    &from->how.idmap_how_u.rule);
23136386Sjp151216 		break;
23146386Sjp151216 
23156386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
23166386Sjp151216 		break;
23176386Sjp151216 
23186386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
23196386Sjp151216 		break;
23206386Sjp151216 
23216386Sjp151216 	case IDMAP_MAP_TYPE_KNOWN_SID:
23226386Sjp151216 		break;
23236386Sjp151216 	}
23246386Sjp151216 	return (retval);
23256386Sjp151216 }
23266386Sjp151216 
23276386Sjp151216 
23286386Sjp151216 /*
23296386Sjp151216  * This routine is similar to idmap_info_cpy, but the strings
23306386Sjp151216  * are moved from the "from" info to the "to" info.
23316386Sjp151216  * This routine is equivelent of:
23326386Sjp151216  *
23336386Sjp151216  *	idmap_info_cpy(to,from);
23346386Sjp151216  *	idmap_info_free(from);
23356386Sjp151216  */
23366386Sjp151216 idmap_stat
23376386Sjp151216 idmap_info_mov(idmap_info *to, idmap_info *from)
23386386Sjp151216 {
23396386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
23406386Sjp151216 
23416386Sjp151216 	if (to == NULL) {
23426386Sjp151216 		idmap_info_free(from);
23436386Sjp151216 		return (IDMAP_SUCCESS);
23446386Sjp151216 	}
23456386Sjp151216 	(void) memcpy(to, from, sizeof (idmap_info));
23466386Sjp151216 
23476386Sjp151216 	(void) memset(from, 0, sizeof (idmap_info));
23486386Sjp151216 
23496386Sjp151216 	return (retval);
23506386Sjp151216 }
23516386Sjp151216 
23526386Sjp151216 
23536386Sjp151216 void
23546386Sjp151216 idmap_info_free(idmap_info *info)
23556386Sjp151216 {
23566386Sjp151216 	idmap_how *how;
23576386Sjp151216 
23586386Sjp151216 	if (info == NULL)
23596386Sjp151216 		return;
23606386Sjp151216 
23616386Sjp151216 	how = &info->how;
23626386Sjp151216 	switch (how->map_type) {
23636386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
23646386Sjp151216 		free(how->idmap_how_u.ad.dn);
23656386Sjp151216 		how->idmap_how_u.ad.dn = NULL;
23666386Sjp151216 		free(how->idmap_how_u.ad.attr);
23676386Sjp151216 		how->idmap_how_u.ad.attr = NULL;
23686386Sjp151216 		free(how->idmap_how_u.ad.value);
23696386Sjp151216 		how->idmap_how_u.ad.value = NULL;
23706386Sjp151216 		break;
23716386Sjp151216 
23726386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
23736386Sjp151216 		free(how->idmap_how_u.nldap.dn);
23746386Sjp151216 		how->idmap_how_u.nldap.dn = NULL;
23756386Sjp151216 		free(how->idmap_how_u.nldap.attr);
23766386Sjp151216 		how->idmap_how_u.nldap.attr = NULL;
23776386Sjp151216 		free(how->idmap_how_u.nldap.value);
23786386Sjp151216 		how->idmap_how_u.nldap.value = NULL;
23796386Sjp151216 		break;
23806386Sjp151216 
23816386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
23826386Sjp151216 		free(how->idmap_how_u.rule.windomain);
23836386Sjp151216 		how->idmap_how_u.rule.windomain = NULL;
23846386Sjp151216 		free(how->idmap_how_u.rule.winname);
23856386Sjp151216 		how->idmap_how_u.rule.winname = NULL;
23866386Sjp151216 		free(how->idmap_how_u.rule.unixname);
23876386Sjp151216 		how->idmap_how_u.rule.unixname = NULL;
23886386Sjp151216 		break;
23896386Sjp151216 
23906386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
23916386Sjp151216 		break;
23926386Sjp151216 
23936386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
23946386Sjp151216 		break;
23956386Sjp151216 	}
23966386Sjp151216 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
23976386Sjp151216 	info->src = IDMAP_MAP_SRC_UNKNOWN;
23986386Sjp151216 }
23996386Sjp151216 
24006386Sjp151216 
24015064Sdm199847 /*
24025043Sbaban  * Get uid given Windows name
24035043Sbaban  */
24045043Sbaban idmap_stat
2405*7369SJulian.Pullen@Sun.COM idmap_getuidbywinname(const char *name, const char *domain, int flag,
2406*7369SJulian.Pullen@Sun.COM 	uid_t *uid)
24075696Snw141292 {
24085043Sbaban 	idmap_handle_t	*ih;
24095043Sbaban 	idmap_retcode	rc;
24105696Snw141292 	int		is_user = 1;
24115696Snw141292 	int		is_wuser = -1;
2412*7369SJulian.Pullen@Sun.COM 	int 		direction;
24135043Sbaban 
24145043Sbaban 	if (uid == NULL)
24155043Sbaban 		return (IDMAP_ERR_ARG);
24165043Sbaban 
2417*7369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2418*7369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_uidbywinname(name, domain, uid);
2419*7369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
2420*7369SJulian.Pullen@Sun.COM 			return (rc);
2421*7369SJulian.Pullen@Sun.COM 	}
24225043Sbaban 	/* Get mapping */
24235043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
24245043Sbaban 		return (rc);
2425*7369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
2426*7369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
24275043Sbaban 	(void) idmap_fini(ih);
24285043Sbaban 
2429*7369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
2430*7369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store UID to winname */
2431*7369SJulian.Pullen@Sun.COM 		if (domain == NULL)
2432*7369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
2433*7369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2uid(name, domain, *uid, direction);
2434*7369SJulian.Pullen@Sun.COM 	}
2435*7369SJulian.Pullen@Sun.COM 
24365043Sbaban 	return (rc);
24375043Sbaban }
24385043Sbaban 
24395043Sbaban 
24405043Sbaban /*
24415043Sbaban  * Get gid given Windows name
24425043Sbaban  */
24435043Sbaban idmap_stat
2444*7369SJulian.Pullen@Sun.COM idmap_getgidbywinname(const char *name, const char *domain, int flag,
2445*7369SJulian.Pullen@Sun.COM 	gid_t *gid)
24465696Snw141292 {
24475043Sbaban 	idmap_handle_t	*ih;
24485043Sbaban 	idmap_retcode	rc;
24495696Snw141292 	int		is_user = 0;
24505696Snw141292 	int		is_wuser = -1;
2451*7369SJulian.Pullen@Sun.COM 	int		direction;
24525043Sbaban 
24535043Sbaban 	if (gid == NULL)
24545043Sbaban 		return (IDMAP_ERR_ARG);
24555043Sbaban 
2456*7369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2457*7369SJulian.Pullen@Sun.COM 		rc = idmap_cache_lookup_gidbywinname(name, domain, gid);
2458*7369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
2459*7369SJulian.Pullen@Sun.COM 			return (rc);
2460*7369SJulian.Pullen@Sun.COM 	}
2461*7369SJulian.Pullen@Sun.COM 
24625043Sbaban 	/* Get mapping */
24635043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
24645043Sbaban 		return (rc);
2465*7369SJulian.Pullen@Sun.COM 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
2466*7369SJulian.Pullen@Sun.COM 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
24675043Sbaban 	(void) idmap_fini(ih);
24685043Sbaban 
2469*7369SJulian.Pullen@Sun.COM 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
2470*7369SJulian.Pullen@Sun.COM 		/* If we have not got the domain don't store GID to winname */
2471*7369SJulian.Pullen@Sun.COM 		if (domain == NULL)
2472*7369SJulian.Pullen@Sun.COM 			direction = IDMAP_DIRECTION_W2U;
2473*7369SJulian.Pullen@Sun.COM 		idmap_cache_add_winname2gid(name, domain, *gid, direction);
2474*7369SJulian.Pullen@Sun.COM 	}
2475*7369SJulian.Pullen@Sun.COM 
24765043Sbaban 	return (rc);
24775043Sbaban }
24785043Sbaban 
24795043Sbaban 
24805043Sbaban /*
24815043Sbaban  * Get winname given pid
24825043Sbaban  */
24835043Sbaban static idmap_retcode
2484*7369SJulian.Pullen@Sun.COM idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
2485*7369SJulian.Pullen@Sun.COM 	char **domain)
24865696Snw141292 {
24875043Sbaban 	idmap_handle_t	*ih;
24885043Sbaban 	idmap_retcode	rc;
24895043Sbaban 	int		len;
24905043Sbaban 	char		*winname, *windomain;
2491*7369SJulian.Pullen@Sun.COM 	int		direction;
24925043Sbaban 
24935043Sbaban 	if (name == NULL)
24945043Sbaban 		return (IDMAP_ERR_ARG);
24955043Sbaban 
2496*7369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2497*7369SJulian.Pullen@Sun.COM 		if (is_user)
2498*7369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebyuid(&winname,
2499*7369SJulian.Pullen@Sun.COM 			    &windomain, pid);
2500*7369SJulian.Pullen@Sun.COM 		else
2501*7369SJulian.Pullen@Sun.COM 			rc = idmap_cache_lookup_winnamebygid(&winname,
2502*7369SJulian.Pullen@Sun.COM 			    &windomain, pid);
2503*7369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_SUCCESS)
2504*7369SJulian.Pullen@Sun.COM 			goto out;
2505*7369SJulian.Pullen@Sun.COM 		if (rc == IDMAP_ERR_MEMORY)
2506*7369SJulian.Pullen@Sun.COM 			return (rc);
2507*7369SJulian.Pullen@Sun.COM 	}
2508*7369SJulian.Pullen@Sun.COM 
25095043Sbaban 	/* Get mapping */
25105043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
25115043Sbaban 		return (rc);
2512*7369SJulian.Pullen@Sun.COM 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
2513*7369SJulian.Pullen@Sun.COM 	    NULL, NULL, &winname, &windomain, &direction, NULL);
25145043Sbaban 	(void) idmap_fini(ih);
25155043Sbaban 
25165043Sbaban 	/* Return on error */
25175043Sbaban 	if (rc != IDMAP_SUCCESS)
25185043Sbaban 		return (rc);
25195043Sbaban 
25205043Sbaban 	/*
25215043Sbaban 	 * The given PID may have been mapped to a locally
25225043Sbaban 	 * generated SID in which case there isn't any
25235043Sbaban 	 * Windows name
25245043Sbaban 	 */
25255043Sbaban 	if (winname == NULL || windomain == NULL) {
25265043Sbaban 		idmap_free(winname);
25275043Sbaban 		idmap_free(windomain);
25285043Sbaban 		return (IDMAP_ERR_NORESULT);
25295043Sbaban 	}
25305043Sbaban 
2531*7369SJulian.Pullen@Sun.COM 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2532*7369SJulian.Pullen@Sun.COM 		if (is_user)
2533*7369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2uid(winname, windomain,
2534*7369SJulian.Pullen@Sun.COM 			    pid, direction);
2535*7369SJulian.Pullen@Sun.COM 		else
2536*7369SJulian.Pullen@Sun.COM 			idmap_cache_add_winname2gid(winname, windomain,
2537*7369SJulian.Pullen@Sun.COM 			    pid, direction);
2538*7369SJulian.Pullen@Sun.COM 	}
2539*7369SJulian.Pullen@Sun.COM 
2540*7369SJulian.Pullen@Sun.COM out:
25415043Sbaban 	if (domain != NULL) {
25425043Sbaban 		*name = winname;
25435043Sbaban 		*domain = windomain;
25445043Sbaban 	} else {
25455043Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
25465043Sbaban 		if ((*name = malloc(len)) != NULL)
25475043Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
25485043Sbaban 			    windomain);
25495043Sbaban 		else
25505043Sbaban 			rc = IDMAP_ERR_MEMORY;
25515043Sbaban 		idmap_free(winname);
25525043Sbaban 		idmap_free(windomain);
25535043Sbaban 	}
2554*7369SJulian.Pullen@Sun.COM 
25555043Sbaban 	return (rc);
25565043Sbaban }
25575043Sbaban 
25585043Sbaban 
25595043Sbaban /*
25605043Sbaban  * Get winname given uid
25615043Sbaban  */
25625043Sbaban idmap_stat
2563*7369SJulian.Pullen@Sun.COM idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain)
25645696Snw141292 {
2565*7369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(uid, 1, flag, name, domain));
25665043Sbaban }
25675043Sbaban 
25685043Sbaban 
25695043Sbaban /*
25705043Sbaban  * Get winname given gid
25715043Sbaban  */
25725043Sbaban idmap_stat
2573*7369SJulian.Pullen@Sun.COM idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain)
25745696Snw141292 {
2575*7369SJulian.Pullen@Sun.COM 	return (idmap_getwinnamebypid(gid, 0, flag, name, domain));
25765043Sbaban }
25776616Sdm199847 
25786616Sdm199847 
25796616Sdm199847 /* printflike */
25806616Sdm199847 void
25816616Sdm199847 idmapdlog(int pri, const char *format, ...) {
25826616Sdm199847 	va_list args;
25836616Sdm199847 
25846616Sdm199847 	va_start(args, format);
25856616Sdm199847 	if (pri <= logstate.max_pri) {
25866616Sdm199847 		(void) vfprintf(stderr, format, args);
25876616Sdm199847 		(void) fprintf(stderr, "\n");
25886616Sdm199847 	}
25896616Sdm199847 
25906616Sdm199847 	/*
25916616Sdm199847 	 * We don't want to fill up the logs with useless messages when
25926616Sdm199847 	 * we're degraded, but we still want to log.
25936616Sdm199847 	 */
25946616Sdm199847 	if (logstate.degraded)
25956616Sdm199847 		pri = LOG_DEBUG;
25966616Sdm199847 
25976616Sdm199847 	if (logstate.write_syslog)
25986616Sdm199847 		(void) vsyslog(pri, format, args);
25996616Sdm199847 	va_end(args);
26006616Sdm199847 }
26016616Sdm199847 
26026616Sdm199847 void
26036616Sdm199847 idmap_log_stderr(int pri)
26046616Sdm199847 {
26056616Sdm199847 	logstate.max_pri = pri;
26066616Sdm199847 }
26076616Sdm199847 
26086616Sdm199847 void
26096616Sdm199847 idmap_log_syslog(bool_t what)
26106616Sdm199847 {
26116616Sdm199847 	logstate.write_syslog = what;
26126616Sdm199847 }
26136616Sdm199847 
26146616Sdm199847 void
26156616Sdm199847 idmap_log_degraded(bool_t what)
26166616Sdm199847 {
26176616Sdm199847 	logstate.degraded = what;
26186616Sdm199847 }
2619