14520Snw141292 /*
24520Snw141292  * CDDL HEADER START
34520Snw141292  *
44520Snw141292  * The contents of this file are subject to the terms of the
54520Snw141292  * Common Development and Distribution License (the "License").
64520Snw141292  * You may not use this file except in compliance with the License.
74520Snw141292  *
84520Snw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94520Snw141292  * or http://www.opensolaris.org/os/licensing.
104520Snw141292  * See the License for the specific language governing permissions
114520Snw141292  * and limitations under the License.
124520Snw141292  *
134520Snw141292  * When distributing Covered Code, include this CDDL HEADER in each
144520Snw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154520Snw141292  * If applicable, add the following below this CDDL HEADER, with the
164520Snw141292  * fields enclosed by brackets "[]" replaced with your own identifying
174520Snw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
184520Snw141292  *
194520Snw141292  * CDDL HEADER END
204520Snw141292  */
214520Snw141292 /*
224520Snw141292  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
234520Snw141292  * Use is subject to license terms.
244520Snw141292  */
254520Snw141292 
264520Snw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
274520Snw141292 
284520Snw141292 /*
294520Snw141292  * libidmap API
304520Snw141292  */
314520Snw141292 
324520Snw141292 #include <stdlib.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>
42*5232Snw141292 #include <ucontext.h>
434520Snw141292 #include "idmap_impl.h"
444520Snw141292 
454520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
464520Snw141292 
474520Snw141292 static int idmap_stat2errno(idmap_stat);
485064Sdm199847 static idmap_stat idmap_strdupnull(char **, const char *);
494520Snw141292 
504520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
514520Snw141292 	if (handl == NULL) {\
524520Snw141292 		errno = EINVAL;\
534520Snw141292 		return (IDMAP_ERR_ARG);\
544520Snw141292 	}\
554520Snw141292 	itera = calloc(1, sizeof (*itera));\
564520Snw141292 	if (itera == NULL) {\
574520Snw141292 		errno = ENOMEM;\
584520Snw141292 		return (IDMAP_ERR_MEMORY);\
594520Snw141292 	}\
604520Snw141292 	argu = calloc(1, sizeof (*argu));\
614520Snw141292 	if (argu == NULL) {\
624520Snw141292 		free(itera);\
634520Snw141292 		errno = ENOMEM;\
644520Snw141292 		return (IDMAP_ERR_MEMORY);\
654520Snw141292 	}\
664520Snw141292 	itera->ih = handl;\
674520Snw141292 	itera->type = ityp;\
684520Snw141292 	itera->retcode = IDMAP_NEXT;\
694520Snw141292 	itera->limit = 1024;\
704520Snw141292 	itera->arg = argu;
714520Snw141292 
724520Snw141292 
734520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
744520Snw141292 	if (argu) {\
754520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
764520Snw141292 		free(argu);\
774520Snw141292 	}\
784520Snw141292 	if (itera)\
794520Snw141292 		free(itera);\
804520Snw141292 	return (iretcod);
814520Snw141292 
824520Snw141292 
834520Snw141292 #define	__ITER_CHECK(itera, ityp)\
844520Snw141292 	if (itera == NULL) {\
854520Snw141292 		errno = EINVAL;\
864520Snw141292 		return (IDMAP_ERR_ARG);\
874520Snw141292 	}\
884520Snw141292 	if (itera->type != ityp) {\
894520Snw141292 		errno = EINVAL;\
904520Snw141292 		return (IDMAP_ERR_ARG);\
914520Snw141292 	}
924520Snw141292 
935064Sdm199847 #define	EMPTY_STRING(str)	(str == NULL || *str == '\0')
944520Snw141292 
954520Snw141292 /*
964520Snw141292  * Free memory allocated by libidmap API
974520Snw141292  *
984520Snw141292  * Input:
994520Snw141292  * ptr - memory to be freed
1004520Snw141292  */
1014520Snw141292 void
1024520Snw141292 idmap_free(void *ptr) {
1034520Snw141292 	free(ptr);
1044520Snw141292 }
1054520Snw141292 
1064520Snw141292 
107*5232Snw141292 #define	MIN_STACK_NEEDS	16384
108*5232Snw141292 
1094520Snw141292 /*
1104520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1114520Snw141292  *
1124520Snw141292  * Output:
1134520Snw141292  * handle - idmap handle
1144520Snw141292  */
1154520Snw141292 idmap_stat
1164520Snw141292 idmap_init(idmap_handle_t **handle) {
1174520Snw141292 	CLIENT			*clnt = NULL;
1184520Snw141292 	struct idmap_handle	*hptr;
119*5232Snw141292 	uint_t			sendsz = 0;
120*5232Snw141292 	stack_t			st;
1214520Snw141292 
1224520Snw141292 	*handle = NULL;
1234520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1244520Snw141292 	if (hptr == NULL)
1254520Snw141292 		return (IDMAP_ERR_MEMORY);
1264520Snw141292 
127*5232Snw141292 	/*
128*5232Snw141292 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
129*5232Snw141292 	 * the call args buffer and once for the call result buffer), so
130*5232Snw141292 	 * we want to pick a sendsz that will be large enough, but not
131*5232Snw141292 	 * too large.
132*5232Snw141292 	 */
133*5232Snw141292 	if (stack_getbounds(&st) == 0) {
134*5232Snw141292 		/*
135*5232Snw141292 		 * Estimate how much stack space is left;
136*5232Snw141292 		 * st.ss_sp is the top of stack.
137*5232Snw141292 		 */
138*5232Snw141292 		if ((char *)&sendsz < (char *)st.ss_sp)
139*5232Snw141292 			/* stack grows up */
140*5232Snw141292 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
141*5232Snw141292 		else
142*5232Snw141292 			/* stack grows down */
143*5232Snw141292 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
144*5232Snw141292 
145*5232Snw141292 		/*
146*5232Snw141292 		 * Take much of the stack space left, divided by two,
147*5232Snw141292 		 * but leave enough for our needs (just a guess!), and
148*5232Snw141292 		 * if we can't, then roll the dice.
149*5232Snw141292 		 */
150*5232Snw141292 		sendsz = RNDUP(sendsz / 2);
151*5232Snw141292 		if (sendsz < MIN_STACK_NEEDS)
152*5232Snw141292 			sendsz = 0;	/* RPC call may fail */
153*5232Snw141292 		else if (sendsz > IDMAP_MAX_DOOR_RPC)
154*5232Snw141292 			sendsz = IDMAP_MAX_DOOR_RPC;
155*5232Snw141292 	}
156*5232Snw141292 
157*5232Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
1584520Snw141292 	if (clnt == NULL) {
1594520Snw141292 		free(hptr);
1604520Snw141292 		return (IDMAP_ERR_RPC);
1614520Snw141292 	}
1624520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1634520Snw141292 	hptr->privhandle = clnt;
1644520Snw141292 	*handle = hptr;
1654520Snw141292 	return (IDMAP_SUCCESS);
1664520Snw141292 }
1674520Snw141292 
1684520Snw141292 
1694520Snw141292 /*
1704520Snw141292  * Finalize idmap handle
1714520Snw141292  *
1724520Snw141292  * Input:
1734520Snw141292  * handle - idmap handle
1744520Snw141292  */
1754520Snw141292 idmap_stat
1764520Snw141292 idmap_fini(idmap_handle_t *handle) {
1774520Snw141292 	CLIENT			*clnt;
1784520Snw141292 	struct idmap_handle	*hptr;
1794520Snw141292 
1804520Snw141292 	if (handle == NULL)
1814520Snw141292 		return (IDMAP_SUCCESS);
1824520Snw141292 
1834520Snw141292 	hptr = (struct idmap_handle *)handle;
1844520Snw141292 
1854520Snw141292 	switch (hptr->type) {
1864520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
1874520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
1884520Snw141292 		if (clnt) {
1894520Snw141292 			if (clnt->cl_auth)
1904520Snw141292 				auth_destroy(clnt->cl_auth);
1914520Snw141292 			clnt_destroy(clnt);
1924520Snw141292 		}
1934520Snw141292 		break;
1944520Snw141292 	default:
1954520Snw141292 		break;
1964520Snw141292 	}
1974520Snw141292 	free(hptr);
1984520Snw141292 	return (IDMAP_SUCCESS);
1994520Snw141292 }
2004520Snw141292 
2014520Snw141292 
2024520Snw141292 
2034520Snw141292 /*
2044520Snw141292  * Create/Initialize handle for updates
2054520Snw141292  *
2064520Snw141292  * Output:
2074520Snw141292  * udthandle - update handle
2084520Snw141292  */
2094520Snw141292 idmap_stat
2104520Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) {
2114520Snw141292 	idmap_udt_handle_t	*tmp;
2124520Snw141292 
2134520Snw141292 	if (handle == NULL || udthandle == NULL) {
2144520Snw141292 		errno = EINVAL;
2154520Snw141292 		return (IDMAP_ERR_ARG);
2164520Snw141292 	}
2174520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
2184520Snw141292 		errno = ENOMEM;
2194520Snw141292 		return (IDMAP_ERR_MEMORY);
2204520Snw141292 	}
2214520Snw141292 
2224520Snw141292 	tmp->ih = handle;
2234520Snw141292 	*udthandle = tmp;
2244520Snw141292 	return (IDMAP_SUCCESS);
2254520Snw141292 }
2264520Snw141292 
2274520Snw141292 
2284520Snw141292 /*
2294520Snw141292  * All the updates specified by the update handle are committed
2304520Snw141292  * in a single transaction. i.e either all succeed or none.
2314520Snw141292  *
2324520Snw141292  * Input:
2334520Snw141292  * udthandle - update handle with the update requests
2344520Snw141292  *
2354520Snw141292  * Return value:
2364520Snw141292  * Status of the commit
2374520Snw141292  */
2384520Snw141292 idmap_stat
2394520Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle) {
2404520Snw141292 	CLIENT			*clnt;
2414520Snw141292 	enum clnt_stat		clntstat;
2425064Sdm199847 	idmap_update_res	res;
2435064Sdm199847 	idmap_stat		retcode;
2444520Snw141292 
2454520Snw141292 	if (udthandle == NULL) {
2464520Snw141292 		errno = EINVAL;
2474520Snw141292 		return (IDMAP_ERR_ARG);
2484520Snw141292 	}
2495064Sdm199847 
2505064Sdm199847 	(void) memset(&res, 0, sizeof (res));
2515064Sdm199847 
2524520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
2534520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
2544520Snw141292 		(xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
2555064Sdm199847 		(xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
2564520Snw141292 		TIMEOUT);
2574644Sbaban 
2585064Sdm199847 	if (clntstat != RPC_SUCCESS) {
2595064Sdm199847 		retcode = _idmap_rpc2stat(clnt);
2605064Sdm199847 		goto out;
2615064Sdm199847 	}
2625064Sdm199847 
2635064Sdm199847 	retcode = udthandle->commit_stat = res.retcode;
2645064Sdm199847 	udthandle->error_index = res.error_index;
2655064Sdm199847 
2665064Sdm199847 	if (retcode != IDMAP_SUCCESS) {
2675064Sdm199847 
2685064Sdm199847 		if (udthandle->error_index < 0)
2695064Sdm199847 			goto out;
2705064Sdm199847 
2715064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
2725064Sdm199847 		    &res.error_rule);
2735064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
2745064Sdm199847 			udthandle->error_index = -2;
2755064Sdm199847 			goto out;
2765064Sdm199847 		}
2775064Sdm199847 
2785064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
2795064Sdm199847 		    &res.conflict_rule);
2805064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
2815064Sdm199847 			udthandle->error_index = -2;
2825064Sdm199847 			goto out;
2835064Sdm199847 		}
2845064Sdm199847 	}
2855064Sdm199847 
2865064Sdm199847 	retcode = res.retcode;
2875064Sdm199847 
2885064Sdm199847 
2895064Sdm199847 out:
2904644Sbaban 	/* reset handle so that it can be used again */
2915064Sdm199847 	if (retcode == IDMAP_SUCCESS) {
2925064Sdm199847 		_IDMAP_RESET_UDT_HANDLE(udthandle);
2935064Sdm199847 	}
2945064Sdm199847 
2955064Sdm199847 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
2965064Sdm199847 	errno = idmap_stat2errno(retcode);
2975064Sdm199847 	return (retcode);
2985064Sdm199847 }
2995064Sdm199847 
3005064Sdm199847 
3015064Sdm199847 static void
3025064Sdm199847 idmap_namerule_parts_clear(char **windomain, char **winname,
3035064Sdm199847     char **unixname, boolean_t *is_user, boolean_t *is_nt4,
3045064Sdm199847     int *direction) {
3055064Sdm199847 	if (windomain)
3065064Sdm199847 		*windomain = NULL;
3075064Sdm199847 	if (winname)
3085064Sdm199847 		*winname = NULL;
3095064Sdm199847 	if (unixname)
3105064Sdm199847 		*unixname = NULL;
3115064Sdm199847 
3125064Sdm199847 	if (is_nt4)
3135064Sdm199847 		*is_nt4 = 0;
3145064Sdm199847 	if (is_user)
3155064Sdm199847 		*is_user = -1;
3165064Sdm199847 	if (direction)
3175064Sdm199847 		*direction = IDMAP_DIRECTION_UNDEF;
3185064Sdm199847 }
3195064Sdm199847 
3205064Sdm199847 static idmap_stat
3215064Sdm199847 idmap_namerule2parts(idmap_namerule	*rule,
3225064Sdm199847     char **windomain, char **winname,
3235064Sdm199847     char **unixname, boolean_t *is_user, boolean_t *is_nt4,
3245064Sdm199847     int *direction) {
3255064Sdm199847 	idmap_stat retcode;
3265064Sdm199847 
3275064Sdm199847 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
3285064Sdm199847 		return (IDMAP_ERR_NORESULT);
3295064Sdm199847 
3305064Sdm199847 
3315064Sdm199847 	retcode = idmap_strdupnull(windomain, rule->windomain);
3325064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3335064Sdm199847 		goto errout;
3345064Sdm199847 
3355064Sdm199847 	retcode = idmap_strdupnull(winname, rule->winname);
3365064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3375064Sdm199847 		goto errout;
3385064Sdm199847 
3395064Sdm199847 	retcode = idmap_strdupnull(unixname, rule->unixname);
3405064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3415064Sdm199847 		goto errout;
3425064Sdm199847 
3435064Sdm199847 
3445064Sdm199847 	if (is_user)
3455064Sdm199847 		*is_user = rule->is_user;
3465064Sdm199847 	if (is_nt4)
3475064Sdm199847 		*is_nt4 = rule->is_nt4;
3485064Sdm199847 	if (direction)
3495064Sdm199847 		*direction = rule->direction;
3505064Sdm199847 
3515064Sdm199847 
3525064Sdm199847 	return (IDMAP_SUCCESS);
3534644Sbaban 
3545064Sdm199847 errout:
3555064Sdm199847 	if (windomain && *windomain)
3565064Sdm199847 		free(*windomain);
3575064Sdm199847 	if (winname && *winname)
3585064Sdm199847 		free(*winname);
3595064Sdm199847 	if (unixname && *unixname)
3605064Sdm199847 		free(*unixname);
3615064Sdm199847 
3625064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
3635064Sdm199847 	    unixname, is_user, is_nt4, direction);
3645064Sdm199847 
3654520Snw141292 	return (retcode);
3665064Sdm199847 
3675064Sdm199847 }
3685064Sdm199847 
3695064Sdm199847 /*
3705064Sdm199847  * Retrieve the index of the failed batch element. error_index == -1
3715064Sdm199847  * indicates failure at the beginning, -2 at the end.
3725064Sdm199847  *
3735064Sdm199847  * If idmap_udt_commit didn't return error, the returned value is undefined.
3745064Sdm199847  *
3755064Sdm199847  * Return value:
3765064Sdm199847  * IDMAP_SUCCESS
3775064Sdm199847  */
3785064Sdm199847 
3795064Sdm199847 idmap_stat
3805064Sdm199847 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
3815064Sdm199847     int64_t *error_index) {
3825064Sdm199847 	if (error_index)
3835064Sdm199847 		*error_index = udthandle->error_index;
3845064Sdm199847 
3855064Sdm199847 	return (IDMAP_SUCCESS);
3865064Sdm199847 }
3875064Sdm199847 
3885064Sdm199847 
3895064Sdm199847 /*
3905064Sdm199847  * Retrieve the rule which caused the batch to fail. If
3915064Sdm199847  * idmap_udt_commit didn't return error or if error_index is < 0, the
3925064Sdm199847  * retrieved rule is undefined.
3935064Sdm199847  *
3945064Sdm199847  * Return value:
3955064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
3965064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
3975064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
3985064Sdm199847  */
3995064Sdm199847 
4005064Sdm199847 idmap_stat
4015064Sdm199847 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
4025064Sdm199847     char **windomain, char **winname,
4035064Sdm199847     char **unixname, boolean_t *is_user, boolean_t *is_nt4,
4045064Sdm199847     int *direction) {
4055064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4065064Sdm199847 	    unixname, is_user, is_nt4, direction);
4075064Sdm199847 
4085064Sdm199847 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
4095064Sdm199847 	    udthandle->error_index < 0)
4105064Sdm199847 		return (IDMAP_ERR_NORESULT);
4115064Sdm199847 
4125064Sdm199847 	return (idmap_namerule2parts(
4135064Sdm199847 			&udthandle->error_rule,
4145064Sdm199847 			    windomain,
4155064Sdm199847 			    winname,
4165064Sdm199847 			    unixname,
4175064Sdm199847 			    is_user,
4185064Sdm199847 			    is_nt4,
4195064Sdm199847 			    direction));
4205064Sdm199847 }
4215064Sdm199847 
4225064Sdm199847 /*
4235064Sdm199847  * Retrieve the rule with which there was a conflict. TODO: retrieve
4245064Sdm199847  * the value.
4255064Sdm199847  *
4265064Sdm199847  * Return value:
4275064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
4285064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
4295064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
4305064Sdm199847  */
4315064Sdm199847 
4325064Sdm199847 idmap_stat
4335064Sdm199847 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
4345064Sdm199847     char **windomain, char **winname,
4355064Sdm199847     char **unixname, boolean_t *is_user, boolean_t *is_nt4,
4365064Sdm199847     int *direction) {
4375064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4385064Sdm199847 	    unixname, is_user, is_nt4, direction);
4395064Sdm199847 
4405064Sdm199847 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
4415064Sdm199847 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
4425064Sdm199847 		    return (IDMAP_ERR_NORESULT);
4435064Sdm199847 	}
4445064Sdm199847 
4455064Sdm199847 	return (idmap_namerule2parts(
4465064Sdm199847 			&udthandle->conflict_rule,
4475064Sdm199847 			    windomain,
4485064Sdm199847 			    winname,
4495064Sdm199847 			    unixname,
4505064Sdm199847 			    is_user,
4515064Sdm199847 			    is_nt4,
4525064Sdm199847 			    direction));
4534520Snw141292 }
4544520Snw141292 
4554520Snw141292 
4564520Snw141292 /*
4574520Snw141292  * Destroy the update handle
4584520Snw141292  */
4594520Snw141292 void
4604520Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle) {
4614520Snw141292 	if (udthandle == NULL)
4624520Snw141292 		return;
4634520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
4645064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
4655064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
4664520Snw141292 	free(udthandle);
4674520Snw141292 }
4684520Snw141292 
4694520Snw141292 
4704520Snw141292 idmap_stat
4714520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
4724520Snw141292 		boolean_t is_user, const char *winname, const char *unixname,
4734520Snw141292 		boolean_t is_nt4, int direction) {
4744520Snw141292 	idmap_retcode	retcode;
4754644Sbaban 	idmap_namerule	*rule = NULL;
4764520Snw141292 
4774644Sbaban 	retcode = _udt_extend_batch(udthandle);
4784520Snw141292 	if (retcode != IDMAP_SUCCESS)
4794520Snw141292 		goto errout;
4804520Snw141292 
4814520Snw141292 	rule = &udthandle->batch.
4824520Snw141292 		idmap_update_batch_val[udthandle->next].
4834520Snw141292 		idmap_update_op_u.rule;
4844520Snw141292 	rule->is_user = is_user;
4854520Snw141292 	rule->direction = direction;
4864520Snw141292 	rule->is_nt4 = is_nt4;
4875064Sdm199847 
4885064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
4895064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4905064Sdm199847 		goto errout;
4915064Sdm199847 
4925064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
4935064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4945064Sdm199847 		goto errout;
4955064Sdm199847 
4965064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
4975064Sdm199847 	if (retcode != IDMAP_SUCCESS)
4985064Sdm199847 		goto errout;
4994644Sbaban 
5004644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5014644Sbaban 	    OP_ADD_NAMERULE;
5024520Snw141292 	udthandle->next++;
5034520Snw141292 	return (IDMAP_SUCCESS);
5044520Snw141292 
5054520Snw141292 errout:
5064644Sbaban 	/* The batch should still be usable */
5074644Sbaban 	if (rule)
5084644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5094520Snw141292 	errno = idmap_stat2errno(retcode);
5104520Snw141292 	return (retcode);
5114520Snw141292 }
5124520Snw141292 
5134520Snw141292 
5144520Snw141292 /* ARGSUSED */
5154520Snw141292 idmap_stat
5164520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
5174520Snw141292 		const char *windomain, const char *winname,
5184520Snw141292 		const char *unixname, int direction) {
5194520Snw141292 	idmap_retcode	retcode;
5204644Sbaban 	idmap_namerule	*rule = NULL;
5214520Snw141292 
5224644Sbaban 	retcode = _udt_extend_batch(udthandle);
5234520Snw141292 	if (retcode != IDMAP_SUCCESS)
5244520Snw141292 		goto errout;
5254520Snw141292 
5264520Snw141292 	rule = &udthandle->batch.
5274520Snw141292 		idmap_update_batch_val[udthandle->next].
5284520Snw141292 		idmap_update_op_u.rule;
5294520Snw141292 	rule->is_user = is_user;
5304520Snw141292 	rule->direction = direction;
5315064Sdm199847 
5325064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
5335064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5345064Sdm199847 		goto errout;
5355064Sdm199847 
5365064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
5375064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5385064Sdm199847 		goto errout;
5395064Sdm199847 
5405064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
5415064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5425064Sdm199847 		goto errout;
5435064Sdm199847 
5444644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5454644Sbaban 	    OP_RM_NAMERULE;
5464520Snw141292 	udthandle->next++;
5474520Snw141292 	return (IDMAP_SUCCESS);
5484520Snw141292 
5494520Snw141292 errout:
5504644Sbaban 	if (rule)
5514644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5524520Snw141292 	errno = idmap_stat2errno(retcode);
5534520Snw141292 	return (retcode);
5544520Snw141292 }
5554520Snw141292 
5564520Snw141292 
5574520Snw141292 /* ARGSUSED */
5584520Snw141292 idmap_stat
5594520Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle, boolean_t is_user) {
5604520Snw141292 	idmap_retcode	retcode;
5614520Snw141292 
5624644Sbaban 	retcode = _udt_extend_batch(udthandle);
5634520Snw141292 	if (retcode != IDMAP_SUCCESS)
5644520Snw141292 		goto errout;
5654520Snw141292 
5664520Snw141292 	udthandle->batch.idmap_update_batch_val[udthandle->next].
5674520Snw141292 		idmap_update_op_u.is_user = is_user;
5684520Snw141292 
5694644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5704644Sbaban 	    OP_FLUSH_NAMERULES;
5714520Snw141292 	udthandle->next++;
5724520Snw141292 	return (IDMAP_SUCCESS);
5734520Snw141292 
5744520Snw141292 errout:
5754520Snw141292 	errno = idmap_stat2errno(retcode);
5764520Snw141292 	return (retcode);
5774520Snw141292 }
5784520Snw141292 
5794520Snw141292 
5804520Snw141292 /*
5814520Snw141292  * Set the number of entries requested per batch by the iterator
5824520Snw141292  *
5834520Snw141292  * Input:
5844520Snw141292  * iter  - iterator
5854520Snw141292  * limit - number of entries requested per batch
5864520Snw141292  */
5874520Snw141292 idmap_stat
5884520Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) {
5894520Snw141292 	if (iter == NULL) {
5904520Snw141292 		errno = EINVAL;
5914520Snw141292 		return (IDMAP_ERR_ARG);
5924520Snw141292 	}
5934520Snw141292 	iter->limit = limit;
5944520Snw141292 	return (IDMAP_SUCCESS);
5954520Snw141292 }
5964520Snw141292 
5974520Snw141292 
5984520Snw141292 /*
5994520Snw141292  * Create iterator to get name-based mapping rules
6004520Snw141292  *
6014520Snw141292  * Input:
6024520Snw141292  * windomain - Windows domain
6034520Snw141292  * is_user   - user or group rules
6044520Snw141292  * winname   - Windows user or group name
6054520Snw141292  * unixname  - Unix user or group name
6064520Snw141292  *
6074520Snw141292  * Output:
6084520Snw141292  * iter - iterator
6094520Snw141292  */
6104520Snw141292 idmap_stat
6114520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
6124520Snw141292 		boolean_t is_user, const char *winname,
6134520Snw141292 		const char *unixname, idmap_iter_t **iter) {
6144520Snw141292 
6154520Snw141292 	idmap_iter_t			*tmpiter;
6164520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
6174520Snw141292 	idmap_namerule			*rule;
6184520Snw141292 	idmap_retcode			retcode;
6194520Snw141292 
6204520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
6214520Snw141292 
6224520Snw141292 	rule = &arg->rule;
6234520Snw141292 	rule->is_user = is_user;
6244644Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
6255064Sdm199847 
6265064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6275064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6285064Sdm199847 		goto errout;
6295064Sdm199847 
6305064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
6315064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6325064Sdm199847 		goto errout;
6335064Sdm199847 
6345064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6355064Sdm199847 	if (retcode != IDMAP_SUCCESS)
6365064Sdm199847 		goto errout;
6374520Snw141292 
6384520Snw141292 	*iter = tmpiter;
6394520Snw141292 	return (IDMAP_SUCCESS);
6404520Snw141292 
6414520Snw141292 errout:
6424520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
6434520Snw141292 		xdr_idmap_list_namerules_1_argument, retcode);
6444520Snw141292 }
6454520Snw141292 
6464520Snw141292 
6474520Snw141292 /*
6484520Snw141292  * Iterate through the name-based mapping rules
6494520Snw141292  *
6504520Snw141292  * Input:
6514520Snw141292  * iter - iterator
6524520Snw141292  *
6534520Snw141292  * Output:
6544520Snw141292  * windomain - Windows domain
6554520Snw141292  * winname   - Windows user or group name
6564520Snw141292  * unixname  - Unix user or group name
6574520Snw141292  * is_nt4    - NT4 or AD
6584520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
6594520Snw141292  *
6604520Snw141292  * Return value:
6614520Snw141292  * 0   - done
6624520Snw141292  * 1   - more results available
6634520Snw141292  * < 0 - error
6644520Snw141292  */
6654520Snw141292 idmap_stat
6664520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
6674520Snw141292 		char **winname, char **unixname, boolean_t *is_nt4,
6684520Snw141292 		int *direction) {
6694520Snw141292 	idmap_namerules_res		*namerules;
6704520Snw141292 	idmap_list_namerules_1_argument	*arg;
6714520Snw141292 	idmap_retcode			retcode;
6724520Snw141292 
6734520Snw141292 	if (windomain)
6744520Snw141292 		*windomain = NULL;
6754520Snw141292 	if (winname)
6764520Snw141292 		*winname = NULL;
6774520Snw141292 	if (unixname)
6784520Snw141292 		*unixname = NULL;
6794520Snw141292 	if (is_nt4)
6804520Snw141292 		*is_nt4 = 0;
6814520Snw141292 	if (direction)
6824644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
6834520Snw141292 
6844520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
6854520Snw141292 
6864520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
6874520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
6884520Snw141292 			iter->next >= namerules->rules.rules_len)) {
6894520Snw141292 
6904520Snw141292 		if ((arg = iter->arg) == NULL) {
6914520Snw141292 			errno = EINVAL;
6924520Snw141292 			return (IDMAP_ERR_ARG);
6934520Snw141292 		}
6944520Snw141292 		arg->limit = iter->limit;
6954520Snw141292 
6964520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
6974520Snw141292 			iter, arg,
6984520Snw141292 			(uchar_t **)&namerules, sizeof (*namerules),
6994520Snw141292 			(xdrproc_t)xdr_idmap_list_namerules_1_argument,
7004520Snw141292 			(xdrproc_t)xdr_idmap_namerules_res);
7014520Snw141292 		if (retcode != IDMAP_SUCCESS)
7024520Snw141292 			return (retcode);
7034520Snw141292 
7044520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
7054520Snw141292 			retcode  = namerules->retcode;
7064520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
7074520Snw141292 			free(namerules);
7084520Snw141292 			iter->retlist = NULL;
7094520Snw141292 			return (retcode);
7104520Snw141292 		}
7114520Snw141292 		iter->retcode = namerules->retcode;
7124520Snw141292 		arg->lastrowid = namerules->lastrowid;
7134520Snw141292 	}
7144520Snw141292 
7154520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
7164520Snw141292 		return (IDMAP_SUCCESS);
7174520Snw141292 
7184520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
7194520Snw141292 		return (IDMAP_ERR_ARG);
7204520Snw141292 	}
7214520Snw141292 
7225064Sdm199847 	retcode = idmap_strdupnull(windomain,
7235064Sdm199847 	    namerules->rules.rules_val[iter->next].windomain);
7245064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7255064Sdm199847 		goto errout;
7265064Sdm199847 
7275064Sdm199847 	retcode = idmap_strdupnull(winname,
7285064Sdm199847 	    namerules->rules.rules_val[iter->next].winname);
7295064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7305064Sdm199847 		goto errout;
7315064Sdm199847 
7325064Sdm199847 	retcode = idmap_strdupnull(unixname,
7335064Sdm199847 	    namerules->rules.rules_val[iter->next].unixname);
7345064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7355064Sdm199847 		goto errout;
7365064Sdm199847 
7374520Snw141292 	if (is_nt4)
7384520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
7394520Snw141292 	if (direction)
7404520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
7414520Snw141292 	iter->next++;
7424520Snw141292 
7434520Snw141292 	if (iter->next == namerules->rules.rules_len)
7444520Snw141292 		return (iter->retcode);
7454520Snw141292 	else
7464520Snw141292 		return (IDMAP_NEXT);
7474520Snw141292 
7484520Snw141292 errout:
7494520Snw141292 	if (windomain && *windomain)
7504520Snw141292 		free(*windomain);
7514520Snw141292 	if (winname && *winname)
7524520Snw141292 		free(*winname);
7534520Snw141292 	if (unixname && *unixname)
7544520Snw141292 		free(*unixname);
7554520Snw141292 	return (retcode);
7564520Snw141292 }
7574520Snw141292 
7584520Snw141292 
7594520Snw141292 /*
7604520Snw141292  * Create iterator to get SID to UID/GID mappings
7614520Snw141292  *
7624520Snw141292  * Input:
7634520Snw141292  * is_user - user or group
7644520Snw141292  *
7654520Snw141292  * Output:
7664520Snw141292  * iter - iterator
7674520Snw141292  */
7684520Snw141292 idmap_stat
7694520Snw141292 idmap_iter_mappings(idmap_handle_t *handle, boolean_t is_user,
7704520Snw141292 		idmap_iter_t **iter) {
7714520Snw141292 	idmap_iter_t			*tmpiter;
7724520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
7734520Snw141292 
7744520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
7754520Snw141292 
7764520Snw141292 	arg->is_user = is_user;
7774520Snw141292 	*iter = tmpiter;
7784520Snw141292 	return (IDMAP_SUCCESS);
7794520Snw141292 }
7804520Snw141292 
7814520Snw141292 
7824520Snw141292 /*
7834520Snw141292  * Iterate through the SID to UID/GID mappings
7844520Snw141292  *
7854520Snw141292  * Input:
7864520Snw141292  * iter - iterator
7874520Snw141292  *
7884520Snw141292  * Output:
7894520Snw141292  * sid - SID in canonical form
7904520Snw141292  * pid - UID or GID
7914520Snw141292  *
7924520Snw141292  * Return value:
7934520Snw141292  * 0   - done
7944520Snw141292  * 1   - more results available
7954520Snw141292  * < 0 - error
7964520Snw141292  */
7974520Snw141292 idmap_stat
7984520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
7994520Snw141292 		idmap_rid_t *rid, uid_t *pid, char **winname,
8004520Snw141292 		char **windomain, char **unixname, int *direction) {
8014520Snw141292 	idmap_mappings_res		*mappings;
8024520Snw141292 	idmap_list_mappings_1_argument	*arg;
8034520Snw141292 	idmap_retcode			retcode;
8044520Snw141292 	char				*str;
8054520Snw141292 
8064520Snw141292 	if (sidprefix)
8074520Snw141292 		*sidprefix = NULL;
8084520Snw141292 	if (rid)
8094520Snw141292 		*rid = UINT32_MAX;
8104520Snw141292 	if (winname)
8114520Snw141292 		*winname = NULL;
8124520Snw141292 	if (windomain)
8134520Snw141292 		*windomain = NULL;
8144520Snw141292 	if (unixname)
8154520Snw141292 		*unixname = NULL;
8164520Snw141292 	if (pid)
8174520Snw141292 		*pid = UINT32_MAX;
8184520Snw141292 	if (direction)
8194644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
8204520Snw141292 
8214520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
8224520Snw141292 
8234520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
8244520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
8254520Snw141292 			iter->next >= mappings->mappings.mappings_len)) {
8264520Snw141292 
8274520Snw141292 		if ((arg = iter->arg) == NULL) {
8284520Snw141292 			errno = EINVAL;
8294520Snw141292 			return (IDMAP_ERR_ARG);
8304520Snw141292 		}
8314520Snw141292 		arg->limit = iter->limit;
8324520Snw141292 
8334520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
8344520Snw141292 			iter, arg,
8354520Snw141292 			(uchar_t **)&mappings, sizeof (*mappings),
8364520Snw141292 			(xdrproc_t)xdr_idmap_list_mappings_1_argument,
8374520Snw141292 			(xdrproc_t)xdr_idmap_mappings_res);
8384520Snw141292 		if (retcode != IDMAP_SUCCESS)
8394520Snw141292 			return (retcode);
8404520Snw141292 
8414520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
8424520Snw141292 			retcode  = mappings->retcode;
8434520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
8444520Snw141292 			free(mappings);
8454520Snw141292 			iter->retlist = NULL;
8464520Snw141292 			return (retcode);
8474520Snw141292 		}
8484520Snw141292 		iter->retcode = mappings->retcode;
8494520Snw141292 		arg->lastrowid = mappings->lastrowid;
8504520Snw141292 	}
8514520Snw141292 
8524520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
8534520Snw141292 		return (IDMAP_SUCCESS);
8544520Snw141292 
8554520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
8564520Snw141292 		return (IDMAP_ERR_ARG);
8574520Snw141292 	}
8584520Snw141292 
8594520Snw141292 	if (sidprefix) {
8604520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
8614520Snw141292 			idmap_id_u.sid.prefix;
8624695Sbaban 		if (str && *str != '\0') {
8634520Snw141292 			*sidprefix = strdup(str);
8644526Sbaban 			if (*sidprefix == NULL) {
8654526Sbaban 				retcode = IDMAP_ERR_MEMORY;
8664526Sbaban 				goto errout;
8674526Sbaban 			}
8684520Snw141292 		}
8694520Snw141292 	}
8704520Snw141292 	if (rid)
8714520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
8724520Snw141292 			idmap_id_u.sid.rid;
8735064Sdm199847 
8745064Sdm199847 	retcode = idmap_strdupnull(windomain,
8755064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1domain);
8765064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8775064Sdm199847 		goto errout;
8785064Sdm199847 
8795064Sdm199847 	retcode = idmap_strdupnull(winname,
8805064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1name);
8815064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8825064Sdm199847 		goto errout;
8835064Sdm199847 
8845064Sdm199847 	retcode = idmap_strdupnull(unixname,
8855064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id2name);
8865064Sdm199847 	if (retcode != IDMAP_SUCCESS)
8875064Sdm199847 		goto errout;
8885064Sdm199847 
8895064Sdm199847 
8904520Snw141292 	if (pid)
8914520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
8924520Snw141292 			idmap_id_u.uid;
8934520Snw141292 	if (direction)
8944520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
8954520Snw141292 			direction;
8964520Snw141292 	iter->next++;
8974520Snw141292 
8984520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
8994520Snw141292 		return (iter->retcode);
9004520Snw141292 	else
9014520Snw141292 		return (IDMAP_NEXT);
9024520Snw141292 
9034520Snw141292 errout:
9044520Snw141292 	if (sidprefix && *sidprefix)
9054520Snw141292 		free(*sidprefix);
9064520Snw141292 	if (winname && *winname)
9074520Snw141292 		free(*winname);
9084520Snw141292 	if (windomain && *windomain)
9094520Snw141292 		free(*windomain);
9104520Snw141292 	if (unixname && *unixname)
9114520Snw141292 		free(*unixname);
9124520Snw141292 	return (retcode);
9134520Snw141292 }
9144520Snw141292 
9154520Snw141292 
9164520Snw141292 /*
9174520Snw141292  * Destroy the iterator
9184520Snw141292  */
9194520Snw141292 void
9204520Snw141292 idmap_iter_destroy(idmap_iter_t *iter) {
9214520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
9224520Snw141292 
9234520Snw141292 	if (iter == NULL)
9244520Snw141292 		return;
9254520Snw141292 
9264520Snw141292 	switch (iter->type) {
9274520Snw141292 	case IDMAP_LIST_NAMERULES:
9284520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
9294520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
9304520Snw141292 		break;
9314520Snw141292 	case IDMAP_LIST_MAPPINGS:
9324520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
9334520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
9344520Snw141292 		break;
9354520Snw141292 	default:
9364520Snw141292 		free(iter);
9374520Snw141292 		return;
9384520Snw141292 	};
9394520Snw141292 
9404520Snw141292 	if (iter->arg) {
9414520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
9424520Snw141292 		free(iter->arg);
9434520Snw141292 	}
9444520Snw141292 	if (iter->retlist) {
9454520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
9464520Snw141292 		free(iter->retlist);
9474520Snw141292 	}
9484520Snw141292 	free(iter);
9494520Snw141292 }
9504520Snw141292 
9514520Snw141292 
9524520Snw141292 /*
9534520Snw141292  * Create handle to get SID to UID/GID mapping entries
9544520Snw141292  *
9554520Snw141292  * Input:
9564520Snw141292  * gh - "get mapping" handle
9574520Snw141292  */
9584520Snw141292 idmap_stat
9594520Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) {
9604520Snw141292 	idmap_get_handle_t	*tmp;
9614520Snw141292 
9624520Snw141292 	/* sanity checks */
9634520Snw141292 	if (handle == NULL || gh == NULL) {
9644520Snw141292 		errno = EINVAL;
9654520Snw141292 		return (IDMAP_ERR_ARG);
9664520Snw141292 	}
9674520Snw141292 
9684520Snw141292 	/* allocate the handle */
9694520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
9704520Snw141292 		errno = ENOMEM;
9714520Snw141292 		return (IDMAP_ERR_MEMORY);
9724520Snw141292 	}
9734520Snw141292 
9744520Snw141292 	tmp->ih = handle;
9754520Snw141292 	*gh = tmp;
9764520Snw141292 	return (IDMAP_SUCCESS);
9774520Snw141292 }
9784520Snw141292 
9794520Snw141292 
9804520Snw141292 /*
9814520Snw141292  * Given SID, get UID
9824520Snw141292  *
9834520Snw141292  * Input:
9844520Snw141292  * sidprefix  - SID prefix
9854520Snw141292  * rid        - RID
9864520Snw141292  * flag       - flag
9874520Snw141292  *
9884520Snw141292  * Output:
9894520Snw141292  * stat - status of the get request
9904520Snw141292  * uid  - POSIX UID if stat = 0
9914520Snw141292  *
9924520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
9934520Snw141292  */
9944520Snw141292 idmap_stat
9954520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
9964520Snw141292 		int flag, uid_t *uid, idmap_stat *stat) {
9974520Snw141292 
9984520Snw141292 	idmap_retcode	retcode;
9994644Sbaban 	idmap_mapping	*mapping = NULL;
10004520Snw141292 
10014520Snw141292 	/* sanity checks */
10024520Snw141292 	if (gh == NULL)
10034520Snw141292 		return (IDMAP_ERR_ARG);
10044520Snw141292 	if (uid == NULL || sidprefix == NULL)
10054520Snw141292 		return (IDMAP_ERR_ARG);
10064520Snw141292 
10074520Snw141292 	/* Extend the request array and the return list */
10084520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
10094520Snw141292 		goto errout;
10104520Snw141292 
10114520Snw141292 	/* Setup the request */
10124520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
10134520Snw141292 	mapping->flag = flag;
10144520Snw141292 	mapping->id1.idtype = IDMAP_SID;
10154520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
10164520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
10174520Snw141292 		retcode = IDMAP_ERR_MEMORY;
10184520Snw141292 		goto errout;
10194520Snw141292 	}
10204520Snw141292 	mapping->id2.idtype = IDMAP_UID;
10214520Snw141292 
10224520Snw141292 	/* Setup pointers for the result */
10234520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
10244520Snw141292 	gh->retlist[gh->next].uid = uid;
10254520Snw141292 	gh->retlist[gh->next].stat = stat;
10264520Snw141292 
10274520Snw141292 	gh->next++;
10284520Snw141292 	return (IDMAP_SUCCESS);
10294520Snw141292 
10304520Snw141292 errout:
10314644Sbaban 	/* Batch created so far should still be usable */
10324644Sbaban 	if (mapping)
10334644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
10344520Snw141292 	errno = idmap_stat2errno(retcode);
10354520Snw141292 	return (retcode);
10364520Snw141292 }
10374520Snw141292 
10384520Snw141292 
10394520Snw141292 /*
10404520Snw141292  * Given SID, get GID
10414520Snw141292  *
10424520Snw141292  * Input:
10434520Snw141292  * sidprefix  - SID prefix
10444520Snw141292  * rid        - rid
10454520Snw141292  * flag       - flag
10464520Snw141292  *
10474520Snw141292  * Output:
10484520Snw141292  * stat - status of the get request
10494520Snw141292  * gid  - POSIX GID if stat = 0
10504520Snw141292  *
10514520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
10524520Snw141292  */
10534520Snw141292 idmap_stat
10544520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
10554520Snw141292 		int flag, gid_t *gid, idmap_stat *stat) {
10564520Snw141292 
10574520Snw141292 	idmap_retcode	retcode;
10584644Sbaban 	idmap_mapping	*mapping = NULL;
10594520Snw141292 
10604520Snw141292 	/* sanity checks */
10614520Snw141292 	if (gh == NULL)
10624520Snw141292 		return (IDMAP_ERR_ARG);
10634520Snw141292 	if (gid == NULL || sidprefix == NULL)
10644520Snw141292 		return (IDMAP_ERR_ARG);
10654520Snw141292 
10664520Snw141292 	/* Extend the request array and the return list */
10674520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
10684520Snw141292 		goto errout;
10694520Snw141292 
10704520Snw141292 	/* Setup the request */
10714520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
10724520Snw141292 	mapping->flag = flag;
10734520Snw141292 	mapping->id1.idtype = IDMAP_SID;
10744520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
10754520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
10764520Snw141292 		retcode = IDMAP_ERR_MEMORY;
10774520Snw141292 		goto errout;
10784520Snw141292 	}
10794520Snw141292 	mapping->id2.idtype = IDMAP_GID;
10804520Snw141292 
10814520Snw141292 	/* Setup pointers for the result */
10824520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
10834520Snw141292 	gh->retlist[gh->next].gid = gid;
10844520Snw141292 	gh->retlist[gh->next].stat = stat;
10854520Snw141292 
10864520Snw141292 	gh->next++;
10874520Snw141292 	return (IDMAP_SUCCESS);
10884520Snw141292 
10894520Snw141292 errout:
10904644Sbaban 	if (mapping)
10914644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
10924520Snw141292 	errno = idmap_stat2errno(retcode);
10934520Snw141292 	return (retcode);
10944520Snw141292 }
10954520Snw141292 
10964520Snw141292 
10974520Snw141292 /*
10984520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
10994520Snw141292  *
11004520Snw141292  * Input:
11014520Snw141292  * sidprefix  - SID prefix
11024520Snw141292  * rid        - rid
11034520Snw141292  * flag       - flag
11044520Snw141292  *
11054520Snw141292  * Output:
11064520Snw141292  * stat    - status of the get request
11074520Snw141292  * is_user - user or group
11084520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
11094520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
11104520Snw141292  *
11114520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11124520Snw141292  */
11134520Snw141292 idmap_stat
11144520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11154520Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat) {
11164520Snw141292 	idmap_retcode	retcode;
11174644Sbaban 	idmap_mapping	*mapping = NULL;
11184520Snw141292 
11194520Snw141292 	/* sanity checks */
11204520Snw141292 	if (gh == NULL)
11214520Snw141292 		return (IDMAP_ERR_ARG);
11224520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
11234520Snw141292 		return (IDMAP_ERR_ARG);
11244520Snw141292 
11254520Snw141292 	/* Extend the request array and the return list */
11264520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11274520Snw141292 		goto errout;
11284520Snw141292 
11294520Snw141292 	/* Setup the request */
11304520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11314520Snw141292 	mapping->flag = flag;
11324520Snw141292 	mapping->id1.idtype = IDMAP_SID;
11334520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
11344520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
11354520Snw141292 		retcode = IDMAP_ERR_MEMORY;
11364520Snw141292 		goto errout;
11374520Snw141292 	}
11384520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
11394520Snw141292 
11404520Snw141292 	/* Setup pointers for the result */
11414520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
11424520Snw141292 	gh->retlist[gh->next].uid = pid;
11434520Snw141292 	gh->retlist[gh->next].gid = pid;
11444520Snw141292 	gh->retlist[gh->next].is_user = is_user;
11454520Snw141292 	gh->retlist[gh->next].stat = stat;
11464520Snw141292 
11474520Snw141292 	gh->next++;
11484520Snw141292 	return (IDMAP_SUCCESS);
11494520Snw141292 
11504520Snw141292 errout:
11514644Sbaban 	if (mapping)
11524644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
11534520Snw141292 	errno = idmap_stat2errno(retcode);
11544520Snw141292 	return (retcode);
11554520Snw141292 }
11564520Snw141292 
11574520Snw141292 
11584520Snw141292 /*
11594520Snw141292  * Given UID, get SID
11604520Snw141292  *
11614520Snw141292  * Input:
11624520Snw141292  * uid  - POSIX UID
11634520Snw141292  * flag - flag
11644520Snw141292  *
11654520Snw141292  * Output:
11664520Snw141292  * stat - status of the get request
11674520Snw141292  * sid  - SID prefix (if stat == 0)
11684520Snw141292  * rid  - rid
11694520Snw141292  *
11704520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11714520Snw141292  */
11724520Snw141292 idmap_stat
11734520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
11744520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
11754520Snw141292 
11764520Snw141292 	idmap_retcode	retcode;
11774644Sbaban 	idmap_mapping	*mapping = NULL;
11784520Snw141292 
11794520Snw141292 	/* sanity checks */
11804520Snw141292 	if (gh == NULL)
11814520Snw141292 		return (IDMAP_ERR_ARG);
11824520Snw141292 	if (sidprefix == NULL)
11834520Snw141292 		return (IDMAP_ERR_ARG);
11844520Snw141292 
11854520Snw141292 	/* Extend the request array and the return list */
11864520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11874520Snw141292 		goto errout;
11884520Snw141292 
11894520Snw141292 	/* Setup the request */
11904520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11914520Snw141292 	mapping->flag = flag;
11924520Snw141292 	mapping->id1.idtype = IDMAP_UID;
11934520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
11944520Snw141292 	mapping->id2.idtype = IDMAP_SID;
11954520Snw141292 
11964520Snw141292 	/* Setup pointers for the result */
11974520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
11984520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
11994520Snw141292 	gh->retlist[gh->next].rid = rid;
12004520Snw141292 	gh->retlist[gh->next].stat = stat;
12014520Snw141292 
12024520Snw141292 	gh->next++;
12034520Snw141292 	return (IDMAP_SUCCESS);
12044520Snw141292 
12054520Snw141292 errout:
12064644Sbaban 	if (mapping)
12074644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12084520Snw141292 	errno = idmap_stat2errno(retcode);
12094520Snw141292 	return (retcode);
12104520Snw141292 }
12114520Snw141292 
12124520Snw141292 
12134520Snw141292 /*
12144520Snw141292  * Given GID, get SID
12154520Snw141292  *
12164520Snw141292  * Input:
12174520Snw141292  * gid  - POSIX GID
12184520Snw141292  * flag - flag
12194520Snw141292  *
12204520Snw141292  * Output:
12214520Snw141292  * stat       - status of the get request
12224520Snw141292  * sidprefix  - SID prefix (if stat == 0)
12234520Snw141292  * rid        - rid
12244520Snw141292  *
12254520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12264520Snw141292  */
12274520Snw141292 idmap_stat
12284520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
12294520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
12304520Snw141292 
12314520Snw141292 	idmap_retcode	retcode;
12324644Sbaban 	idmap_mapping	*mapping = NULL;
12334520Snw141292 
12344520Snw141292 	/* sanity checks */
12354520Snw141292 	if (gh == NULL)
12364520Snw141292 		return (IDMAP_ERR_ARG);
12374520Snw141292 	if (sidprefix == NULL)
12384520Snw141292 		return (IDMAP_ERR_ARG);
12394520Snw141292 
12404520Snw141292 	/* Extend the request array and the return list */
12414520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
12424520Snw141292 		goto errout;
12434520Snw141292 
12444520Snw141292 	/* Setup the request */
12454520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
12464520Snw141292 	mapping->flag = flag;
12474520Snw141292 	mapping->id1.idtype = IDMAP_GID;
12484520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
12494520Snw141292 	mapping->id2.idtype = IDMAP_SID;
12504520Snw141292 
12514520Snw141292 	/* Setup pointers for the result */
12524520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
12534520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
12544520Snw141292 	gh->retlist[gh->next].rid = rid;
12554520Snw141292 	gh->retlist[gh->next].stat = stat;
12564520Snw141292 
12574520Snw141292 	gh->next++;
12584520Snw141292 	return (IDMAP_SUCCESS);
12594520Snw141292 
12604520Snw141292 errout:
12614644Sbaban 	if (mapping)
12624644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12634520Snw141292 	errno = idmap_stat2errno(retcode);
12644520Snw141292 	return (retcode);
12654520Snw141292 }
12664520Snw141292 
12674520Snw141292 
12684520Snw141292 /*
12694520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
12704520Snw141292  * status and identity) will be available in the data areas
12714520Snw141292  * provided by individual requests.
12724520Snw141292  */
12734520Snw141292 idmap_stat
12744520Snw141292 idmap_get_mappings(idmap_get_handle_t *gh) {
12754520Snw141292 	CLIENT		*clnt;
12764520Snw141292 	enum clnt_stat	clntstat;
12774520Snw141292 	idmap_retcode	retcode;
12784520Snw141292 	idmap_ids_res	res;
12794520Snw141292 	idmap_id	*id;
12804520Snw141292 	int		i;
12814520Snw141292 
12824520Snw141292 	if (gh == NULL) {
12834520Snw141292 		errno = EINVAL;
12844520Snw141292 		return (IDMAP_ERR_ARG);
12854520Snw141292 	}
12864520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
12874520Snw141292 
12884520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
12894520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
12904520Snw141292 		(xdrproc_t)xdr_idmap_mapping_batch,
12914520Snw141292 		(caddr_t)&gh->batch,
12924520Snw141292 		(xdrproc_t)xdr_idmap_ids_res,
12934520Snw141292 		(caddr_t)&res,
12944520Snw141292 		TIMEOUT);
12954520Snw141292 	if (clntstat != RPC_SUCCESS) {
12964644Sbaban 		retcode = _idmap_rpc2stat(clnt);
12974520Snw141292 		goto out;
12984520Snw141292 	}
12994520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
13004520Snw141292 		retcode = res.retcode;
13014520Snw141292 		goto out;
13024520Snw141292 	}
13034520Snw141292 	for (i = 0; i < gh->next; i++) {
13044520Snw141292 		if (i >= res.ids.ids_len) {
13054520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
13064520Snw141292 			continue;
13074520Snw141292 		}
13084520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
13094520Snw141292 		id = &res.ids.ids_val[i].id;
13104520Snw141292 		switch (id->idtype) {
13114520Snw141292 		case IDMAP_UID:
13124520Snw141292 			if (gh->retlist[i].uid)
13134520Snw141292 				*gh->retlist[i].uid = id->idmap_id_u.uid;
13144520Snw141292 			if (gh->retlist[i].is_user)
13154520Snw141292 				*gh->retlist[i].is_user = 1;
13164520Snw141292 			break;
13174520Snw141292 		case IDMAP_GID:
13184520Snw141292 			if (gh->retlist[i].gid)
13194520Snw141292 				*gh->retlist[i].gid = id->idmap_id_u.gid;
13204520Snw141292 			if (gh->retlist[i].is_user)
13214520Snw141292 				*gh->retlist[i].is_user = 0;
13224520Snw141292 			break;
13234864Sbaban 		case IDMAP_POSIXID:
13244864Sbaban 			if (gh->retlist[i].uid)
13254864Sbaban 				*gh->retlist[i].uid = 60001;
13264864Sbaban 			if (gh->retlist[i].is_user)
13274864Sbaban 				*gh->retlist[i].is_user = -1;
13284864Sbaban 			break;
13294520Snw141292 		case IDMAP_SID:
13304520Snw141292 			if (gh->retlist[i].rid)
13314520Snw141292 				*gh->retlist[i].rid = id->idmap_id_u.sid.rid;
13324520Snw141292 			if (gh->retlist[i].sidprefix) {
13334695Sbaban 				if (id->idmap_id_u.sid.prefix == NULL ||
13344695Sbaban 				    *id->idmap_id_u.sid.prefix == '\0') {
13354520Snw141292 					*gh->retlist[i].sidprefix = NULL;
13364520Snw141292 					break;
13374520Snw141292 				}
13384520Snw141292 				*gh->retlist[i].sidprefix =
13394520Snw141292 					strdup(id->idmap_id_u.sid.prefix);
13404520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
13414520Snw141292 					*gh->retlist[i].stat =
13424520Snw141292 						IDMAP_ERR_MEMORY;
13434520Snw141292 			}
13444520Snw141292 			break;
13454520Snw141292 		case IDMAP_NONE:
13464520Snw141292 			break;
13474520Snw141292 		default:
13484520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
13494520Snw141292 			break;
13504520Snw141292 		}
13514520Snw141292 	}
13524520Snw141292 	retcode = IDMAP_SUCCESS;
13534520Snw141292 
13544520Snw141292 out:
13554644Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
13564520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
13574520Snw141292 	errno = idmap_stat2errno(retcode);
13584520Snw141292 	return (retcode);
13594520Snw141292 }
13604520Snw141292 
13614520Snw141292 
13624520Snw141292 /*
13634520Snw141292  * Destroy the "get mapping" handle
13644520Snw141292  */
13654520Snw141292 void
13664520Snw141292 idmap_get_destroy(idmap_get_handle_t *gh) {
13674520Snw141292 	if (gh == NULL)
13684520Snw141292 		return;
13694520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
13704520Snw141292 	if (gh->retlist)
13714520Snw141292 		free(gh->retlist);
13724520Snw141292 	free(gh);
13734520Snw141292 }
13744520Snw141292 
13754520Snw141292 
13764520Snw141292 /*
13774520Snw141292  * Get windows to unix mapping
13784520Snw141292  */
13794520Snw141292 idmap_stat
13804520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
13814520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
13824520Snw141292 		const char *winname, const char *windomain,
13834520Snw141292 		int flag, int *is_user,
13844520Snw141292 		uid_t *pid, char **unixname, int *direction) {
13854520Snw141292 	CLIENT			*clnt;
13864520Snw141292 	enum clnt_stat		clntstat;
13874520Snw141292 	idmap_mapping		request, *mapping;
13884520Snw141292 	idmap_mappings_res	result;
13894520Snw141292 	idmap_retcode		retcode, rc;
13904520Snw141292 
13914520Snw141292 	if (handle == NULL) {
13924520Snw141292 		errno = EINVAL;
13934520Snw141292 		return (IDMAP_ERR_ARG);
13944520Snw141292 	}
13954520Snw141292 
13964520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
13974520Snw141292 
13984520Snw141292 	(void) memset(&request, 0, sizeof (request));
13994520Snw141292 	(void) memset(&result, 0, sizeof (result));
14004520Snw141292 
14014864Sbaban 	if (is_user)
14024864Sbaban 		*is_user = -1;
14034520Snw141292 	if (pid)
14044520Snw141292 		*pid = UINT32_MAX;
14054520Snw141292 	if (unixname)
14064520Snw141292 		*unixname = NULL;
14074520Snw141292 	if (direction)
14084644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
14094520Snw141292 
14104520Snw141292 	request.flag = flag;
14114520Snw141292 	request.id1.idtype = IDMAP_SID;
14124520Snw141292 	if (sidprefix && rid) {
14134520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
14144520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
14154520Snw141292 	} else if (winname) {
14165064Sdm199847 		retcode = idmap_strdupnull(&request.id1name, winname);
14175064Sdm199847 		if (retcode != SUCCESS)
14184520Snw141292 			goto out;
14195064Sdm199847 
14205064Sdm199847 		retcode = idmap_strdupnull(&request.id1domain, windomain);
14215064Sdm199847 		if (retcode != SUCCESS)
14225064Sdm199847 			goto out;
14235064Sdm199847 
14244520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
14254520Snw141292 	} else {
14264520Snw141292 		errno = EINVAL;
14274520Snw141292 		return (IDMAP_ERR_ARG);
14284520Snw141292 	}
14294520Snw141292 
14304520Snw141292 	if (is_user == NULL)
14314520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
14324520Snw141292 	else if (*is_user == 1)
14334520Snw141292 		request.id2.idtype = IDMAP_UID;
14344520Snw141292 	else if (*is_user == 0)
14354520Snw141292 		request.id2.idtype = IDMAP_GID;
14364520Snw141292 	else
14374520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
14384520Snw141292 
14394520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
14404520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
14414520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
14424520Snw141292 		TIMEOUT);
14434520Snw141292 
14444644Sbaban 	if (clntstat != RPC_SUCCESS)
14454644Sbaban 		return (_idmap_rpc2stat(clnt));
14464520Snw141292 
14474520Snw141292 	retcode = result.retcode;
14484520Snw141292 
14494520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
14504520Snw141292 		if (retcode == IDMAP_SUCCESS)
14514520Snw141292 			retcode = IDMAP_ERR_NORESULT;
14524520Snw141292 		goto out;
14534520Snw141292 	}
14544520Snw141292 
14554864Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
14564864Sbaban 		if (is_user) *is_user = 1;
14574864Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
14584864Sbaban 		if (is_user) *is_user = 0;
14594864Sbaban 	} else {
14604864Sbaban 		goto out;
14614864Sbaban 	}
14624520Snw141292 	if (direction)
14634520Snw141292 		*direction = mapping->direction;
14644520Snw141292 	if (pid)
14654520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
14665064Sdm199847 
14675064Sdm199847 	rc = idmap_strdupnull(unixname, mapping->id2name);
14685064Sdm199847 	if (rc != IDMAP_SUCCESS)
14695064Sdm199847 		retcode = rc;
14704520Snw141292 
14714520Snw141292 out:
14724520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
14734520Snw141292 	if (retcode != IDMAP_SUCCESS)
14744520Snw141292 		errno = idmap_stat2errno(retcode);
14754520Snw141292 	return (retcode);
14764520Snw141292 }
14774520Snw141292 
14784520Snw141292 
14794520Snw141292 /*
14804520Snw141292  * Get unix to windows mapping
14814520Snw141292  */
14824520Snw141292 idmap_stat
14834520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
14844520Snw141292 		uid_t *pid, const char *unixname,
14854520Snw141292 		int flag, int is_user,
14864520Snw141292 		char **sidprefix, idmap_rid_t *rid,
14874520Snw141292 		char **winname, char **windomain,
14884520Snw141292 		int *direction) {
14894520Snw141292 	CLIENT			*clnt;
14904520Snw141292 	enum clnt_stat		clntstat;
14914520Snw141292 	idmap_mapping		request, *mapping;
14924520Snw141292 	idmap_mappings_res	result;
14934520Snw141292 	idmap_retcode		retcode, rc;
14944520Snw141292 
14954520Snw141292 	if (handle == NULL) {
14964520Snw141292 		errno = EINVAL;
14974520Snw141292 		return (IDMAP_ERR_ARG);
14984520Snw141292 	}
14994520Snw141292 
15004520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
15014520Snw141292 
15024520Snw141292 	if (sidprefix)
15034520Snw141292 		*sidprefix = NULL;
15044520Snw141292 	if (winname)
15054520Snw141292 		*winname = NULL;
15064520Snw141292 	if (windomain)
15074520Snw141292 		*windomain = NULL;
15084520Snw141292 	if (rid)
15094520Snw141292 		*rid = UINT32_MAX;
15104520Snw141292 	if (direction)
15114644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
15124520Snw141292 
15134520Snw141292 	(void) memset(&request, 0, sizeof (request));
15144520Snw141292 	(void) memset(&result, 0, sizeof (result));
15154520Snw141292 
15164520Snw141292 	request.flag = flag;
15174520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
15184520Snw141292 
15194520Snw141292 	if (pid && *pid != UINT32_MAX) {
15204520Snw141292 		request.id1.idmap_id_u.uid = *pid;
15214520Snw141292 	} else if (unixname) {
15225064Sdm199847 		request.id1name = (char *)unixname;
15234520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
15244520Snw141292 	} else {
15254520Snw141292 		errno = EINVAL;
15264520Snw141292 		return (IDMAP_ERR_ARG);
15274520Snw141292 	}
15284520Snw141292 
15294520Snw141292 	request.id2.idtype = IDMAP_SID;
15304520Snw141292 
15314520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
15324520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
15334520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
15344520Snw141292 		TIMEOUT);
15354520Snw141292 
15364644Sbaban 	if (clntstat != RPC_SUCCESS)
15374644Sbaban 		return (_idmap_rpc2stat(clnt));
15384520Snw141292 
15394520Snw141292 	retcode = result.retcode;
15404520Snw141292 
15414520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
15424520Snw141292 		if (retcode == IDMAP_SUCCESS)
15434520Snw141292 			retcode = IDMAP_ERR_NORESULT;
15444520Snw141292 		goto out;
15454520Snw141292 	}
15464520Snw141292 
15474520Snw141292 	if (direction)
15484520Snw141292 		*direction = mapping->direction;
15494695Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
15504695Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
15514520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
15524520Snw141292 		if (*sidprefix == NULL) {
15534520Snw141292 			retcode = IDMAP_ERR_MEMORY;
15544520Snw141292 			goto errout;
15554520Snw141292 		}
15564520Snw141292 	}
15574520Snw141292 	if (rid)
15584520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
15595064Sdm199847 
15605064Sdm199847 	rc = idmap_strdupnull(winname, mapping->id2name);
15615064Sdm199847 	if (rc != IDMAP_SUCCESS)
15625064Sdm199847 		retcode = rc;
15635064Sdm199847 
15645064Sdm199847 	rc = idmap_strdupnull(windomain, mapping->id2domain);
15655064Sdm199847 	if (rc != IDMAP_SUCCESS)
15665064Sdm199847 		retcode = rc;
15674520Snw141292 
15684520Snw141292 	goto out;
15694520Snw141292 
15704520Snw141292 errout:
15714520Snw141292 	if (sidprefix && *sidprefix) {
15724520Snw141292 		free(*sidprefix);
15734520Snw141292 		*sidprefix = NULL;
15744520Snw141292 	}
15754520Snw141292 	if (winname && *winname) {
15764520Snw141292 		free(*winname);
15774520Snw141292 		*winname = NULL;
15784520Snw141292 	}
15794520Snw141292 	if (windomain && *windomain) {
15804520Snw141292 		free(*windomain);
15814520Snw141292 		*windomain = NULL;
15824520Snw141292 	}
15834520Snw141292 
15844520Snw141292 out:
15854520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
15864520Snw141292 	if (retcode != IDMAP_SUCCESS)
15874520Snw141292 		errno = idmap_stat2errno(retcode);
15884520Snw141292 	return (retcode);
15894520Snw141292 }
15904520Snw141292 
15914520Snw141292 
15924520Snw141292 
15934520Snw141292 #define	gettext(s)	s
15944520Snw141292 static stat_table_t stattable[] = {
15954520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
15964520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
15974520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
15984520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
15994520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
16004520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
16014520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
16024520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
16034644Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
16044520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
16054520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
16064520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
16074520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
16084520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
16094520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
16104520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
16114520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
16124520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
16134644Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
16144520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
16154520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
16164644Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
16174695Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
16184520Snw141292 	{IDMAP_ERR_NOMAPPING,
16194520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
16204520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
16214520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
16224520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
16234520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
16244520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
16254520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
16264520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
16274520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
16284520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
16294520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
16304520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
16314520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
16324864Sbaban 		gettext("Windows lookup failed"), EINVAL},
16334864Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
16344864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
16354864Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
16364864Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
16374864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
16384864Sbaban 		"Unix to Windows name-based rule"), EINVAL},
16394520Snw141292 	{-1, NULL, 0}
16404520Snw141292 };
16414520Snw141292 #undef	gettext
16424520Snw141292 
16434520Snw141292 
16444520Snw141292 /*
16454520Snw141292  * Get description of status code
16464520Snw141292  *
16474520Snw141292  * Input:
16484520Snw141292  * status - Status code returned by libidmap API call
16494520Snw141292  *
16504520Snw141292  * Return Value:
16514520Snw141292  * human-readable localized description of idmap_stat
16524520Snw141292  */
16534520Snw141292 /* ARGSUSED */
16544520Snw141292 const char *
16554520Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) {
16564520Snw141292 	int i;
16574520Snw141292 
16584520Snw141292 	for (i = 0; stattable[i].msg; i++) {
16594520Snw141292 		if (stattable[i].retcode == status)
16604526Sbaban 			return (gettext(stattable[i].msg));
16614520Snw141292 	}
16624520Snw141292 	return (gettext("Unknown error"));
16634520Snw141292 }
16644520Snw141292 
16654520Snw141292 
16664520Snw141292 static int
16674520Snw141292 idmap_stat2errno(idmap_stat stat) {
16684520Snw141292 	int i;
16694520Snw141292 	for (i = 0; stattable[i].msg; i++) {
16704520Snw141292 		if (stattable[i].retcode == stat)
16714520Snw141292 			return (stattable[i].errnum);
16724520Snw141292 	}
16734520Snw141292 	return (EINVAL);
16744520Snw141292 }
16754520Snw141292 
16764520Snw141292 
16774520Snw141292 /*
16784520Snw141292  * Get status code from string
16794520Snw141292  */
16804520Snw141292 idmap_stat
16814520Snw141292 idmap_string2stat(const char *str) {
16824520Snw141292 	if (str == NULL)
16834520Snw141292 		return (IDMAP_ERR_INTERNAL);
16844520Snw141292 
16854520Snw141292 #define	return_cmp(a) \
16864520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
16874520Snw141292 		return (IDMAP_ERR_ ## a);
16884520Snw141292 
16894520Snw141292 	return_cmp(OTHER);
16904520Snw141292 	return_cmp(INTERNAL);
16914520Snw141292 	return_cmp(MEMORY);
16924520Snw141292 	return_cmp(NORESULT);
16934520Snw141292 	return_cmp(NOTUSER);
16944520Snw141292 	return_cmp(NOTGROUP);
16954520Snw141292 	return_cmp(NOTSUPPORTED);
16964520Snw141292 	return_cmp(W2U_NAMERULE);
16974520Snw141292 	return_cmp(U2W_NAMERULE);
16984520Snw141292 	return_cmp(CACHE);
16994520Snw141292 	return_cmp(DB);
17004520Snw141292 	return_cmp(ARG);
17014520Snw141292 	return_cmp(SID);
17024520Snw141292 	return_cmp(IDTYPE);
17034520Snw141292 	return_cmp(RPC_HANDLE);
17044520Snw141292 	return_cmp(RPC);
17054520Snw141292 	return_cmp(CLIENT_HANDLE);
17064520Snw141292 	return_cmp(BUSY);
17074520Snw141292 	return_cmp(PERMISSION_DENIED);
17084520Snw141292 	return_cmp(NOMAPPING);
17094520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
17104520Snw141292 	return_cmp(DOMAIN);
17114520Snw141292 	return_cmp(SECURITY);
17124520Snw141292 	return_cmp(NOTFOUND);
17134520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
17144520Snw141292 	return_cmp(MEMORY);
17154520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
17164520Snw141292 	return_cmp(CFG);
17174520Snw141292 	return_cmp(CFG_CHANGE);
17184520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
17194520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
17204864Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
17214864Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
17224520Snw141292 #undef return_cmp
17234520Snw141292 
17244520Snw141292 	return (IDMAP_ERR_OTHER);
17254520Snw141292 }
17264520Snw141292 
17274520Snw141292 
17284520Snw141292 /*
17294520Snw141292  * Map the given status to one that can be returned by the protocol
17304520Snw141292  */
17314520Snw141292 idmap_stat
17324520Snw141292 idmap_stat4prot(idmap_stat status) {
17334520Snw141292 	switch (status) {
17344520Snw141292 	case IDMAP_ERR_MEMORY:
17354520Snw141292 	case IDMAP_ERR_CACHE:
17364520Snw141292 		return (IDMAP_ERR_INTERNAL);
17374520Snw141292 	}
17384520Snw141292 	return (status);
17394520Snw141292 }
17405043Sbaban 
17415043Sbaban 
17425043Sbaban /*
17435064Sdm199847  * duplicate a string, possibly null
17445064Sdm199847  */
17455064Sdm199847 static idmap_stat
17465064Sdm199847 idmap_strdupnull(char **to, const char *from) {
17475064Sdm199847 	if (from == NULL || *from == '\0') {
17485064Sdm199847 		*to = NULL;
17495064Sdm199847 		return (IDMAP_SUCCESS);
17505064Sdm199847 	}
17515064Sdm199847 
17525064Sdm199847 	*to = strdup(from);
17535064Sdm199847 	if (*to == NULL)
17545064Sdm199847 		return (IDMAP_ERR_MEMORY);
17555064Sdm199847 	return (IDMAP_SUCCESS);
17565064Sdm199847 }
17575064Sdm199847 
17585064Sdm199847 idmap_stat
17595064Sdm199847 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) {
17605064Sdm199847 	idmap_stat retval;
17615064Sdm199847 
17625064Sdm199847 	(void) memcpy(to, from, sizeof (idmap_namerule));
17635064Sdm199847 
17645064Sdm199847 	retval = idmap_strdupnull(&to->windomain, from->windomain);
17655064Sdm199847 	if (retval != IDMAP_SUCCESS)
17665064Sdm199847 		return (retval);
17675064Sdm199847 
17685064Sdm199847 	retval = idmap_strdupnull(&to->winname, from->winname);
17695064Sdm199847 	if (retval != IDMAP_SUCCESS)
17705064Sdm199847 		return (retval);
17715064Sdm199847 
17725064Sdm199847 	retval = idmap_strdupnull(&to->unixname, from->unixname);
17735064Sdm199847 
17745064Sdm199847 	return (retval);
17755064Sdm199847 }
17765064Sdm199847 
17775064Sdm199847 
17785064Sdm199847 /*
17795043Sbaban  * Get uid given Windows name
17805043Sbaban  */
17815043Sbaban idmap_stat
17825043Sbaban idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) {
17835043Sbaban 	idmap_handle_t	*ih;
17845043Sbaban 	idmap_retcode	rc;
17855043Sbaban 	int		is_user;
17865043Sbaban 
17875043Sbaban 	if (uid == NULL)
17885043Sbaban 		return (IDMAP_ERR_ARG);
17895043Sbaban 
17905043Sbaban 	/* Get mapping */
17915043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
17925043Sbaban 		return (rc);
17935043Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
17945043Sbaban 	    &is_user, uid, NULL, NULL);
17955043Sbaban 	(void) idmap_fini(ih);
17965043Sbaban 
17975043Sbaban 	/*
17985043Sbaban 	 * XXX Until we have diagonal mapping support, check if
17995043Sbaban 	 * the given name belongs to a user
18005043Sbaban 	 */
18015043Sbaban 	if (rc == IDMAP_SUCCESS && !is_user)
18025043Sbaban 		return (IDMAP_ERR_NOTUSER);
18035043Sbaban 	return (rc);
18045043Sbaban }
18055043Sbaban 
18065043Sbaban 
18075043Sbaban /*
18085043Sbaban  * Get gid given Windows name
18095043Sbaban  */
18105043Sbaban idmap_stat
18115043Sbaban idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) {
18125043Sbaban 	idmap_handle_t	*ih;
18135043Sbaban 	idmap_retcode	rc;
18145043Sbaban 	int		is_user;
18155043Sbaban 
18165043Sbaban 	if (gid == NULL)
18175043Sbaban 		return (IDMAP_ERR_ARG);
18185043Sbaban 
18195043Sbaban 	/* Get mapping */
18205043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
18215043Sbaban 		return (rc);
18225043Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
18235043Sbaban 	    &is_user, gid, NULL, NULL);
18245043Sbaban 	(void) idmap_fini(ih);
18255043Sbaban 
18265043Sbaban 	/*
18275043Sbaban 	 * XXX Until we have diagonal mapping support, check if
18285043Sbaban 	 * the given name belongs to a group
18295043Sbaban 	 */
18305043Sbaban 	if (rc == IDMAP_SUCCESS && is_user)
18315043Sbaban 		return (IDMAP_ERR_NOTGROUP);
18325043Sbaban 	return (rc);
18335043Sbaban }
18345043Sbaban 
18355043Sbaban 
18365043Sbaban /*
18375043Sbaban  * Get winname given pid
18385043Sbaban  */
18395043Sbaban static idmap_retcode
18405043Sbaban idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) {
18415043Sbaban 	idmap_handle_t	*ih;
18425043Sbaban 	idmap_retcode	rc;
18435043Sbaban 	int		len;
18445043Sbaban 	char		*winname, *windomain;
18455043Sbaban 
18465043Sbaban 	if (name == NULL)
18475043Sbaban 		return (IDMAP_ERR_ARG);
18485043Sbaban 
18495043Sbaban 	/* Get mapping */
18505043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
18515043Sbaban 		return (rc);
18525043Sbaban 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL,
18535043Sbaban 	    NULL, &winname, &windomain, NULL);
18545043Sbaban 	(void) idmap_fini(ih);
18555043Sbaban 
18565043Sbaban 	/* Return on error */
18575043Sbaban 	if (rc != IDMAP_SUCCESS)
18585043Sbaban 		return (rc);
18595043Sbaban 
18605043Sbaban 	/*
18615043Sbaban 	 * The given PID may have been mapped to a locally
18625043Sbaban 	 * generated SID in which case there isn't any
18635043Sbaban 	 * Windows name
18645043Sbaban 	 */
18655043Sbaban 	if (winname == NULL || windomain == NULL) {
18665043Sbaban 		idmap_free(winname);
18675043Sbaban 		idmap_free(windomain);
18685043Sbaban 		return (IDMAP_ERR_NORESULT);
18695043Sbaban 	}
18705043Sbaban 
18715043Sbaban 	if (domain != NULL) {
18725043Sbaban 		*name = winname;
18735043Sbaban 		*domain = windomain;
18745043Sbaban 	} else {
18755043Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
18765043Sbaban 		if ((*name = malloc(len)) != NULL)
18775043Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
18785043Sbaban 			    windomain);
18795043Sbaban 		else
18805043Sbaban 			rc = IDMAP_ERR_MEMORY;
18815043Sbaban 		idmap_free(winname);
18825043Sbaban 		idmap_free(windomain);
18835043Sbaban 	}
18845043Sbaban 	return (rc);
18855043Sbaban }
18865043Sbaban 
18875043Sbaban 
18885043Sbaban /*
18895043Sbaban  * Get winname given uid
18905043Sbaban  */
18915043Sbaban idmap_stat
18925043Sbaban idmap_getwinnamebyuid(uid_t uid, char **name, char **domain) {
18935043Sbaban 	return (idmap_getwinnamebypid(uid, 1, name, domain));
18945043Sbaban }
18955043Sbaban 
18965043Sbaban 
18975043Sbaban /*
18985043Sbaban  * Get winname given gid
18995043Sbaban  */
19005043Sbaban idmap_stat
19015043Sbaban idmap_getwinnamebygid(gid_t gid, char **name, char **domain) {
19025043Sbaban 	return (idmap_getwinnamebypid(gid, 0, name, domain));
19035043Sbaban }
1904