1*4520Snw141292 /*
2*4520Snw141292  * CDDL HEADER START
3*4520Snw141292  *
4*4520Snw141292  * The contents of this file are subject to the terms of the
5*4520Snw141292  * Common Development and Distribution License (the "License").
6*4520Snw141292  * You may not use this file except in compliance with the License.
7*4520Snw141292  *
8*4520Snw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4520Snw141292  * or http://www.opensolaris.org/os/licensing.
10*4520Snw141292  * See the License for the specific language governing permissions
11*4520Snw141292  * and limitations under the License.
12*4520Snw141292  *
13*4520Snw141292  * When distributing Covered Code, include this CDDL HEADER in each
14*4520Snw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4520Snw141292  * If applicable, add the following below this CDDL HEADER, with the
16*4520Snw141292  * fields enclosed by brackets "[]" replaced with your own identifying
17*4520Snw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4520Snw141292  *
19*4520Snw141292  * CDDL HEADER END
20*4520Snw141292  */
21*4520Snw141292 /*
22*4520Snw141292  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*4520Snw141292  * Use is subject to license terms.
24*4520Snw141292  */
25*4520Snw141292 
26*4520Snw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*4520Snw141292 
28*4520Snw141292 /*
29*4520Snw141292  * libidmap API
30*4520Snw141292  */
31*4520Snw141292 
32*4520Snw141292 #include <stdlib.h>
33*4520Snw141292 #include <inttypes.h>
34*4520Snw141292 #include <errno.h>
35*4520Snw141292 #include <strings.h>
36*4520Snw141292 #include <ctype.h>
37*4520Snw141292 #include <sys/param.h>
38*4520Snw141292 #include <sys/types.h>
39*4520Snw141292 #include <sys/stat.h>
40*4520Snw141292 #include <dlfcn.h>
41*4520Snw141292 #include <libintl.h>
42*4520Snw141292 #include "idmap_impl.h"
43*4520Snw141292 
44*4520Snw141292 static struct timeval TIMEOUT = { 25, 0 };
45*4520Snw141292 
46*4520Snw141292 static int idmap_stat2errno(idmap_stat);
47*4520Snw141292 
48*4520Snw141292 int __idmap_verbose;
49*4520Snw141292 
50*4520Snw141292 #define	__ITER_CREATE(itera, argu, handl, ityp)\
51*4520Snw141292 	if (handl == NULL) {\
52*4520Snw141292 		errno = EINVAL;\
53*4520Snw141292 		return (IDMAP_ERR_ARG);\
54*4520Snw141292 	}\
55*4520Snw141292 	itera = calloc(1, sizeof (*itera));\
56*4520Snw141292 	if (itera == NULL) {\
57*4520Snw141292 		if (__idmap_verbose)\
58*4520Snw141292 			(void) fprintf(stderr, gettext("Out of memory\n"));\
59*4520Snw141292 		errno = ENOMEM;\
60*4520Snw141292 		return (IDMAP_ERR_MEMORY);\
61*4520Snw141292 	}\
62*4520Snw141292 	argu = calloc(1, sizeof (*argu));\
63*4520Snw141292 	if (argu == NULL) {\
64*4520Snw141292 		free(itera);\
65*4520Snw141292 		if (__idmap_verbose)\
66*4520Snw141292 			(void) fprintf(stderr, gettext("Out of memory\n"));\
67*4520Snw141292 		errno = ENOMEM;\
68*4520Snw141292 		return (IDMAP_ERR_MEMORY);\
69*4520Snw141292 	}\
70*4520Snw141292 	itera->ih = handl;\
71*4520Snw141292 	itera->type = ityp;\
72*4520Snw141292 	itera->retcode = IDMAP_NEXT;\
73*4520Snw141292 	itera->limit = 1024;\
74*4520Snw141292 	itera->arg = argu;
75*4520Snw141292 
76*4520Snw141292 
77*4520Snw141292 #define	__ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\
78*4520Snw141292 	if (argu) {\
79*4520Snw141292 		xdr_free(xdr_argu, (caddr_t)argu);\
80*4520Snw141292 		free(argu);\
81*4520Snw141292 	}\
82*4520Snw141292 	if (itera)\
83*4520Snw141292 		free(itera);\
84*4520Snw141292 	return (iretcod);
85*4520Snw141292 
86*4520Snw141292 
87*4520Snw141292 #define	__ITER_CHECK(itera, ityp)\
88*4520Snw141292 	if (itera == NULL) {\
89*4520Snw141292 		if (__idmap_verbose)\
90*4520Snw141292 			(void) fprintf(stderr,\
91*4520Snw141292 				gettext("%s: Iterator is null\n"), me);\
92*4520Snw141292 		errno = EINVAL;\
93*4520Snw141292 		return (IDMAP_ERR_ARG);\
94*4520Snw141292 	}\
95*4520Snw141292 	if (itera->type != ityp) {\
96*4520Snw141292 		if (__idmap_verbose)\
97*4520Snw141292 			(void) fprintf(stderr,\
98*4520Snw141292 				gettext("%s: Invalid iterator\n"), me);\
99*4520Snw141292 		errno = EINVAL;\
100*4520Snw141292 		return (IDMAP_ERR_ARG);\
101*4520Snw141292 	}
102*4520Snw141292 
103*4520Snw141292 
104*4520Snw141292 /*
105*4520Snw141292  * Free memory allocated by libidmap API
106*4520Snw141292  *
107*4520Snw141292  * Input:
108*4520Snw141292  * ptr - memory to be freed
109*4520Snw141292  */
110*4520Snw141292 void
111*4520Snw141292 idmap_free(void *ptr) {
112*4520Snw141292 	free(ptr);
113*4520Snw141292 }
114*4520Snw141292 
115*4520Snw141292 
116*4520Snw141292 /*
117*4520Snw141292  * Verbose on/off switch (Private)
118*4520Snw141292  *
119*4520Snw141292  * Input:
120*4520Snw141292  * on - TRUE=on, FALSE=off
121*4520Snw141292  */
122*4520Snw141292 void
123*4520Snw141292 idmap_set_verbose(boolean_t on) {
124*4520Snw141292 	__idmap_verbose = (on == B_TRUE)?1:0;
125*4520Snw141292 }
126*4520Snw141292 
127*4520Snw141292 
128*4520Snw141292 /*
129*4520Snw141292  * Create and Initialize idmap client handle for rpc/doors
130*4520Snw141292  *
131*4520Snw141292  * Output:
132*4520Snw141292  * handle - idmap handle
133*4520Snw141292  */
134*4520Snw141292 idmap_stat
135*4520Snw141292 idmap_init(idmap_handle_t **handle) {
136*4520Snw141292 	CLIENT			*clnt = NULL;
137*4520Snw141292 	struct idmap_handle	*hptr;
138*4520Snw141292 
139*4520Snw141292 	*handle = NULL;
140*4520Snw141292 	hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr));
141*4520Snw141292 	if (hptr == NULL)
142*4520Snw141292 		return (IDMAP_ERR_MEMORY);
143*4520Snw141292 
144*4520Snw141292 	clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, 0);
145*4520Snw141292 	if (clnt == NULL) {
146*4520Snw141292 		if (__idmap_verbose)
147*4520Snw141292 			clnt_pcreateerror("clnt_door_create");
148*4520Snw141292 		free(hptr);
149*4520Snw141292 		return (IDMAP_ERR_RPC);
150*4520Snw141292 	}
151*4520Snw141292 	hptr->type = _IDMAP_HANDLE_RPC_DOORS;
152*4520Snw141292 	hptr->privhandle = clnt;
153*4520Snw141292 	*handle = hptr;
154*4520Snw141292 	return (IDMAP_SUCCESS);
155*4520Snw141292 }
156*4520Snw141292 
157*4520Snw141292 
158*4520Snw141292 /*
159*4520Snw141292  * Finalize idmap handle
160*4520Snw141292  *
161*4520Snw141292  * Input:
162*4520Snw141292  * handle - idmap handle
163*4520Snw141292  */
164*4520Snw141292 idmap_stat
165*4520Snw141292 idmap_fini(idmap_handle_t *handle) {
166*4520Snw141292 	CLIENT			*clnt;
167*4520Snw141292 	struct idmap_handle	*hptr;
168*4520Snw141292 
169*4520Snw141292 	if (handle == NULL)
170*4520Snw141292 		return (IDMAP_SUCCESS);
171*4520Snw141292 
172*4520Snw141292 	hptr = (struct idmap_handle *)handle;
173*4520Snw141292 
174*4520Snw141292 	switch (hptr->type) {
175*4520Snw141292 	case _IDMAP_HANDLE_RPC_DOORS:
176*4520Snw141292 		clnt = (CLIENT *)hptr->privhandle;
177*4520Snw141292 		if (clnt) {
178*4520Snw141292 			if (clnt->cl_auth)
179*4520Snw141292 				auth_destroy(clnt->cl_auth);
180*4520Snw141292 			clnt_destroy(clnt);
181*4520Snw141292 		}
182*4520Snw141292 		break;
183*4520Snw141292 	default:
184*4520Snw141292 		break;
185*4520Snw141292 	}
186*4520Snw141292 	free(hptr);
187*4520Snw141292 	return (IDMAP_SUCCESS);
188*4520Snw141292 }
189*4520Snw141292 
190*4520Snw141292 
191*4520Snw141292 
192*4520Snw141292 /*
193*4520Snw141292  * Create/Initialize handle for updates
194*4520Snw141292  *
195*4520Snw141292  * Output:
196*4520Snw141292  * udthandle - update handle
197*4520Snw141292  */
198*4520Snw141292 idmap_stat
199*4520Snw141292 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) {
200*4520Snw141292 	idmap_udt_handle_t	*tmp;
201*4520Snw141292 	const char		*me = "idmap_udt_create";
202*4520Snw141292 
203*4520Snw141292 	if (handle == NULL || udthandle == NULL) {
204*4520Snw141292 		errno = EINVAL;
205*4520Snw141292 		return (IDMAP_ERR_ARG);
206*4520Snw141292 	}
207*4520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
208*4520Snw141292 		if (__idmap_verbose)
209*4520Snw141292 			(void) fprintf(stderr,
210*4520Snw141292 				gettext("%s: Out of memory\n"), me);
211*4520Snw141292 		errno = ENOMEM;
212*4520Snw141292 		return (IDMAP_ERR_MEMORY);
213*4520Snw141292 	}
214*4520Snw141292 
215*4520Snw141292 	tmp->ih = handle;
216*4520Snw141292 	*udthandle = tmp;
217*4520Snw141292 	return (IDMAP_SUCCESS);
218*4520Snw141292 }
219*4520Snw141292 
220*4520Snw141292 
221*4520Snw141292 /*
222*4520Snw141292  * All the updates specified by the update handle are committed
223*4520Snw141292  * in a single transaction. i.e either all succeed or none.
224*4520Snw141292  *
225*4520Snw141292  * Input:
226*4520Snw141292  * udthandle - update handle with the update requests
227*4520Snw141292  *
228*4520Snw141292  * Return value:
229*4520Snw141292  * Status of the commit
230*4520Snw141292  */
231*4520Snw141292 idmap_stat
232*4520Snw141292 idmap_udt_commit(idmap_udt_handle_t *udthandle) {
233*4520Snw141292 	CLIENT			*clnt;
234*4520Snw141292 	enum clnt_stat		clntstat;
235*4520Snw141292 	idmap_retcode		retcode;
236*4520Snw141292 	const char		*me = "idmap_udt_commit";
237*4520Snw141292 
238*4520Snw141292 	if (udthandle == NULL) {
239*4520Snw141292 		if (__idmap_verbose)
240*4520Snw141292 			(void) fprintf(stderr,
241*4520Snw141292 				gettext("%s: Invalid handle\n"), me);
242*4520Snw141292 		errno = EINVAL;
243*4520Snw141292 		return (IDMAP_ERR_ARG);
244*4520Snw141292 	}
245*4520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt);
246*4520Snw141292 	clntstat = clnt_call(clnt, IDMAP_UPDATE,
247*4520Snw141292 		(xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch,
248*4520Snw141292 		(xdrproc_t)xdr_idmap_retcode, (caddr_t)&retcode,
249*4520Snw141292 		TIMEOUT);
250*4520Snw141292 	if (clntstat != RPC_SUCCESS) {
251*4520Snw141292 		if (__idmap_verbose)
252*4520Snw141292 			clnt_perror(clnt, "IDMAP_UPDATE");
253*4520Snw141292 		return (IDMAP_ERR_RPC);
254*4520Snw141292 	}
255*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
256*4520Snw141292 		errno = idmap_stat2errno(retcode);
257*4520Snw141292 	return (retcode);
258*4520Snw141292 }
259*4520Snw141292 
260*4520Snw141292 
261*4520Snw141292 /*
262*4520Snw141292  * Destroy the update handle
263*4520Snw141292  */
264*4520Snw141292 void
265*4520Snw141292 idmap_udt_destroy(idmap_udt_handle_t *udthandle) {
266*4520Snw141292 	if (udthandle == NULL)
267*4520Snw141292 		return;
268*4520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
269*4520Snw141292 	free(udthandle);
270*4520Snw141292 }
271*4520Snw141292 
272*4520Snw141292 
273*4520Snw141292 idmap_stat
274*4520Snw141292 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain,
275*4520Snw141292 		boolean_t is_user, const char *winname, const char *unixname,
276*4520Snw141292 		boolean_t is_nt4, int direction) {
277*4520Snw141292 	idmap_retcode	retcode;
278*4520Snw141292 	idmap_namerule	*rule;
279*4520Snw141292 	idmap_utf8str	*str;
280*4520Snw141292 
281*4520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_ADD_NAMERULE);
282*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
283*4520Snw141292 		goto errout;
284*4520Snw141292 
285*4520Snw141292 	rule = &udthandle->batch.
286*4520Snw141292 		idmap_update_batch_val[udthandle->next].
287*4520Snw141292 		idmap_update_op_u.rule;
288*4520Snw141292 	rule->is_user = is_user;
289*4520Snw141292 	rule->direction = direction;
290*4520Snw141292 	rule->is_nt4 = is_nt4;
291*4520Snw141292 	if (windomain) {
292*4520Snw141292 		str = &rule->windomain;
293*4520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
294*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
295*4520Snw141292 			goto errout;
296*4520Snw141292 	}
297*4520Snw141292 	if (winname) {
298*4520Snw141292 		str = &rule->winname;
299*4520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
300*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
301*4520Snw141292 			goto errout;
302*4520Snw141292 	}
303*4520Snw141292 	if (unixname) {
304*4520Snw141292 		str = &rule->unixname;
305*4520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
306*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
307*4520Snw141292 			goto errout;
308*4520Snw141292 	}
309*4520Snw141292 	udthandle->next++;
310*4520Snw141292 	return (IDMAP_SUCCESS);
311*4520Snw141292 
312*4520Snw141292 errout:
313*4520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
314*4520Snw141292 	errno = idmap_stat2errno(retcode);
315*4520Snw141292 	return (retcode);
316*4520Snw141292 }
317*4520Snw141292 
318*4520Snw141292 
319*4520Snw141292 /* ARGSUSED */
320*4520Snw141292 idmap_stat
321*4520Snw141292 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user,
322*4520Snw141292 		const char *windomain, const char *winname,
323*4520Snw141292 		const char *unixname, int direction) {
324*4520Snw141292 	idmap_retcode	retcode;
325*4520Snw141292 	idmap_namerule	*rule;
326*4520Snw141292 	idmap_utf8str	*str;
327*4520Snw141292 
328*4520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_RM_NAMERULE);
329*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
330*4520Snw141292 		goto errout;
331*4520Snw141292 
332*4520Snw141292 	rule = &udthandle->batch.
333*4520Snw141292 		idmap_update_batch_val[udthandle->next].
334*4520Snw141292 		idmap_update_op_u.rule;
335*4520Snw141292 	rule->is_user = is_user;
336*4520Snw141292 	rule->direction = direction;
337*4520Snw141292 	if (windomain) {
338*4520Snw141292 		str = &rule->windomain;
339*4520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
340*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
341*4520Snw141292 			goto errout;
342*4520Snw141292 	}
343*4520Snw141292 	if (winname) {
344*4520Snw141292 		str = &rule->winname;
345*4520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
346*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
347*4520Snw141292 			goto errout;
348*4520Snw141292 	}
349*4520Snw141292 	if (unixname) {
350*4520Snw141292 		str = &rule->unixname;
351*4520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
352*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
353*4520Snw141292 			goto errout;
354*4520Snw141292 	}
355*4520Snw141292 	udthandle->next++;
356*4520Snw141292 	return (IDMAP_SUCCESS);
357*4520Snw141292 
358*4520Snw141292 errout:
359*4520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
360*4520Snw141292 	errno = idmap_stat2errno(retcode);
361*4520Snw141292 	return (retcode);
362*4520Snw141292 }
363*4520Snw141292 
364*4520Snw141292 
365*4520Snw141292 /* ARGSUSED */
366*4520Snw141292 idmap_stat
367*4520Snw141292 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle, boolean_t is_user) {
368*4520Snw141292 	idmap_retcode	retcode;
369*4520Snw141292 
370*4520Snw141292 	retcode = _udt_extend_batch(udthandle, OP_FLUSH_NAMERULES);
371*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
372*4520Snw141292 		goto errout;
373*4520Snw141292 
374*4520Snw141292 	udthandle->batch.idmap_update_batch_val[udthandle->next].
375*4520Snw141292 		idmap_update_op_u.is_user = is_user;
376*4520Snw141292 
377*4520Snw141292 	udthandle->next++;
378*4520Snw141292 	return (IDMAP_SUCCESS);
379*4520Snw141292 
380*4520Snw141292 errout:
381*4520Snw141292 	(void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch);
382*4520Snw141292 	errno = idmap_stat2errno(retcode);
383*4520Snw141292 	return (retcode);
384*4520Snw141292 }
385*4520Snw141292 
386*4520Snw141292 
387*4520Snw141292 /*
388*4520Snw141292  * Set the number of entries requested per batch by the iterator
389*4520Snw141292  *
390*4520Snw141292  * Input:
391*4520Snw141292  * iter  - iterator
392*4520Snw141292  * limit - number of entries requested per batch
393*4520Snw141292  */
394*4520Snw141292 idmap_stat
395*4520Snw141292 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) {
396*4520Snw141292 	if (iter == NULL) {
397*4520Snw141292 		errno = EINVAL;
398*4520Snw141292 		return (IDMAP_ERR_ARG);
399*4520Snw141292 	}
400*4520Snw141292 	iter->limit = limit;
401*4520Snw141292 	return (IDMAP_SUCCESS);
402*4520Snw141292 }
403*4520Snw141292 
404*4520Snw141292 
405*4520Snw141292 /*
406*4520Snw141292  * Create iterator to get name-based mapping rules
407*4520Snw141292  *
408*4520Snw141292  * Input:
409*4520Snw141292  * windomain - Windows domain
410*4520Snw141292  * is_user   - user or group rules
411*4520Snw141292  * winname   - Windows user or group name
412*4520Snw141292  * unixname  - Unix user or group name
413*4520Snw141292  *
414*4520Snw141292  * Output:
415*4520Snw141292  * iter - iterator
416*4520Snw141292  */
417*4520Snw141292 idmap_stat
418*4520Snw141292 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain,
419*4520Snw141292 		boolean_t is_user, const char *winname,
420*4520Snw141292 		const char *unixname, idmap_iter_t **iter) {
421*4520Snw141292 
422*4520Snw141292 	idmap_iter_t			*tmpiter;
423*4520Snw141292 	idmap_list_namerules_1_argument	*arg = NULL;
424*4520Snw141292 	idmap_namerule			*rule;
425*4520Snw141292 	idmap_utf8str			*str;
426*4520Snw141292 	idmap_retcode			retcode;
427*4520Snw141292 
428*4520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES);
429*4520Snw141292 
430*4520Snw141292 	rule = &arg->rule;
431*4520Snw141292 	rule->is_user = is_user;
432*4520Snw141292 	rule->direction = -1;
433*4520Snw141292 	if (windomain) {
434*4520Snw141292 		str = &rule->windomain;
435*4520Snw141292 		retcode = idmap_str2utf8(&str, windomain, 0);
436*4520Snw141292 		if (retcode != IDMAP_SUCCESS) {
437*4520Snw141292 			errno = ENOMEM;
438*4520Snw141292 			goto errout;
439*4520Snw141292 		}
440*4520Snw141292 	}
441*4520Snw141292 	if (winname) {
442*4520Snw141292 		str = &rule->winname;
443*4520Snw141292 		retcode = idmap_str2utf8(&str, winname, 0);
444*4520Snw141292 		if (retcode != IDMAP_SUCCESS) {
445*4520Snw141292 			errno = ENOMEM;
446*4520Snw141292 			goto errout;
447*4520Snw141292 		}
448*4520Snw141292 	}
449*4520Snw141292 	if (unixname) {
450*4520Snw141292 		str = &rule->unixname;
451*4520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 0);
452*4520Snw141292 		if (retcode != IDMAP_SUCCESS) {
453*4520Snw141292 			errno = ENOMEM;
454*4520Snw141292 			goto errout;
455*4520Snw141292 		}
456*4520Snw141292 	}
457*4520Snw141292 
458*4520Snw141292 	*iter = tmpiter;
459*4520Snw141292 	return (IDMAP_SUCCESS);
460*4520Snw141292 
461*4520Snw141292 errout:
462*4520Snw141292 	__ITER_ERR_RETURN(tmpiter, arg,
463*4520Snw141292 		xdr_idmap_list_namerules_1_argument, retcode);
464*4520Snw141292 }
465*4520Snw141292 
466*4520Snw141292 
467*4520Snw141292 /*
468*4520Snw141292  * Iterate through the name-based mapping rules
469*4520Snw141292  *
470*4520Snw141292  * Input:
471*4520Snw141292  * iter - iterator
472*4520Snw141292  *
473*4520Snw141292  * Output:
474*4520Snw141292  * windomain - Windows domain
475*4520Snw141292  * winname   - Windows user or group name
476*4520Snw141292  * unixname  - Unix user or group name
477*4520Snw141292  * is_nt4    - NT4 or AD
478*4520Snw141292  * direction - bi(0), win2unix(1), unix2win(2)
479*4520Snw141292  *
480*4520Snw141292  * Return value:
481*4520Snw141292  * 0   - done
482*4520Snw141292  * 1   - more results available
483*4520Snw141292  * < 0 - error
484*4520Snw141292  */
485*4520Snw141292 idmap_stat
486*4520Snw141292 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain,
487*4520Snw141292 		char **winname, char **unixname, boolean_t *is_nt4,
488*4520Snw141292 		int *direction) {
489*4520Snw141292 	idmap_namerules_res		*namerules;
490*4520Snw141292 	idmap_list_namerules_1_argument	*arg;
491*4520Snw141292 	idmap_retcode			retcode;
492*4520Snw141292 	const char			*me = "idmap_iter_next_namerule";
493*4520Snw141292 
494*4520Snw141292 	if (windomain)
495*4520Snw141292 		*windomain = NULL;
496*4520Snw141292 	if (winname)
497*4520Snw141292 		*winname = NULL;
498*4520Snw141292 	if (unixname)
499*4520Snw141292 		*unixname = NULL;
500*4520Snw141292 	if (is_nt4)
501*4520Snw141292 		*is_nt4 = 0;
502*4520Snw141292 	if (direction)
503*4520Snw141292 		*direction = -1;
504*4520Snw141292 
505*4520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_NAMERULES);
506*4520Snw141292 
507*4520Snw141292 	namerules = (idmap_namerules_res *)iter->retlist;
508*4520Snw141292 	if (iter->retcode == IDMAP_NEXT && (namerules == NULL ||
509*4520Snw141292 			iter->next >= namerules->rules.rules_len)) {
510*4520Snw141292 
511*4520Snw141292 		if ((arg = iter->arg) == NULL) {
512*4520Snw141292 			errno = EINVAL;
513*4520Snw141292 			return (IDMAP_ERR_ARG);
514*4520Snw141292 		}
515*4520Snw141292 		arg->limit = iter->limit;
516*4520Snw141292 
517*4520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES,
518*4520Snw141292 			iter, arg,
519*4520Snw141292 			(uchar_t **)&namerules, sizeof (*namerules),
520*4520Snw141292 			(xdrproc_t)xdr_idmap_list_namerules_1_argument,
521*4520Snw141292 			(xdrproc_t)xdr_idmap_namerules_res);
522*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
523*4520Snw141292 			return (retcode);
524*4520Snw141292 
525*4520Snw141292 		if (IDMAP_ERROR(namerules->retcode)) {
526*4520Snw141292 			retcode  = namerules->retcode;
527*4520Snw141292 			if (__idmap_verbose)
528*4520Snw141292 				(void) fprintf(stderr,
529*4520Snw141292 				gettext("Server returned failure\n"));
530*4520Snw141292 			xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules);
531*4520Snw141292 			free(namerules);
532*4520Snw141292 			iter->retlist = NULL;
533*4520Snw141292 			return (retcode);
534*4520Snw141292 		}
535*4520Snw141292 		iter->retcode = namerules->retcode;
536*4520Snw141292 		arg->lastrowid = namerules->lastrowid;
537*4520Snw141292 	}
538*4520Snw141292 
539*4520Snw141292 	if (namerules == NULL || namerules->rules.rules_len == 0)
540*4520Snw141292 		return (IDMAP_SUCCESS);
541*4520Snw141292 
542*4520Snw141292 	if (iter->next >= namerules->rules.rules_len) {
543*4520Snw141292 		if (__idmap_verbose)
544*4520Snw141292 			(void) fprintf(stderr,
545*4520Snw141292 				gettext("%s: Invalid result\n"), me);
546*4520Snw141292 		return (IDMAP_ERR_ARG);
547*4520Snw141292 	}
548*4520Snw141292 
549*4520Snw141292 	if (windomain) {
550*4520Snw141292 		retcode = idmap_utf82str(windomain, 0,
551*4520Snw141292 			&namerules->rules.rules_val[iter->next].windomain);
552*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
553*4520Snw141292 			goto errout;
554*4520Snw141292 	}
555*4520Snw141292 	if (winname) {
556*4520Snw141292 		retcode = idmap_utf82str(winname, 0,
557*4520Snw141292 			&namerules->rules.rules_val[iter->next].winname);
558*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
559*4520Snw141292 			goto errout;
560*4520Snw141292 	}
561*4520Snw141292 	if (unixname) {
562*4520Snw141292 		retcode = idmap_utf82str(unixname, 0,
563*4520Snw141292 			&namerules->rules.rules_val[iter->next].unixname);
564*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
565*4520Snw141292 			goto errout;
566*4520Snw141292 	}
567*4520Snw141292 	if (is_nt4)
568*4520Snw141292 		*is_nt4 = namerules->rules.rules_val[iter->next].is_nt4;
569*4520Snw141292 	if (direction)
570*4520Snw141292 		*direction = namerules->rules.rules_val[iter->next].direction;
571*4520Snw141292 	iter->next++;
572*4520Snw141292 
573*4520Snw141292 	if (iter->next == namerules->rules.rules_len)
574*4520Snw141292 		return (iter->retcode);
575*4520Snw141292 	else
576*4520Snw141292 		return (IDMAP_NEXT);
577*4520Snw141292 
578*4520Snw141292 errout:
579*4520Snw141292 	if (windomain && *windomain)
580*4520Snw141292 		free(*windomain);
581*4520Snw141292 	if (winname && *winname)
582*4520Snw141292 		free(*winname);
583*4520Snw141292 	if (unixname && *unixname)
584*4520Snw141292 		free(*unixname);
585*4520Snw141292 	return (retcode);
586*4520Snw141292 }
587*4520Snw141292 
588*4520Snw141292 
589*4520Snw141292 /*
590*4520Snw141292  * Create iterator to get SID to UID/GID mappings
591*4520Snw141292  *
592*4520Snw141292  * Input:
593*4520Snw141292  * is_user - user or group
594*4520Snw141292  *
595*4520Snw141292  * Output:
596*4520Snw141292  * iter - iterator
597*4520Snw141292  */
598*4520Snw141292 idmap_stat
599*4520Snw141292 idmap_iter_mappings(idmap_handle_t *handle, boolean_t is_user,
600*4520Snw141292 		idmap_iter_t **iter) {
601*4520Snw141292 	idmap_iter_t			*tmpiter;
602*4520Snw141292 	idmap_list_mappings_1_argument	*arg = NULL;
603*4520Snw141292 
604*4520Snw141292 	__ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS);
605*4520Snw141292 
606*4520Snw141292 	arg->is_user = is_user;
607*4520Snw141292 	*iter = tmpiter;
608*4520Snw141292 	return (IDMAP_SUCCESS);
609*4520Snw141292 }
610*4520Snw141292 
611*4520Snw141292 
612*4520Snw141292 /*
613*4520Snw141292  * Iterate through the SID to UID/GID mappings
614*4520Snw141292  *
615*4520Snw141292  * Input:
616*4520Snw141292  * iter - iterator
617*4520Snw141292  *
618*4520Snw141292  * Output:
619*4520Snw141292  * sid - SID in canonical form
620*4520Snw141292  * pid - UID or GID
621*4520Snw141292  *
622*4520Snw141292  * Return value:
623*4520Snw141292  * 0   - done
624*4520Snw141292  * 1   - more results available
625*4520Snw141292  * < 0 - error
626*4520Snw141292  */
627*4520Snw141292 idmap_stat
628*4520Snw141292 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix,
629*4520Snw141292 		idmap_rid_t *rid, uid_t *pid, char **winname,
630*4520Snw141292 		char **windomain, char **unixname, int *direction) {
631*4520Snw141292 	idmap_mappings_res		*mappings;
632*4520Snw141292 	idmap_list_mappings_1_argument	*arg;
633*4520Snw141292 	idmap_retcode			retcode;
634*4520Snw141292 	char				*str;
635*4520Snw141292 	const char			*me = "idmap_iter_next_mapping";
636*4520Snw141292 
637*4520Snw141292 	if (sidprefix)
638*4520Snw141292 		*sidprefix = NULL;
639*4520Snw141292 	if (rid)
640*4520Snw141292 		*rid = UINT32_MAX;
641*4520Snw141292 	if (winname)
642*4520Snw141292 		*winname = NULL;
643*4520Snw141292 	if (windomain)
644*4520Snw141292 		*windomain = NULL;
645*4520Snw141292 	if (unixname)
646*4520Snw141292 		*unixname = NULL;
647*4520Snw141292 	if (pid)
648*4520Snw141292 		*pid = UINT32_MAX;
649*4520Snw141292 	if (direction)
650*4520Snw141292 		*direction = -1;
651*4520Snw141292 
652*4520Snw141292 	__ITER_CHECK(iter, IDMAP_LIST_MAPPINGS);
653*4520Snw141292 
654*4520Snw141292 	mappings = (idmap_mappings_res *)iter->retlist;
655*4520Snw141292 	if (iter->retcode == IDMAP_NEXT && (mappings == NULL ||
656*4520Snw141292 			iter->next >= mappings->mappings.mappings_len)) {
657*4520Snw141292 
658*4520Snw141292 		if ((arg = iter->arg) == NULL) {
659*4520Snw141292 			errno = EINVAL;
660*4520Snw141292 			return (IDMAP_ERR_ARG);
661*4520Snw141292 		}
662*4520Snw141292 		arg->limit = iter->limit;
663*4520Snw141292 
664*4520Snw141292 		retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS,
665*4520Snw141292 			iter, arg,
666*4520Snw141292 			(uchar_t **)&mappings, sizeof (*mappings),
667*4520Snw141292 			(xdrproc_t)xdr_idmap_list_mappings_1_argument,
668*4520Snw141292 			(xdrproc_t)xdr_idmap_mappings_res);
669*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
670*4520Snw141292 			return (retcode);
671*4520Snw141292 
672*4520Snw141292 		if (IDMAP_ERROR(mappings->retcode)) {
673*4520Snw141292 			retcode  = mappings->retcode;
674*4520Snw141292 			if (__idmap_verbose)
675*4520Snw141292 				(void) fprintf(stderr,
676*4520Snw141292 				gettext("Server returned failure\n"));
677*4520Snw141292 			xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings);
678*4520Snw141292 			free(mappings);
679*4520Snw141292 			iter->retlist = NULL;
680*4520Snw141292 			return (retcode);
681*4520Snw141292 		}
682*4520Snw141292 		iter->retcode = mappings->retcode;
683*4520Snw141292 		arg->lastrowid = mappings->lastrowid;
684*4520Snw141292 	}
685*4520Snw141292 
686*4520Snw141292 	if (mappings == NULL || mappings->mappings.mappings_len == 0)
687*4520Snw141292 		return (IDMAP_SUCCESS);
688*4520Snw141292 
689*4520Snw141292 	if (iter->next >= mappings->mappings.mappings_len) {
690*4520Snw141292 		if (__idmap_verbose)
691*4520Snw141292 			(void) fprintf(stderr,
692*4520Snw141292 				gettext("%s: Invalid result\n"), me);
693*4520Snw141292 		return (IDMAP_ERR_ARG);
694*4520Snw141292 	}
695*4520Snw141292 
696*4520Snw141292 	if (sidprefix) {
697*4520Snw141292 		str = mappings->mappings.mappings_val[iter->next].id1.
698*4520Snw141292 			idmap_id_u.sid.prefix;
699*4520Snw141292 		if (str)
700*4520Snw141292 			*sidprefix = strdup(str);
701*4520Snw141292 		else
702*4520Snw141292 			*sidprefix = strdup("<sidprefix missing>");
703*4520Snw141292 		if (*sidprefix == NULL) {
704*4520Snw141292 			retcode = IDMAP_ERR_MEMORY;
705*4520Snw141292 			goto errout;
706*4520Snw141292 		}
707*4520Snw141292 	}
708*4520Snw141292 	if (rid)
709*4520Snw141292 		*rid = mappings->mappings.mappings_val[iter->next].id1.
710*4520Snw141292 			idmap_id_u.sid.rid;
711*4520Snw141292 	if (winname) {
712*4520Snw141292 		retcode = idmap_utf82str(winname, 0,
713*4520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id1name);
714*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
715*4520Snw141292 			goto errout;
716*4520Snw141292 	}
717*4520Snw141292 	if (windomain) {
718*4520Snw141292 		retcode = idmap_utf82str(windomain, 0,
719*4520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id1domain);
720*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
721*4520Snw141292 			goto errout;
722*4520Snw141292 	}
723*4520Snw141292 	if (unixname) {
724*4520Snw141292 		retcode = idmap_utf82str(unixname, 0,
725*4520Snw141292 		    &mappings->mappings.mappings_val[iter->next].id2name);
726*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
727*4520Snw141292 			goto errout;
728*4520Snw141292 	}
729*4520Snw141292 	if (pid)
730*4520Snw141292 		*pid = mappings->mappings.mappings_val[iter->next].id2.
731*4520Snw141292 			idmap_id_u.uid;
732*4520Snw141292 	if (direction)
733*4520Snw141292 		*direction = mappings->mappings.mappings_val[iter->next].
734*4520Snw141292 			direction;
735*4520Snw141292 	iter->next++;
736*4520Snw141292 
737*4520Snw141292 	if (iter->next == mappings->mappings.mappings_len)
738*4520Snw141292 		return (iter->retcode);
739*4520Snw141292 	else
740*4520Snw141292 		return (IDMAP_NEXT);
741*4520Snw141292 
742*4520Snw141292 errout:
743*4520Snw141292 	if (sidprefix && *sidprefix)
744*4520Snw141292 		free(*sidprefix);
745*4520Snw141292 	if (winname && *winname)
746*4520Snw141292 		free(*winname);
747*4520Snw141292 	if (windomain && *windomain)
748*4520Snw141292 		free(*windomain);
749*4520Snw141292 	if (unixname && *unixname)
750*4520Snw141292 		free(*unixname);
751*4520Snw141292 	return (retcode);
752*4520Snw141292 }
753*4520Snw141292 
754*4520Snw141292 
755*4520Snw141292 /*
756*4520Snw141292  * Destroy the iterator
757*4520Snw141292  */
758*4520Snw141292 void
759*4520Snw141292 idmap_iter_destroy(idmap_iter_t *iter) {
760*4520Snw141292 	xdrproc_t _xdr_argument, _xdr_result;
761*4520Snw141292 
762*4520Snw141292 	if (iter == NULL)
763*4520Snw141292 		return;
764*4520Snw141292 
765*4520Snw141292 	switch (iter->type) {
766*4520Snw141292 	case IDMAP_LIST_NAMERULES:
767*4520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument;
768*4520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_namerules_res;
769*4520Snw141292 		break;
770*4520Snw141292 	case IDMAP_LIST_MAPPINGS:
771*4520Snw141292 		_xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument;
772*4520Snw141292 		_xdr_result = (xdrproc_t)xdr_idmap_mappings_res;
773*4520Snw141292 		break;
774*4520Snw141292 	default:
775*4520Snw141292 		free(iter);
776*4520Snw141292 		return;
777*4520Snw141292 	};
778*4520Snw141292 
779*4520Snw141292 	if (iter->arg) {
780*4520Snw141292 		xdr_free(_xdr_argument, (caddr_t)iter->arg);
781*4520Snw141292 		free(iter->arg);
782*4520Snw141292 	}
783*4520Snw141292 	if (iter->retlist) {
784*4520Snw141292 		xdr_free(_xdr_result, (caddr_t)iter->retlist);
785*4520Snw141292 		free(iter->retlist);
786*4520Snw141292 	}
787*4520Snw141292 	free(iter);
788*4520Snw141292 }
789*4520Snw141292 
790*4520Snw141292 
791*4520Snw141292 /*
792*4520Snw141292  * Create handle to get SID to UID/GID mapping entries
793*4520Snw141292  *
794*4520Snw141292  * Input:
795*4520Snw141292  * gh - "get mapping" handle
796*4520Snw141292  */
797*4520Snw141292 idmap_stat
798*4520Snw141292 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) {
799*4520Snw141292 	idmap_get_handle_t	*tmp;
800*4520Snw141292 	const char		*me = "idmap_get_create";
801*4520Snw141292 
802*4520Snw141292 	/* sanity checks */
803*4520Snw141292 	if (handle == NULL || gh == NULL) {
804*4520Snw141292 		errno = EINVAL;
805*4520Snw141292 		return (IDMAP_ERR_ARG);
806*4520Snw141292 	}
807*4520Snw141292 
808*4520Snw141292 	/* allocate the handle */
809*4520Snw141292 	if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
810*4520Snw141292 		if (__idmap_verbose)
811*4520Snw141292 			(void) fprintf(stderr,
812*4520Snw141292 				gettext("%s: Out of memory\n"), me);
813*4520Snw141292 		errno = ENOMEM;
814*4520Snw141292 		return (IDMAP_ERR_MEMORY);
815*4520Snw141292 	}
816*4520Snw141292 
817*4520Snw141292 	tmp->ih = handle;
818*4520Snw141292 	*gh = tmp;
819*4520Snw141292 	return (IDMAP_SUCCESS);
820*4520Snw141292 }
821*4520Snw141292 
822*4520Snw141292 
823*4520Snw141292 /*
824*4520Snw141292  * Given SID, get UID
825*4520Snw141292  *
826*4520Snw141292  * Input:
827*4520Snw141292  * sidprefix  - SID prefix
828*4520Snw141292  * rid        - RID
829*4520Snw141292  * flag       - flag
830*4520Snw141292  *
831*4520Snw141292  * Output:
832*4520Snw141292  * stat - status of the get request
833*4520Snw141292  * uid  - POSIX UID if stat = 0
834*4520Snw141292  *
835*4520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
836*4520Snw141292  */
837*4520Snw141292 idmap_stat
838*4520Snw141292 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
839*4520Snw141292 		int flag, uid_t *uid, idmap_stat *stat) {
840*4520Snw141292 
841*4520Snw141292 	idmap_retcode	retcode;
842*4520Snw141292 	idmap_mapping	*mapping;
843*4520Snw141292 
844*4520Snw141292 	/* sanity checks */
845*4520Snw141292 	if (gh == NULL)
846*4520Snw141292 		return (IDMAP_ERR_ARG);
847*4520Snw141292 	if (uid == NULL || sidprefix == NULL)
848*4520Snw141292 		return (IDMAP_ERR_ARG);
849*4520Snw141292 
850*4520Snw141292 	/* Extend the request array and the return list */
851*4520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
852*4520Snw141292 		goto errout;
853*4520Snw141292 
854*4520Snw141292 	/* Setup the request */
855*4520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
856*4520Snw141292 	mapping->flag = flag;
857*4520Snw141292 	mapping->id1.idtype = IDMAP_SID;
858*4520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
859*4520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
860*4520Snw141292 		retcode = IDMAP_ERR_MEMORY;
861*4520Snw141292 		goto errout;
862*4520Snw141292 	}
863*4520Snw141292 	mapping->id2.idtype = IDMAP_UID;
864*4520Snw141292 
865*4520Snw141292 	/* Setup pointers for the result */
866*4520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_UID;
867*4520Snw141292 	gh->retlist[gh->next].uid = uid;
868*4520Snw141292 	gh->retlist[gh->next].stat = stat;
869*4520Snw141292 
870*4520Snw141292 	gh->next++;
871*4520Snw141292 	return (IDMAP_SUCCESS);
872*4520Snw141292 
873*4520Snw141292 errout:
874*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
875*4520Snw141292 	free(gh->retlist);
876*4520Snw141292 	gh->retlist = NULL;
877*4520Snw141292 	gh->next = 0;
878*4520Snw141292 	errno = idmap_stat2errno(retcode);
879*4520Snw141292 	return (retcode);
880*4520Snw141292 }
881*4520Snw141292 
882*4520Snw141292 
883*4520Snw141292 /*
884*4520Snw141292  * Given SID, get GID
885*4520Snw141292  *
886*4520Snw141292  * Input:
887*4520Snw141292  * sidprefix  - SID prefix
888*4520Snw141292  * rid        - rid
889*4520Snw141292  * flag       - flag
890*4520Snw141292  *
891*4520Snw141292  * Output:
892*4520Snw141292  * stat - status of the get request
893*4520Snw141292  * gid  - POSIX GID if stat = 0
894*4520Snw141292  *
895*4520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
896*4520Snw141292  */
897*4520Snw141292 idmap_stat
898*4520Snw141292 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
899*4520Snw141292 		int flag, gid_t *gid, idmap_stat *stat) {
900*4520Snw141292 
901*4520Snw141292 	idmap_retcode	retcode;
902*4520Snw141292 	idmap_mapping	*mapping;
903*4520Snw141292 
904*4520Snw141292 	/* sanity checks */
905*4520Snw141292 	if (gh == NULL)
906*4520Snw141292 		return (IDMAP_ERR_ARG);
907*4520Snw141292 	if (gid == NULL || sidprefix == NULL)
908*4520Snw141292 		return (IDMAP_ERR_ARG);
909*4520Snw141292 
910*4520Snw141292 	/* Extend the request array and the return list */
911*4520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
912*4520Snw141292 		goto errout;
913*4520Snw141292 
914*4520Snw141292 	/* Setup the request */
915*4520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
916*4520Snw141292 	mapping->flag = flag;
917*4520Snw141292 	mapping->id1.idtype = IDMAP_SID;
918*4520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
919*4520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
920*4520Snw141292 		retcode = IDMAP_ERR_MEMORY;
921*4520Snw141292 		goto errout;
922*4520Snw141292 	}
923*4520Snw141292 	mapping->id2.idtype = IDMAP_GID;
924*4520Snw141292 
925*4520Snw141292 	/* Setup pointers for the result */
926*4520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_GID;
927*4520Snw141292 	gh->retlist[gh->next].gid = gid;
928*4520Snw141292 	gh->retlist[gh->next].stat = stat;
929*4520Snw141292 
930*4520Snw141292 	gh->next++;
931*4520Snw141292 	return (IDMAP_SUCCESS);
932*4520Snw141292 
933*4520Snw141292 errout:
934*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
935*4520Snw141292 	free(gh->retlist);
936*4520Snw141292 	gh->retlist = NULL;
937*4520Snw141292 	gh->next = 0;
938*4520Snw141292 	errno = idmap_stat2errno(retcode);
939*4520Snw141292 	return (retcode);
940*4520Snw141292 }
941*4520Snw141292 
942*4520Snw141292 
943*4520Snw141292 /*
944*4520Snw141292  * Given SID, get POSIX ID i.e. UID/GID
945*4520Snw141292  *
946*4520Snw141292  * Input:
947*4520Snw141292  * sidprefix  - SID prefix
948*4520Snw141292  * rid        - rid
949*4520Snw141292  * flag       - flag
950*4520Snw141292  *
951*4520Snw141292  * Output:
952*4520Snw141292  * stat    - status of the get request
953*4520Snw141292  * is_user - user or group
954*4520Snw141292  * pid     - POSIX UID if stat = 0 and is_user = 1
955*4520Snw141292  *           POSIX GID if stat = 0 and is_user = 0
956*4520Snw141292  *
957*4520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
958*4520Snw141292  */
959*4520Snw141292 idmap_stat
960*4520Snw141292 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid,
961*4520Snw141292 		int flag, uid_t *pid, int *is_user, idmap_stat *stat) {
962*4520Snw141292 	idmap_retcode	retcode;
963*4520Snw141292 	idmap_mapping	*mapping;
964*4520Snw141292 
965*4520Snw141292 	/* sanity checks */
966*4520Snw141292 	if (gh == NULL)
967*4520Snw141292 		return (IDMAP_ERR_ARG);
968*4520Snw141292 	if (pid == NULL || sidprefix == NULL || is_user == NULL)
969*4520Snw141292 		return (IDMAP_ERR_ARG);
970*4520Snw141292 
971*4520Snw141292 	/* Extend the request array and the return list */
972*4520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
973*4520Snw141292 		goto errout;
974*4520Snw141292 
975*4520Snw141292 	/* Setup the request */
976*4520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
977*4520Snw141292 	mapping->flag = flag;
978*4520Snw141292 	mapping->id1.idtype = IDMAP_SID;
979*4520Snw141292 	mapping->id1.idmap_id_u.sid.rid = rid;
980*4520Snw141292 	if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) {
981*4520Snw141292 		retcode = IDMAP_ERR_MEMORY;
982*4520Snw141292 		goto errout;
983*4520Snw141292 	}
984*4520Snw141292 	mapping->id2.idtype = IDMAP_POSIXID;
985*4520Snw141292 
986*4520Snw141292 	/* Setup pointers for the result */
987*4520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_POSIXID;
988*4520Snw141292 	gh->retlist[gh->next].uid = pid;
989*4520Snw141292 	gh->retlist[gh->next].gid = pid;
990*4520Snw141292 	gh->retlist[gh->next].is_user = is_user;
991*4520Snw141292 	gh->retlist[gh->next].stat = stat;
992*4520Snw141292 
993*4520Snw141292 	gh->next++;
994*4520Snw141292 	return (IDMAP_SUCCESS);
995*4520Snw141292 
996*4520Snw141292 errout:
997*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
998*4520Snw141292 	free(gh->retlist);
999*4520Snw141292 	gh->retlist = NULL;
1000*4520Snw141292 	gh->next = 0;
1001*4520Snw141292 	errno = idmap_stat2errno(retcode);
1002*4520Snw141292 	return (retcode);
1003*4520Snw141292 }
1004*4520Snw141292 
1005*4520Snw141292 
1006*4520Snw141292 /*
1007*4520Snw141292  * Given UID, get SID
1008*4520Snw141292  *
1009*4520Snw141292  * Input:
1010*4520Snw141292  * uid  - POSIX UID
1011*4520Snw141292  * flag - flag
1012*4520Snw141292  *
1013*4520Snw141292  * Output:
1014*4520Snw141292  * stat - status of the get request
1015*4520Snw141292  * sid  - SID prefix (if stat == 0)
1016*4520Snw141292  * rid  - rid
1017*4520Snw141292  *
1018*4520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
1019*4520Snw141292  */
1020*4520Snw141292 idmap_stat
1021*4520Snw141292 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag,
1022*4520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
1023*4520Snw141292 
1024*4520Snw141292 	idmap_retcode	retcode;
1025*4520Snw141292 	idmap_mapping	*mapping;
1026*4520Snw141292 
1027*4520Snw141292 	/* sanity checks */
1028*4520Snw141292 	if (gh == NULL)
1029*4520Snw141292 		return (IDMAP_ERR_ARG);
1030*4520Snw141292 	if (sidprefix == NULL)
1031*4520Snw141292 		return (IDMAP_ERR_ARG);
1032*4520Snw141292 
1033*4520Snw141292 	/* Extend the request array and the return list */
1034*4520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1035*4520Snw141292 		goto errout;
1036*4520Snw141292 
1037*4520Snw141292 	/* Setup the request */
1038*4520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1039*4520Snw141292 	mapping->flag = flag;
1040*4520Snw141292 	mapping->id1.idtype = IDMAP_UID;
1041*4520Snw141292 	mapping->id1.idmap_id_u.uid = uid;
1042*4520Snw141292 	mapping->id2.idtype = IDMAP_SID;
1043*4520Snw141292 
1044*4520Snw141292 	/* Setup pointers for the result */
1045*4520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
1046*4520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
1047*4520Snw141292 	gh->retlist[gh->next].rid = rid;
1048*4520Snw141292 	gh->retlist[gh->next].stat = stat;
1049*4520Snw141292 
1050*4520Snw141292 	gh->next++;
1051*4520Snw141292 	return (IDMAP_SUCCESS);
1052*4520Snw141292 
1053*4520Snw141292 errout:
1054*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1055*4520Snw141292 	free(gh->retlist);
1056*4520Snw141292 	gh->retlist = NULL;
1057*4520Snw141292 	gh->next = 0;
1058*4520Snw141292 	errno = idmap_stat2errno(retcode);
1059*4520Snw141292 	return (retcode);
1060*4520Snw141292 }
1061*4520Snw141292 
1062*4520Snw141292 
1063*4520Snw141292 /*
1064*4520Snw141292  * Given GID, get SID
1065*4520Snw141292  *
1066*4520Snw141292  * Input:
1067*4520Snw141292  * gid  - POSIX GID
1068*4520Snw141292  * flag - flag
1069*4520Snw141292  *
1070*4520Snw141292  * Output:
1071*4520Snw141292  * stat       - status of the get request
1072*4520Snw141292  * sidprefix  - SID prefix (if stat == 0)
1073*4520Snw141292  * rid        - rid
1074*4520Snw141292  *
1075*4520Snw141292  * Note: The output parameters will be set by idmap_get_mappings()
1076*4520Snw141292  */
1077*4520Snw141292 idmap_stat
1078*4520Snw141292 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag,
1079*4520Snw141292 		char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) {
1080*4520Snw141292 
1081*4520Snw141292 	idmap_retcode	retcode;
1082*4520Snw141292 	idmap_mapping	*mapping;
1083*4520Snw141292 
1084*4520Snw141292 	/* sanity checks */
1085*4520Snw141292 	if (gh == NULL)
1086*4520Snw141292 		return (IDMAP_ERR_ARG);
1087*4520Snw141292 	if (sidprefix == NULL)
1088*4520Snw141292 		return (IDMAP_ERR_ARG);
1089*4520Snw141292 
1090*4520Snw141292 	/* Extend the request array and the return list */
1091*4520Snw141292 	if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS)
1092*4520Snw141292 		goto errout;
1093*4520Snw141292 
1094*4520Snw141292 	/* Setup the request */
1095*4520Snw141292 	mapping = &gh->batch.idmap_mapping_batch_val[gh->next];
1096*4520Snw141292 	mapping->flag = flag;
1097*4520Snw141292 	mapping->id1.idtype = IDMAP_GID;
1098*4520Snw141292 	mapping->id1.idmap_id_u.gid = gid;
1099*4520Snw141292 	mapping->id2.idtype = IDMAP_SID;
1100*4520Snw141292 
1101*4520Snw141292 	/* Setup pointers for the result */
1102*4520Snw141292 	gh->retlist[gh->next].idtype = IDMAP_SID;
1103*4520Snw141292 	gh->retlist[gh->next].sidprefix = sidprefix;
1104*4520Snw141292 	gh->retlist[gh->next].rid = rid;
1105*4520Snw141292 	gh->retlist[gh->next].stat = stat;
1106*4520Snw141292 
1107*4520Snw141292 	gh->next++;
1108*4520Snw141292 	return (IDMAP_SUCCESS);
1109*4520Snw141292 
1110*4520Snw141292 errout:
1111*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1112*4520Snw141292 	free(gh->retlist);
1113*4520Snw141292 	gh->retlist = NULL;
1114*4520Snw141292 	gh->next = 0;
1115*4520Snw141292 	errno = idmap_stat2errno(retcode);
1116*4520Snw141292 	return (retcode);
1117*4520Snw141292 }
1118*4520Snw141292 
1119*4520Snw141292 
1120*4520Snw141292 /*
1121*4520Snw141292  * Process the batched "get mapping" requests. The results (i.e.
1122*4520Snw141292  * status and identity) will be available in the data areas
1123*4520Snw141292  * provided by individual requests.
1124*4520Snw141292  */
1125*4520Snw141292 idmap_stat
1126*4520Snw141292 idmap_get_mappings(idmap_get_handle_t *gh) {
1127*4520Snw141292 	CLIENT		*clnt;
1128*4520Snw141292 	enum clnt_stat	clntstat;
1129*4520Snw141292 	idmap_retcode	retcode;
1130*4520Snw141292 	idmap_ids_res	res;
1131*4520Snw141292 	idmap_id	*id;
1132*4520Snw141292 	int		i;
1133*4520Snw141292 
1134*4520Snw141292 	if (gh == NULL) {
1135*4520Snw141292 		errno = EINVAL;
1136*4520Snw141292 		return (IDMAP_ERR_ARG);
1137*4520Snw141292 	}
1138*4520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt);
1139*4520Snw141292 
1140*4520Snw141292 	(void) memset(&res, 0, sizeof (idmap_ids_res));
1141*4520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS,
1142*4520Snw141292 		(xdrproc_t)xdr_idmap_mapping_batch,
1143*4520Snw141292 		(caddr_t)&gh->batch,
1144*4520Snw141292 		(xdrproc_t)xdr_idmap_ids_res,
1145*4520Snw141292 		(caddr_t)&res,
1146*4520Snw141292 		TIMEOUT);
1147*4520Snw141292 	if (clntstat != RPC_SUCCESS) {
1148*4520Snw141292 		if (__idmap_verbose)
1149*4520Snw141292 			clnt_perror(clnt, "IDMAP_GET_MAPPED_IDS");
1150*4520Snw141292 		retcode = IDMAP_ERR_RPC;
1151*4520Snw141292 		goto out;
1152*4520Snw141292 	}
1153*4520Snw141292 	if (res.retcode != IDMAP_SUCCESS) {
1154*4520Snw141292 		retcode = res.retcode;
1155*4520Snw141292 		goto out;
1156*4520Snw141292 	}
1157*4520Snw141292 	for (i = 0; i < gh->next; i++) {
1158*4520Snw141292 		if (i >= res.ids.ids_len) {
1159*4520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1160*4520Snw141292 			continue;
1161*4520Snw141292 		}
1162*4520Snw141292 		*gh->retlist[i].stat = res.ids.ids_val[i].retcode;
1163*4520Snw141292 		id = &res.ids.ids_val[i].id;
1164*4520Snw141292 		switch (id->idtype) {
1165*4520Snw141292 		case IDMAP_UID:
1166*4520Snw141292 			if (gh->retlist[i].uid)
1167*4520Snw141292 				*gh->retlist[i].uid = id->idmap_id_u.uid;
1168*4520Snw141292 			if (gh->retlist[i].is_user)
1169*4520Snw141292 				*gh->retlist[i].is_user = 1;
1170*4520Snw141292 			break;
1171*4520Snw141292 		case IDMAP_GID:
1172*4520Snw141292 			if (gh->retlist[i].gid)
1173*4520Snw141292 				*gh->retlist[i].gid = id->idmap_id_u.gid;
1174*4520Snw141292 			if (gh->retlist[i].is_user)
1175*4520Snw141292 				*gh->retlist[i].is_user = 0;
1176*4520Snw141292 			break;
1177*4520Snw141292 		case IDMAP_SID:
1178*4520Snw141292 			if (gh->retlist[i].rid)
1179*4520Snw141292 				*gh->retlist[i].rid = id->idmap_id_u.sid.rid;
1180*4520Snw141292 			if (gh->retlist[i].sidprefix) {
1181*4520Snw141292 				if (id->idmap_id_u.sid.prefix == NULL) {
1182*4520Snw141292 					*gh->retlist[i].sidprefix = NULL;
1183*4520Snw141292 					break;
1184*4520Snw141292 				}
1185*4520Snw141292 				*gh->retlist[i].sidprefix =
1186*4520Snw141292 					strdup(id->idmap_id_u.sid.prefix);
1187*4520Snw141292 				if (*gh->retlist[i].sidprefix == NULL)
1188*4520Snw141292 					*gh->retlist[i].stat =
1189*4520Snw141292 						IDMAP_ERR_MEMORY;
1190*4520Snw141292 			}
1191*4520Snw141292 			break;
1192*4520Snw141292 		case IDMAP_NONE:
1193*4520Snw141292 			break;
1194*4520Snw141292 		default:
1195*4520Snw141292 			*gh->retlist[i].stat = IDMAP_ERR_NORESULT;
1196*4520Snw141292 			break;
1197*4520Snw141292 		}
1198*4520Snw141292 	}
1199*4520Snw141292 	retcode = IDMAP_SUCCESS;
1200*4520Snw141292 
1201*4520Snw141292 out:
1202*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1203*4520Snw141292 	free(gh->retlist);
1204*4520Snw141292 	gh->retlist = NULL;
1205*4520Snw141292 	gh->next = 0;
1206*4520Snw141292 	(void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res);
1207*4520Snw141292 	errno = idmap_stat2errno(retcode);
1208*4520Snw141292 	return (retcode);
1209*4520Snw141292 }
1210*4520Snw141292 
1211*4520Snw141292 
1212*4520Snw141292 /*
1213*4520Snw141292  * Destroy the "get mapping" handle
1214*4520Snw141292  */
1215*4520Snw141292 void
1216*4520Snw141292 idmap_get_destroy(idmap_get_handle_t *gh) {
1217*4520Snw141292 	if (gh == NULL)
1218*4520Snw141292 		return;
1219*4520Snw141292 	(void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch);
1220*4520Snw141292 	if (gh->retlist)
1221*4520Snw141292 		free(gh->retlist);
1222*4520Snw141292 	free(gh);
1223*4520Snw141292 }
1224*4520Snw141292 
1225*4520Snw141292 
1226*4520Snw141292 /*
1227*4520Snw141292  * Get windows to unix mapping
1228*4520Snw141292  */
1229*4520Snw141292 idmap_stat
1230*4520Snw141292 idmap_get_w2u_mapping(idmap_handle_t *handle,
1231*4520Snw141292 		const char *sidprefix, idmap_rid_t *rid,
1232*4520Snw141292 		const char *winname, const char *windomain,
1233*4520Snw141292 		int flag, int *is_user,
1234*4520Snw141292 		uid_t *pid, char **unixname, int *direction) {
1235*4520Snw141292 	CLIENT			*clnt;
1236*4520Snw141292 	enum clnt_stat		clntstat;
1237*4520Snw141292 	idmap_mapping		request, *mapping;
1238*4520Snw141292 	idmap_mappings_res	result;
1239*4520Snw141292 	idmap_retcode		retcode, rc;
1240*4520Snw141292 	idmap_utf8str		*str;
1241*4520Snw141292 	const char		*me = "idmap_get_w2u_mapping";
1242*4520Snw141292 
1243*4520Snw141292 	if (handle == NULL) {
1244*4520Snw141292 		if (__idmap_verbose)
1245*4520Snw141292 			(void) fprintf(stderr,
1246*4520Snw141292 				gettext("%s: Invalid handle\n"), me);
1247*4520Snw141292 		errno = EINVAL;
1248*4520Snw141292 		return (IDMAP_ERR_ARG);
1249*4520Snw141292 	}
1250*4520Snw141292 
1251*4520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1252*4520Snw141292 
1253*4520Snw141292 	(void) memset(&request, 0, sizeof (request));
1254*4520Snw141292 	(void) memset(&result, 0, sizeof (result));
1255*4520Snw141292 
1256*4520Snw141292 	if (pid)
1257*4520Snw141292 		*pid = UINT32_MAX;
1258*4520Snw141292 	if (unixname)
1259*4520Snw141292 		*unixname = NULL;
1260*4520Snw141292 	if (direction)
1261*4520Snw141292 		*direction = -1;
1262*4520Snw141292 
1263*4520Snw141292 	request.flag = flag;
1264*4520Snw141292 	request.id1.idtype = IDMAP_SID;
1265*4520Snw141292 	if (sidprefix && rid) {
1266*4520Snw141292 		request.id1.idmap_id_u.sid.prefix = (char *)sidprefix;
1267*4520Snw141292 		request.id1.idmap_id_u.sid.rid = *rid;
1268*4520Snw141292 	} else if (winname) {
1269*4520Snw141292 		str = &request.id1name;
1270*4520Snw141292 		retcode = idmap_str2utf8(&str, winname, 1);
1271*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
1272*4520Snw141292 			goto out;
1273*4520Snw141292 		if (windomain) {
1274*4520Snw141292 			str = &request.id1domain;
1275*4520Snw141292 			retcode = idmap_str2utf8(&str, windomain, 1);
1276*4520Snw141292 			if (retcode != IDMAP_SUCCESS)
1277*4520Snw141292 				return (retcode);
1278*4520Snw141292 		}
1279*4520Snw141292 		request.id1.idmap_id_u.sid.prefix = NULL;
1280*4520Snw141292 	} else {
1281*4520Snw141292 		errno = EINVAL;
1282*4520Snw141292 		return (IDMAP_ERR_ARG);
1283*4520Snw141292 	}
1284*4520Snw141292 
1285*4520Snw141292 	if (is_user == NULL)
1286*4520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
1287*4520Snw141292 	else if (*is_user == 1)
1288*4520Snw141292 		request.id2.idtype = IDMAP_UID;
1289*4520Snw141292 	else if (*is_user == 0)
1290*4520Snw141292 		request.id2.idtype = IDMAP_GID;
1291*4520Snw141292 	else
1292*4520Snw141292 		request.id2.idtype = IDMAP_POSIXID;
1293*4520Snw141292 
1294*4520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1295*4520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1296*4520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1297*4520Snw141292 		TIMEOUT);
1298*4520Snw141292 
1299*4520Snw141292 	if (clntstat != RPC_SUCCESS) {
1300*4520Snw141292 		if (__idmap_verbose)
1301*4520Snw141292 			clnt_perror(clnt, "IDMAP_GET_MAPPED_ID_BY_NAME");
1302*4520Snw141292 		return (IDMAP_ERR_RPC);
1303*4520Snw141292 	}
1304*4520Snw141292 
1305*4520Snw141292 	retcode = result.retcode;
1306*4520Snw141292 
1307*4520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
1308*4520Snw141292 		if (retcode == IDMAP_SUCCESS)
1309*4520Snw141292 			retcode = IDMAP_ERR_NORESULT;
1310*4520Snw141292 		goto out;
1311*4520Snw141292 	}
1312*4520Snw141292 
1313*4520Snw141292 	if (is_user)
1314*4520Snw141292 		*is_user = (mapping->id2.idtype == IDMAP_UID)?1:0;
1315*4520Snw141292 	if (direction)
1316*4520Snw141292 		*direction = mapping->direction;
1317*4520Snw141292 	if (pid)
1318*4520Snw141292 		*pid = mapping->id2.idmap_id_u.uid;
1319*4520Snw141292 	if (unixname) {
1320*4520Snw141292 		rc = idmap_utf82str(unixname, 0, &mapping->id2name);
1321*4520Snw141292 		if (rc != IDMAP_SUCCESS)
1322*4520Snw141292 			retcode = rc;
1323*4520Snw141292 	}
1324*4520Snw141292 
1325*4520Snw141292 out:
1326*4520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
1327*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
1328*4520Snw141292 		errno = idmap_stat2errno(retcode);
1329*4520Snw141292 	return (retcode);
1330*4520Snw141292 }
1331*4520Snw141292 
1332*4520Snw141292 
1333*4520Snw141292 /*
1334*4520Snw141292  * Get unix to windows mapping
1335*4520Snw141292  */
1336*4520Snw141292 idmap_stat
1337*4520Snw141292 idmap_get_u2w_mapping(idmap_handle_t *handle,
1338*4520Snw141292 		uid_t *pid, const char *unixname,
1339*4520Snw141292 		int flag, int is_user,
1340*4520Snw141292 		char **sidprefix, idmap_rid_t *rid,
1341*4520Snw141292 		char **winname, char **windomain,
1342*4520Snw141292 		int *direction) {
1343*4520Snw141292 	CLIENT			*clnt;
1344*4520Snw141292 	enum clnt_stat		clntstat;
1345*4520Snw141292 	idmap_mapping		request, *mapping;
1346*4520Snw141292 	idmap_mappings_res	result;
1347*4520Snw141292 	idmap_retcode		retcode, rc;
1348*4520Snw141292 	idmap_utf8str		*str;
1349*4520Snw141292 	const char		*me = "idmap_get_u2w_mapping";
1350*4520Snw141292 
1351*4520Snw141292 	if (handle == NULL) {
1352*4520Snw141292 		if (__idmap_verbose)
1353*4520Snw141292 			(void) fprintf(stderr,
1354*4520Snw141292 				gettext("%s: Invalid handle\n"), me);
1355*4520Snw141292 		errno = EINVAL;
1356*4520Snw141292 		return (IDMAP_ERR_ARG);
1357*4520Snw141292 	}
1358*4520Snw141292 
1359*4520Snw141292 	_IDMAP_GET_CLIENT_HANDLE(handle, clnt);
1360*4520Snw141292 
1361*4520Snw141292 	if (sidprefix)
1362*4520Snw141292 		*sidprefix = NULL;
1363*4520Snw141292 	if (winname)
1364*4520Snw141292 		*winname = NULL;
1365*4520Snw141292 	if (windomain)
1366*4520Snw141292 		*windomain = NULL;
1367*4520Snw141292 	if (rid)
1368*4520Snw141292 		*rid = UINT32_MAX;
1369*4520Snw141292 	if (direction)
1370*4520Snw141292 		*direction = -1;
1371*4520Snw141292 
1372*4520Snw141292 	(void) memset(&request, 0, sizeof (request));
1373*4520Snw141292 	(void) memset(&result, 0, sizeof (result));
1374*4520Snw141292 
1375*4520Snw141292 	request.flag = flag;
1376*4520Snw141292 	request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID;
1377*4520Snw141292 
1378*4520Snw141292 	if (pid && *pid != UINT32_MAX) {
1379*4520Snw141292 		request.id1.idmap_id_u.uid = *pid;
1380*4520Snw141292 	} else if (unixname) {
1381*4520Snw141292 		str = &request.id1name;
1382*4520Snw141292 		retcode = idmap_str2utf8(&str, unixname, 1);
1383*4520Snw141292 		if (retcode != IDMAP_SUCCESS)
1384*4520Snw141292 			goto out;
1385*4520Snw141292 		request.id1.idmap_id_u.uid = UINT32_MAX;
1386*4520Snw141292 	} else {
1387*4520Snw141292 		errno = EINVAL;
1388*4520Snw141292 		return (IDMAP_ERR_ARG);
1389*4520Snw141292 	}
1390*4520Snw141292 
1391*4520Snw141292 	request.id2.idtype = IDMAP_SID;
1392*4520Snw141292 
1393*4520Snw141292 	clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME,
1394*4520Snw141292 		(xdrproc_t)xdr_idmap_mapping, (caddr_t)&request,
1395*4520Snw141292 		(xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result,
1396*4520Snw141292 		TIMEOUT);
1397*4520Snw141292 
1398*4520Snw141292 	if (clntstat != RPC_SUCCESS) {
1399*4520Snw141292 		if (__idmap_verbose)
1400*4520Snw141292 			clnt_perror(clnt, "IDMAP_GET_MAPPED_ID_BY_NAME");
1401*4520Snw141292 		return (IDMAP_ERR_RPC);
1402*4520Snw141292 	}
1403*4520Snw141292 
1404*4520Snw141292 	retcode = result.retcode;
1405*4520Snw141292 
1406*4520Snw141292 	if ((mapping = result.mappings.mappings_val) == NULL) {
1407*4520Snw141292 		if (retcode == IDMAP_SUCCESS)
1408*4520Snw141292 			retcode = IDMAP_ERR_NORESULT;
1409*4520Snw141292 		goto out;
1410*4520Snw141292 	}
1411*4520Snw141292 
1412*4520Snw141292 	if (direction)
1413*4520Snw141292 		*direction = mapping->direction;
1414*4520Snw141292 	if (sidprefix) {
1415*4520Snw141292 		*sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix);
1416*4520Snw141292 		if (*sidprefix == NULL) {
1417*4520Snw141292 			retcode = IDMAP_ERR_MEMORY;
1418*4520Snw141292 			goto errout;
1419*4520Snw141292 		}
1420*4520Snw141292 	}
1421*4520Snw141292 	if (rid)
1422*4520Snw141292 		*rid = mapping->id2.idmap_id_u.sid.rid;
1423*4520Snw141292 	if (winname) {
1424*4520Snw141292 		rc = idmap_utf82str(winname, 0, &mapping->id2name);
1425*4520Snw141292 		if (rc != IDMAP_SUCCESS) {
1426*4520Snw141292 			retcode = rc;
1427*4520Snw141292 			goto errout;
1428*4520Snw141292 		}
1429*4520Snw141292 	}
1430*4520Snw141292 	if (windomain) {
1431*4520Snw141292 		rc = idmap_utf82str(windomain, 0, &mapping->id2domain);
1432*4520Snw141292 		if (rc != IDMAP_SUCCESS) {
1433*4520Snw141292 			retcode = rc;
1434*4520Snw141292 			goto errout;
1435*4520Snw141292 		}
1436*4520Snw141292 	}
1437*4520Snw141292 
1438*4520Snw141292 	goto out;
1439*4520Snw141292 
1440*4520Snw141292 errout:
1441*4520Snw141292 	if (sidprefix && *sidprefix) {
1442*4520Snw141292 		free(*sidprefix);
1443*4520Snw141292 		*sidprefix = NULL;
1444*4520Snw141292 	}
1445*4520Snw141292 	if (winname && *winname) {
1446*4520Snw141292 		free(*winname);
1447*4520Snw141292 		*winname = NULL;
1448*4520Snw141292 	}
1449*4520Snw141292 	if (windomain && *windomain) {
1450*4520Snw141292 		free(*windomain);
1451*4520Snw141292 		*windomain = NULL;
1452*4520Snw141292 	}
1453*4520Snw141292 
1454*4520Snw141292 out:
1455*4520Snw141292 	xdr_free(xdr_idmap_mappings_res, (caddr_t)&result);
1456*4520Snw141292 	if (retcode != IDMAP_SUCCESS)
1457*4520Snw141292 		errno = idmap_stat2errno(retcode);
1458*4520Snw141292 	return (retcode);
1459*4520Snw141292 }
1460*4520Snw141292 
1461*4520Snw141292 
1462*4520Snw141292 /*
1463*4520Snw141292  * utf8str to string
1464*4520Snw141292  */
1465*4520Snw141292 idmap_stat
1466*4520Snw141292 idmap_utf82str(char **out, size_t outsize, idmap_utf8str *in) {
1467*4520Snw141292 	int len;
1468*4520Snw141292 
1469*4520Snw141292 	if (in == NULL || out == NULL)
1470*4520Snw141292 		return (IDMAP_ERR_ARG);
1471*4520Snw141292 
1472*4520Snw141292 	if (outsize == 0) {
1473*4520Snw141292 		*out = NULL;
1474*4520Snw141292 		if ((len = in->idmap_utf8str_len) == 0)
1475*4520Snw141292 			return (IDMAP_SUCCESS);
1476*4520Snw141292 		if (in->idmap_utf8str_val == NULL)
1477*4520Snw141292 			return (IDMAP_ERR_ARG);
1478*4520Snw141292 		if (in->idmap_utf8str_val[len - 1] != 0)
1479*4520Snw141292 			len++;
1480*4520Snw141292 		*out = calloc(1, len);
1481*4520Snw141292 		if (*out == NULL)
1482*4520Snw141292 			return (IDMAP_ERR_MEMORY);
1483*4520Snw141292 	} else {
1484*4520Snw141292 		if (*out == NULL)
1485*4520Snw141292 			return (IDMAP_ERR_ARG);
1486*4520Snw141292 		(void) memset(*out, 0, outsize);
1487*4520Snw141292 		if ((len = in->idmap_utf8str_len) == 0)
1488*4520Snw141292 			return (IDMAP_SUCCESS);
1489*4520Snw141292 		if (in->idmap_utf8str_val == NULL)
1490*4520Snw141292 			return (IDMAP_ERR_ARG);
1491*4520Snw141292 		if (in->idmap_utf8str_val[len - 1] != 0)
1492*4520Snw141292 			len++;
1493*4520Snw141292 		if (outsize < len)
1494*4520Snw141292 			return (IDMAP_ERR_ARG);
1495*4520Snw141292 	}
1496*4520Snw141292 	(void) memcpy(*out, in->idmap_utf8str_val, in->idmap_utf8str_len);
1497*4520Snw141292 	return (IDMAP_SUCCESS);
1498*4520Snw141292 }
1499*4520Snw141292 
1500*4520Snw141292 
1501*4520Snw141292 /*
1502*4520Snw141292  * string to utf8str
1503*4520Snw141292  */
1504*4520Snw141292 idmap_stat
1505*4520Snw141292 idmap_str2utf8(idmap_utf8str **out, const char *in, int flag) {
1506*4520Snw141292 	idmap_utf8str	*tmp;
1507*4520Snw141292 
1508*4520Snw141292 	if (out == NULL)
1509*4520Snw141292 		return (IDMAP_ERR_ARG);
1510*4520Snw141292 	else if (*out == NULL) {
1511*4520Snw141292 		tmp = malloc(sizeof (idmap_utf8str));
1512*4520Snw141292 		if (tmp == NULL)
1513*4520Snw141292 			return (IDMAP_ERR_MEMORY);
1514*4520Snw141292 	} else {
1515*4520Snw141292 		tmp = *out;
1516*4520Snw141292 	}
1517*4520Snw141292 
1518*4520Snw141292 	if (in == NULL) {
1519*4520Snw141292 		tmp->idmap_utf8str_len = 0;
1520*4520Snw141292 		tmp->idmap_utf8str_val = NULL;
1521*4520Snw141292 		if (*out == NULL)
1522*4520Snw141292 			*out = tmp;
1523*4520Snw141292 		return (IDMAP_SUCCESS);
1524*4520Snw141292 	}
1525*4520Snw141292 
1526*4520Snw141292 	/* include the null terminator */
1527*4520Snw141292 	tmp->idmap_utf8str_len = strlen(in) + 1;
1528*4520Snw141292 
1529*4520Snw141292 	if (flag == 1) {
1530*4520Snw141292 		/* Don't malloc, simply assign */
1531*4520Snw141292 		tmp->idmap_utf8str_val = (char *)in;
1532*4520Snw141292 		if (*out == NULL)
1533*4520Snw141292 			*out = tmp;
1534*4520Snw141292 		return (IDMAP_SUCCESS);
1535*4520Snw141292 	}
1536*4520Snw141292 
1537*4520Snw141292 	tmp->idmap_utf8str_val = malloc(tmp->idmap_utf8str_len);
1538*4520Snw141292 	if (tmp->idmap_utf8str_val == NULL) {
1539*4520Snw141292 		tmp->idmap_utf8str_len = 0;
1540*4520Snw141292 		if (*out == NULL)
1541*4520Snw141292 			free(tmp);
1542*4520Snw141292 		return (IDMAP_ERR_MEMORY);
1543*4520Snw141292 	}
1544*4520Snw141292 	(void) memcpy(tmp->idmap_utf8str_val, in, tmp->idmap_utf8str_len);
1545*4520Snw141292 	if (*out == NULL)
1546*4520Snw141292 		*out = tmp;
1547*4520Snw141292 	return (IDMAP_SUCCESS);
1548*4520Snw141292 }
1549*4520Snw141292 
1550*4520Snw141292 
1551*4520Snw141292 #define	gettext(s)	s
1552*4520Snw141292 static stat_table_t stattable[] = {
1553*4520Snw141292 	{IDMAP_SUCCESS, gettext("Success"), 0},
1554*4520Snw141292 	{IDMAP_NEXT, gettext("More results available"), 0},
1555*4520Snw141292 	{IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL},
1556*4520Snw141292 	{IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL},
1557*4520Snw141292 	{IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM},
1558*4520Snw141292 	{IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL},
1559*4520Snw141292 	{IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL},
1560*4520Snw141292 	{IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL},
1561*4520Snw141292 	{IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), EINVAL},
1562*4520Snw141292 	{IDMAP_ERR_W2U_NAMERULE,
1563*4520Snw141292 		gettext("Invalid Windows to UNIX name-based rule"), EINVAL},
1564*4520Snw141292 	{IDMAP_ERR_U2W_NAMERULE,
1565*4520Snw141292 		gettext("Invalid UNIX to Windows name-based rule"), EINVAL},
1566*4520Snw141292 	{IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL},
1567*4520Snw141292 	{IDMAP_ERR_DB, gettext("Invalid database"), EINVAL},
1568*4520Snw141292 	{IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL},
1569*4520Snw141292 	{IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL},
1570*4520Snw141292 	{IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL},
1571*4520Snw141292 	{IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EINVAL},
1572*4520Snw141292 	{IDMAP_ERR_RPC, gettext("RPC error"), EINVAL},
1573*4520Snw141292 	{IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL},
1574*4520Snw141292 	{IDMAP_ERR_BUSY, gettext("Server is busy"), EINVAL},
1575*4520Snw141292 	{IDMAP_ERR_PERMISSION_DENIED, gettext("Permisssion denied"), EINVAL},
1576*4520Snw141292 	{IDMAP_ERR_NOMAPPING,
1577*4520Snw141292 		gettext("Mapping not found or inhibited"), EINVAL},
1578*4520Snw141292 	{IDMAP_ERR_NEW_ID_ALLOC_REQD,
1579*4520Snw141292 		gettext("New mapping needs to be created"), EINVAL},
1580*4520Snw141292 	{IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL},
1581*4520Snw141292 	{IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL},
1582*4520Snw141292 	{IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL},
1583*4520Snw141292 	{IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL},
1584*4520Snw141292 	{IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL},
1585*4520Snw141292 	{IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL},
1586*4520Snw141292 	{IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL},
1587*4520Snw141292 	{IDMAP_ERR_NOTMAPPED_WELLKNOWN,
1588*4520Snw141292 		gettext("No mapping for well-known SID"), EINVAL},
1589*4520Snw141292 	{IDMAP_ERR_RETRIABLE_NET_ERR,
1590*4520Snw141292 		gettext("Network error"), EINVAL},
1591*4520Snw141292 	{-1, NULL, 0}
1592*4520Snw141292 };
1593*4520Snw141292 #undef	gettext
1594*4520Snw141292 
1595*4520Snw141292 
1596*4520Snw141292 /*
1597*4520Snw141292  * Get description of status code
1598*4520Snw141292  *
1599*4520Snw141292  * Input:
1600*4520Snw141292  * status - Status code returned by libidmap API call
1601*4520Snw141292  *
1602*4520Snw141292  * Return Value:
1603*4520Snw141292  * human-readable localized description of idmap_stat
1604*4520Snw141292  */
1605*4520Snw141292 /* ARGSUSED */
1606*4520Snw141292 const char *
1607*4520Snw141292 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) {
1608*4520Snw141292 	int i;
1609*4520Snw141292 
1610*4520Snw141292 	for (i = 0; stattable[i].msg; i++) {
1611*4520Snw141292 		if (stattable[i].retcode == status)
1612*4520Snw141292 			return (stattable[i].msg);
1613*4520Snw141292 	}
1614*4520Snw141292 	return (gettext("Unknown error"));
1615*4520Snw141292 }
1616*4520Snw141292 
1617*4520Snw141292 
1618*4520Snw141292 static int
1619*4520Snw141292 idmap_stat2errno(idmap_stat stat) {
1620*4520Snw141292 	int i;
1621*4520Snw141292 	for (i = 0; stattable[i].msg; i++) {
1622*4520Snw141292 		if (stattable[i].retcode == stat)
1623*4520Snw141292 			return (stattable[i].errnum);
1624*4520Snw141292 	}
1625*4520Snw141292 	return (EINVAL);
1626*4520Snw141292 }
1627*4520Snw141292 
1628*4520Snw141292 
1629*4520Snw141292 /*
1630*4520Snw141292  * Get status code from string
1631*4520Snw141292  */
1632*4520Snw141292 idmap_stat
1633*4520Snw141292 idmap_string2stat(const char *str) {
1634*4520Snw141292 	if (str == NULL)
1635*4520Snw141292 		return (IDMAP_ERR_INTERNAL);
1636*4520Snw141292 
1637*4520Snw141292 #define	return_cmp(a) \
1638*4520Snw141292 	if (0 == strcmp(str, "IDMAP_ERR_" #a)) \
1639*4520Snw141292 		return (IDMAP_ERR_ ## a);
1640*4520Snw141292 
1641*4520Snw141292 	return_cmp(OTHER);
1642*4520Snw141292 	return_cmp(INTERNAL);
1643*4520Snw141292 	return_cmp(MEMORY);
1644*4520Snw141292 	return_cmp(NORESULT);
1645*4520Snw141292 	return_cmp(NOTUSER);
1646*4520Snw141292 	return_cmp(NOTGROUP);
1647*4520Snw141292 	return_cmp(NOTSUPPORTED);
1648*4520Snw141292 	return_cmp(W2U_NAMERULE);
1649*4520Snw141292 	return_cmp(U2W_NAMERULE);
1650*4520Snw141292 	return_cmp(CACHE);
1651*4520Snw141292 	return_cmp(DB);
1652*4520Snw141292 	return_cmp(ARG);
1653*4520Snw141292 	return_cmp(SID);
1654*4520Snw141292 	return_cmp(IDTYPE);
1655*4520Snw141292 	return_cmp(RPC_HANDLE);
1656*4520Snw141292 	return_cmp(RPC);
1657*4520Snw141292 	return_cmp(CLIENT_HANDLE);
1658*4520Snw141292 	return_cmp(BUSY);
1659*4520Snw141292 	return_cmp(PERMISSION_DENIED);
1660*4520Snw141292 	return_cmp(NOMAPPING);
1661*4520Snw141292 	return_cmp(NEW_ID_ALLOC_REQD);
1662*4520Snw141292 	return_cmp(DOMAIN);
1663*4520Snw141292 	return_cmp(SECURITY);
1664*4520Snw141292 	return_cmp(NOTFOUND);
1665*4520Snw141292 	return_cmp(DOMAIN_NOTFOUND);
1666*4520Snw141292 	return_cmp(MEMORY);
1667*4520Snw141292 	return_cmp(UPDATE_NOTALLOWED);
1668*4520Snw141292 	return_cmp(CFG);
1669*4520Snw141292 	return_cmp(CFG_CHANGE);
1670*4520Snw141292 	return_cmp(NOTMAPPED_WELLKNOWN);
1671*4520Snw141292 	return_cmp(RETRIABLE_NET_ERR);
1672*4520Snw141292 #undef return_cmp
1673*4520Snw141292 
1674*4520Snw141292 	return (IDMAP_ERR_OTHER);
1675*4520Snw141292 }
1676*4520Snw141292 
1677*4520Snw141292 
1678*4520Snw141292 /*
1679*4520Snw141292  * Map the given status to one that can be returned by the protocol
1680*4520Snw141292  */
1681*4520Snw141292 idmap_stat
1682*4520Snw141292 idmap_stat4prot(idmap_stat status) {
1683*4520Snw141292 	switch (status) {
1684*4520Snw141292 	case IDMAP_ERR_MEMORY:
1685*4520Snw141292 	case IDMAP_ERR_CACHE:
1686*4520Snw141292 		return (IDMAP_ERR_INTERNAL);
1687*4520Snw141292 	}
1688*4520Snw141292 	return (status);
1689*4520Snw141292 }
1690