xref: /illumos-gate/usr/src/lib/libidmap/common/idmap_api.c (revision 479ac37569625bae44ffb80071d4bc865fc710ed)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c5c4113dSnw 
28c5c4113dSnw /*
29c5c4113dSnw  * libidmap API
30c5c4113dSnw  */
31c5c4113dSnw 
32c5c4113dSnw #include <stdlib.h>
33*479ac375Sdm #include <sys/varargs.h>
34c5c4113dSnw #include <inttypes.h>
35c5c4113dSnw #include <errno.h>
36c5c4113dSnw #include <strings.h>
37c5c4113dSnw #include <ctype.h>
38c5c4113dSnw #include <sys/param.h>
39c5c4113dSnw #include <sys/types.h>
40c5c4113dSnw #include <sys/stat.h>
41c5c4113dSnw #include <dlfcn.h>
42c5c4113dSnw #include <libintl.h>
43d3a612caSnw #include <ucontext.h>
44c5c4113dSnw #include "idmap_impl.h"
45c5c4113dSnw 
46*479ac375Sdm /*LINTLIBRARY*/
47*479ac375Sdm 
48*479ac375Sdm /*
49*479ac375Sdm  * The following structure determines where the log messages from idmapdlog()
50*479ac375Sdm  * go to. It can be stderr (idmap, idmapd -d) and/or syslog (idmapd).
51*479ac375Sdm  *
52*479ac375Sdm  * logstate.max_pri is integer cutoff necessary to silence low-priority
53*479ac375Sdm  * messages to stderr. Syslog has its own means so there a boolean
54*479ac375Sdm  * logstate.write_syslog is enough.
55*479ac375Sdm  *
56*479ac375Sdm  * logstate.degraded is a mode used by idmapd in its degraded state.
57*479ac375Sdm  */
58*479ac375Sdm 
59*479ac375Sdm static struct {
60*479ac375Sdm 	bool_t write_syslog;
61*479ac375Sdm 	int max_pri; /* Max priority written to stderr */
62*479ac375Sdm 	bool_t degraded;
63*479ac375Sdm } logstate = {FALSE, LOG_DEBUG, FALSE};
64*479ac375Sdm 
65*479ac375Sdm 
66c5c4113dSnw static struct timeval TIMEOUT = { 25, 0 };
67c5c4113dSnw 
68c5c4113dSnw static int idmap_stat2errno(idmap_stat);
69*479ac375Sdm 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 
1148e228215Sdm #define	EMPTY_STRING(str)	(str == NULL || *str == '\0')
115c5c4113dSnw 
116c5c4113dSnw /*
117c5c4113dSnw  * Free memory allocated by libidmap API
118c5c4113dSnw  *
119c5c4113dSnw  * Input:
120c5c4113dSnw  * ptr - memory to be freed
121c5c4113dSnw  */
122c5c4113dSnw void
123cd37da74Snw idmap_free(void *ptr)
124cd37da74Snw {
125c5c4113dSnw 	free(ptr);
126c5c4113dSnw }
127c5c4113dSnw 
128c5c4113dSnw 
129d3a612caSnw #define	MIN_STACK_NEEDS	16384
130d3a612caSnw 
131c5c4113dSnw /*
132c5c4113dSnw  * Create and Initialize idmap client handle for rpc/doors
133c5c4113dSnw  *
134c5c4113dSnw  * Output:
135c5c4113dSnw  * handle - idmap handle
136c5c4113dSnw  */
137c5c4113dSnw idmap_stat
138cd37da74Snw idmap_init(idmap_handle_t **handle)
139cd37da74Snw {
140c5c4113dSnw 	CLIENT			*clnt = NULL;
141c5c4113dSnw 	struct idmap_handle	*hptr;
142d3a612caSnw 	uint_t			sendsz = 0;
143d3a612caSnw 	stack_t			st;
144c5c4113dSnw 
145c5c4113dSnw 	*handle = NULL;
146c5c4113dSnw 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
147c5c4113dSnw 	if (hptr == NULL)
148c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
149c5c4113dSnw 
150d3a612caSnw 	/*
151d3a612caSnw 	 * clnt_door_call() alloca()s sendsz bytes (twice too, once for
152d3a612caSnw 	 * the call args buffer and once for the call result buffer), so
153d3a612caSnw 	 * we want to pick a sendsz that will be large enough, but not
154d3a612caSnw 	 * too large.
155d3a612caSnw 	 */
156d3a612caSnw 	if (stack_getbounds(&st) == 0) {
157d3a612caSnw 		/*
158d3a612caSnw 		 * Estimate how much stack space is left;
159d3a612caSnw 		 * st.ss_sp is the top of stack.
160d3a612caSnw 		 */
161d3a612caSnw 		if ((char *)&sendsz < (char *)st.ss_sp)
162d3a612caSnw 			/* stack grows up */
163d3a612caSnw 			sendsz = ((char *)st.ss_sp - (char *)&sendsz);
164d3a612caSnw 		else
165d3a612caSnw 			/* stack grows down */
166d3a612caSnw 			sendsz = ((char *)&sendsz - (char *)st.ss_sp);
167d3a612caSnw 
168d3a612caSnw 		/*
169d3a612caSnw 		 * Take much of the stack space left, divided by two,
170d3a612caSnw 		 * but leave enough for our needs (just a guess!), and
171d3a612caSnw 		 * if we can't, then roll the dice.
172d3a612caSnw 		 */
173d3a612caSnw 		sendsz = RNDUP(sendsz / 2);
174d3a612caSnw 		if (sendsz < MIN_STACK_NEEDS)
175d3a612caSnw 			sendsz = 0;	/* RPC call may fail */
176d3a612caSnw 		else if (sendsz > IDMAP_MAX_DOOR_RPC)
177d3a612caSnw 			sendsz = IDMAP_MAX_DOOR_RPC;
178d3a612caSnw 	}
179d3a612caSnw 
180d3a612caSnw 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz);
181c5c4113dSnw 	if (clnt == NULL) {
182c5c4113dSnw 		free(hptr);
183c5c4113dSnw 		return (IDMAP_ERR_RPC);
184c5c4113dSnw 	}
185c5c4113dSnw 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
186c5c4113dSnw 	hptr->privhandle = clnt;
187c5c4113dSnw 	*handle = hptr;
188c5c4113dSnw 	return (IDMAP_SUCCESS);
189c5c4113dSnw }
190c5c4113dSnw 
191c5c4113dSnw 
192c5c4113dSnw /*
193c5c4113dSnw  * Finalize idmap handle
194c5c4113dSnw  *
195c5c4113dSnw  * Input:
196c5c4113dSnw  * handle - idmap handle
197c5c4113dSnw  */
198c5c4113dSnw idmap_stat
199cd37da74Snw idmap_fini(idmap_handle_t *handle)
200cd37da74Snw {
201c5c4113dSnw 	CLIENT			*clnt;
202c5c4113dSnw 	struct idmap_handle	*hptr;
203c5c4113dSnw 
204c5c4113dSnw 	if (handle == NULL)
205c5c4113dSnw 		return (IDMAP_SUCCESS);
206c5c4113dSnw 
207c5c4113dSnw 	hptr = (struct idmap_handle *)handle;
208c5c4113dSnw 
209c5c4113dSnw 	switch (hptr->type) {
210c5c4113dSnw 	case _IDMAP_HANDLE_RPC_DOORS:
211c5c4113dSnw 		clnt = (CLIENT *)hptr->privhandle;
212c5c4113dSnw 		if (clnt) {
213c5c4113dSnw 			if (clnt->cl_auth)
214c5c4113dSnw 				auth_destroy(clnt->cl_auth);
215c5c4113dSnw 			clnt_destroy(clnt);
216c5c4113dSnw 		}
217c5c4113dSnw 		break;
218c5c4113dSnw 	default:
219c5c4113dSnw 		break;
220c5c4113dSnw 	}
221c5c4113dSnw 	free(hptr);
222c5c4113dSnw 	return (IDMAP_SUCCESS);
223c5c4113dSnw }
224c5c4113dSnw 
225c5c4113dSnw 
226*479ac375Sdm idmap_stat
227*479ac375Sdm idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res)
228*479ac375Sdm {
229*479ac375Sdm 	CLIENT			*clnt;
230*479ac375Sdm 	enum clnt_stat		clntstat;
231*479ac375Sdm 
232*479ac375Sdm 
233*479ac375Sdm 	(void) memset(res, 0, sizeof (*res));
234*479ac375Sdm 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
235*479ac375Sdm 
236*479ac375Sdm 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
237*479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
238*479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT);
239*479ac375Sdm 
240*479ac375Sdm 	if (clntstat != RPC_SUCCESS) {
241*479ac375Sdm 		return (_idmap_rpc2stat(clnt));
242*479ac375Sdm 	}
243*479ac375Sdm 
244*479ac375Sdm 	return (res->retcode); /* This might not be IDMAP_SUCCESS! */
245*479ac375Sdm 
246*479ac375Sdm #if 0
247*479ac375Sdm 	(void) memset(&res, 0, sizeof (res));
248*479ac375Sdm 	pr = PROP_DOMAIN_CONTROLLER;
249*479ac375Sdm 
250*479ac375Sdm 	clntstat = clnt_call(clnt, IDMAP_GET_PROP,
251*479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr,
252*479ac375Sdm 	    (xdrproc_t)xdr_idmap_prop_res, (caddr_t)&res, TIMEOUT);
253*479ac375Sdm 
254*479ac375Sdm 	if (clntstat != RPC_SUCCESS) {
255*479ac375Sdm 		fprintf(stderr, "clntstat != RPC_SUCCESS\n");
256*479ac375Sdm 		rc = _idmap_rpc2stat(clnt);
257*479ac375Sdm 		goto cleanup;
258*479ac375Sdm 	}
259*479ac375Sdm #endif
260*479ac375Sdm 
261*479ac375Sdm }
262*479ac375Sdm 
263*479ac375Sdm idmap_stat
264*479ac375Sdm idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr,
265*479ac375Sdm     idmap_ad_disc_ds_t *dc)
266*479ac375Sdm {
267*479ac375Sdm 	idmap_prop_res res;
268*479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
269*479ac375Sdm 
270*479ac375Sdm 	rc = idmap_get_prop(handle, pr, &res);
271*479ac375Sdm 	if (rc < 0)
272*479ac375Sdm 		return (rc);
273*479ac375Sdm 
274*479ac375Sdm 	dc->port = res.value.idmap_prop_val_u.dsval.port;
275*479ac375Sdm 	(void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host,
276*479ac375Sdm 	    AD_DISC_MAXHOSTNAME);
277*479ac375Sdm 
278*479ac375Sdm 	/* xdr doesn't guarantee 0-termination of char[]: */
279*479ac375Sdm 	dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0';
280*479ac375Sdm 
281*479ac375Sdm 	return (rc);
282*479ac375Sdm }
283*479ac375Sdm 
284*479ac375Sdm 
285*479ac375Sdm /*
286*479ac375Sdm  * Sometimes the property is not set. In that case, str is set to NULL but
287*479ac375Sdm  * otherwise IDMAP_SUCCESS is returned.
288*479ac375Sdm  */
289*479ac375Sdm idmap_stat
290*479ac375Sdm idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str)
291*479ac375Sdm {
292*479ac375Sdm 	idmap_prop_res res;
293*479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
294*479ac375Sdm 
295*479ac375Sdm 	rc = idmap_get_prop(handle, pr, &res);
296*479ac375Sdm 	if (rc < 0)
297*479ac375Sdm 		return (rc);
298*479ac375Sdm 
299*479ac375Sdm 	rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val);
300*479ac375Sdm 	return (rc);
301*479ac375Sdm }
302c5c4113dSnw 
303c5c4113dSnw /*
304c5c4113dSnw  * Create/Initialize handle for updates
305c5c4113dSnw  *
306c5c4113dSnw  * Output:
307c5c4113dSnw  * udthandle - update handle
308c5c4113dSnw  */
309c5c4113dSnw idmap_stat
310cd37da74Snw idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle)
311cd37da74Snw {
312c5c4113dSnw 	idmap_udt_handle_t	*tmp;
313c5c4113dSnw 
314c5c4113dSnw 	if (handle == NULL || udthandle == NULL) {
315c5c4113dSnw 		errno = EINVAL;
316c5c4113dSnw 		return (IDMAP_ERR_ARG);
317c5c4113dSnw 	}
318c5c4113dSnw 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
319c5c4113dSnw 		errno = ENOMEM;
320c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
321c5c4113dSnw 	}
322c5c4113dSnw 
323c5c4113dSnw 	tmp->ih = handle;
324c5c4113dSnw 	*udthandle = tmp;
325c5c4113dSnw 	return (IDMAP_SUCCESS);
326c5c4113dSnw }
327c5c4113dSnw 
328c5c4113dSnw 
329c5c4113dSnw /*
330c5c4113dSnw  * All the updates specified by the update handle are committed
331c5c4113dSnw  * in a single transaction. i.e either all succeed or none.
332c5c4113dSnw  *
333c5c4113dSnw  * Input:
334c5c4113dSnw  * udthandle - update handle with the update requests
335c5c4113dSnw  *
336c5c4113dSnw  * Return value:
337c5c4113dSnw  * Status of the commit
338c5c4113dSnw  */
339c5c4113dSnw idmap_stat
340cd37da74Snw idmap_udt_commit(idmap_udt_handle_t *udthandle)
341cd37da74Snw {
342c5c4113dSnw 	CLIENT			*clnt;
343c5c4113dSnw 	enum clnt_stat		clntstat;
3448e228215Sdm 	idmap_update_res	res;
3458e228215Sdm 	idmap_stat		retcode;
346c5c4113dSnw 
347c5c4113dSnw 	if (udthandle == NULL) {
348c5c4113dSnw 		errno = EINVAL;
349c5c4113dSnw 		return (IDMAP_ERR_ARG);
350c5c4113dSnw 	}
3518e228215Sdm 
3528e228215Sdm 	(void) memset(&res, 0, sizeof (res));
3538e228215Sdm 
354c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
355c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
356cd37da74Snw 	    (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
357cd37da74Snw 	    (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res,
358cd37da74Snw 	    TIMEOUT);
359651c0131Sbaban 
3608e228215Sdm 	if (clntstat != RPC_SUCCESS) {
3618e228215Sdm 		retcode = _idmap_rpc2stat(clnt);
3628e228215Sdm 		goto out;
3638e228215Sdm 	}
3648e228215Sdm 
3658e228215Sdm 	retcode = udthandle->commit_stat = res.retcode;
3668e228215Sdm 	udthandle->error_index = res.error_index;
3678e228215Sdm 
3688e228215Sdm 	if (retcode != IDMAP_SUCCESS) {
3698e228215Sdm 
3708e228215Sdm 		if (udthandle->error_index < 0)
3718e228215Sdm 			goto out;
3728e228215Sdm 
3738e228215Sdm 		retcode = idmap_namerule_cpy(&udthandle->error_rule,
3748e228215Sdm 		    &res.error_rule);
3758e228215Sdm 		if (retcode != IDMAP_SUCCESS) {
3768e228215Sdm 			udthandle->error_index = -2;
3778e228215Sdm 			goto out;
3788e228215Sdm 		}
3798e228215Sdm 
3808e228215Sdm 		retcode = idmap_namerule_cpy(&udthandle->conflict_rule,
3818e228215Sdm 		    &res.conflict_rule);
3828e228215Sdm 		if (retcode != IDMAP_SUCCESS) {
3838e228215Sdm 			udthandle->error_index = -2;
3848e228215Sdm 			goto out;
3858e228215Sdm 		}
3868e228215Sdm 	}
3878e228215Sdm 
3888e228215Sdm 	retcode = res.retcode;
3898e228215Sdm 
3908e228215Sdm 
3918e228215Sdm out:
392651c0131Sbaban 	/* reset handle so that it can be used again */
3938e228215Sdm 	if (retcode == IDMAP_SUCCESS) {
3948e228215Sdm 		_IDMAP_RESET_UDT_HANDLE(udthandle);
3958e228215Sdm 	}
396651c0131Sbaban 
3978e228215Sdm 	(void) xdr_free(xdr_idmap_update_res, (caddr_t)&res);
3988e228215Sdm 	errno = idmap_stat2errno(retcode);
3998e228215Sdm 	return (retcode);
4008e228215Sdm }
4018e228215Sdm 
4028e228215Sdm 
4038e228215Sdm static void
4048e228215Sdm idmap_namerule_parts_clear(char **windomain, char **winname,
405cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
406cd37da74Snw     boolean_t *is_nt4, int *direction)
407cd37da74Snw {
4088e228215Sdm 	if (windomain)
4098e228215Sdm 		*windomain = NULL;
4108e228215Sdm 	if (winname)
4118e228215Sdm 		*winname = NULL;
4128e228215Sdm 	if (unixname)
4138e228215Sdm 		*unixname = NULL;
4148e228215Sdm 
4158e228215Sdm 	if (is_nt4)
4168e228215Sdm 		*is_nt4 = 0;
4178e228215Sdm 	if (is_user)
4188e228215Sdm 		*is_user = -1;
419cd37da74Snw 	if (is_wuser)
420cd37da74Snw 		*is_wuser = -1;
4218e228215Sdm 	if (direction)
4228e228215Sdm 		*direction = IDMAP_DIRECTION_UNDEF;
4238e228215Sdm }
4248e228215Sdm 
4258e228215Sdm static idmap_stat
426cd37da74Snw idmap_namerule2parts(idmap_namerule *rule,
4278e228215Sdm     char **windomain, char **winname,
428cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
429cd37da74Snw     boolean_t *is_nt4, int *direction)
430cd37da74Snw {
4318e228215Sdm 	idmap_stat retcode;
4328e228215Sdm 
4338e228215Sdm 	if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname))
4348e228215Sdm 		return (IDMAP_ERR_NORESULT);
4358e228215Sdm 
4368e228215Sdm 
4378e228215Sdm 	retcode = idmap_strdupnull(windomain, rule->windomain);
438c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
4398e228215Sdm 		goto errout;
4408e228215Sdm 
4418e228215Sdm 	retcode = idmap_strdupnull(winname, rule->winname);
4428e228215Sdm 	if (retcode != IDMAP_SUCCESS)
4438e228215Sdm 		goto errout;
4448e228215Sdm 
4458e228215Sdm 	retcode = idmap_strdupnull(unixname, rule->unixname);
4468e228215Sdm 	if (retcode != IDMAP_SUCCESS)
4478e228215Sdm 		goto errout;
4488e228215Sdm 
4498e228215Sdm 
4508e228215Sdm 	if (is_user)
4518e228215Sdm 		*is_user = rule->is_user;
452cd37da74Snw 	if (is_wuser)
453cd37da74Snw 		*is_wuser = rule->is_wuser;
4548e228215Sdm 	if (is_nt4)
4558e228215Sdm 		*is_nt4 = rule->is_nt4;
4568e228215Sdm 	if (direction)
4578e228215Sdm 		*direction = rule->direction;
4588e228215Sdm 
4598e228215Sdm 
4608e228215Sdm 	return (IDMAP_SUCCESS);
4618e228215Sdm 
4628e228215Sdm errout:
4638e228215Sdm 	if (windomain && *windomain)
4648e228215Sdm 		free(*windomain);
4658e228215Sdm 	if (winname && *winname)
4668e228215Sdm 		free(*winname);
4678e228215Sdm 	if (unixname && *unixname)
4688e228215Sdm 		free(*unixname);
4698e228215Sdm 
4708e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
471cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
4728e228215Sdm 
473c5c4113dSnw 	return (retcode);
4748e228215Sdm 
4758e228215Sdm }
4768e228215Sdm 
4778e228215Sdm /*
4788e228215Sdm  * Retrieve the index of the failed batch element. error_index == -1
4798e228215Sdm  * indicates failure at the beginning, -2 at the end.
4808e228215Sdm  *
4818e228215Sdm  * If idmap_udt_commit didn't return error, the returned value is undefined.
4828e228215Sdm  *
4838e228215Sdm  * Return value:
4848e228215Sdm  * IDMAP_SUCCESS
4858e228215Sdm  */
4868e228215Sdm 
4878e228215Sdm idmap_stat
4888e228215Sdm idmap_udt_get_error_index(idmap_udt_handle_t *udthandle,
489cd37da74Snw     int64_t *error_index)
490cd37da74Snw {
4918e228215Sdm 	if (error_index)
4928e228215Sdm 		*error_index = udthandle->error_index;
4938e228215Sdm 
4948e228215Sdm 	return (IDMAP_SUCCESS);
4958e228215Sdm }
4968e228215Sdm 
4978e228215Sdm 
4988e228215Sdm /*
4998e228215Sdm  * Retrieve the rule which caused the batch to fail. If
5008e228215Sdm  * idmap_udt_commit didn't return error or if error_index is < 0, the
5018e228215Sdm  * retrieved rule is undefined.
5028e228215Sdm  *
5038e228215Sdm  * Return value:
5048e228215Sdm  * IDMAP_ERR_NORESULT if there is no error rule.
5058e228215Sdm  * IDMAP_SUCCESS if the rule was obtained OK.
5068e228215Sdm  * other error code (IDMAP_ERR_NOMEMORY etc)
5078e228215Sdm  */
5088e228215Sdm 
5098e228215Sdm idmap_stat
5108e228215Sdm idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle,
5118e228215Sdm     char **windomain, char **winname,
512cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
513cd37da74Snw     boolean_t *is_nt4, int *direction)
514cd37da74Snw {
5158e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
516cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
5178e228215Sdm 
5188e228215Sdm 	if (udthandle->commit_stat == IDMAP_SUCCESS ||
5198e228215Sdm 	    udthandle->error_index < 0)
5208e228215Sdm 		return (IDMAP_ERR_NORESULT);
5218e228215Sdm 
5228e228215Sdm 	return (idmap_namerule2parts(
523cd37da74Snw 	    &udthandle->error_rule,
524cd37da74Snw 	    windomain,
525cd37da74Snw 	    winname,
526cd37da74Snw 	    unixname,
527cd37da74Snw 	    is_user,
528cd37da74Snw 	    is_wuser,
529cd37da74Snw 	    is_nt4,
530cd37da74Snw 	    direction));
5318e228215Sdm }
5328e228215Sdm 
5338e228215Sdm /*
5348e228215Sdm  * Retrieve the rule with which there was a conflict. TODO: retrieve
5358e228215Sdm  * the value.
5368e228215Sdm  *
5378e228215Sdm  * Return value:
5388e228215Sdm  * IDMAP_ERR_NORESULT if there is no error rule.
5398e228215Sdm  * IDMAP_SUCCESS if the rule was obtained OK.
5408e228215Sdm  * other error code (IDMAP_ERR_NOMEMORY etc)
5418e228215Sdm  */
5428e228215Sdm 
5438e228215Sdm idmap_stat
5448e228215Sdm idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle,
5458e228215Sdm     char **windomain, char **winname,
546cd37da74Snw     char **unixname, boolean_t *is_user, boolean_t *is_wuser,
547cd37da74Snw     boolean_t *is_nt4, int *direction)
548cd37da74Snw {
5498e228215Sdm 	idmap_namerule_parts_clear(windomain, winname,
550cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
5518e228215Sdm 
5528e228215Sdm 	if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT &&
5538e228215Sdm 	    udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) {
554cd37da74Snw 		return (IDMAP_ERR_NORESULT);
5558e228215Sdm 	}
5568e228215Sdm 
5578e228215Sdm 	return (idmap_namerule2parts(
558cd37da74Snw 	    &udthandle->conflict_rule,
559cd37da74Snw 	    windomain,
560cd37da74Snw 	    winname,
561cd37da74Snw 	    unixname,
562cd37da74Snw 	    is_user,
563cd37da74Snw 	    is_wuser,
564cd37da74Snw 	    is_nt4,
565cd37da74Snw 	    direction));
566c5c4113dSnw }
567c5c4113dSnw 
568c5c4113dSnw 
569c5c4113dSnw /*
570c5c4113dSnw  * Destroy the update handle
571c5c4113dSnw  */
572c5c4113dSnw void
573cd37da74Snw idmap_udt_destroy(idmap_udt_handle_t *udthandle)
574cd37da74Snw {
575c5c4113dSnw 	if (udthandle == NULL)
576c5c4113dSnw 		return;
577c5c4113dSnw 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
5788e228215Sdm 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule);
5798e228215Sdm 	(void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule);
580c5c4113dSnw 	free(udthandle);
581c5c4113dSnw }
582c5c4113dSnw 
583c5c4113dSnw 
584c5c4113dSnw idmap_stat
585c5c4113dSnw idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
586cd37da74Snw     boolean_t is_user, boolean_t is_wuser, const char *winname,
587cd37da74Snw     const char *unixname, boolean_t is_nt4, int direction)
588cd37da74Snw {
589c5c4113dSnw 	idmap_retcode	retcode;
590651c0131Sbaban 	idmap_namerule	*rule = NULL;
591c5c4113dSnw 
592651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
593c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
594c5c4113dSnw 		goto errout;
595c5c4113dSnw 
596c5c4113dSnw 	rule = &udthandle->batch.
597cd37da74Snw 	    idmap_update_batch_val[udthandle->next].
598cd37da74Snw 	    idmap_update_op_u.rule;
599c5c4113dSnw 	rule->is_user = is_user;
600cd37da74Snw 	rule->is_wuser = is_wuser;
601c5c4113dSnw 	rule->direction = direction;
602c5c4113dSnw 	rule->is_nt4 = is_nt4;
6038e228215Sdm 
6048e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6058e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6068e228215Sdm 		goto errout;
6078e228215Sdm 
6088e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
6098e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6108e228215Sdm 		goto errout;
6118e228215Sdm 
6128e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6138e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6148e228215Sdm 		goto errout;
615651c0131Sbaban 
616651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
617651c0131Sbaban 	    OP_ADD_NAMERULE;
618c5c4113dSnw 	udthandle->next++;
619c5c4113dSnw 	return (IDMAP_SUCCESS);
620c5c4113dSnw 
621c5c4113dSnw errout:
622651c0131Sbaban 	/* The batch should still be usable */
623651c0131Sbaban 	if (rule)
624651c0131Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
625c5c4113dSnw 	errno = idmap_stat2errno(retcode);
626c5c4113dSnw 	return (retcode);
627c5c4113dSnw }
628c5c4113dSnw 
629c5c4113dSnw 
630c5c4113dSnw /* ARGSUSED */
631c5c4113dSnw idmap_stat
632c5c4113dSnw idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
633cd37da74Snw     boolean_t is_wuser,	const char *windomain, const char *winname,
634cd37da74Snw     const char *unixname, int direction)
635cd37da74Snw {
636c5c4113dSnw 	idmap_retcode	retcode;
637651c0131Sbaban 	idmap_namerule	*rule = NULL;
638c5c4113dSnw 
639651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
640c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
641c5c4113dSnw 		goto errout;
642c5c4113dSnw 
643c5c4113dSnw 	rule = &udthandle->batch.
644cd37da74Snw 	    idmap_update_batch_val[udthandle->next].
645cd37da74Snw 	    idmap_update_op_u.rule;
646c5c4113dSnw 	rule->is_user = is_user;
647cd37da74Snw 	rule->is_wuser = is_wuser;
648c5c4113dSnw 	rule->direction = direction;
6498e228215Sdm 
6508e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
6518e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6528e228215Sdm 		goto errout;
6538e228215Sdm 
6548e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
6558e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6568e228215Sdm 		goto errout;
6578e228215Sdm 
6588e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
6598e228215Sdm 	if (retcode != IDMAP_SUCCESS)
6608e228215Sdm 		goto errout;
6618e228215Sdm 
662651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
663651c0131Sbaban 	    OP_RM_NAMERULE;
664c5c4113dSnw 	udthandle->next++;
665c5c4113dSnw 	return (IDMAP_SUCCESS);
666c5c4113dSnw 
667c5c4113dSnw errout:
668651c0131Sbaban 	if (rule)
669651c0131Sbaban 		(void) xdr_free(xdr_idmap_namerule, (caddr_t)rule);
670c5c4113dSnw 	errno = idmap_stat2errno(retcode);
671c5c4113dSnw 	return (retcode);
672c5c4113dSnw }
673c5c4113dSnw 
674c5c4113dSnw 
675c5c4113dSnw /* ARGSUSED */
676c5c4113dSnw idmap_stat
677cd37da74Snw idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle)
678cd37da74Snw {
679c5c4113dSnw 	idmap_retcode	retcode;
680c5c4113dSnw 
681651c0131Sbaban 	retcode = _udt_extend_batch(udthandle);
682c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
683c5c4113dSnw 		goto errout;
684c5c4113dSnw 
685651c0131Sbaban 	udthandle->batch.idmap_update_batch_val[udthandle->next].opnum =
686651c0131Sbaban 	    OP_FLUSH_NAMERULES;
687c5c4113dSnw 	udthandle->next++;
688c5c4113dSnw 	return (IDMAP_SUCCESS);
689c5c4113dSnw 
690c5c4113dSnw errout:
691c5c4113dSnw 	errno = idmap_stat2errno(retcode);
692c5c4113dSnw 	return (retcode);
693c5c4113dSnw }
694c5c4113dSnw 
695c5c4113dSnw 
696c5c4113dSnw /*
697c5c4113dSnw  * Set the number of entries requested per batch by the iterator
698c5c4113dSnw  *
699c5c4113dSnw  * Input:
700c5c4113dSnw  * iter  - iterator
701c5c4113dSnw  * limit - number of entries requested per batch
702c5c4113dSnw  */
703c5c4113dSnw idmap_stat
704cd37da74Snw idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit)
705cd37da74Snw {
706c5c4113dSnw 	if (iter == NULL) {
707c5c4113dSnw 		errno = EINVAL;
708c5c4113dSnw 		return (IDMAP_ERR_ARG);
709c5c4113dSnw 	}
710c5c4113dSnw 	iter->limit = limit;
711c5c4113dSnw 	return (IDMAP_SUCCESS);
712c5c4113dSnw }
713c5c4113dSnw 
714c5c4113dSnw 
715c5c4113dSnw /*
716c5c4113dSnw  * Create iterator to get name-based mapping rules
717c5c4113dSnw  *
718c5c4113dSnw  * Input:
719c5c4113dSnw  * windomain - Windows domain
720c5c4113dSnw  * is_user   - user or group rules
721c5c4113dSnw  * winname   - Windows user or group name
722c5c4113dSnw  * unixname  - Unix user or group name
723c5c4113dSnw  *
724c5c4113dSnw  * Output:
725c5c4113dSnw  * iter - iterator
726c5c4113dSnw  */
727c5c4113dSnw idmap_stat
728c5c4113dSnw idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
729cd37da74Snw 		boolean_t is_user, boolean_t is_wuser, const char *winname,
730cd37da74Snw 		const char *unixname, idmap_iter_t **iter)
731cd37da74Snw {
732c5c4113dSnw 
733c5c4113dSnw 	idmap_iter_t			*tmpiter;
734c5c4113dSnw 	idmap_list_namerules_1_argument	*arg = NULL;
735c5c4113dSnw 	idmap_namerule			*rule;
736c5c4113dSnw 	idmap_retcode			retcode;
737c5c4113dSnw 
738c5c4113dSnw 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
739c5c4113dSnw 
740c5c4113dSnw 	rule = &arg->rule;
741c5c4113dSnw 	rule->is_user = is_user;
742cd37da74Snw 	rule->is_wuser = is_wuser;
743651c0131Sbaban 	rule->direction = IDMAP_DIRECTION_UNDEF;
7448e228215Sdm 
7458e228215Sdm 	retcode = idmap_strdupnull(&rule->windomain, windomain);
7468e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7478e228215Sdm 		goto errout;
7488e228215Sdm 
7498e228215Sdm 	retcode = idmap_strdupnull(&rule->winname, winname);
7508e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7518e228215Sdm 		goto errout;
7528e228215Sdm 
7538e228215Sdm 	retcode = idmap_strdupnull(&rule->unixname, unixname);
7548e228215Sdm 	if (retcode != IDMAP_SUCCESS)
7558e228215Sdm 		goto errout;
756c5c4113dSnw 
757c5c4113dSnw 	*iter = tmpiter;
758c5c4113dSnw 	return (IDMAP_SUCCESS);
759c5c4113dSnw 
760c5c4113dSnw errout:
761c5c4113dSnw 	__ITER_ERR_RETURN(tmpiter, arg,
762cd37da74Snw 	    xdr_idmap_list_namerules_1_argument, retcode);
763c5c4113dSnw }
764c5c4113dSnw 
765c5c4113dSnw 
766c5c4113dSnw /*
767c5c4113dSnw  * Iterate through the name-based mapping rules
768c5c4113dSnw  *
769c5c4113dSnw  * Input:
770c5c4113dSnw  * iter - iterator
771c5c4113dSnw  *
772c5c4113dSnw  * Output:
773c5c4113dSnw  * windomain - Windows domain
774c5c4113dSnw  * winname   - Windows user or group name
775c5c4113dSnw  * unixname  - Unix user or group name
776c5c4113dSnw  * is_nt4    - NT4 or AD
777c5c4113dSnw  * direction - bi(0), win2unix(1), unix2win(2)
778c5c4113dSnw  *
779c5c4113dSnw  * Return value:
780c5c4113dSnw  * 0   - done
781c5c4113dSnw  * 1   - more results available
782c5c4113dSnw  * < 0 - error
783c5c4113dSnw  */
784c5c4113dSnw idmap_stat
785c5c4113dSnw idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
786cd37da74Snw     char **winname, char **unixname,  boolean_t *is_user,
787cd37da74Snw     boolean_t *is_wuser, boolean_t *is_nt4, int *direction)
788cd37da74Snw {
789c5c4113dSnw 	idmap_namerules_res		*namerules;
790c5c4113dSnw 	idmap_list_namerules_1_argument	*arg;
791c5c4113dSnw 	idmap_retcode			retcode;
792c5c4113dSnw 
793cd37da74Snw 	idmap_namerule_parts_clear(windomain, winname,
794cd37da74Snw 	    unixname, is_user, is_wuser, is_nt4, direction);
795cd37da74Snw 
796c5c4113dSnw 
797c5c4113dSnw 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
798c5c4113dSnw 
799c5c4113dSnw 	namerules = (idmap_namerules_res *)iter->retlist;
800c5c4113dSnw 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
801cd37da74Snw 	    iter->next >= namerules->rules.rules_len)) {
802c5c4113dSnw 
803c5c4113dSnw 		if ((arg = iter->arg) == NULL) {
804c5c4113dSnw 			errno = EINVAL;
805c5c4113dSnw 			return (IDMAP_ERR_ARG);
806c5c4113dSnw 		}
807c5c4113dSnw 		arg->limit = iter->limit;
808c5c4113dSnw 
809c5c4113dSnw 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
810cd37da74Snw 		    iter, arg,
811cd37da74Snw 		    (uchar_t **)&namerules, sizeof (*namerules),
812cd37da74Snw 		    (xdrproc_t)xdr_idmap_list_namerules_1_argument,
813cd37da74Snw 		    (xdrproc_t)xdr_idmap_namerules_res);
814c5c4113dSnw 		if (retcode != IDMAP_SUCCESS)
815c5c4113dSnw 			return (retcode);
816c5c4113dSnw 
817c5c4113dSnw 		if (IDMAP_ERROR(namerules->retcode)) {
818c5c4113dSnw 			retcode  = namerules->retcode;
819c5c4113dSnw 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
820c5c4113dSnw 			free(namerules);
821c5c4113dSnw 			iter->retlist = NULL;
822c5c4113dSnw 			return (retcode);
823c5c4113dSnw 		}
824c5c4113dSnw 		iter->retcode = namerules->retcode;
825c5c4113dSnw 		arg->lastrowid = namerules->lastrowid;
826c5c4113dSnw 	}
827c5c4113dSnw 
828c5c4113dSnw 	if (namerules == NULL || namerules->rules.rules_len == 0)
829c5c4113dSnw 		return (IDMAP_SUCCESS);
830c5c4113dSnw 
831c5c4113dSnw 	if (iter->next >= namerules->rules.rules_len) {
832c5c4113dSnw 		return (IDMAP_ERR_ARG);
833c5c4113dSnw 	}
834c5c4113dSnw 
8358e228215Sdm 	retcode = idmap_strdupnull(windomain,
8368e228215Sdm 	    namerules->rules.rules_val[iter->next].windomain);
8378e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8388e228215Sdm 		goto errout;
8398e228215Sdm 
8408e228215Sdm 	retcode = idmap_strdupnull(winname,
8418e228215Sdm 	    namerules->rules.rules_val[iter->next].winname);
8428e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8438e228215Sdm 		goto errout;
8448e228215Sdm 
8458e228215Sdm 	retcode = idmap_strdupnull(unixname,
8468e228215Sdm 	    namerules->rules.rules_val[iter->next].unixname);
8478e228215Sdm 	if (retcode != IDMAP_SUCCESS)
8488e228215Sdm 		goto errout;
8498e228215Sdm 
850c5c4113dSnw 	if (is_nt4)
851c5c4113dSnw 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
852cd37da74Snw 	if (is_user)
853cd37da74Snw 		*is_user = namerules->rules.rules_val[iter->next].is_user;
854cd37da74Snw 	if (is_wuser)
855cd37da74Snw 		*is_wuser = namerules->rules.rules_val[iter->next].is_wuser;
856c5c4113dSnw 	if (direction)
857c5c4113dSnw 		*direction = namerules->rules.rules_val[iter->next].direction;
858c5c4113dSnw 	iter->next++;
859c5c4113dSnw 
860c5c4113dSnw 	if (iter->next == namerules->rules.rules_len)
861c5c4113dSnw 		return (iter->retcode);
862c5c4113dSnw 	else
863c5c4113dSnw 		return (IDMAP_NEXT);
864c5c4113dSnw 
865c5c4113dSnw errout:
866c5c4113dSnw 	if (windomain && *windomain)
867c5c4113dSnw 		free(*windomain);
868c5c4113dSnw 	if (winname && *winname)
869c5c4113dSnw 		free(*winname);
870c5c4113dSnw 	if (unixname && *unixname)
871c5c4113dSnw 		free(*unixname);
872c5c4113dSnw 	return (retcode);
873c5c4113dSnw }
874c5c4113dSnw 
875c5c4113dSnw 
876c5c4113dSnw /*
877c5c4113dSnw  * Create iterator to get SID to UID/GID mappings
878c5c4113dSnw  *
879c5c4113dSnw  * Output:
880c5c4113dSnw  * iter - iterator
881c5c4113dSnw  */
882c5c4113dSnw idmap_stat
88348258c6bSjp idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag)
884cd37da74Snw {
885c5c4113dSnw 	idmap_iter_t			*tmpiter;
886c5c4113dSnw 	idmap_list_mappings_1_argument	*arg = NULL;
887c5c4113dSnw 
888c5c4113dSnw 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
889c5c4113dSnw 
89048258c6bSjp 	arg->flag = flag;
891c5c4113dSnw 	*iter = tmpiter;
892c5c4113dSnw 	return (IDMAP_SUCCESS);
893c5c4113dSnw }
894c5c4113dSnw 
895c5c4113dSnw 
896c5c4113dSnw /*
897c5c4113dSnw  * Iterate through the SID to UID/GID mappings
898c5c4113dSnw  *
899c5c4113dSnw  * Input:
900c5c4113dSnw  * iter - iterator
901c5c4113dSnw  *
902c5c4113dSnw  * Output:
903c5c4113dSnw  * sid - SID in canonical form
904c5c4113dSnw  * pid - UID or GID
905c5c4113dSnw  *
906c5c4113dSnw  * Return value:
907c5c4113dSnw  * 0   - done
908c5c4113dSnw  * 1   - more results available
909c5c4113dSnw  * < 0 - error
910c5c4113dSnw  */
911c5c4113dSnw idmap_stat
912c5c4113dSnw idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
913cd37da74Snw     idmap_rid_t *rid, uid_t *pid, char **winname,
914cd37da74Snw     char **windomain, char **unixname, boolean_t *is_user,
91548258c6bSjp     boolean_t *is_wuser, int *direction, idmap_info *info)
916cd37da74Snw {
917c5c4113dSnw 	idmap_mappings_res		*mappings;
918c5c4113dSnw 	idmap_list_mappings_1_argument	*arg;
919c5c4113dSnw 	idmap_retcode			retcode;
920c5c4113dSnw 	char				*str;
921c5c4113dSnw 
922c5c4113dSnw 	if (sidprefix)
923c5c4113dSnw 		*sidprefix = NULL;
924c5c4113dSnw 	if (rid)
925c5c4113dSnw 		*rid = UINT32_MAX;
926c5c4113dSnw 	if (winname)
927c5c4113dSnw 		*winname = NULL;
928c5c4113dSnw 	if (windomain)
929c5c4113dSnw 		*windomain = NULL;
930c5c4113dSnw 	if (unixname)
931c5c4113dSnw 		*unixname = NULL;
932c5c4113dSnw 	if (pid)
933c5c4113dSnw 		*pid = UINT32_MAX;
934cd37da74Snw 	if (is_user)
935cd37da74Snw 		*is_user = -1;
936cd37da74Snw 	if (is_wuser)
937cd37da74Snw 		*is_wuser = -1;
938c5c4113dSnw 	if (direction)
939651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
940c5c4113dSnw 
941c5c4113dSnw 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
942c5c4113dSnw 
943c5c4113dSnw 	mappings = (idmap_mappings_res *)iter->retlist;
944c5c4113dSnw 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
945cd37da74Snw 	    iter->next >= mappings->mappings.mappings_len)) {
946c5c4113dSnw 
947c5c4113dSnw 		if ((arg = iter->arg) == NULL) {
948c5c4113dSnw 			errno = EINVAL;
949c5c4113dSnw 			return (IDMAP_ERR_ARG);
950c5c4113dSnw 		}
951c5c4113dSnw 		arg->limit = iter->limit;
952c5c4113dSnw 
953c5c4113dSnw 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
954cd37da74Snw 		    iter, arg,
955cd37da74Snw 		    (uchar_t **)&mappings, sizeof (*mappings),
956cd37da74Snw 		    (xdrproc_t)xdr_idmap_list_mappings_1_argument,
957cd37da74Snw 		    (xdrproc_t)xdr_idmap_mappings_res);
958c5c4113dSnw 		if (retcode != IDMAP_SUCCESS)
959c5c4113dSnw 			return (retcode);
960c5c4113dSnw 
961c5c4113dSnw 		if (IDMAP_ERROR(mappings->retcode)) {
962c5c4113dSnw 			retcode  = mappings->retcode;
963c5c4113dSnw 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
964c5c4113dSnw 			free(mappings);
965c5c4113dSnw 			iter->retlist = NULL;
966c5c4113dSnw 			return (retcode);
967c5c4113dSnw 		}
968c5c4113dSnw 		iter->retcode = mappings->retcode;
969c5c4113dSnw 		arg->lastrowid = mappings->lastrowid;
970c5c4113dSnw 	}
971c5c4113dSnw 
972c5c4113dSnw 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
973c5c4113dSnw 		return (IDMAP_SUCCESS);
974c5c4113dSnw 
975c5c4113dSnw 	if (iter->next >= mappings->mappings.mappings_len) {
976c5c4113dSnw 		return (IDMAP_ERR_ARG);
977c5c4113dSnw 	}
978c5c4113dSnw 
979c5c4113dSnw 	if (sidprefix) {
980c5c4113dSnw 		str = mappings->mappings.mappings_val[iter->next].id1.
981cd37da74Snw 		    idmap_id_u.sid.prefix;
9828edda628Sbaban 		if (str && *str != '\0') {
983c5c4113dSnw 			*sidprefix = strdup(str);
9849581d9f4Sbaban 			if (*sidprefix == NULL) {
9859581d9f4Sbaban 				retcode = IDMAP_ERR_MEMORY;
9869581d9f4Sbaban 				goto errout;
9879581d9f4Sbaban 			}
988c5c4113dSnw 		}
989c5c4113dSnw 	}
990c5c4113dSnw 	if (rid)
991c5c4113dSnw 		*rid = mappings->mappings.mappings_val[iter->next].id1.
992cd37da74Snw 		    idmap_id_u.sid.rid;
9938e228215Sdm 
9948e228215Sdm 	retcode = idmap_strdupnull(windomain,
9958e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id1domain);
9968e228215Sdm 	if (retcode != IDMAP_SUCCESS)
9978e228215Sdm 		goto errout;
9988e228215Sdm 
9998e228215Sdm 	retcode = idmap_strdupnull(winname,
10008e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id1name);
10018e228215Sdm 	if (retcode != IDMAP_SUCCESS)
10028e228215Sdm 		goto errout;
10038e228215Sdm 
10048e228215Sdm 	retcode = idmap_strdupnull(unixname,
10058e228215Sdm 	    mappings->mappings.mappings_val[iter->next].id2name);
10068e228215Sdm 	if (retcode != IDMAP_SUCCESS)
10078e228215Sdm 		goto errout;
10088e228215Sdm 
10098e228215Sdm 
1010c5c4113dSnw 	if (pid)
1011c5c4113dSnw 		*pid = mappings->mappings.mappings_val[iter->next].id2.
1012cd37da74Snw 		    idmap_id_u.uid;
1013c5c4113dSnw 	if (direction)
1014c5c4113dSnw 		*direction = mappings->mappings.mappings_val[iter->next].
1015cd37da74Snw 		    direction;
1016cd37da74Snw 	if (is_user)
1017cd37da74Snw 		*is_user = (mappings->mappings.mappings_val[iter->next].id2
1018cd37da74Snw 		    .idtype == IDMAP_UID)?1:0;
1019cd37da74Snw 	if (is_wuser)
1020cd37da74Snw 		*is_wuser = (mappings->mappings.mappings_val[iter->next].id1
1021cd37da74Snw 		    .idtype == IDMAP_USID)?1:0;
1022cd37da74Snw 
102348258c6bSjp 	if (info) {
102448258c6bSjp 		retcode = idmap_info_cpy(info,
102548258c6bSjp 		    &mappings->mappings.mappings_val[iter->next].info);
102648258c6bSjp 		if (retcode != IDMAP_SUCCESS)
102748258c6bSjp 			goto errout;
102848258c6bSjp 	}
1029c5c4113dSnw 	iter->next++;
1030c5c4113dSnw 
1031c5c4113dSnw 	if (iter->next == mappings->mappings.mappings_len)
1032c5c4113dSnw 		return (iter->retcode);
1033c5c4113dSnw 	else
1034c5c4113dSnw 		return (IDMAP_NEXT);
1035c5c4113dSnw 
1036c5c4113dSnw errout:
1037c5c4113dSnw 	if (sidprefix && *sidprefix)
1038c5c4113dSnw 		free(*sidprefix);
1039c5c4113dSnw 	if (winname && *winname)
1040c5c4113dSnw 		free(*winname);
1041c5c4113dSnw 	if (windomain && *windomain)
1042c5c4113dSnw 		free(*windomain);
1043c5c4113dSnw 	if (unixname && *unixname)
1044c5c4113dSnw 		free(*unixname);
1045c5c4113dSnw 	return (retcode);
1046c5c4113dSnw }
1047c5c4113dSnw 
1048c5c4113dSnw 
1049c5c4113dSnw /*
1050c5c4113dSnw  * Destroy the iterator
1051c5c4113dSnw  */
1052c5c4113dSnw void
1053cd37da74Snw idmap_iter_destroy(idmap_iter_t *iter)
1054cd37da74Snw {
1055c5c4113dSnw 	xdrproc_t _xdr_argument, _xdr_result;
1056c5c4113dSnw 
1057c5c4113dSnw 	if (iter == NULL)
1058c5c4113dSnw 		return;
1059c5c4113dSnw 
1060c5c4113dSnw 	switch (iter->type) {
1061c5c4113dSnw 	case IDMAP_LIST_NAMERULES:
1062c5c4113dSnw 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
1063c5c4113dSnw 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
1064c5c4113dSnw 		break;
1065c5c4113dSnw 	case IDMAP_LIST_MAPPINGS:
1066c5c4113dSnw 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
1067c5c4113dSnw 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
1068c5c4113dSnw 		break;
1069c5c4113dSnw 	default:
1070c5c4113dSnw 		free(iter);
1071c5c4113dSnw 		return;
1072c5c4113dSnw 	};
1073c5c4113dSnw 
1074c5c4113dSnw 	if (iter->arg) {
1075c5c4113dSnw 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
1076c5c4113dSnw 		free(iter->arg);
1077c5c4113dSnw 	}
1078c5c4113dSnw 	if (iter->retlist) {
1079c5c4113dSnw 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
1080c5c4113dSnw 		free(iter->retlist);
1081c5c4113dSnw 	}
1082c5c4113dSnw 	free(iter);
1083c5c4113dSnw }
1084c5c4113dSnw 
1085c5c4113dSnw 
1086c5c4113dSnw /*
1087c5c4113dSnw  * Create handle to get SID to UID/GID mapping entries
1088c5c4113dSnw  *
1089c5c4113dSnw  * Input:
1090c5c4113dSnw  * gh - "get mapping" handle
1091c5c4113dSnw  */
1092c5c4113dSnw idmap_stat
1093cd37da74Snw idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh)
1094cd37da74Snw {
1095c5c4113dSnw 	idmap_get_handle_t	*tmp;
1096c5c4113dSnw 
1097c5c4113dSnw 	/* sanity checks */
1098c5c4113dSnw 	if (handle == NULL || gh == NULL) {
1099c5c4113dSnw 		errno = EINVAL;
1100c5c4113dSnw 		return (IDMAP_ERR_ARG);
1101c5c4113dSnw 	}
1102c5c4113dSnw 
1103c5c4113dSnw 	/* allocate the handle */
1104c5c4113dSnw 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
1105c5c4113dSnw 		errno = ENOMEM;
1106c5c4113dSnw 		return (IDMAP_ERR_MEMORY);
1107c5c4113dSnw 	}
1108c5c4113dSnw 
1109c5c4113dSnw 	tmp->ih = handle;
1110c5c4113dSnw 	*gh = tmp;
1111c5c4113dSnw 	return (IDMAP_SUCCESS);
1112c5c4113dSnw }
1113c5c4113dSnw 
1114c5c4113dSnw 
1115c5c4113dSnw /*
1116c5c4113dSnw  * Given SID, get UID
1117c5c4113dSnw  *
1118c5c4113dSnw  * Input:
1119c5c4113dSnw  * sidprefix  - SID prefix
1120c5c4113dSnw  * rid        - RID
1121c5c4113dSnw  * flag       - flag
1122c5c4113dSnw  *
1123c5c4113dSnw  * Output:
1124c5c4113dSnw  * stat - status of the get request
1125c5c4113dSnw  * uid  - POSIX UID if stat = 0
1126c5c4113dSnw  *
1127c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1128c5c4113dSnw  */
1129c5c4113dSnw idmap_stat
1130c5c4113dSnw idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1131cd37da74Snw 		int flag, uid_t *uid, idmap_stat *stat)
1132cd37da74Snw {
113348258c6bSjp 	return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid,
113448258c6bSjp 	    NULL, stat));
113548258c6bSjp }
113648258c6bSjp 
113748258c6bSjp /*
113848258c6bSjp  * Given SID, get UID
113948258c6bSjp  *
114048258c6bSjp  * Input:
114148258c6bSjp  * sidprefix  - SID prefix
114248258c6bSjp  * rid        - RID
114348258c6bSjp  * flag       - flag
114448258c6bSjp  *
114548258c6bSjp  * Output:
114648258c6bSjp  * stat - status of the get request
114748258c6bSjp  * uid  - POSIX UID if stat = 0
114848258c6bSjp  * how  - mapping type if stat = 0
114948258c6bSjp  *
115048258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
115148258c6bSjp  */
1152c5c4113dSnw 
115348258c6bSjp idmap_stat
115448258c6bSjp idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
115548258c6bSjp 		int flag, uid_t *uid, idmap_info *info, idmap_stat *stat)
115648258c6bSjp {
1157c5c4113dSnw 	idmap_retcode	retcode;
1158651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1159c5c4113dSnw 
1160c5c4113dSnw 	/* sanity checks */
1161c5c4113dSnw 	if (gh == NULL)
1162c5c4113dSnw 		return (IDMAP_ERR_ARG);
1163c5c4113dSnw 	if (uid == NULL || sidprefix == NULL)
1164c5c4113dSnw 		return (IDMAP_ERR_ARG);
1165c5c4113dSnw 
1166c5c4113dSnw 	/* Extend the request array and the return list */
1167c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1168c5c4113dSnw 		goto errout;
1169c5c4113dSnw 
1170c5c4113dSnw 	/* Setup the request */
1171c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1172c5c4113dSnw 	mapping->flag = flag;
1173c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1174c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1175c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1176c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1177c5c4113dSnw 		goto errout;
1178c5c4113dSnw 	}
1179c5c4113dSnw 	mapping->id2.idtype = IDMAP_UID;
1180c5c4113dSnw 
1181c5c4113dSnw 	/* Setup pointers for the result */
1182c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_UID;
1183c5c4113dSnw 	gh->retlist[gh->next].uid = uid;
1184c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
118548258c6bSjp 	gh->retlist[gh->next].info = info;
1186c5c4113dSnw 
1187c5c4113dSnw 	gh->next++;
1188c5c4113dSnw 	return (IDMAP_SUCCESS);
1189c5c4113dSnw 
1190c5c4113dSnw errout:
1191651c0131Sbaban 	/* Batch created so far should still be usable */
1192651c0131Sbaban 	if (mapping)
1193651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1194c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1195c5c4113dSnw 	return (retcode);
1196c5c4113dSnw }
1197c5c4113dSnw 
1198c5c4113dSnw 
1199c5c4113dSnw /*
1200c5c4113dSnw  * Given SID, get GID
1201c5c4113dSnw  *
1202c5c4113dSnw  * Input:
1203c5c4113dSnw  * sidprefix  - SID prefix
1204c5c4113dSnw  * rid        - rid
1205c5c4113dSnw  * flag       - flag
1206c5c4113dSnw  *
1207c5c4113dSnw  * Output:
1208c5c4113dSnw  * stat - status of the get request
1209c5c4113dSnw  * gid  - POSIX GID if stat = 0
1210c5c4113dSnw  *
1211c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1212c5c4113dSnw  */
1213c5c4113dSnw idmap_stat
1214c5c4113dSnw idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1215cd37da74Snw 		int flag, gid_t *gid, idmap_stat *stat)
1216cd37da74Snw {
121748258c6bSjp 	return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid,
121848258c6bSjp 	    NULL, stat));
121948258c6bSjp }
122048258c6bSjp 
122148258c6bSjp 
122248258c6bSjp /*
122348258c6bSjp  * Given SID, get GID
122448258c6bSjp  *
122548258c6bSjp  * Input:
122648258c6bSjp  * sidprefix  - SID prefix
122748258c6bSjp  * rid        - rid
122848258c6bSjp  * flag       - flag
122948258c6bSjp  *
123048258c6bSjp  * Output:
123148258c6bSjp  * stat - status of the get request
123248258c6bSjp  * gid  - POSIX GID if stat = 0
123348258c6bSjp  * how  - mapping type if stat = 0
123448258c6bSjp  *
123548258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
123648258c6bSjp  */
123748258c6bSjp idmap_stat
123848258c6bSjp idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
123948258c6bSjp 		int flag, gid_t *gid, idmap_info *info, idmap_stat *stat)
124048258c6bSjp {
1241c5c4113dSnw 
1242c5c4113dSnw 	idmap_retcode	retcode;
1243651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1244c5c4113dSnw 
1245c5c4113dSnw 	/* sanity checks */
1246c5c4113dSnw 	if (gh == NULL)
1247c5c4113dSnw 		return (IDMAP_ERR_ARG);
1248c5c4113dSnw 	if (gid == NULL || sidprefix == NULL)
1249c5c4113dSnw 		return (IDMAP_ERR_ARG);
1250c5c4113dSnw 
1251c5c4113dSnw 	/* Extend the request array and the return list */
1252c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1253c5c4113dSnw 		goto errout;
1254c5c4113dSnw 
1255c5c4113dSnw 	/* Setup the request */
1256c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1257c5c4113dSnw 	mapping->flag = flag;
1258c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1259c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1260c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1261c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1262c5c4113dSnw 		goto errout;
1263c5c4113dSnw 	}
1264c5c4113dSnw 	mapping->id2.idtype = IDMAP_GID;
1265c5c4113dSnw 
1266c5c4113dSnw 	/* Setup pointers for the result */
1267c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_GID;
1268c5c4113dSnw 	gh->retlist[gh->next].gid = gid;
1269c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
127048258c6bSjp 	gh->retlist[gh->next].info = info;
1271c5c4113dSnw 
1272c5c4113dSnw 	gh->next++;
1273c5c4113dSnw 	return (IDMAP_SUCCESS);
1274c5c4113dSnw 
1275c5c4113dSnw errout:
1276651c0131Sbaban 	if (mapping)
1277651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1278c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1279c5c4113dSnw 	return (retcode);
1280c5c4113dSnw }
1281c5c4113dSnw 
1282c5c4113dSnw 
128348258c6bSjp 
1284c5c4113dSnw /*
1285c5c4113dSnw  * Given SID, get POSIX ID i.e. UID/GID
1286c5c4113dSnw  *
1287c5c4113dSnw  * Input:
1288c5c4113dSnw  * sidprefix  - SID prefix
1289c5c4113dSnw  * rid        - rid
1290c5c4113dSnw  * flag       - flag
1291c5c4113dSnw  *
1292c5c4113dSnw  * Output:
1293c5c4113dSnw  * stat    - status of the get request
1294c5c4113dSnw  * is_user - user or group
1295c5c4113dSnw  * pid     - POSIX UID if stat = 0 and is_user = 1
1296c5c4113dSnw  *           POSIX GID if stat = 0 and is_user = 0
1297c5c4113dSnw  *
1298c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1299c5c4113dSnw  */
1300c5c4113dSnw idmap_stat
1301c5c4113dSnw idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
1302cd37da74Snw 		int flag, uid_t *pid, int *is_user, idmap_stat *stat)
130348258c6bSjp {
130448258c6bSjp 	return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user,
130548258c6bSjp 	    NULL, stat));
130648258c6bSjp }
130748258c6bSjp 
130848258c6bSjp 
130948258c6bSjp 
131048258c6bSjp /*
131148258c6bSjp  * Given SID, get POSIX ID i.e. UID/GID
131248258c6bSjp  *
131348258c6bSjp  * Input:
131448258c6bSjp  * sidprefix  - SID prefix
131548258c6bSjp  * rid        - rid
131648258c6bSjp  * flag       - flag
131748258c6bSjp  *
131848258c6bSjp  * Output:
131948258c6bSjp  * stat    - status of the get request
132048258c6bSjp  * is_user - user or group
132148258c6bSjp  * pid     - POSIX UID if stat = 0 and is_user = 1
132248258c6bSjp  *           POSIX GID if stat = 0 and is_user = 0
132348258c6bSjp  * how     - mapping type if stat = 0
132448258c6bSjp  *
132548258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
132648258c6bSjp  */
132748258c6bSjp idmap_stat
132848258c6bSjp idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
132948258c6bSjp 	int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat)
1330cd37da74Snw {
1331c5c4113dSnw 	idmap_retcode	retcode;
1332651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1333c5c4113dSnw 
1334c5c4113dSnw 	/* sanity checks */
1335c5c4113dSnw 	if (gh == NULL)
1336c5c4113dSnw 		return (IDMAP_ERR_ARG);
1337c5c4113dSnw 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
1338c5c4113dSnw 		return (IDMAP_ERR_ARG);
1339c5c4113dSnw 
1340c5c4113dSnw 	/* Extend the request array and the return list */
1341c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1342c5c4113dSnw 		goto errout;
1343c5c4113dSnw 
1344c5c4113dSnw 	/* Setup the request */
1345c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1346c5c4113dSnw 	mapping->flag = flag;
1347c5c4113dSnw 	mapping->id1.idtype = IDMAP_SID;
1348c5c4113dSnw 	mapping->id1.idmap_id_u.sid.rid = rid;
1349c5c4113dSnw 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
1350c5c4113dSnw 		retcode = IDMAP_ERR_MEMORY;
1351c5c4113dSnw 		goto errout;
1352c5c4113dSnw 	}
1353c5c4113dSnw 	mapping->id2.idtype = IDMAP_POSIXID;
1354c5c4113dSnw 
1355c5c4113dSnw 	/* Setup pointers for the result */
1356c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
1357c5c4113dSnw 	gh->retlist[gh->next].uid = pid;
1358c5c4113dSnw 	gh->retlist[gh->next].gid = pid;
1359c5c4113dSnw 	gh->retlist[gh->next].is_user = is_user;
1360c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
136148258c6bSjp 	gh->retlist[gh->next].info = info;
1362c5c4113dSnw 
1363c5c4113dSnw 	gh->next++;
1364c5c4113dSnw 	return (IDMAP_SUCCESS);
1365c5c4113dSnw 
1366c5c4113dSnw errout:
1367651c0131Sbaban 	if (mapping)
1368651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1369c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1370c5c4113dSnw 	return (retcode);
1371c5c4113dSnw }
1372c5c4113dSnw 
1373c5c4113dSnw 
1374c5c4113dSnw /*
1375c5c4113dSnw  * Given UID, get SID
1376c5c4113dSnw  *
1377c5c4113dSnw  * Input:
1378c5c4113dSnw  * uid  - POSIX UID
1379c5c4113dSnw  * flag - flag
1380c5c4113dSnw  *
1381c5c4113dSnw  * Output:
1382c5c4113dSnw  * stat - status of the get request
1383c5c4113dSnw  * sid  - SID prefix (if stat == 0)
1384c5c4113dSnw  * rid  - rid
1385c5c4113dSnw  *
1386c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1387c5c4113dSnw  */
1388c5c4113dSnw idmap_stat
1389c5c4113dSnw idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
1390cd37da74Snw 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
1391cd37da74Snw {
139248258c6bSjp 	return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid,
139348258c6bSjp 	    NULL, stat));
139448258c6bSjp }
139548258c6bSjp 
139648258c6bSjp 
139748258c6bSjp /*
139848258c6bSjp  * Given UID, get SID
139948258c6bSjp  *
140048258c6bSjp  * Input:
140148258c6bSjp  * uid  - POSIX UID
140248258c6bSjp  * flag - flag
140348258c6bSjp  *
140448258c6bSjp  * Output:
140548258c6bSjp  * stat - status of the get request
140648258c6bSjp  * sid  - SID prefix (if stat == 0)
140748258c6bSjp  * rid  - rid
140848258c6bSjp  * how  - mapping type if stat = 0
140948258c6bSjp  *
141048258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
141148258c6bSjp  */
141248258c6bSjp idmap_stat
141348258c6bSjp idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
141448258c6bSjp 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
141548258c6bSjp {
1416c5c4113dSnw 
1417c5c4113dSnw 	idmap_retcode	retcode;
1418651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1419c5c4113dSnw 
1420c5c4113dSnw 	/* sanity checks */
1421c5c4113dSnw 	if (gh == NULL)
1422c5c4113dSnw 		return (IDMAP_ERR_ARG);
1423c5c4113dSnw 	if (sidprefix == NULL)
1424c5c4113dSnw 		return (IDMAP_ERR_ARG);
1425c5c4113dSnw 
1426c5c4113dSnw 	/* Extend the request array and the return list */
1427c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1428c5c4113dSnw 		goto errout;
1429c5c4113dSnw 
1430c5c4113dSnw 	/* Setup the request */
1431c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1432c5c4113dSnw 	mapping->flag = flag;
1433c5c4113dSnw 	mapping->id1.idtype = IDMAP_UID;
1434c5c4113dSnw 	mapping->id1.idmap_id_u.uid = uid;
1435c5c4113dSnw 	mapping->id2.idtype = IDMAP_SID;
1436c5c4113dSnw 
1437c5c4113dSnw 	/* Setup pointers for the result */
1438c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_SID;
1439c5c4113dSnw 	gh->retlist[gh->next].sidprefix = sidprefix;
1440c5c4113dSnw 	gh->retlist[gh->next].rid = rid;
1441c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
144248258c6bSjp 	gh->retlist[gh->next].info = info;
1443c5c4113dSnw 
1444c5c4113dSnw 	gh->next++;
1445c5c4113dSnw 	return (IDMAP_SUCCESS);
1446c5c4113dSnw 
1447c5c4113dSnw errout:
1448651c0131Sbaban 	if (mapping)
1449651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1450c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1451c5c4113dSnw 	return (retcode);
1452c5c4113dSnw }
1453c5c4113dSnw 
1454c5c4113dSnw 
1455c5c4113dSnw /*
1456c5c4113dSnw  * Given GID, get SID
1457c5c4113dSnw  *
1458c5c4113dSnw  * Input:
1459c5c4113dSnw  * gid  - POSIX GID
1460c5c4113dSnw  * flag - flag
1461c5c4113dSnw  *
1462c5c4113dSnw  * Output:
1463c5c4113dSnw  * stat       - status of the get request
1464c5c4113dSnw  * sidprefix  - SID prefix (if stat == 0)
1465c5c4113dSnw  * rid        - rid
1466c5c4113dSnw  *
1467c5c4113dSnw  * Note: The output parameters will be set by idmap_get_mappings()
1468c5c4113dSnw  */
1469c5c4113dSnw idmap_stat
1470c5c4113dSnw idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
1471cd37da74Snw 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat)
1472cd37da74Snw {
147348258c6bSjp 	return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid,
147448258c6bSjp 	    NULL, stat));
147548258c6bSjp }
147648258c6bSjp 
147748258c6bSjp 
147848258c6bSjp /*
147948258c6bSjp  * Given GID, get SID
148048258c6bSjp  *
148148258c6bSjp  * Input:
148248258c6bSjp  * gid  - POSIX GID
148348258c6bSjp  * flag - flag
148448258c6bSjp  *
148548258c6bSjp  * Output:
148648258c6bSjp  * stat       - status of the get request
148748258c6bSjp  * sidprefix  - SID prefix (if stat == 0)
148848258c6bSjp  * rid        - rid
148948258c6bSjp  * how        - mapping type if stat = 0
149048258c6bSjp  *
149148258c6bSjp  * Note: The output parameters will be set by idmap_get_mappings()
149248258c6bSjp  */
149348258c6bSjp idmap_stat
149448258c6bSjp idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
149548258c6bSjp 	char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat)
149648258c6bSjp {
1497c5c4113dSnw 
1498c5c4113dSnw 	idmap_retcode	retcode;
1499651c0131Sbaban 	idmap_mapping	*mapping = NULL;
1500c5c4113dSnw 
1501c5c4113dSnw 	/* sanity checks */
1502c5c4113dSnw 	if (gh == NULL)
1503c5c4113dSnw 		return (IDMAP_ERR_ARG);
1504c5c4113dSnw 	if (sidprefix == NULL)
1505c5c4113dSnw 		return (IDMAP_ERR_ARG);
1506c5c4113dSnw 
1507c5c4113dSnw 	/* Extend the request array and the return list */
1508c5c4113dSnw 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1509c5c4113dSnw 		goto errout;
1510c5c4113dSnw 
1511c5c4113dSnw 	/* Setup the request */
1512c5c4113dSnw 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1513c5c4113dSnw 	mapping->flag = flag;
1514c5c4113dSnw 	mapping->id1.idtype = IDMAP_GID;
1515c5c4113dSnw 	mapping->id1.idmap_id_u.gid = gid;
1516c5c4113dSnw 	mapping->id2.idtype = IDMAP_SID;
1517c5c4113dSnw 
1518c5c4113dSnw 	/* Setup pointers for the result */
1519c5c4113dSnw 	gh->retlist[gh->next].idtype = IDMAP_SID;
1520c5c4113dSnw 	gh->retlist[gh->next].sidprefix = sidprefix;
1521c5c4113dSnw 	gh->retlist[gh->next].rid = rid;
1522c5c4113dSnw 	gh->retlist[gh->next].stat = stat;
152348258c6bSjp 	gh->retlist[gh->next].info = info;
1524c5c4113dSnw 
1525c5c4113dSnw 	gh->next++;
1526c5c4113dSnw 	return (IDMAP_SUCCESS);
1527c5c4113dSnw 
1528c5c4113dSnw errout:
1529651c0131Sbaban 	if (mapping)
1530651c0131Sbaban 		(void) memset(mapping, 0, sizeof (*mapping));
1531c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1532c5c4113dSnw 	return (retcode);
1533c5c4113dSnw }
1534c5c4113dSnw 
1535c5c4113dSnw 
1536c5c4113dSnw /*
1537c5c4113dSnw  * Process the batched "get mapping" requests. The results (i.e.
1538c5c4113dSnw  * status and identity) will be available in the data areas
1539c5c4113dSnw  * provided by individual requests.
1540c5c4113dSnw  */
1541c5c4113dSnw idmap_stat
1542cd37da74Snw idmap_get_mappings(idmap_get_handle_t *gh)
1543cd37da74Snw {
1544c5c4113dSnw 	CLIENT		*clnt;
1545c5c4113dSnw 	enum clnt_stat	clntstat;
1546c5c4113dSnw 	idmap_retcode	retcode;
1547c5c4113dSnw 	idmap_ids_res	res;
1548c5c4113dSnw 	idmap_id	*id;
1549c5c4113dSnw 	int		i;
1550c5c4113dSnw 
1551c5c4113dSnw 	if (gh == NULL) {
1552c5c4113dSnw 		errno = EINVAL;
1553c5c4113dSnw 		return (IDMAP_ERR_ARG);
1554c5c4113dSnw 	}
1555c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
1556c5c4113dSnw 
1557c5c4113dSnw 	(void) memset(&res, 0, sizeof (idmap_ids_res));
1558c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
1559cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping_batch,
1560cd37da74Snw 	    (caddr_t)&gh->batch,
1561cd37da74Snw 	    (xdrproc_t)xdr_idmap_ids_res,
1562cd37da74Snw 	    (caddr_t)&res,
1563cd37da74Snw 	    TIMEOUT);
1564c5c4113dSnw 	if (clntstat != RPC_SUCCESS) {
1565651c0131Sbaban 		retcode = _idmap_rpc2stat(clnt);
1566c5c4113dSnw 		goto out;
1567c5c4113dSnw 	}
1568c5c4113dSnw 	if (res.retcode != IDMAP_SUCCESS) {
1569c5c4113dSnw 		retcode = res.retcode;
1570c5c4113dSnw 		goto out;
1571c5c4113dSnw 	}
1572c5c4113dSnw 	for (i = 0; i < gh->next; i++) {
1573c5c4113dSnw 		if (i >= res.ids.ids_len) {
1574c5c4113dSnw 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1575c5c4113dSnw 			continue;
1576c5c4113dSnw 		}
1577c5c4113dSnw 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
1578c5c4113dSnw 		id = &res.ids.ids_val[i].id;
1579c5c4113dSnw 		switch (id->idtype) {
1580c5c4113dSnw 		case IDMAP_UID:
1581c5c4113dSnw 			if (gh->retlist[i].uid)
1582c5c4113dSnw 				*gh->retlist[i].uid = id->idmap_id_u.uid;
1583c5c4113dSnw 			if (gh->retlist[i].is_user)
1584c5c4113dSnw 				*gh->retlist[i].is_user = 1;
1585c5c4113dSnw 			break;
1586c5c4113dSnw 		case IDMAP_GID:
1587c5c4113dSnw 			if (gh->retlist[i].gid)
1588c5c4113dSnw 				*gh->retlist[i].gid = id->idmap_id_u.gid;
1589c5c4113dSnw 			if (gh->retlist[i].is_user)
1590c5c4113dSnw 				*gh->retlist[i].is_user = 0;
1591c5c4113dSnw 			break;
159262c60062Sbaban 		case IDMAP_POSIXID:
159362c60062Sbaban 			if (gh->retlist[i].uid)
159462c60062Sbaban 				*gh->retlist[i].uid = 60001;
159562c60062Sbaban 			if (gh->retlist[i].is_user)
159662c60062Sbaban 				*gh->retlist[i].is_user = -1;
159762c60062Sbaban 			break;
1598c5c4113dSnw 		case IDMAP_SID:
1599cd37da74Snw 		case IDMAP_USID:
1600cd37da74Snw 		case IDMAP_GSID:
1601c5c4113dSnw 			if (gh->retlist[i].rid)
1602c5c4113dSnw 				*gh->retlist[i].rid = id->idmap_id_u.sid.rid;
1603c5c4113dSnw 			if (gh->retlist[i].sidprefix) {
16048edda628Sbaban 				if (id->idmap_id_u.sid.prefix == NULL ||
16058edda628Sbaban 				    *id->idmap_id_u.sid.prefix == '\0') {
1606c5c4113dSnw 					*gh->retlist[i].sidprefix = NULL;
1607c5c4113dSnw 					break;
1608c5c4113dSnw 				}
1609c5c4113dSnw 				*gh->retlist[i].sidprefix =
1610cd37da74Snw 				    strdup(id->idmap_id_u.sid.prefix);
1611c5c4113dSnw 				if (*gh->retlist[i].sidprefix == NULL)
1612c5c4113dSnw 					*gh->retlist[i].stat =
1613cd37da74Snw 					    IDMAP_ERR_MEMORY;
1614c5c4113dSnw 			}
1615c5c4113dSnw 			break;
1616c5c4113dSnw 		case IDMAP_NONE:
1617c5c4113dSnw 			break;
1618c5c4113dSnw 		default:
1619c5c4113dSnw 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1620c5c4113dSnw 			break;
1621c5c4113dSnw 		}
162248258c6bSjp 		if (gh->retlist[i].info != NULL)
162348258c6bSjp 			(void) idmap_info_cpy(gh->retlist[i].info,
162448258c6bSjp 			    &res.ids.ids_val[i].info);
1625c5c4113dSnw 	}
1626c5c4113dSnw 	retcode = IDMAP_SUCCESS;
1627c5c4113dSnw 
1628c5c4113dSnw out:
1629651c0131Sbaban 	_IDMAP_RESET_GET_HANDLE(gh);
1630c5c4113dSnw 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
1631c5c4113dSnw 	errno = idmap_stat2errno(retcode);
1632c5c4113dSnw 	return (retcode);
1633c5c4113dSnw }
1634c5c4113dSnw 
1635c5c4113dSnw 
1636c5c4113dSnw /*
1637c5c4113dSnw  * Destroy the "get mapping" handle
1638c5c4113dSnw  */
1639c5c4113dSnw void
1640cd37da74Snw idmap_get_destroy(idmap_get_handle_t *gh)
1641cd37da74Snw {
1642c5c4113dSnw 	if (gh == NULL)
1643c5c4113dSnw 		return;
1644c5c4113dSnw 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1645c5c4113dSnw 	if (gh->retlist)
1646c5c4113dSnw 		free(gh->retlist);
1647c5c4113dSnw 	free(gh);
1648c5c4113dSnw }
1649c5c4113dSnw 
1650c5c4113dSnw 
1651c5c4113dSnw /*
1652c5c4113dSnw  * Get windows to unix mapping
1653c5c4113dSnw  */
1654c5c4113dSnw idmap_stat
1655c5c4113dSnw idmap_get_w2u_mapping(idmap_handle_t *handle,
1656c5c4113dSnw 		const char *sidprefix, idmap_rid_t *rid,
1657c5c4113dSnw 		const char *winname, const char *windomain,
1658cd37da74Snw 		int flag, int *is_user, int *is_wuser,
165948258c6bSjp 		uid_t *pid, char **unixname, int *direction, idmap_info *info)
1660cd37da74Snw {
1661c5c4113dSnw 	CLIENT			*clnt;
1662c5c4113dSnw 	enum clnt_stat		clntstat;
1663c5c4113dSnw 	idmap_mapping		request, *mapping;
1664c5c4113dSnw 	idmap_mappings_res	result;
1665c5c4113dSnw 	idmap_retcode		retcode, rc;
1666c5c4113dSnw 
1667c5c4113dSnw 	if (handle == NULL) {
1668c5c4113dSnw 		errno = EINVAL;
1669c5c4113dSnw 		return (IDMAP_ERR_ARG);
1670c5c4113dSnw 	}
1671c5c4113dSnw 
1672c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1673c5c4113dSnw 
1674c5c4113dSnw 	(void) memset(&request, 0, sizeof (request));
1675c5c4113dSnw 	(void) memset(&result, 0, sizeof (result));
1676c5c4113dSnw 
1677c5c4113dSnw 	if (pid)
1678c5c4113dSnw 		*pid = UINT32_MAX;
1679c5c4113dSnw 	if (unixname)
1680c5c4113dSnw 		*unixname = NULL;
1681c5c4113dSnw 	if (direction)
1682651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
1683c5c4113dSnw 
1684c5c4113dSnw 	request.flag = flag;
1685c5c4113dSnw 	request.id1.idtype = IDMAP_SID;
1686c5c4113dSnw 	if (sidprefix && rid) {
1687c5c4113dSnw 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
1688c5c4113dSnw 		request.id1.idmap_id_u.sid.rid = *rid;
1689c5c4113dSnw 	} else if (winname) {
16908e228215Sdm 		retcode = idmap_strdupnull(&request.id1name, winname);
1691c5a946baSbaban 		if (retcode != IDMAP_SUCCESS)
1692c5c4113dSnw 			goto out;
16938e228215Sdm 
16948e228215Sdm 		retcode = idmap_strdupnull(&request.id1domain, windomain);
1695c5a946baSbaban 		if (retcode != IDMAP_SUCCESS)
16968e228215Sdm 			goto out;
16978e228215Sdm 
1698c5c4113dSnw 		request.id1.idmap_id_u.sid.prefix = NULL;
1699c5c4113dSnw 	} else {
1700c5c4113dSnw 		errno = EINVAL;
1701c5c4113dSnw 		return (IDMAP_ERR_ARG);
1702c5c4113dSnw 	}
1703c5c4113dSnw 
1704cd37da74Snw 	if (*is_user == 1)
1705c5c4113dSnw 		request.id2.idtype = IDMAP_UID;
1706c5c4113dSnw 	else if (*is_user == 0)
1707c5c4113dSnw 		request.id2.idtype = IDMAP_GID;
1708c5c4113dSnw 	else
1709c5c4113dSnw 		request.id2.idtype = IDMAP_POSIXID;
1710c5c4113dSnw 
1711cd37da74Snw 	if (*is_wuser == 1)
1712cd37da74Snw 		request.id1.idtype = IDMAP_USID;
1713cd37da74Snw 	else if (*is_wuser == 0)
1714cd37da74Snw 		request.id1.idtype = IDMAP_GSID;
1715cd37da74Snw 	else
1716cd37da74Snw 		request.id1.idtype = IDMAP_SID;
1717cd37da74Snw 
1718c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1719cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1720cd37da74Snw 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1721cd37da74Snw 	    TIMEOUT);
1722c5c4113dSnw 
1723651c0131Sbaban 	if (clntstat != RPC_SUCCESS)
1724651c0131Sbaban 		return (_idmap_rpc2stat(clnt));
1725c5c4113dSnw 
1726c5c4113dSnw 	retcode = result.retcode;
1727c5c4113dSnw 
1728c5c4113dSnw 	if ((mapping = result.mappings.mappings_val) == NULL) {
1729c5c4113dSnw 		if (retcode == IDMAP_SUCCESS)
1730c5c4113dSnw 			retcode = IDMAP_ERR_NORESULT;
1731c5c4113dSnw 		goto out;
1732c5c4113dSnw 	}
1733c5c4113dSnw 
173462c60062Sbaban 	if (mapping->id2.idtype == IDMAP_UID) {
1735cd37da74Snw 		*is_user = 1;
173662c60062Sbaban 	} else if (mapping->id2.idtype == IDMAP_GID) {
1737cd37da74Snw 		*is_user = 0;
173862c60062Sbaban 	} else {
173962c60062Sbaban 		goto out;
174062c60062Sbaban 	}
1741cd37da74Snw 
1742cd37da74Snw 	if (mapping->id1.idtype == IDMAP_USID) {
1743cd37da74Snw 		*is_wuser = 1;
1744cd37da74Snw 	} else if (mapping->id1.idtype == IDMAP_GSID) {
1745cd37da74Snw 		*is_wuser = 0;
1746cd37da74Snw 	} else {
1747cd37da74Snw 		goto out;
1748cd37da74Snw 	}
1749cd37da74Snw 
1750c5c4113dSnw 	if (direction)
1751c5c4113dSnw 		*direction = mapping->direction;
1752c5c4113dSnw 	if (pid)
1753c5c4113dSnw 		*pid = mapping->id2.idmap_id_u.uid;
17548e228215Sdm 
17558e228215Sdm 	rc = idmap_strdupnull(unixname, mapping->id2name);
17568e228215Sdm 	if (rc != IDMAP_SUCCESS)
17578e228215Sdm 		retcode = rc;
1758c5c4113dSnw 
175948258c6bSjp 	rc = idmap_info_cpy(info, &mapping->info);
176048258c6bSjp 	if (rc != IDMAP_SUCCESS)
176148258c6bSjp 		retcode = rc;
176248258c6bSjp 
1763c5c4113dSnw out:
1764c5c4113dSnw 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
1765c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
1766c5c4113dSnw 		errno = idmap_stat2errno(retcode);
1767c5c4113dSnw 	return (retcode);
1768c5c4113dSnw }
1769c5c4113dSnw 
1770c5c4113dSnw 
1771c5c4113dSnw /*
1772c5c4113dSnw  * Get unix to windows mapping
1773c5c4113dSnw  */
1774c5c4113dSnw idmap_stat
1775c5c4113dSnw idmap_get_u2w_mapping(idmap_handle_t *handle,
1776c5c4113dSnw 		uid_t *pid, const char *unixname,
1777cd37da74Snw 		int flag, int is_user, int *is_wuser,
1778c5c4113dSnw 		char **sidprefix, idmap_rid_t *rid,
1779c5c4113dSnw 		char **winname, char **windomain,
178048258c6bSjp 		int *direction, idmap_info *info)
1781cd37da74Snw {
1782c5c4113dSnw 	CLIENT			*clnt;
1783c5c4113dSnw 	enum clnt_stat		clntstat;
1784c5c4113dSnw 	idmap_mapping		request, *mapping;
1785c5c4113dSnw 	idmap_mappings_res	result;
1786c5c4113dSnw 	idmap_retcode		retcode, rc;
1787c5c4113dSnw 
1788c5c4113dSnw 	if (handle == NULL) {
1789c5c4113dSnw 		errno = EINVAL;
1790c5c4113dSnw 		return (IDMAP_ERR_ARG);
1791c5c4113dSnw 	}
1792c5c4113dSnw 
1793c5c4113dSnw 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1794c5c4113dSnw 
1795c5c4113dSnw 	if (sidprefix)
1796c5c4113dSnw 		*sidprefix = NULL;
1797c5c4113dSnw 	if (winname)
1798c5c4113dSnw 		*winname = NULL;
1799c5c4113dSnw 	if (windomain)
1800c5c4113dSnw 		*windomain = NULL;
1801c5c4113dSnw 	if (rid)
1802c5c4113dSnw 		*rid = UINT32_MAX;
1803c5c4113dSnw 	if (direction)
1804651c0131Sbaban 		*direction = IDMAP_DIRECTION_UNDEF;
1805c5c4113dSnw 
1806c5c4113dSnw 	(void) memset(&request, 0, sizeof (request));
1807c5c4113dSnw 	(void) memset(&result, 0, sizeof (result));
1808c5c4113dSnw 
1809c5c4113dSnw 	request.flag = flag;
1810c5c4113dSnw 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
1811c5c4113dSnw 
1812c5c4113dSnw 	if (pid && *pid != UINT32_MAX) {
1813c5c4113dSnw 		request.id1.idmap_id_u.uid = *pid;
1814c5c4113dSnw 	} else if (unixname) {
18158e228215Sdm 		request.id1name = (char *)unixname;
1816c5c4113dSnw 		request.id1.idmap_id_u.uid = UINT32_MAX;
1817c5c4113dSnw 	} else {
1818c5c4113dSnw 		errno = EINVAL;
1819c5c4113dSnw 		return (IDMAP_ERR_ARG);
1820c5c4113dSnw 	}
1821c5c4113dSnw 
1822cd37da74Snw 	if (is_wuser == NULL)
1823cd37da74Snw 		request.id2.idtype = IDMAP_SID;
1824cd37da74Snw 	else if (*is_wuser == -1)
1825cd37da74Snw 		request.id2.idtype = IDMAP_SID;
1826cd37da74Snw 	else if (*is_wuser == 0)
1827cd37da74Snw 		request.id2.idtype = IDMAP_GSID;
1828cd37da74Snw 	else if (*is_wuser == 1)
1829cd37da74Snw 		request.id2.idtype = IDMAP_USID;
1830c5c4113dSnw 
1831c5c4113dSnw 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1832cd37da74Snw 	    (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1833cd37da74Snw 	    (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1834cd37da74Snw 	    TIMEOUT);
1835c5c4113dSnw 
1836651c0131Sbaban 	if (clntstat != RPC_SUCCESS)
1837651c0131Sbaban 		return (_idmap_rpc2stat(clnt));
1838c5c4113dSnw 
1839c5c4113dSnw 	retcode = result.retcode;
1840c5c4113dSnw 
1841c5c4113dSnw 	if ((mapping = result.mappings.mappings_val) == NULL) {
1842c5c4113dSnw 		if (retcode == IDMAP_SUCCESS)
1843c5c4113dSnw 			retcode = IDMAP_ERR_NORESULT;
1844c5c4113dSnw 		goto out;
1845c5c4113dSnw 	}
1846c5c4113dSnw 
1847cd37da74Snw 	if (direction != NULL)
1848c5c4113dSnw 		*direction = mapping->direction;
1849cd37da74Snw 
185048258c6bSjp 	if (is_wuser != NULL) {
185148258c6bSjp 		if (mapping->id2.idtype == IDMAP_USID)
185248258c6bSjp 			*is_wuser = 1;
185348258c6bSjp 		else if (mapping->id2.idtype == IDMAP_GSID)
185448258c6bSjp 			*is_wuser = 0;
185548258c6bSjp 		else
185648258c6bSjp 			*is_wuser = -1;
185748258c6bSjp 	}
1858cd37da74Snw 
18598edda628Sbaban 	if (sidprefix && mapping->id2.idmap_id_u.sid.prefix &&
18608edda628Sbaban 	    *mapping->id2.idmap_id_u.sid.prefix != '\0') {
1861c5c4113dSnw 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
1862c5c4113dSnw 		if (*sidprefix == NULL) {
1863c5c4113dSnw 			retcode = IDMAP_ERR_MEMORY;
1864c5c4113dSnw 			goto errout;
1865c5c4113dSnw 		}
1866c5c4113dSnw 	}
1867c5c4113dSnw 	if (rid)
1868c5c4113dSnw 		*rid = mapping->id2.idmap_id_u.sid.rid;
18698e228215Sdm 
18708e228215Sdm 	rc = idmap_strdupnull(winname, mapping->id2name);
18718e228215Sdm 	if (rc != IDMAP_SUCCESS)
18728e228215Sdm 		retcode = rc;
18738e228215Sdm 
18748e228215Sdm 	rc = idmap_strdupnull(windomain, mapping->id2domain);
18758e228215Sdm 	if (rc != IDMAP_SUCCESS)
18768e228215Sdm 		retcode = rc;
1877c5c4113dSnw 
187848258c6bSjp 	rc = idmap_info_cpy(info, &mapping->info);
187948258c6bSjp 	if (rc != IDMAP_SUCCESS)
188048258c6bSjp 		retcode = rc;
188148258c6bSjp 
1882c5c4113dSnw 	goto out;
1883c5c4113dSnw 
1884c5c4113dSnw errout:
1885c5c4113dSnw 	if (sidprefix && *sidprefix) {
1886c5c4113dSnw 		free(*sidprefix);
1887c5c4113dSnw 		*sidprefix = NULL;
1888c5c4113dSnw 	}
1889c5c4113dSnw 	if (winname && *winname) {
1890c5c4113dSnw 		free(*winname);
1891c5c4113dSnw 		*winname = NULL;
1892c5c4113dSnw 	}
1893c5c4113dSnw 	if (windomain && *windomain) {
1894c5c4113dSnw 		free(*windomain);
1895c5c4113dSnw 		*windomain = NULL;
1896c5c4113dSnw 	}
1897c5c4113dSnw 
1898c5c4113dSnw out:
1899c5c4113dSnw 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
1900c5c4113dSnw 	if (retcode != IDMAP_SUCCESS)
1901c5c4113dSnw 		errno = idmap_stat2errno(retcode);
1902c5c4113dSnw 	return (retcode);
1903c5c4113dSnw }
1904c5c4113dSnw 
1905c5c4113dSnw 
1906c5c4113dSnw 
1907c5c4113dSnw #define	gettext(s)	s
1908c5c4113dSnw static stat_table_t stattable[] = {
1909c5c4113dSnw 	{IDMAP_SUCCESS, gettext("Success"), 0},
1910c5c4113dSnw 	{IDMAP_NEXT, gettext("More results available"), 0},
1911c5c4113dSnw 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
1912c5c4113dSnw 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
1913c5c4113dSnw 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
1914c5c4113dSnw 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
1915c5c4113dSnw 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
1916c5c4113dSnw 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
1917651c0131Sbaban 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP},
1918c5c4113dSnw 	{IDMAP_ERR_W2U_NAMERULE,
1919c5c4113dSnw 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
1920c5c4113dSnw 	{IDMAP_ERR_U2W_NAMERULE,
1921c5c4113dSnw 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
1922c5c4113dSnw 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
1923c5c4113dSnw 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
1924c5c4113dSnw 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
1925c5c4113dSnw 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
1926c5c4113dSnw 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
1927651c0131Sbaban 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF},
1928c5c4113dSnw 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
1929c5c4113dSnw 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
1930651c0131Sbaban 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY},
19318edda628Sbaban 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES},
1932c5c4113dSnw 	{IDMAP_ERR_NOMAPPING,
1933c5c4113dSnw 		gettext("Mapping not found or inhibited"), EINVAL},
1934c5c4113dSnw 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
1935c5c4113dSnw 		gettext("New mapping needs to be created"), EINVAL},
1936c5c4113dSnw 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
1937c5c4113dSnw 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
1938c5c4113dSnw 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
1939c5c4113dSnw 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
1940c5c4113dSnw 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
1941c5c4113dSnw 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
1942c5c4113dSnw 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
1943c5c4113dSnw 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
1944c5c4113dSnw 		gettext("No mapping for well-known SID"), EINVAL},
1945c5c4113dSnw 	{IDMAP_ERR_RETRIABLE_NET_ERR,
194662c60062Sbaban 		gettext("Windows lookup failed"), EINVAL},
194762c60062Sbaban 	{IDMAP_ERR_W2U_NAMERULE_CONFLICT,
194862c60062Sbaban 		gettext("Duplicate rule or conflicts with an existing "
194962c60062Sbaban 		"Windows to UNIX name-based rule"), EINVAL},
195062c60062Sbaban 	{IDMAP_ERR_U2W_NAMERULE_CONFLICT,
195162c60062Sbaban 		gettext("Duplicate rule or conflicts with an existing "
195262c60062Sbaban 		"Unix to Windows name-based rule"), EINVAL},
19530dcc7149Snw 	{IDMAP_ERR_BAD_UTF8,
19540dcc7149Snw 		gettext("Invalid or illegal UTF-8 sequence found in "
19550dcc7149Snw 		"a given Windows entity name or domain name"), EINVAL},
195648258c6bSjp 	{IDMAP_ERR_NONEGENERATED,
195748258c6bSjp 		gettext("Mapping not found and none created (see -c option)"),
195848258c6bSjp 		EINVAL},
1959*479ac375Sdm 	{IDMAP_ERR_PROP_UNKNOWN,
1960*479ac375Sdm 		gettext("Undefined property"),
1961*479ac375Sdm 		EINVAL},
1962*479ac375Sdm 	{IDMAP_ERR_NS_LDAP_CFG,
1963*479ac375Sdm 		gettext("Native LDAP configuration error"), EINVAL},
1964*479ac375Sdm 	{IDMAP_ERR_NS_LDAP_PARTIAL,
1965*479ac375Sdm 		gettext("Partial result from Native LDAP"), EINVAL},
1966*479ac375Sdm 	{IDMAP_ERR_NS_LDAP_OP_FAILED,
1967*479ac375Sdm 		gettext("Native LDAP operation failed"), EINVAL},
1968*479ac375Sdm 	{IDMAP_ERR_NS_LDAP_BAD_WINNAME,
1969*479ac375Sdm 		gettext("Improper winname form found in Native LDAP"), EINVAL},
1970c5c4113dSnw 	{-1, NULL, 0}
1971c5c4113dSnw };
1972c5c4113dSnw #undef	gettext
1973c5c4113dSnw 
1974c5c4113dSnw 
1975c5c4113dSnw /*
1976c5c4113dSnw  * Get description of status code
1977c5c4113dSnw  *
1978c5c4113dSnw  * Input:
1979c5c4113dSnw  * status - Status code returned by libidmap API call
1980c5c4113dSnw  *
1981c5c4113dSnw  * Return Value:
1982c5c4113dSnw  * human-readable localized description of idmap_stat
1983c5c4113dSnw  */
1984c5c4113dSnw /* ARGSUSED */
1985c5c4113dSnw const char *
1986cd37da74Snw idmap_stat2string(idmap_handle_t *handle, idmap_stat status)
1987cd37da74Snw {
1988c5c4113dSnw 	int i;
1989c5c4113dSnw 
1990c5c4113dSnw 	for (i = 0; stattable[i].msg; i++) {
1991c5c4113dSnw 		if (stattable[i].retcode == status)
19929581d9f4Sbaban 			return (gettext(stattable[i].msg));
1993c5c4113dSnw 	}
1994c5c4113dSnw 	return (gettext("Unknown error"));
1995c5c4113dSnw }
1996c5c4113dSnw 
1997c5c4113dSnw 
1998c5c4113dSnw static int
1999cd37da74Snw idmap_stat2errno(idmap_stat stat)
2000cd37da74Snw {
2001c5c4113dSnw 	int i;
2002c5c4113dSnw 	for (i = 0; stattable[i].msg; i++) {
2003c5c4113dSnw 		if (stattable[i].retcode == stat)
2004c5c4113dSnw 			return (stattable[i].errnum);
2005c5c4113dSnw 	}
2006c5c4113dSnw 	return (EINVAL);
2007c5c4113dSnw }
2008c5c4113dSnw 
2009c5c4113dSnw 
2010c5c4113dSnw /*
2011c5c4113dSnw  * Get status code from string
2012c5c4113dSnw  */
2013c5c4113dSnw idmap_stat
2014cd37da74Snw idmap_string2stat(const char *str)
2015cd37da74Snw {
2016c5c4113dSnw 	if (str == NULL)
2017c5c4113dSnw 		return (IDMAP_ERR_INTERNAL);
2018c5c4113dSnw 
2019c5c4113dSnw #define	return_cmp(a) \
2020c5c4113dSnw 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
2021c5c4113dSnw 		return (IDMAP_ERR_ ## a);
2022c5c4113dSnw 
2023c5c4113dSnw 	return_cmp(OTHER);
2024c5c4113dSnw 	return_cmp(INTERNAL);
2025c5c4113dSnw 	return_cmp(MEMORY);
2026c5c4113dSnw 	return_cmp(NORESULT);
2027c5c4113dSnw 	return_cmp(NOTUSER);
2028c5c4113dSnw 	return_cmp(NOTGROUP);
2029c5c4113dSnw 	return_cmp(NOTSUPPORTED);
2030c5c4113dSnw 	return_cmp(W2U_NAMERULE);
2031c5c4113dSnw 	return_cmp(U2W_NAMERULE);
2032c5c4113dSnw 	return_cmp(CACHE);
2033c5c4113dSnw 	return_cmp(DB);
2034c5c4113dSnw 	return_cmp(ARG);
2035c5c4113dSnw 	return_cmp(SID);
2036c5c4113dSnw 	return_cmp(IDTYPE);
2037c5c4113dSnw 	return_cmp(RPC_HANDLE);
2038c5c4113dSnw 	return_cmp(RPC);
2039c5c4113dSnw 	return_cmp(CLIENT_HANDLE);
2040c5c4113dSnw 	return_cmp(BUSY);
2041c5c4113dSnw 	return_cmp(PERMISSION_DENIED);
2042c5c4113dSnw 	return_cmp(NOMAPPING);
2043c5c4113dSnw 	return_cmp(NEW_ID_ALLOC_REQD);
2044c5c4113dSnw 	return_cmp(DOMAIN);
2045c5c4113dSnw 	return_cmp(SECURITY);
2046c5c4113dSnw 	return_cmp(NOTFOUND);
2047c5c4113dSnw 	return_cmp(DOMAIN_NOTFOUND);
2048c5c4113dSnw 	return_cmp(MEMORY);
2049c5c4113dSnw 	return_cmp(UPDATE_NOTALLOWED);
2050c5c4113dSnw 	return_cmp(CFG);
2051c5c4113dSnw 	return_cmp(CFG_CHANGE);
2052c5c4113dSnw 	return_cmp(NOTMAPPED_WELLKNOWN);
2053c5c4113dSnw 	return_cmp(RETRIABLE_NET_ERR);
205462c60062Sbaban 	return_cmp(W2U_NAMERULE_CONFLICT);
205562c60062Sbaban 	return_cmp(U2W_NAMERULE_CONFLICT);
2056*479ac375Sdm 	return_cmp(BAD_UTF8);
2057*479ac375Sdm 	return_cmp(NONEGENERATED);
2058*479ac375Sdm 	return_cmp(PROP_UNKNOWN);
2059*479ac375Sdm 	return_cmp(NS_LDAP_CFG);
2060*479ac375Sdm 	return_cmp(NS_LDAP_PARTIAL);
2061*479ac375Sdm 	return_cmp(NS_LDAP_OP_FAILED);
2062*479ac375Sdm 	return_cmp(NS_LDAP_BAD_WINNAME);
2063c5c4113dSnw #undef return_cmp
2064c5c4113dSnw 
2065c5c4113dSnw 	return (IDMAP_ERR_OTHER);
2066c5c4113dSnw }
2067c5c4113dSnw 
2068c5c4113dSnw 
2069c5c4113dSnw /*
2070c5c4113dSnw  * Map the given status to one that can be returned by the protocol
2071c5c4113dSnw  */
2072c5c4113dSnw idmap_stat
2073cd37da74Snw idmap_stat4prot(idmap_stat status)
2074cd37da74Snw {
2075c5c4113dSnw 	switch (status) {
2076c5c4113dSnw 	case IDMAP_ERR_MEMORY:
2077c5c4113dSnw 	case IDMAP_ERR_CACHE:
2078c5c4113dSnw 		return (IDMAP_ERR_INTERNAL);
2079c5c4113dSnw 	}
2080c5c4113dSnw 	return (status);
2081c5c4113dSnw }
2082dd5829d1Sbaban 
2083dd5829d1Sbaban 
20848e228215Sdm /*
2085c5a946baSbaban  * This is a convenience routine which duplicates a string after
2086c5a946baSbaban  * checking for NULL pointers. This function will return success if
2087c5a946baSbaban  * either the 'to' OR 'from' pointers are NULL.
20888e228215Sdm  */
20898e228215Sdm static idmap_stat
2090cd37da74Snw idmap_strdupnull(char **to, const char *from)
2091cd37da74Snw {
2092c5a946baSbaban 	if (to == NULL)
2093c5a946baSbaban 		return (IDMAP_SUCCESS);
2094c5a946baSbaban 
20958e228215Sdm 	if (from == NULL || *from == '\0') {
20968e228215Sdm 		*to = NULL;
20978e228215Sdm 		return (IDMAP_SUCCESS);
20988e228215Sdm 	}
20998e228215Sdm 
21008e228215Sdm 	*to = strdup(from);
21018e228215Sdm 	if (*to == NULL)
21028e228215Sdm 		return (IDMAP_ERR_MEMORY);
21038e228215Sdm 	return (IDMAP_SUCCESS);
21048e228215Sdm }
21058e228215Sdm 
210648258c6bSjp 
21078e228215Sdm idmap_stat
2108cd37da74Snw idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from)
2109cd37da74Snw {
21108e228215Sdm 	idmap_stat retval;
21118e228215Sdm 
211248258c6bSjp 	if (to == NULL)
211348258c6bSjp 		return (IDMAP_SUCCESS);
211448258c6bSjp 
21158e228215Sdm 	(void) memcpy(to, from, sizeof (idmap_namerule));
211648258c6bSjp 	to->windomain = NULL;
211748258c6bSjp 	to->winname = NULL;
211848258c6bSjp 	to->unixname = NULL;
21198e228215Sdm 
21208e228215Sdm 	retval = idmap_strdupnull(&to->windomain, from->windomain);
21218e228215Sdm 	if (retval != IDMAP_SUCCESS)
21228e228215Sdm 		return (retval);
21238e228215Sdm 
21248e228215Sdm 	retval = idmap_strdupnull(&to->winname, from->winname);
212548258c6bSjp 	if (retval != IDMAP_SUCCESS) {
212648258c6bSjp 		free(to->windomain);
212748258c6bSjp 		to->windomain = NULL;
21288e228215Sdm 		return (retval);
212948258c6bSjp 	}
21308e228215Sdm 
21318e228215Sdm 	retval = idmap_strdupnull(&to->unixname, from->unixname);
213248258c6bSjp 	if (retval != IDMAP_SUCCESS) {
213348258c6bSjp 		free(to->windomain);
213448258c6bSjp 		to->windomain = NULL;
213548258c6bSjp 		free(to->winname);
213648258c6bSjp 		to->winname = NULL;
213748258c6bSjp 		return (retval);
213848258c6bSjp 	}
213948258c6bSjp 
214048258c6bSjp 	return (retval);
214148258c6bSjp }
214248258c6bSjp 
214348258c6bSjp 
214448258c6bSjp static
214548258c6bSjp idmap_stat
214648258c6bSjp idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from)
214748258c6bSjp {
214848258c6bSjp 	idmap_stat retval;
214948258c6bSjp 
215048258c6bSjp 	if (to == NULL)
215148258c6bSjp 		return (IDMAP_SUCCESS);
215248258c6bSjp 
215348258c6bSjp 	retval = idmap_strdupnull(&to->dn, from->dn);
215448258c6bSjp 	if (retval != IDMAP_SUCCESS)
215548258c6bSjp 		return (retval);
215648258c6bSjp 
215748258c6bSjp 	retval = idmap_strdupnull(&to->attr, from->attr);
215848258c6bSjp 	if (retval != IDMAP_SUCCESS) {
215948258c6bSjp 		free(to->dn);
216048258c6bSjp 		to->dn = NULL;
216148258c6bSjp 		return (retval);
216248258c6bSjp 	}
216348258c6bSjp 
216448258c6bSjp 	retval = idmap_strdupnull(&to->value, from->value);
216548258c6bSjp 	if (retval != IDMAP_SUCCESS) {
216648258c6bSjp 		free(to->dn);
216748258c6bSjp 		to->dn = NULL;
216848258c6bSjp 		free(to->attr);
216948258c6bSjp 		to->attr = NULL;
217048258c6bSjp 		return (retval);
217148258c6bSjp 	}
217248258c6bSjp 
217348258c6bSjp 	return (retval);
217448258c6bSjp }
217548258c6bSjp 
217648258c6bSjp 
217748258c6bSjp idmap_stat
217848258c6bSjp idmap_info_cpy(idmap_info *to, idmap_info *from)
217948258c6bSjp {
218048258c6bSjp 	idmap_stat retval = IDMAP_SUCCESS;
218148258c6bSjp 
218248258c6bSjp 	if (to == NULL)
218348258c6bSjp 		return (IDMAP_SUCCESS);
218448258c6bSjp 
218548258c6bSjp 	(void) memset(to, 0, sizeof (idmap_info));
218648258c6bSjp 
218748258c6bSjp 	to->src = from->src;
218848258c6bSjp 	to->how.map_type = from->how.map_type;
218948258c6bSjp 	switch (to->how.map_type) {
219048258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
219148258c6bSjp 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad,
219248258c6bSjp 		    &from->how.idmap_how_u.ad);
219348258c6bSjp 		break;
219448258c6bSjp 
219548258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
219648258c6bSjp 		retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap,
219748258c6bSjp 		    &from->how.idmap_how_u.nldap);
219848258c6bSjp 		break;
219948258c6bSjp 
220048258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
220148258c6bSjp 		retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule,
220248258c6bSjp 		    &from->how.idmap_how_u.rule);
220348258c6bSjp 		break;
220448258c6bSjp 
220548258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
220648258c6bSjp 		break;
220748258c6bSjp 
220848258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
220948258c6bSjp 		break;
221048258c6bSjp 
221148258c6bSjp 	case IDMAP_MAP_TYPE_KNOWN_SID:
221248258c6bSjp 		break;
221348258c6bSjp 	}
221448258c6bSjp 	return (retval);
221548258c6bSjp }
221648258c6bSjp 
221748258c6bSjp 
221848258c6bSjp /*
221948258c6bSjp  * This routine is similar to idmap_info_cpy, but the strings
222048258c6bSjp  * are moved from the "from" info to the "to" info.
222148258c6bSjp  * This routine is equivelent of:
222248258c6bSjp  *
222348258c6bSjp  *	idmap_info_cpy(to,from);
222448258c6bSjp  *	idmap_info_free(from);
222548258c6bSjp  */
222648258c6bSjp idmap_stat
222748258c6bSjp idmap_info_mov(idmap_info *to, idmap_info *from)
222848258c6bSjp {
222948258c6bSjp 	idmap_stat retval = IDMAP_SUCCESS;
223048258c6bSjp 
223148258c6bSjp 	if (to == NULL) {
223248258c6bSjp 		idmap_info_free(from);
223348258c6bSjp 		return (IDMAP_SUCCESS);
223448258c6bSjp 	}
223548258c6bSjp 	(void) memcpy(to, from, sizeof (idmap_info));
223648258c6bSjp 
223748258c6bSjp 	(void) memset(from, 0, sizeof (idmap_info));
22388e228215Sdm 
22398e228215Sdm 	return (retval);
22408e228215Sdm }
22418e228215Sdm 
22428e228215Sdm 
224348258c6bSjp void
224448258c6bSjp idmap_info_free(idmap_info *info)
224548258c6bSjp {
224648258c6bSjp 	idmap_how *how;
224748258c6bSjp 
224848258c6bSjp 	if (info == NULL)
224948258c6bSjp 		return;
225048258c6bSjp 
225148258c6bSjp 	how = &info->how;
225248258c6bSjp 	switch (how->map_type) {
225348258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
225448258c6bSjp 		free(how->idmap_how_u.ad.dn);
225548258c6bSjp 		how->idmap_how_u.ad.dn = NULL;
225648258c6bSjp 		free(how->idmap_how_u.ad.attr);
225748258c6bSjp 		how->idmap_how_u.ad.attr = NULL;
225848258c6bSjp 		free(how->idmap_how_u.ad.value);
225948258c6bSjp 		how->idmap_how_u.ad.value = NULL;
226048258c6bSjp 		break;
226148258c6bSjp 
226248258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
226348258c6bSjp 		free(how->idmap_how_u.nldap.dn);
226448258c6bSjp 		how->idmap_how_u.nldap.dn = NULL;
226548258c6bSjp 		free(how->idmap_how_u.nldap.attr);
226648258c6bSjp 		how->idmap_how_u.nldap.attr = NULL;
226748258c6bSjp 		free(how->idmap_how_u.nldap.value);
226848258c6bSjp 		how->idmap_how_u.nldap.value = NULL;
226948258c6bSjp 		break;
227048258c6bSjp 
227148258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
227248258c6bSjp 		free(how->idmap_how_u.rule.windomain);
227348258c6bSjp 		how->idmap_how_u.rule.windomain = NULL;
227448258c6bSjp 		free(how->idmap_how_u.rule.winname);
227548258c6bSjp 		how->idmap_how_u.rule.winname = NULL;
227648258c6bSjp 		free(how->idmap_how_u.rule.unixname);
227748258c6bSjp 		how->idmap_how_u.rule.unixname = NULL;
227848258c6bSjp 		break;
227948258c6bSjp 
228048258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
228148258c6bSjp 		break;
228248258c6bSjp 
228348258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
228448258c6bSjp 		break;
228548258c6bSjp 	}
228648258c6bSjp 	how->map_type = IDMAP_MAP_TYPE_UNKNOWN;
228748258c6bSjp 	info->src = IDMAP_MAP_SRC_UNKNOWN;
228848258c6bSjp }
228948258c6bSjp 
229048258c6bSjp 
2291dd5829d1Sbaban /*
2292dd5829d1Sbaban  * Get uid given Windows name
2293dd5829d1Sbaban  */
2294dd5829d1Sbaban idmap_stat
2295cd37da74Snw idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid)
2296cd37da74Snw {
2297dd5829d1Sbaban 	idmap_handle_t	*ih;
2298dd5829d1Sbaban 	idmap_retcode	rc;
2299cd37da74Snw 	int		is_user = 1;
2300cd37da74Snw 	int		is_wuser = -1;
2301dd5829d1Sbaban 
2302dd5829d1Sbaban 	if (uid == NULL)
2303dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2304dd5829d1Sbaban 
2305dd5829d1Sbaban 	/* Get mapping */
2306dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2307dd5829d1Sbaban 		return (rc);
2308dd5829d1Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
230948258c6bSjp 	    &is_user, &is_wuser, uid, NULL, NULL, NULL);
2310dd5829d1Sbaban 	(void) idmap_fini(ih);
2311dd5829d1Sbaban 
2312dd5829d1Sbaban 	/*
2313dd5829d1Sbaban 	 * XXX Until we have diagonal mapping support, check if
2314dd5829d1Sbaban 	 * the given name belongs to a user
2315dd5829d1Sbaban 	 */
2316dd5829d1Sbaban 	if (rc == IDMAP_SUCCESS && !is_user)
2317dd5829d1Sbaban 		return (IDMAP_ERR_NOTUSER);
2318dd5829d1Sbaban 	return (rc);
2319dd5829d1Sbaban }
2320dd5829d1Sbaban 
2321dd5829d1Sbaban 
2322dd5829d1Sbaban /*
2323dd5829d1Sbaban  * Get gid given Windows name
2324dd5829d1Sbaban  */
2325dd5829d1Sbaban idmap_stat
2326cd37da74Snw idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid)
2327cd37da74Snw {
2328dd5829d1Sbaban 	idmap_handle_t	*ih;
2329dd5829d1Sbaban 	idmap_retcode	rc;
2330cd37da74Snw 	int		is_user = 0;
2331cd37da74Snw 	int		is_wuser = -1;
2332dd5829d1Sbaban 
2333dd5829d1Sbaban 	if (gid == NULL)
2334dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2335dd5829d1Sbaban 
2336dd5829d1Sbaban 	/* Get mapping */
2337dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2338dd5829d1Sbaban 		return (rc);
2339dd5829d1Sbaban 	rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0,
234048258c6bSjp 	    &is_user, &is_wuser, gid, NULL, NULL, NULL);
2341dd5829d1Sbaban 	(void) idmap_fini(ih);
2342dd5829d1Sbaban 
2343dd5829d1Sbaban 	/*
2344dd5829d1Sbaban 	 * XXX Until we have diagonal mapping support, check if
2345dd5829d1Sbaban 	 * the given name belongs to a group
2346dd5829d1Sbaban 	 */
2347dd5829d1Sbaban 	if (rc == IDMAP_SUCCESS && is_user)
2348dd5829d1Sbaban 		return (IDMAP_ERR_NOTGROUP);
2349dd5829d1Sbaban 	return (rc);
2350dd5829d1Sbaban }
2351dd5829d1Sbaban 
2352dd5829d1Sbaban 
2353dd5829d1Sbaban /*
2354dd5829d1Sbaban  * Get winname given pid
2355dd5829d1Sbaban  */
2356dd5829d1Sbaban static idmap_retcode
2357cd37da74Snw idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain)
2358cd37da74Snw {
2359dd5829d1Sbaban 	idmap_handle_t	*ih;
2360dd5829d1Sbaban 	idmap_retcode	rc;
2361dd5829d1Sbaban 	int		len;
2362dd5829d1Sbaban 	char		*winname, *windomain;
2363dd5829d1Sbaban 
2364dd5829d1Sbaban 	if (name == NULL)
2365dd5829d1Sbaban 		return (IDMAP_ERR_ARG);
2366dd5829d1Sbaban 
2367dd5829d1Sbaban 	/* Get mapping */
2368dd5829d1Sbaban 	if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS)
2369dd5829d1Sbaban 		return (rc);
2370cd37da74Snw 	rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, NULL,
237148258c6bSjp 	    NULL, &winname, &windomain, NULL, NULL);
2372dd5829d1Sbaban 	(void) idmap_fini(ih);
2373dd5829d1Sbaban 
2374dd5829d1Sbaban 	/* Return on error */
2375dd5829d1Sbaban 	if (rc != IDMAP_SUCCESS)
2376dd5829d1Sbaban 		return (rc);
2377dd5829d1Sbaban 
2378dd5829d1Sbaban 	/*
2379dd5829d1Sbaban 	 * The given PID may have been mapped to a locally
2380dd5829d1Sbaban 	 * generated SID in which case there isn't any
2381dd5829d1Sbaban 	 * Windows name
2382dd5829d1Sbaban 	 */
2383dd5829d1Sbaban 	if (winname == NULL || windomain == NULL) {
2384dd5829d1Sbaban 		idmap_free(winname);
2385dd5829d1Sbaban 		idmap_free(windomain);
2386dd5829d1Sbaban 		return (IDMAP_ERR_NORESULT);
2387dd5829d1Sbaban 	}
2388dd5829d1Sbaban 
2389dd5829d1Sbaban 	if (domain != NULL) {
2390dd5829d1Sbaban 		*name = winname;
2391dd5829d1Sbaban 		*domain = windomain;
2392dd5829d1Sbaban 	} else {
2393dd5829d1Sbaban 		len = strlen(winname) + strlen(windomain) + 2;
2394dd5829d1Sbaban 		if ((*name = malloc(len)) != NULL)
2395dd5829d1Sbaban 			(void) snprintf(*name, len, "%s@%s", winname,
2396dd5829d1Sbaban 			    windomain);
2397dd5829d1Sbaban 		else
2398dd5829d1Sbaban 			rc = IDMAP_ERR_MEMORY;
2399dd5829d1Sbaban 		idmap_free(winname);
2400dd5829d1Sbaban 		idmap_free(windomain);
2401dd5829d1Sbaban 	}
2402dd5829d1Sbaban 	return (rc);
2403dd5829d1Sbaban }
2404dd5829d1Sbaban 
2405dd5829d1Sbaban 
2406dd5829d1Sbaban /*
2407dd5829d1Sbaban  * Get winname given uid
2408dd5829d1Sbaban  */
2409dd5829d1Sbaban idmap_stat
2410cd37da74Snw idmap_getwinnamebyuid(uid_t uid, char **name, char **domain)
2411cd37da74Snw {
2412dd5829d1Sbaban 	return (idmap_getwinnamebypid(uid, 1, name, domain));
2413dd5829d1Sbaban }
2414dd5829d1Sbaban 
2415dd5829d1Sbaban 
2416dd5829d1Sbaban /*
2417dd5829d1Sbaban  * Get winname given gid
2418dd5829d1Sbaban  */
2419dd5829d1Sbaban idmap_stat
2420cd37da74Snw idmap_getwinnamebygid(gid_t gid, char **name, char **domain)
2421cd37da74Snw {
2422dd5829d1Sbaban 	return (idmap_getwinnamebypid(gid, 0, name, domain));
2423dd5829d1Sbaban }
2424*479ac375Sdm 
2425*479ac375Sdm 
2426*479ac375Sdm /* printflike */
2427*479ac375Sdm void
2428*479ac375Sdm idmapdlog(int pri, const char *format, ...) {
2429*479ac375Sdm 	va_list args;
2430*479ac375Sdm 
2431*479ac375Sdm 	va_start(args, format);
2432*479ac375Sdm 	if (pri <= logstate.max_pri) {
2433*479ac375Sdm 		(void) vfprintf(stderr, format, args);
2434*479ac375Sdm 		(void) fprintf(stderr, "\n");
2435*479ac375Sdm 	}
2436*479ac375Sdm 
2437*479ac375Sdm 	/*
2438*479ac375Sdm 	 * We don't want to fill up the logs with useless messages when
2439*479ac375Sdm 	 * we're degraded, but we still want to log.
2440*479ac375Sdm 	 */
2441*479ac375Sdm 	if (logstate.degraded)
2442*479ac375Sdm 		pri = LOG_DEBUG;
2443*479ac375Sdm 
2444*479ac375Sdm 	if (logstate.write_syslog)
2445*479ac375Sdm 		(void) vsyslog(pri, format, args);
2446*479ac375Sdm 	va_end(args);
2447*479ac375Sdm }
2448*479ac375Sdm 
2449*479ac375Sdm void
2450*479ac375Sdm idmap_log_stderr(int pri)
2451*479ac375Sdm {
2452*479ac375Sdm 	logstate.max_pri = pri;
2453*479ac375Sdm }
2454*479ac375Sdm 
2455*479ac375Sdm void
2456*479ac375Sdm idmap_log_syslog(bool_t what)
2457*479ac375Sdm {
2458*479ac375Sdm 	logstate.write_syslog = what;
2459*479ac375Sdm }
2460*479ac375Sdm 
2461*479ac375Sdm void
2462*479ac375Sdm idmap_log_degraded(bool_t what)
2463*479ac375Sdm {
2464*479ac375Sdm 	logstate.degraded = what;
2465*479ac375Sdm }
2466