xref: /illumos-gate/usr/src/lib/libidmap/common/idmap_api.c (revision 3ee87bca47e74aa2719352485b80973ca6e079b7)
1c5c4113dSnw /*
2c5c4113dSnw  * CDDL HEADER START
3c5c4113dSnw  *
4c5c4113dSnw  * The contents of this file are subject to the terms of the
5c5c4113dSnw  * Common Development and Distribution License (the "License").
6c5c4113dSnw  * You may not use this file except in compliance with the License.
7c5c4113dSnw  *
8c5c4113dSnw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw  * See the License for the specific language governing permissions
11c5c4113dSnw  * and limitations under the License.
12c5c4113dSnw  *
13c5c4113dSnw  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw  *
19c5c4113dSnw  * CDDL HEADER END
20c5c4113dSnw  */
21c5c4113dSnw /*
220dcc7149Snw  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23c5c4113dSnw  * Use is subject to license terms.
24c5c4113dSnw  */
25c5c4113dSnw 
26c5c4113dSnw 
27c5c4113dSnw /*
28c5c4113dSnw  * libidmap API
29c5c4113dSnw  */
30c5c4113dSnw 
31c5c4113dSnw #include <stdlib.h>
32479ac375Sdm #include <sys/varargs.h>
33c5c4113dSnw #include <inttypes.h>
34c5c4113dSnw #include <errno.h>
35c5c4113dSnw #include <strings.h>
36c5c4113dSnw #include <ctype.h>
37c5c4113dSnw #include <sys/param.h>
38c5c4113dSnw #include <sys/types.h>
39c5c4113dSnw #include <sys/stat.h>
40c5c4113dSnw #include <dlfcn.h>
41c5c4113dSnw #include <libintl.h>
42d3a612caSnw #include <ucontext.h>
43c5c4113dSnw #include "idmap_impl.h"
44*3ee87bcaSJulian Pullen #include "idmap_cache.h"
45c5c4113dSnw 
46479ac375Sdm /*LINTLIBRARY*/
47479ac375Sdm 
48479ac375Sdm /*
49479ac375Sdm  * The following structure determines where the log messages from idmapdlog()
50479ac375Sdm  * go to. It can be stderr (idmap, idmapd -d) and/or syslog (idmapd).
51479ac375Sdm  *
52479ac375Sdm  * logstate.max_pri is integer cutoff necessary to silence low-priority
53479ac375Sdm  * messages to stderr. Syslog has its own means so there a boolean
54479ac375Sdm  * logstate.write_syslog is enough.
55479ac375Sdm  *
56479ac375Sdm  * logstate.degraded is a mode used by idmapd in its degraded state.
57479ac375Sdm  */
58479ac375Sdm 
59479ac375Sdm static struct {
60479ac375Sdm 	bool_t write_syslog;
61479ac375Sdm 	int max_pri; /* Max priority written to stderr */
62479ac375Sdm 	bool_t degraded;
63479ac375Sdm } logstate = {FALSE, LOG_DEBUG, FALSE};
64479ac375Sdm 
65479ac375Sdm 
66c5c4113dSnw static struct timeval TIMEOUT = { 25, 0 };
67c5c4113dSnw 
68c5c4113dSnw static int idmap_stat2errno(idmap_stat);
69479ac375Sdm static idmap_stat	idmap_strdupnull(char **, const char *);
70c5c4113dSnw 
71c5c4113dSnw #define	__ITER_CREATE(itera, argu, handl, ityp)\
72c5c4113dSnw 	if (handl == NULL) {\
73c5c4113dSnw 		errno = EINVAL;\
74c5c4113dSnw 		return (IDMAP_ERR_ARG);\
75c5c4113dSnw 	}\
76c5c4113dSnw 	itera = calloc(1, sizeof (*itera));\
77c5c4113dSnw 	if (itera == NULL) {\
78c5c4113dSnw 		errno = ENOMEM;\
79c5c4113dSnw 		return (IDMAP_ERR_MEMORY);\
80c5c4113dSnw 	}\
81c5c4113dSnw 	argu = calloc(1, sizeof (*argu));\
82c5c4113dSnw 	if (argu == NULL) {\
83c5c4113dSnw 		free(itera);\
84c5c4113dSnw 		errno = ENOMEM;\
85c5c4113dSnw 		return (IDMAP_ERR_MEMORY);\
86c5c4113dSnw 	}\
87c5c4113dSnw 	itera->ih = handl;\
88c5c4113dSnw 	itera->type = ityp;\
89c5c4113dSnw 	itera->retcode = IDMAP_NEXT;\
90c5c4113dSnw 	itera->limit = 1024;\
91c5c4113dSnw 	itera->arg = argu;
92c5c4113dSnw 
93c5c4113dSnw 
94c5c4113dSnw #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
95c5c4113dSnw 	if (argu) {\
96c5c4113dSnw 		xdr_free(xdr_argu, (caddr_t)argu);\
97c5c4113dSnw 		free(argu);\
98c5c4113dSnw 	}\
99c5c4113dSnw 	if (itera)\
100c5c4113dSnw 		free(itera);\
101c5c4113dSnw 	return (iretcod);
102c5c4113dSnw 
103c5c4113dSnw 
104c5c4113dSnw #define	__ITER_CHECK(itera, ityp)\
105c5c4113dSnw 	if (itera == NULL) {\
106c5c4113dSnw 		errno = EINVAL;\
107c5c4113dSnw 		return (IDMAP_ERR_ARG);\
108c5c4113dSnw 	}\
109c5c4113dSnw 	if (itera->type != ityp) {\
110c5c4113dSnw 		errno = EINVAL;\
111c5c4113dSnw 		return (IDMAP_ERR_ARG);\
112c5c4113dSnw 	}
113c5c4113dSnw 
114c5c4113dSnw /*
115c5c4113dSnw  * Free memory allocated by libidmap API
116c5c4113dSnw  *
117c5c4113dSnw  * Input:
118c5c4113dSnw  * ptr - memory to be freed
119c5c4113dSnw  */
120c5c4113dSnw void
121cd37da74Snw idmap_free(void *ptr)
122cd37da74Snw {
123c5c4113dSnw 	free(ptr);
124c5c4113dSnw }
125c5c4113dSnw 
126c5c4113dSnw 
127d3a612caSnw #define	MIN_STACK_NEEDS	16384
128d3a612caSnw 
129c5c4113dSnw /*
130c5c4113dSnw  * Create and Initialize idmap client handle for rpc/doors
131c5c4113dSnw  *
132c5c4113dSnw  * Output:
133c5c4113dSnw  * handle - idmap handle
134c5c4113dSnw  */
135c5c4113dSnw idmap_stat
136cd37da74Snw idmap_init(idmap_handle_t **handle)
137cd37da74Snw {
138c5c4113dSnw 	CLIENT			*clnt = NULL;
139c5c4113dSnw 	struct idmap_handle	*hptr;
140d3a612caSnw 	uint_t			sendsz = 0;
141d3a612caSnw 	stack_t			st;
142c5c4113dSnw 
143c5c4113dSnw 	*handle = NULL;
144c5c4113dSnw 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
145c5c4113dSnw 	if (hptr == NULL)
146c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
147c5c4113dSnw 
148d3a612caSnw 	/*
149d3a612caSnw 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
150d3a612caSnw 	 * the call args buffer and once for the call result buffer), so
151d3a612caSnw 	 * we want to pick a sendsz that will be large enough, but not
152d3a612caSnw 	 * too large.
153d3a612caSnw 	 */
154d3a612caSnw 	if (stack_getbounds(&st) == 0) {
155d3a612caSnw 		/*
156d3a612caSnw 		 * Estimate how much stack space is left;
157d3a612caSnw 		 * st.ss_sp is the top of stack.
158d3a612caSnw 		 */
159d3a612caSnw 		if ((char *)&sendsz < (char *)st.ss_sp)
160d3a612caSnw 			/* stack grows up */
161d3a612caSnw 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
162d3a612caSnw 		else
163d3a612caSnw 			/* stack grows down */
164d3a612caSnw 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
165d3a612caSnw 
166d3a612caSnw 		/*
167d3a612caSnw 		 * Take much of the stack space left, divided by two,
168d3a612caSnw 		 * but leave enough for our needs (just a guess!), and
169d3a612caSnw 		 * if we can't, then roll the dice.
170d3a612caSnw 		 */
171d3a612caSnw 		sendsz = RNDUP(sendsz / 2);
172d3a612caSnw 		if (sendsz < MIN_STACK_NEEDS)
173d3a612caSnw 			sendsz = 0;	/* RPC call may fail */
174d3a612caSnw 		else if (sendsz > IDMAP_MAX_DOOR_RPC)
175d3a612caSnw 			sendsz = IDMAP_MAX_DOOR_RPC;
176d3a612caSnw 	}
177d3a612caSnw 
178d3a612caSnw 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
179c5c4113dSnw 	if (clnt == NULL) {
180c5c4113dSnw 		free(hptr);
181c5c4113dSnw 		return (IDMAP_ERR_RPC);
182c5c4113dSnw 	}
183c5c4113dSnw 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
184c5c4113dSnw 	hptr->privhandle = clnt;
185c5c4113dSnw 	*handle = hptr;
186c5c4113dSnw 	return (IDMAP_SUCCESS);
187c5c4113dSnw }
188c5c4113dSnw 
189c5c4113dSnw 
190c5c4113dSnw /*
191c5c4113dSnw  * Finalize idmap handle
192c5c4113dSnw  *
193c5c4113dSnw  * Input:
194c5c4113dSnw  * handle - idmap handle
195c5c4113dSnw  */
196c5c4113dSnw idmap_stat
197cd37da74Snw idmap_fini(idmap_handle_t *handle)
198cd37da74Snw {
199c5c4113dSnw 	CLIENT			*clnt;
200c5c4113dSnw 	struct idmap_handle	*hptr;
201c5c4113dSnw 
202c5c4113dSnw 	if (handle == NULL)
203c5c4113dSnw 		return (IDMAP_SUCCESS);
204c5c4113dSnw 
205c5c4113dSnw 	hptr = (struct idmap_handle *)handle;
206c5c4113dSnw 
207c5c4113dSnw 	switch (hptr->type) {
208c5c4113dSnw 	case _IDMAP_HANDLE_RPC_DOORS:
209c5c4113dSnw 		clnt = (CLIENT *)hptr->privhandle;
210c5c4113dSnw 		if (clnt) {
211c5c4113dSnw 			if (clnt->cl_auth)
212c5c4113dSnw 				auth_destroy(clnt->cl_auth);
213c5c4113dSnw 			clnt_destroy(clnt);
214c5c4113dSnw 		}
215c5c4113dSnw 		break;
216c5c4113dSnw 	default:
217c5c4113dSnw 		break;
218c5c4113dSnw 	}
219c5c4113dSnw 	free(hptr);
220c5c4113dSnw 	return (IDMAP_SUCCESS);
221c5c4113dSnw }
222c5c4113dSnw 
223c5c4113dSnw 
224479ac375Sdm idmap_stat
225479ac375Sdm idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
226479ac375Sdm {
227479ac375Sdm 	CLIENT			*clnt;
228479ac375Sdm 	enum clnt_stat		clntstat;
229479ac375Sdm 
230479ac375Sdm 
231479ac375Sdm 	(void) memset(res, 0, sizeof (*res));
232479ac375Sdm 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
233479ac375Sdm 
234479ac375Sdm 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
235479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
236479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
237479ac375Sdm 
238479ac375Sdm 	if (clntstat != RPC_SUCCESS) {
239479ac375Sdm 		return (_idmap_rpc2stat(clnt));
240479ac375Sdm 	}
241479ac375Sdm 
242479ac375Sdm 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
243479ac375Sdm 
244479ac375Sdm #if 0
245479ac375Sdm 	(void) memset(&res, 0, sizeof (res));
246479ac375Sdm 	pr = PROP_DOMAIN_CONTROLLER;
247479ac375Sdm 
248479ac375Sdm 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
249479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
250479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)&res, TIMEOUT);
251479ac375Sdm 
252479ac375Sdm 	if (clntstat != RPC_SUCCESS) {
253479ac375Sdm 		fprintf(stderr, "clntstat != RPC_SUCCESS\n");
254479ac375Sdm 		rc = _idmap_rpc2stat(clnt);
255479ac375Sdm 		goto cleanup;
256479ac375Sdm 	}
257479ac375Sdm #endif
258479ac375Sdm 
259479ac375Sdm }
260479ac375Sdm 
261479ac375Sdm idmap_stat
262479ac375Sdm idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
263479ac375Sdm     idmap_ad_disc_ds_t *dc)
264479ac375Sdm {
265479ac375Sdm 	idmap_prop_res res;
266479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
267479ac375Sdm 
268479ac375Sdm 	rc = idmap_get_prop(handle, pr, &res);
269479ac375Sdm 	if (rc < 0)
270479ac375Sdm 		return (rc);
271479ac375Sdm 
272479ac375Sdm 	dc->port = res.value.idmap_prop_val_u.dsval.port;
273479ac375Sdm 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
274479ac375Sdm 	    AD_DISC_MAXHOSTNAME);
275479ac375Sdm 
276479ac375Sdm 	/* xdr doesn't guarantee 0-termination of char[]: */
277479ac375Sdm 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
278479ac375Sdm 
279479ac375Sdm 	return (rc);
280479ac375Sdm }
281479ac375Sdm 
282479ac375Sdm 
283479ac375Sdm /*
284479ac375Sdm  * Sometimes the property is not set. In that case, str is set to NULL but
285479ac375Sdm  * otherwise IDMAP_SUCCESS is returned.
286479ac375Sdm  */
287479ac375Sdm idmap_stat
288479ac375Sdm idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
289479ac375Sdm {
290479ac375Sdm 	idmap_prop_res res;
291479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
292479ac375Sdm 
293479ac375Sdm 	rc = idmap_get_prop(handle, pr, &res);
294479ac375Sdm 	if (rc < 0)
295479ac375Sdm 		return (rc);
296479ac375Sdm 
297479ac375Sdm 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
298479ac375Sdm 	return (rc);
299479ac375Sdm }
300c5c4113dSnw 
301c5c4113dSnw /*
302c5c4113dSnw  * Create/Initialize handle for updates
303c5c4113dSnw  *
304c5c4113dSnw  * Output:
305c5c4113dSnw  * udthandle - update handle
306c5c4113dSnw  */
307c5c4113dSnw idmap_stat
308cd37da74Snw idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
309cd37da74Snw {
310c5c4113dSnw 	idmap_udt_handle_t	*tmp;
311c5c4113dSnw 
312c5c4113dSnw 	if (handle == NULL || udthandle == NULL) {
313c5c4113dSnw 		errno = EINVAL;
314c5c4113dSnw 		return (IDMAP_ERR_ARG);
315c5c4113dSnw 	}
316c5c4113dSnw 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
317c5c4113dSnw 		errno = ENOMEM;
318c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
319c5c4113dSnw 	}
320c5c4113dSnw 
321c5c4113dSnw 	tmp->ih = handle;
322c5c4113dSnw 	*udthandle = tmp;
323c5c4113dSnw 	return (IDMAP_SUCCESS);
324c5c4113dSnw }
325c5c4113dSnw 
326c5c4113dSnw 
327c5c4113dSnw /*
328c5c4113dSnw  * All the updates specified by the update handle are committed
329c5c4113dSnw  * in a single transaction. i.e either all succeed or none.
330c5c4113dSnw  *
331c5c4113dSnw  * Input:
332c5c4113dSnw  * udthandle - update handle with the update requests
333c5c4113dSnw  *
334c5c4113dSnw  * Return value:
335c5c4113dSnw  * Status of the commit
336c5c4113dSnw  */
337c5c4113dSnw idmap_stat
338cd37da74Snw idmap_udt_commit(idmap_udt_handle_t *udthandle)
339cd37da74Snw {
340c5c4113dSnw 	CLIENT			*clnt;
341c5c4113dSnw 	enum clnt_stat		clntstat;
3428e228215Sdm 	idmap_update_res	res;
3438e228215Sdm 	idmap_stat		retcode;
344c5c4113dSnw 
345c5c4113dSnw 	if (udthandle == NULL) {
346c5c4113dSnw 		errno = EINVAL;
347c5c4113dSnw 		return (IDMAP_ERR_ARG);
348c5c4113dSnw 	}
3498e228215Sdm 
3508e228215Sdm 	(void) memset(&res, 0, sizeof (res));
3518e228215Sdm 
352c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
353c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
354cd37da74Snw 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
355cd37da74Snw 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
356cd37da74Snw 	    TIMEOUT);
357651c0131Sbaban 
3588e228215Sdm 	if (clntstat != RPC_SUCCESS) {
3598e228215Sdm 		retcode = _idmap_rpc2stat(clnt);
3608e228215Sdm 		goto out;
3618e228215Sdm 	}
3628e228215Sdm 
3638e228215Sdm 	retcode = udthandle->commit_stat = res.retcode;
3648e228215Sdm 	udthandle->error_index = res.error_index;
3658e228215Sdm 
3668e228215Sdm 	if (retcode != IDMAP_SUCCESS) {
3678e228215Sdm 
3688e228215Sdm 		if (udthandle->error_index < 0)
3698e228215Sdm 			goto out;
3708e228215Sdm 
3718e228215Sdm 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
3728e228215Sdm 		    &res.error_rule);
3738e228215Sdm 		if (retcode != IDMAP_SUCCESS) {
3748e228215Sdm 			udthandle->error_index = -2;
3758e228215Sdm 			goto out;
3768e228215Sdm 		}
3778e228215Sdm 
3788e228215Sdm 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
3798e228215Sdm 		    &res.conflict_rule);
3808e228215Sdm 		if (retcode != IDMAP_SUCCESS) {
3818e228215Sdm 			udthandle->error_index = -2;
3828e228215Sdm 			goto out;
3838e228215Sdm 		}
3848e228215Sdm 	}
3858e228215Sdm 
3868e228215Sdm 	retcode = res.retcode;
3878e228215Sdm 
3888e228215Sdm 
3898e228215Sdm out:
390651c0131Sbaban 	/* reset handle so that it can be used again */
3918e228215Sdm 	if (retcode == IDMAP_SUCCESS) {
3928e228215Sdm 		_IDMAP_RESET_UDT_HANDLE(udthandle);
3938e228215Sdm 	}
394651c0131Sbaban 
3958e228215Sdm 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3968e228215Sdm 	errno = idmap_stat2errno(retcode);
3978e228215Sdm 	return (retcode);
3988e228215Sdm }
3998e228215Sdm 
4008e228215Sdm 
4018e228215Sdm static void
4028e228215Sdm idmap_namerule_parts_clear(char **windomain, char **winname,
403cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
404cd37da74Snw     boolean_t *is_nt4, int *direction)
405cd37da74Snw {
4068e228215Sdm 	if (windomain)
4078e228215Sdm 		*windomain = NULL;
4088e228215Sdm 	if (winname)
4098e228215Sdm 		*winname = NULL;
4108e228215Sdm 	if (unixname)
4118e228215Sdm 		*unixname = NULL;
4128e228215Sdm 
4138e228215Sdm 	if (is_nt4)
4148e228215Sdm 		*is_nt4 = 0;
4158e228215Sdm 	if (is_user)
4168e228215Sdm 		*is_user = -1;
417cd37da74Snw 	if (is_wuser)
418cd37da74Snw 		*is_wuser = -1;
4198e228215Sdm 	if (direction)
4208e228215Sdm 		*direction = IDMAP_DIRECTION_UNDEF;
4218e228215Sdm }
4228e228215Sdm 
4238e228215Sdm static idmap_stat
424cd37da74Snw idmap_namerule2parts(idmap_namerule *rule,
4258e228215Sdm     char **windomain, char **winname,
426cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
427cd37da74Snw     boolean_t *is_nt4, int *direction)
428cd37da74Snw {
4298e228215Sdm 	idmap_stat retcode;
4308e228215Sdm 
4318e228215Sdm 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
4328e228215Sdm 		return (IDMAP_ERR_NORESULT);
4338e228215Sdm 
4348e228215Sdm 
4358e228215Sdm 	retcode = idmap_strdupnull(windomain, rule->windomain);
436c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
4378e228215Sdm 		goto errout;
4388e228215Sdm 
4398e228215Sdm 	retcode = idmap_strdupnull(winname, rule->winname);
4408e228215Sdm 	if (retcode != IDMAP_SUCCESS)
4418e228215Sdm 		goto errout;
4428e228215Sdm 
4438e228215Sdm 	retcode = idmap_strdupnull(unixname, rule->unixname);
4448e228215Sdm 	if (retcode != IDMAP_SUCCESS)
4458e228215Sdm 		goto errout;
4468e228215Sdm 
4478e228215Sdm 
4488e228215Sdm 	if (is_user)
4498e228215Sdm 		*is_user = rule->is_user;
450cd37da74Snw 	if (is_wuser)
451cd37da74Snw 		*is_wuser = rule->is_wuser;
4528e228215Sdm 	if (is_nt4)
4538e228215Sdm 		*is_nt4 = rule->is_nt4;
4548e228215Sdm 	if (direction)
4558e228215Sdm 		*direction = rule->direction;
4568e228215Sdm 
4578e228215Sdm 
4588e228215Sdm 	return (IDMAP_SUCCESS);
4598e228215Sdm 
4608e228215Sdm errout:
4618e228215Sdm 	if (windomain && *windomain)
4628e228215Sdm 		free(*windomain);
4638e228215Sdm 	if (winname && *winname)
4648e228215Sdm 		free(*winname);
4658e228215Sdm 	if (unixname && *unixname)
4668e228215Sdm 		free(*unixname);
4678e228215Sdm 
4688e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
469cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
4708e228215Sdm 
471c5c4113dSnw 	return (retcode);
4728e228215Sdm 
4738e228215Sdm }
4748e228215Sdm 
4758e228215Sdm /*
4768e228215Sdm  * Retrieve the index of the failed batch element. error_index == -1
4778e228215Sdm  * indicates failure at the beginning, -2 at the end.
4788e228215Sdm  *
4798e228215Sdm  * If idmap_udt_commit didn't return error, the returned value is undefined.
4808e228215Sdm  *
4818e228215Sdm  * Return value:
4828e228215Sdm  * IDMAP_SUCCESS
4838e228215Sdm  */
4848e228215Sdm 
4858e228215Sdm idmap_stat
4868e228215Sdm idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
487cd37da74Snw     int64_t *error_index)
488cd37da74Snw {
4898e228215Sdm 	if (error_index)
4908e228215Sdm 		*error_index = udthandle->error_index;
4918e228215Sdm 
4928e228215Sdm 	return (IDMAP_SUCCESS);
4938e228215Sdm }
4948e228215Sdm 
4958e228215Sdm 
4968e228215Sdm /*
4978e228215Sdm  * Retrieve the rule which caused the batch to fail. If
4988e228215Sdm  * idmap_udt_commit didn't return error or if error_index is < 0, the
4998e228215Sdm  * retrieved rule is undefined.
5008e228215Sdm  *
5018e228215Sdm  * Return value:
5028e228215Sdm  * IDMAP_ERR_NORESULT if there is no error rule.
5038e228215Sdm  * IDMAP_SUCCESS if the rule was obtained OK.
5048e228215Sdm  * other error code (IDMAP_ERR_NOMEMORY etc)
5058e228215Sdm  */
5068e228215Sdm 
5078e228215Sdm idmap_stat
5088e228215Sdm idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
5098e228215Sdm     char **windomain, char **winname,
510cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
511cd37da74Snw     boolean_t *is_nt4, int *direction)
512cd37da74Snw {
5138e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
514cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
5158e228215Sdm 
5168e228215Sdm 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
5178e228215Sdm 	    udthandle->error_index < 0)
5188e228215Sdm 		return (IDMAP_ERR_NORESULT);
5198e228215Sdm 
5208e228215Sdm 	return (idmap_namerule2parts(
521cd37da74Snw 	    &udthandle->error_rule,
522cd37da74Snw 	    windomain,
523cd37da74Snw 	    winname,
524cd37da74Snw 	    unixname,
525cd37da74Snw 	    is_user,
526cd37da74Snw 	    is_wuser,
527cd37da74Snw 	    is_nt4,
528cd37da74Snw 	    direction));
5298e228215Sdm }
5308e228215Sdm 
5318e228215Sdm /*
5328e228215Sdm  * Retrieve the rule with which there was a conflict. TODO: retrieve
5338e228215Sdm  * the value.
5348e228215Sdm  *
5358e228215Sdm  * Return value:
5368e228215Sdm  * IDMAP_ERR_NORESULT if there is no error rule.
5378e228215Sdm  * IDMAP_SUCCESS if the rule was obtained OK.
5388e228215Sdm  * other error code (IDMAP_ERR_NOMEMORY etc)
5398e228215Sdm  */
5408e228215Sdm 
5418e228215Sdm idmap_stat
5428e228215Sdm idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
5438e228215Sdm     char **windomain, char **winname,
544cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
545cd37da74Snw     boolean_t *is_nt4, int *direction)
546cd37da74Snw {
5478e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
548cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
5498e228215Sdm 
5508e228215Sdm 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
5518e228215Sdm 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
552cd37da74Snw 		return (IDMAP_ERR_NORESULT);
5538e228215Sdm 	}
5548e228215Sdm 
5558e228215Sdm 	return (idmap_namerule2parts(
556cd37da74Snw 	    &udthandle->conflict_rule,
557cd37da74Snw 	    windomain,
558cd37da74Snw 	    winname,
559cd37da74Snw 	    unixname,
560cd37da74Snw 	    is_user,
561cd37da74Snw 	    is_wuser,
562cd37da74Snw 	    is_nt4,
563cd37da74Snw 	    direction));
564c5c4113dSnw }
565c5c4113dSnw 
566c5c4113dSnw 
567c5c4113dSnw /*
568c5c4113dSnw  * Destroy the update handle
569c5c4113dSnw  */
570c5c4113dSnw void
571cd37da74Snw idmap_udt_destroy(idmap_udt_handle_t *udthandle)
572cd37da74Snw {
573c5c4113dSnw 	if (udthandle == NULL)
574c5c4113dSnw 		return;
575c5c4113dSnw 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
5768e228215Sdm 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
5778e228215Sdm 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
578c5c4113dSnw 	free(udthandle);
579c5c4113dSnw }
580c5c4113dSnw 
581c5c4113dSnw 
582c5c4113dSnw idmap_stat
583c5c4113dSnw idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
584cd37da74Snw     boolean_t is_user, boolean_t is_wuser, const char *winname,
585cd37da74Snw     const char *unixname, boolean_t is_nt4, int direction)
586cd37da74Snw {
587c5c4113dSnw 	idmap_retcode	retcode;
588651c0131Sbaban 	idmap_namerule	*rule = NULL;
589c5c4113dSnw 
590651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
591c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
592c5c4113dSnw 		goto errout;
593c5c4113dSnw 
594c5c4113dSnw 	rule = &udthandle->batch.
595cd37da74Snw 	    idmap_update_batch_val[udthandle->next].
596cd37da74Snw 	    idmap_update_op_u.rule;
597c5c4113dSnw 	rule->is_user = is_user;
598cd37da74Snw 	rule->is_wuser = is_wuser;
599c5c4113dSnw 	rule->direction = direction;
600c5c4113dSnw 	rule->is_nt4 = is_nt4;
6018e228215Sdm 
6028e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6038e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6048e228215Sdm 		goto errout;
6058e228215Sdm 
6068e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
6078e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6088e228215Sdm 		goto errout;
6098e228215Sdm 
6108e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6118e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6128e228215Sdm 		goto errout;
613651c0131Sbaban 
614651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
615651c0131Sbaban 	    OP_ADD_NAMERULE;
616c5c4113dSnw 	udthandle->next++;
617c5c4113dSnw 	return (IDMAP_SUCCESS);
618c5c4113dSnw 
619c5c4113dSnw errout:
620651c0131Sbaban 	/* The batch should still be usable */
621651c0131Sbaban 	if (rule)
622651c0131Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
623c5c4113dSnw 	errno = idmap_stat2errno(retcode);
624c5c4113dSnw 	return (retcode);
625c5c4113dSnw }
626c5c4113dSnw 
627c5c4113dSnw 
628c5c4113dSnw /* ARGSUSED */
629c5c4113dSnw idmap_stat
630c5c4113dSnw idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
631cd37da74Snw     boolean_t is_wuser,	const char *windomain, const char *winname,
632cd37da74Snw     const char *unixname, int direction)
633cd37da74Snw {
634c5c4113dSnw 	idmap_retcode	retcode;
635651c0131Sbaban 	idmap_namerule	*rule = NULL;
636c5c4113dSnw 
637651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
638c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
639c5c4113dSnw 		goto errout;
640c5c4113dSnw 
641c5c4113dSnw 	rule = &udthandle->batch.
642cd37da74Snw 	    idmap_update_batch_val[udthandle->next].
643cd37da74Snw 	    idmap_update_op_u.rule;
644c5c4113dSnw 	rule->is_user = is_user;
645cd37da74Snw 	rule->is_wuser = is_wuser;
646c5c4113dSnw 	rule->direction = direction;
6478e228215Sdm 
6488e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6498e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6508e228215Sdm 		goto errout;
6518e228215Sdm 
6528e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
6538e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6548e228215Sdm 		goto errout;
6558e228215Sdm 
6568e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6578e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6588e228215Sdm 		goto errout;
6598e228215Sdm 
660651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
661651c0131Sbaban 	    OP_RM_NAMERULE;
662c5c4113dSnw 	udthandle->next++;
663c5c4113dSnw 	return (IDMAP_SUCCESS);
664c5c4113dSnw 
665c5c4113dSnw errout:
666651c0131Sbaban 	if (rule)
667651c0131Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
668c5c4113dSnw 	errno = idmap_stat2errno(retcode);
669c5c4113dSnw 	return (retcode);
670c5c4113dSnw }
671c5c4113dSnw 
672c5c4113dSnw 
673c5c4113dSnw /* ARGSUSED */
674c5c4113dSnw idmap_stat
675cd37da74Snw idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
676cd37da74Snw {
677c5c4113dSnw 	idmap_retcode	retcode;
678c5c4113dSnw 
679651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
680c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
681c5c4113dSnw 		goto errout;
682c5c4113dSnw 
683651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
684651c0131Sbaban 	    OP_FLUSH_NAMERULES;
685c5c4113dSnw 	udthandle->next++;
686c5c4113dSnw 	return (IDMAP_SUCCESS);
687c5c4113dSnw 
688c5c4113dSnw errout:
689c5c4113dSnw 	errno = idmap_stat2errno(retcode);
690c5c4113dSnw 	return (retcode);
691c5c4113dSnw }
692c5c4113dSnw 
693c5c4113dSnw 
694c5c4113dSnw /*
695c5c4113dSnw  * Set the number of entries requested per batch by the iterator
696c5c4113dSnw  *
697c5c4113dSnw  * Input:
698c5c4113dSnw  * iter  - iterator
699c5c4113dSnw  * limit - number of entries requested per batch
700c5c4113dSnw  */
701c5c4113dSnw idmap_stat
702cd37da74Snw idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
703cd37da74Snw {
704c5c4113dSnw 	if (iter == NULL) {
705c5c4113dSnw 		errno = EINVAL;
706c5c4113dSnw 		return (IDMAP_ERR_ARG);
707c5c4113dSnw 	}
708c5c4113dSnw 	iter->limit = limit;
709c5c4113dSnw 	return (IDMAP_SUCCESS);
710c5c4113dSnw }
711c5c4113dSnw 
712c5c4113dSnw 
713c5c4113dSnw /*
714c5c4113dSnw  * Create iterator to get name-based mapping rules
715c5c4113dSnw  *
716c5c4113dSnw  * Input:
717c5c4113dSnw  * windomain - Windows domain
718c5c4113dSnw  * is_user   - user or group rules
719c5c4113dSnw  * winname   - Windows user or group name
720c5c4113dSnw  * unixname  - Unix user or group name
721c5c4113dSnw  *
722c5c4113dSnw  * Output:
723c5c4113dSnw  * iter - iterator
724c5c4113dSnw  */
725c5c4113dSnw idmap_stat
726c5c4113dSnw idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
727cd37da74Snw 		boolean_t is_user, boolean_t is_wuser, const char *winname,
728cd37da74Snw 		const char *unixname, idmap_iter_t **iter)
729cd37da74Snw {
730c5c4113dSnw 
731c5c4113dSnw 	idmap_iter_t			*tmpiter;
732c5c4113dSnw 	idmap_list_namerules_1_argument	*arg = NULL;
733c5c4113dSnw 	idmap_namerule			*rule;
734c5c4113dSnw 	idmap_retcode			retcode;
735c5c4113dSnw 
736c5c4113dSnw 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
737c5c4113dSnw 
738c5c4113dSnw 	rule = &arg->rule;
739c5c4113dSnw 	rule->is_user = is_user;
740cd37da74Snw 	rule->is_wuser = is_wuser;
741651c0131Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
7428e228215Sdm 
7438e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
7448e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7458e228215Sdm 		goto errout;
7468e228215Sdm 
7478e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
7488e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7498e228215Sdm 		goto errout;
7508e228215Sdm 
7518e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
7528e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7538e228215Sdm 		goto errout;
754c5c4113dSnw 
755c5c4113dSnw 	*iter = tmpiter;
756c5c4113dSnw 	return (IDMAP_SUCCESS);
757c5c4113dSnw 
758c5c4113dSnw errout:
759c5c4113dSnw 	__ITER_ERR_RETURN(tmpiter, arg,
760cd37da74Snw 	    xdr_idmap_list_namerules_1_argument, retcode);
761c5c4113dSnw }
762c5c4113dSnw 
763c5c4113dSnw 
764c5c4113dSnw /*
765c5c4113dSnw  * Iterate through the name-based mapping rules
766c5c4113dSnw  *
767c5c4113dSnw  * Input:
768c5c4113dSnw  * iter - iterator
769c5c4113dSnw  *
770c5c4113dSnw  * Output:
771c5c4113dSnw  * windomain - Windows domain
772c5c4113dSnw  * winname   - Windows user or group name
773c5c4113dSnw  * unixname  - Unix user or group name
774c5c4113dSnw  * is_nt4    - NT4 or AD
775c5c4113dSnw  * direction - bi(0), win2unix(1), unix2win(2)
776c5c4113dSnw  *
777c5c4113dSnw  * Return value:
778c5c4113dSnw  * 0   - done
779c5c4113dSnw  * 1   - more results available
780c5c4113dSnw  * < 0 - error
781c5c4113dSnw  */
782c5c4113dSnw idmap_stat
783c5c4113dSnw idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
784cd37da74Snw     char **winname, char **unixname,  boolean_t *is_user,
785cd37da74Snw     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
786cd37da74Snw {
787c5c4113dSnw 	idmap_namerules_res		*namerules;
788c5c4113dSnw 	idmap_list_namerules_1_argument	*arg;
789c5c4113dSnw 	idmap_retcode			retcode;
790c5c4113dSnw 
791cd37da74Snw 	idmap_namerule_parts_clear(windomain, winname,
792cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
793cd37da74Snw 
794c5c4113dSnw 
795c5c4113dSnw 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
796c5c4113dSnw 
797c5c4113dSnw 	namerules = (idmap_namerules_res *)iter->retlist;
798c5c4113dSnw 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
799cd37da74Snw 	    iter->next >= namerules->rules.rules_len)) {
800c5c4113dSnw 
801c5c4113dSnw 		if ((arg = iter->arg) == NULL) {
802c5c4113dSnw 			errno = EINVAL;
803c5c4113dSnw 			return (IDMAP_ERR_ARG);
804c5c4113dSnw 		}
805c5c4113dSnw 		arg->limit = iter->limit;
806c5c4113dSnw 
807c5c4113dSnw 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
808cd37da74Snw 		    iter, arg,
809cd37da74Snw 		    (uchar_t **)&namerules, sizeof (*namerules),
810cd37da74Snw 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
811cd37da74Snw 		    (xdrproc_t)xdr_idmap_namerules_res);
812c5c4113dSnw 		if (retcode != IDMAP_SUCCESS)
813c5c4113dSnw 			return (retcode);
814c5c4113dSnw 
815c5c4113dSnw 		if (IDMAP_ERROR(namerules->retcode)) {
816c5c4113dSnw 			retcode  = namerules->retcode;
817c5c4113dSnw 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
818c5c4113dSnw 			free(namerules);
819c5c4113dSnw 			iter->retlist = NULL;
820c5c4113dSnw 			return (retcode);
821c5c4113dSnw 		}
822c5c4113dSnw 		iter->retcode = namerules->retcode;
823c5c4113dSnw 		arg->lastrowid = namerules->lastrowid;
824c5c4113dSnw 	}
825c5c4113dSnw 
826c5c4113dSnw 	if (namerules == NULL || namerules->rules.rules_len == 0)
827c5c4113dSnw 		return (IDMAP_SUCCESS);
828c5c4113dSnw 
829c5c4113dSnw 	if (iter->next >= namerules->rules.rules_len) {
830c5c4113dSnw 		return (IDMAP_ERR_ARG);
831c5c4113dSnw 	}
832c5c4113dSnw 
8338e228215Sdm 	retcode = idmap_strdupnull(windomain,
8348e228215Sdm 	    namerules->rules.rules_val[iter->next].windomain);
8358e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8368e228215Sdm 		goto errout;
8378e228215Sdm 
8388e228215Sdm 	retcode = idmap_strdupnull(winname,
8398e228215Sdm 	    namerules->rules.rules_val[iter->next].winname);
8408e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8418e228215Sdm 		goto errout;
8428e228215Sdm 
8438e228215Sdm 	retcode = idmap_strdupnull(unixname,
8448e228215Sdm 	    namerules->rules.rules_val[iter->next].unixname);
8458e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8468e228215Sdm 		goto errout;
8478e228215Sdm 
848c5c4113dSnw 	if (is_nt4)
849c5c4113dSnw 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
850cd37da74Snw 	if (is_user)
851cd37da74Snw 		*is_user = namerules->rules.rules_val[iter->next].is_user;
852cd37da74Snw 	if (is_wuser)
853cd37da74Snw 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
854c5c4113dSnw 	if (direction)
855c5c4113dSnw 		*direction = namerules->rules.rules_val[iter->next].direction;
856c5c4113dSnw 	iter->next++;
857c5c4113dSnw 
858c5c4113dSnw 	if (iter->next == namerules->rules.rules_len)
859c5c4113dSnw 		return (iter->retcode);
860c5c4113dSnw 	else
861c5c4113dSnw 		return (IDMAP_NEXT);
862c5c4113dSnw 
863c5c4113dSnw errout:
864c5c4113dSnw 	if (windomain && *windomain)
865c5c4113dSnw 		free(*windomain);
866c5c4113dSnw 	if (winname && *winname)
867c5c4113dSnw 		free(*winname);
868c5c4113dSnw 	if (unixname && *unixname)
869c5c4113dSnw 		free(*unixname);
870c5c4113dSnw 	return (retcode);
871c5c4113dSnw }
872c5c4113dSnw 
873c5c4113dSnw 
874c5c4113dSnw /*
875c5c4113dSnw  * Create iterator to get SID to UID/GID mappings
876c5c4113dSnw  *
877c5c4113dSnw  * Output:
878c5c4113dSnw  * iter - iterator
879c5c4113dSnw  */
880c5c4113dSnw idmap_stat
88148258c6bSjp idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
882cd37da74Snw {
883c5c4113dSnw 	idmap_iter_t			*tmpiter;
884c5c4113dSnw 	idmap_list_mappings_1_argument	*arg = NULL;
885c5c4113dSnw 
886c5c4113dSnw 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
887c5c4113dSnw 
88848258c6bSjp 	arg->flag = flag;
889c5c4113dSnw 	*iter = tmpiter;
890c5c4113dSnw 	return (IDMAP_SUCCESS);
891c5c4113dSnw }
892c5c4113dSnw 
893c5c4113dSnw 
894c5c4113dSnw /*
895c5c4113dSnw  * Iterate through the SID to UID/GID mappings
896c5c4113dSnw  *
897c5c4113dSnw  * Input:
898c5c4113dSnw  * iter - iterator
899c5c4113dSnw  *
900c5c4113dSnw  * Output:
901c5c4113dSnw  * sid - SID in canonical form
902c5c4113dSnw  * pid - UID or GID
903c5c4113dSnw  *
904c5c4113dSnw  * Return value:
905c5c4113dSnw  * 0   - done
906c5c4113dSnw  * 1   - more results available
907c5c4113dSnw  * < 0 - error
908c5c4113dSnw  */
909c5c4113dSnw idmap_stat
910c5c4113dSnw idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
911cd37da74Snw     idmap_rid_t *rid, uid_t *pid, char **winname,
912cd37da74Snw     char **windomain, char **unixname, boolean_t *is_user,
91348258c6bSjp     boolean_t *is_wuser, int *direction, idmap_info *info)
914cd37da74Snw {
915c5c4113dSnw 	idmap_mappings_res		*mappings;
916c5c4113dSnw 	idmap_list_mappings_1_argument	*arg;
917c5c4113dSnw 	idmap_retcode			retcode;
918c5c4113dSnw 	char				*str;
919c5c4113dSnw 
920c5c4113dSnw 	if (sidprefix)
921c5c4113dSnw 		*sidprefix = NULL;
922c5c4113dSnw 	if (rid)
923c5c4113dSnw 		*rid = UINT32_MAX;
924c5c4113dSnw 	if (winname)
925c5c4113dSnw 		*winname = NULL;
926c5c4113dSnw 	if (windomain)
927c5c4113dSnw 		*windomain = NULL;
928c5c4113dSnw 	if (unixname)
929c5c4113dSnw 		*unixname = NULL;
930c5c4113dSnw 	if (pid)
931c5c4113dSnw 		*pid = UINT32_MAX;
932cd37da74Snw 	if (is_user)
933cd37da74Snw 		*is_user = -1;
934cd37da74Snw 	if (is_wuser)
935cd37da74Snw 		*is_wuser = -1;
936c5c4113dSnw 	if (direction)
937651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
938c5c4113dSnw 
939c5c4113dSnw 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
940c5c4113dSnw 
941c5c4113dSnw 	mappings = (idmap_mappings_res *)iter->retlist;
942c5c4113dSnw 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
943cd37da74Snw 	    iter->next >= mappings->mappings.mappings_len)) {
944c5c4113dSnw 
945c5c4113dSnw 		if ((arg = iter->arg) == NULL) {
946c5c4113dSnw 			errno = EINVAL;
947c5c4113dSnw 			return (IDMAP_ERR_ARG);
948c5c4113dSnw 		}
949c5c4113dSnw 		arg->limit = iter->limit;
950c5c4113dSnw 
951c5c4113dSnw 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
952cd37da74Snw 		    iter, arg,
953cd37da74Snw 		    (uchar_t **)&mappings, sizeof (*mappings),
954cd37da74Snw 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
955cd37da74Snw 		    (xdrproc_t)xdr_idmap_mappings_res);
956c5c4113dSnw 		if (retcode != IDMAP_SUCCESS)
957c5c4113dSnw 			return (retcode);
958c5c4113dSnw 
959c5c4113dSnw 		if (IDMAP_ERROR(mappings->retcode)) {
960c5c4113dSnw 			retcode  = mappings->retcode;
961c5c4113dSnw 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
962c5c4113dSnw 			free(mappings);
963c5c4113dSnw 			iter->retlist = NULL;
964c5c4113dSnw 			return (retcode);
965c5c4113dSnw 		}
966c5c4113dSnw 		iter->retcode = mappings->retcode;
967c5c4113dSnw 		arg->lastrowid = mappings->lastrowid;
968c5c4113dSnw 	}
969c5c4113dSnw 
970c5c4113dSnw 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
971c5c4113dSnw 		return (IDMAP_SUCCESS);
972c5c4113dSnw 
973c5c4113dSnw 	if (iter->next >= mappings->mappings.mappings_len) {
974c5c4113dSnw 		return (IDMAP_ERR_ARG);
975c5c4113dSnw 	}
976c5c4113dSnw 
977c5c4113dSnw 	if (sidprefix) {
978c5c4113dSnw 		str = mappings->mappings.mappings_val[iter->next].id1.
979cd37da74Snw 		    idmap_id_u.sid.prefix;
9808edda628Sbaban 		if (str && *str != '\0') {
981c5c4113dSnw 			*sidprefix = strdup(str);
9829581d9f4Sbaban 			if (*sidprefix == NULL) {
9839581d9f4Sbaban 				retcode = IDMAP_ERR_MEMORY;
9849581d9f4Sbaban 				goto errout;
9859581d9f4Sbaban 			}
986c5c4113dSnw 		}
987c5c4113dSnw 	}
988c5c4113dSnw 	if (rid)
989c5c4113dSnw 		*rid = mappings->mappings.mappings_val[iter->next].id1.
990cd37da74Snw 		    idmap_id_u.sid.rid;
9918e228215Sdm 
9928e228215Sdm 	retcode = idmap_strdupnull(windomain,
9938e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id1domain);
9948e228215Sdm 	if (retcode != IDMAP_SUCCESS)
9958e228215Sdm 		goto errout;
9968e228215Sdm 
9978e228215Sdm 	retcode = idmap_strdupnull(winname,
9988e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id1name);
9998e228215Sdm 	if (retcode != IDMAP_SUCCESS)
10008e228215Sdm 		goto errout;
10018e228215Sdm 
10028e228215Sdm 	retcode = idmap_strdupnull(unixname,
10038e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id2name);
10048e228215Sdm 	if (retcode != IDMAP_SUCCESS)
10058e228215Sdm 		goto errout;
10068e228215Sdm 
10078e228215Sdm 
1008c5c4113dSnw 	if (pid)
1009c5c4113dSnw 		*pid = mappings->mappings.mappings_val[iter->next].id2.
1010cd37da74Snw 		    idmap_id_u.uid;
1011c5c4113dSnw 	if (direction)
1012c5c4113dSnw 		*direction = mappings->mappings.mappings_val[iter->next].
1013cd37da74Snw 		    direction;
1014cd37da74Snw 	if (is_user)
1015cd37da74Snw 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
1016cd37da74Snw 		    .idtype == IDMAP_UID)?1:0;
1017cd37da74Snw 	if (is_wuser)
1018cd37da74Snw 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
1019cd37da74Snw 		    .idtype == IDMAP_USID)?1:0;
1020cd37da74Snw 
102148258c6bSjp 	if (info) {
102248258c6bSjp 		retcode = idmap_info_cpy(info,
102348258c6bSjp 		    &mappings->mappings.mappings_val[iter->next].info);
102448258c6bSjp 		if (retcode != IDMAP_SUCCESS)
102548258c6bSjp 			goto errout;
102648258c6bSjp 	}
1027c5c4113dSnw 	iter->next++;
1028c5c4113dSnw 
1029c5c4113dSnw 	if (iter->next == mappings->mappings.mappings_len)
1030c5c4113dSnw 		return (iter->retcode);
1031c5c4113dSnw 	else
1032c5c4113dSnw 		return (IDMAP_NEXT);
1033c5c4113dSnw 
1034c5c4113dSnw errout:
1035c5c4113dSnw 	if (sidprefix && *sidprefix)
1036c5c4113dSnw 		free(*sidprefix);
1037c5c4113dSnw 	if (winname && *winname)
1038c5c4113dSnw 		free(*winname);
1039c5c4113dSnw 	if (windomain && *windomain)
1040c5c4113dSnw 		free(*windomain);
1041c5c4113dSnw 	if (unixname && *unixname)
1042c5c4113dSnw 		free(*unixname);
1043c5c4113dSnw 	return (retcode);
1044c5c4113dSnw }
1045c5c4113dSnw 
1046c5c4113dSnw 
1047c5c4113dSnw /*
1048c5c4113dSnw  * Destroy the iterator
1049c5c4113dSnw  */
1050c5c4113dSnw void
1051cd37da74Snw idmap_iter_destroy(idmap_iter_t *iter)
1052cd37da74Snw {
1053c5c4113dSnw 	xdrproc_t _xdr_argument, _xdr_result;
1054c5c4113dSnw 
1055c5c4113dSnw 	if (iter == NULL)
1056c5c4113dSnw 		return;
1057c5c4113dSnw 
1058c5c4113dSnw 	switch (iter->type) {
1059c5c4113dSnw 	case IDMAP_LIST_NAMERULES:
1060c5c4113dSnw 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
1061c5c4113dSnw 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
1062c5c4113dSnw 		break;
1063c5c4113dSnw 	case IDMAP_LIST_MAPPINGS:
1064c5c4113dSnw 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
1065c5c4113dSnw 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
1066c5c4113dSnw 		break;
1067c5c4113dSnw 	default:
1068c5c4113dSnw 		free(iter);
1069c5c4113dSnw 		return;
1070c5c4113dSnw 	};
1071c5c4113dSnw 
1072c5c4113dSnw 	if (iter->arg) {
1073c5c4113dSnw 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
1074c5c4113dSnw 		free(iter->arg);
1075c5c4113dSnw 	}
1076c5c4113dSnw 	if (iter->retlist) {
1077c5c4113dSnw 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
1078c5c4113dSnw 		free(iter->retlist);
1079c5c4113dSnw 	}
1080c5c4113dSnw 	free(iter);
1081c5c4113dSnw }
1082c5c4113dSnw 
1083c5c4113dSnw 
1084c5c4113dSnw /*
1085c5c4113dSnw  * Create handle to get SID to UID/GID mapping entries
1086c5c4113dSnw  *
1087c5c4113dSnw  * Input:
1088c5c4113dSnw  * gh - "get mapping" handle
1089c5c4113dSnw  */
1090c5c4113dSnw idmap_stat
1091cd37da74Snw idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
1092cd37da74Snw {
1093c5c4113dSnw 	idmap_get_handle_t	*tmp;
1094c5c4113dSnw 
1095c5c4113dSnw 	/* sanity checks */
1096c5c4113dSnw 	if (handle == NULL || gh == NULL) {
1097c5c4113dSnw 		errno = EINVAL;
1098c5c4113dSnw 		return (IDMAP_ERR_ARG);
1099c5c4113dSnw 	}
1100c5c4113dSnw 
1101c5c4113dSnw 	/* allocate the handle */
1102c5c4113dSnw 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
1103c5c4113dSnw 		errno = ENOMEM;
1104c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
1105c5c4113dSnw 	}
1106c5c4113dSnw 
1107c5c4113dSnw 	tmp->ih = handle;
1108c5c4113dSnw 	*gh = tmp;
1109c5c4113dSnw 	return (IDMAP_SUCCESS);
1110c5c4113dSnw }
1111c5c4113dSnw 
1112c5c4113dSnw 
1113c5c4113dSnw /*
1114c5c4113dSnw  * Given SID, get UID
1115c5c4113dSnw  *
1116c5c4113dSnw  * Input:
1117c5c4113dSnw  * sidprefix  - SID prefix
1118c5c4113dSnw  * rid        - RID
1119c5c4113dSnw  * flag       - flag
1120c5c4113dSnw  *
1121c5c4113dSnw  * Output:
1122c5c4113dSnw  * stat - status of the get request
1123c5c4113dSnw  * uid  - POSIX UID if stat = 0
1124c5c4113dSnw  *
1125c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1126c5c4113dSnw  */
1127c5c4113dSnw idmap_stat
1128c5c4113dSnw idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1129cd37da74Snw 		int flag, uid_t *uid, idmap_stat *stat)
1130cd37da74Snw {
113148258c6bSjp 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
113248258c6bSjp 	    NULL, stat));
113348258c6bSjp }
113448258c6bSjp 
113548258c6bSjp /*
113648258c6bSjp  * Given SID, get UID
113748258c6bSjp  *
113848258c6bSjp  * Input:
113948258c6bSjp  * sidprefix  - SID prefix
114048258c6bSjp  * rid        - RID
114148258c6bSjp  * flag       - flag
114248258c6bSjp  *
114348258c6bSjp  * Output:
114448258c6bSjp  * stat - status of the get request
114548258c6bSjp  * uid  - POSIX UID if stat = 0
114648258c6bSjp  * how  - mapping type if stat = 0
114748258c6bSjp  *
114848258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
114948258c6bSjp  */
1150c5c4113dSnw 
115148258c6bSjp idmap_stat
115248258c6bSjp idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
115348258c6bSjp 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
115448258c6bSjp {
1155c5c4113dSnw 	idmap_retcode	retcode;
1156651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1157c5c4113dSnw 
1158c5c4113dSnw 	/* sanity checks */
1159c5c4113dSnw 	if (gh == NULL)
1160c5c4113dSnw 		return (IDMAP_ERR_ARG);
1161c5c4113dSnw 	if (uid == NULL || sidprefix == NULL)
1162c5c4113dSnw 		return (IDMAP_ERR_ARG);
1163c5c4113dSnw 
1164*3ee87bcaSJulian Pullen 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1165*3ee87bcaSJulian Pullen 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1166*3ee87bcaSJulian Pullen 		retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid);
1167*3ee87bcaSJulian Pullen 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1168*3ee87bcaSJulian Pullen 			*stat = retcode;
1169*3ee87bcaSJulian Pullen 			return (retcode);
1170*3ee87bcaSJulian Pullen 		}
1171*3ee87bcaSJulian Pullen 	}
1172*3ee87bcaSJulian Pullen 
1173c5c4113dSnw 	/* Extend the request array and the return list */
1174c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1175c5c4113dSnw 		goto errout;
1176c5c4113dSnw 
1177c5c4113dSnw 	/* Setup the request */
1178c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1179c5c4113dSnw 	mapping->flag = flag;
1180c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1181c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1182c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1183c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1184c5c4113dSnw 		goto errout;
1185c5c4113dSnw 	}
1186c5c4113dSnw 	mapping->id2.idtype = IDMAP_UID;
1187c5c4113dSnw 
1188c5c4113dSnw 	/* Setup pointers for the result */
1189c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_UID;
1190c5c4113dSnw 	gh->retlist[gh->next].uid = uid;
1191c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
119248258c6bSjp 	gh->retlist[gh->next].info = info;
1193*3ee87bcaSJulian Pullen 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
1194c5c4113dSnw 
1195c5c4113dSnw 	gh->next++;
1196c5c4113dSnw 	return (IDMAP_SUCCESS);
1197c5c4113dSnw 
1198c5c4113dSnw errout:
1199651c0131Sbaban 	/* Batch created so far should still be usable */
1200651c0131Sbaban 	if (mapping)
1201651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1202c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1203c5c4113dSnw 	return (retcode);
1204c5c4113dSnw }
1205c5c4113dSnw 
1206c5c4113dSnw 
1207c5c4113dSnw /*
1208c5c4113dSnw  * Given SID, get GID
1209c5c4113dSnw  *
1210c5c4113dSnw  * Input:
1211c5c4113dSnw  * sidprefix  - SID prefix
1212c5c4113dSnw  * rid        - rid
1213c5c4113dSnw  * flag       - flag
1214c5c4113dSnw  *
1215c5c4113dSnw  * Output:
1216c5c4113dSnw  * stat - status of the get request
1217c5c4113dSnw  * gid  - POSIX GID if stat = 0
1218c5c4113dSnw  *
1219c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1220c5c4113dSnw  */
1221c5c4113dSnw idmap_stat
1222c5c4113dSnw idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1223cd37da74Snw 		int flag, gid_t *gid, idmap_stat *stat)
1224cd37da74Snw {
122548258c6bSjp 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
122648258c6bSjp 	    NULL, stat));
122748258c6bSjp }
122848258c6bSjp 
122948258c6bSjp 
123048258c6bSjp /*
123148258c6bSjp  * Given SID, get GID
123248258c6bSjp  *
123348258c6bSjp  * Input:
123448258c6bSjp  * sidprefix  - SID prefix
123548258c6bSjp  * rid        - rid
123648258c6bSjp  * flag       - flag
123748258c6bSjp  *
123848258c6bSjp  * Output:
123948258c6bSjp  * stat - status of the get request
124048258c6bSjp  * gid  - POSIX GID if stat = 0
124148258c6bSjp  * how  - mapping type if stat = 0
124248258c6bSjp  *
124348258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
124448258c6bSjp  */
124548258c6bSjp idmap_stat
124648258c6bSjp idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
124748258c6bSjp 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
124848258c6bSjp {
1249c5c4113dSnw 
1250c5c4113dSnw 	idmap_retcode	retcode;
1251651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1252c5c4113dSnw 
1253c5c4113dSnw 	/* sanity checks */
1254c5c4113dSnw 	if (gh == NULL)
1255c5c4113dSnw 		return (IDMAP_ERR_ARG);
1256c5c4113dSnw 	if (gid == NULL || sidprefix == NULL)
1257c5c4113dSnw 		return (IDMAP_ERR_ARG);
1258c5c4113dSnw 
1259*3ee87bcaSJulian Pullen 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1260*3ee87bcaSJulian Pullen 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1261*3ee87bcaSJulian Pullen 		retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid);
1262*3ee87bcaSJulian Pullen 		if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1263*3ee87bcaSJulian Pullen 			*stat = retcode;
1264*3ee87bcaSJulian Pullen 			return (retcode);
1265*3ee87bcaSJulian Pullen 		}
1266*3ee87bcaSJulian Pullen 	}
1267*3ee87bcaSJulian Pullen 
1268c5c4113dSnw 	/* Extend the request array and the return list */
1269c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1270c5c4113dSnw 		goto errout;
1271c5c4113dSnw 
1272c5c4113dSnw 	/* Setup the request */
1273c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1274c5c4113dSnw 	mapping->flag = flag;
1275c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1276c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1277c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1278c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1279c5c4113dSnw 		goto errout;
1280c5c4113dSnw 	}
1281c5c4113dSnw 	mapping->id2.idtype = IDMAP_GID;
1282c5c4113dSnw 
1283c5c4113dSnw 	/* Setup pointers for the result */
1284c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_GID;
1285c5c4113dSnw 	gh->retlist[gh->next].gid = gid;
1286c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
128748258c6bSjp 	gh->retlist[gh->next].info = info;
1288*3ee87bcaSJulian Pullen 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
1289c5c4113dSnw 
1290c5c4113dSnw 	gh->next++;
1291c5c4113dSnw 	return (IDMAP_SUCCESS);
1292c5c4113dSnw 
1293c5c4113dSnw errout:
1294651c0131Sbaban 	if (mapping)
1295651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1296c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1297c5c4113dSnw 	return (retcode);
1298c5c4113dSnw }
1299c5c4113dSnw 
1300c5c4113dSnw 
130148258c6bSjp 
1302c5c4113dSnw /*
1303c5c4113dSnw  * Given SID, get POSIX ID i.e. UID/GID
1304c5c4113dSnw  *
1305c5c4113dSnw  * Input:
1306c5c4113dSnw  * sidprefix  - SID prefix
1307c5c4113dSnw  * rid        - rid
1308c5c4113dSnw  * flag       - flag
1309c5c4113dSnw  *
1310c5c4113dSnw  * Output:
1311c5c4113dSnw  * stat    - status of the get request
1312c5c4113dSnw  * is_user - user or group
1313c5c4113dSnw  * pid     - POSIX UID if stat = 0 and is_user = 1
1314c5c4113dSnw  *           POSIX GID if stat = 0 and is_user = 0
1315c5c4113dSnw  *
1316c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1317c5c4113dSnw  */
1318c5c4113dSnw idmap_stat
1319c5c4113dSnw idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1320cd37da74Snw 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
132148258c6bSjp {
132248258c6bSjp 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
132348258c6bSjp 	    NULL, stat));
132448258c6bSjp }
132548258c6bSjp 
132648258c6bSjp 
132748258c6bSjp 
132848258c6bSjp /*
132948258c6bSjp  * Given SID, get POSIX ID i.e. UID/GID
133048258c6bSjp  *
133148258c6bSjp  * Input:
133248258c6bSjp  * sidprefix  - SID prefix
133348258c6bSjp  * rid        - rid
133448258c6bSjp  * flag       - flag
133548258c6bSjp  *
133648258c6bSjp  * Output:
133748258c6bSjp  * stat    - status of the get request
133848258c6bSjp  * is_user - user or group
133948258c6bSjp  * pid     - POSIX UID if stat = 0 and is_user = 1
134048258c6bSjp  *           POSIX GID if stat = 0 and is_user = 0
134148258c6bSjp  * how     - mapping type if stat = 0
134248258c6bSjp  *
134348258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
134448258c6bSjp  */
134548258c6bSjp idmap_stat
134648258c6bSjp idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
134748258c6bSjp 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
1348cd37da74Snw {
1349c5c4113dSnw 	idmap_retcode	retcode;
1350651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1351c5c4113dSnw 
1352c5c4113dSnw 	/* sanity checks */
1353c5c4113dSnw 	if (gh == NULL)
1354c5c4113dSnw 		return (IDMAP_ERR_ARG);
1355c5c4113dSnw 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
1356c5c4113dSnw 		return (IDMAP_ERR_ARG);
1357c5c4113dSnw 
1358*3ee87bcaSJulian Pullen 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1359*3ee87bcaSJulian Pullen 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1360*3ee87bcaSJulian Pullen 		retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid,
1361*3ee87bcaSJulian Pullen 		    is_user);
1362*3ee87bcaSJulian Pullen 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1363*3ee87bcaSJulian Pullen 			*stat = retcode;
1364*3ee87bcaSJulian Pullen 			return (retcode);
1365*3ee87bcaSJulian Pullen 		}
1366*3ee87bcaSJulian Pullen 	}
1367*3ee87bcaSJulian Pullen 
1368c5c4113dSnw 	/* Extend the request array and the return list */
1369c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1370c5c4113dSnw 		goto errout;
1371c5c4113dSnw 
1372c5c4113dSnw 	/* Setup the request */
1373c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1374c5c4113dSnw 	mapping->flag = flag;
1375c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1376c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1377c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1378c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1379c5c4113dSnw 		goto errout;
1380c5c4113dSnw 	}
1381c5c4113dSnw 	mapping->id2.idtype = IDMAP_POSIXID;
1382c5c4113dSnw 
1383c5c4113dSnw 	/* Setup pointers for the result */
1384c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
1385c5c4113dSnw 	gh->retlist[gh->next].uid = pid;
1386c5c4113dSnw 	gh->retlist[gh->next].gid = pid;
1387c5c4113dSnw 	gh->retlist[gh->next].is_user = is_user;
1388c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
138948258c6bSjp 	gh->retlist[gh->next].info = info;
1390*3ee87bcaSJulian Pullen 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
1391c5c4113dSnw 
1392c5c4113dSnw 	gh->next++;
1393c5c4113dSnw 	return (IDMAP_SUCCESS);
1394c5c4113dSnw 
1395c5c4113dSnw errout:
1396651c0131Sbaban 	if (mapping)
1397651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1398c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1399c5c4113dSnw 	return (retcode);
1400c5c4113dSnw }
1401c5c4113dSnw 
1402c5c4113dSnw 
1403c5c4113dSnw /*
1404c5c4113dSnw  * Given UID, get SID
1405c5c4113dSnw  *
1406c5c4113dSnw  * Input:
1407c5c4113dSnw  * uid  - POSIX UID
1408c5c4113dSnw  * flag - flag
1409c5c4113dSnw  *
1410c5c4113dSnw  * Output:
1411c5c4113dSnw  * stat - status of the get request
1412c5c4113dSnw  * sid  - SID prefix (if stat == 0)
1413c5c4113dSnw  * rid  - rid
1414c5c4113dSnw  *
1415c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1416c5c4113dSnw  */
1417c5c4113dSnw idmap_stat
1418c5c4113dSnw idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
1419cd37da74Snw 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
1420cd37da74Snw {
142148258c6bSjp 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
142248258c6bSjp 	    NULL, stat));
142348258c6bSjp }
142448258c6bSjp 
142548258c6bSjp 
142648258c6bSjp /*
142748258c6bSjp  * Given UID, get SID
142848258c6bSjp  *
142948258c6bSjp  * Input:
143048258c6bSjp  * uid  - POSIX UID
143148258c6bSjp  * flag - flag
143248258c6bSjp  *
143348258c6bSjp  * Output:
143448258c6bSjp  * stat - status of the get request
143548258c6bSjp  * sid  - SID prefix (if stat == 0)
143648258c6bSjp  * rid  - rid
143748258c6bSjp  * how  - mapping type if stat = 0
143848258c6bSjp  *
143948258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
144048258c6bSjp  */
144148258c6bSjp idmap_stat
144248258c6bSjp idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
144348258c6bSjp 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
144448258c6bSjp {
1445c5c4113dSnw 
1446c5c4113dSnw 	idmap_retcode	retcode;
1447651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1448c5c4113dSnw 
1449c5c4113dSnw 	/* sanity checks */
1450c5c4113dSnw 	if (gh == NULL)
1451c5c4113dSnw 		return (IDMAP_ERR_ARG);
1452c5c4113dSnw 	if (sidprefix == NULL)
1453c5c4113dSnw 		return (IDMAP_ERR_ARG);
1454c5c4113dSnw 
1455*3ee87bcaSJulian Pullen 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1456*3ee87bcaSJulian Pullen 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1457*3ee87bcaSJulian Pullen 		retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid);
1458*3ee87bcaSJulian Pullen 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1459*3ee87bcaSJulian Pullen 			*stat = retcode;
1460*3ee87bcaSJulian Pullen 			return (retcode);
1461*3ee87bcaSJulian Pullen 		}
1462*3ee87bcaSJulian Pullen 	}
1463*3ee87bcaSJulian Pullen 
1464c5c4113dSnw 	/* Extend the request array and the return list */
1465c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1466c5c4113dSnw 		goto errout;
1467c5c4113dSnw 
1468c5c4113dSnw 	/* Setup the request */
1469c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1470c5c4113dSnw 	mapping->flag = flag;
1471c5c4113dSnw 	mapping->id1.idtype = IDMAP_UID;
1472c5c4113dSnw 	mapping->id1.idmap_id_u.uid = uid;
1473c5c4113dSnw 	mapping->id2.idtype = IDMAP_SID;
1474c5c4113dSnw 
1475c5c4113dSnw 	/* Setup pointers for the result */
1476c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_SID;
1477c5c4113dSnw 	gh->retlist[gh->next].sidprefix = sidprefix;
1478c5c4113dSnw 	gh->retlist[gh->next].rid = rid;
1479c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
148048258c6bSjp 	gh->retlist[gh->next].info = info;
1481*3ee87bcaSJulian Pullen 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
1482c5c4113dSnw 
1483c5c4113dSnw 	gh->next++;
1484c5c4113dSnw 	return (IDMAP_SUCCESS);
1485c5c4113dSnw 
1486c5c4113dSnw errout:
1487651c0131Sbaban 	if (mapping)
1488651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1489c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1490c5c4113dSnw 	return (retcode);
1491c5c4113dSnw }
1492c5c4113dSnw 
1493c5c4113dSnw 
1494c5c4113dSnw /*
1495c5c4113dSnw  * Given GID, get SID
1496c5c4113dSnw  *
1497c5c4113dSnw  * Input:
1498c5c4113dSnw  * gid  - POSIX GID
1499c5c4113dSnw  * flag - flag
1500c5c4113dSnw  *
1501c5c4113dSnw  * Output:
1502c5c4113dSnw  * stat       - status of the get request
1503c5c4113dSnw  * sidprefix  - SID prefix (if stat == 0)
1504c5c4113dSnw  * rid        - rid
1505c5c4113dSnw  *
1506c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1507c5c4113dSnw  */
1508c5c4113dSnw idmap_stat
1509c5c4113dSnw idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
1510cd37da74Snw 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
1511cd37da74Snw {
151248258c6bSjp 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
151348258c6bSjp 	    NULL, stat));
151448258c6bSjp }
151548258c6bSjp 
151648258c6bSjp 
151748258c6bSjp /*
151848258c6bSjp  * Given GID, get SID
151948258c6bSjp  *
152048258c6bSjp  * Input:
152148258c6bSjp  * gid  - POSIX GID
152248258c6bSjp  * flag - flag
152348258c6bSjp  *
152448258c6bSjp  * Output:
152548258c6bSjp  * stat       - status of the get request
152648258c6bSjp  * sidprefix  - SID prefix (if stat == 0)
152748258c6bSjp  * rid        - rid
152848258c6bSjp  * how        - mapping type if stat = 0
152948258c6bSjp  *
153048258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
153148258c6bSjp  */
153248258c6bSjp idmap_stat
153348258c6bSjp idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
153448258c6bSjp 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
153548258c6bSjp {
1536c5c4113dSnw 
1537c5c4113dSnw 	idmap_retcode	retcode;
1538651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1539c5c4113dSnw 
1540c5c4113dSnw 	/* sanity checks */
1541c5c4113dSnw 	if (gh == NULL)
1542c5c4113dSnw 		return (IDMAP_ERR_ARG);
1543c5c4113dSnw 	if (sidprefix == NULL)
1544c5c4113dSnw 		return (IDMAP_ERR_ARG);
1545c5c4113dSnw 
1546*3ee87bcaSJulian Pullen 	if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
1547*3ee87bcaSJulian Pullen 	    !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
1548*3ee87bcaSJulian Pullen 		retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid);
1549*3ee87bcaSJulian Pullen 		if (retcode  == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) {
1550*3ee87bcaSJulian Pullen 			*stat = retcode;
1551*3ee87bcaSJulian Pullen 			return (retcode);
1552*3ee87bcaSJulian Pullen 		}
1553*3ee87bcaSJulian Pullen 	}
1554*3ee87bcaSJulian Pullen 
1555c5c4113dSnw 	/* Extend the request array and the return list */
1556c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1557c5c4113dSnw 		goto errout;
1558c5c4113dSnw 
1559c5c4113dSnw 	/* Setup the request */
1560c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1561c5c4113dSnw 	mapping->flag = flag;
1562c5c4113dSnw 	mapping->id1.idtype = IDMAP_GID;
1563c5c4113dSnw 	mapping->id1.idmap_id_u.gid = gid;
1564c5c4113dSnw 	mapping->id2.idtype = IDMAP_SID;
1565c5c4113dSnw 
1566c5c4113dSnw 	/* Setup pointers for the result */
1567c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_SID;
1568c5c4113dSnw 	gh->retlist[gh->next].sidprefix = sidprefix;
1569c5c4113dSnw 	gh->retlist[gh->next].rid = rid;
1570c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
157148258c6bSjp 	gh->retlist[gh->next].info = info;
1572*3ee87bcaSJulian Pullen 	gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE;
1573c5c4113dSnw 
1574c5c4113dSnw 	gh->next++;
1575c5c4113dSnw 	return (IDMAP_SUCCESS);
1576c5c4113dSnw 
1577c5c4113dSnw errout:
1578651c0131Sbaban 	if (mapping)
1579651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1580c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1581c5c4113dSnw 	return (retcode);
1582c5c4113dSnw }
1583c5c4113dSnw 
1584c5c4113dSnw 
1585c5c4113dSnw /*
1586c5c4113dSnw  * Process the batched "get mapping" requests. The results (i.e.
1587c5c4113dSnw  * status and identity) will be available in the data areas
1588c5c4113dSnw  * provided by individual requests.
1589c5c4113dSnw  */
1590c5c4113dSnw idmap_stat
1591cd37da74Snw idmap_get_mappings(idmap_get_handle_t *gh)
1592cd37da74Snw {
1593c5c4113dSnw 	CLIENT		*clnt;
1594c5c4113dSnw 	enum clnt_stat	clntstat;
1595c5c4113dSnw 	idmap_retcode	retcode;
1596c5c4113dSnw 	idmap_ids_res	res;
1597*3ee87bcaSJulian Pullen 	idmap_id	*res_id;
1598c5c4113dSnw 	int		i;
1599*3ee87bcaSJulian Pullen 	idmap_id	*req_id;
1600*3ee87bcaSJulian Pullen 	int		direction;
1601c5c4113dSnw 
1602c5c4113dSnw 	if (gh == NULL) {
1603c5c4113dSnw 		errno = EINVAL;
1604c5c4113dSnw 		return (IDMAP_ERR_ARG);
1605c5c4113dSnw 	}
1606c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
1607c5c4113dSnw 
1608c5c4113dSnw 	(void) memset(&res, 0, sizeof (idmap_ids_res));
1609c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
1610cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping_batch,
1611cd37da74Snw 	    (caddr_t)&gh->batch,
1612cd37da74Snw 	    (xdrproc_t)xdr_idmap_ids_res,
1613cd37da74Snw 	    (caddr_t)&res,
1614cd37da74Snw 	    TIMEOUT);
1615c5c4113dSnw 	if (clntstat != RPC_SUCCESS) {
1616651c0131Sbaban 		retcode = _idmap_rpc2stat(clnt);
1617c5c4113dSnw 		goto out;
1618c5c4113dSnw 	}
1619c5c4113dSnw 	if (res.retcode != IDMAP_SUCCESS) {
1620c5c4113dSnw 		retcode = res.retcode;
1621c5c4113dSnw 		goto out;
1622c5c4113dSnw 	}
1623c5c4113dSnw 	for (i = 0; i < gh->next; i++) {
1624c5c4113dSnw 		if (i >= res.ids.ids_len) {
1625c5c4113dSnw 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1626c5c4113dSnw 			continue;
1627c5c4113dSnw 		}
1628c5c4113dSnw 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
1629*3ee87bcaSJulian Pullen 		res_id = &res.ids.ids_val[i].id;
1630*3ee87bcaSJulian Pullen 		direction = res.ids.ids_val[i].direction;
1631*3ee87bcaSJulian Pullen 		req_id = &gh->batch.idmap_mapping_batch_val[i].id1;
1632*3ee87bcaSJulian Pullen 		switch (res_id->idtype) {
1633c5c4113dSnw 		case IDMAP_UID:
1634c5c4113dSnw 			if (gh->retlist[i].uid)
1635*3ee87bcaSJulian Pullen 				*gh->retlist[i].uid = res_id->idmap_id_u.uid;
1636c5c4113dSnw 			if (gh->retlist[i].is_user)
1637c5c4113dSnw 				*gh->retlist[i].is_user = 1;
1638*3ee87bcaSJulian Pullen 
1639*3ee87bcaSJulian Pullen 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1640*3ee87bcaSJulian Pullen 			    gh->retlist[i].cache_res) {
1641*3ee87bcaSJulian Pullen 				if (gh->retlist[i].is_user != NULL)
1642*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2pid(
1643*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.prefix,
1644*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.rid,
1645*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.uid, 1,
1646*3ee87bcaSJulian Pullen 					    direction);
1647*3ee87bcaSJulian Pullen 				else
1648*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2uid(
1649*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.prefix,
1650*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.rid,
1651*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.uid,
1652*3ee87bcaSJulian Pullen 					    direction);
1653*3ee87bcaSJulian Pullen 			}
1654c5c4113dSnw 			break;
1655*3ee87bcaSJulian Pullen 
1656c5c4113dSnw 		case IDMAP_GID:
1657c5c4113dSnw 			if (gh->retlist[i].gid)
1658*3ee87bcaSJulian Pullen 				*gh->retlist[i].gid = res_id->idmap_id_u.gid;
1659c5c4113dSnw 			if (gh->retlist[i].is_user)
1660c5c4113dSnw 				*gh->retlist[i].is_user = 0;
1661*3ee87bcaSJulian Pullen 
1662*3ee87bcaSJulian Pullen 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1663*3ee87bcaSJulian Pullen 			    gh->retlist[i].cache_res) {
1664*3ee87bcaSJulian Pullen 				if (gh->retlist[i].is_user != NULL)
1665*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2pid(
1666*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.prefix,
1667*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.rid,
1668*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.gid, 0,
1669*3ee87bcaSJulian Pullen 					    direction);
1670*3ee87bcaSJulian Pullen 				else
1671*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2gid(
1672*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.prefix,
1673*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.sid.rid,
1674*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.gid,
1675*3ee87bcaSJulian Pullen 					    direction);
1676*3ee87bcaSJulian Pullen 			}
1677c5c4113dSnw 			break;
1678*3ee87bcaSJulian Pullen 
167962c60062Sbaban 		case IDMAP_POSIXID:
168062c60062Sbaban 			if (gh->retlist[i].uid)
168162c60062Sbaban 				*gh->retlist[i].uid = 60001;
168262c60062Sbaban 			if (gh->retlist[i].is_user)
168362c60062Sbaban 				*gh->retlist[i].is_user = -1;
168462c60062Sbaban 			break;
1685*3ee87bcaSJulian Pullen 
1686c5c4113dSnw 		case IDMAP_SID:
1687cd37da74Snw 		case IDMAP_USID:
1688cd37da74Snw 		case IDMAP_GSID:
1689c5c4113dSnw 			if (gh->retlist[i].rid)
1690*3ee87bcaSJulian Pullen 				*gh->retlist[i].rid =
1691*3ee87bcaSJulian Pullen 				    res_id->idmap_id_u.sid.rid;
1692c5c4113dSnw 			if (gh->retlist[i].sidprefix) {
1693*3ee87bcaSJulian Pullen 				if (res_id->idmap_id_u.sid.prefix == NULL ||
1694*3ee87bcaSJulian Pullen 				    *res_id->idmap_id_u.sid.prefix == '\0') {
1695c5c4113dSnw 					*gh->retlist[i].sidprefix = NULL;
1696c5c4113dSnw 					break;
1697c5c4113dSnw 				}
1698c5c4113dSnw 				*gh->retlist[i].sidprefix =
1699*3ee87bcaSJulian Pullen 				    strdup(res_id->idmap_id_u.sid.prefix);
1700c5c4113dSnw 				if (*gh->retlist[i].sidprefix == NULL)
1701c5c4113dSnw 					*gh->retlist[i].stat =
1702cd37da74Snw 					    IDMAP_ERR_MEMORY;
1703c5c4113dSnw 			}
1704*3ee87bcaSJulian Pullen 			if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS &&
1705*3ee87bcaSJulian Pullen 			    gh->retlist[i].cache_res) {
1706*3ee87bcaSJulian Pullen 				if (req_id->idtype == IDMAP_UID)
1707*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2uid(
1708*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.sid.prefix,
1709*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.sid.rid,
1710*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.uid,
1711*3ee87bcaSJulian Pullen 					    direction);
1712*3ee87bcaSJulian Pullen 				else /* req_id->idtype == IDMAP_GID */
1713*3ee87bcaSJulian Pullen 					idmap_cache_add_sid2gid(
1714*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.sid.prefix,
1715*3ee87bcaSJulian Pullen 					    res_id->idmap_id_u.sid.rid,
1716*3ee87bcaSJulian Pullen 					    req_id->idmap_id_u.gid,
1717*3ee87bcaSJulian Pullen 					    direction);
1718*3ee87bcaSJulian Pullen 			}
1719c5c4113dSnw 			break;
1720*3ee87bcaSJulian Pullen 
1721c5c4113dSnw 		case IDMAP_NONE:
1722c5c4113dSnw 			break;
1723*3ee87bcaSJulian Pullen 
1724c5c4113dSnw 		default:
1725c5c4113dSnw 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1726c5c4113dSnw 			break;
1727c5c4113dSnw 		}
172848258c6bSjp 		if (gh->retlist[i].info != NULL)
172948258c6bSjp 			(void) idmap_info_cpy(gh->retlist[i].info,
173048258c6bSjp 			    &res.ids.ids_val[i].info);
1731c5c4113dSnw 	}
1732c5c4113dSnw 	retcode = IDMAP_SUCCESS;
1733c5c4113dSnw 
1734c5c4113dSnw out:
1735651c0131Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
1736c5c4113dSnw 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
1737c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1738c5c4113dSnw 	return (retcode);
1739c5c4113dSnw }
1740c5c4113dSnw 
1741c5c4113dSnw 
1742c5c4113dSnw /*
1743c5c4113dSnw  * Destroy the "get mapping" handle
1744c5c4113dSnw  */
1745c5c4113dSnw void
1746cd37da74Snw idmap_get_destroy(idmap_get_handle_t *gh)
1747cd37da74Snw {
1748c5c4113dSnw 	if (gh == NULL)
1749c5c4113dSnw 		return;
1750c5c4113dSnw 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1751c5c4113dSnw 	if (gh->retlist)
1752c5c4113dSnw 		free(gh->retlist);
1753c5c4113dSnw 	free(gh);
1754c5c4113dSnw }
1755c5c4113dSnw 
1756c5c4113dSnw 
1757c5c4113dSnw /*
1758c5c4113dSnw  * Get windows to unix mapping
1759c5c4113dSnw  */
1760c5c4113dSnw idmap_stat
1761c5c4113dSnw idmap_get_w2u_mapping(idmap_handle_t *handle,
1762c5c4113dSnw 		const char *sidprefix, idmap_rid_t *rid,
1763c5c4113dSnw 		const char *winname, const char *windomain,
1764cd37da74Snw 		int flag, int *is_user, int *is_wuser,
176548258c6bSjp 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
1766cd37da74Snw {
1767c5c4113dSnw 	CLIENT			*clnt;
1768c5c4113dSnw 	enum clnt_stat		clntstat;
1769c5c4113dSnw 	idmap_mapping		request, *mapping;
1770c5c4113dSnw 	idmap_mappings_res	result;
1771c5c4113dSnw 	idmap_retcode		retcode, rc;
1772c5c4113dSnw 
1773c5c4113dSnw 	if (handle == NULL) {
1774c5c4113dSnw 		errno = EINVAL;
1775c5c4113dSnw 		return (IDMAP_ERR_ARG);
1776c5c4113dSnw 	}
1777c5c4113dSnw 
1778c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1779c5c4113dSnw 
1780c5c4113dSnw 	(void) memset(&request, 0, sizeof (request));
1781c5c4113dSnw 	(void) memset(&result, 0, sizeof (result));
1782c5c4113dSnw 
1783c5c4113dSnw 	if (pid)
1784c5c4113dSnw 		*pid = UINT32_MAX;
1785c5c4113dSnw 	if (unixname)
1786c5c4113dSnw 		*unixname = NULL;
1787c5c4113dSnw 	if (direction)
1788651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
1789c5c4113dSnw 
1790c5c4113dSnw 	request.flag = flag;
1791c5c4113dSnw 	request.id1.idtype = IDMAP_SID;
1792c5c4113dSnw 	if (sidprefix && rid) {
1793c5c4113dSnw 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
1794c5c4113dSnw 		request.id1.idmap_id_u.sid.rid = *rid;
1795c5c4113dSnw 	} else if (winname) {
17968e228215Sdm 		retcode = idmap_strdupnull(&request.id1name, winname);
1797c5a946baSbaban 		if (retcode != IDMAP_SUCCESS)
1798c5c4113dSnw 			goto out;
17998e228215Sdm 
18008e228215Sdm 		retcode = idmap_strdupnull(&request.id1domain, windomain);
1801c5a946baSbaban 		if (retcode != IDMAP_SUCCESS)
18028e228215Sdm 			goto out;
18038e228215Sdm 
1804c5c4113dSnw 		request.id1.idmap_id_u.sid.prefix = NULL;
1805c5c4113dSnw 	} else {
1806c5c4113dSnw 		errno = EINVAL;
1807c5c4113dSnw 		return (IDMAP_ERR_ARG);
1808c5c4113dSnw 	}
1809c5c4113dSnw 
1810cd37da74Snw 	if (*is_user == 1)
1811c5c4113dSnw 		request.id2.idtype = IDMAP_UID;
1812c5c4113dSnw 	else if (*is_user == 0)
1813c5c4113dSnw 		request.id2.idtype = IDMAP_GID;
1814c5c4113dSnw 	else
1815c5c4113dSnw 		request.id2.idtype = IDMAP_POSIXID;
1816c5c4113dSnw 
1817cd37da74Snw 	if (*is_wuser == 1)
1818cd37da74Snw 		request.id1.idtype = IDMAP_USID;
1819cd37da74Snw 	else if (*is_wuser == 0)
1820cd37da74Snw 		request.id1.idtype = IDMAP_GSID;
1821cd37da74Snw 	else
1822cd37da74Snw 		request.id1.idtype = IDMAP_SID;
1823cd37da74Snw 
1824c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1825cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1826cd37da74Snw 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1827cd37da74Snw 	    TIMEOUT);
1828c5c4113dSnw 
1829651c0131Sbaban 	if (clntstat != RPC_SUCCESS)
1830651c0131Sbaban 		return (_idmap_rpc2stat(clnt));
1831c5c4113dSnw 
1832c5c4113dSnw 	retcode = result.retcode;
1833c5c4113dSnw 
1834c5c4113dSnw 	if ((mapping = result.mappings.mappings_val) == NULL) {
1835c5c4113dSnw 		if (retcode == IDMAP_SUCCESS)
1836c5c4113dSnw 			retcode = IDMAP_ERR_NORESULT;
1837c5c4113dSnw 		goto out;
1838c5c4113dSnw 	}
1839c5c4113dSnw 
184062c60062Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
1841cd37da74Snw 		*is_user = 1;
184262c60062Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
1843cd37da74Snw 		*is_user = 0;
184462c60062Sbaban 	} else {
184562c60062Sbaban 		goto out;
184662c60062Sbaban 	}
1847cd37da74Snw 
1848cd37da74Snw 	if (mapping->id1.idtype == IDMAP_USID) {
1849cd37da74Snw 		*is_wuser = 1;
1850cd37da74Snw 	} else if (mapping->id1.idtype == IDMAP_GSID) {
1851cd37da74Snw 		*is_wuser = 0;
1852cd37da74Snw 	} else {
1853cd37da74Snw 		goto out;
1854cd37da74Snw 	}
1855cd37da74Snw 
1856c5c4113dSnw 	if (direction)
1857c5c4113dSnw 		*direction = mapping->direction;
1858c5c4113dSnw 	if (pid)
1859c5c4113dSnw 		*pid = mapping->id2.idmap_id_u.uid;
18608e228215Sdm 
18618e228215Sdm 	rc = idmap_strdupnull(unixname, mapping->id2name);
18628e228215Sdm 	if (rc != IDMAP_SUCCESS)
18638e228215Sdm 		retcode = rc;
1864c5c4113dSnw 
186548258c6bSjp 	rc = idmap_info_cpy(info, &mapping->info);
186648258c6bSjp 	if (rc != IDMAP_SUCCESS)
186748258c6bSjp 		retcode = rc;
186848258c6bSjp 
1869c5c4113dSnw out:
1870f7b4b2feSjp 	if (request.id1name != NULL)
1871f7b4b2feSjp 		free(request.id1name);
1872f7b4b2feSjp 	if (request.id1domain != NULL)
1873f7b4b2feSjp 		free(request.id1domain);
1874c5c4113dSnw 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
1875c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
1876c5c4113dSnw 		errno = idmap_stat2errno(retcode);
1877c5c4113dSnw 	return (retcode);
1878c5c4113dSnw }
1879c5c4113dSnw 
1880c5c4113dSnw 
1881c5c4113dSnw /*
1882c5c4113dSnw  * Get unix to windows mapping
1883c5c4113dSnw  */
1884c5c4113dSnw idmap_stat
1885c5c4113dSnw idmap_get_u2w_mapping(idmap_handle_t *handle,
1886c5c4113dSnw 		uid_t *pid, const char *unixname,
1887cd37da74Snw 		int flag, int is_user, int *is_wuser,
1888c5c4113dSnw 		char **sidprefix, idmap_rid_t *rid,
1889c5c4113dSnw 		char **winname, char **windomain,
189048258c6bSjp 		int *direction, idmap_info *info)
1891cd37da74Snw {
1892c5c4113dSnw 	CLIENT			*clnt;
1893c5c4113dSnw 	enum clnt_stat		clntstat;
1894c5c4113dSnw 	idmap_mapping		request, *mapping;
1895c5c4113dSnw 	idmap_mappings_res	result;
1896c5c4113dSnw 	idmap_retcode		retcode, rc;
1897c5c4113dSnw 
1898c5c4113dSnw 	if (handle == NULL) {
1899c5c4113dSnw 		errno = EINVAL;
1900c5c4113dSnw 		return (IDMAP_ERR_ARG);
1901c5c4113dSnw 	}
1902c5c4113dSnw 
1903c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1904c5c4113dSnw 
1905c5c4113dSnw 	if (sidprefix)
1906c5c4113dSnw 		*sidprefix = NULL;
1907c5c4113dSnw 	if (winname)
1908c5c4113dSnw 		*winname = NULL;
1909c5c4113dSnw 	if (windomain)
1910c5c4113dSnw 		*windomain = NULL;
1911c5c4113dSnw 	if (rid)
1912c5c4113dSnw 		*rid = UINT32_MAX;
1913c5c4113dSnw 	if (direction)
1914651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
1915c5c4113dSnw 
1916c5c4113dSnw 	(void) memset(&request, 0, sizeof (request));
1917c5c4113dSnw 	(void) memset(&result, 0, sizeof (result));
1918c5c4113dSnw 
1919c5c4113dSnw 	request.flag = flag;
1920c5c4113dSnw 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
1921c5c4113dSnw 
1922c5c4113dSnw 	if (pid && *pid != UINT32_MAX) {
1923c5c4113dSnw 		request.id1.idmap_id_u.uid = *pid;
1924c5c4113dSnw 	} else if (unixname) {
19258e228215Sdm 		request.id1name = (char *)unixname;
1926c5c4113dSnw 		request.id1.idmap_id_u.uid = UINT32_MAX;
1927c5c4113dSnw 	} else {
1928c5c4113dSnw 		errno = EINVAL;
1929c5c4113dSnw 		return (IDMAP_ERR_ARG);
1930c5c4113dSnw 	}
1931c5c4113dSnw 
1932cd37da74Snw 	if (is_wuser == NULL)
1933cd37da74Snw 		request.id2.idtype = IDMAP_SID;
1934cd37da74Snw 	else if (*is_wuser == -1)
1935cd37da74Snw 		request.id2.idtype = IDMAP_SID;
1936cd37da74Snw 	else if (*is_wuser == 0)
1937cd37da74Snw 		request.id2.idtype = IDMAP_GSID;
1938cd37da74Snw 	else if (*is_wuser == 1)
1939cd37da74Snw 		request.id2.idtype = IDMAP_USID;
1940c5c4113dSnw 
1941c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1942cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1943cd37da74Snw 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1944cd37da74Snw 	    TIMEOUT);
1945c5c4113dSnw 
1946651c0131Sbaban 	if (clntstat != RPC_SUCCESS)
1947651c0131Sbaban 		return (_idmap_rpc2stat(clnt));
1948c5c4113dSnw 
1949c5c4113dSnw 	retcode = result.retcode;
1950c5c4113dSnw 
1951c5c4113dSnw 	if ((mapping = result.mappings.mappings_val) == NULL) {
1952c5c4113dSnw 		if (retcode == IDMAP_SUCCESS)
1953c5c4113dSnw 			retcode = IDMAP_ERR_NORESULT;
1954c5c4113dSnw 		goto out;
1955c5c4113dSnw 	}
1956c5c4113dSnw 
1957cd37da74Snw 	if (direction != NULL)
1958c5c4113dSnw 		*direction = mapping->direction;
1959cd37da74Snw 
196048258c6bSjp 	if (is_wuser != NULL) {
196148258c6bSjp 		if (mapping->id2.idtype == IDMAP_USID)
196248258c6bSjp 			*is_wuser = 1;
196348258c6bSjp 		else if (mapping->id2.idtype == IDMAP_GSID)
196448258c6bSjp 			*is_wuser = 0;
196548258c6bSjp 		else
196648258c6bSjp 			*is_wuser = -1;
196748258c6bSjp 	}
1968cd37da74Snw 
19698edda628Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
19708edda628Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
1971c5c4113dSnw 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
1972c5c4113dSnw 		if (*sidprefix == NULL) {
1973c5c4113dSnw 			retcode = IDMAP_ERR_MEMORY;
1974c5c4113dSnw 			goto errout;
1975c5c4113dSnw 		}
1976c5c4113dSnw 	}
1977c5c4113dSnw 	if (rid)
1978c5c4113dSnw 		*rid = mapping->id2.idmap_id_u.sid.rid;
19798e228215Sdm 
19808e228215Sdm 	rc = idmap_strdupnull(winname, mapping->id2name);
19818e228215Sdm 	if (rc != IDMAP_SUCCESS)
19828e228215Sdm 		retcode = rc;
19838e228215Sdm 
19848e228215Sdm 	rc = idmap_strdupnull(windomain, mapping->id2domain);
19858e228215Sdm 	if (rc != IDMAP_SUCCESS)
19868e228215Sdm 		retcode = rc;
1987c5c4113dSnw 
198848258c6bSjp 	rc = idmap_info_cpy(info, &mapping->info);
198948258c6bSjp 	if (rc != IDMAP_SUCCESS)
199048258c6bSjp 		retcode = rc;
199148258c6bSjp 
1992c5c4113dSnw 	goto out;
1993c5c4113dSnw 
1994c5c4113dSnw errout:
1995c5c4113dSnw 	if (sidprefix && *sidprefix) {
1996c5c4113dSnw 		free(*sidprefix);
1997c5c4113dSnw 		*sidprefix = NULL;
1998c5c4113dSnw 	}
1999c5c4113dSnw 	if (winname && *winname) {
2000c5c4113dSnw 		free(*winname);
2001c5c4113dSnw 		*winname = NULL;
2002c5c4113dSnw 	}
2003c5c4113dSnw 	if (windomain && *windomain) {
2004c5c4113dSnw 		free(*windomain);
2005c5c4113dSnw 		*windomain = NULL;
2006c5c4113dSnw 	}
2007c5c4113dSnw 
2008c5c4113dSnw out:
2009c5c4113dSnw 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
2010c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
2011c5c4113dSnw 		errno = idmap_stat2errno(retcode);
2012c5c4113dSnw 	return (retcode);
2013c5c4113dSnw }
2014c5c4113dSnw 
2015c5c4113dSnw 
2016c5c4113dSnw 
2017c5c4113dSnw #define	gettext(s)	s
2018c5c4113dSnw static stat_table_t stattable[] = {
2019c5c4113dSnw 	{IDMAP_SUCCESS, gettext("Success"), 0},
2020c5c4113dSnw 	{IDMAP_NEXT, gettext("More results available"), 0},
2021c5c4113dSnw 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
2022c5c4113dSnw 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
2023c5c4113dSnw 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
2024c5c4113dSnw 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
2025c5c4113dSnw 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
2026c5c4113dSnw 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
2027651c0131Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
2028c5c4113dSnw 	{IDMAP_ERR_W2U_NAMERULE,
2029c5c4113dSnw 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
2030c5c4113dSnw 	{IDMAP_ERR_U2W_NAMERULE,
2031c5c4113dSnw 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
2032c5c4113dSnw 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
2033c5c4113dSnw 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
2034c5c4113dSnw 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
2035c5c4113dSnw 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
2036c5c4113dSnw 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
2037651c0131Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
2038c5c4113dSnw 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
2039c5c4113dSnw 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
2040651c0131Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
20418edda628Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
2042c5c4113dSnw 	{IDMAP_ERR_NOMAPPING,
2043c5c4113dSnw 		gettext("Mapping not found or inhibited"), EINVAL},
2044c5c4113dSnw 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
2045c5c4113dSnw 		gettext("New mapping needs to be created"), EINVAL},
2046c5c4113dSnw 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
2047c5c4113dSnw 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
2048c5c4113dSnw 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
2049c5c4113dSnw 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
2050c5c4113dSnw 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
2051c5c4113dSnw 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
2052c5c4113dSnw 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
2053c5c4113dSnw 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
2054c5c4113dSnw 		gettext("No mapping for well-known SID"), EINVAL},
2055c5c4113dSnw 	{IDMAP_ERR_RETRIABLE_NET_ERR,
205662c60062Sbaban 		gettext("Windows lookup failed"), EINVAL},
205762c60062Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
205862c60062Sbaban 		gettext("Duplicate rule or conflicts with an existing "
205962c60062Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
206062c60062Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
206162c60062Sbaban 		gettext("Duplicate rule or conflicts with an existing "
206262c60062Sbaban 		"Unix to Windows name-based rule"), EINVAL},
20630dcc7149Snw 	{IDMAP_ERR_BAD_UTF8,
20640dcc7149Snw 		gettext("Invalid or illegal UTF-8 sequence found in "
20650dcc7149Snw 		"a given Windows entity name or domain name"), EINVAL},
206648258c6bSjp 	{IDMAP_ERR_NONEGENERATED,
206748258c6bSjp 		gettext("Mapping not found and none created (see -c option)"),
206848258c6bSjp 		EINVAL},
2069479ac375Sdm 	{IDMAP_ERR_PROP_UNKNOWN,
2070479ac375Sdm 		gettext("Undefined property"),
2071479ac375Sdm 		EINVAL},
2072479ac375Sdm 	{IDMAP_ERR_NS_LDAP_CFG,
2073479ac375Sdm 		gettext("Native LDAP configuration error"), EINVAL},
2074479ac375Sdm 	{IDMAP_ERR_NS_LDAP_PARTIAL,
2075479ac375Sdm 		gettext("Partial result from Native LDAP"), EINVAL},
2076479ac375Sdm 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
2077479ac375Sdm 		gettext("Native LDAP operation failed"), EINVAL},
2078479ac375Sdm 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
2079479ac375Sdm 		gettext("Improper winname form found in Native LDAP"), EINVAL},
2080c5c4113dSnw 	{-1, NULL, 0}
2081c5c4113dSnw };
2082c5c4113dSnw #undef	gettext
2083c5c4113dSnw 
2084c5c4113dSnw 
2085c5c4113dSnw /*
2086c5c4113dSnw  * Get description of status code
2087c5c4113dSnw  *
2088c5c4113dSnw  * Input:
2089c5c4113dSnw  * status - Status code returned by libidmap API call
2090c5c4113dSnw  *
2091c5c4113dSnw  * Return Value:
2092c5c4113dSnw  * human-readable localized description of idmap_stat
2093c5c4113dSnw  */
2094c5c4113dSnw /* ARGSUSED */
2095c5c4113dSnw const char *
2096cd37da74Snw idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
2097cd37da74Snw {
2098c5c4113dSnw 	int i;
2099c5c4113dSnw 
2100c5c4113dSnw 	for (i = 0; stattable[i].msg; i++) {
2101c5c4113dSnw 		if (stattable[i].retcode == status)
21029581d9f4Sbaban 			return (gettext(stattable[i].msg));
2103c5c4113dSnw 	}
2104c5c4113dSnw 	return (gettext("Unknown error"));
2105c5c4113dSnw }
2106c5c4113dSnw 
2107c5c4113dSnw 
2108c5c4113dSnw static int
2109cd37da74Snw idmap_stat2errno(idmap_stat stat)
2110cd37da74Snw {
2111c5c4113dSnw 	int i;
2112c5c4113dSnw 	for (i = 0; stattable[i].msg; i++) {
2113c5c4113dSnw 		if (stattable[i].retcode == stat)
2114c5c4113dSnw 			return (stattable[i].errnum);
2115c5c4113dSnw 	}
2116c5c4113dSnw 	return (EINVAL);
2117c5c4113dSnw }
2118c5c4113dSnw 
2119c5c4113dSnw 
2120c5c4113dSnw /*
2121c5c4113dSnw  * Get status code from string
2122c5c4113dSnw  */
2123c5c4113dSnw idmap_stat
2124cd37da74Snw idmap_string2stat(const char *str)
2125cd37da74Snw {
2126c5c4113dSnw 	if (str == NULL)
2127c5c4113dSnw 		return (IDMAP_ERR_INTERNAL);
2128c5c4113dSnw 
2129c5c4113dSnw #define	return_cmp(a) \
2130c5c4113dSnw 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
2131c5c4113dSnw 		return (IDMAP_ERR_ ## a);
2132c5c4113dSnw 
2133c5c4113dSnw 	return_cmp(OTHER);
2134c5c4113dSnw 	return_cmp(INTERNAL);
2135c5c4113dSnw 	return_cmp(MEMORY);
2136c5c4113dSnw 	return_cmp(NORESULT);
2137c5c4113dSnw 	return_cmp(NOTUSER);
2138c5c4113dSnw 	return_cmp(NOTGROUP);
2139c5c4113dSnw 	return_cmp(NOTSUPPORTED);
2140c5c4113dSnw 	return_cmp(W2U_NAMERULE);
2141c5c4113dSnw 	return_cmp(U2W_NAMERULE);
2142c5c4113dSnw 	return_cmp(CACHE);
2143c5c4113dSnw 	return_cmp(DB);
2144c5c4113dSnw 	return_cmp(ARG);
2145c5c4113dSnw 	return_cmp(SID);
2146c5c4113dSnw 	return_cmp(IDTYPE);
2147c5c4113dSnw 	return_cmp(RPC_HANDLE);
2148c5c4113dSnw 	return_cmp(RPC);
2149c5c4113dSnw 	return_cmp(CLIENT_HANDLE);
2150c5c4113dSnw 	return_cmp(BUSY);
2151c5c4113dSnw 	return_cmp(PERMISSION_DENIED);
2152c5c4113dSnw 	return_cmp(NOMAPPING);
2153c5c4113dSnw 	return_cmp(NEW_ID_ALLOC_REQD);
2154c5c4113dSnw 	return_cmp(DOMAIN);
2155c5c4113dSnw 	return_cmp(SECURITY);
2156c5c4113dSnw 	return_cmp(NOTFOUND);
2157c5c4113dSnw 	return_cmp(DOMAIN_NOTFOUND);
2158c5c4113dSnw 	return_cmp(MEMORY);
2159c5c4113dSnw 	return_cmp(UPDATE_NOTALLOWED);
2160c5c4113dSnw 	return_cmp(CFG);
2161c5c4113dSnw 	return_cmp(CFG_CHANGE);
2162c5c4113dSnw 	return_cmp(NOTMAPPED_WELLKNOWN);
2163c5c4113dSnw 	return_cmp(RETRIABLE_NET_ERR);
216462c60062Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
216562c60062Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
2166479ac375Sdm 	return_cmp(BAD_UTF8);
2167479ac375Sdm 	return_cmp(NONEGENERATED);
2168479ac375Sdm 	return_cmp(PROP_UNKNOWN);
2169479ac375Sdm 	return_cmp(NS_LDAP_CFG);
2170479ac375Sdm 	return_cmp(NS_LDAP_PARTIAL);
2171479ac375Sdm 	return_cmp(NS_LDAP_OP_FAILED);
2172479ac375Sdm 	return_cmp(NS_LDAP_BAD_WINNAME);
2173c5c4113dSnw #undef return_cmp
2174c5c4113dSnw 
2175c5c4113dSnw 	return (IDMAP_ERR_OTHER);
2176c5c4113dSnw }
2177c5c4113dSnw 
2178c5c4113dSnw 
2179c5c4113dSnw /*
2180c5c4113dSnw  * Map the given status to one that can be returned by the protocol
2181c5c4113dSnw  */
2182c5c4113dSnw idmap_stat
2183cd37da74Snw idmap_stat4prot(idmap_stat status)
2184cd37da74Snw {
2185c5c4113dSnw 	switch (status) {
2186c5c4113dSnw 	case IDMAP_ERR_MEMORY:
2187c5c4113dSnw 	case IDMAP_ERR_CACHE:
2188c5c4113dSnw 		return (IDMAP_ERR_INTERNAL);
2189c5c4113dSnw 	}
2190c5c4113dSnw 	return (status);
2191c5c4113dSnw }
2192dd5829d1Sbaban 
2193dd5829d1Sbaban 
21948e228215Sdm /*
2195c5a946baSbaban  * This is a convenience routine which duplicates a string after
2196c5a946baSbaban  * checking for NULL pointers. This function will return success if
2197c5a946baSbaban  * either the 'to' OR 'from' pointers are NULL.
21988e228215Sdm  */
21998e228215Sdm static idmap_stat
2200cd37da74Snw idmap_strdupnull(char **to, const char *from)
2201cd37da74Snw {
2202c5a946baSbaban 	if (to == NULL)
2203c5a946baSbaban 		return (IDMAP_SUCCESS);
2204c5a946baSbaban 
22058e228215Sdm 	if (from == NULL || *from == '\0') {
22068e228215Sdm 		*to = NULL;
22078e228215Sdm 		return (IDMAP_SUCCESS);
22088e228215Sdm 	}
22098e228215Sdm 
22108e228215Sdm 	*to = strdup(from);
22118e228215Sdm 	if (*to == NULL)
22128e228215Sdm 		return (IDMAP_ERR_MEMORY);
22138e228215Sdm 	return (IDMAP_SUCCESS);
22148e228215Sdm }
22158e228215Sdm 
221648258c6bSjp 
22178e228215Sdm idmap_stat
2218cd37da74Snw idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
2219cd37da74Snw {
22208e228215Sdm 	idmap_stat retval;
22218e228215Sdm 
222248258c6bSjp 	if (to == NULL)
222348258c6bSjp 		return (IDMAP_SUCCESS);
222448258c6bSjp 
22258e228215Sdm 	(void) memcpy(to, from, sizeof (idmap_namerule));
222648258c6bSjp 	to->windomain = NULL;
222748258c6bSjp 	to->winname = NULL;
222848258c6bSjp 	to->unixname = NULL;
22298e228215Sdm 
22308e228215Sdm 	retval = idmap_strdupnull(&to->windomain, from->windomain);
22318e228215Sdm 	if (retval != IDMAP_SUCCESS)
22328e228215Sdm 		return (retval);
22338e228215Sdm 
22348e228215Sdm 	retval = idmap_strdupnull(&to->winname, from->winname);
223548258c6bSjp 	if (retval != IDMAP_SUCCESS) {
223648258c6bSjp 		free(to->windomain);
223748258c6bSjp 		to->windomain = NULL;
22388e228215Sdm 		return (retval);
223948258c6bSjp 	}
22408e228215Sdm 
22418e228215Sdm 	retval = idmap_strdupnull(&to->unixname, from->unixname);
224248258c6bSjp 	if (retval != IDMAP_SUCCESS) {
224348258c6bSjp 		free(to->windomain);
224448258c6bSjp 		to->windomain = NULL;
224548258c6bSjp 		free(to->winname);
224648258c6bSjp 		to->winname = NULL;
224748258c6bSjp 		return (retval);
224848258c6bSjp 	}
224948258c6bSjp 
225048258c6bSjp 	return (retval);
225148258c6bSjp }
225248258c6bSjp 
225348258c6bSjp 
225448258c6bSjp static
225548258c6bSjp idmap_stat
225648258c6bSjp idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
225748258c6bSjp {
225848258c6bSjp 	idmap_stat retval;
225948258c6bSjp 
226048258c6bSjp 	if (to == NULL)
226148258c6bSjp 		return (IDMAP_SUCCESS);
226248258c6bSjp 
226348258c6bSjp 	retval = idmap_strdupnull(&to->dn, from->dn);
226448258c6bSjp 	if (retval != IDMAP_SUCCESS)
226548258c6bSjp 		return (retval);
226648258c6bSjp 
226748258c6bSjp 	retval = idmap_strdupnull(&to->attr, from->attr);
226848258c6bSjp 	if (retval != IDMAP_SUCCESS) {
226948258c6bSjp 		free(to->dn);
227048258c6bSjp 		to->dn = NULL;
227148258c6bSjp 		return (retval);
227248258c6bSjp 	}
227348258c6bSjp 
227448258c6bSjp 	retval = idmap_strdupnull(&to->value, from->value);
227548258c6bSjp 	if (retval != IDMAP_SUCCESS) {
227648258c6bSjp 		free(to->dn);
227748258c6bSjp 		to->dn = NULL;
227848258c6bSjp 		free(to->attr);
227948258c6bSjp 		to->attr = NULL;
228048258c6bSjp 		return (retval);
228148258c6bSjp 	}
228248258c6bSjp 
228348258c6bSjp 	return (retval);
228448258c6bSjp }
228548258c6bSjp 
228648258c6bSjp 
228748258c6bSjp idmap_stat
228848258c6bSjp idmap_info_cpy(idmap_info *to, idmap_info *from)
228948258c6bSjp {
229048258c6bSjp 	idmap_stat retval = IDMAP_SUCCESS;
229148258c6bSjp 
229248258c6bSjp 	if (to == NULL)
229348258c6bSjp 		return (IDMAP_SUCCESS);
229448258c6bSjp 
229548258c6bSjp 	(void) memset(to, 0, sizeof (idmap_info));
229648258c6bSjp 
229748258c6bSjp 	to->src = from->src;
229848258c6bSjp 	to->how.map_type = from->how.map_type;
229948258c6bSjp 	switch (to->how.map_type) {
230048258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
230148258c6bSjp 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
230248258c6bSjp 		    &from->how.idmap_how_u.ad);
230348258c6bSjp 		break;
230448258c6bSjp 
230548258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
230648258c6bSjp 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
230748258c6bSjp 		    &from->how.idmap_how_u.nldap);
230848258c6bSjp 		break;
230948258c6bSjp 
231048258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
231148258c6bSjp 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
231248258c6bSjp 		    &from->how.idmap_how_u.rule);
231348258c6bSjp 		break;
231448258c6bSjp 
231548258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
231648258c6bSjp 		break;
231748258c6bSjp 
231848258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
231948258c6bSjp 		break;
232048258c6bSjp 
232148258c6bSjp 	case IDMAP_MAP_TYPE_KNOWN_SID:
232248258c6bSjp 		break;
232348258c6bSjp 	}
232448258c6bSjp 	return (retval);
232548258c6bSjp }
232648258c6bSjp 
232748258c6bSjp 
232848258c6bSjp /*
232948258c6bSjp  * This routine is similar to idmap_info_cpy, but the strings
233048258c6bSjp  * are moved from the "from" info to the "to" info.
233148258c6bSjp  * This routine is equivelent of:
233248258c6bSjp  *
233348258c6bSjp  *	idmap_info_cpy(to,from);
233448258c6bSjp  *	idmap_info_free(from);
233548258c6bSjp  */
233648258c6bSjp idmap_stat
233748258c6bSjp idmap_info_mov(idmap_info *to, idmap_info *from)
233848258c6bSjp {
233948258c6bSjp 	idmap_stat retval = IDMAP_SUCCESS;
234048258c6bSjp 
234148258c6bSjp 	if (to == NULL) {
234248258c6bSjp 		idmap_info_free(from);
234348258c6bSjp 		return (IDMAP_SUCCESS);
234448258c6bSjp 	}
234548258c6bSjp 	(void) memcpy(to, from, sizeof (idmap_info));
234648258c6bSjp 
234748258c6bSjp 	(void) memset(from, 0, sizeof (idmap_info));
23488e228215Sdm 
23498e228215Sdm 	return (retval);
23508e228215Sdm }
23518e228215Sdm 
23528e228215Sdm 
235348258c6bSjp void
235448258c6bSjp idmap_info_free(idmap_info *info)
235548258c6bSjp {
235648258c6bSjp 	idmap_how *how;
235748258c6bSjp 
235848258c6bSjp 	if (info == NULL)
235948258c6bSjp 		return;
236048258c6bSjp 
236148258c6bSjp 	how = &info->how;
236248258c6bSjp 	switch (how->map_type) {
236348258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
236448258c6bSjp 		free(how->idmap_how_u.ad.dn);
236548258c6bSjp 		how->idmap_how_u.ad.dn = NULL;
236648258c6bSjp 		free(how->idmap_how_u.ad.attr);
236748258c6bSjp 		how->idmap_how_u.ad.attr = NULL;
236848258c6bSjp 		free(how->idmap_how_u.ad.value);
236948258c6bSjp 		how->idmap_how_u.ad.value = NULL;
237048258c6bSjp 		break;
237148258c6bSjp 
237248258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
237348258c6bSjp 		free(how->idmap_how_u.nldap.dn);
237448258c6bSjp 		how->idmap_how_u.nldap.dn = NULL;
237548258c6bSjp 		free(how->idmap_how_u.nldap.attr);
237648258c6bSjp 		how->idmap_how_u.nldap.attr = NULL;
237748258c6bSjp 		free(how->idmap_how_u.nldap.value);
237848258c6bSjp 		how->idmap_how_u.nldap.value = NULL;
237948258c6bSjp 		break;
238048258c6bSjp 
238148258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
238248258c6bSjp 		free(how->idmap_how_u.rule.windomain);
238348258c6bSjp 		how->idmap_how_u.rule.windomain = NULL;
238448258c6bSjp 		free(how->idmap_how_u.rule.winname);
238548258c6bSjp 		how->idmap_how_u.rule.winname = NULL;
238648258c6bSjp 		free(how->idmap_how_u.rule.unixname);
238748258c6bSjp 		how->idmap_how_u.rule.unixname = NULL;
238848258c6bSjp 		break;
238948258c6bSjp 
239048258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
239148258c6bSjp 		break;
239248258c6bSjp 
239348258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
239448258c6bSjp 		break;
239548258c6bSjp 	}
239648258c6bSjp 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
239748258c6bSjp 	info->src = IDMAP_MAP_SRC_UNKNOWN;
239848258c6bSjp }
239948258c6bSjp 
240048258c6bSjp 
2401dd5829d1Sbaban /*
2402dd5829d1Sbaban  * Get uid given Windows name
2403dd5829d1Sbaban  */
2404dd5829d1Sbaban idmap_stat
2405*3ee87bcaSJulian Pullen idmap_getuidbywinname(const char *name, const char *domain, int flag,
2406*3ee87bcaSJulian Pullen 	uid_t *uid)
2407cd37da74Snw {
2408dd5829d1Sbaban 	idmap_handle_t	*ih;
2409dd5829d1Sbaban 	idmap_retcode	rc;
2410cd37da74Snw 	int		is_user = 1;
2411cd37da74Snw 	int		is_wuser = -1;
2412*3ee87bcaSJulian Pullen 	int 		direction;
2413dd5829d1Sbaban 
2414dd5829d1Sbaban 	if (uid == NULL)
2415dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2416dd5829d1Sbaban 
2417*3ee87bcaSJulian Pullen 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2418*3ee87bcaSJulian Pullen 		rc = idmap_cache_lookup_uidbywinname(name, domain, uid);
2419*3ee87bcaSJulian Pullen 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
2420*3ee87bcaSJulian Pullen 			return (rc);
2421*3ee87bcaSJulian Pullen 	}
2422dd5829d1Sbaban 	/* Get mapping */
2423dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2424dd5829d1Sbaban 		return (rc);
2425*3ee87bcaSJulian Pullen 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
2426*3ee87bcaSJulian Pullen 	    &is_user, &is_wuser, uid, NULL, &direction, NULL);
2427dd5829d1Sbaban 	(void) idmap_fini(ih);
2428dd5829d1Sbaban 
2429*3ee87bcaSJulian Pullen 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
2430*3ee87bcaSJulian Pullen 		/* If we have not got the domain don't store UID to winname */
2431*3ee87bcaSJulian Pullen 		if (domain == NULL)
2432*3ee87bcaSJulian Pullen 			direction = IDMAP_DIRECTION_W2U;
2433*3ee87bcaSJulian Pullen 		idmap_cache_add_winname2uid(name, domain, *uid, direction);
2434*3ee87bcaSJulian Pullen 	}
2435*3ee87bcaSJulian Pullen 
2436dd5829d1Sbaban 	return (rc);
2437dd5829d1Sbaban }
2438dd5829d1Sbaban 
2439dd5829d1Sbaban 
2440dd5829d1Sbaban /*
2441dd5829d1Sbaban  * Get gid given Windows name
2442dd5829d1Sbaban  */
2443dd5829d1Sbaban idmap_stat
2444*3ee87bcaSJulian Pullen idmap_getgidbywinname(const char *name, const char *domain, int flag,
2445*3ee87bcaSJulian Pullen 	gid_t *gid)
2446cd37da74Snw {
2447dd5829d1Sbaban 	idmap_handle_t	*ih;
2448dd5829d1Sbaban 	idmap_retcode	rc;
2449cd37da74Snw 	int		is_user = 0;
2450cd37da74Snw 	int		is_wuser = -1;
2451*3ee87bcaSJulian Pullen 	int		direction;
2452dd5829d1Sbaban 
2453dd5829d1Sbaban 	if (gid == NULL)
2454dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2455dd5829d1Sbaban 
2456*3ee87bcaSJulian Pullen 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2457*3ee87bcaSJulian Pullen 		rc = idmap_cache_lookup_gidbywinname(name, domain, gid);
2458*3ee87bcaSJulian Pullen 		if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY)
2459*3ee87bcaSJulian Pullen 			return (rc);
2460*3ee87bcaSJulian Pullen 	}
2461*3ee87bcaSJulian Pullen 
2462dd5829d1Sbaban 	/* Get mapping */
2463dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2464dd5829d1Sbaban 		return (rc);
2465*3ee87bcaSJulian Pullen 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag,
2466*3ee87bcaSJulian Pullen 	    &is_user, &is_wuser, gid, NULL, &direction, NULL);
2467dd5829d1Sbaban 	(void) idmap_fini(ih);
2468dd5829d1Sbaban 
2469*3ee87bcaSJulian Pullen 	if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) {
2470*3ee87bcaSJulian Pullen 		/* If we have not got the domain don't store GID to winname */
2471*3ee87bcaSJulian Pullen 		if (domain == NULL)
2472*3ee87bcaSJulian Pullen 			direction = IDMAP_DIRECTION_W2U;
2473*3ee87bcaSJulian Pullen 		idmap_cache_add_winname2gid(name, domain, *gid, direction);
2474*3ee87bcaSJulian Pullen 	}
2475*3ee87bcaSJulian Pullen 
2476dd5829d1Sbaban 	return (rc);
2477dd5829d1Sbaban }
2478dd5829d1Sbaban 
2479dd5829d1Sbaban 
2480dd5829d1Sbaban /*
2481dd5829d1Sbaban  * Get winname given pid
2482dd5829d1Sbaban  */
2483dd5829d1Sbaban static idmap_retcode
2484*3ee87bcaSJulian Pullen idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name,
2485*3ee87bcaSJulian Pullen 	char **domain)
2486cd37da74Snw {
2487dd5829d1Sbaban 	idmap_handle_t	*ih;
2488dd5829d1Sbaban 	idmap_retcode	rc;
2489dd5829d1Sbaban 	int		len;
2490dd5829d1Sbaban 	char		*winname, *windomain;
2491*3ee87bcaSJulian Pullen 	int		direction;
2492dd5829d1Sbaban 
2493dd5829d1Sbaban 	if (name == NULL)
2494dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2495dd5829d1Sbaban 
2496*3ee87bcaSJulian Pullen 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2497*3ee87bcaSJulian Pullen 		if (is_user)
2498*3ee87bcaSJulian Pullen 			rc = idmap_cache_lookup_winnamebyuid(&winname,
2499*3ee87bcaSJulian Pullen 			    &windomain, pid);
2500*3ee87bcaSJulian Pullen 		else
2501*3ee87bcaSJulian Pullen 			rc = idmap_cache_lookup_winnamebygid(&winname,
2502*3ee87bcaSJulian Pullen 			    &windomain, pid);
2503*3ee87bcaSJulian Pullen 		if (rc == IDMAP_SUCCESS)
2504*3ee87bcaSJulian Pullen 			goto out;
2505*3ee87bcaSJulian Pullen 		if (rc == IDMAP_ERR_MEMORY)
2506*3ee87bcaSJulian Pullen 			return (rc);
2507*3ee87bcaSJulian Pullen 	}
2508*3ee87bcaSJulian Pullen 
2509dd5829d1Sbaban 	/* Get mapping */
2510dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2511dd5829d1Sbaban 		return (rc);
2512*3ee87bcaSJulian Pullen 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL,
2513*3ee87bcaSJulian Pullen 	    NULL, NULL, &winname, &windomain, &direction, NULL);
2514dd5829d1Sbaban 	(void) idmap_fini(ih);
2515dd5829d1Sbaban 
2516dd5829d1Sbaban 	/* Return on error */
2517dd5829d1Sbaban 	if (rc != IDMAP_SUCCESS)
2518dd5829d1Sbaban 		return (rc);
2519dd5829d1Sbaban 
2520dd5829d1Sbaban 	/*
2521dd5829d1Sbaban 	 * The given PID may have been mapped to a locally
2522dd5829d1Sbaban 	 * generated SID in which case there isn't any
2523dd5829d1Sbaban 	 * Windows name
2524dd5829d1Sbaban 	 */
2525dd5829d1Sbaban 	if (winname == NULL || windomain == NULL) {
2526dd5829d1Sbaban 		idmap_free(winname);
2527dd5829d1Sbaban 		idmap_free(windomain);
2528dd5829d1Sbaban 		return (IDMAP_ERR_NORESULT);
2529dd5829d1Sbaban 	}
2530dd5829d1Sbaban 
2531*3ee87bcaSJulian Pullen 	if (flag & IDMAP_REQ_FLG_USE_CACHE) {
2532*3ee87bcaSJulian Pullen 		if (is_user)
2533*3ee87bcaSJulian Pullen 			idmap_cache_add_winname2uid(winname, windomain,
2534*3ee87bcaSJulian Pullen 			    pid, direction);
2535*3ee87bcaSJulian Pullen 		else
2536*3ee87bcaSJulian Pullen 			idmap_cache_add_winname2gid(winname, windomain,
2537*3ee87bcaSJulian Pullen 			    pid, direction);
2538*3ee87bcaSJulian Pullen 	}
2539*3ee87bcaSJulian Pullen 
2540*3ee87bcaSJulian Pullen out:
2541dd5829d1Sbaban 	if (domain != NULL) {
2542dd5829d1Sbaban 		*name = winname;
2543dd5829d1Sbaban 		*domain = windomain;
2544dd5829d1Sbaban 	} else {
2545dd5829d1Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
2546dd5829d1Sbaban 		if ((*name = malloc(len)) != NULL)
2547dd5829d1Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
2548dd5829d1Sbaban 			    windomain);
2549dd5829d1Sbaban 		else
2550dd5829d1Sbaban 			rc = IDMAP_ERR_MEMORY;
2551dd5829d1Sbaban 		idmap_free(winname);
2552dd5829d1Sbaban 		idmap_free(windomain);
2553dd5829d1Sbaban 	}
2554*3ee87bcaSJulian Pullen 
2555dd5829d1Sbaban 	return (rc);
2556dd5829d1Sbaban }
2557dd5829d1Sbaban 
2558dd5829d1Sbaban 
2559dd5829d1Sbaban /*
2560dd5829d1Sbaban  * Get winname given uid
2561dd5829d1Sbaban  */
2562dd5829d1Sbaban idmap_stat
2563*3ee87bcaSJulian Pullen idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain)
2564cd37da74Snw {
2565*3ee87bcaSJulian Pullen 	return (idmap_getwinnamebypid(uid, 1, flag, name, domain));
2566dd5829d1Sbaban }
2567dd5829d1Sbaban 
2568dd5829d1Sbaban 
2569dd5829d1Sbaban /*
2570dd5829d1Sbaban  * Get winname given gid
2571dd5829d1Sbaban  */
2572dd5829d1Sbaban idmap_stat
2573*3ee87bcaSJulian Pullen idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain)
2574cd37da74Snw {
2575*3ee87bcaSJulian Pullen 	return (idmap_getwinnamebypid(gid, 0, flag, name, domain));
2576dd5829d1Sbaban }
2577479ac375Sdm 
2578479ac375Sdm 
2579479ac375Sdm /* printflike */
2580479ac375Sdm void
2581479ac375Sdm idmapdlog(int pri, const char *format, ...) {
2582479ac375Sdm 	va_list args;
2583479ac375Sdm 
2584479ac375Sdm 	va_start(args, format);
2585479ac375Sdm 	if (pri <= logstate.max_pri) {
2586479ac375Sdm 		(void) vfprintf(stderr, format, args);
2587479ac375Sdm 		(void) fprintf(stderr, "\n");
2588479ac375Sdm 	}
2589479ac375Sdm 
2590479ac375Sdm 	/*
2591479ac375Sdm 	 * We don't want to fill up the logs with useless messages when
2592479ac375Sdm 	 * we're degraded, but we still want to log.
2593479ac375Sdm 	 */
2594479ac375Sdm 	if (logstate.degraded)
2595479ac375Sdm 		pri = LOG_DEBUG;
2596479ac375Sdm 
2597479ac375Sdm 	if (logstate.write_syslog)
2598479ac375Sdm 		(void) vsyslog(pri, format, args);
2599479ac375Sdm 	va_end(args);
2600479ac375Sdm }
2601479ac375Sdm 
2602479ac375Sdm void
2603479ac375Sdm idmap_log_stderr(int pri)
2604479ac375Sdm {
2605479ac375Sdm 	logstate.max_pri = pri;
2606479ac375Sdm }
2607479ac375Sdm 
2608479ac375Sdm void
2609479ac375Sdm idmap_log_syslog(bool_t what)
2610479ac375Sdm {
2611479ac375Sdm 	logstate.write_syslog = what;
2612479ac375Sdm }
2613479ac375Sdm 
2614479ac375Sdm void
2615479ac375Sdm idmap_log_degraded(bool_t what)
2616479ac375Sdm {
2617479ac375Sdm 	logstate.degraded = what;
2618479ac375Sdm }
2619