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