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