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