Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 /*
     28  * libidmap API
     29  */
     30 
     31 #include <stdlib.h>
     32 #include <sys/varargs.h>
     33 #include <inttypes.h>
     34 #include <errno.h>
     35 #include <strings.h>
     36 #include <ctype.h>
     37 #include <sys/param.h>
     38 #include <sys/types.h>
     39 #include <sys/stat.h>
     40 #include <dlfcn.h>
     41 #include <libintl.h>
     42 #include <ucontext.h>
     43 #include "idmap_impl.h"
     44 #include "idmap_cache.h"
     45 
     46 /*LINTLIBRARY*/
     47 
     48 static struct timeval TIMEOUT = { 25, 0 };
     49 
     50 static int idmap_stat2errno(idmap_stat);
     51 static idmap_stat	idmap_strdupnull(char **, const char *);
     52 
     53 #define	__ITER_CREATE(itera, argu, handl, ityp)\
     54 	if (handl == NULL) {\
     55 		errno = EINVAL;\
     56 		return (IDMAP_ERR_ARG);\
     57 	}\
     58 	itera = calloc(1, sizeof (*itera));\
     59 	if (itera == NULL) {\
     60 		errno = ENOMEM;\
     61 		return (IDMAP_ERR_MEMORY);\
     62 	}\
     63 	argu = calloc(1, sizeof (*argu));\
     64 	if (argu == NULL) {\
     65 		free(itera);\
     66 		errno = ENOMEM;\
     67 		return (IDMAP_ERR_MEMORY);\
     68 	}\
     69 	itera->ih = handl;\
     70 	itera->type = ityp;\
     71 	itera->retcode = IDMAP_NEXT;\
     72 	itera->limit = 1024;\
     73 	itera->arg = argu;
     74 
     75 
     76 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
     77 	if (argu) {\
     78 		xdr_free(xdr_argu, (caddr_t)argu);\
     79 		free(argu);\
     80 	}\
     81 	if (itera)\
     82 		free(itera);\
     83 	return (iretcod);
     84 
     85 
     86 #define	__ITER_CHECK(itera, ityp)\
     87 	if (itera == NULL) {\
     88 		errno = EINVAL;\
     89 		return (IDMAP_ERR_ARG);\
     90 	}\
     91 	if (itera->type != ityp) {\
     92 		errno = EINVAL;\
     93 		return (IDMAP_ERR_ARG);\
     94 	}
     95 
     96 /*
     97  * Free memory allocated by libidmap API
     98  *
     99  * Input:
    100  * ptr - memory to be freed
    101  */
    102 void
    103 idmap_free(void *ptr)
    104 {
    105 	free(ptr);
    106 }
    107 
    108 
    109 #define	MIN_STACK_NEEDS	65536
    110 
    111 /*
    112  * Create and Initialize idmap client handle for rpc/doors
    113  *
    114  * Output:
    115  * handle - idmap handle
    116  */
    117 idmap_stat
    118 idmap_init(idmap_handle_t **handle)
    119 {
    120 	CLIENT			*clnt = NULL;
    121 	struct idmap_handle	*hptr;
    122 	uint_t			sendsz = 0;
    123 	stack_t			st;
    124 
    125 	*handle = NULL;
    126 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
    127 	if (hptr == NULL)
    128 		return (IDMAP_ERR_MEMORY);
    129 
    130 	/*
    131 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
    132 	 * the call args buffer and once for the call result buffer), so
    133 	 * we want to pick a sendsz that will be large enough, but not
    134 	 * too large.
    135 	 */
    136 	if (stack_getbounds(&st) == 0) {
    137 		/*
    138 		 * Estimate how much stack space is left;
    139 		 * st.ss_sp is the top of stack.
    140 		 */
    141 		if ((char *)&sendsz < (char *)st.ss_sp)
    142 			/* stack grows up */
    143 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
    144 		else
    145 			/* stack grows down */
    146 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
    147 
    148 		if (sendsz <= MIN_STACK_NEEDS) {
    149 			sendsz = 0;	/* RPC call may fail */
    150 		} else {
    151 			/* Leave 64Kb (just a guess) for our needs */
    152 			sendsz -= MIN_STACK_NEEDS;
    153 
    154 			/* Divide the stack space left by two */
    155 			sendsz = RNDUP(sendsz / 2);
    156 
    157 			/* Limit sendsz to 256KB */
    158 			if (sendsz > IDMAP_MAX_DOOR_RPC)
    159 				sendsz = IDMAP_MAX_DOOR_RPC;
    160 		}
    161 	}
    162 
    163 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
    164 	if (clnt == NULL) {
    165 		free(hptr);
    166 		return (IDMAP_ERR_RPC);
    167 	}
    168 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
    169 	hptr->privhandle = clnt;
    170 	*handle = hptr;
    171 	return (IDMAP_SUCCESS);
    172 }
    173 
    174 
    175 /*
    176  * Finalize idmap handle
    177  *
    178  * Input:
    179  * handle - idmap handle
    180  */
    181 idmap_stat
    182 idmap_fini(idmap_handle_t *handle)
    183 {
    184 	CLIENT			*clnt;
    185 	struct idmap_handle	*hptr;
    186 
    187 	if (handle == NULL)
    188 		return (IDMAP_SUCCESS);
    189 
    190 	hptr = (struct idmap_handle *)handle;
    191 
    192 	switch (hptr->type) {
    193 	case _IDMAP_HANDLE_RPC_DOORS:
    194 		clnt = (CLIENT *)hptr->privhandle;
    195 		if (clnt) {
    196 			if (clnt->cl_auth)
    197 				auth_destroy(clnt->cl_auth);
    198 			clnt_destroy(clnt);
    199 		}
    200 		break;
    201 	default:
    202 		break;
    203 	}
    204 	free(hptr);
    205 	return (IDMAP_SUCCESS);
    206 }
    207 
    208 
    209 static idmap_stat
    210 idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
    211 {
    212 	CLIENT			*clnt;
    213 	enum clnt_stat		clntstat;
    214 
    215 
    216 	(void) memset(res, 0, sizeof (*res));
    217 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
    218 
    219 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
    220 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
    221 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
    222 
    223 	if (clntstat != RPC_SUCCESS) {
    224 		return (_idmap_rpc2stat(clnt));
    225 	}
    226 
    227 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
    228 }
    229 
    230 
    231 idmap_stat
    232 idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
    233     idmap_ad_disc_ds_t *dc)
    234 {
    235 	idmap_prop_res res;
    236 	idmap_stat rc = IDMAP_SUCCESS;
    237 
    238 	rc = idmap_get_prop(handle, pr, &res);
    239 	if (rc < 0)
    240 		return (rc);
    241 
    242 	dc->port = res.value.idmap_prop_val_u.dsval.port;
    243 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
    244 	    AD_DISC_MAXHOSTNAME);
    245 
    246 	/* xdr doesn't guarantee 0-termination of char[]: */
    247 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
    248 
    249 	return (rc);
    250 }
    251 
    252 
    253 /*
    254  * Sometimes the property is not set. In that case, str is set to NULL but
    255  * otherwise IDMAP_SUCCESS is returned.
    256  */
    257 idmap_stat
    258 idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
    259 {
    260 	idmap_prop_res res;
    261 	idmap_stat rc = IDMAP_SUCCESS;
    262 
    263 	rc = idmap_get_prop(handle, pr, &res);
    264 	if (rc < 0)
    265 		return (rc);
    266 
    267 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
    268 	return (rc);
    269 }
    270 
    271 /*
    272  * Create/Initialize handle for updates
    273  *
    274  * Output:
    275  * udthandle - update handle
    276  */
    277 idmap_stat
    278 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
    279 {
    280 	idmap_udt_handle_t	*tmp;
    281 
    282 	if (handle == NULL || udthandle == NULL) {
    283 		errno = EINVAL;
    284 		return (IDMAP_ERR_ARG);
    285 	}
    286 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
    287 		errno = ENOMEM;
    288 		return (IDMAP_ERR_MEMORY);
    289 	}
    290 
    291 	tmp->ih = handle;
    292 	*udthandle = tmp;
    293 	return (IDMAP_SUCCESS);
    294 }
    295 
    296 
    297 /*
    298  * All the updates specified by the update handle are committed
    299  * in a single transaction. i.e either all succeed or none.
    300  *
    301  * Input:
    302  * udthandle - update handle with the update requests
    303  *
    304  * Return value:
    305  * Status of the commit
    306  */
    307 idmap_stat
    308 idmap_udt_commit(idmap_udt_handle_t *udthandle)
    309 {
    310 	CLIENT			*clnt;
    311 	enum clnt_stat		clntstat;
    312 	idmap_update_res	res;
    313 	idmap_stat		retcode;
    314 
    315 	if (udthandle == NULL) {
    316 		errno = EINVAL;
    317 		return (IDMAP_ERR_ARG);
    318 	}
    319 
    320 	(void) memset(&res, 0, sizeof (res));
    321 
    322 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
    323 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
    324 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
    325 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
    326 	    TIMEOUT);
    327 
    328 	if (clntstat != RPC_SUCCESS) {
    329 		retcode = _idmap_rpc2stat(clnt);
    330 		goto out;
    331 	}
    332 
    333 	retcode = udthandle->commit_stat = res.retcode;
    334 	udthandle->error_index = res.error_index;
    335 
    336 	if (retcode != IDMAP_SUCCESS) {
    337 
    338 		if (udthandle->error_index < 0)
    339 			goto out;
    340 
    341 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
    342 		    &res.error_rule);
    343 		if (retcode != IDMAP_SUCCESS) {
    344 			udthandle->error_index = -2;
    345 			goto out;
    346 		}
    347 
    348 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
    349 		    &res.conflict_rule);
    350 		if (retcode != IDMAP_SUCCESS) {
    351 			udthandle->error_index = -2;
    352 			goto out;
    353 		}
    354 	}
    355 
    356 	retcode = res.retcode;
    357 
    358 
    359 out:
    360 	/* reset handle so that it can be used again */
    361 	if (retcode == IDMAP_SUCCESS) {
    362 		_IDMAP_RESET_UDT_HANDLE(udthandle);
    363 	}
    364 
    365 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
    366 	errno = idmap_stat2errno(retcode);
    367 	return (retcode);
    368 }
    369 
    370 
    371 static void
    372 idmap_namerule_parts_clear(char **windomain, char **winname,
    373     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
    374     boolean_t *is_nt4, int *direction)
    375 {
    376 	if (windomain)
    377 		*windomain = NULL;
    378 	if (winname)
    379 		*winname = NULL;
    380 	if (unixname)
    381 		*unixname = NULL;
    382 
    383 	if (is_nt4)
    384 		*is_nt4 = 0;
    385 	if (is_user)
    386 		*is_user = -1;
    387 	if (is_wuser)
    388 		*is_wuser = -1;
    389 	if (direction)
    390 		*direction = IDMAP_DIRECTION_UNDEF;
    391 }
    392 
    393 static idmap_stat
    394 idmap_namerule2parts(idmap_namerule *rule,
    395     char **windomain, char **winname,
    396     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
    397     boolean_t *is_nt4, int *direction)
    398 {
    399 	idmap_stat retcode;
    400 
    401 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
    402 		return (IDMAP_ERR_NORESULT);
    403 
    404 
    405 	retcode = idmap_strdupnull(windomain, rule->windomain);
    406 	if (retcode != IDMAP_SUCCESS)
    407 		goto errout;
    408 
    409 	retcode = idmap_strdupnull(winname, rule->winname);
    410 	if (retcode != IDMAP_SUCCESS)
    411 		goto errout;
    412 
    413 	retcode = idmap_strdupnull(unixname, rule->unixname);
    414 	if (retcode != IDMAP_SUCCESS)
    415 		goto errout;
    416 
    417 
    418 	if (is_user)
    419 		*is_user = rule->is_user;
    420 	if (is_wuser)
    421 		*is_wuser = rule->is_wuser;
    422 	if (is_nt4)
    423 		*is_nt4 = rule->is_nt4;
    424 	if (direction)
    425 		*direction = rule->direction;
    426 
    427 
    428 	return (IDMAP_SUCCESS);
    429 
    430 errout:
    431 	if (windomain && *windomain)
    432 		free(*windomain);
    433 	if (winname && *winname)
    434 		free(*winname);
    435 	if (unixname && *unixname)
    436 		free(*unixname);
    437 
    438 	idmap_namerule_parts_clear(windomain, winname,
    439 	    unixname, is_user, is_wuser, is_nt4, direction);
    440 
    441 	return (retcode);
    442 
    443 }
    444 
    445 /*
    446  * Retrieve the index of the failed batch element. error_index == -1
    447  * indicates failure at the beginning, -2 at the end.
    448  *
    449  * If idmap_udt_commit didn't return error, the returned value is undefined.
    450  *
    451  * Return value:
    452  * IDMAP_SUCCESS
    453  */
    454 
    455 idmap_stat
    456 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
    457     int64_t *error_index)
    458 {
    459 	if (error_index)
    460 		*error_index = udthandle->error_index;
    461 
    462 	return (IDMAP_SUCCESS);
    463 }
    464 
    465 
    466 /*
    467  * Retrieve the rule which caused the batch to fail. If
    468  * idmap_udt_commit didn't return error or if error_index is < 0, the
    469  * retrieved rule is undefined.
    470  *
    471  * Return value:
    472  * IDMAP_ERR_NORESULT if there is no error rule.
    473  * IDMAP_SUCCESS if the rule was obtained OK.
    474  * other error code (IDMAP_ERR_NOMEMORY etc)
    475  */
    476 
    477 idmap_stat
    478 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
    479     char **windomain, char **winname,
    480     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
    481     boolean_t *is_nt4, int *direction)
    482 {
    483 	idmap_namerule_parts_clear(windomain, winname,
    484 	    unixname, is_user, is_wuser, is_nt4, direction);
    485 
    486 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
    487 	    udthandle->error_index < 0)
    488 		return (IDMAP_ERR_NORESULT);
    489 
    490 	return (idmap_namerule2parts(
    491 	    &udthandle->error_rule,
    492 	    windomain,
    493 	    winname,
    494 	    unixname,
    495 	    is_user,
    496 	    is_wuser,
    497 	    is_nt4,
    498 	    direction));
    499 }
    500 
    501 /*
    502  * Retrieve the rule with which there was a conflict. TODO: retrieve
    503  * the value.
    504  *
    505  * Return value:
    506  * IDMAP_ERR_NORESULT if there is no error rule.
    507  * IDMAP_SUCCESS if the rule was obtained OK.
    508  * other error code (IDMAP_ERR_NOMEMORY etc)
    509  */
    510 
    511 idmap_stat
    512 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
    513     char **windomain, char **winname,
    514     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
    515     boolean_t *is_nt4, int *direction)
    516 {
    517 	idmap_namerule_parts_clear(windomain, winname,
    518 	    unixname, is_user, is_wuser, is_nt4, direction);
    519 
    520 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
    521 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
    522 		return (IDMAP_ERR_NORESULT);
    523 	}
    524 
    525 	return (idmap_namerule2parts(
    526 	    &udthandle->conflict_rule,
    527 	    windomain,
    528 	    winname,
    529 	    unixname,
    530 	    is_user,
    531 	    is_wuser,
    532 	    is_nt4,
    533 	    direction));
    534 }
    535 
    536 
    537 /*
    538  * Destroy the update handle
    539  */
    540 void
    541 idmap_udt_destroy(idmap_udt_handle_t *udthandle)
    542 {
    543 	if (udthandle == NULL)
    544 		return;
    545 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
    546 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
    547 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
    548 	free(udthandle);
    549 }
    550 
    551 
    552 idmap_stat
    553 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
    554     boolean_t is_user, boolean_t is_wuser, const char *winname,
    555     const char *unixname, boolean_t is_nt4, int direction)
    556 {
    557 	idmap_retcode	retcode;
    558 	idmap_namerule	*rule = NULL;
    559 
    560 	retcode = _udt_extend_batch(udthandle);
    561 	if (retcode != IDMAP_SUCCESS)
    562 		goto errout;
    563 
    564 	rule = &udthandle->batch.
    565 	    idmap_update_batch_val[udthandle->next].
    566 	    idmap_update_op_u.rule;
    567 	rule->is_user = is_user;
    568 	rule->is_wuser = is_wuser;
    569 	rule->direction = direction;
    570 	rule->is_nt4 = is_nt4;
    571 
    572 	retcode = idmap_strdupnull(&rule->windomain, windomain);
    573 	if (retcode != IDMAP_SUCCESS)
    574 		goto errout;
    575 
    576 	retcode = idmap_strdupnull(&rule->winname, winname);
    577 	if (retcode != IDMAP_SUCCESS)
    578 		goto errout;
    579 
    580 	retcode = idmap_strdupnull(&rule->unixname, unixname);
    581 	if (retcode != IDMAP_SUCCESS)
    582 		goto errout;
    583 
    584 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
    585 	    OP_ADD_NAMERULE;
    586 	udthandle->next++;
    587 	return (IDMAP_SUCCESS);
    588 
    589 errout:
    590 	/* The batch should still be usable */
    591 	if (rule)
    592 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
    593 	errno = idmap_stat2errno(retcode);
    594 	return (retcode);
    595 }
    596 
    597 
    598 /* ARGSUSED */
    599 idmap_stat
    600 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
    601     boolean_t is_wuser,	const char *windomain, const char *winname,
    602     const char *unixname, int direction)
    603 {
    604 	idmap_retcode	retcode;
    605 	idmap_namerule	*rule = NULL;
    606 
    607 	retcode = _udt_extend_batch(udthandle);
    608 	if (retcode != IDMAP_SUCCESS)
    609 		goto errout;
    610 
    611 	rule = &udthandle->batch.
    612 	    idmap_update_batch_val[udthandle->next].
    613 	    idmap_update_op_u.rule;
    614 	rule->is_user = is_user;
    615 	rule->is_wuser = is_wuser;
    616 	rule->direction = direction;
    617 
    618 	retcode = idmap_strdupnull(&rule->windomain, windomain);
    619 	if (retcode != IDMAP_SUCCESS)
    620 		goto errout;
    621 
    622 	retcode = idmap_strdupnull(&rule->winname, winname);
    623 	if (retcode != IDMAP_SUCCESS)
    624 		goto errout;
    625 
    626 	retcode = idmap_strdupnull(&rule->unixname, unixname);
    627 	if (retcode != IDMAP_SUCCESS)
    628 		goto errout;
    629 
    630 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
    631 	    OP_RM_NAMERULE;
    632 	udthandle->next++;
    633 	return (IDMAP_SUCCESS);
    634 
    635 errout:
    636 	if (rule)
    637 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
    638 	errno = idmap_stat2errno(retcode);
    639 	return (retcode);
    640 }
    641 
    642 
    643 /* ARGSUSED */
    644 idmap_stat
    645 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
    646 {
    647 	idmap_retcode	retcode;
    648 
    649 	retcode = _udt_extend_batch(udthandle);
    650 	if (retcode != IDMAP_SUCCESS)
    651 		goto errout;
    652 
    653 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
    654 	    OP_FLUSH_NAMERULES;
    655 	udthandle->next++;
    656 	return (IDMAP_SUCCESS);
    657 
    658 errout:
    659 	errno = idmap_stat2errno(retcode);
    660 	return (retcode);
    661 }
    662 
    663 
    664 /*
    665  * Set the number of entries requested per batch by the iterator
    666  *
    667  * Input:
    668  * iter  - iterator
    669  * limit - number of entries requested per batch
    670  */
    671 idmap_stat
    672 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
    673 {
    674 	if (iter == NULL) {
    675 		errno = EINVAL;
    676 		return (IDMAP_ERR_ARG);
    677 	}
    678 	iter->limit = limit;
    679 	return (IDMAP_SUCCESS);
    680 }
    681 
    682 
    683 /*
    684  * Create iterator to get name-based mapping rules
    685  *
    686  * Input:
    687  * windomain - Windows domain
    688  * is_user   - user or group rules
    689  * winname   - Windows user or group name
    690  * unixname  - Unix user or group name
    691  *
    692  * Output:
    693  * iter - iterator
    694  */
    695 idmap_stat
    696 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
    697 		boolean_t is_user, boolean_t is_wuser, const char *winname,
    698 		const char *unixname, idmap_iter_t **iter)
    699 {
    700 
    701 	idmap_iter_t			*tmpiter;
    702 	idmap_list_namerules_1_argument	*arg = NULL;
    703 	idmap_namerule			*rule;
    704 	idmap_retcode			retcode;
    705 
    706 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
    707 
    708 	rule = &arg->rule;
    709 	rule->is_user = is_user;
    710 	rule->is_wuser = is_wuser;
    711 	rule->direction = IDMAP_DIRECTION_UNDEF;
    712 
    713 	retcode = idmap_strdupnull(&rule->windomain, windomain);
    714 	if (retcode != IDMAP_SUCCESS)
    715 		goto errout;
    716 
    717 	retcode = idmap_strdupnull(&rule->winname, winname);
    718 	if (retcode != IDMAP_SUCCESS)
    719 		goto errout;
    720 
    721 	retcode = idmap_strdupnull(&rule->unixname, unixname);
    722 	if (retcode != IDMAP_SUCCESS)
    723 		goto errout;
    724 
    725 	*iter = tmpiter;
    726 	return (IDMAP_SUCCESS);
    727 
    728 errout:
    729 	__ITER_ERR_RETURN(tmpiter, arg,
    730 	    xdr_idmap_list_namerules_1_argument, retcode);
    731 }
    732 
    733 
    734 /*
    735  * Iterate through the name-based mapping rules
    736  *
    737  * Input:
    738  * iter - iterator
    739  *
    740  * Output:
    741  * windomain - Windows domain
    742  * winname   - Windows user or group name
    743  * unixname  - Unix user or group name
    744  * is_nt4    - NT4 or AD
    745  * direction - bi(0), win2unix(1), unix2win(2)
    746  *
    747  * Return value:
    748  * 0   - done
    749  * 1   - more results available
    750  * < 0 - error
    751  */
    752 idmap_stat
    753 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
    754     char **winname, char **unixname,  boolean_t *is_user,
    755     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
    756 {
    757 	idmap_namerules_res		*namerules;
    758 	idmap_list_namerules_1_argument	*arg;
    759 	idmap_retcode			retcode;
    760 
    761 	idmap_namerule_parts_clear(windomain, winname,
    762 	    unixname, is_user, is_wuser, is_nt4, direction);
    763 
    764 
    765 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
    766 
    767 	namerules = (idmap_namerules_res *)iter->retlist;
    768 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
    769 	    iter->next >= namerules->rules.rules_len)) {
    770 
    771 		if ((arg = iter->arg) == NULL) {
    772 			errno = EINVAL;
    773 			return (IDMAP_ERR_ARG);
    774 		}
    775 		arg->limit = iter->limit;
    776 
    777 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
    778 		    iter, arg,
    779 		    (uchar_t **)&namerules, sizeof (*namerules),
    780 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
    781 		    (xdrproc_t)xdr_idmap_namerules_res);
    782 		if (retcode != IDMAP_SUCCESS)
    783 			return (retcode);
    784 
    785 		if (IDMAP_ERROR(namerules->retcode)) {
    786 			retcode  = namerules->retcode;
    787 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
    788 			free(namerules);
    789 			iter->retlist = NULL;
    790 			return (retcode);
    791 		}
    792 		iter->retcode = namerules->retcode;
    793 		arg->lastrowid = namerules->lastrowid;
    794 	}
    795 
    796 	if (namerules == NULL || namerules->rules.rules_len == 0)
    797 		return (IDMAP_SUCCESS);
    798 
    799 	if (iter->next >= namerules->rules.rules_len) {
    800 		return (IDMAP_ERR_ARG);
    801 	}
    802 
    803 	retcode = idmap_strdupnull(windomain,
    804 	    namerules->rules.rules_val[iter->next].windomain);
    805 	if (retcode != IDMAP_SUCCESS)
    806 		goto errout;
    807 
    808 	retcode = idmap_strdupnull(winname,
    809 	    namerules->rules.rules_val[iter->next].winname);
    810 	if (retcode != IDMAP_SUCCESS)
    811 		goto errout;
    812 
    813 	retcode = idmap_strdupnull(unixname,
    814 	    namerules->rules.rules_val[iter->next].unixname);
    815 	if (retcode != IDMAP_SUCCESS)
    816 		goto errout;
    817 
    818 	if (is_nt4)
    819 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
    820 	if (is_user)
    821 		*is_user = namerules->rules.rules_val[iter->next].is_user;
    822 	if (is_wuser)
    823 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
    824 	if (direction)
    825 		*direction = namerules->rules.rules_val[iter->next].direction;
    826 	iter->next++;
    827 
    828 	if (iter->next == namerules->rules.rules_len)
    829 		return (iter->retcode);
    830 	else
    831 		return (IDMAP_NEXT);
    832 
    833 errout:
    834 	if (windomain && *windomain)
    835 		free(*windomain);
    836 	if (winname && *winname)
    837 		free(*winname);
    838 	if (unixname && *unixname)
    839 		free(*unixname);
    840 	return (retcode);
    841 }
    842 
    843 
    844 /*
    845  * Create iterator to get SID to UID/GID mappings
    846  *
    847  * Output:
    848  * iter - iterator
    849  */
    850 idmap_stat
    851 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
    852 {
    853 	idmap_iter_t			*tmpiter;
    854 	idmap_list_mappings_1_argument	*arg = NULL;
    855 
    856 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
    857 
    858 	arg->flag = flag;
    859 	*iter = tmpiter;
    860 	return (IDMAP_SUCCESS);
    861 }
    862 
    863 
    864 /*
    865  * Iterate through the SID to UID/GID mappings
    866  *
    867  * Input:
    868  * iter - iterator
    869  *
    870  * Output:
    871  * sid - SID in canonical form
    872  * pid - UID or GID
    873  *
    874  * Return value:
    875  * 0   - done
    876  * 1   - more results available
    877  * < 0 - error
    878  */
    879 idmap_stat
    880 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
    881     idmap_rid_t *rid, uid_t *pid, char **winname,
    882     char **windomain, char **unixname, boolean_t *is_user,
    883     boolean_t *is_wuser, int *direction, idmap_info *info)
    884 {
    885 	idmap_mappings_res		*mappings;
    886 	idmap_list_mappings_1_argument	*arg;
    887 	idmap_retcode			retcode;
    888 	char				*str;
    889 
    890 	if (sidprefix)
    891 		*sidprefix = NULL;
    892 	if (rid)
    893 		*rid = UINT32_MAX;
    894 	if (winname)
    895 		*winname = NULL;
    896 	if (windomain)
    897 		*windomain = NULL;
    898 	if (unixname)
    899 		*unixname = NULL;
    900 	if (pid)
    901 		*pid = UINT32_MAX;
    902 	if (is_user)
    903 		*is_user = -1;
    904 	if (is_wuser)
    905 		*is_wuser = -1;
    906 	if (direction)
    907 		*direction = IDMAP_DIRECTION_UNDEF;
    908 
    909 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
    910 
    911 	mappings = (idmap_mappings_res *)iter->retlist;
    912 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
    913 	    iter->next >= mappings->mappings.mappings_len)) {
    914 
    915 		if ((arg = iter->arg) == NULL) {
    916 			errno = EINVAL;
    917 			return (IDMAP_ERR_ARG);
    918 		}
    919 		arg->limit = iter->limit;
    920 
    921 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
    922 		    iter, arg,
    923 		    (uchar_t **)&mappings, sizeof (*mappings),
    924 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
    925 		    (xdrproc_t)xdr_idmap_mappings_res);
    926 		if (retcode != IDMAP_SUCCESS)
    927 			return (retcode);
    928 
    929 		if (IDMAP_ERROR(mappings->retcode)) {
    930 			retcode  = mappings->retcode;
    931 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
    932 			free(mappings);
    933 			iter->retlist = NULL;
    934 			return (retcode);
    935 		}
    936 		iter->retcode = mappings->retcode;
    937 		arg->lastrowid = mappings->lastrowid;
    938 	}
    939 
    940 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
    941 		return (IDMAP_SUCCESS);
    942 
    943 	if (iter->next >= mappings->mappings.mappings_len) {
    944 		return (IDMAP_ERR_ARG);
    945 	}
    946 
    947 	if (sidprefix) {
    948 		str = mappings->mappings.mappings_val[iter->next].id1.
    949 		    idmap_id_u.sid.prefix;
    950 		if (str && *str != '\0') {
    951 			*sidprefix = strdup(str);
    952 			if (*sidprefix == NULL) {
    953 				retcode = IDMAP_ERR_MEMORY;
    954 				goto errout;
    955 			}
    956 		}
    957 	}
    958 	if (rid)
    959 		*rid = mappings->mappings.mappings_val[iter->next].id1.
    960 		    idmap_id_u.sid.rid;
    961 
    962 	retcode = idmap_strdupnull(windomain,
    963 	    mappings->mappings.mappings_val[iter->next].id1domain);
    964 	if (retcode != IDMAP_SUCCESS)
    965 		goto errout;
    966 
    967 	retcode = idmap_strdupnull(winname,
    968 	    mappings->mappings.mappings_val[iter->next].id1name);
    969 	if (retcode != IDMAP_SUCCESS)
    970 		goto errout;
    971 
    972 	retcode = idmap_strdupnull(unixname,
    973 	    mappings->mappings.mappings_val[iter->next].id2name);
    974 	if (retcode != IDMAP_SUCCESS)
    975 		goto errout;
    976 
    977 
    978 	if (pid)
    979 		*pid = mappings->mappings.mappings_val[iter->next].id2.
    980 		    idmap_id_u.uid;
    981 	if (direction)
    982 		*direction = mappings->mappings.mappings_val[iter->next].
    983 		    direction;
    984 	if (is_user)
    985 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
    986 		    .idtype == IDMAP_UID)?1:0;
    987 	if (is_wuser)
    988 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
    989 		    .idtype == IDMAP_USID)?1:0;
    990 
    991 	if (info) {
    992 		retcode = idmap_info_cpy(info,
    993 		    &mappings->mappings.mappings_val[iter->next].info);
    994 		if (retcode != IDMAP_SUCCESS)
    995 			goto errout;
    996 	}
    997 	iter->next++;
    998 
    999 	if (iter->next == mappings->mappings.mappings_len)
   1000 		return (iter->retcode);
   1001 	else
   1002 		return (IDMAP_NEXT);
   1003 
   1004 errout:
   1005 	if (sidprefix && *sidprefix)
   1006 		free(*sidprefix);
   1007 	if (winname && *winname)
   1008 		free(*winname);
   1009 	if (windomain && *windomain)
   1010 		free(*windomain);
   1011 	if (unixname && *unixname)
   1012 		free(*unixname);
   1013 	return (retcode);
   1014 }
   1015 
   1016 
   1017 /*
   1018  * Destroy the iterator
   1019  */
   1020 void
   1021 idmap_iter_destroy(idmap_iter_t *iter)
   1022 {
   1023 	xdrproc_t _xdr_argument, _xdr_result;
   1024 
   1025 	if (iter == NULL)
   1026 		return;
   1027 
   1028 	switch (iter->type) {
   1029 	case IDMAP_LIST_NAMERULES:
   1030 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
   1031 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
   1032 		break;
   1033 	case IDMAP_LIST_MAPPINGS:
   1034 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
   1035 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
   1036 		break;
   1037 	default:
   1038 		free(iter);
   1039 		return;
   1040 	};
   1041 
   1042 	if (iter->arg) {
   1043 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
   1044 		free(iter->arg);
   1045 	}
   1046 	if (iter->retlist) {
   1047 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
   1048 		free(iter->retlist);
   1049 	}
   1050 	free(iter);
   1051 }
   1052 
   1053 
   1054 /*
   1055  * Create handle to get SID to UID/GID mapping entries
   1056  *
   1057  * Input:
   1058  * gh - "get mapping" handle
   1059  */
   1060 idmap_stat
   1061 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
   1062 {
   1063 	idmap_get_handle_t	*tmp;
   1064 
   1065 	/* sanity checks */
   1066 	if (handle == NULL || gh == NULL) {
   1067 		errno = EINVAL;
   1068 		return (IDMAP_ERR_ARG);
   1069 	}
   1070 
   1071 	/* allocate the handle */
   1072 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
   1073 		errno = ENOMEM;
   1074 		return (IDMAP_ERR_MEMORY);
   1075 	}
   1076 
   1077 	tmp->ih = handle;
   1078 	*gh = tmp;
   1079 	return (IDMAP_SUCCESS);
   1080 }
   1081 
   1082 
   1083 /*
   1084  * Given SID, get UID
   1085  *
   1086  * Input:
   1087  * sidprefix  - SID prefix
   1088  * rid        - RID
   1089  * flag       - flag
   1090  *
   1091  * Output:
   1092  * stat - status of the get request
   1093  * uid  - POSIX UID if stat = 0
   1094  *
   1095  * Note: The output parameters will be set by idmap_get_mappings()
   1096  */
   1097 idmap_stat
   1098 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1099 		int flag, uid_t *uid, idmap_stat *stat)
   1100 {
   1101 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
   1102 	    NULL, stat));
   1103 }
   1104 
   1105 /*
   1106  * Given SID, get UID
   1107  *
   1108  * Input:
   1109  * sidprefix  - SID prefix
   1110  * rid        - RID
   1111  * flag       - flag
   1112  *
   1113  * Output:
   1114  * stat - status of the get request
   1115  * uid  - POSIX UID if stat = 0
   1116  * how  - mapping type if stat = 0
   1117  *
   1118  * Note: The output parameters will be set by idmap_get_mappings()
   1119  */
   1120 
   1121 idmap_stat
   1122 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1123 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
   1124 {
   1125 	idmap_retcode	retcode;
   1126 	idmap_mapping	*mapping = NULL;
   1127 
   1128 	/* sanity checks */
   1129 	if (gh == NULL)
   1130 		return (IDMAP_ERR_ARG);
   1131 	if (uid == NULL || sidprefix == NULL)
   1132 		return (IDMAP_ERR_ARG);
   1133 
   1134 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
   1135 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
   1136 		retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid);
   1137 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
   1138 			*stat = retcode;
   1139 			return (retcode);
   1140 		}
   1141 	}
   1142 
   1143 	/* Extend the request array and the return list */
   1144 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
   1145 		goto errout;
   1146 
   1147 	/* Setup the request */
   1148 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
   1149 	mapping->flag = flag;
   1150 	mapping->id1.idtype = IDMAP_SID;
   1151 	mapping->id1.idmap_id_u.sid.rid = rid;
   1152 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
   1153 		retcode = IDMAP_ERR_MEMORY;
   1154 		goto errout;
   1155 	}
   1156 	mapping->id2.idtype = IDMAP_UID;
   1157 
   1158 	/* Setup pointers for the result */
   1159 	gh->retlist[gh->next].idtype = IDMAP_UID;
   1160 	gh->retlist[gh->next].uid = uid;
   1161 	gh->retlist[gh->next].stat = stat;
   1162 	gh->retlist[gh->next].info = info;
   1163 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
   1164 
   1165 	gh->next++;
   1166 	return (IDMAP_SUCCESS);
   1167 
   1168 errout:
   1169 	/* Batch created so far should still be usable */
   1170 	if (mapping)
   1171 		(void) memset(mapping, 0, sizeof (*mapping));
   1172 	errno = idmap_stat2errno(retcode);
   1173 	return (retcode);
   1174 }
   1175 
   1176 
   1177 /*
   1178  * Given SID, get GID
   1179  *
   1180  * Input:
   1181  * sidprefix  - SID prefix
   1182  * rid        - rid
   1183  * flag       - flag
   1184  *
   1185  * Output:
   1186  * stat - status of the get request
   1187  * gid  - POSIX GID if stat = 0
   1188  *
   1189  * Note: The output parameters will be set by idmap_get_mappings()
   1190  */
   1191 idmap_stat
   1192 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1193 		int flag, gid_t *gid, idmap_stat *stat)
   1194 {
   1195 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
   1196 	    NULL, stat));
   1197 }
   1198 
   1199 
   1200 /*
   1201  * Given SID, get GID
   1202  *
   1203  * Input:
   1204  * sidprefix  - SID prefix
   1205  * rid        - rid
   1206  * flag       - flag
   1207  *
   1208  * Output:
   1209  * stat - status of the get request
   1210  * gid  - POSIX GID if stat = 0
   1211  * how  - mapping type if stat = 0
   1212  *
   1213  * Note: The output parameters will be set by idmap_get_mappings()
   1214  */
   1215 idmap_stat
   1216 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1217 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
   1218 {
   1219 
   1220 	idmap_retcode	retcode;
   1221 	idmap_mapping	*mapping = NULL;
   1222 
   1223 	/* sanity checks */
   1224 	if (gh == NULL)
   1225 		return (IDMAP_ERR_ARG);
   1226 	if (gid == NULL || sidprefix == NULL)
   1227 		return (IDMAP_ERR_ARG);
   1228 
   1229 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
   1230 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
   1231 		retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid);
   1232 		if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
   1233 			*stat = retcode;
   1234 			return (retcode);
   1235 		}
   1236 	}
   1237 
   1238 	/* Extend the request array and the return list */
   1239 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
   1240 		goto errout;
   1241 
   1242 	/* Setup the request */
   1243 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
   1244 	mapping->flag = flag;
   1245 	mapping->id1.idtype = IDMAP_SID;
   1246 	mapping->id1.idmap_id_u.sid.rid = rid;
   1247 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
   1248 		retcode = IDMAP_ERR_MEMORY;
   1249 		goto errout;
   1250 	}
   1251 	mapping->id2.idtype = IDMAP_GID;
   1252 
   1253 	/* Setup pointers for the result */
   1254 	gh->retlist[gh->next].idtype = IDMAP_GID;
   1255 	gh->retlist[gh->next].gid = gid;
   1256 	gh->retlist[gh->next].stat = stat;
   1257 	gh->retlist[gh->next].info = info;
   1258 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
   1259 
   1260 	gh->next++;
   1261 	return (IDMAP_SUCCESS);
   1262 
   1263 errout:
   1264 	if (mapping)
   1265 		(void) memset(mapping, 0, sizeof (*mapping));
   1266 	errno = idmap_stat2errno(retcode);
   1267 	return (retcode);
   1268 }
   1269 
   1270 
   1271 
   1272 /*
   1273  * Given SID, get POSIX ID i.e. UID/GID
   1274  *
   1275  * Input:
   1276  * sidprefix  - SID prefix
   1277  * rid        - rid
   1278  * flag       - flag
   1279  *
   1280  * Output:
   1281  * stat    - status of the get request
   1282  * is_user - user or group
   1283  * pid     - POSIX UID if stat = 0 and is_user = 1
   1284  *           POSIX GID if stat = 0 and is_user = 0
   1285  *
   1286  * Note: The output parameters will be set by idmap_get_mappings()
   1287  */
   1288 idmap_stat
   1289 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1290 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
   1291 {
   1292 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
   1293 	    NULL, stat));
   1294 }
   1295 
   1296 
   1297 
   1298 /*
   1299  * Given SID, get POSIX ID i.e. UID/GID
   1300  *
   1301  * Input:
   1302  * sidprefix  - SID prefix
   1303  * rid        - rid
   1304  * flag       - flag
   1305  *
   1306  * Output:
   1307  * stat    - status of the get request
   1308  * is_user - user or group
   1309  * pid     - POSIX UID if stat = 0 and is_user = 1
   1310  *           POSIX GID if stat = 0 and is_user = 0
   1311  * how     - mapping type if stat = 0
   1312  *
   1313  * Note: The output parameters will be set by idmap_get_mappings()
   1314  */
   1315 idmap_stat
   1316 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
   1317 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
   1318 {
   1319 	idmap_retcode	retcode;
   1320 	idmap_mapping	*mapping = NULL;
   1321 
   1322 	/* sanity checks */
   1323 	if (gh == NULL)
   1324 		return (IDMAP_ERR_ARG);
   1325 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
   1326 		return (IDMAP_ERR_ARG);
   1327 
   1328 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
   1329 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
   1330 		retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid,
   1331 		    is_user);
   1332 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
   1333 			*stat = retcode;
   1334 			return (retcode);
   1335 		}
   1336 	}
   1337 
   1338 	/* Extend the request array and the return list */
   1339 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
   1340 		goto errout;
   1341 
   1342 	/* Setup the request */
   1343 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
   1344 	mapping->flag = flag;
   1345 	mapping->id1.idtype = IDMAP_SID;
   1346 	mapping->id1.idmap_id_u.sid.rid = rid;
   1347 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
   1348 		retcode = IDMAP_ERR_MEMORY;
   1349 		goto errout;
   1350 	}
   1351 	mapping->id2.idtype = IDMAP_POSIXID;
   1352 
   1353 	/* Setup pointers for the result */
   1354 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
   1355 	gh->retlist[gh->next].uid = pid;
   1356 	gh->retlist[gh->next].gid = pid;
   1357 	gh->retlist[gh->next].is_user = is_user;
   1358 	gh->retlist[gh->next].stat = stat;
   1359 	gh->retlist[gh->next].info = info;
   1360 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
   1361 
   1362 	gh->next++;
   1363 	return (IDMAP_SUCCESS);
   1364 
   1365 errout:
   1366 	if (mapping)
   1367 		(void) memset(mapping, 0, sizeof (*mapping));
   1368 	errno = idmap_stat2errno(retcode);
   1369 	return (retcode);
   1370 }
   1371 
   1372 
   1373 /*
   1374  * Given UID, get SID
   1375  *
   1376  * Input:
   1377  * uid  - POSIX UID
   1378  * flag - flag
   1379  *
   1380  * Output:
   1381  * stat - status of the get request
   1382  * sid  - SID prefix (if stat == 0)
   1383  * rid  - rid
   1384  *
   1385  * Note: The output parameters will be set by idmap_get_mappings()
   1386  */
   1387 idmap_stat
   1388 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
   1389 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
   1390 {
   1391 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
   1392 	    NULL, stat));
   1393 }
   1394 
   1395 
   1396 /*
   1397  * Given UID, get SID
   1398  *
   1399  * Input:
   1400  * uid  - POSIX UID
   1401  * flag - flag
   1402  *
   1403  * Output:
   1404  * stat - status of the get request
   1405  * sid  - SID prefix (if stat == 0)
   1406  * rid  - rid
   1407  * how  - mapping type if stat = 0
   1408  *
   1409  * Note: The output parameters will be set by idmap_get_mappings()
   1410  */
   1411 idmap_stat
   1412 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
   1413 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
   1414 {
   1415 
   1416 	idmap_retcode	retcode;
   1417 	idmap_mapping	*mapping = NULL;
   1418 
   1419 	/* sanity checks */
   1420 	if (gh == NULL)
   1421 		return (IDMAP_ERR_ARG);
   1422 	if (sidprefix == NULL)
   1423 		return (IDMAP_ERR_ARG);
   1424 
   1425 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
   1426 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
   1427 		retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid);
   1428 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
   1429 			*stat = retcode;
   1430 			return (retcode);
   1431 		}
   1432 	}
   1433 
   1434 	/* Extend the request array and the return list */
   1435 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
   1436 		goto errout;
   1437 
   1438 	/* Setup the request */
   1439 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
   1440 	mapping->flag = flag;
   1441 	mapping->id1.idtype = IDMAP_UID;
   1442 	mapping->id1.idmap_id_u.uid = uid;
   1443 	mapping->id2.idtype = IDMAP_SID;
   1444 
   1445 	/* Setup pointers for the result */
   1446 	gh->retlist[gh->next].idtype = IDMAP_SID;
   1447 	gh->retlist[gh->next].sidprefix = sidprefix;
   1448 	gh->retlist[gh->next].rid = rid;
   1449 	gh->retlist[gh->next].stat = stat;
   1450 	gh->retlist[gh->next].info = info;
   1451 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
   1452 
   1453 	gh->next++;
   1454 	return (IDMAP_SUCCESS);
   1455 
   1456 errout:
   1457 	if (mapping)
   1458 		(void) memset(mapping, 0, sizeof (*mapping));
   1459 	errno = idmap_stat2errno(retcode);
   1460 	return (retcode);
   1461 }
   1462 
   1463 
   1464 /*
   1465  * Given GID, get SID
   1466  *
   1467  * Input:
   1468  * gid  - POSIX GID
   1469  * flag - flag
   1470  *
   1471  * Output:
   1472  * stat       - status of the get request
   1473  * sidprefix  - SID prefix (if stat == 0)
   1474  * rid        - rid
   1475  *
   1476  * Note: The output parameters will be set by idmap_get_mappings()
   1477  */
   1478 idmap_stat
   1479 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
   1480 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
   1481 {
   1482 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
   1483 	    NULL, stat));
   1484 }
   1485 
   1486 
   1487 /*
   1488  * Given GID, get SID
   1489  *
   1490  * Input:
   1491  * gid  - POSIX GID
   1492  * flag - flag
   1493  *
   1494  * Output:
   1495  * stat       - status of the get request
   1496  * sidprefix  - SID prefix (if stat == 0)
   1497  * rid        - rid
   1498  * how        - mapping type if stat = 0
   1499  *
   1500  * Note: The output parameters will be set by idmap_get_mappings()
   1501  */
   1502 idmap_stat
   1503 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
   1504 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
   1505 {
   1506 
   1507 	idmap_retcode	retcode;
   1508 	idmap_mapping	*mapping = NULL;
   1509 
   1510 	/* sanity checks */
   1511 	if (gh == NULL)
   1512 		return (IDMAP_ERR_ARG);
   1513 	if (sidprefix == NULL)
   1514 		return (IDMAP_ERR_ARG);
   1515 
   1516 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
   1517 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
   1518 		retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid);
   1519 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
   1520 			*stat = retcode;
   1521 			return (retcode);
   1522 		}
   1523 	}
   1524 
   1525 	/* Extend the request array and the return list */
   1526 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
   1527 		goto errout;
   1528 
   1529 	/* Setup the request */
   1530 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
   1531 	mapping->flag = flag;
   1532 	mapping->id1.idtype = IDMAP_GID;
   1533 	mapping->id1.idmap_id_u.gid = gid;
   1534 	mapping->id2.idtype = IDMAP_SID;
   1535 
   1536 	/* Setup pointers for the result */
   1537 	gh->retlist[gh->next].idtype = IDMAP_SID;
   1538 	gh->retlist[gh->next].sidprefix = sidprefix;
   1539 	gh->retlist[gh->next].rid = rid;
   1540 	gh->retlist[gh->next].stat = stat;
   1541 	gh->retlist[gh->next].info = info;
   1542 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
   1543 
   1544 	gh->next++;
   1545 	return (IDMAP_SUCCESS);
   1546 
   1547 errout:
   1548 	if (mapping)
   1549 		(void) memset(mapping, 0, sizeof (*mapping));
   1550 	errno = idmap_stat2errno(retcode);
   1551 	return (retcode);
   1552 }
   1553 
   1554 
   1555 /*
   1556  * Process the batched "get mapping" requests. The results (i.e.
   1557  * status and identity) will be available in the data areas
   1558  * provided by individual requests.
   1559  */
   1560 idmap_stat
   1561 idmap_get_mappings(idmap_get_handle_t *gh)
   1562 {
   1563 	CLIENT		*clnt;
   1564 	enum clnt_stat	clntstat;
   1565 	idmap_retcode	retcode;
   1566 	idmap_ids_res	res;
   1567 	idmap_id	*res_id;
   1568 	int		i;
   1569 	idmap_id	*req_id;
   1570 	int		direction;
   1571 
   1572 	if (gh == NULL) {
   1573 		errno = EINVAL;
   1574 		return (IDMAP_ERR_ARG);
   1575 	}
   1576 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
   1577 
   1578 	(void) memset(&res, 0, sizeof (idmap_ids_res));
   1579 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
   1580 	    (xdrproc_t)xdr_idmap_mapping_batch,
   1581 	    (caddr_t)&gh->batch,
   1582 	    (xdrproc_t)xdr_idmap_ids_res,
   1583 	    (caddr_t)&res,
   1584 	    TIMEOUT);
   1585 	if (clntstat != RPC_SUCCESS) {
   1586 		retcode = _idmap_rpc2stat(clnt);
   1587 		goto out;
   1588 	}
   1589 	if (res.retcode != IDMAP_SUCCESS) {
   1590 		retcode = res.retcode;
   1591 		goto out;
   1592 	}
   1593 	for (i = 0; i < gh->next; i++) {
   1594 		if (i >= res.ids.ids_len) {
   1595 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
   1596 			continue;
   1597 		}
   1598 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
   1599 		res_id = &res.ids.ids_val[i].id;
   1600 		direction = res.ids.ids_val[i].direction;
   1601 		req_id = &gh->batch.idmap_mapping_batch_val[i].id1;
   1602 		switch (res_id->idtype) {
   1603 		case IDMAP_UID:
   1604 			if (gh->retlist[i].uid)
   1605 				*gh->retlist[i].uid = res_id->idmap_id_u.uid;
   1606 			if (gh->retlist[i].is_user)
   1607 				*gh->retlist[i].is_user = 1;
   1608 
   1609 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
   1610 			    gh->retlist[i].cache_res) {
   1611 				if (gh->retlist[i].is_user != NULL)
   1612 					idmap_cache_add_sid2pid(
   1613 					    req_id->idmap_id_u.sid.prefix,
   1614 					    req_id->idmap_id_u.sid.rid,
   1615 					    res_id->idmap_id_u.uid, 1,
   1616 					    direction);
   1617 				else
   1618 					idmap_cache_add_sid2uid(
   1619 					    req_id->idmap_id_u.sid.prefix,
   1620 					    req_id->idmap_id_u.sid.rid,
   1621 					    res_id->idmap_id_u.uid,
   1622 					    direction);
   1623 			}
   1624 			break;
   1625 
   1626 		case IDMAP_GID:
   1627 			if (gh->retlist[i].gid)
   1628 				*gh->retlist[i].gid = res_id->idmap_id_u.gid;
   1629 			if (gh->retlist[i].is_user)
   1630 				*gh->retlist[i].is_user = 0;
   1631 
   1632 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
   1633 			    gh->retlist[i].cache_res) {
   1634 				if (gh->retlist[i].is_user != NULL)
   1635 					idmap_cache_add_sid2pid(
   1636 					    req_id->idmap_id_u.sid.prefix,
   1637 					    req_id->idmap_id_u.sid.rid,
   1638 					    res_id->idmap_id_u.gid, 0,
   1639 					    direction);
   1640 				else
   1641 					idmap_cache_add_sid2gid(
   1642 					    req_id->idmap_id_u.sid.prefix,
   1643 					    req_id->idmap_id_u.sid.rid,
   1644 					    res_id->idmap_id_u.gid,
   1645 					    direction);
   1646 			}
   1647 			break;
   1648 
   1649 		case IDMAP_POSIXID:
   1650 			if (gh->retlist[i].uid)
   1651 				*gh->retlist[i].uid = 60001;
   1652 			if (gh->retlist[i].is_user)
   1653 				*gh->retlist[i].is_user = -1;
   1654 			break;
   1655 
   1656 		case IDMAP_SID:
   1657 		case IDMAP_USID:
   1658 		case IDMAP_GSID:
   1659 			if (gh->retlist[i].rid)
   1660 				*gh->retlist[i].rid =
   1661 				    res_id->idmap_id_u.sid.rid;
   1662 			if (gh->retlist[i].sidprefix) {
   1663 				if (res_id->idmap_id_u.sid.prefix == NULL ||
   1664 				    *res_id->idmap_id_u.sid.prefix == '\0') {
   1665 					*gh->retlist[i].sidprefix = NULL;
   1666 					break;
   1667 				}
   1668 				*gh->retlist[i].sidprefix =
   1669 				    strdup(res_id->idmap_id_u.sid.prefix);
   1670 				if (*gh->retlist[i].sidprefix == NULL)
   1671 					*gh->retlist[i].stat =
   1672 					    IDMAP_ERR_MEMORY;
   1673 			}
   1674 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
   1675 			    gh->retlist[i].cache_res) {
   1676 				if (req_id->idtype == IDMAP_UID)
   1677 					idmap_cache_add_sid2uid(
   1678 					    res_id->idmap_id_u.sid.prefix,
   1679 					    res_id->idmap_id_u.sid.rid,
   1680 					    req_id->idmap_id_u.uid,
   1681 					    direction);
   1682 				else /* req_id->idtype == IDMAP_GID */
   1683 					idmap_cache_add_sid2gid(
   1684 					    res_id->idmap_id_u.sid.prefix,
   1685 					    res_id->idmap_id_u.sid.rid,
   1686 					    req_id->idmap_id_u.gid,
   1687 					    direction);
   1688 			}
   1689 			break;
   1690 
   1691 		case IDMAP_NONE:
   1692 			break;
   1693 
   1694 		default:
   1695 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
   1696 			break;
   1697 		}
   1698 		if (gh->retlist[i].info != NULL)
   1699 			(void) idmap_info_cpy(gh->retlist[i].info,
   1700 			    &res.ids.ids_val[i].info);
   1701 	}
   1702 	retcode = IDMAP_SUCCESS;
   1703 
   1704 out:
   1705 	_IDMAP_RESET_GET_HANDLE(gh);
   1706 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
   1707 	errno = idmap_stat2errno(retcode);
   1708 	return (retcode);
   1709 }
   1710 
   1711 
   1712 /*
   1713  * Destroy the "get mapping" handle
   1714  */
   1715 void
   1716 idmap_get_destroy(idmap_get_handle_t *gh)
   1717 {
   1718 	if (gh == NULL)
   1719 		return;
   1720 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
   1721 	if (gh->retlist)
   1722 		free(gh->retlist);
   1723 	free(gh);
   1724 }
   1725 
   1726 
   1727 /*
   1728  * Get windows to unix mapping
   1729  */
   1730 idmap_stat
   1731 idmap_get_w2u_mapping(idmap_handle_t *handle,
   1732 		const char *sidprefix, idmap_rid_t *rid,
   1733 		const char *winname, const char *windomain,
   1734 		int flag, int *is_user, int *is_wuser,
   1735 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
   1736 {
   1737 	CLIENT			*clnt;
   1738 	enum clnt_stat		clntstat;
   1739 	idmap_mapping		request, *mapping;
   1740 	idmap_mappings_res	result;
   1741 	idmap_retcode		retcode, rc;
   1742 
   1743 	if (handle == NULL) {
   1744 		errno = EINVAL;
   1745 		return (IDMAP_ERR_ARG);
   1746 	}
   1747 
   1748 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
   1749 
   1750 	(void) memset(&request, 0, sizeof (request));
   1751 	(void) memset(&result, 0, sizeof (result));
   1752 
   1753 	if (pid)
   1754 		*pid = UINT32_MAX;
   1755 	if (unixname)
   1756 		*unixname = NULL;
   1757 	if (direction)
   1758 		*direction = IDMAP_DIRECTION_UNDEF;
   1759 
   1760 	request.flag = flag;
   1761 	request.id1.idtype = IDMAP_SID;
   1762 	if (sidprefix && rid) {
   1763 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
   1764 		request.id1.idmap_id_u.sid.rid = *rid;
   1765 	} else if (winname) {
   1766 		retcode = idmap_strdupnull(&request.id1name, winname);
   1767 		if (retcode != IDMAP_SUCCESS)
   1768 			goto out;
   1769 
   1770 		retcode = idmap_strdupnull(&request.id1domain, windomain);
   1771 		if (retcode != IDMAP_SUCCESS)
   1772 			goto out;
   1773 
   1774 		request.id1.idmap_id_u.sid.prefix = NULL;
   1775 	} else {
   1776 		errno = EINVAL;
   1777 		return (IDMAP_ERR_ARG);
   1778 	}
   1779 
   1780 	if (*is_user == 1)
   1781 		request.id2.idtype = IDMAP_UID;
   1782 	else if (*is_user == 0)
   1783 		request.id2.idtype = IDMAP_GID;
   1784 	else
   1785 		request.id2.idtype = IDMAP_POSIXID;
   1786 
   1787 	if (*is_wuser == 1)
   1788 		request.id1.idtype = IDMAP_USID;
   1789 	else if (*is_wuser == 0)
   1790 		request.id1.idtype = IDMAP_GSID;
   1791 	else
   1792 		request.id1.idtype = IDMAP_SID;
   1793 
   1794 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
   1795 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
   1796 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
   1797 	    TIMEOUT);
   1798 
   1799 	if (clntstat != RPC_SUCCESS)
   1800 		return (_idmap_rpc2stat(clnt));
   1801 
   1802 	retcode = result.retcode;
   1803 
   1804 	if ((mapping = result.mappings.mappings_val) == NULL) {
   1805 		if (retcode == IDMAP_SUCCESS)
   1806 			retcode = IDMAP_ERR_NORESULT;
   1807 		goto out;
   1808 	}
   1809 
   1810 	if (mapping->id2.idtype == IDMAP_UID) {
   1811 		*is_user = 1;
   1812 	} else if (mapping->id2.idtype == IDMAP_GID) {
   1813 		*is_user = 0;
   1814 	} else {
   1815 		goto out;
   1816 	}
   1817 
   1818 	if (mapping->id1.idtype == IDMAP_USID) {
   1819 		*is_wuser = 1;
   1820 	} else if (mapping->id1.idtype == IDMAP_GSID) {
   1821 		*is_wuser = 0;
   1822 	} else {
   1823 		goto out;
   1824 	}
   1825 
   1826 	if (direction)
   1827 		*direction = mapping->direction;
   1828 	if (pid)
   1829 		*pid = mapping->id2.idmap_id_u.uid;
   1830 
   1831 	rc = idmap_strdupnull(unixname, mapping->id2name);
   1832 	if (rc != IDMAP_SUCCESS)
   1833 		retcode = rc;
   1834 
   1835 	rc = idmap_info_cpy(info, &mapping->info);
   1836 	if (rc != IDMAP_SUCCESS)
   1837 		retcode = rc;
   1838 
   1839 out:
   1840 	if (request.id1name != NULL)
   1841 		free(request.id1name);
   1842 	if (request.id1domain != NULL)
   1843 		free(request.id1domain);
   1844 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
   1845 	if (retcode != IDMAP_SUCCESS)
   1846 		errno = idmap_stat2errno(retcode);
   1847 	return (retcode);
   1848 }
   1849 
   1850 
   1851 /*
   1852  * Get unix to windows mapping
   1853  */
   1854 idmap_stat
   1855 idmap_get_u2w_mapping(idmap_handle_t *handle,
   1856 		uid_t *pid, const char *unixname,
   1857 		int flag, int is_user, int *is_wuser,
   1858 		char **sidprefix, idmap_rid_t *rid,
   1859 		char **winname, char **windomain,
   1860 		int *direction, idmap_info *info)
   1861 {
   1862 	CLIENT			*clnt;
   1863 	enum clnt_stat		clntstat;
   1864 	idmap_mapping		request, *mapping;
   1865 	idmap_mappings_res	result;
   1866 	idmap_retcode		retcode, rc;
   1867 
   1868 	if (handle == NULL) {
   1869 		errno = EINVAL;
   1870 		return (IDMAP_ERR_ARG);
   1871 	}
   1872 
   1873 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
   1874 
   1875 	if (sidprefix)
   1876 		*sidprefix = NULL;
   1877 	if (winname)
   1878 		*winname = NULL;
   1879 	if (windomain)
   1880 		*windomain = NULL;
   1881 	if (rid)
   1882 		*rid = UINT32_MAX;
   1883 	if (direction)
   1884 		*direction = IDMAP_DIRECTION_UNDEF;
   1885 
   1886 	(void) memset(&request, 0, sizeof (request));
   1887 	(void) memset(&result, 0, sizeof (result));
   1888 
   1889 	request.flag = flag;
   1890 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
   1891 
   1892 	if (pid && *pid != UINT32_MAX) {
   1893 		request.id1.idmap_id_u.uid = *pid;
   1894 	} else if (unixname) {
   1895 		request.id1name = (char *)unixname;
   1896 		request.id1.idmap_id_u.uid = UINT32_MAX;
   1897 	} else {
   1898 		errno = EINVAL;
   1899 		return (IDMAP_ERR_ARG);
   1900 	}
   1901 
   1902 	if (is_wuser == NULL)
   1903 		request.id2.idtype = IDMAP_SID;
   1904 	else if (*is_wuser == -1)
   1905 		request.id2.idtype = IDMAP_SID;
   1906 	else if (*is_wuser == 0)
   1907 		request.id2.idtype = IDMAP_GSID;
   1908 	else if (*is_wuser == 1)
   1909 		request.id2.idtype = IDMAP_USID;
   1910 
   1911 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
   1912 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
   1913 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
   1914 	    TIMEOUT);
   1915 
   1916 	if (clntstat != RPC_SUCCESS)
   1917 		return (_idmap_rpc2stat(clnt));
   1918 
   1919 	retcode = result.retcode;
   1920 
   1921 	if ((mapping = result.mappings.mappings_val) == NULL) {
   1922 		if (retcode == IDMAP_SUCCESS)
   1923 			retcode = IDMAP_ERR_NORESULT;
   1924 		goto out;
   1925 	}
   1926 
   1927 	if (direction != NULL)
   1928 		*direction = mapping->direction;
   1929 
   1930 	if (is_wuser != NULL) {
   1931 		if (mapping->id2.idtype == IDMAP_USID)
   1932 			*is_wuser = 1;
   1933 		else if (mapping->id2.idtype == IDMAP_GSID)
   1934 			*is_wuser = 0;
   1935 		else
   1936 			*is_wuser = -1;
   1937 	}
   1938 
   1939 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
   1940 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
   1941 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
   1942 		if (*sidprefix == NULL) {
   1943 			retcode = IDMAP_ERR_MEMORY;
   1944 			goto errout;
   1945 		}
   1946 	}
   1947 	if (rid)
   1948 		*rid = mapping->id2.idmap_id_u.sid.rid;
   1949 
   1950 	rc = idmap_strdupnull(winname, mapping->id2name);
   1951 	if (rc != IDMAP_SUCCESS)
   1952 		retcode = rc;
   1953 
   1954 	rc = idmap_strdupnull(windomain, mapping->id2domain);
   1955 	if (rc != IDMAP_SUCCESS)
   1956 		retcode = rc;
   1957 
   1958 	rc = idmap_info_cpy(info, &mapping->info);
   1959 	if (rc != IDMAP_SUCCESS)
   1960 		retcode = rc;
   1961 
   1962 	goto out;
   1963 
   1964 errout:
   1965 	if (sidprefix && *sidprefix) {
   1966 		free(*sidprefix);
   1967 		*sidprefix = NULL;
   1968 	}
   1969 	if (winname && *winname) {
   1970 		free(*winname);
   1971 		*winname = NULL;
   1972 	}
   1973 	if (windomain && *windomain) {
   1974 		free(*windomain);
   1975 		*windomain = NULL;
   1976 	}
   1977 
   1978 out:
   1979 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
   1980 	if (retcode != IDMAP_SUCCESS)
   1981 		errno = idmap_stat2errno(retcode);
   1982 	return (retcode);
   1983 }
   1984 
   1985 
   1986 
   1987 #define	gettext(s)	s
   1988 static stat_table_t stattable[] = {
   1989 	{IDMAP_SUCCESS, gettext("Success"), 0},
   1990 	{IDMAP_NEXT, gettext("More results available"), 0},
   1991 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
   1992 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
   1993 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
   1994 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
   1995 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
   1996 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
   1997 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
   1998 	{IDMAP_ERR_W2U_NAMERULE,
   1999 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
   2000 	{IDMAP_ERR_U2W_NAMERULE,
   2001 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
   2002 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
   2003 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
   2004 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
   2005 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
   2006 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
   2007 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
   2008 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
   2009 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
   2010 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
   2011 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
   2012 	{IDMAP_ERR_NOMAPPING,
   2013 		gettext("Mapping not found or inhibited"), EINVAL},
   2014 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
   2015 		gettext("New mapping needs to be created"), EINVAL},
   2016 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
   2017 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
   2018 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
   2019 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
   2020 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
   2021 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
   2022 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
   2023 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
   2024 		gettext("No mapping for well-known SID"), EINVAL},
   2025 	{IDMAP_ERR_RETRIABLE_NET_ERR,
   2026 		gettext("Windows lookup failed"), EINVAL},
   2027 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
   2028 		gettext("Duplicate rule or conflicts with an existing "
   2029 		"Windows to UNIX name-based rule"), EINVAL},
   2030 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
   2031 		gettext("Duplicate rule or conflicts with an existing "
   2032 		"Unix to Windows name-based rule"), EINVAL},
   2033 	{IDMAP_ERR_BAD_UTF8,
   2034 		gettext("Invalid or illegal UTF-8 sequence found in "
   2035 		"a given Windows entity name or domain name"), EINVAL},
   2036 	{IDMAP_ERR_NONE_GENERATED,
   2037 		gettext("Mapping not found and none created (see -c option)"),
   2038 		EINVAL},
   2039 	{IDMAP_ERR_PROP_UNKNOWN,
   2040 		gettext("Undefined property"),
   2041 		EINVAL},
   2042 	{IDMAP_ERR_NS_LDAP_CFG,
   2043 		gettext("Native LDAP configuration error"), EINVAL},
   2044 	{IDMAP_ERR_NS_LDAP_PARTIAL,
   2045 		gettext("Partial result from Native LDAP"), EINVAL},
   2046 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
   2047 		gettext("Native LDAP operation failed"), EINVAL},
   2048 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
   2049 		gettext("Improper winname form found in Native LDAP"), EINVAL},
   2050 	{IDMAP_ERR_NO_ACTIVEDIRECTORY,
   2051 		gettext("No AD servers"),
   2052 		EINVAL},
   2053 	{-1, NULL, 0}
   2054 };
   2055 #undef	gettext
   2056 
   2057 
   2058 /*
   2059  * Get description of status code
   2060  *
   2061  * Input:
   2062  * status - Status code returned by libidmap API call
   2063  *
   2064  * Return Value:
   2065  * human-readable localized description of idmap_stat
   2066  */
   2067 /* ARGSUSED */
   2068 const char *
   2069 idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
   2070 {
   2071 	int i;
   2072 
   2073 	for (i = 0; stattable[i].msg; i++) {
   2074 		if (stattable[i].retcode == status)
   2075 			return (dgettext(TEXT_DOMAIN, stattable[i].msg));
   2076 	}
   2077 	return (dgettext(TEXT_DOMAIN, "Unknown error"));
   2078 }
   2079 
   2080 
   2081 static int
   2082 idmap_stat2errno(idmap_stat stat)
   2083 {
   2084 	int i;
   2085 	for (i = 0; stattable[i].msg; i++) {
   2086 		if (stattable[i].retcode == stat)
   2087 			return (stattable[i].errnum);
   2088 	}
   2089 	return (EINVAL);
   2090 }
   2091 
   2092 
   2093 /*
   2094  * Get status code from string
   2095  */
   2096 idmap_stat
   2097 idmap_string2stat(const char *str)
   2098 {
   2099 	if (str == NULL)
   2100 		return (IDMAP_ERR_INTERNAL);
   2101 
   2102 #define	return_cmp(a) \
   2103 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
   2104 		return (IDMAP_ERR_ ## a);
   2105 
   2106 	return_cmp(OTHER);
   2107 	return_cmp(INTERNAL);
   2108 	return_cmp(MEMORY);
   2109 	return_cmp(NORESULT);
   2110 	return_cmp(NOTUSER);
   2111 	return_cmp(NOTGROUP);
   2112 	return_cmp(NOTSUPPORTED);
   2113 	return_cmp(W2U_NAMERULE);
   2114 	return_cmp(U2W_NAMERULE);
   2115 	return_cmp(CACHE);
   2116 	return_cmp(DB);
   2117 	return_cmp(ARG);
   2118 	return_cmp(SID);
   2119 	return_cmp(IDTYPE);
   2120 	return_cmp(RPC_HANDLE);
   2121 	return_cmp(RPC);
   2122 	return_cmp(CLIENT_HANDLE);
   2123 	return_cmp(BUSY);
   2124 	return_cmp(PERMISSION_DENIED);
   2125 	return_cmp(NOMAPPING);
   2126 	return_cmp(NEW_ID_ALLOC_REQD);
   2127 	return_cmp(DOMAIN);
   2128 	return_cmp(SECURITY);
   2129 	return_cmp(NOTFOUND);
   2130 	return_cmp(DOMAIN_NOTFOUND);
   2131 	return_cmp(MEMORY);
   2132 	return_cmp(UPDATE_NOTALLOWED);
   2133 	return_cmp(CFG);
   2134 	return_cmp(CFG_CHANGE);
   2135 	return_cmp(NOTMAPPED_WELLKNOWN);
   2136 	return_cmp(RETRIABLE_NET_ERR);
   2137 	return_cmp(W2U_NAMERULE_CONFLICT);
   2138 	return_cmp(U2W_NAMERULE_CONFLICT);
   2139 	return_cmp(BAD_UTF8);
   2140 	return_cmp(NONE_GENERATED);
   2141 	return_cmp(PROP_UNKNOWN);
   2142 	return_cmp(NS_LDAP_CFG);
   2143 	return_cmp(NS_LDAP_PARTIAL);
   2144 	return_cmp(NS_LDAP_OP_FAILED);
   2145 	return_cmp(NS_LDAP_BAD_WINNAME);
   2146 	return_cmp(NO_ACTIVEDIRECTORY);
   2147 #undef return_cmp
   2148 
   2149 	return (IDMAP_ERR_OTHER);
   2150 }
   2151 
   2152 
   2153 /*
   2154  * Map the given status to one that can be returned by the protocol
   2155  */
   2156 idmap_stat
   2157 idmap_stat4prot(idmap_stat status)
   2158 {
   2159 	switch (status) {
   2160 	case IDMAP_ERR_MEMORY:
   2161 	case IDMAP_ERR_CACHE:
   2162 		return (IDMAP_ERR_INTERNAL);
   2163 	}
   2164 	return (status);
   2165 }
   2166 
   2167 
   2168 /*
   2169  * This is a convenience routine which duplicates a string after
   2170  * checking for NULL pointers. This function will return success if
   2171  * either the 'to' OR 'from' pointers are NULL.
   2172  */
   2173 static idmap_stat
   2174 idmap_strdupnull(char **to, const char *from)
   2175 {
   2176 	if (to == NULL)
   2177 		return (IDMAP_SUCCESS);
   2178 
   2179 	if (from == NULL || *from == '\0') {
   2180 		*to = NULL;
   2181 		return (IDMAP_SUCCESS);
   2182 	}
   2183 
   2184 	*to = strdup(from);
   2185 	if (*to == NULL)
   2186 		return (IDMAP_ERR_MEMORY);
   2187 	return (IDMAP_SUCCESS);
   2188 }
   2189 
   2190 
   2191 idmap_stat
   2192 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
   2193 {
   2194 	idmap_stat retval;
   2195 
   2196 	if (to == NULL)
   2197 		return (IDMAP_SUCCESS);
   2198 
   2199 	(void) memcpy(to, from, sizeof (idmap_namerule));
   2200 	to->windomain = NULL;
   2201 	to->winname = NULL;
   2202 	to->unixname = NULL;
   2203 
   2204 	retval = idmap_strdupnull(&to->windomain, from->windomain);
   2205 	if (retval != IDMAP_SUCCESS)
   2206 		return (retval);
   2207 
   2208 	retval = idmap_strdupnull(&to->winname, from->winname);
   2209 	if (retval != IDMAP_SUCCESS) {
   2210 		free(to->windomain);
   2211 		to->windomain = NULL;
   2212 		return (retval);
   2213 	}
   2214 
   2215 	retval = idmap_strdupnull(&to->unixname, from->unixname);
   2216 	if (retval != IDMAP_SUCCESS) {
   2217 		free(to->windomain);
   2218 		to->windomain = NULL;
   2219 		free(to->winname);
   2220 		to->winname = NULL;
   2221 		return (retval);
   2222 	}
   2223 
   2224 	return (retval);
   2225 }
   2226 
   2227 
   2228 static
   2229 idmap_stat
   2230 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
   2231 {
   2232 	idmap_stat retval;
   2233 
   2234 	if (to == NULL)
   2235 		return (IDMAP_SUCCESS);
   2236 
   2237 	retval = idmap_strdupnull(&to->dn, from->dn);
   2238 	if (retval != IDMAP_SUCCESS)
   2239 		return (retval);
   2240 
   2241 	retval = idmap_strdupnull(&to->attr, from->attr);
   2242 	if (retval != IDMAP_SUCCESS) {
   2243 		free(to->dn);
   2244 		to->dn = NULL;
   2245 		return (retval);
   2246 	}
   2247 
   2248 	retval = idmap_strdupnull(&to->value, from->value);
   2249 	if (retval != IDMAP_SUCCESS) {
   2250 		free(to->dn);
   2251 		to->dn = NULL;
   2252 		free(to->attr);
   2253 		to->attr = NULL;
   2254 		return (retval);
   2255 	}
   2256 
   2257 	return (retval);
   2258 }
   2259 
   2260 idmap_stat
   2261 idmap_info_cpy(idmap_info *to, idmap_info *from)
   2262 {
   2263 	idmap_stat retval = IDMAP_SUCCESS;
   2264 
   2265 	if (to == NULL)
   2266 		return (IDMAP_SUCCESS);
   2267 
   2268 	(void) memset(to, 0, sizeof (idmap_info));
   2269 
   2270 	to->src = from->src;
   2271 	to->how.map_type = from->how.map_type;
   2272 	switch (to->how.map_type) {
   2273 	case IDMAP_MAP_TYPE_DS_AD:
   2274 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
   2275 		    &from->how.idmap_how_u.ad);
   2276 		break;
   2277 
   2278 	case IDMAP_MAP_TYPE_DS_NLDAP:
   2279 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
   2280 		    &from->how.idmap_how_u.nldap);
   2281 		break;
   2282 
   2283 	case IDMAP_MAP_TYPE_RULE_BASED:
   2284 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
   2285 		    &from->how.idmap_how_u.rule);
   2286 		break;
   2287 
   2288 	case IDMAP_MAP_TYPE_EPHEMERAL:
   2289 		break;
   2290 
   2291 	case IDMAP_MAP_TYPE_LOCAL_SID:
   2292 		break;
   2293 
   2294 	case IDMAP_MAP_TYPE_KNOWN_SID:
   2295 		break;
   2296 
   2297 	case IDMAP_MAP_TYPE_IDMU:
   2298 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.idmu,
   2299 		    &from->how.idmap_how_u.idmu);
   2300 		break;
   2301 	}
   2302 	return (retval);
   2303 }
   2304 
   2305 
   2306 /*
   2307  * This routine is similar to idmap_info_cpy, but the strings
   2308  * are moved from the "from" info to the "to" info.
   2309  * This routine is equivalent to:
   2310  *
   2311  *	idmap_info_cpy(to,from);
   2312  *	idmap_info_free(from);
   2313  */
   2314 idmap_stat
   2315 idmap_info_mov(idmap_info *to, idmap_info *from)
   2316 {
   2317 	idmap_stat retval = IDMAP_SUCCESS;
   2318 
   2319 	if (to == NULL) {
   2320 		idmap_info_free(from);
   2321 		return (IDMAP_SUCCESS);
   2322 	}
   2323 	(void) memcpy(to, from, sizeof (idmap_info));
   2324 
   2325 	(void) memset(from, 0, sizeof (idmap_info));
   2326 
   2327 	return (retval);
   2328 }
   2329 
   2330 
   2331 void
   2332 idmap_info_free(idmap_info *info)
   2333 {
   2334 	idmap_how *how;
   2335 
   2336 	if (info == NULL)
   2337 		return;
   2338 
   2339 	how = &info->how;
   2340 	switch (how->map_type) {
   2341 	case IDMAP_MAP_TYPE_DS_AD:
   2342 		free(how->idmap_how_u.ad.dn);
   2343 		how->idmap_how_u.ad.dn = NULL;
   2344 		free(how->idmap_how_u.ad.attr);
   2345 		how->idmap_how_u.ad.attr = NULL;
   2346 		free(how->idmap_how_u.ad.value);
   2347 		how->idmap_how_u.ad.value = NULL;
   2348 		break;
   2349 
   2350 	case IDMAP_MAP_TYPE_DS_NLDAP:
   2351 		free(how->idmap_how_u.nldap.dn);
   2352 		how->idmap_how_u.nldap.dn = NULL;
   2353 		free(how->idmap_how_u.nldap.attr);
   2354 		how->idmap_how_u.nldap.attr = NULL;
   2355 		free(how->idmap_how_u.nldap.value);
   2356 		how->idmap_how_u.nldap.value = NULL;
   2357 		break;
   2358 
   2359 	case IDMAP_MAP_TYPE_RULE_BASED:
   2360 		free(how->idmap_how_u.rule.windomain);
   2361 		how->idmap_how_u.rule.windomain = NULL;
   2362 		free(how->idmap_how_u.rule.winname);
   2363 		how->idmap_how_u.rule.winname = NULL;
   2364 		free(how->idmap_how_u.rule.unixname);
   2365 		how->idmap_how_u.rule.unixname = NULL;
   2366 		break;
   2367 
   2368 	case IDMAP_MAP_TYPE_EPHEMERAL:
   2369 		break;
   2370 
   2371 	case IDMAP_MAP_TYPE_LOCAL_SID:
   2372 		break;
   2373 
   2374 	case IDMAP_MAP_TYPE_IDMU:
   2375 		free(how->idmap_how_u.idmu.dn);
   2376 		how->idmap_how_u.idmu.dn = NULL;
   2377 		free(how->idmap_how_u.idmu.attr);
   2378 		how->idmap_how_u.idmu.attr = NULL;
   2379 		free(how->idmap_how_u.idmu.value);
   2380 		how->idmap_how_u.idmu.value = NULL;
   2381 		break;
   2382 	}
   2383 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
   2384 	info->src = IDMAP_MAP_SRC_UNKNOWN;
   2385 }
   2386 
   2387 
   2388 /*
   2389  * Get uid given Windows name
   2390  */
   2391 idmap_stat
   2392 idmap_getuidbywinname(const char *name, const char *domain, int flag,
   2393 	uid_t *uid)
   2394 {
   2395 	idmap_handle_t	*ih;
   2396 	idmap_retcode	rc;
   2397 	int		is_user = 1;
   2398 	int		is_wuser = -1;
   2399 	int 		direction;
   2400 
   2401 	if (uid == NULL)
   2402 		return (IDMAP_ERR_ARG);
   2403 
   2404 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
   2405 		rc = idmap_cache_lookup_uidbywinname(name, domain, uid);
   2406 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
   2407 			return (rc);
   2408 	}
   2409 	/* Get mapping */
   2410 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
   2411 		return (rc);
   2412 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
   2413 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
   2414 	(void) idmap_fini(ih);
   2415 
   2416 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
   2417 		/* If we have not got the domain don't store UID to winname */
   2418 		if (domain == NULL)
   2419 			direction = IDMAP_DIRECTION_W2U;
   2420 		idmap_cache_add_winname2uid(name, domain, *uid, direction);
   2421 	}
   2422 
   2423 	return (rc);
   2424 }
   2425 
   2426 
   2427 /*
   2428  * Get gid given Windows name
   2429  */
   2430 idmap_stat
   2431 idmap_getgidbywinname(const char *name, const char *domain, int flag,
   2432 	gid_t *gid)
   2433 {
   2434 	idmap_handle_t	*ih;
   2435 	idmap_retcode	rc;
   2436 	int		is_user = 0;
   2437 	int		is_wuser = -1;
   2438 	int		direction;
   2439 
   2440 	if (gid == NULL)
   2441 		return (IDMAP_ERR_ARG);
   2442 
   2443 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
   2444 		rc = idmap_cache_lookup_gidbywinname(name, domain, gid);
   2445 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
   2446 			return (rc);
   2447 	}
   2448 
   2449 	/* Get mapping */
   2450 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
   2451 		return (rc);
   2452 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
   2453 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
   2454 	(void) idmap_fini(ih);
   2455 
   2456 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
   2457 		/* If we have not got the domain don't store GID to winname */
   2458 		if (domain == NULL)
   2459 			direction = IDMAP_DIRECTION_W2U;
   2460 		idmap_cache_add_winname2gid(name, domain, *gid, direction);
   2461 	}
   2462 
   2463 	return (rc);
   2464 }
   2465 
   2466 
   2467 /*
   2468  * Get winname given pid
   2469  */
   2470 static idmap_retcode
   2471 idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
   2472 	char **domain)
   2473 {
   2474 	idmap_handle_t	*ih;
   2475 	idmap_retcode	rc;
   2476 	int		len;
   2477 	char		*winname, *windomain;
   2478 	int		direction;
   2479 
   2480 	if (name == NULL)
   2481 		return (IDMAP_ERR_ARG);
   2482 
   2483 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
   2484 		if (is_user)
   2485 			rc = idmap_cache_lookup_winnamebyuid(&winname,
   2486 			    &windomain, pid);
   2487 		else
   2488 			rc = idmap_cache_lookup_winnamebygid(&winname,
   2489 			    &windomain, pid);
   2490 		if (rc == IDMAP_SUCCESS)
   2491 			goto out;
   2492 		if (rc == IDMAP_ERR_MEMORY)
   2493 			return (rc);
   2494 	}
   2495 
   2496 	/* Get mapping */
   2497 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
   2498 		return (rc);
   2499 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
   2500 	    NULL, NULL, &winname, &windomain, &direction, NULL);
   2501 	(void) idmap_fini(ih);
   2502 
   2503 	/* Return on error */
   2504 	if (rc != IDMAP_SUCCESS)
   2505 		return (rc);
   2506 
   2507 	/*
   2508 	 * The given PID may have been mapped to a locally
   2509 	 * generated SID in which case there isn't any
   2510 	 * Windows name
   2511 	 */
   2512 	if (winname == NULL || windomain == NULL) {
   2513 		idmap_free(winname);
   2514 		idmap_free(windomain);
   2515 		return (IDMAP_ERR_NORESULT);
   2516 	}
   2517 
   2518 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
   2519 		if (is_user)
   2520 			idmap_cache_add_winname2uid(winname, windomain,
   2521 			    pid, direction);
   2522 		else
   2523 			idmap_cache_add_winname2gid(winname, windomain,
   2524 			    pid, direction);
   2525 	}
   2526 
   2527 out:
   2528 	if (domain != NULL) {
   2529 		*name = winname;
   2530 		*domain = windomain;
   2531 	} else {
   2532 		len = strlen(winname) + strlen(windomain) + 2;
   2533 		if ((*name = malloc(len)) != NULL)
   2534 			(void) snprintf(*name, len, "%s@%s", winname,
   2535 			    windomain);
   2536 		else
   2537 			rc = IDMAP_ERR_MEMORY;
   2538 		idmap_free(winname);
   2539 		idmap_free(windomain);
   2540 	}
   2541 
   2542 	return (rc);
   2543 }
   2544 
   2545 
   2546 /*
   2547  * Get winname given uid
   2548  */
   2549 idmap_stat
   2550 idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain)
   2551 {
   2552 	return (idmap_getwinnamebypid(uid, 1, flag, name, domain));
   2553 }
   2554 
   2555 
   2556 /*
   2557  * Get winname given gid
   2558  */
   2559 idmap_stat
   2560 idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain)
   2561 {
   2562 	return (idmap_getwinnamebypid(gid, 0, flag, name, domain));
   2563 }
   2564