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