14520Snw141292 /*
24520Snw141292  * CDDL HEADER START
34520Snw141292  *
44520Snw141292  * The contents of this file are subject to the terms of the
54520Snw141292  * Common Development and Distribution License (the "License").
64520Snw141292  * You may not use this file except in compliance with the License.
74520Snw141292  *
84520Snw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94520Snw141292  * or http://www.opensolaris.org/os/licensing.
104520Snw141292  * See the License for the specific language governing permissions
114520Snw141292  * and limitations under the License.
124520Snw141292  *
134520Snw141292  * When distributing Covered Code, include this CDDL HEADER in each
144520Snw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154520Snw141292  * If applicable, add the following below this CDDL HEADER, with the
164520Snw141292  * fields enclosed by brackets "[]" replaced with your own identifying
174520Snw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
184520Snw141292  *
194520Snw141292  * CDDL HEADER END
204520Snw141292  */
214520Snw141292 /*
224520Snw141292  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
234520Snw141292  * Use is subject to license terms.
244520Snw141292  */
254520Snw141292 
264520Snw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
274520Snw141292 
284520Snw141292 /*
294520Snw141292  * libidmap API
304520Snw141292  */
314520Snw141292 
324520Snw141292 #include <stdlib.h>
334520Snw141292 #include <inttypes.h>
344520Snw141292 #include <errno.h>
354520Snw141292 #include <strings.h>
364520Snw141292 #include <ctype.h>
374520Snw141292 #include <sys/param.h>
384520Snw141292 #include <sys/types.h>
394520Snw141292 #include <sys/stat.h>
404520Snw141292 #include <dlfcn.h>
414520Snw141292 #include <libintl.h>
424520Snw141292 #include "idmap_impl.h"
434520Snw141292 
444520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
454520Snw141292 
464520Snw141292 static int idmap_stat2errno(idmap_stat);
474520Snw141292 
484520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
494520Snw141292 	if (handl == NULL) {\
504520Snw141292 		errno = EINVAL;\
514520Snw141292 		return (IDMAP_ERR_ARG);\
524520Snw141292 	}\
534520Snw141292 	itera = calloc(1, sizeof (*itera));\
544520Snw141292 	if (itera == NULL) {\
554520Snw141292 		errno = ENOMEM;\
564520Snw141292 		return (IDMAP_ERR_MEMORY);\
574520Snw141292 	}\
584520Snw141292 	argu = calloc(1, sizeof (*argu));\
594520Snw141292 	if (argu == NULL) {\
604520Snw141292 		free(itera);\
614520Snw141292 		errno = ENOMEM;\
624520Snw141292 		return (IDMAP_ERR_MEMORY);\
634520Snw141292 	}\
644520Snw141292 	itera->ih = handl;\
654520Snw141292 	itera->type = ityp;\
664520Snw141292 	itera->retcode = IDMAP_NEXT;\
674520Snw141292 	itera->limit = 1024;\
684520Snw141292 	itera->arg = argu;
694520Snw141292 
704520Snw141292 
714520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
724520Snw141292 	if (argu) {\
734520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
744520Snw141292 		free(argu);\
754520Snw141292 	}\
764520Snw141292 	if (itera)\
774520Snw141292 		free(itera);\
784520Snw141292 	return (iretcod);
794520Snw141292 
804520Snw141292 
814520Snw141292 #define	__ITER_CHECK(itera, ityp)\
824520Snw141292 	if (itera == NULL) {\
834520Snw141292 		errno = EINVAL;\
844520Snw141292 		return (IDMAP_ERR_ARG);\
854520Snw141292 	}\
864520Snw141292 	if (itera->type != ityp) {\
874520Snw141292 		errno = EINVAL;\
884520Snw141292 		return (IDMAP_ERR_ARG);\
894520Snw141292 	}
904520Snw141292 
914520Snw141292 
924520Snw141292 /*
934520Snw141292  * Free memory allocated by libidmap API
944520Snw141292  *
954520Snw141292  * Input:
964520Snw141292  * ptr - memory to be freed
974520Snw141292  */
984520Snw141292 void
994520Snw141292 idmap_free(void *ptr) {
1004520Snw141292 	free(ptr);
1014520Snw141292 }
1024520Snw141292 
1034520Snw141292 
1044520Snw141292 /*
1054520Snw141292  * Create and Initialize idmap client handle for rpc/doors
1064520Snw141292  *
1074520Snw141292  * Output:
1084520Snw141292  * handle - idmap handle
1094520Snw141292  */
1104520Snw141292 idmap_stat
1114520Snw141292 idmap_init(idmap_handle_t **handle) {
1124520Snw141292 	CLIENT			*clnt = NULL;
1134520Snw141292 	struct idmap_handle	*hptr;
1144520Snw141292 
1154520Snw141292 	*handle = NULL;
1164520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
1174520Snw141292 	if (hptr == NULL)
1184520Snw141292 		return (IDMAP_ERR_MEMORY);
1194520Snw141292 
1204520Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, 0);
1214520Snw141292 	if (clnt == NULL) {
1224520Snw141292 		free(hptr);
1234520Snw141292 		return (IDMAP_ERR_RPC);
1244520Snw141292 	}
1254520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
1264520Snw141292 	hptr->privhandle = clnt;
1274520Snw141292 	*handle = hptr;
1284520Snw141292 	return (IDMAP_SUCCESS);
1294520Snw141292 }
1304520Snw141292 
1314520Snw141292 
1324520Snw141292 /*
1334520Snw141292  * Finalize idmap handle
1344520Snw141292  *
1354520Snw141292  * Input:
1364520Snw141292  * handle - idmap handle
1374520Snw141292  */
1384520Snw141292 idmap_stat
1394520Snw141292 idmap_fini(idmap_handle_t *handle) {
1404520Snw141292 	CLIENT			*clnt;
1414520Snw141292 	struct idmap_handle	*hptr;
1424520Snw141292 
1434520Snw141292 	if (handle == NULL)
1444520Snw141292 		return (IDMAP_SUCCESS);
1454520Snw141292 
1464520Snw141292 	hptr = (struct idmap_handle *)handle;
1474520Snw141292 
1484520Snw141292 	switch (hptr->type) {
1494520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
1504520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
1514520Snw141292 		if (clnt) {
1524520Snw141292 			if (clnt->cl_auth)
1534520Snw141292 				auth_destroy(clnt->cl_auth);
1544520Snw141292 			clnt_destroy(clnt);
1554520Snw141292 		}
1564520Snw141292 		break;
1574520Snw141292 	default:
1584520Snw141292 		break;
1594520Snw141292 	}
1604520Snw141292 	free(hptr);
1614520Snw141292 	return (IDMAP_SUCCESS);
1624520Snw141292 }
1634520Snw141292 
1644520Snw141292 
1654520Snw141292 
1664520Snw141292 /*
1674520Snw141292  * Create/Initialize handle for updates
1684520Snw141292  *
1694520Snw141292  * Output:
1704520Snw141292  * udthandle - update handle
1714520Snw141292  */
1724520Snw141292 idmap_stat
1734520Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) {
1744520Snw141292 	idmap_udt_handle_t	*tmp;
1754520Snw141292 
1764520Snw141292 	if (handle == NULL || udthandle == NULL) {
1774520Snw141292 		errno = EINVAL;
1784520Snw141292 		return (IDMAP_ERR_ARG);
1794520Snw141292 	}
1804520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
1814520Snw141292 		errno = ENOMEM;
1824520Snw141292 		return (IDMAP_ERR_MEMORY);
1834520Snw141292 	}
1844520Snw141292 
1854520Snw141292 	tmp->ih = handle;
1864520Snw141292 	*udthandle = tmp;
1874520Snw141292 	return (IDMAP_SUCCESS);
1884520Snw141292 }
1894520Snw141292 
1904520Snw141292 
1914520Snw141292 /*
1924520Snw141292  * All the updates specified by the update handle are committed
1934520Snw141292  * in a single transaction. i.e either all succeed or none.
1944520Snw141292  *
1954520Snw141292  * Input:
1964520Snw141292  * udthandle - update handle with the update requests
1974520Snw141292  *
1984520Snw141292  * Return value:
1994520Snw141292  * Status of the commit
2004520Snw141292  */
2014520Snw141292 idmap_stat
2024520Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle) {
2034520Snw141292 	CLIENT			*clnt;
2044520Snw141292 	enum clnt_stat		clntstat;
2054520Snw141292 	idmap_retcode		retcode;
2064520Snw141292 
2074520Snw141292 	if (udthandle == NULL) {
2084520Snw141292 		errno = EINVAL;
2094520Snw141292 		return (IDMAP_ERR_ARG);
2104520Snw141292 	}
2114520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
2124520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
2134520Snw141292 		(xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
2144520Snw141292 		(xdrproc_t)xdr_idmap_retcode, (caddr_t)&retcode,
2154520Snw141292 		TIMEOUT);
2164520Snw141292 	if (clntstat != RPC_SUCCESS) {
2174520Snw141292 		return (IDMAP_ERR_RPC);
2184520Snw141292 	}
2194520Snw141292 	if (retcode != IDMAP_SUCCESS)
2204520Snw141292 		errno = idmap_stat2errno(retcode);
2214520Snw141292 	return (retcode);
2224520Snw141292 }
2234520Snw141292 
2244520Snw141292 
2254520Snw141292 /*
2264520Snw141292  * Destroy the update handle
2274520Snw141292  */
2284520Snw141292 void
2294520Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle) {
2304520Snw141292 	if (udthandle == NULL)
2314520Snw141292 		return;
2324520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
2334520Snw141292 	free(udthandle);
2344520Snw141292 }
2354520Snw141292 
2364520Snw141292 
2374520Snw141292 idmap_stat
2384520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
2394520Snw141292 		boolean_t is_user, const char *winname, const char *unixname,
2404520Snw141292 		boolean_t is_nt4, int direction) {
2414520Snw141292 	idmap_retcode	retcode;
2424520Snw141292 	idmap_namerule	*rule;
2434520Snw141292 	idmap_utf8str	*str;
2444520Snw141292 
2454520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_ADD_NAMERULE);
2464520Snw141292 	if (retcode != IDMAP_SUCCESS)
2474520Snw141292 		goto errout;
2484520Snw141292 
2494520Snw141292 	rule = &udthandle->batch.
2504520Snw141292 		idmap_update_batch_val[udthandle->next].
2514520Snw141292 		idmap_update_op_u.rule;
2524520Snw141292 	rule->is_user = is_user;
2534520Snw141292 	rule->direction = direction;
2544520Snw141292 	rule->is_nt4 = is_nt4;
2554520Snw141292 	if (windomain) {
2564520Snw141292 		str = &rule->windomain;
2574520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
2584520Snw141292 		if (retcode != IDMAP_SUCCESS)
2594520Snw141292 			goto errout;
2604520Snw141292 	}
2614520Snw141292 	if (winname) {
2624520Snw141292 		str = &rule->winname;
2634520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
2644520Snw141292 		if (retcode != IDMAP_SUCCESS)
2654520Snw141292 			goto errout;
2664520Snw141292 	}
2674520Snw141292 	if (unixname) {
2684520Snw141292 		str = &rule->unixname;
2694520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
2704520Snw141292 		if (retcode != IDMAP_SUCCESS)
2714520Snw141292 			goto errout;
2724520Snw141292 	}
2734520Snw141292 	udthandle->next++;
2744520Snw141292 	return (IDMAP_SUCCESS);
2754520Snw141292 
2764520Snw141292 errout:
2774520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
2784520Snw141292 	errno = idmap_stat2errno(retcode);
2794520Snw141292 	return (retcode);
2804520Snw141292 }
2814520Snw141292 
2824520Snw141292 
2834520Snw141292 /* ARGSUSED */
2844520Snw141292 idmap_stat
2854520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
2864520Snw141292 		const char *windomain, const char *winname,
2874520Snw141292 		const char *unixname, int direction) {
2884520Snw141292 	idmap_retcode	retcode;
2894520Snw141292 	idmap_namerule	*rule;
2904520Snw141292 	idmap_utf8str	*str;
2914520Snw141292 
2924520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_RM_NAMERULE);
2934520Snw141292 	if (retcode != IDMAP_SUCCESS)
2944520Snw141292 		goto errout;
2954520Snw141292 
2964520Snw141292 	rule = &udthandle->batch.
2974520Snw141292 		idmap_update_batch_val[udthandle->next].
2984520Snw141292 		idmap_update_op_u.rule;
2994520Snw141292 	rule->is_user = is_user;
3004520Snw141292 	rule->direction = direction;
3014520Snw141292 	if (windomain) {
3024520Snw141292 		str = &rule->windomain;
3034520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
3044520Snw141292 		if (retcode != IDMAP_SUCCESS)
3054520Snw141292 			goto errout;
3064520Snw141292 	}
3074520Snw141292 	if (winname) {
3084520Snw141292 		str = &rule->winname;
3094520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
3104520Snw141292 		if (retcode != IDMAP_SUCCESS)
3114520Snw141292 			goto errout;
3124520Snw141292 	}
3134520Snw141292 	if (unixname) {
3144520Snw141292 		str = &rule->unixname;
3154520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
3164520Snw141292 		if (retcode != IDMAP_SUCCESS)
3174520Snw141292 			goto errout;
3184520Snw141292 	}
3194520Snw141292 	udthandle->next++;
3204520Snw141292 	return (IDMAP_SUCCESS);
3214520Snw141292 
3224520Snw141292 errout:
3234520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
3244520Snw141292 	errno = idmap_stat2errno(retcode);
3254520Snw141292 	return (retcode);
3264520Snw141292 }
3274520Snw141292 
3284520Snw141292 
3294520Snw141292 /* ARGSUSED */
3304520Snw141292 idmap_stat
3314520Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle, boolean_t is_user) {
3324520Snw141292 	idmap_retcode	retcode;
3334520Snw141292 
3344520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_FLUSH_NAMERULES);
3354520Snw141292 	if (retcode != IDMAP_SUCCESS)
3364520Snw141292 		goto errout;
3374520Snw141292 
3384520Snw141292 	udthandle->batch.idmap_update_batch_val[udthandle->next].
3394520Snw141292 		idmap_update_op_u.is_user = is_user;
3404520Snw141292 
3414520Snw141292 	udthandle->next++;
3424520Snw141292 	return (IDMAP_SUCCESS);
3434520Snw141292 
3444520Snw141292 errout:
3454520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
3464520Snw141292 	errno = idmap_stat2errno(retcode);
3474520Snw141292 	return (retcode);
3484520Snw141292 }
3494520Snw141292 
3504520Snw141292 
3514520Snw141292 /*
3524520Snw141292  * Set the number of entries requested per batch by the iterator
3534520Snw141292  *
3544520Snw141292  * Input:
3554520Snw141292  * iter  - iterator
3564520Snw141292  * limit - number of entries requested per batch
3574520Snw141292  */
3584520Snw141292 idmap_stat
3594520Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) {
3604520Snw141292 	if (iter == NULL) {
3614520Snw141292 		errno = EINVAL;
3624520Snw141292 		return (IDMAP_ERR_ARG);
3634520Snw141292 	}
3644520Snw141292 	iter->limit = limit;
3654520Snw141292 	return (IDMAP_SUCCESS);
3664520Snw141292 }
3674520Snw141292 
3684520Snw141292 
3694520Snw141292 /*
3704520Snw141292  * Create iterator to get name-based mapping rules
3714520Snw141292  *
3724520Snw141292  * Input:
3734520Snw141292  * windomain - Windows domain
3744520Snw141292  * is_user   - user or group rules
3754520Snw141292  * winname   - Windows user or group name
3764520Snw141292  * unixname  - Unix user or group name
3774520Snw141292  *
3784520Snw141292  * Output:
3794520Snw141292  * iter - iterator
3804520Snw141292  */
3814520Snw141292 idmap_stat
3824520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
3834520Snw141292 		boolean_t is_user, const char *winname,
3844520Snw141292 		const char *unixname, idmap_iter_t **iter) {
3854520Snw141292 
3864520Snw141292 	idmap_iter_t			*tmpiter;
3874520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
3884520Snw141292 	idmap_namerule			*rule;
3894520Snw141292 	idmap_utf8str			*str;
3904520Snw141292 	idmap_retcode			retcode;
3914520Snw141292 
3924520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
3934520Snw141292 
3944520Snw141292 	rule = &arg->rule;
3954520Snw141292 	rule->is_user = is_user;
3964520Snw141292 	rule->direction = -1;
3974520Snw141292 	if (windomain) {
3984520Snw141292 		str = &rule->windomain;
3994520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
4004520Snw141292 		if (retcode != IDMAP_SUCCESS) {
4014520Snw141292 			errno = ENOMEM;
4024520Snw141292 			goto errout;
4034520Snw141292 		}
4044520Snw141292 	}
4054520Snw141292 	if (winname) {
4064520Snw141292 		str = &rule->winname;
4074520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
4084520Snw141292 		if (retcode != IDMAP_SUCCESS) {
4094520Snw141292 			errno = ENOMEM;
4104520Snw141292 			goto errout;
4114520Snw141292 		}
4124520Snw141292 	}
4134520Snw141292 	if (unixname) {
4144520Snw141292 		str = &rule->unixname;
4154520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
4164520Snw141292 		if (retcode != IDMAP_SUCCESS) {
4174520Snw141292 			errno = ENOMEM;
4184520Snw141292 			goto errout;
4194520Snw141292 		}
4204520Snw141292 	}
4214520Snw141292 
4224520Snw141292 	*iter = tmpiter;
4234520Snw141292 	return (IDMAP_SUCCESS);
4244520Snw141292 
4254520Snw141292 errout:
4264520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
4274520Snw141292 		xdr_idmap_list_namerules_1_argument, retcode);
4284520Snw141292 }
4294520Snw141292 
4304520Snw141292 
4314520Snw141292 /*
4324520Snw141292  * Iterate through the name-based mapping rules
4334520Snw141292  *
4344520Snw141292  * Input:
4354520Snw141292  * iter - iterator
4364520Snw141292  *
4374520Snw141292  * Output:
4384520Snw141292  * windomain - Windows domain
4394520Snw141292  * winname   - Windows user or group name
4404520Snw141292  * unixname  - Unix user or group name
4414520Snw141292  * is_nt4    - NT4 or AD
4424520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
4434520Snw141292  *
4444520Snw141292  * Return value:
4454520Snw141292  * 0   - done
4464520Snw141292  * 1   - more results available
4474520Snw141292  * < 0 - error
4484520Snw141292  */
4494520Snw141292 idmap_stat
4504520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
4514520Snw141292 		char **winname, char **unixname, boolean_t *is_nt4,
4524520Snw141292 		int *direction) {
4534520Snw141292 	idmap_namerules_res		*namerules;
4544520Snw141292 	idmap_list_namerules_1_argument	*arg;
4554520Snw141292 	idmap_retcode			retcode;
4564520Snw141292 
4574520Snw141292 	if (windomain)
4584520Snw141292 		*windomain = NULL;
4594520Snw141292 	if (winname)
4604520Snw141292 		*winname = NULL;
4614520Snw141292 	if (unixname)
4624520Snw141292 		*unixname = NULL;
4634520Snw141292 	if (is_nt4)
4644520Snw141292 		*is_nt4 = 0;
4654520Snw141292 	if (direction)
4664520Snw141292 		*direction = -1;
4674520Snw141292 
4684520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
4694520Snw141292 
4704520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
4714520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
4724520Snw141292 			iter->next >= namerules->rules.rules_len)) {
4734520Snw141292 
4744520Snw141292 		if ((arg = iter->arg) == NULL) {
4754520Snw141292 			errno = EINVAL;
4764520Snw141292 			return (IDMAP_ERR_ARG);
4774520Snw141292 		}
4784520Snw141292 		arg->limit = iter->limit;
4794520Snw141292 
4804520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
4814520Snw141292 			iter, arg,
4824520Snw141292 			(uchar_t **)&namerules, sizeof (*namerules),
4834520Snw141292 			(xdrproc_t)xdr_idmap_list_namerules_1_argument,
4844520Snw141292 			(xdrproc_t)xdr_idmap_namerules_res);
4854520Snw141292 		if (retcode != IDMAP_SUCCESS)
4864520Snw141292 			return (retcode);
4874520Snw141292 
4884520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
4894520Snw141292 			retcode  = namerules->retcode;
4904520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
4914520Snw141292 			free(namerules);
4924520Snw141292 			iter->retlist = NULL;
4934520Snw141292 			return (retcode);
4944520Snw141292 		}
4954520Snw141292 		iter->retcode = namerules->retcode;
4964520Snw141292 		arg->lastrowid = namerules->lastrowid;
4974520Snw141292 	}
4984520Snw141292 
4994520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
5004520Snw141292 		return (IDMAP_SUCCESS);
5014520Snw141292 
5024520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
5034520Snw141292 		return (IDMAP_ERR_ARG);
5044520Snw141292 	}
5054520Snw141292 
5064520Snw141292 	if (windomain) {
5074520Snw141292 		retcode = idmap_utf82str(windomain, 0,
5084520Snw141292 			&namerules->rules.rules_val[iter->next].windomain);
5094520Snw141292 		if (retcode != IDMAP_SUCCESS)
5104520Snw141292 			goto errout;
5114520Snw141292 	}
5124520Snw141292 	if (winname) {
5134520Snw141292 		retcode = idmap_utf82str(winname, 0,
5144520Snw141292 			&namerules->rules.rules_val[iter->next].winname);
5154520Snw141292 		if (retcode != IDMAP_SUCCESS)
5164520Snw141292 			goto errout;
5174520Snw141292 	}
5184520Snw141292 	if (unixname) {
5194520Snw141292 		retcode = idmap_utf82str(unixname, 0,
5204520Snw141292 			&namerules->rules.rules_val[iter->next].unixname);
5214520Snw141292 		if (retcode != IDMAP_SUCCESS)
5224520Snw141292 			goto errout;
5234520Snw141292 	}
5244520Snw141292 	if (is_nt4)
5254520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
5264520Snw141292 	if (direction)
5274520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
5284520Snw141292 	iter->next++;
5294520Snw141292 
5304520Snw141292 	if (iter->next == namerules->rules.rules_len)
5314520Snw141292 		return (iter->retcode);
5324520Snw141292 	else
5334520Snw141292 		return (IDMAP_NEXT);
5344520Snw141292 
5354520Snw141292 errout:
5364520Snw141292 	if (windomain && *windomain)
5374520Snw141292 		free(*windomain);
5384520Snw141292 	if (winname && *winname)
5394520Snw141292 		free(*winname);
5404520Snw141292 	if (unixname && *unixname)
5414520Snw141292 		free(*unixname);
5424520Snw141292 	return (retcode);
5434520Snw141292 }
5444520Snw141292 
5454520Snw141292 
5464520Snw141292 /*
5474520Snw141292  * Create iterator to get SID to UID/GID mappings
5484520Snw141292  *
5494520Snw141292  * Input:
5504520Snw141292  * is_user - user or group
5514520Snw141292  *
5524520Snw141292  * Output:
5534520Snw141292  * iter - iterator
5544520Snw141292  */
5554520Snw141292 idmap_stat
5564520Snw141292 idmap_iter_mappings(idmap_handle_t *handle, boolean_t is_user,
5574520Snw141292 		idmap_iter_t **iter) {
5584520Snw141292 	idmap_iter_t			*tmpiter;
5594520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
5604520Snw141292 
5614520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
5624520Snw141292 
5634520Snw141292 	arg->is_user = is_user;
5644520Snw141292 	*iter = tmpiter;
5654520Snw141292 	return (IDMAP_SUCCESS);
5664520Snw141292 }
5674520Snw141292 
5684520Snw141292 
5694520Snw141292 /*
5704520Snw141292  * Iterate through the SID to UID/GID mappings
5714520Snw141292  *
5724520Snw141292  * Input:
5734520Snw141292  * iter - iterator
5744520Snw141292  *
5754520Snw141292  * Output:
5764520Snw141292  * sid - SID in canonical form
5774520Snw141292  * pid - UID or GID
5784520Snw141292  *
5794520Snw141292  * Return value:
5804520Snw141292  * 0   - done
5814520Snw141292  * 1   - more results available
5824520Snw141292  * < 0 - error
5834520Snw141292  */
5844520Snw141292 idmap_stat
5854520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
5864520Snw141292 		idmap_rid_t *rid, uid_t *pid, char **winname,
5874520Snw141292 		char **windomain, char **unixname, int *direction) {
5884520Snw141292 	idmap_mappings_res		*mappings;
5894520Snw141292 	idmap_list_mappings_1_argument	*arg;
5904520Snw141292 	idmap_retcode			retcode;
5914520Snw141292 	char				*str;
5924520Snw141292 
5934520Snw141292 	if (sidprefix)
5944520Snw141292 		*sidprefix = NULL;
5954520Snw141292 	if (rid)
5964520Snw141292 		*rid = UINT32_MAX;
5974520Snw141292 	if (winname)
5984520Snw141292 		*winname = NULL;
5994520Snw141292 	if (windomain)
6004520Snw141292 		*windomain = NULL;
6014520Snw141292 	if (unixname)
6024520Snw141292 		*unixname = NULL;
6034520Snw141292 	if (pid)
6044520Snw141292 		*pid = UINT32_MAX;
6054520Snw141292 	if (direction)
6064520Snw141292 		*direction = -1;
6074520Snw141292 
6084520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
6094520Snw141292 
6104520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
6114520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
6124520Snw141292 			iter->next >= mappings->mappings.mappings_len)) {
6134520Snw141292 
6144520Snw141292 		if ((arg = iter->arg) == NULL) {
6154520Snw141292 			errno = EINVAL;
6164520Snw141292 			return (IDMAP_ERR_ARG);
6174520Snw141292 		}
6184520Snw141292 		arg->limit = iter->limit;
6194520Snw141292 
6204520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
6214520Snw141292 			iter, arg,
6224520Snw141292 			(uchar_t **)&mappings, sizeof (*mappings),
6234520Snw141292 			(xdrproc_t)xdr_idmap_list_mappings_1_argument,
6244520Snw141292 			(xdrproc_t)xdr_idmap_mappings_res);
6254520Snw141292 		if (retcode != IDMAP_SUCCESS)
6264520Snw141292 			return (retcode);
6274520Snw141292 
6284520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
6294520Snw141292 			retcode  = mappings->retcode;
6304520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
6314520Snw141292 			free(mappings);
6324520Snw141292 			iter->retlist = NULL;
6334520Snw141292 			return (retcode);
6344520Snw141292 		}
6354520Snw141292 		iter->retcode = mappings->retcode;
6364520Snw141292 		arg->lastrowid = mappings->lastrowid;
6374520Snw141292 	}
6384520Snw141292 
6394520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
6404520Snw141292 		return (IDMAP_SUCCESS);
6414520Snw141292 
6424520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
6434520Snw141292 		return (IDMAP_ERR_ARG);
6444520Snw141292 	}
6454520Snw141292 
6464520Snw141292 	if (sidprefix) {
6474520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
6484520Snw141292 			idmap_id_u.sid.prefix;
649*4526Sbaban 		if (str) {
6504520Snw141292 			*sidprefix = strdup(str);
651*4526Sbaban 			if (*sidprefix == NULL) {
652*4526Sbaban 				retcode = IDMAP_ERR_MEMORY;
653*4526Sbaban 				goto errout;
654*4526Sbaban 			}
6554520Snw141292 		}
6564520Snw141292 	}
6574520Snw141292 	if (rid)
6584520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
6594520Snw141292 			idmap_id_u.sid.rid;
6604520Snw141292 	if (winname) {
6614520Snw141292 		retcode = idmap_utf82str(winname, 0,
6624520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id1name);
6634520Snw141292 		if (retcode != IDMAP_SUCCESS)
6644520Snw141292 			goto errout;
6654520Snw141292 	}
6664520Snw141292 	if (windomain) {
6674520Snw141292 		retcode = idmap_utf82str(windomain, 0,
6684520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id1domain);
6694520Snw141292 		if (retcode != IDMAP_SUCCESS)
6704520Snw141292 			goto errout;
6714520Snw141292 	}
6724520Snw141292 	if (unixname) {
6734520Snw141292 		retcode = idmap_utf82str(unixname, 0,
6744520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id2name);
6754520Snw141292 		if (retcode != IDMAP_SUCCESS)
6764520Snw141292 			goto errout;
6774520Snw141292 	}
6784520Snw141292 	if (pid)
6794520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
6804520Snw141292 			idmap_id_u.uid;
6814520Snw141292 	if (direction)
6824520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
6834520Snw141292 			direction;
6844520Snw141292 	iter->next++;
6854520Snw141292 
6864520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
6874520Snw141292 		return (iter->retcode);
6884520Snw141292 	else
6894520Snw141292 		return (IDMAP_NEXT);
6904520Snw141292 
6914520Snw141292 errout:
6924520Snw141292 	if (sidprefix && *sidprefix)
6934520Snw141292 		free(*sidprefix);
6944520Snw141292 	if (winname && *winname)
6954520Snw141292 		free(*winname);
6964520Snw141292 	if (windomain && *windomain)
6974520Snw141292 		free(*windomain);
6984520Snw141292 	if (unixname && *unixname)
6994520Snw141292 		free(*unixname);
7004520Snw141292 	return (retcode);
7014520Snw141292 }
7024520Snw141292 
7034520Snw141292 
7044520Snw141292 /*
7054520Snw141292  * Destroy the iterator
7064520Snw141292  */
7074520Snw141292 void
7084520Snw141292 idmap_iter_destroy(idmap_iter_t *iter) {
7094520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
7104520Snw141292 
7114520Snw141292 	if (iter == NULL)
7124520Snw141292 		return;
7134520Snw141292 
7144520Snw141292 	switch (iter->type) {
7154520Snw141292 	case IDMAP_LIST_NAMERULES:
7164520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
7174520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
7184520Snw141292 		break;
7194520Snw141292 	case IDMAP_LIST_MAPPINGS:
7204520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
7214520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
7224520Snw141292 		break;
7234520Snw141292 	default:
7244520Snw141292 		free(iter);
7254520Snw141292 		return;
7264520Snw141292 	};
7274520Snw141292 
7284520Snw141292 	if (iter->arg) {
7294520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
7304520Snw141292 		free(iter->arg);
7314520Snw141292 	}
7324520Snw141292 	if (iter->retlist) {
7334520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
7344520Snw141292 		free(iter->retlist);
7354520Snw141292 	}
7364520Snw141292 	free(iter);
7374520Snw141292 }
7384520Snw141292 
7394520Snw141292 
7404520Snw141292 /*
7414520Snw141292  * Create handle to get SID to UID/GID mapping entries
7424520Snw141292  *
7434520Snw141292  * Input:
7444520Snw141292  * gh - "get mapping" handle
7454520Snw141292  */
7464520Snw141292 idmap_stat
7474520Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) {
7484520Snw141292 	idmap_get_handle_t	*tmp;
7494520Snw141292 
7504520Snw141292 	/* sanity checks */
7514520Snw141292 	if (handle == NULL || gh == NULL) {
7524520Snw141292 		errno = EINVAL;
7534520Snw141292 		return (IDMAP_ERR_ARG);
7544520Snw141292 	}
7554520Snw141292 
7564520Snw141292 	/* allocate the handle */
7574520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
7584520Snw141292 		errno = ENOMEM;
7594520Snw141292 		return (IDMAP_ERR_MEMORY);
7604520Snw141292 	}
7614520Snw141292 
7624520Snw141292 	tmp->ih = handle;
7634520Snw141292 	*gh = tmp;
7644520Snw141292 	return (IDMAP_SUCCESS);
7654520Snw141292 }
7664520Snw141292 
7674520Snw141292 
7684520Snw141292 /*
7694520Snw141292  * Given SID, get UID
7704520Snw141292  *
7714520Snw141292  * Input:
7724520Snw141292  * sidprefix  - SID prefix
7734520Snw141292  * rid        - RID
7744520Snw141292  * flag       - flag
7754520Snw141292  *
7764520Snw141292  * Output:
7774520Snw141292  * stat - status of the get request
7784520Snw141292  * uid  - POSIX UID if stat = 0
7794520Snw141292  *
7804520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
7814520Snw141292  */
7824520Snw141292 idmap_stat
7834520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
7844520Snw141292 		int flag, uid_t *uid, idmap_stat *stat) {
7854520Snw141292 
7864520Snw141292 	idmap_retcode	retcode;
7874520Snw141292 	idmap_mapping	*mapping;
7884520Snw141292 
7894520Snw141292 	/* sanity checks */
7904520Snw141292 	if (gh == NULL)
7914520Snw141292 		return (IDMAP_ERR_ARG);
7924520Snw141292 	if (uid == NULL || sidprefix == NULL)
7934520Snw141292 		return (IDMAP_ERR_ARG);
7944520Snw141292 
7954520Snw141292 	/* Extend the request array and the return list */
7964520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
7974520Snw141292 		goto errout;
7984520Snw141292 
7994520Snw141292 	/* Setup the request */
8004520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
8014520Snw141292 	mapping->flag = flag;
8024520Snw141292 	mapping->id1.idtype = IDMAP_SID;
8034520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
8044520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
8054520Snw141292 		retcode = IDMAP_ERR_MEMORY;
8064520Snw141292 		goto errout;
8074520Snw141292 	}
8084520Snw141292 	mapping->id2.idtype = IDMAP_UID;
8094520Snw141292 
8104520Snw141292 	/* Setup pointers for the result */
8114520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
8124520Snw141292 	gh->retlist[gh->next].uid = uid;
8134520Snw141292 	gh->retlist[gh->next].stat = stat;
8144520Snw141292 
8154520Snw141292 	gh->next++;
8164520Snw141292 	return (IDMAP_SUCCESS);
8174520Snw141292 
8184520Snw141292 errout:
8194520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
8204520Snw141292 	free(gh->retlist);
8214520Snw141292 	gh->retlist = NULL;
8224520Snw141292 	gh->next = 0;
8234520Snw141292 	errno = idmap_stat2errno(retcode);
8244520Snw141292 	return (retcode);
8254520Snw141292 }
8264520Snw141292 
8274520Snw141292 
8284520Snw141292 /*
8294520Snw141292  * Given SID, get GID
8304520Snw141292  *
8314520Snw141292  * Input:
8324520Snw141292  * sidprefix  - SID prefix
8334520Snw141292  * rid        - rid
8344520Snw141292  * flag       - flag
8354520Snw141292  *
8364520Snw141292  * Output:
8374520Snw141292  * stat - status of the get request
8384520Snw141292  * gid  - POSIX GID if stat = 0
8394520Snw141292  *
8404520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
8414520Snw141292  */
8424520Snw141292 idmap_stat
8434520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
8444520Snw141292 		int flag, gid_t *gid, idmap_stat *stat) {
8454520Snw141292 
8464520Snw141292 	idmap_retcode	retcode;
8474520Snw141292 	idmap_mapping	*mapping;
8484520Snw141292 
8494520Snw141292 	/* sanity checks */
8504520Snw141292 	if (gh == NULL)
8514520Snw141292 		return (IDMAP_ERR_ARG);
8524520Snw141292 	if (gid == NULL || sidprefix == NULL)
8534520Snw141292 		return (IDMAP_ERR_ARG);
8544520Snw141292 
8554520Snw141292 	/* Extend the request array and the return list */
8564520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
8574520Snw141292 		goto errout;
8584520Snw141292 
8594520Snw141292 	/* Setup the request */
8604520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
8614520Snw141292 	mapping->flag = flag;
8624520Snw141292 	mapping->id1.idtype = IDMAP_SID;
8634520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
8644520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
8654520Snw141292 		retcode = IDMAP_ERR_MEMORY;
8664520Snw141292 		goto errout;
8674520Snw141292 	}
8684520Snw141292 	mapping->id2.idtype = IDMAP_GID;
8694520Snw141292 
8704520Snw141292 	/* Setup pointers for the result */
8714520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
8724520Snw141292 	gh->retlist[gh->next].gid = gid;
8734520Snw141292 	gh->retlist[gh->next].stat = stat;
8744520Snw141292 
8754520Snw141292 	gh->next++;
8764520Snw141292 	return (IDMAP_SUCCESS);
8774520Snw141292 
8784520Snw141292 errout:
8794520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
8804520Snw141292 	free(gh->retlist);
8814520Snw141292 	gh->retlist = NULL;
8824520Snw141292 	gh->next = 0;
8834520Snw141292 	errno = idmap_stat2errno(retcode);
8844520Snw141292 	return (retcode);
8854520Snw141292 }
8864520Snw141292 
8874520Snw141292 
8884520Snw141292 /*
8894520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
8904520Snw141292  *
8914520Snw141292  * Input:
8924520Snw141292  * sidprefix  - SID prefix
8934520Snw141292  * rid        - rid
8944520Snw141292  * flag       - flag
8954520Snw141292  *
8964520Snw141292  * Output:
8974520Snw141292  * stat    - status of the get request
8984520Snw141292  * is_user - user or group
8994520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
9004520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
9014520Snw141292  *
9024520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
9034520Snw141292  */
9044520Snw141292 idmap_stat
9054520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
9064520Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat) {
9074520Snw141292 	idmap_retcode	retcode;
9084520Snw141292 	idmap_mapping	*mapping;
9094520Snw141292 
9104520Snw141292 	/* sanity checks */
9114520Snw141292 	if (gh == NULL)
9124520Snw141292 		return (IDMAP_ERR_ARG);
9134520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
9144520Snw141292 		return (IDMAP_ERR_ARG);
9154520Snw141292 
9164520Snw141292 	/* Extend the request array and the return list */
9174520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
9184520Snw141292 		goto errout;
9194520Snw141292 
9204520Snw141292 	/* Setup the request */
9214520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
9224520Snw141292 	mapping->flag = flag;
9234520Snw141292 	mapping->id1.idtype = IDMAP_SID;
9244520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
9254520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
9264520Snw141292 		retcode = IDMAP_ERR_MEMORY;
9274520Snw141292 		goto errout;
9284520Snw141292 	}
9294520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
9304520Snw141292 
9314520Snw141292 	/* Setup pointers for the result */
9324520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
9334520Snw141292 	gh->retlist[gh->next].uid = pid;
9344520Snw141292 	gh->retlist[gh->next].gid = pid;
9354520Snw141292 	gh->retlist[gh->next].is_user = is_user;
9364520Snw141292 	gh->retlist[gh->next].stat = stat;
9374520Snw141292 
9384520Snw141292 	gh->next++;
9394520Snw141292 	return (IDMAP_SUCCESS);
9404520Snw141292 
9414520Snw141292 errout:
9424520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
9434520Snw141292 	free(gh->retlist);
9444520Snw141292 	gh->retlist = NULL;
9454520Snw141292 	gh->next = 0;
9464520Snw141292 	errno = idmap_stat2errno(retcode);
9474520Snw141292 	return (retcode);
9484520Snw141292 }
9494520Snw141292 
9504520Snw141292 
9514520Snw141292 /*
9524520Snw141292  * Given UID, get SID
9534520Snw141292  *
9544520Snw141292  * Input:
9554520Snw141292  * uid  - POSIX UID
9564520Snw141292  * flag - flag
9574520Snw141292  *
9584520Snw141292  * Output:
9594520Snw141292  * stat - status of the get request
9604520Snw141292  * sid  - SID prefix (if stat == 0)
9614520Snw141292  * rid  - rid
9624520Snw141292  *
9634520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
9644520Snw141292  */
9654520Snw141292 idmap_stat
9664520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
9674520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
9684520Snw141292 
9694520Snw141292 	idmap_retcode	retcode;
9704520Snw141292 	idmap_mapping	*mapping;
9714520Snw141292 
9724520Snw141292 	/* sanity checks */
9734520Snw141292 	if (gh == NULL)
9744520Snw141292 		return (IDMAP_ERR_ARG);
9754520Snw141292 	if (sidprefix == NULL)
9764520Snw141292 		return (IDMAP_ERR_ARG);
9774520Snw141292 
9784520Snw141292 	/* Extend the request array and the return list */
9794520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
9804520Snw141292 		goto errout;
9814520Snw141292 
9824520Snw141292 	/* Setup the request */
9834520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
9844520Snw141292 	mapping->flag = flag;
9854520Snw141292 	mapping->id1.idtype = IDMAP_UID;
9864520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
9874520Snw141292 	mapping->id2.idtype = IDMAP_SID;
9884520Snw141292 
9894520Snw141292 	/* Setup pointers for the result */
9904520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
9914520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
9924520Snw141292 	gh->retlist[gh->next].rid = rid;
9934520Snw141292 	gh->retlist[gh->next].stat = stat;
9944520Snw141292 
9954520Snw141292 	gh->next++;
9964520Snw141292 	return (IDMAP_SUCCESS);
9974520Snw141292 
9984520Snw141292 errout:
9994520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
10004520Snw141292 	free(gh->retlist);
10014520Snw141292 	gh->retlist = NULL;
10024520Snw141292 	gh->next = 0;
10034520Snw141292 	errno = idmap_stat2errno(retcode);
10044520Snw141292 	return (retcode);
10054520Snw141292 }
10064520Snw141292 
10074520Snw141292 
10084520Snw141292 /*
10094520Snw141292  * Given GID, get SID
10104520Snw141292  *
10114520Snw141292  * Input:
10124520Snw141292  * gid  - POSIX GID
10134520Snw141292  * flag - flag
10144520Snw141292  *
10154520Snw141292  * Output:
10164520Snw141292  * stat       - status of the get request
10174520Snw141292  * sidprefix  - SID prefix (if stat == 0)
10184520Snw141292  * rid        - rid
10194520Snw141292  *
10204520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
10214520Snw141292  */
10224520Snw141292 idmap_stat
10234520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
10244520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
10254520Snw141292 
10264520Snw141292 	idmap_retcode	retcode;
10274520Snw141292 	idmap_mapping	*mapping;
10284520Snw141292 
10294520Snw141292 	/* sanity checks */
10304520Snw141292 	if (gh == NULL)
10314520Snw141292 		return (IDMAP_ERR_ARG);
10324520Snw141292 	if (sidprefix == NULL)
10334520Snw141292 		return (IDMAP_ERR_ARG);
10344520Snw141292 
10354520Snw141292 	/* Extend the request array and the return list */
10364520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
10374520Snw141292 		goto errout;
10384520Snw141292 
10394520Snw141292 	/* Setup the request */
10404520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
10414520Snw141292 	mapping->flag = flag;
10424520Snw141292 	mapping->id1.idtype = IDMAP_GID;
10434520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
10444520Snw141292 	mapping->id2.idtype = IDMAP_SID;
10454520Snw141292 
10464520Snw141292 	/* Setup pointers for the result */
10474520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
10484520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
10494520Snw141292 	gh->retlist[gh->next].rid = rid;
10504520Snw141292 	gh->retlist[gh->next].stat = stat;
10514520Snw141292 
10524520Snw141292 	gh->next++;
10534520Snw141292 	return (IDMAP_SUCCESS);
10544520Snw141292 
10554520Snw141292 errout:
10564520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
10574520Snw141292 	free(gh->retlist);
10584520Snw141292 	gh->retlist = NULL;
10594520Snw141292 	gh->next = 0;
10604520Snw141292 	errno = idmap_stat2errno(retcode);
10614520Snw141292 	return (retcode);
10624520Snw141292 }
10634520Snw141292 
10644520Snw141292 
10654520Snw141292 /*
10664520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
10674520Snw141292  * status and identity) will be available in the data areas
10684520Snw141292  * provided by individual requests.
10694520Snw141292  */
10704520Snw141292 idmap_stat
10714520Snw141292 idmap_get_mappings(idmap_get_handle_t *gh) {
10724520Snw141292 	CLIENT		*clnt;
10734520Snw141292 	enum clnt_stat	clntstat;
10744520Snw141292 	idmap_retcode	retcode;
10754520Snw141292 	idmap_ids_res	res;
10764520Snw141292 	idmap_id	*id;
10774520Snw141292 	int		i;
10784520Snw141292 
10794520Snw141292 	if (gh == NULL) {
10804520Snw141292 		errno = EINVAL;
10814520Snw141292 		return (IDMAP_ERR_ARG);
10824520Snw141292 	}
10834520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
10844520Snw141292 
10854520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
10864520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
10874520Snw141292 		(xdrproc_t)xdr_idmap_mapping_batch,
10884520Snw141292 		(caddr_t)&gh->batch,
10894520Snw141292 		(xdrproc_t)xdr_idmap_ids_res,
10904520Snw141292 		(caddr_t)&res,
10914520Snw141292 		TIMEOUT);
10924520Snw141292 	if (clntstat != RPC_SUCCESS) {
10934520Snw141292 		retcode = IDMAP_ERR_RPC;
10944520Snw141292 		goto out;
10954520Snw141292 	}
10964520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
10974520Snw141292 		retcode = res.retcode;
10984520Snw141292 		goto out;
10994520Snw141292 	}
11004520Snw141292 	for (i = 0; i < gh->next; i++) {
11014520Snw141292 		if (i >= res.ids.ids_len) {
11024520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
11034520Snw141292 			continue;
11044520Snw141292 		}
11054520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
11064520Snw141292 		id = &res.ids.ids_val[i].id;
11074520Snw141292 		switch (id->idtype) {
11084520Snw141292 		case IDMAP_UID:
11094520Snw141292 			if (gh->retlist[i].uid)
11104520Snw141292 				*gh->retlist[i].uid = id->idmap_id_u.uid;
11114520Snw141292 			if (gh->retlist[i].is_user)
11124520Snw141292 				*gh->retlist[i].is_user = 1;
11134520Snw141292 			break;
11144520Snw141292 		case IDMAP_GID:
11154520Snw141292 			if (gh->retlist[i].gid)
11164520Snw141292 				*gh->retlist[i].gid = id->idmap_id_u.gid;
11174520Snw141292 			if (gh->retlist[i].is_user)
11184520Snw141292 				*gh->retlist[i].is_user = 0;
11194520Snw141292 			break;
11204520Snw141292 		case IDMAP_SID:
11214520Snw141292 			if (gh->retlist[i].rid)
11224520Snw141292 				*gh->retlist[i].rid = id->idmap_id_u.sid.rid;
11234520Snw141292 			if (gh->retlist[i].sidprefix) {
11244520Snw141292 				if (id->idmap_id_u.sid.prefix == NULL) {
11254520Snw141292 					*gh->retlist[i].sidprefix = NULL;
11264520Snw141292 					break;
11274520Snw141292 				}
11284520Snw141292 				*gh->retlist[i].sidprefix =
11294520Snw141292 					strdup(id->idmap_id_u.sid.prefix);
11304520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
11314520Snw141292 					*gh->retlist[i].stat =
11324520Snw141292 						IDMAP_ERR_MEMORY;
11334520Snw141292 			}
11344520Snw141292 			break;
11354520Snw141292 		case IDMAP_NONE:
11364520Snw141292 			break;
11374520Snw141292 		default:
11384520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
11394520Snw141292 			break;
11404520Snw141292 		}
11414520Snw141292 	}
11424520Snw141292 	retcode = IDMAP_SUCCESS;
11434520Snw141292 
11444520Snw141292 out:
11454520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
11464520Snw141292 	free(gh->retlist);
11474520Snw141292 	gh->retlist = NULL;
11484520Snw141292 	gh->next = 0;
11494520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
11504520Snw141292 	errno = idmap_stat2errno(retcode);
11514520Snw141292 	return (retcode);
11524520Snw141292 }
11534520Snw141292 
11544520Snw141292 
11554520Snw141292 /*
11564520Snw141292  * Destroy the "get mapping" handle
11574520Snw141292  */
11584520Snw141292 void
11594520Snw141292 idmap_get_destroy(idmap_get_handle_t *gh) {
11604520Snw141292 	if (gh == NULL)
11614520Snw141292 		return;
11624520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
11634520Snw141292 	if (gh->retlist)
11644520Snw141292 		free(gh->retlist);
11654520Snw141292 	free(gh);
11664520Snw141292 }
11674520Snw141292 
11684520Snw141292 
11694520Snw141292 /*
11704520Snw141292  * Get windows to unix mapping
11714520Snw141292  */
11724520Snw141292 idmap_stat
11734520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
11744520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
11754520Snw141292 		const char *winname, const char *windomain,
11764520Snw141292 		int flag, int *is_user,
11774520Snw141292 		uid_t *pid, char **unixname, int *direction) {
11784520Snw141292 	CLIENT			*clnt;
11794520Snw141292 	enum clnt_stat		clntstat;
11804520Snw141292 	idmap_mapping		request, *mapping;
11814520Snw141292 	idmap_mappings_res	result;
11824520Snw141292 	idmap_retcode		retcode, rc;
11834520Snw141292 	idmap_utf8str		*str;
11844520Snw141292 
11854520Snw141292 	if (handle == NULL) {
11864520Snw141292 		errno = EINVAL;
11874520Snw141292 		return (IDMAP_ERR_ARG);
11884520Snw141292 	}
11894520Snw141292 
11904520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
11914520Snw141292 
11924520Snw141292 	(void) memset(&request, 0, sizeof (request));
11934520Snw141292 	(void) memset(&result, 0, sizeof (result));
11944520Snw141292 
11954520Snw141292 	if (pid)
11964520Snw141292 		*pid = UINT32_MAX;
11974520Snw141292 	if (unixname)
11984520Snw141292 		*unixname = NULL;
11994520Snw141292 	if (direction)
12004520Snw141292 		*direction = -1;
12014520Snw141292 
12024520Snw141292 	request.flag = flag;
12034520Snw141292 	request.id1.idtype = IDMAP_SID;
12044520Snw141292 	if (sidprefix && rid) {
12054520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
12064520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
12074520Snw141292 	} else if (winname) {
12084520Snw141292 		str = &request.id1name;
12094520Snw141292 		retcode = idmap_str2utf8(&str, winname, 1);
12104520Snw141292 		if (retcode != IDMAP_SUCCESS)
12114520Snw141292 			goto out;
12124520Snw141292 		if (windomain) {
12134520Snw141292 			str = &request.id1domain;
12144520Snw141292 			retcode = idmap_str2utf8(&str, windomain, 1);
12154520Snw141292 			if (retcode != IDMAP_SUCCESS)
12164520Snw141292 				return (retcode);
12174520Snw141292 		}
12184520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
12194520Snw141292 	} else {
12204520Snw141292 		errno = EINVAL;
12214520Snw141292 		return (IDMAP_ERR_ARG);
12224520Snw141292 	}
12234520Snw141292 
12244520Snw141292 	if (is_user == NULL)
12254520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
12264520Snw141292 	else if (*is_user == 1)
12274520Snw141292 		request.id2.idtype = IDMAP_UID;
12284520Snw141292 	else if (*is_user == 0)
12294520Snw141292 		request.id2.idtype = IDMAP_GID;
12304520Snw141292 	else
12314520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
12324520Snw141292 
12334520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
12344520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
12354520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
12364520Snw141292 		TIMEOUT);
12374520Snw141292 
12384520Snw141292 	if (clntstat != RPC_SUCCESS) {
12394520Snw141292 		return (IDMAP_ERR_RPC);
12404520Snw141292 	}
12414520Snw141292 
12424520Snw141292 	retcode = result.retcode;
12434520Snw141292 
12444520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
12454520Snw141292 		if (retcode == IDMAP_SUCCESS)
12464520Snw141292 			retcode = IDMAP_ERR_NORESULT;
12474520Snw141292 		goto out;
12484520Snw141292 	}
12494520Snw141292 
12504520Snw141292 	if (is_user)
12514520Snw141292 		*is_user = (mapping->id2.idtype == IDMAP_UID)?1:0;
12524520Snw141292 	if (direction)
12534520Snw141292 		*direction = mapping->direction;
12544520Snw141292 	if (pid)
12554520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
12564520Snw141292 	if (unixname) {
12574520Snw141292 		rc = idmap_utf82str(unixname, 0, &mapping->id2name);
12584520Snw141292 		if (rc != IDMAP_SUCCESS)
12594520Snw141292 			retcode = rc;
12604520Snw141292 	}
12614520Snw141292 
12624520Snw141292 out:
12634520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
12644520Snw141292 	if (retcode != IDMAP_SUCCESS)
12654520Snw141292 		errno = idmap_stat2errno(retcode);
12664520Snw141292 	return (retcode);
12674520Snw141292 }
12684520Snw141292 
12694520Snw141292 
12704520Snw141292 /*
12714520Snw141292  * Get unix to windows mapping
12724520Snw141292  */
12734520Snw141292 idmap_stat
12744520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
12754520Snw141292 		uid_t *pid, const char *unixname,
12764520Snw141292 		int flag, int is_user,
12774520Snw141292 		char **sidprefix, idmap_rid_t *rid,
12784520Snw141292 		char **winname, char **windomain,
12794520Snw141292 		int *direction) {
12804520Snw141292 	CLIENT			*clnt;
12814520Snw141292 	enum clnt_stat		clntstat;
12824520Snw141292 	idmap_mapping		request, *mapping;
12834520Snw141292 	idmap_mappings_res	result;
12844520Snw141292 	idmap_retcode		retcode, rc;
12854520Snw141292 	idmap_utf8str		*str;
12864520Snw141292 
12874520Snw141292 	if (handle == NULL) {
12884520Snw141292 		errno = EINVAL;
12894520Snw141292 		return (IDMAP_ERR_ARG);
12904520Snw141292 	}
12914520Snw141292 
12924520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
12934520Snw141292 
12944520Snw141292 	if (sidprefix)
12954520Snw141292 		*sidprefix = NULL;
12964520Snw141292 	if (winname)
12974520Snw141292 		*winname = NULL;
12984520Snw141292 	if (windomain)
12994520Snw141292 		*windomain = NULL;
13004520Snw141292 	if (rid)
13014520Snw141292 		*rid = UINT32_MAX;
13024520Snw141292 	if (direction)
13034520Snw141292 		*direction = -1;
13044520Snw141292 
13054520Snw141292 	(void) memset(&request, 0, sizeof (request));
13064520Snw141292 	(void) memset(&result, 0, sizeof (result));
13074520Snw141292 
13084520Snw141292 	request.flag = flag;
13094520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
13104520Snw141292 
13114520Snw141292 	if (pid && *pid != UINT32_MAX) {
13124520Snw141292 		request.id1.idmap_id_u.uid = *pid;
13134520Snw141292 	} else if (unixname) {
13144520Snw141292 		str = &request.id1name;
13154520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 1);
13164520Snw141292 		if (retcode != IDMAP_SUCCESS)
13174520Snw141292 			goto out;
13184520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
13194520Snw141292 	} else {
13204520Snw141292 		errno = EINVAL;
13214520Snw141292 		return (IDMAP_ERR_ARG);
13224520Snw141292 	}
13234520Snw141292 
13244520Snw141292 	request.id2.idtype = IDMAP_SID;
13254520Snw141292 
13264520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
13274520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
13284520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
13294520Snw141292 		TIMEOUT);
13304520Snw141292 
13314520Snw141292 	if (clntstat != RPC_SUCCESS) {
13324520Snw141292 		return (IDMAP_ERR_RPC);
13334520Snw141292 	}
13344520Snw141292 
13354520Snw141292 	retcode = result.retcode;
13364520Snw141292 
13374520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
13384520Snw141292 		if (retcode == IDMAP_SUCCESS)
13394520Snw141292 			retcode = IDMAP_ERR_NORESULT;
13404520Snw141292 		goto out;
13414520Snw141292 	}
13424520Snw141292 
13434520Snw141292 	if (direction)
13444520Snw141292 		*direction = mapping->direction;
13454520Snw141292 	if (sidprefix) {
13464520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
13474520Snw141292 		if (*sidprefix == NULL) {
13484520Snw141292 			retcode = IDMAP_ERR_MEMORY;
13494520Snw141292 			goto errout;
13504520Snw141292 		}
13514520Snw141292 	}
13524520Snw141292 	if (rid)
13534520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
13544520Snw141292 	if (winname) {
13554520Snw141292 		rc = idmap_utf82str(winname, 0, &mapping->id2name);
13564520Snw141292 		if (rc != IDMAP_SUCCESS) {
13574520Snw141292 			retcode = rc;
13584520Snw141292 			goto errout;
13594520Snw141292 		}
13604520Snw141292 	}
13614520Snw141292 	if (windomain) {
13624520Snw141292 		rc = idmap_utf82str(windomain, 0, &mapping->id2domain);
13634520Snw141292 		if (rc != IDMAP_SUCCESS) {
13644520Snw141292 			retcode = rc;
13654520Snw141292 			goto errout;
13664520Snw141292 		}
13674520Snw141292 	}
13684520Snw141292 
13694520Snw141292 	goto out;
13704520Snw141292 
13714520Snw141292 errout:
13724520Snw141292 	if (sidprefix && *sidprefix) {
13734520Snw141292 		free(*sidprefix);
13744520Snw141292 		*sidprefix = NULL;
13754520Snw141292 	}
13764520Snw141292 	if (winname && *winname) {
13774520Snw141292 		free(*winname);
13784520Snw141292 		*winname = NULL;
13794520Snw141292 	}
13804520Snw141292 	if (windomain && *windomain) {
13814520Snw141292 		free(*windomain);
13824520Snw141292 		*windomain = NULL;
13834520Snw141292 	}
13844520Snw141292 
13854520Snw141292 out:
13864520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
13874520Snw141292 	if (retcode != IDMAP_SUCCESS)
13884520Snw141292 		errno = idmap_stat2errno(retcode);
13894520Snw141292 	return (retcode);
13904520Snw141292 }
13914520Snw141292 
13924520Snw141292 
13934520Snw141292 /*
13944520Snw141292  * utf8str to string
13954520Snw141292  */
13964520Snw141292 idmap_stat
13974520Snw141292 idmap_utf82str(char **out, size_t outsize, idmap_utf8str *in) {
13984520Snw141292 	int len;
13994520Snw141292 
14004520Snw141292 	if (in == NULL || out == NULL)
14014520Snw141292 		return (IDMAP_ERR_ARG);
14024520Snw141292 
14034520Snw141292 	if (outsize == 0) {
14044520Snw141292 		*out = NULL;
14054520Snw141292 		if ((len = in->idmap_utf8str_len) == 0)
14064520Snw141292 			return (IDMAP_SUCCESS);
14074520Snw141292 		if (in->idmap_utf8str_val == NULL)
14084520Snw141292 			return (IDMAP_ERR_ARG);
14094520Snw141292 		if (in->idmap_utf8str_val[len - 1] != 0)
14104520Snw141292 			len++;
14114520Snw141292 		*out = calloc(1, len);
14124520Snw141292 		if (*out == NULL)
14134520Snw141292 			return (IDMAP_ERR_MEMORY);
14144520Snw141292 	} else {
14154520Snw141292 		if (*out == NULL)
14164520Snw141292 			return (IDMAP_ERR_ARG);
14174520Snw141292 		(void) memset(*out, 0, outsize);
14184520Snw141292 		if ((len = in->idmap_utf8str_len) == 0)
14194520Snw141292 			return (IDMAP_SUCCESS);
14204520Snw141292 		if (in->idmap_utf8str_val == NULL)
14214520Snw141292 			return (IDMAP_ERR_ARG);
14224520Snw141292 		if (in->idmap_utf8str_val[len - 1] != 0)
14234520Snw141292 			len++;
14244520Snw141292 		if (outsize < len)
14254520Snw141292 			return (IDMAP_ERR_ARG);
14264520Snw141292 	}
14274520Snw141292 	(void) memcpy(*out, in->idmap_utf8str_val, in->idmap_utf8str_len);
14284520Snw141292 	return (IDMAP_SUCCESS);
14294520Snw141292 }
14304520Snw141292 
14314520Snw141292 
14324520Snw141292 /*
14334520Snw141292  * string to utf8str
14344520Snw141292  */
14354520Snw141292 idmap_stat
14364520Snw141292 idmap_str2utf8(idmap_utf8str **out, const char *in, int flag) {
14374520Snw141292 	idmap_utf8str	*tmp;
14384520Snw141292 
14394520Snw141292 	if (out == NULL)
14404520Snw141292 		return (IDMAP_ERR_ARG);
14414520Snw141292 	else if (*out == NULL) {
14424520Snw141292 		tmp = malloc(sizeof (idmap_utf8str));
14434520Snw141292 		if (tmp == NULL)
14444520Snw141292 			return (IDMAP_ERR_MEMORY);
14454520Snw141292 	} else {
14464520Snw141292 		tmp = *out;
14474520Snw141292 	}
14484520Snw141292 
14494520Snw141292 	if (in == NULL) {
14504520Snw141292 		tmp->idmap_utf8str_len = 0;
14514520Snw141292 		tmp->idmap_utf8str_val = NULL;
14524520Snw141292 		if (*out == NULL)
14534520Snw141292 			*out = tmp;
14544520Snw141292 		return (IDMAP_SUCCESS);
14554520Snw141292 	}
14564520Snw141292 
14574520Snw141292 	/* include the null terminator */
14584520Snw141292 	tmp->idmap_utf8str_len = strlen(in) + 1;
14594520Snw141292 
14604520Snw141292 	if (flag == 1) {
14614520Snw141292 		/* Don't malloc, simply assign */
14624520Snw141292 		tmp->idmap_utf8str_val = (char *)in;
14634520Snw141292 		if (*out == NULL)
14644520Snw141292 			*out = tmp;
14654520Snw141292 		return (IDMAP_SUCCESS);
14664520Snw141292 	}
14674520Snw141292 
14684520Snw141292 	tmp->idmap_utf8str_val = malloc(tmp->idmap_utf8str_len);
14694520Snw141292 	if (tmp->idmap_utf8str_val == NULL) {
14704520Snw141292 		tmp->idmap_utf8str_len = 0;
14714520Snw141292 		if (*out == NULL)
14724520Snw141292 			free(tmp);
14734520Snw141292 		return (IDMAP_ERR_MEMORY);
14744520Snw141292 	}
14754520Snw141292 	(void) memcpy(tmp->idmap_utf8str_val, in, tmp->idmap_utf8str_len);
14764520Snw141292 	if (*out == NULL)
14774520Snw141292 		*out = tmp;
14784520Snw141292 	return (IDMAP_SUCCESS);
14794520Snw141292 }
14804520Snw141292 
14814520Snw141292 
14824520Snw141292 #define	gettext(s)	s
14834520Snw141292 static stat_table_t stattable[] = {
14844520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
14854520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
14864520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
14874520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
14884520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
14894520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
14904520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
14914520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
14924520Snw141292 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), EINVAL},
14934520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
14944520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
14954520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
14964520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
14974520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
14984520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
14994520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
15004520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
15014520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
15024520Snw141292 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EINVAL},
15034520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
15044520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
15054520Snw141292 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EINVAL},
15064520Snw141292 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permisssion denied"), EINVAL},
15074520Snw141292 	{IDMAP_ERR_NOMAPPING,
15084520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
15094520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
15104520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
15114520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
15124520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
15134520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
15144520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
15154520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
15164520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
15174520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
15184520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
15194520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
15204520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
15214520Snw141292 		gettext("Network error"), EINVAL},
15224520Snw141292 	{-1, NULL, 0}
15234520Snw141292 };
15244520Snw141292 #undef	gettext
15254520Snw141292 
15264520Snw141292 
15274520Snw141292 /*
15284520Snw141292  * Get description of status code
15294520Snw141292  *
15304520Snw141292  * Input:
15314520Snw141292  * status - Status code returned by libidmap API call
15324520Snw141292  *
15334520Snw141292  * Return Value:
15344520Snw141292  * human-readable localized description of idmap_stat
15354520Snw141292  */
15364520Snw141292 /* ARGSUSED */
15374520Snw141292 const char *
15384520Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) {
15394520Snw141292 	int i;
15404520Snw141292 
15414520Snw141292 	for (i = 0; stattable[i].msg; i++) {
15424520Snw141292 		if (stattable[i].retcode == status)
1543*4526Sbaban 			return (gettext(stattable[i].msg));
15444520Snw141292 	}
15454520Snw141292 	return (gettext("Unknown error"));
15464520Snw141292 }
15474520Snw141292 
15484520Snw141292 
15494520Snw141292 static int
15504520Snw141292 idmap_stat2errno(idmap_stat stat) {
15514520Snw141292 	int i;
15524520Snw141292 	for (i = 0; stattable[i].msg; i++) {
15534520Snw141292 		if (stattable[i].retcode == stat)
15544520Snw141292 			return (stattable[i].errnum);
15554520Snw141292 	}
15564520Snw141292 	return (EINVAL);
15574520Snw141292 }
15584520Snw141292 
15594520Snw141292 
15604520Snw141292 /*
15614520Snw141292  * Get status code from string
15624520Snw141292  */
15634520Snw141292 idmap_stat
15644520Snw141292 idmap_string2stat(const char *str) {
15654520Snw141292 	if (str == NULL)
15664520Snw141292 		return (IDMAP_ERR_INTERNAL);
15674520Snw141292 
15684520Snw141292 #define	return_cmp(a) \
15694520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
15704520Snw141292 		return (IDMAP_ERR_ ## a);
15714520Snw141292 
15724520Snw141292 	return_cmp(OTHER);
15734520Snw141292 	return_cmp(INTERNAL);
15744520Snw141292 	return_cmp(MEMORY);
15754520Snw141292 	return_cmp(NORESULT);
15764520Snw141292 	return_cmp(NOTUSER);
15774520Snw141292 	return_cmp(NOTGROUP);
15784520Snw141292 	return_cmp(NOTSUPPORTED);
15794520Snw141292 	return_cmp(W2U_NAMERULE);
15804520Snw141292 	return_cmp(U2W_NAMERULE);
15814520Snw141292 	return_cmp(CACHE);
15824520Snw141292 	return_cmp(DB);
15834520Snw141292 	return_cmp(ARG);
15844520Snw141292 	return_cmp(SID);
15854520Snw141292 	return_cmp(IDTYPE);
15864520Snw141292 	return_cmp(RPC_HANDLE);
15874520Snw141292 	return_cmp(RPC);
15884520Snw141292 	return_cmp(CLIENT_HANDLE);
15894520Snw141292 	return_cmp(BUSY);
15904520Snw141292 	return_cmp(PERMISSION_DENIED);
15914520Snw141292 	return_cmp(NOMAPPING);
15924520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
15934520Snw141292 	return_cmp(DOMAIN);
15944520Snw141292 	return_cmp(SECURITY);
15954520Snw141292 	return_cmp(NOTFOUND);
15964520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
15974520Snw141292 	return_cmp(MEMORY);
15984520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
15994520Snw141292 	return_cmp(CFG);
16004520Snw141292 	return_cmp(CFG_CHANGE);
16014520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
16024520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
16034520Snw141292 #undef return_cmp
16044520Snw141292 
16054520Snw141292 	return (IDMAP_ERR_OTHER);
16064520Snw141292 }
16074520Snw141292 
16084520Snw141292 
16094520Snw141292 /*
16104520Snw141292  * Map the given status to one that can be returned by the protocol
16114520Snw141292  */
16124520Snw141292 idmap_stat
16134520Snw141292 idmap_stat4prot(idmap_stat status) {
16144520Snw141292 	switch (status) {
16154520Snw141292 	case IDMAP_ERR_MEMORY:
16164520Snw141292 	case IDMAP_ERR_CACHE:
16174520Snw141292 		return (IDMAP_ERR_INTERNAL);
16184520Snw141292 	}
16194520Snw141292 	return (status);
16204520Snw141292 }
1621