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 #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>
425232Snw141292 #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
1025696Snw141292 idmap_free(void *ptr)
1035696Snw141292 {
1044520Snw141292 	free(ptr);
1054520Snw141292 }
1064520Snw141292 
1074520Snw141292 
1085232Snw141292 #define	MIN_STACK_NEEDS	16384
1095232Snw141292 
1104520Snw141292 /*
1114520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1124520Snw141292  *
1134520Snw141292  * Output:
1144520Snw141292  * handle - idmap handle
1154520Snw141292  */
1164520Snw141292 idmap_stat
1175696Snw141292 idmap_init(idmap_handle_t **handle)
1185696Snw141292 {
1194520Snw141292 	CLIENT			*clnt = NULL;
1204520Snw141292 	struct idmap_handle	*hptr;
1215232Snw141292 	uint_t			sendsz = 0;
1225232Snw141292 	stack_t			st;
1234520Snw141292 
1244520Snw141292 	*handle = NULL;
1254520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1264520Snw141292 	if (hptr == NULL)
1274520Snw141292 		return (IDMAP_ERR_MEMORY);
1284520Snw141292 
1295232Snw141292 	/*
1305232Snw141292 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
1315232Snw141292 	 * the call args buffer and once for the call result buffer), so
1325232Snw141292 	 * we want to pick a sendsz that will be large enough, but not
1335232Snw141292 	 * too large.
1345232Snw141292 	 */
1355232Snw141292 	if (stack_getbounds(&st) == 0) {
1365232Snw141292 		/*
1375232Snw141292 		 * Estimate how much stack space is left;
1385232Snw141292 		 * st.ss_sp is the top of stack.
1395232Snw141292 		 */
1405232Snw141292 		if ((char *)&sendsz < (char *)st.ss_sp)
1415232Snw141292 			/* stack grows up */
1425232Snw141292 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
1435232Snw141292 		else
1445232Snw141292 			/* stack grows down */
1455232Snw141292 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
1465232Snw141292 
1475232Snw141292 		/*
1485232Snw141292 		 * Take much of the stack space left, divided by two,
1495232Snw141292 		 * but leave enough for our needs (just a guess!), and
1505232Snw141292 		 * if we can't, then roll the dice.
1515232Snw141292 		 */
1525232Snw141292 		sendsz = RNDUP(sendsz / 2);
1535232Snw141292 		if (sendsz < MIN_STACK_NEEDS)
1545232Snw141292 			sendsz = 0;	/* RPC call may fail */
1555232Snw141292 		else if (sendsz > IDMAP_MAX_DOOR_RPC)
1565232Snw141292 			sendsz = IDMAP_MAX_DOOR_RPC;
1575232Snw141292 	}
1585232Snw141292 
1595232Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
1604520Snw141292 	if (clnt == NULL) {
1614520Snw141292 		free(hptr);
1624520Snw141292 		return (IDMAP_ERR_RPC);
1634520Snw141292 	}
1644520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1654520Snw141292 	hptr->privhandle = clnt;
1664520Snw141292 	*handle = hptr;
1674520Snw141292 	return (IDMAP_SUCCESS);
1684520Snw141292 }
1694520Snw141292 
1704520Snw141292 
1714520Snw141292 /*
1724520Snw141292  * Finalize idmap handle
1734520Snw141292  *
1744520Snw141292  * Input:
1754520Snw141292  * handle - idmap handle
1764520Snw141292  */
1774520Snw141292 idmap_stat
1785696Snw141292 idmap_fini(idmap_handle_t *handle)
1795696Snw141292 {
1804520Snw141292 	CLIENT			*clnt;
1814520Snw141292 	struct idmap_handle	*hptr;
1824520Snw141292 
1834520Snw141292 	if (handle == NULL)
1844520Snw141292 		return (IDMAP_SUCCESS);
1854520Snw141292 
1864520Snw141292 	hptr = (struct idmap_handle *)handle;
1874520Snw141292 
1884520Snw141292 	switch (hptr->type) {
1894520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
1904520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
1914520Snw141292 		if (clnt) {
1924520Snw141292 			if (clnt->cl_auth)
1934520Snw141292 				auth_destroy(clnt->cl_auth);
1944520Snw141292 			clnt_destroy(clnt);
1954520Snw141292 		}
1964520Snw141292 		break;
1974520Snw141292 	default:
1984520Snw141292 		break;
1994520Snw141292 	}
2004520Snw141292 	free(hptr);
2014520Snw141292 	return (IDMAP_SUCCESS);
2024520Snw141292 }
2034520Snw141292 
2044520Snw141292 
2054520Snw141292 
2064520Snw141292 /*
2074520Snw141292  * Create/Initialize handle for updates
2084520Snw141292  *
2094520Snw141292  * Output:
2104520Snw141292  * udthandle - update handle
2114520Snw141292  */
2124520Snw141292 idmap_stat
2135696Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
2145696Snw141292 {
2154520Snw141292 	idmap_udt_handle_t	*tmp;
2164520Snw141292 
2174520Snw141292 	if (handle == NULL || udthandle == NULL) {
2184520Snw141292 		errno = EINVAL;
2194520Snw141292 		return (IDMAP_ERR_ARG);
2204520Snw141292 	}
2214520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
2224520Snw141292 		errno = ENOMEM;
2234520Snw141292 		return (IDMAP_ERR_MEMORY);
2244520Snw141292 	}
2254520Snw141292 
2264520Snw141292 	tmp->ih = handle;
2274520Snw141292 	*udthandle = tmp;
2284520Snw141292 	return (IDMAP_SUCCESS);
2294520Snw141292 }
2304520Snw141292 
2314520Snw141292 
2324520Snw141292 /*
2334520Snw141292  * All the updates specified by the update handle are committed
2344520Snw141292  * in a single transaction. i.e either all succeed or none.
2354520Snw141292  *
2364520Snw141292  * Input:
2374520Snw141292  * udthandle - update handle with the update requests
2384520Snw141292  *
2394520Snw141292  * Return value:
2404520Snw141292  * Status of the commit
2414520Snw141292  */
2424520Snw141292 idmap_stat
2435696Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle)
2445696Snw141292 {
2454520Snw141292 	CLIENT			*clnt;
2464520Snw141292 	enum clnt_stat		clntstat;
2475064Sdm199847 	idmap_update_res	res;
2485064Sdm199847 	idmap_stat		retcode;
2494520Snw141292 
2504520Snw141292 	if (udthandle == NULL) {
2514520Snw141292 		errno = EINVAL;
2524520Snw141292 		return (IDMAP_ERR_ARG);
2534520Snw141292 	}
2545064Sdm199847 
2555064Sdm199847 	(void) memset(&res, 0, sizeof (res));
2565064Sdm199847 
2574520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
2584520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
2595696Snw141292 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
2605696Snw141292 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
2615696Snw141292 	    TIMEOUT);
2624644Sbaban 
2635064Sdm199847 	if (clntstat != RPC_SUCCESS) {
2645064Sdm199847 		retcode = _idmap_rpc2stat(clnt);
2655064Sdm199847 		goto out;
2665064Sdm199847 	}
2675064Sdm199847 
2685064Sdm199847 	retcode = udthandle->commit_stat = res.retcode;
2695064Sdm199847 	udthandle->error_index = res.error_index;
2705064Sdm199847 
2715064Sdm199847 	if (retcode != IDMAP_SUCCESS) {
2725064Sdm199847 
2735064Sdm199847 		if (udthandle->error_index < 0)
2745064Sdm199847 			goto out;
2755064Sdm199847 
2765064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
2775064Sdm199847 		    &res.error_rule);
2785064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
2795064Sdm199847 			udthandle->error_index = -2;
2805064Sdm199847 			goto out;
2815064Sdm199847 		}
2825064Sdm199847 
2835064Sdm199847 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
2845064Sdm199847 		    &res.conflict_rule);
2855064Sdm199847 		if (retcode != IDMAP_SUCCESS) {
2865064Sdm199847 			udthandle->error_index = -2;
2875064Sdm199847 			goto out;
2885064Sdm199847 		}
2895064Sdm199847 	}
2905064Sdm199847 
2915064Sdm199847 	retcode = res.retcode;
2925064Sdm199847 
2935064Sdm199847 
2945064Sdm199847 out:
2954644Sbaban 	/* reset handle so that it can be used again */
2965064Sdm199847 	if (retcode == IDMAP_SUCCESS) {
2975064Sdm199847 		_IDMAP_RESET_UDT_HANDLE(udthandle);
2985064Sdm199847 	}
2995064Sdm199847 
3005064Sdm199847 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3015064Sdm199847 	errno = idmap_stat2errno(retcode);
3025064Sdm199847 	return (retcode);
3035064Sdm199847 }
3045064Sdm199847 
3055064Sdm199847 
3065064Sdm199847 static void
3075064Sdm199847 idmap_namerule_parts_clear(char **windomain, char **winname,
3085696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3095696Snw141292     boolean_t *is_nt4, int *direction)
3105696Snw141292 {
3115064Sdm199847 	if (windomain)
3125064Sdm199847 		*windomain = NULL;
3135064Sdm199847 	if (winname)
3145064Sdm199847 		*winname = NULL;
3155064Sdm199847 	if (unixname)
3165064Sdm199847 		*unixname = NULL;
3175064Sdm199847 
3185064Sdm199847 	if (is_nt4)
3195064Sdm199847 		*is_nt4 = 0;
3205064Sdm199847 	if (is_user)
3215064Sdm199847 		*is_user = -1;
3225696Snw141292 	if (is_wuser)
3235696Snw141292 		*is_wuser = -1;
3245064Sdm199847 	if (direction)
3255064Sdm199847 		*direction = IDMAP_DIRECTION_UNDEF;
3265064Sdm199847 }
3275064Sdm199847 
3285064Sdm199847 static idmap_stat
3295696Snw141292 idmap_namerule2parts(idmap_namerule *rule,
3305064Sdm199847     char **windomain, char **winname,
3315696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
3325696Snw141292     boolean_t *is_nt4, int *direction)
3335696Snw141292 {
3345064Sdm199847 	idmap_stat retcode;
3355064Sdm199847 
3365064Sdm199847 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
3375064Sdm199847 		return (IDMAP_ERR_NORESULT);
3385064Sdm199847 
3395064Sdm199847 
3405064Sdm199847 	retcode = idmap_strdupnull(windomain, rule->windomain);
3415064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3425064Sdm199847 		goto errout;
3435064Sdm199847 
3445064Sdm199847 	retcode = idmap_strdupnull(winname, rule->winname);
3455064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3465064Sdm199847 		goto errout;
3475064Sdm199847 
3485064Sdm199847 	retcode = idmap_strdupnull(unixname, rule->unixname);
3495064Sdm199847 	if (retcode != IDMAP_SUCCESS)
3505064Sdm199847 		goto errout;
3515064Sdm199847 
3525064Sdm199847 
3535064Sdm199847 	if (is_user)
3545064Sdm199847 		*is_user = rule->is_user;
3555696Snw141292 	if (is_wuser)
3565696Snw141292 		*is_wuser = rule->is_wuser;
3575064Sdm199847 	if (is_nt4)
3585064Sdm199847 		*is_nt4 = rule->is_nt4;
3595064Sdm199847 	if (direction)
3605064Sdm199847 		*direction = rule->direction;
3615064Sdm199847 
3625064Sdm199847 
3635064Sdm199847 	return (IDMAP_SUCCESS);
3644644Sbaban 
3655064Sdm199847 errout:
3665064Sdm199847 	if (windomain && *windomain)
3675064Sdm199847 		free(*windomain);
3685064Sdm199847 	if (winname && *winname)
3695064Sdm199847 		free(*winname);
3705064Sdm199847 	if (unixname && *unixname)
3715064Sdm199847 		free(*unixname);
3725064Sdm199847 
3735064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
3745696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
3755064Sdm199847 
3764520Snw141292 	return (retcode);
3775064Sdm199847 
3785064Sdm199847 }
3795064Sdm199847 
3805064Sdm199847 /*
3815064Sdm199847  * Retrieve the index of the failed batch element. error_index == -1
3825064Sdm199847  * indicates failure at the beginning, -2 at the end.
3835064Sdm199847  *
3845064Sdm199847  * If idmap_udt_commit didn't return error, the returned value is undefined.
3855064Sdm199847  *
3865064Sdm199847  * Return value:
3875064Sdm199847  * IDMAP_SUCCESS
3885064Sdm199847  */
3895064Sdm199847 
3905064Sdm199847 idmap_stat
3915064Sdm199847 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
3925696Snw141292     int64_t *error_index)
3935696Snw141292 {
3945064Sdm199847 	if (error_index)
3955064Sdm199847 		*error_index = udthandle->error_index;
3965064Sdm199847 
3975064Sdm199847 	return (IDMAP_SUCCESS);
3985064Sdm199847 }
3995064Sdm199847 
4005064Sdm199847 
4015064Sdm199847 /*
4025064Sdm199847  * Retrieve the rule which caused the batch to fail. If
4035064Sdm199847  * idmap_udt_commit didn't return error or if error_index is < 0, the
4045064Sdm199847  * retrieved rule is undefined.
4055064Sdm199847  *
4065064Sdm199847  * Return value:
4075064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
4085064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
4095064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
4105064Sdm199847  */
4115064Sdm199847 
4125064Sdm199847 idmap_stat
4135064Sdm199847 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
4145064Sdm199847     char **windomain, char **winname,
4155696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4165696Snw141292     boolean_t *is_nt4, int *direction)
4175696Snw141292 {
4185064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4195696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4205064Sdm199847 
4215064Sdm199847 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
4225064Sdm199847 	    udthandle->error_index < 0)
4235064Sdm199847 		return (IDMAP_ERR_NORESULT);
4245064Sdm199847 
4255064Sdm199847 	return (idmap_namerule2parts(
4265696Snw141292 	    &udthandle->error_rule,
4275696Snw141292 	    windomain,
4285696Snw141292 	    winname,
4295696Snw141292 	    unixname,
4305696Snw141292 	    is_user,
4315696Snw141292 	    is_wuser,
4325696Snw141292 	    is_nt4,
4335696Snw141292 	    direction));
4345064Sdm199847 }
4355064Sdm199847 
4365064Sdm199847 /*
4375064Sdm199847  * Retrieve the rule with which there was a conflict. TODO: retrieve
4385064Sdm199847  * the value.
4395064Sdm199847  *
4405064Sdm199847  * Return value:
4415064Sdm199847  * IDMAP_ERR_NORESULT if there is no error rule.
4425064Sdm199847  * IDMAP_SUCCESS if the rule was obtained OK.
4435064Sdm199847  * other error code (IDMAP_ERR_NOMEMORY etc)
4445064Sdm199847  */
4455064Sdm199847 
4465064Sdm199847 idmap_stat
4475064Sdm199847 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
4485064Sdm199847     char **windomain, char **winname,
4495696Snw141292     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
4505696Snw141292     boolean_t *is_nt4, int *direction)
4515696Snw141292 {
4525064Sdm199847 	idmap_namerule_parts_clear(windomain, winname,
4535696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
4545064Sdm199847 
4555064Sdm199847 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
4565064Sdm199847 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
4575696Snw141292 		return (IDMAP_ERR_NORESULT);
4585064Sdm199847 	}
4595064Sdm199847 
4605064Sdm199847 	return (idmap_namerule2parts(
4615696Snw141292 	    &udthandle->conflict_rule,
4625696Snw141292 	    windomain,
4635696Snw141292 	    winname,
4645696Snw141292 	    unixname,
4655696Snw141292 	    is_user,
4665696Snw141292 	    is_wuser,
4675696Snw141292 	    is_nt4,
4685696Snw141292 	    direction));
4694520Snw141292 }
4704520Snw141292 
4714520Snw141292 
4724520Snw141292 /*
4734520Snw141292  * Destroy the update handle
4744520Snw141292  */
4754520Snw141292 void
4765696Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle)
4775696Snw141292 {
4784520Snw141292 	if (udthandle == NULL)
4794520Snw141292 		return;
4804520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
4815064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
4825064Sdm199847 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
4834520Snw141292 	free(udthandle);
4844520Snw141292 }
4854520Snw141292 
4864520Snw141292 
4874520Snw141292 idmap_stat
4884520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
4895696Snw141292     boolean_t is_user, boolean_t is_wuser, const char *winname,
4905696Snw141292     const char *unixname, boolean_t is_nt4, int direction)
4915696Snw141292 {
4924520Snw141292 	idmap_retcode	retcode;
4934644Sbaban 	idmap_namerule	*rule = NULL;
4944520Snw141292 
4954644Sbaban 	retcode = _udt_extend_batch(udthandle);
4964520Snw141292 	if (retcode != IDMAP_SUCCESS)
4974520Snw141292 		goto errout;
4984520Snw141292 
4994520Snw141292 	rule = &udthandle->batch.
5005696Snw141292 	    idmap_update_batch_val[udthandle->next].
5015696Snw141292 	    idmap_update_op_u.rule;
5024520Snw141292 	rule->is_user = is_user;
5035696Snw141292 	rule->is_wuser = is_wuser;
5044520Snw141292 	rule->direction = direction;
5054520Snw141292 	rule->is_nt4 = is_nt4;
5065064Sdm199847 
5075064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
5085064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5095064Sdm199847 		goto errout;
5105064Sdm199847 
5115064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
5125064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5135064Sdm199847 		goto errout;
5145064Sdm199847 
5155064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
5165064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5175064Sdm199847 		goto errout;
5184644Sbaban 
5194644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5204644Sbaban 	    OP_ADD_NAMERULE;
5214520Snw141292 	udthandle->next++;
5224520Snw141292 	return (IDMAP_SUCCESS);
5234520Snw141292 
5244520Snw141292 errout:
5254644Sbaban 	/* The batch should still be usable */
5264644Sbaban 	if (rule)
5274644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5284520Snw141292 	errno = idmap_stat2errno(retcode);
5294520Snw141292 	return (retcode);
5304520Snw141292 }
5314520Snw141292 
5324520Snw141292 
5334520Snw141292 /* ARGSUSED */
5344520Snw141292 idmap_stat
5354520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
5365696Snw141292     boolean_t is_wuser,	const char *windomain, const char *winname,
5375696Snw141292     const char *unixname, int direction)
5385696Snw141292 {
5394520Snw141292 	idmap_retcode	retcode;
5404644Sbaban 	idmap_namerule	*rule = NULL;
5414520Snw141292 
5424644Sbaban 	retcode = _udt_extend_batch(udthandle);
5434520Snw141292 	if (retcode != IDMAP_SUCCESS)
5444520Snw141292 		goto errout;
5454520Snw141292 
5464520Snw141292 	rule = &udthandle->batch.
5475696Snw141292 	    idmap_update_batch_val[udthandle->next].
5485696Snw141292 	    idmap_update_op_u.rule;
5494520Snw141292 	rule->is_user = is_user;
5505696Snw141292 	rule->is_wuser = is_wuser;
5514520Snw141292 	rule->direction = direction;
5525064Sdm199847 
5535064Sdm199847 	retcode = idmap_strdupnull(&rule->windomain, windomain);
5545064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5555064Sdm199847 		goto errout;
5565064Sdm199847 
5575064Sdm199847 	retcode = idmap_strdupnull(&rule->winname, winname);
5585064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5595064Sdm199847 		goto errout;
5605064Sdm199847 
5615064Sdm199847 	retcode = idmap_strdupnull(&rule->unixname, unixname);
5625064Sdm199847 	if (retcode != IDMAP_SUCCESS)
5635064Sdm199847 		goto errout;
5645064Sdm199847 
5654644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5664644Sbaban 	    OP_RM_NAMERULE;
5674520Snw141292 	udthandle->next++;
5684520Snw141292 	return (IDMAP_SUCCESS);
5694520Snw141292 
5704520Snw141292 errout:
5714644Sbaban 	if (rule)
5724644Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
5734520Snw141292 	errno = idmap_stat2errno(retcode);
5744520Snw141292 	return (retcode);
5754520Snw141292 }
5764520Snw141292 
5774520Snw141292 
5784520Snw141292 /* ARGSUSED */
5794520Snw141292 idmap_stat
5805696Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
5815696Snw141292 {
5824520Snw141292 	idmap_retcode	retcode;
5834520Snw141292 
5844644Sbaban 	retcode = _udt_extend_batch(udthandle);
5854520Snw141292 	if (retcode != IDMAP_SUCCESS)
5864520Snw141292 		goto errout;
5874520Snw141292 
5884644Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
5894644Sbaban 	    OP_FLUSH_NAMERULES;
5904520Snw141292 	udthandle->next++;
5914520Snw141292 	return (IDMAP_SUCCESS);
5924520Snw141292 
5934520Snw141292 errout:
5944520Snw141292 	errno = idmap_stat2errno(retcode);
5954520Snw141292 	return (retcode);
5964520Snw141292 }
5974520Snw141292 
5984520Snw141292 
5994520Snw141292 /*
6004520Snw141292  * Set the number of entries requested per batch by the iterator
6014520Snw141292  *
6024520Snw141292  * Input:
6034520Snw141292  * iter  - iterator
6044520Snw141292  * limit - number of entries requested per batch
6054520Snw141292  */
6064520Snw141292 idmap_stat
6075696Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
6085696Snw141292 {
6094520Snw141292 	if (iter == NULL) {
6104520Snw141292 		errno = EINVAL;
6114520Snw141292 		return (IDMAP_ERR_ARG);
6124520Snw141292 	}
6134520Snw141292 	iter->limit = limit;
6144520Snw141292 	return (IDMAP_SUCCESS);
6154520Snw141292 }
6164520Snw141292 
6174520Snw141292 
6184520Snw141292 /*
6194520Snw141292  * Create iterator to get name-based mapping rules
6204520Snw141292  *
6214520Snw141292  * Input:
6224520Snw141292  * windomain - Windows domain
6234520Snw141292  * is_user   - user or group rules
6244520Snw141292  * winname   - Windows user or group name
6254520Snw141292  * unixname  - Unix user or group name
6264520Snw141292  *
6274520Snw141292  * Output:
6284520Snw141292  * iter - iterator
6294520Snw141292  */
6304520Snw141292 idmap_stat
6314520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
6325696Snw141292 		boolean_t is_user, boolean_t is_wuser, const char *winname,
6335696Snw141292 		const char *unixname, idmap_iter_t **iter)
6345696Snw141292 {
6354520Snw141292 
6364520Snw141292 	idmap_iter_t			*tmpiter;
6374520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
6384520Snw141292 	idmap_namerule			*rule;
6394520Snw141292 	idmap_retcode			retcode;
6404520Snw141292 
6414520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
6424520Snw141292 
6434520Snw141292 	rule = &arg->rule;
6444520Snw141292 	rule->is_user = is_user;
6455696Snw141292 	rule->is_wuser = is_wuser;
6464644Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
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;
6594520Snw141292 
6604520Snw141292 	*iter = tmpiter;
6614520Snw141292 	return (IDMAP_SUCCESS);
6624520Snw141292 
6634520Snw141292 errout:
6644520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
6655696Snw141292 	    xdr_idmap_list_namerules_1_argument, retcode);
6664520Snw141292 }
6674520Snw141292 
6684520Snw141292 
6694520Snw141292 /*
6704520Snw141292  * Iterate through the name-based mapping rules
6714520Snw141292  *
6724520Snw141292  * Input:
6734520Snw141292  * iter - iterator
6744520Snw141292  *
6754520Snw141292  * Output:
6764520Snw141292  * windomain - Windows domain
6774520Snw141292  * winname   - Windows user or group name
6784520Snw141292  * unixname  - Unix user or group name
6794520Snw141292  * is_nt4    - NT4 or AD
6804520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
6814520Snw141292  *
6824520Snw141292  * Return value:
6834520Snw141292  * 0   - done
6844520Snw141292  * 1   - more results available
6854520Snw141292  * < 0 - error
6864520Snw141292  */
6874520Snw141292 idmap_stat
6884520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
6895696Snw141292     char **winname, char **unixname,  boolean_t *is_user,
6905696Snw141292     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
6915696Snw141292 {
6924520Snw141292 	idmap_namerules_res		*namerules;
6934520Snw141292 	idmap_list_namerules_1_argument	*arg;
6944520Snw141292 	idmap_retcode			retcode;
6954520Snw141292 
6965696Snw141292 	idmap_namerule_parts_clear(windomain, winname,
6975696Snw141292 	    unixname, is_user, is_wuser, is_nt4, direction);
6985696Snw141292 
6994520Snw141292 
7004520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
7014520Snw141292 
7024520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
7034520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
7045696Snw141292 	    iter->next >= namerules->rules.rules_len)) {
7054520Snw141292 
7064520Snw141292 		if ((arg = iter->arg) == NULL) {
7074520Snw141292 			errno = EINVAL;
7084520Snw141292 			return (IDMAP_ERR_ARG);
7094520Snw141292 		}
7104520Snw141292 		arg->limit = iter->limit;
7114520Snw141292 
7124520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
7135696Snw141292 		    iter, arg,
7145696Snw141292 		    (uchar_t **)&namerules, sizeof (*namerules),
7155696Snw141292 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
7165696Snw141292 		    (xdrproc_t)xdr_idmap_namerules_res);
7174520Snw141292 		if (retcode != IDMAP_SUCCESS)
7184520Snw141292 			return (retcode);
7194520Snw141292 
7204520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
7214520Snw141292 			retcode  = namerules->retcode;
7224520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
7234520Snw141292 			free(namerules);
7244520Snw141292 			iter->retlist = NULL;
7254520Snw141292 			return (retcode);
7264520Snw141292 		}
7274520Snw141292 		iter->retcode = namerules->retcode;
7284520Snw141292 		arg->lastrowid = namerules->lastrowid;
7294520Snw141292 	}
7304520Snw141292 
7314520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
7324520Snw141292 		return (IDMAP_SUCCESS);
7334520Snw141292 
7344520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
7354520Snw141292 		return (IDMAP_ERR_ARG);
7364520Snw141292 	}
7374520Snw141292 
7385064Sdm199847 	retcode = idmap_strdupnull(windomain,
7395064Sdm199847 	    namerules->rules.rules_val[iter->next].windomain);
7405064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7415064Sdm199847 		goto errout;
7425064Sdm199847 
7435064Sdm199847 	retcode = idmap_strdupnull(winname,
7445064Sdm199847 	    namerules->rules.rules_val[iter->next].winname);
7455064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7465064Sdm199847 		goto errout;
7475064Sdm199847 
7485064Sdm199847 	retcode = idmap_strdupnull(unixname,
7495064Sdm199847 	    namerules->rules.rules_val[iter->next].unixname);
7505064Sdm199847 	if (retcode != IDMAP_SUCCESS)
7515064Sdm199847 		goto errout;
7525064Sdm199847 
7534520Snw141292 	if (is_nt4)
7544520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
7555696Snw141292 	if (is_user)
7565696Snw141292 		*is_user = namerules->rules.rules_val[iter->next].is_user;
7575696Snw141292 	if (is_wuser)
7585696Snw141292 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
7594520Snw141292 	if (direction)
7604520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
7614520Snw141292 	iter->next++;
7624520Snw141292 
7634520Snw141292 	if (iter->next == namerules->rules.rules_len)
7644520Snw141292 		return (iter->retcode);
7654520Snw141292 	else
7664520Snw141292 		return (IDMAP_NEXT);
7674520Snw141292 
7684520Snw141292 errout:
7694520Snw141292 	if (windomain && *windomain)
7704520Snw141292 		free(*windomain);
7714520Snw141292 	if (winname && *winname)
7724520Snw141292 		free(*winname);
7734520Snw141292 	if (unixname && *unixname)
7744520Snw141292 		free(*unixname);
7754520Snw141292 	return (retcode);
7764520Snw141292 }
7774520Snw141292 
7784520Snw141292 
7794520Snw141292 /*
7804520Snw141292  * Create iterator to get SID to UID/GID mappings
7814520Snw141292  *
7824520Snw141292  * Output:
7834520Snw141292  * iter - iterator
7844520Snw141292  */
7854520Snw141292 idmap_stat
786*6386Sjp151216 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
7875696Snw141292 {
7884520Snw141292 	idmap_iter_t			*tmpiter;
7894520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
7904520Snw141292 
7914520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
7924520Snw141292 
793*6386Sjp151216 	arg->flag = flag;
7944520Snw141292 	*iter = tmpiter;
7954520Snw141292 	return (IDMAP_SUCCESS);
7964520Snw141292 }
7974520Snw141292 
7984520Snw141292 
7994520Snw141292 /*
8004520Snw141292  * Iterate through the SID to UID/GID mappings
8014520Snw141292  *
8024520Snw141292  * Input:
8034520Snw141292  * iter - iterator
8044520Snw141292  *
8054520Snw141292  * Output:
8064520Snw141292  * sid - SID in canonical form
8074520Snw141292  * pid - UID or GID
8084520Snw141292  *
8094520Snw141292  * Return value:
8104520Snw141292  * 0   - done
8114520Snw141292  * 1   - more results available
8124520Snw141292  * < 0 - error
8134520Snw141292  */
8144520Snw141292 idmap_stat
8154520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
8165696Snw141292     idmap_rid_t *rid, uid_t *pid, char **winname,
8175696Snw141292     char **windomain, char **unixname, boolean_t *is_user,
818*6386Sjp151216     boolean_t *is_wuser, int *direction, idmap_info *info)
8195696Snw141292 {
8204520Snw141292 	idmap_mappings_res		*mappings;
8214520Snw141292 	idmap_list_mappings_1_argument	*arg;
8224520Snw141292 	idmap_retcode			retcode;
8234520Snw141292 	char				*str;
8244520Snw141292 
8254520Snw141292 	if (sidprefix)
8264520Snw141292 		*sidprefix = NULL;
8274520Snw141292 	if (rid)
8284520Snw141292 		*rid = UINT32_MAX;
8294520Snw141292 	if (winname)
8304520Snw141292 		*winname = NULL;
8314520Snw141292 	if (windomain)
8324520Snw141292 		*windomain = NULL;
8334520Snw141292 	if (unixname)
8344520Snw141292 		*unixname = NULL;
8354520Snw141292 	if (pid)
8364520Snw141292 		*pid = UINT32_MAX;
8375696Snw141292 	if (is_user)
8385696Snw141292 		*is_user = -1;
8395696Snw141292 	if (is_wuser)
8405696Snw141292 		*is_wuser = -1;
8414520Snw141292 	if (direction)
8424644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
8434520Snw141292 
8444520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
8454520Snw141292 
8464520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
8474520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
8485696Snw141292 	    iter->next >= mappings->mappings.mappings_len)) {
8494520Snw141292 
8504520Snw141292 		if ((arg = iter->arg) == NULL) {
8514520Snw141292 			errno = EINVAL;
8524520Snw141292 			return (IDMAP_ERR_ARG);
8534520Snw141292 		}
8544520Snw141292 		arg->limit = iter->limit;
8554520Snw141292 
8564520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
8575696Snw141292 		    iter, arg,
8585696Snw141292 		    (uchar_t **)&mappings, sizeof (*mappings),
8595696Snw141292 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
8605696Snw141292 		    (xdrproc_t)xdr_idmap_mappings_res);
8614520Snw141292 		if (retcode != IDMAP_SUCCESS)
8624520Snw141292 			return (retcode);
8634520Snw141292 
8644520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
8654520Snw141292 			retcode  = mappings->retcode;
8664520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
8674520Snw141292 			free(mappings);
8684520Snw141292 			iter->retlist = NULL;
8694520Snw141292 			return (retcode);
8704520Snw141292 		}
8714520Snw141292 		iter->retcode = mappings->retcode;
8724520Snw141292 		arg->lastrowid = mappings->lastrowid;
8734520Snw141292 	}
8744520Snw141292 
8754520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
8764520Snw141292 		return (IDMAP_SUCCESS);
8774520Snw141292 
8784520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
8794520Snw141292 		return (IDMAP_ERR_ARG);
8804520Snw141292 	}
8814520Snw141292 
8824520Snw141292 	if (sidprefix) {
8834520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
8845696Snw141292 		    idmap_id_u.sid.prefix;
8854695Sbaban 		if (str && *str != '\0') {
8864520Snw141292 			*sidprefix = strdup(str);
8874526Sbaban 			if (*sidprefix == NULL) {
8884526Sbaban 				retcode = IDMAP_ERR_MEMORY;
8894526Sbaban 				goto errout;
8904526Sbaban 			}
8914520Snw141292 		}
8924520Snw141292 	}
8934520Snw141292 	if (rid)
8944520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
8955696Snw141292 		    idmap_id_u.sid.rid;
8965064Sdm199847 
8975064Sdm199847 	retcode = idmap_strdupnull(windomain,
8985064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1domain);
8995064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9005064Sdm199847 		goto errout;
9015064Sdm199847 
9025064Sdm199847 	retcode = idmap_strdupnull(winname,
9035064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id1name);
9045064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9055064Sdm199847 		goto errout;
9065064Sdm199847 
9075064Sdm199847 	retcode = idmap_strdupnull(unixname,
9085064Sdm199847 	    mappings->mappings.mappings_val[iter->next].id2name);
9095064Sdm199847 	if (retcode != IDMAP_SUCCESS)
9105064Sdm199847 		goto errout;
9115064Sdm199847 
9125064Sdm199847 
9134520Snw141292 	if (pid)
9144520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
9155696Snw141292 		    idmap_id_u.uid;
9164520Snw141292 	if (direction)
9174520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
9185696Snw141292 		    direction;
9195696Snw141292 	if (is_user)
9205696Snw141292 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
9215696Snw141292 		    .idtype == IDMAP_UID)?1:0;
9225696Snw141292 	if (is_wuser)
9235696Snw141292 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
9245696Snw141292 		    .idtype == IDMAP_USID)?1:0;
9255696Snw141292 
926*6386Sjp151216 	if (info) {
927*6386Sjp151216 		retcode = idmap_info_cpy(info,
928*6386Sjp151216 		    &mappings->mappings.mappings_val[iter->next].info);
929*6386Sjp151216 		if (retcode != IDMAP_SUCCESS)
930*6386Sjp151216 			goto errout;
931*6386Sjp151216 	}
9324520Snw141292 	iter->next++;
9334520Snw141292 
9344520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
9354520Snw141292 		return (iter->retcode);
9364520Snw141292 	else
9374520Snw141292 		return (IDMAP_NEXT);
9384520Snw141292 
9394520Snw141292 errout:
9404520Snw141292 	if (sidprefix && *sidprefix)
9414520Snw141292 		free(*sidprefix);
9424520Snw141292 	if (winname && *winname)
9434520Snw141292 		free(*winname);
9444520Snw141292 	if (windomain && *windomain)
9454520Snw141292 		free(*windomain);
9464520Snw141292 	if (unixname && *unixname)
9474520Snw141292 		free(*unixname);
9484520Snw141292 	return (retcode);
9494520Snw141292 }
9504520Snw141292 
9514520Snw141292 
9524520Snw141292 /*
9534520Snw141292  * Destroy the iterator
9544520Snw141292  */
9554520Snw141292 void
9565696Snw141292 idmap_iter_destroy(idmap_iter_t *iter)
9575696Snw141292 {
9584520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
9594520Snw141292 
9604520Snw141292 	if (iter == NULL)
9614520Snw141292 		return;
9624520Snw141292 
9634520Snw141292 	switch (iter->type) {
9644520Snw141292 	case IDMAP_LIST_NAMERULES:
9654520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
9664520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
9674520Snw141292 		break;
9684520Snw141292 	case IDMAP_LIST_MAPPINGS:
9694520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
9704520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
9714520Snw141292 		break;
9724520Snw141292 	default:
9734520Snw141292 		free(iter);
9744520Snw141292 		return;
9754520Snw141292 	};
9764520Snw141292 
9774520Snw141292 	if (iter->arg) {
9784520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
9794520Snw141292 		free(iter->arg);
9804520Snw141292 	}
9814520Snw141292 	if (iter->retlist) {
9824520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
9834520Snw141292 		free(iter->retlist);
9844520Snw141292 	}
9854520Snw141292 	free(iter);
9864520Snw141292 }
9874520Snw141292 
9884520Snw141292 
9894520Snw141292 /*
9904520Snw141292  * Create handle to get SID to UID/GID mapping entries
9914520Snw141292  *
9924520Snw141292  * Input:
9934520Snw141292  * gh - "get mapping" handle
9944520Snw141292  */
9954520Snw141292 idmap_stat
9965696Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
9975696Snw141292 {
9984520Snw141292 	idmap_get_handle_t	*tmp;
9994520Snw141292 
10004520Snw141292 	/* sanity checks */
10014520Snw141292 	if (handle == NULL || gh == NULL) {
10024520Snw141292 		errno = EINVAL;
10034520Snw141292 		return (IDMAP_ERR_ARG);
10044520Snw141292 	}
10054520Snw141292 
10064520Snw141292 	/* allocate the handle */
10074520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
10084520Snw141292 		errno = ENOMEM;
10094520Snw141292 		return (IDMAP_ERR_MEMORY);
10104520Snw141292 	}
10114520Snw141292 
10124520Snw141292 	tmp->ih = handle;
10134520Snw141292 	*gh = tmp;
10144520Snw141292 	return (IDMAP_SUCCESS);
10154520Snw141292 }
10164520Snw141292 
10174520Snw141292 
10184520Snw141292 /*
10194520Snw141292  * Given SID, get UID
10204520Snw141292  *
10214520Snw141292  * Input:
10224520Snw141292  * sidprefix  - SID prefix
10234520Snw141292  * rid        - RID
10244520Snw141292  * flag       - flag
10254520Snw141292  *
10264520Snw141292  * Output:
10274520Snw141292  * stat - status of the get request
10284520Snw141292  * uid  - POSIX UID if stat = 0
10294520Snw141292  *
10304520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
10314520Snw141292  */
10324520Snw141292 idmap_stat
10334520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
10345696Snw141292 		int flag, uid_t *uid, idmap_stat *stat)
10355696Snw141292 {
1036*6386Sjp151216 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
1037*6386Sjp151216 	    NULL, stat));
1038*6386Sjp151216 }
10394520Snw141292 
1040*6386Sjp151216 /*
1041*6386Sjp151216  * Given SID, get UID
1042*6386Sjp151216  *
1043*6386Sjp151216  * Input:
1044*6386Sjp151216  * sidprefix  - SID prefix
1045*6386Sjp151216  * rid        - RID
1046*6386Sjp151216  * flag       - flag
1047*6386Sjp151216  *
1048*6386Sjp151216  * Output:
1049*6386Sjp151216  * stat - status of the get request
1050*6386Sjp151216  * uid  - POSIX UID if stat = 0
1051*6386Sjp151216  * how  - mapping type if stat = 0
1052*6386Sjp151216  *
1053*6386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
1054*6386Sjp151216  */
1055*6386Sjp151216 
1056*6386Sjp151216 idmap_stat
1057*6386Sjp151216 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1058*6386Sjp151216 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
1059*6386Sjp151216 {
10604520Snw141292 	idmap_retcode	retcode;
10614644Sbaban 	idmap_mapping	*mapping = NULL;
10624520Snw141292 
10634520Snw141292 	/* sanity checks */
10644520Snw141292 	if (gh == NULL)
10654520Snw141292 		return (IDMAP_ERR_ARG);
10664520Snw141292 	if (uid == NULL || sidprefix == NULL)
10674520Snw141292 		return (IDMAP_ERR_ARG);
10684520Snw141292 
10694520Snw141292 	/* Extend the request array and the return list */
10704520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
10714520Snw141292 		goto errout;
10724520Snw141292 
10734520Snw141292 	/* Setup the request */
10744520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
10754520Snw141292 	mapping->flag = flag;
10764520Snw141292 	mapping->id1.idtype = IDMAP_SID;
10774520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
10784520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
10794520Snw141292 		retcode = IDMAP_ERR_MEMORY;
10804520Snw141292 		goto errout;
10814520Snw141292 	}
10824520Snw141292 	mapping->id2.idtype = IDMAP_UID;
10834520Snw141292 
10844520Snw141292 	/* Setup pointers for the result */
10854520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
10864520Snw141292 	gh->retlist[gh->next].uid = uid;
10874520Snw141292 	gh->retlist[gh->next].stat = stat;
1088*6386Sjp151216 	gh->retlist[gh->next].info = info;
10894520Snw141292 
10904520Snw141292 	gh->next++;
10914520Snw141292 	return (IDMAP_SUCCESS);
10924520Snw141292 
10934520Snw141292 errout:
10944644Sbaban 	/* Batch created so far should still be usable */
10954644Sbaban 	if (mapping)
10964644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
10974520Snw141292 	errno = idmap_stat2errno(retcode);
10984520Snw141292 	return (retcode);
10994520Snw141292 }
11004520Snw141292 
11014520Snw141292 
11024520Snw141292 /*
11034520Snw141292  * Given SID, get GID
11044520Snw141292  *
11054520Snw141292  * Input:
11064520Snw141292  * sidprefix  - SID prefix
11074520Snw141292  * rid        - rid
11084520Snw141292  * flag       - flag
11094520Snw141292  *
11104520Snw141292  * Output:
11114520Snw141292  * stat - status of the get request
11124520Snw141292  * gid  - POSIX GID if stat = 0
11134520Snw141292  *
11144520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
11154520Snw141292  */
11164520Snw141292 idmap_stat
11174520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
11185696Snw141292 		int flag, gid_t *gid, idmap_stat *stat)
11195696Snw141292 {
1120*6386Sjp151216 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
1121*6386Sjp151216 	    NULL, stat));
1122*6386Sjp151216 }
1123*6386Sjp151216 
1124*6386Sjp151216 
1125*6386Sjp151216 /*
1126*6386Sjp151216  * Given SID, get GID
1127*6386Sjp151216  *
1128*6386Sjp151216  * Input:
1129*6386Sjp151216  * sidprefix  - SID prefix
1130*6386Sjp151216  * rid        - rid
1131*6386Sjp151216  * flag       - flag
1132*6386Sjp151216  *
1133*6386Sjp151216  * Output:
1134*6386Sjp151216  * stat - status of the get request
1135*6386Sjp151216  * gid  - POSIX GID if stat = 0
1136*6386Sjp151216  * how  - mapping type if stat = 0
1137*6386Sjp151216  *
1138*6386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
1139*6386Sjp151216  */
1140*6386Sjp151216 idmap_stat
1141*6386Sjp151216 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1142*6386Sjp151216 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
1143*6386Sjp151216 {
11444520Snw141292 
11454520Snw141292 	idmap_retcode	retcode;
11464644Sbaban 	idmap_mapping	*mapping = NULL;
11474520Snw141292 
11484520Snw141292 	/* sanity checks */
11494520Snw141292 	if (gh == NULL)
11504520Snw141292 		return (IDMAP_ERR_ARG);
11514520Snw141292 	if (gid == NULL || sidprefix == NULL)
11524520Snw141292 		return (IDMAP_ERR_ARG);
11534520Snw141292 
11544520Snw141292 	/* Extend the request array and the return list */
11554520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
11564520Snw141292 		goto errout;
11574520Snw141292 
11584520Snw141292 	/* Setup the request */
11594520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
11604520Snw141292 	mapping->flag = flag;
11614520Snw141292 	mapping->id1.idtype = IDMAP_SID;
11624520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
11634520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
11644520Snw141292 		retcode = IDMAP_ERR_MEMORY;
11654520Snw141292 		goto errout;
11664520Snw141292 	}
11674520Snw141292 	mapping->id2.idtype = IDMAP_GID;
11684520Snw141292 
11694520Snw141292 	/* Setup pointers for the result */
11704520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
11714520Snw141292 	gh->retlist[gh->next].gid = gid;
11724520Snw141292 	gh->retlist[gh->next].stat = stat;
1173*6386Sjp151216 	gh->retlist[gh->next].info = info;
11744520Snw141292 
11754520Snw141292 	gh->next++;
11764520Snw141292 	return (IDMAP_SUCCESS);
11774520Snw141292 
11784520Snw141292 errout:
11794644Sbaban 	if (mapping)
11804644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
11814520Snw141292 	errno = idmap_stat2errno(retcode);
11824520Snw141292 	return (retcode);
11834520Snw141292 }
11844520Snw141292 
11854520Snw141292 
1186*6386Sjp151216 
11874520Snw141292 /*
11884520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
11894520Snw141292  *
11904520Snw141292  * Input:
11914520Snw141292  * sidprefix  - SID prefix
11924520Snw141292  * rid        - rid
11934520Snw141292  * flag       - flag
11944520Snw141292  *
11954520Snw141292  * Output:
11964520Snw141292  * stat    - status of the get request
11974520Snw141292  * is_user - user or group
11984520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
11994520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
12004520Snw141292  *
12014520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12024520Snw141292  */
12034520Snw141292 idmap_stat
12044520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
12055696Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
12065696Snw141292 {
1207*6386Sjp151216 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
1208*6386Sjp151216 	    NULL, stat));
1209*6386Sjp151216 }
1210*6386Sjp151216 
1211*6386Sjp151216 
1212*6386Sjp151216 
1213*6386Sjp151216 /*
1214*6386Sjp151216  * Given SID, get POSIX ID i.e. UID/GID
1215*6386Sjp151216  *
1216*6386Sjp151216  * Input:
1217*6386Sjp151216  * sidprefix  - SID prefix
1218*6386Sjp151216  * rid        - rid
1219*6386Sjp151216  * flag       - flag
1220*6386Sjp151216  *
1221*6386Sjp151216  * Output:
1222*6386Sjp151216  * stat    - status of the get request
1223*6386Sjp151216  * is_user - user or group
1224*6386Sjp151216  * pid     - POSIX UID if stat = 0 and is_user = 1
1225*6386Sjp151216  *           POSIX GID if stat = 0 and is_user = 0
1226*6386Sjp151216  * how     - mapping type if stat = 0
1227*6386Sjp151216  *
1228*6386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
1229*6386Sjp151216  */
1230*6386Sjp151216 idmap_stat
1231*6386Sjp151216 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1232*6386Sjp151216 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
1233*6386Sjp151216 {
12344520Snw141292 	idmap_retcode	retcode;
12354644Sbaban 	idmap_mapping	*mapping = NULL;
12364520Snw141292 
12374520Snw141292 	/* sanity checks */
12384520Snw141292 	if (gh == NULL)
12394520Snw141292 		return (IDMAP_ERR_ARG);
12404520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
12414520Snw141292 		return (IDMAP_ERR_ARG);
12424520Snw141292 
12434520Snw141292 	/* Extend the request array and the return list */
12444520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
12454520Snw141292 		goto errout;
12464520Snw141292 
12474520Snw141292 	/* Setup the request */
12484520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
12494520Snw141292 	mapping->flag = flag;
12504520Snw141292 	mapping->id1.idtype = IDMAP_SID;
12514520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
12524520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
12534520Snw141292 		retcode = IDMAP_ERR_MEMORY;
12544520Snw141292 		goto errout;
12554520Snw141292 	}
12564520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
12574520Snw141292 
12584520Snw141292 	/* Setup pointers for the result */
12594520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
12604520Snw141292 	gh->retlist[gh->next].uid = pid;
12614520Snw141292 	gh->retlist[gh->next].gid = pid;
12624520Snw141292 	gh->retlist[gh->next].is_user = is_user;
12634520Snw141292 	gh->retlist[gh->next].stat = stat;
1264*6386Sjp151216 	gh->retlist[gh->next].info = info;
12654520Snw141292 
12664520Snw141292 	gh->next++;
12674520Snw141292 	return (IDMAP_SUCCESS);
12684520Snw141292 
12694520Snw141292 errout:
12704644Sbaban 	if (mapping)
12714644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
12724520Snw141292 	errno = idmap_stat2errno(retcode);
12734520Snw141292 	return (retcode);
12744520Snw141292 }
12754520Snw141292 
12764520Snw141292 
12774520Snw141292 /*
12784520Snw141292  * Given UID, get SID
12794520Snw141292  *
12804520Snw141292  * Input:
12814520Snw141292  * uid  - POSIX UID
12824520Snw141292  * flag - flag
12834520Snw141292  *
12844520Snw141292  * Output:
12854520Snw141292  * stat - status of the get request
12864520Snw141292  * sid  - SID prefix (if stat == 0)
12874520Snw141292  * rid  - rid
12884520Snw141292  *
12894520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
12904520Snw141292  */
12914520Snw141292 idmap_stat
12924520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
12935696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
12945696Snw141292 {
1295*6386Sjp151216 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
1296*6386Sjp151216 	    NULL, stat));
1297*6386Sjp151216 }
1298*6386Sjp151216 
1299*6386Sjp151216 
1300*6386Sjp151216 /*
1301*6386Sjp151216  * Given UID, get SID
1302*6386Sjp151216  *
1303*6386Sjp151216  * Input:
1304*6386Sjp151216  * uid  - POSIX UID
1305*6386Sjp151216  * flag - flag
1306*6386Sjp151216  *
1307*6386Sjp151216  * Output:
1308*6386Sjp151216  * stat - status of the get request
1309*6386Sjp151216  * sid  - SID prefix (if stat == 0)
1310*6386Sjp151216  * rid  - rid
1311*6386Sjp151216  * how  - mapping type if stat = 0
1312*6386Sjp151216  *
1313*6386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
1314*6386Sjp151216  */
1315*6386Sjp151216 idmap_stat
1316*6386Sjp151216 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
1317*6386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
1318*6386Sjp151216 {
13194520Snw141292 
13204520Snw141292 	idmap_retcode	retcode;
13214644Sbaban 	idmap_mapping	*mapping = NULL;
13224520Snw141292 
13234520Snw141292 	/* sanity checks */
13244520Snw141292 	if (gh == NULL)
13254520Snw141292 		return (IDMAP_ERR_ARG);
13264520Snw141292 	if (sidprefix == NULL)
13274520Snw141292 		return (IDMAP_ERR_ARG);
13284520Snw141292 
13294520Snw141292 	/* Extend the request array and the return list */
13304520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
13314520Snw141292 		goto errout;
13324520Snw141292 
13334520Snw141292 	/* Setup the request */
13344520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
13354520Snw141292 	mapping->flag = flag;
13364520Snw141292 	mapping->id1.idtype = IDMAP_UID;
13374520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
13384520Snw141292 	mapping->id2.idtype = IDMAP_SID;
13394520Snw141292 
13404520Snw141292 	/* Setup pointers for the result */
13414520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
13424520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
13434520Snw141292 	gh->retlist[gh->next].rid = rid;
13444520Snw141292 	gh->retlist[gh->next].stat = stat;
1345*6386Sjp151216 	gh->retlist[gh->next].info = info;
13464520Snw141292 
13474520Snw141292 	gh->next++;
13484520Snw141292 	return (IDMAP_SUCCESS);
13494520Snw141292 
13504520Snw141292 errout:
13514644Sbaban 	if (mapping)
13524644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
13534520Snw141292 	errno = idmap_stat2errno(retcode);
13544520Snw141292 	return (retcode);
13554520Snw141292 }
13564520Snw141292 
13574520Snw141292 
13584520Snw141292 /*
13594520Snw141292  * Given GID, get SID
13604520Snw141292  *
13614520Snw141292  * Input:
13624520Snw141292  * gid  - POSIX GID
13634520Snw141292  * flag - flag
13644520Snw141292  *
13654520Snw141292  * Output:
13664520Snw141292  * stat       - status of the get request
13674520Snw141292  * sidprefix  - SID prefix (if stat == 0)
13684520Snw141292  * rid        - rid
13694520Snw141292  *
13704520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
13714520Snw141292  */
13724520Snw141292 idmap_stat
13734520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
13745696Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
13755696Snw141292 {
1376*6386Sjp151216 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
1377*6386Sjp151216 	    NULL, stat));
1378*6386Sjp151216 }
1379*6386Sjp151216 
1380*6386Sjp151216 
1381*6386Sjp151216 /*
1382*6386Sjp151216  * Given GID, get SID
1383*6386Sjp151216  *
1384*6386Sjp151216  * Input:
1385*6386Sjp151216  * gid  - POSIX GID
1386*6386Sjp151216  * flag - flag
1387*6386Sjp151216  *
1388*6386Sjp151216  * Output:
1389*6386Sjp151216  * stat       - status of the get request
1390*6386Sjp151216  * sidprefix  - SID prefix (if stat == 0)
1391*6386Sjp151216  * rid        - rid
1392*6386Sjp151216  * how        - mapping type if stat = 0
1393*6386Sjp151216  *
1394*6386Sjp151216  * Note: The output parameters will be set by idmap_get_mappings()
1395*6386Sjp151216  */
1396*6386Sjp151216 idmap_stat
1397*6386Sjp151216 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
1398*6386Sjp151216 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
1399*6386Sjp151216 {
14004520Snw141292 
14014520Snw141292 	idmap_retcode	retcode;
14024644Sbaban 	idmap_mapping	*mapping = NULL;
14034520Snw141292 
14044520Snw141292 	/* sanity checks */
14054520Snw141292 	if (gh == NULL)
14064520Snw141292 		return (IDMAP_ERR_ARG);
14074520Snw141292 	if (sidprefix == NULL)
14084520Snw141292 		return (IDMAP_ERR_ARG);
14094520Snw141292 
14104520Snw141292 	/* Extend the request array and the return list */
14114520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
14124520Snw141292 		goto errout;
14134520Snw141292 
14144520Snw141292 	/* Setup the request */
14154520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
14164520Snw141292 	mapping->flag = flag;
14174520Snw141292 	mapping->id1.idtype = IDMAP_GID;
14184520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
14194520Snw141292 	mapping->id2.idtype = IDMAP_SID;
14204520Snw141292 
14214520Snw141292 	/* Setup pointers for the result */
14224520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
14234520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
14244520Snw141292 	gh->retlist[gh->next].rid = rid;
14254520Snw141292 	gh->retlist[gh->next].stat = stat;
1426*6386Sjp151216 	gh->retlist[gh->next].info = info;
14274520Snw141292 
14284520Snw141292 	gh->next++;
14294520Snw141292 	return (IDMAP_SUCCESS);
14304520Snw141292 
14314520Snw141292 errout:
14324644Sbaban 	if (mapping)
14334644Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
14344520Snw141292 	errno = idmap_stat2errno(retcode);
14354520Snw141292 	return (retcode);
14364520Snw141292 }
14374520Snw141292 
14384520Snw141292 
14394520Snw141292 /*
14404520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
14414520Snw141292  * status and identity) will be available in the data areas
14424520Snw141292  * provided by individual requests.
14434520Snw141292  */
14444520Snw141292 idmap_stat
14455696Snw141292 idmap_get_mappings(idmap_get_handle_t *gh)
14465696Snw141292 {
14474520Snw141292 	CLIENT		*clnt;
14484520Snw141292 	enum clnt_stat	clntstat;
14494520Snw141292 	idmap_retcode	retcode;
14504520Snw141292 	idmap_ids_res	res;
14514520Snw141292 	idmap_id	*id;
14524520Snw141292 	int		i;
14534520Snw141292 
14544520Snw141292 	if (gh == NULL) {
14554520Snw141292 		errno = EINVAL;
14564520Snw141292 		return (IDMAP_ERR_ARG);
14574520Snw141292 	}
14584520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
14594520Snw141292 
14604520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
14614520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
14625696Snw141292 	    (xdrproc_t)xdr_idmap_mapping_batch,
14635696Snw141292 	    (caddr_t)&gh->batch,
14645696Snw141292 	    (xdrproc_t)xdr_idmap_ids_res,
14655696Snw141292 	    (caddr_t)&res,
14665696Snw141292 	    TIMEOUT);
14674520Snw141292 	if (clntstat != RPC_SUCCESS) {
14684644Sbaban 		retcode = _idmap_rpc2stat(clnt);
14694520Snw141292 		goto out;
14704520Snw141292 	}
14714520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
14724520Snw141292 		retcode = res.retcode;
14734520Snw141292 		goto out;
14744520Snw141292 	}
14754520Snw141292 	for (i = 0; i < gh->next; i++) {
14764520Snw141292 		if (i >= res.ids.ids_len) {
14774520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
14784520Snw141292 			continue;
14794520Snw141292 		}
14804520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
14814520Snw141292 		id = &res.ids.ids_val[i].id;
14824520Snw141292 		switch (id->idtype) {
14834520Snw141292 		case IDMAP_UID:
14844520Snw141292 			if (gh->retlist[i].uid)
14854520Snw141292 				*gh->retlist[i].uid = id->idmap_id_u.uid;
14864520Snw141292 			if (gh->retlist[i].is_user)
14874520Snw141292 				*gh->retlist[i].is_user = 1;
14884520Snw141292 			break;
14894520Snw141292 		case IDMAP_GID:
14904520Snw141292 			if (gh->retlist[i].gid)
14914520Snw141292 				*gh->retlist[i].gid = id->idmap_id_u.gid;
14924520Snw141292 			if (gh->retlist[i].is_user)
14934520Snw141292 				*gh->retlist[i].is_user = 0;
14944520Snw141292 			break;
14954864Sbaban 		case IDMAP_POSIXID:
14964864Sbaban 			if (gh->retlist[i].uid)
14974864Sbaban 				*gh->retlist[i].uid = 60001;
14984864Sbaban 			if (gh->retlist[i].is_user)
14994864Sbaban 				*gh->retlist[i].is_user = -1;
15004864Sbaban 			break;
15014520Snw141292 		case IDMAP_SID:
15025696Snw141292 		case IDMAP_USID:
15035696Snw141292 		case IDMAP_GSID:
15044520Snw141292 			if (gh->retlist[i].rid)
15054520Snw141292 				*gh->retlist[i].rid = id->idmap_id_u.sid.rid;
15064520Snw141292 			if (gh->retlist[i].sidprefix) {
15074695Sbaban 				if (id->idmap_id_u.sid.prefix == NULL ||
15084695Sbaban 				    *id->idmap_id_u.sid.prefix == '\0') {
15094520Snw141292 					*gh->retlist[i].sidprefix = NULL;
15104520Snw141292 					break;
15114520Snw141292 				}
15124520Snw141292 				*gh->retlist[i].sidprefix =
15135696Snw141292 				    strdup(id->idmap_id_u.sid.prefix);
15144520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
15154520Snw141292 					*gh->retlist[i].stat =
15165696Snw141292 					    IDMAP_ERR_MEMORY;
15174520Snw141292 			}
15184520Snw141292 			break;
15194520Snw141292 		case IDMAP_NONE:
15204520Snw141292 			break;
15214520Snw141292 		default:
15224520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
15234520Snw141292 			break;
15244520Snw141292 		}
1525*6386Sjp151216 		if (gh->retlist[i].info != NULL)
1526*6386Sjp151216 			(void) idmap_info_cpy(gh->retlist[i].info,
1527*6386Sjp151216 			    &res.ids.ids_val[i].info);
15284520Snw141292 	}
15294520Snw141292 	retcode = IDMAP_SUCCESS;
15304520Snw141292 
15314520Snw141292 out:
15324644Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
15334520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
15344520Snw141292 	errno = idmap_stat2errno(retcode);
15354520Snw141292 	return (retcode);
15364520Snw141292 }
15374520Snw141292 
15384520Snw141292 
15394520Snw141292 /*
15404520Snw141292  * Destroy the "get mapping" handle
15414520Snw141292  */
15424520Snw141292 void
15435696Snw141292 idmap_get_destroy(idmap_get_handle_t *gh)
15445696Snw141292 {
15454520Snw141292 	if (gh == NULL)
15464520Snw141292 		return;
15474520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
15484520Snw141292 	if (gh->retlist)
15494520Snw141292 		free(gh->retlist);
15504520Snw141292 	free(gh);
15514520Snw141292 }
15524520Snw141292 
15534520Snw141292 
15544520Snw141292 /*
15554520Snw141292  * Get windows to unix mapping
15564520Snw141292  */
15574520Snw141292 idmap_stat
15584520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
15594520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
15604520Snw141292 		const char *winname, const char *windomain,
15615696Snw141292 		int flag, int *is_user, int *is_wuser,
1562*6386Sjp151216 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
15635696Snw141292 {
15644520Snw141292 	CLIENT			*clnt;
15654520Snw141292 	enum clnt_stat		clntstat;
15664520Snw141292 	idmap_mapping		request, *mapping;
15674520Snw141292 	idmap_mappings_res	result;
15684520Snw141292 	idmap_retcode		retcode, rc;
15694520Snw141292 
15704520Snw141292 	if (handle == NULL) {
15714520Snw141292 		errno = EINVAL;
15724520Snw141292 		return (IDMAP_ERR_ARG);
15734520Snw141292 	}
15744520Snw141292 
15754520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
15764520Snw141292 
15774520Snw141292 	(void) memset(&request, 0, sizeof (request));
15784520Snw141292 	(void) memset(&result, 0, sizeof (result));
15794520Snw141292 
15804520Snw141292 	if (pid)
15814520Snw141292 		*pid = UINT32_MAX;
15824520Snw141292 	if (unixname)
15834520Snw141292 		*unixname = NULL;
15844520Snw141292 	if (direction)
15854644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
15864520Snw141292 
15874520Snw141292 	request.flag = flag;
15884520Snw141292 	request.id1.idtype = IDMAP_SID;
15894520Snw141292 	if (sidprefix && rid) {
15904520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
15914520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
15924520Snw141292 	} else if (winname) {
15935064Sdm199847 		retcode = idmap_strdupnull(&request.id1name, winname);
15945247Sbaban 		if (retcode != IDMAP_SUCCESS)
15954520Snw141292 			goto out;
15965064Sdm199847 
15975064Sdm199847 		retcode = idmap_strdupnull(&request.id1domain, windomain);
15985247Sbaban 		if (retcode != IDMAP_SUCCESS)
15995064Sdm199847 			goto out;
16005064Sdm199847 
16014520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
16024520Snw141292 	} else {
16034520Snw141292 		errno = EINVAL;
16044520Snw141292 		return (IDMAP_ERR_ARG);
16054520Snw141292 	}
16064520Snw141292 
16075696Snw141292 	if (*is_user == 1)
16084520Snw141292 		request.id2.idtype = IDMAP_UID;
16094520Snw141292 	else if (*is_user == 0)
16104520Snw141292 		request.id2.idtype = IDMAP_GID;
16114520Snw141292 	else
16124520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
16134520Snw141292 
16145696Snw141292 	if (*is_wuser == 1)
16155696Snw141292 		request.id1.idtype = IDMAP_USID;
16165696Snw141292 	else if (*is_wuser == 0)
16175696Snw141292 		request.id1.idtype = IDMAP_GSID;
16185696Snw141292 	else
16195696Snw141292 		request.id1.idtype = IDMAP_SID;
16205696Snw141292 
16214520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
16225696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
16235696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
16245696Snw141292 	    TIMEOUT);
16254520Snw141292 
16264644Sbaban 	if (clntstat != RPC_SUCCESS)
16274644Sbaban 		return (_idmap_rpc2stat(clnt));
16284520Snw141292 
16294520Snw141292 	retcode = result.retcode;
16304520Snw141292 
16314520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
16324520Snw141292 		if (retcode == IDMAP_SUCCESS)
16334520Snw141292 			retcode = IDMAP_ERR_NORESULT;
16344520Snw141292 		goto out;
16354520Snw141292 	}
16364520Snw141292 
16374864Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
16385696Snw141292 		*is_user = 1;
16394864Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
16405696Snw141292 		*is_user = 0;
16414864Sbaban 	} else {
16424864Sbaban 		goto out;
16434864Sbaban 	}
16445696Snw141292 
16455696Snw141292 	if (mapping->id1.idtype == IDMAP_USID) {
16465696Snw141292 		*is_wuser = 1;
16475696Snw141292 	} else if (mapping->id1.idtype == IDMAP_GSID) {
16485696Snw141292 		*is_wuser = 0;
16495696Snw141292 	} else {
16505696Snw141292 		goto out;
16515696Snw141292 	}
16525696Snw141292 
16534520Snw141292 	if (direction)
16544520Snw141292 		*direction = mapping->direction;
16554520Snw141292 	if (pid)
16564520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
16575064Sdm199847 
16585064Sdm199847 	rc = idmap_strdupnull(unixname, mapping->id2name);
16595064Sdm199847 	if (rc != IDMAP_SUCCESS)
16605064Sdm199847 		retcode = rc;
16614520Snw141292 
1662*6386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
1663*6386Sjp151216 	if (rc != IDMAP_SUCCESS)
1664*6386Sjp151216 		retcode = rc;
1665*6386Sjp151216 
16664520Snw141292 out:
16674520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
16684520Snw141292 	if (retcode != IDMAP_SUCCESS)
16694520Snw141292 		errno = idmap_stat2errno(retcode);
16704520Snw141292 	return (retcode);
16714520Snw141292 }
16724520Snw141292 
16734520Snw141292 
16744520Snw141292 /*
16754520Snw141292  * Get unix to windows mapping
16764520Snw141292  */
16774520Snw141292 idmap_stat
16784520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
16794520Snw141292 		uid_t *pid, const char *unixname,
16805696Snw141292 		int flag, int is_user, int *is_wuser,
16814520Snw141292 		char **sidprefix, idmap_rid_t *rid,
16824520Snw141292 		char **winname, char **windomain,
1683*6386Sjp151216 		int *direction, idmap_info *info)
16845696Snw141292 {
16854520Snw141292 	CLIENT			*clnt;
16864520Snw141292 	enum clnt_stat		clntstat;
16874520Snw141292 	idmap_mapping		request, *mapping;
16884520Snw141292 	idmap_mappings_res	result;
16894520Snw141292 	idmap_retcode		retcode, rc;
16904520Snw141292 
16914520Snw141292 	if (handle == NULL) {
16924520Snw141292 		errno = EINVAL;
16934520Snw141292 		return (IDMAP_ERR_ARG);
16944520Snw141292 	}
16954520Snw141292 
16964520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
16974520Snw141292 
16984520Snw141292 	if (sidprefix)
16994520Snw141292 		*sidprefix = NULL;
17004520Snw141292 	if (winname)
17014520Snw141292 		*winname = NULL;
17024520Snw141292 	if (windomain)
17034520Snw141292 		*windomain = NULL;
17044520Snw141292 	if (rid)
17054520Snw141292 		*rid = UINT32_MAX;
17064520Snw141292 	if (direction)
17074644Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
17084520Snw141292 
17094520Snw141292 	(void) memset(&request, 0, sizeof (request));
17104520Snw141292 	(void) memset(&result, 0, sizeof (result));
17114520Snw141292 
17124520Snw141292 	request.flag = flag;
17134520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
17144520Snw141292 
17154520Snw141292 	if (pid && *pid != UINT32_MAX) {
17164520Snw141292 		request.id1.idmap_id_u.uid = *pid;
17174520Snw141292 	} else if (unixname) {
17185064Sdm199847 		request.id1name = (char *)unixname;
17194520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
17204520Snw141292 	} else {
17214520Snw141292 		errno = EINVAL;
17224520Snw141292 		return (IDMAP_ERR_ARG);
17234520Snw141292 	}
17244520Snw141292 
17255696Snw141292 	if (is_wuser == NULL)
17265696Snw141292 		request.id2.idtype = IDMAP_SID;
17275696Snw141292 	else if (*is_wuser == -1)
17285696Snw141292 		request.id2.idtype = IDMAP_SID;
17295696Snw141292 	else if (*is_wuser == 0)
17305696Snw141292 		request.id2.idtype = IDMAP_GSID;
17315696Snw141292 	else if (*is_wuser == 1)
17325696Snw141292 		request.id2.idtype = IDMAP_USID;
17334520Snw141292 
17344520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
17355696Snw141292 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
17365696Snw141292 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
17375696Snw141292 	    TIMEOUT);
17384520Snw141292 
17394644Sbaban 	if (clntstat != RPC_SUCCESS)
17404644Sbaban 		return (_idmap_rpc2stat(clnt));
17414520Snw141292 
17424520Snw141292 	retcode = result.retcode;
17434520Snw141292 
17444520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
17454520Snw141292 		if (retcode == IDMAP_SUCCESS)
17464520Snw141292 			retcode = IDMAP_ERR_NORESULT;
17474520Snw141292 		goto out;
17484520Snw141292 	}
17494520Snw141292 
17505696Snw141292 	if (direction != NULL)
17514520Snw141292 		*direction = mapping->direction;
17525696Snw141292 
1753*6386Sjp151216 	if (is_wuser != NULL) {
1754*6386Sjp151216 		if (mapping->id2.idtype == IDMAP_USID)
1755*6386Sjp151216 			*is_wuser = 1;
1756*6386Sjp151216 		else if (mapping->id2.idtype == IDMAP_GSID)
1757*6386Sjp151216 			*is_wuser = 0;
1758*6386Sjp151216 		else
1759*6386Sjp151216 			*is_wuser = -1;
1760*6386Sjp151216 	}
17615696Snw141292 
17624695Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
17634695Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
17644520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
17654520Snw141292 		if (*sidprefix == NULL) {
17664520Snw141292 			retcode = IDMAP_ERR_MEMORY;
17674520Snw141292 			goto errout;
17684520Snw141292 		}
17694520Snw141292 	}
17704520Snw141292 	if (rid)
17714520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
17725064Sdm199847 
17735064Sdm199847 	rc = idmap_strdupnull(winname, mapping->id2name);
17745064Sdm199847 	if (rc != IDMAP_SUCCESS)
17755064Sdm199847 		retcode = rc;
17765064Sdm199847 
17775064Sdm199847 	rc = idmap_strdupnull(windomain, mapping->id2domain);
17785064Sdm199847 	if (rc != IDMAP_SUCCESS)
17795064Sdm199847 		retcode = rc;
17804520Snw141292 
1781*6386Sjp151216 	rc = idmap_info_cpy(info, &mapping->info);
1782*6386Sjp151216 	if (rc != IDMAP_SUCCESS)
1783*6386Sjp151216 		retcode = rc;
1784*6386Sjp151216 
17854520Snw141292 	goto out;
17864520Snw141292 
17874520Snw141292 errout:
17884520Snw141292 	if (sidprefix && *sidprefix) {
17894520Snw141292 		free(*sidprefix);
17904520Snw141292 		*sidprefix = NULL;
17914520Snw141292 	}
17924520Snw141292 	if (winname && *winname) {
17934520Snw141292 		free(*winname);
17944520Snw141292 		*winname = NULL;
17954520Snw141292 	}
17964520Snw141292 	if (windomain && *windomain) {
17974520Snw141292 		free(*windomain);
17984520Snw141292 		*windomain = NULL;
17994520Snw141292 	}
18004520Snw141292 
18014520Snw141292 out:
18024520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
18034520Snw141292 	if (retcode != IDMAP_SUCCESS)
18044520Snw141292 		errno = idmap_stat2errno(retcode);
18054520Snw141292 	return (retcode);
18064520Snw141292 }
18074520Snw141292 
18084520Snw141292 
18094520Snw141292 
18104520Snw141292 #define	gettext(s)	s
18114520Snw141292 static stat_table_t stattable[] = {
18124520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
18134520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
18144520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
18154520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
18164520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
18174520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
18184520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
18194520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
18204644Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
18214520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
18224520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
18234520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
18244520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
18254520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
18264520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
18274520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
18284520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
18294520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
18304644Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
18314520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
18324520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
18334644Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
18344695Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
18354520Snw141292 	{IDMAP_ERR_NOMAPPING,
18364520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
18374520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
18384520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
18394520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
18404520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
18414520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
18424520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
18434520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
18444520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
18454520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
18464520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
18474520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
18484520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
18494864Sbaban 		gettext("Windows lookup failed"), EINVAL},
18504864Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
18514864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
18524864Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
18534864Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
18544864Sbaban 		gettext("Duplicate rule or conflicts with an existing "
18554864Sbaban 		"Unix to Windows name-based rule"), EINVAL},
18565968Snw141292 	{IDMAP_ERR_BAD_UTF8,
18575968Snw141292 		gettext("Invalid or illegal UTF-8 sequence found in "
18585968Snw141292 		"a given Windows entity name or domain name"), EINVAL},
1859*6386Sjp151216 	{IDMAP_ERR_NONEGENERATED,
1860*6386Sjp151216 		gettext("Mapping not found and none created (see -c option)"),
1861*6386Sjp151216 		EINVAL},
18624520Snw141292 	{-1, NULL, 0}
18634520Snw141292 };
18644520Snw141292 #undef	gettext
18654520Snw141292 
18664520Snw141292 
18674520Snw141292 /*
18684520Snw141292  * Get description of status code
18694520Snw141292  *
18704520Snw141292  * Input:
18714520Snw141292  * status - Status code returned by libidmap API call
18724520Snw141292  *
18734520Snw141292  * Return Value:
18744520Snw141292  * human-readable localized description of idmap_stat
18754520Snw141292  */
18764520Snw141292 /* ARGSUSED */
18774520Snw141292 const char *
18785696Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
18795696Snw141292 {
18804520Snw141292 	int i;
18814520Snw141292 
18824520Snw141292 	for (i = 0; stattable[i].msg; i++) {
18834520Snw141292 		if (stattable[i].retcode == status)
18844526Sbaban 			return (gettext(stattable[i].msg));
18854520Snw141292 	}
18864520Snw141292 	return (gettext("Unknown error"));
18874520Snw141292 }
18884520Snw141292 
18894520Snw141292 
18904520Snw141292 static int
18915696Snw141292 idmap_stat2errno(idmap_stat stat)
18925696Snw141292 {
18934520Snw141292 	int i;
18944520Snw141292 	for (i = 0; stattable[i].msg; i++) {
18954520Snw141292 		if (stattable[i].retcode == stat)
18964520Snw141292 			return (stattable[i].errnum);
18974520Snw141292 	}
18984520Snw141292 	return (EINVAL);
18994520Snw141292 }
19004520Snw141292 
19014520Snw141292 
19024520Snw141292 /*
19034520Snw141292  * Get status code from string
19044520Snw141292  */
19054520Snw141292 idmap_stat
19065696Snw141292 idmap_string2stat(const char *str)
19075696Snw141292 {
19084520Snw141292 	if (str == NULL)
19094520Snw141292 		return (IDMAP_ERR_INTERNAL);
19104520Snw141292 
19114520Snw141292 #define	return_cmp(a) \
19124520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
19134520Snw141292 		return (IDMAP_ERR_ ## a);
19144520Snw141292 
19154520Snw141292 	return_cmp(OTHER);
19164520Snw141292 	return_cmp(INTERNAL);
19174520Snw141292 	return_cmp(MEMORY);
19184520Snw141292 	return_cmp(NORESULT);
19194520Snw141292 	return_cmp(NOTUSER);
19204520Snw141292 	return_cmp(NOTGROUP);
19214520Snw141292 	return_cmp(NOTSUPPORTED);
19224520Snw141292 	return_cmp(W2U_NAMERULE);
19234520Snw141292 	return_cmp(U2W_NAMERULE);
19244520Snw141292 	return_cmp(CACHE);
19254520Snw141292 	return_cmp(DB);
19264520Snw141292 	return_cmp(ARG);
19274520Snw141292 	return_cmp(SID);
19284520Snw141292 	return_cmp(IDTYPE);
19294520Snw141292 	return_cmp(RPC_HANDLE);
19304520Snw141292 	return_cmp(RPC);
19314520Snw141292 	return_cmp(CLIENT_HANDLE);
19324520Snw141292 	return_cmp(BUSY);
19334520Snw141292 	return_cmp(PERMISSION_DENIED);
19344520Snw141292 	return_cmp(NOMAPPING);
19354520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
19364520Snw141292 	return_cmp(DOMAIN);
19374520Snw141292 	return_cmp(SECURITY);
19384520Snw141292 	return_cmp(NOTFOUND);
19394520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
19404520Snw141292 	return_cmp(MEMORY);
19414520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
19424520Snw141292 	return_cmp(CFG);
19434520Snw141292 	return_cmp(CFG_CHANGE);
19444520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
19454520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
19464864Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
19474864Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
19484520Snw141292 #undef return_cmp
19494520Snw141292 
19504520Snw141292 	return (IDMAP_ERR_OTHER);
19514520Snw141292 }
19524520Snw141292 
19534520Snw141292 
19544520Snw141292 /*
19554520Snw141292  * Map the given status to one that can be returned by the protocol
19564520Snw141292  */
19574520Snw141292 idmap_stat
19585696Snw141292 idmap_stat4prot(idmap_stat status)
19595696Snw141292 {
19604520Snw141292 	switch (status) {
19614520Snw141292 	case IDMAP_ERR_MEMORY:
19624520Snw141292 	case IDMAP_ERR_CACHE:
19634520Snw141292 		return (IDMAP_ERR_INTERNAL);
19644520Snw141292 	}
19654520Snw141292 	return (status);
19664520Snw141292 }
19675043Sbaban 
19685043Sbaban 
19695043Sbaban /*
19705247Sbaban  * This is a convenience routine which duplicates a string after
19715247Sbaban  * checking for NULL pointers. This function will return success if
19725247Sbaban  * either the 'to' OR 'from' pointers are NULL.
19735064Sdm199847  */
19745064Sdm199847 static idmap_stat
19755696Snw141292 idmap_strdupnull(char **to, const char *from)
19765696Snw141292 {
19775247Sbaban 	if (to == NULL)
19785247Sbaban 		return (IDMAP_SUCCESS);
19795247Sbaban 
19805064Sdm199847 	if (from == NULL || *from == '\0') {
19815064Sdm199847 		*to = NULL;
19825064Sdm199847 		return (IDMAP_SUCCESS);
19835064Sdm199847 	}
19845064Sdm199847 
19855064Sdm199847 	*to = strdup(from);
19865064Sdm199847 	if (*to == NULL)
19875064Sdm199847 		return (IDMAP_ERR_MEMORY);
19885064Sdm199847 	return (IDMAP_SUCCESS);
19895064Sdm199847 }
19905064Sdm199847 
1991*6386Sjp151216 
19925064Sdm199847 idmap_stat
19935696Snw141292 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
19945696Snw141292 {
19955064Sdm199847 	idmap_stat retval;
19965064Sdm199847 
1997*6386Sjp151216 	if (to == NULL)
1998*6386Sjp151216 		return (IDMAP_SUCCESS);
1999*6386Sjp151216 
20005064Sdm199847 	(void) memcpy(to, from, sizeof (idmap_namerule));
2001*6386Sjp151216 	to->windomain = NULL;
2002*6386Sjp151216 	to->winname = NULL;
2003*6386Sjp151216 	to->unixname = NULL;
20045064Sdm199847 
20055064Sdm199847 	retval = idmap_strdupnull(&to->windomain, from->windomain);
20065064Sdm199847 	if (retval != IDMAP_SUCCESS)
20075064Sdm199847 		return (retval);
20085064Sdm199847 
20095064Sdm199847 	retval = idmap_strdupnull(&to->winname, from->winname);
2010*6386Sjp151216 	if (retval != IDMAP_SUCCESS) {
2011*6386Sjp151216 		free(to->windomain);
2012*6386Sjp151216 		to->windomain = NULL;
2013*6386Sjp151216 		return (retval);
2014*6386Sjp151216 	}
2015*6386Sjp151216 
2016*6386Sjp151216 	retval = idmap_strdupnull(&to->unixname, from->unixname);
2017*6386Sjp151216 	if (retval != IDMAP_SUCCESS) {
2018*6386Sjp151216 		free(to->windomain);
2019*6386Sjp151216 		to->windomain = NULL;
2020*6386Sjp151216 		free(to->winname);
2021*6386Sjp151216 		to->winname = NULL;
2022*6386Sjp151216 		return (retval);
2023*6386Sjp151216 	}
2024*6386Sjp151216 
2025*6386Sjp151216 	return (retval);
2026*6386Sjp151216 }
2027*6386Sjp151216 
2028*6386Sjp151216 
2029*6386Sjp151216 static
2030*6386Sjp151216 idmap_stat
2031*6386Sjp151216 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
2032*6386Sjp151216 {
2033*6386Sjp151216 	idmap_stat retval;
2034*6386Sjp151216 
2035*6386Sjp151216 	if (to == NULL)
2036*6386Sjp151216 		return (IDMAP_SUCCESS);
2037*6386Sjp151216 
2038*6386Sjp151216 	retval = idmap_strdupnull(&to->dn, from->dn);
20395064Sdm199847 	if (retval != IDMAP_SUCCESS)
20405064Sdm199847 		return (retval);
20415064Sdm199847 
2042*6386Sjp151216 	retval = idmap_strdupnull(&to->attr, from->attr);
2043*6386Sjp151216 	if (retval != IDMAP_SUCCESS) {
2044*6386Sjp151216 		free(to->dn);
2045*6386Sjp151216 		to->dn = NULL;
2046*6386Sjp151216 		return (retval);
2047*6386Sjp151216 	}
2048*6386Sjp151216 
2049*6386Sjp151216 	retval = idmap_strdupnull(&to->value, from->value);
2050*6386Sjp151216 	if (retval != IDMAP_SUCCESS) {
2051*6386Sjp151216 		free(to->dn);
2052*6386Sjp151216 		to->dn = NULL;
2053*6386Sjp151216 		free(to->attr);
2054*6386Sjp151216 		to->attr = NULL;
2055*6386Sjp151216 		return (retval);
2056*6386Sjp151216 	}
20575064Sdm199847 
20585064Sdm199847 	return (retval);
20595064Sdm199847 }
20605064Sdm199847 
20615064Sdm199847 
2062*6386Sjp151216 idmap_stat
2063*6386Sjp151216 idmap_info_cpy(idmap_info *to, idmap_info *from)
2064*6386Sjp151216 {
2065*6386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
2066*6386Sjp151216 
2067*6386Sjp151216 	if (to == NULL)
2068*6386Sjp151216 		return (IDMAP_SUCCESS);
2069*6386Sjp151216 
2070*6386Sjp151216 	(void) memset(to, 0, sizeof (idmap_info));
2071*6386Sjp151216 
2072*6386Sjp151216 	to->src = from->src;
2073*6386Sjp151216 	to->how.map_type = from->how.map_type;
2074*6386Sjp151216 	switch (to->how.map_type) {
2075*6386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
2076*6386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
2077*6386Sjp151216 		    &from->how.idmap_how_u.ad);
2078*6386Sjp151216 		break;
2079*6386Sjp151216 
2080*6386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
2081*6386Sjp151216 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
2082*6386Sjp151216 		    &from->how.idmap_how_u.nldap);
2083*6386Sjp151216 		break;
2084*6386Sjp151216 
2085*6386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
2086*6386Sjp151216 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
2087*6386Sjp151216 		    &from->how.idmap_how_u.rule);
2088*6386Sjp151216 		break;
2089*6386Sjp151216 
2090*6386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
2091*6386Sjp151216 		break;
2092*6386Sjp151216 
2093*6386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
2094*6386Sjp151216 		break;
2095*6386Sjp151216 
2096*6386Sjp151216 	case IDMAP_MAP_TYPE_KNOWN_SID:
2097*6386Sjp151216 		break;
2098*6386Sjp151216 	}
2099*6386Sjp151216 	return (retval);
2100*6386Sjp151216 }
2101*6386Sjp151216 
2102*6386Sjp151216 
2103*6386Sjp151216 /*
2104*6386Sjp151216  * This routine is similar to idmap_info_cpy, but the strings
2105*6386Sjp151216  * are moved from the "from" info to the "to" info.
2106*6386Sjp151216  * This routine is equivelent of:
2107*6386Sjp151216  *
2108*6386Sjp151216  *	idmap_info_cpy(to,from);
2109*6386Sjp151216  *	idmap_info_free(from);
2110*6386Sjp151216  */
2111*6386Sjp151216 idmap_stat
2112*6386Sjp151216 idmap_info_mov(idmap_info *to, idmap_info *from)
2113*6386Sjp151216 {
2114*6386Sjp151216 	idmap_stat retval = IDMAP_SUCCESS;
2115*6386Sjp151216 
2116*6386Sjp151216 	if (to == NULL) {
2117*6386Sjp151216 		idmap_info_free(from);
2118*6386Sjp151216 		return (IDMAP_SUCCESS);
2119*6386Sjp151216 	}
2120*6386Sjp151216 	(void) memcpy(to, from, sizeof (idmap_info));
2121*6386Sjp151216 
2122*6386Sjp151216 	(void) memset(from, 0, sizeof (idmap_info));
2123*6386Sjp151216 
2124*6386Sjp151216 	return (retval);
2125*6386Sjp151216 }
2126*6386Sjp151216 
2127*6386Sjp151216 
2128*6386Sjp151216 void
2129*6386Sjp151216 idmap_info_free(idmap_info *info)
2130*6386Sjp151216 {
2131*6386Sjp151216 	idmap_how *how;
2132*6386Sjp151216 
2133*6386Sjp151216 	if (info == NULL)
2134*6386Sjp151216 		return;
2135*6386Sjp151216 
2136*6386Sjp151216 	how = &info->how;
2137*6386Sjp151216 	switch (how->map_type) {
2138*6386Sjp151216 	case IDMAP_MAP_TYPE_DS_AD:
2139*6386Sjp151216 		free(how->idmap_how_u.ad.dn);
2140*6386Sjp151216 		how->idmap_how_u.ad.dn = NULL;
2141*6386Sjp151216 		free(how->idmap_how_u.ad.attr);
2142*6386Sjp151216 		how->idmap_how_u.ad.attr = NULL;
2143*6386Sjp151216 		free(how->idmap_how_u.ad.value);
2144*6386Sjp151216 		how->idmap_how_u.ad.value = NULL;
2145*6386Sjp151216 		break;
2146*6386Sjp151216 
2147*6386Sjp151216 	case IDMAP_MAP_TYPE_DS_NLDAP:
2148*6386Sjp151216 		free(how->idmap_how_u.nldap.dn);
2149*6386Sjp151216 		how->idmap_how_u.nldap.dn = NULL;
2150*6386Sjp151216 		free(how->idmap_how_u.nldap.attr);
2151*6386Sjp151216 		how->idmap_how_u.nldap.attr = NULL;
2152*6386Sjp151216 		free(how->idmap_how_u.nldap.value);
2153*6386Sjp151216 		how->idmap_how_u.nldap.value = NULL;
2154*6386Sjp151216 		break;
2155*6386Sjp151216 
2156*6386Sjp151216 	case IDMAP_MAP_TYPE_RULE_BASED:
2157*6386Sjp151216 		free(how->idmap_how_u.rule.windomain);
2158*6386Sjp151216 		how->idmap_how_u.rule.windomain = NULL;
2159*6386Sjp151216 		free(how->idmap_how_u.rule.winname);
2160*6386Sjp151216 		how->idmap_how_u.rule.winname = NULL;
2161*6386Sjp151216 		free(how->idmap_how_u.rule.unixname);
2162*6386Sjp151216 		how->idmap_how_u.rule.unixname = NULL;
2163*6386Sjp151216 		break;
2164*6386Sjp151216 
2165*6386Sjp151216 	case IDMAP_MAP_TYPE_EPHEMERAL:
2166*6386Sjp151216 		break;
2167*6386Sjp151216 
2168*6386Sjp151216 	case IDMAP_MAP_TYPE_LOCAL_SID:
2169*6386Sjp151216 		break;
2170*6386Sjp151216 	}
2171*6386Sjp151216 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
2172*6386Sjp151216 	info->src = IDMAP_MAP_SRC_UNKNOWN;
2173*6386Sjp151216 }
2174*6386Sjp151216 
2175*6386Sjp151216 
21765064Sdm199847 /*
21775043Sbaban  * Get uid given Windows name
21785043Sbaban  */
21795043Sbaban idmap_stat
21805696Snw141292 idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid)
21815696Snw141292 {
21825043Sbaban 	idmap_handle_t	*ih;
21835043Sbaban 	idmap_retcode	rc;
21845696Snw141292 	int		is_user = 1;
21855696Snw141292 	int		is_wuser = -1;
21865043Sbaban 
21875043Sbaban 	if (uid == NULL)
21885043Sbaban 		return (IDMAP_ERR_ARG);
21895043Sbaban 
21905043Sbaban 	/* Get mapping */
21915043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
21925043Sbaban 		return (rc);
21935043Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
2194*6386Sjp151216 	    &is_user, &is_wuser, uid, NULL, NULL, NULL);
21955043Sbaban 	(void) idmap_fini(ih);
21965043Sbaban 
21975043Sbaban 	/*
21985043Sbaban 	 * XXX Until we have diagonal mapping support, check if
21995043Sbaban 	 * the given name belongs to a user
22005043Sbaban 	 */
22015043Sbaban 	if (rc == IDMAP_SUCCESS && !is_user)
22025043Sbaban 		return (IDMAP_ERR_NOTUSER);
22035043Sbaban 	return (rc);
22045043Sbaban }
22055043Sbaban 
22065043Sbaban 
22075043Sbaban /*
22085043Sbaban  * Get gid given Windows name
22095043Sbaban  */
22105043Sbaban idmap_stat
22115696Snw141292 idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid)
22125696Snw141292 {
22135043Sbaban 	idmap_handle_t	*ih;
22145043Sbaban 	idmap_retcode	rc;
22155696Snw141292 	int		is_user = 0;
22165696Snw141292 	int		is_wuser = -1;
22175043Sbaban 
22185043Sbaban 	if (gid == NULL)
22195043Sbaban 		return (IDMAP_ERR_ARG);
22205043Sbaban 
22215043Sbaban 	/* Get mapping */
22225043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
22235043Sbaban 		return (rc);
22245043Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
2225*6386Sjp151216 	    &is_user, &is_wuser, gid, NULL, NULL, NULL);
22265043Sbaban 	(void) idmap_fini(ih);
22275043Sbaban 
22285043Sbaban 	/*
22295043Sbaban 	 * XXX Until we have diagonal mapping support, check if
22305043Sbaban 	 * the given name belongs to a group
22315043Sbaban 	 */
22325043Sbaban 	if (rc == IDMAP_SUCCESS && is_user)
22335043Sbaban 		return (IDMAP_ERR_NOTGROUP);
22345043Sbaban 	return (rc);
22355043Sbaban }
22365043Sbaban 
22375043Sbaban 
22385043Sbaban /*
22395043Sbaban  * Get winname given pid
22405043Sbaban  */
22415043Sbaban static idmap_retcode
22425696Snw141292 idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain)
22435696Snw141292 {
22445043Sbaban 	idmap_handle_t	*ih;
22455043Sbaban 	idmap_retcode	rc;
22465043Sbaban 	int		len;
22475043Sbaban 	char		*winname, *windomain;
22485043Sbaban 
22495043Sbaban 	if (name == NULL)
22505043Sbaban 		return (IDMAP_ERR_ARG);
22515043Sbaban 
22525043Sbaban 	/* Get mapping */
22535043Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
22545043Sbaban 		return (rc);
22555696Snw141292 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, NULL,
2256*6386Sjp151216 	    NULL, &winname, &windomain, NULL, NULL);
22575043Sbaban 	(void) idmap_fini(ih);
22585043Sbaban 
22595043Sbaban 	/* Return on error */
22605043Sbaban 	if (rc != IDMAP_SUCCESS)
22615043Sbaban 		return (rc);
22625043Sbaban 
22635043Sbaban 	/*
22645043Sbaban 	 * The given PID may have been mapped to a locally
22655043Sbaban 	 * generated SID in which case there isn't any
22665043Sbaban 	 * Windows name
22675043Sbaban 	 */
22685043Sbaban 	if (winname == NULL || windomain == NULL) {
22695043Sbaban 		idmap_free(winname);
22705043Sbaban 		idmap_free(windomain);
22715043Sbaban 		return (IDMAP_ERR_NORESULT);
22725043Sbaban 	}
22735043Sbaban 
22745043Sbaban 	if (domain != NULL) {
22755043Sbaban 		*name = winname;
22765043Sbaban 		*domain = windomain;
22775043Sbaban 	} else {
22785043Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
22795043Sbaban 		if ((*name = malloc(len)) != NULL)
22805043Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
22815043Sbaban 			    windomain);
22825043Sbaban 		else
22835043Sbaban 			rc = IDMAP_ERR_MEMORY;
22845043Sbaban 		idmap_free(winname);
22855043Sbaban 		idmap_free(windomain);
22865043Sbaban 	}
22875043Sbaban 	return (rc);
22885043Sbaban }
22895043Sbaban 
22905043Sbaban 
22915043Sbaban /*
22925043Sbaban  * Get winname given uid
22935043Sbaban  */
22945043Sbaban idmap_stat
22955696Snw141292 idmap_getwinnamebyuid(uid_t uid, char **name, char **domain)
22965696Snw141292 {
22975043Sbaban 	return (idmap_getwinnamebypid(uid, 1, name, domain));
22985043Sbaban }
22995043Sbaban 
23005043Sbaban 
23015043Sbaban /*
23025043Sbaban  * Get winname given gid
23035043Sbaban  */
23045043Sbaban idmap_stat
23055696Snw141292 idmap_getwinnamebygid(gid_t gid, char **name, char **domain)
23065696Snw141292 {
23075043Sbaban 	return (idmap_getwinnamebypid(gid, 0, name, domain));
23085043Sbaban }
2309