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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2018 Nexenta Systems, Inc.
27 */
28
29 /*
30 * Windows to Solaris Identity Mapping kernel API
31 * This module provides an API to map Windows SIDs to
32 * Solaris UID and GIDs.
33 */
34
35
36 #include <sys/types.h>
37 #include <sys/ksynch.h>
38 #include <sys/door.h>
39 #include <rpc/rpc_msg.h>
40 #include <rpc/xdr.h>
41 #include <rpc/auth.h>
42 #include <rpc/rpc_sztypes.h>
43 #ifdef DEBUG
44 #include <sys/cmn_err.h>
45 #endif /* DEBUG */
46 #include <sys/proc.h>
47 #include <sys/sunddi.h>
48 #include <sys/param.h>
49 #include <sys/atomic.h>
50 #include <sys/sysmacros.h>
51 #include <sys/disp.h>
52 #include <sys/kidmap.h>
53 #include <sys/zone.h>
54 #include <rpcsvc/idmap_prot.h>
55 #include "kidmap_priv.h"
56
57
58 /*
59 * Defined types
60 */
61
62
63 /*
64 * This structure holds pointers for the
65 * batch mapping results.
66 */
67 typedef struct idmap_get_res {
68 idmap_id_type idtype;
69 uid_t *uid;
70 gid_t *gid;
71 uid_t *pid;
72 int *is_user;
73 const char **sid_prefix;
74 uint32_t *rid;
75 idmap_stat *stat;
76 } idmap_get_res;
77
78 /* Batch mapping handle structure */
79 struct idmap_get_handle {
80 struct idmap_zone_specific *zs;
81 int mapping_num;
82 int mapping_size;
83 idmap_mapping *mapping;
84 idmap_get_res *result;
85 };
86
87
88 /* Zone specific data */
89 typedef struct idmap_zone_specific {
90 zoneid_t zone_id;
91 kmutex_t zone_mutex;
92 idmap_cache_t cache;
93 door_handle_t door_handle;
94 int door_valid;
95 int door_retried;
96 uint32_t message_id;
97 } idmap_zone_specific_t;
98
99
100
101 /*
102 * Module global data
103 */
104
105 static kmutex_t idmap_zone_mutex;
106 static zone_key_t idmap_zone_key;
107
108
109 /*
110 * Local function definitions
111 */
112
113
114 static int
115 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op,
116 xdrproc_t xdr_args, caddr_t args, xdrproc_t xdr_res, caddr_t res);
117
118 static int
119 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg);
120
121 static idmap_zone_specific_t *
122 idmap_get_zone_specific(zone_t *zone);
123
124
125
126 int
idmap_reg_dh(zone_t * zone,door_handle_t dh)127 idmap_reg_dh(zone_t *zone, door_handle_t dh)
128 {
129 idmap_zone_specific_t *zs;
130
131 zs = idmap_get_zone_specific(zone);
132
133 mutex_enter(&zs->zone_mutex);
134
135 if (zs->door_valid)
136 door_ki_rele(zs->door_handle);
137
138 zs->door_handle = dh;
139 zs->door_valid = 1;
140
141 mutex_exit(&zs->zone_mutex);
142
143 return (0);
144 }
145
146 /*
147 * idmap_unreg_dh
148 *
149 * This routine is called by system call idmap_unreg().
150 * idmap_unreg() calls door_ki_rele() on the supplied
151 * door handle after this routine returns. We only
152 * need to perform one door release on zs->door_handle
153 */
154 int
idmap_unreg_dh(zone_t * zone,door_handle_t dh)155 idmap_unreg_dh(zone_t *zone, door_handle_t dh)
156 {
157 idmap_zone_specific_t *zs;
158
159 zs = idmap_get_zone_specific(zone);
160
161 kidmap_cache_purge(&zs->cache);
162
163 mutex_enter(&zs->zone_mutex);
164
165 if (!zs->door_valid || zs->door_handle != dh) {
166 mutex_exit(&zs->zone_mutex);
167 return (EINVAL);
168 }
169
170 door_ki_rele(zs->door_handle);
171
172 zs->door_valid = 0;
173 zs->door_retried = 0;
174 mutex_exit(&zs->zone_mutex);
175
176 return (0);
177 }
178
179
180 /*
181 * IMPORTANT. This function idmap_get_cache_data() is project
182 * private and is for use of the test system only and should
183 * not be used for other purposes.
184 */
185 void
idmap_get_cache_data(zone_t * zone,size_t * uidbysid,size_t * gidbysid,size_t * pidbysid,size_t * sidbyuid,size_t * sidbygid)186 idmap_get_cache_data(zone_t *zone, size_t *uidbysid, size_t *gidbysid,
187 size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid)
188 {
189 idmap_zone_specific_t *zs;
190
191 zs = idmap_get_zone_specific(zone);
192
193 kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid,
194 pidbysid, sidbyuid, sidbygid);
195 }
196
197 static int
kidmap_call_door(idmap_zone_specific_t * zs,door_arg_t * arg)198 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg)
199 {
200 door_handle_t dh;
201 door_info_t di;
202 int status = 0;
203 int num_retries = 5;
204 int door_retried = 0;
205
206 retry:
207 mutex_enter(&zs->zone_mutex);
208 if (zs->door_valid) {
209 dh = zs->door_handle;
210 door_ki_hold(dh);
211 } else {
212 dh = NULL;
213 door_retried = zs->door_retried;
214 }
215 mutex_exit(&zs->zone_mutex);
216
217 if (dh == NULL) {
218 /* The door has been retried before so dont wait */
219 if (door_retried)
220 return (-1);
221
222 /*
223 * There is no door handle yet. Give
224 * smf a chance to restart idmapd
225 */
226 if (num_retries-- > 0) {
227 delay(hz);
228 goto retry;
229 }
230
231 #ifdef DEBUG
232 zcmn_err(zs->zone_id, CE_WARN,
233 "idmap: Error no registered door to call the "
234 "idmap daemon\n");
235 #endif
236 mutex_enter(&zs->zone_mutex);
237 if (!zs->door_valid)
238 zs->door_retried = 1;
239 mutex_exit(&zs->zone_mutex);
240
241 return (-1);
242 }
243
244 status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0);
245
246 switch (status) {
247 case 0: /* Success */
248 door_ki_rele(dh);
249 return (0);
250
251 case EINTR:
252 /* If we took an interrupt we have to bail out. */
253 if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) {
254 door_ki_rele(dh);
255 #ifdef DEBUG
256 zcmn_err(zs->zone_id, CE_WARN,
257 "idmap: Interrupted\n");
258 #endif
259 return (-1);
260 }
261 /*
262 * Just retry and see what happens.
263 */
264 /* FALLTHROUGH */
265
266 case EAGAIN:
267 /* A resouce problem */
268 door_ki_rele(dh);
269 /* Back off before retrying */
270 #ifdef DEBUG
271 zcmn_err(zs->zone_id, CE_WARN,
272 "idmap: Door call returned error %d. Retrying\n", status);
273 #endif /* DEBUG */
274 delay(hz);
275 goto retry;
276
277 case EBADF:
278 /* Stale door handle. See if smf restarts the daemon. */
279 door_ki_rele(dh);
280 mutex_enter(&zs->zone_mutex);
281 if (zs->door_valid && dh == zs->door_handle) {
282 zs->door_valid = 0;
283 zs->door_retried = 0;
284 door_ki_rele(zs->door_handle);
285 }
286 mutex_exit(&zs->zone_mutex);
287 /* Back off before retrying */
288 #ifdef DEBUG
289 zcmn_err(zs->zone_id, CE_WARN,
290 "idmap: Door call returned error %d. Retrying\n", status);
291 #endif /* DEBUG */
292 delay(hz);
293 goto retry;
294
295 default:
296 /* Unknown error */
297 #ifdef DEBUG
298 zcmn_err(zs->zone_id, CE_WARN,
299 "idmap: Door call returned error %d.\n", status);
300 #endif /* DEBUG */
301 door_ki_rele(dh);
302 return (-1);
303 }
304 }
305
306
307 static idmap_zone_specific_t *
idmap_get_zone_specific(zone_t * zone)308 idmap_get_zone_specific(zone_t *zone)
309 {
310 idmap_zone_specific_t *zs;
311
312 ASSERT(zone != NULL);
313
314 zs = zone_getspecific(idmap_zone_key, zone);
315 if (zs != NULL)
316 return (zs);
317
318 mutex_enter(&idmap_zone_mutex);
319 zs = zone_getspecific(idmap_zone_key, zone);
320 if (zs == NULL) {
321 zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP);
322 mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL);
323 kidmap_cache_create(&zs->cache);
324 zs->zone_id = zone->zone_id;
325 (void) zone_setspecific(idmap_zone_key, zone, zs);
326 mutex_exit(&idmap_zone_mutex);
327 return (zs);
328 }
329 mutex_exit(&idmap_zone_mutex);
330
331 return (zs);
332 }
333
334
335 static void
336 /* ARGSUSED */
idmap_zone_destroy(zoneid_t zone_id,void * arg)337 idmap_zone_destroy(zoneid_t zone_id, void *arg)
338 {
339 idmap_zone_specific_t *zs = arg;
340 if (zs != NULL) {
341 kidmap_cache_delete(&zs->cache);
342 if (zs->door_valid) {
343 door_ki_rele(zs->door_handle);
344 }
345 mutex_destroy(&zs->zone_mutex);
346 kmem_free(zs, sizeof (idmap_zone_specific_t));
347 }
348 }
349
350
351 int
kidmap_start(void)352 kidmap_start(void)
353 {
354 mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
355 zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy);
356 kidmap_sid_prefix_store_init();
357
358 return (0);
359 }
360
361
362 int
kidmap_stop(void)363 kidmap_stop(void)
364 {
365 return (EBUSY);
366 }
367
368
369 /*
370 * idmap_get_door
371 *
372 * This is called by the system call allocids() to get the door for the
373 * given zone.
374 */
375 door_handle_t
idmap_get_door(zone_t * zone)376 idmap_get_door(zone_t *zone)
377 {
378 door_handle_t dh = NULL;
379 idmap_zone_specific_t *zs;
380
381 zs = idmap_get_zone_specific(zone);
382
383 mutex_enter(&zs->zone_mutex);
384 if (zs->door_valid) {
385 dh = zs->door_handle;
386 door_ki_hold(dh);
387 }
388 mutex_exit(&zs->zone_mutex);
389 return (dh);
390 }
391
392
393 /*
394 * idmap_purge_cache
395 *
396 * This is called by the system call allocids() to purge the cache for the
397 * given zone.
398 */
399 void
idmap_purge_cache(zone_t * zone)400 idmap_purge_cache(zone_t *zone)
401 {
402 idmap_zone_specific_t *zs;
403
404 zs = idmap_get_zone_specific(zone);
405
406 kidmap_cache_purge(&zs->cache);
407 }
408
409
410
411
412 /*
413 * Given Domain SID and RID, get UID
414 *
415 * Input:
416 * sid_prefix - Domain SID in canonical form
417 * rid - RID
418 *
419 * Output:
420 * uid - POSIX UID if return == IDMAP_SUCCESS
421 *
422 * Return:
423 * Success return IDMAP_SUCCESS else IDMAP error
424 */
425 idmap_stat
kidmap_getuidbysid(zone_t * zone,const char * sid_prefix,uint32_t rid,uid_t * uid)426 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
427 uid_t *uid)
428 {
429 idmap_zone_specific_t *zs;
430 idmap_mapping_batch args;
431 idmap_mapping mapping;
432 idmap_ids_res results;
433 uint32_t op = IDMAP_GET_MAPPED_IDS;
434 const char *new_sid_prefix;
435 idmap_stat status;
436
437 if (sid_prefix == NULL || uid == NULL)
438 return (IDMAP_ERR_ARG);
439
440 zs = idmap_get_zone_specific(zone);
441
442 if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid)
443 == IDMAP_SUCCESS)
444 return (IDMAP_SUCCESS);
445
446 bzero(&mapping, sizeof (idmap_mapping));
447 mapping.id1.idtype = IDMAP_SID;
448 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
449 mapping.id1.idmap_id_u.sid.rid = rid;
450 mapping.id2.idtype = IDMAP_UID;
451
452 bzero(&results, sizeof (idmap_ids_res));
453
454 args.idmap_mapping_batch_len = 1;
455 args.idmap_mapping_batch_val = &mapping;
456
457 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
458 (caddr_t)&args, xdr_idmap_ids_res,
459 (caddr_t)&results) == 0) {
460 /* Door call succeded */
461 if (results.retcode != IDMAP_SUCCESS) {
462 status = results.retcode;
463 *uid = UID_NOBODY;
464 } else if (results.ids.ids_len >= 1 &&
465 results.ids.ids_val[0].id.idtype == IDMAP_UID) {
466 status = results.ids.ids_val[0].retcode;
467 *uid = results.ids.ids_val[0].id.idmap_id_u.uid;
468 if (status == IDMAP_SUCCESS) {
469 new_sid_prefix = kidmap_find_sid_prefix(
470 sid_prefix);
471 kidmap_cache_add_sid2uid(&zs->cache,
472 new_sid_prefix, rid, *uid,
473 results.ids.ids_val[0].direction);
474 }
475 } else {
476 status = IDMAP_ERR_NOMAPPING;
477 *uid = UID_NOBODY;
478 }
479 xdr_free(xdr_idmap_ids_res, (char *)&results);
480 } else {
481 /* Door call failed */
482 status = IDMAP_ERR_NOMAPPING;
483 *uid = UID_NOBODY;
484 }
485 return (status);
486 }
487
488
489 /*
490 * Given Domain SID and RID, get GID
491 *
492 * Input:
493 * sid_prefix - Domain SID in canonical form
494 * rid - RID
495 *
496 * Output:
497 * gid - POSIX UID if return == IDMAP_SUCCESS
498 *
499 * Return:
500 * Success return IDMAP_SUCCESS else IDMAP error
501 */
502 idmap_stat
kidmap_getgidbysid(zone_t * zone,const char * sid_prefix,uint32_t rid,gid_t * gid)503 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
504 gid_t *gid)
505 {
506 idmap_zone_specific_t *zs;
507 idmap_mapping_batch args;
508 idmap_mapping mapping;
509 idmap_ids_res results;
510 uint32_t op = IDMAP_GET_MAPPED_IDS;
511 const char *new_sid_prefix;
512 idmap_stat status;
513
514 if (sid_prefix == NULL || gid == NULL)
515 return (IDMAP_ERR_ARG);
516
517 zs = idmap_get_zone_specific(zone);
518
519 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid)
520 == IDMAP_SUCCESS)
521 return (IDMAP_SUCCESS);
522
523 bzero(&mapping, sizeof (idmap_mapping));
524 mapping.id1.idtype = IDMAP_SID;
525 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
526 mapping.id1.idmap_id_u.sid.rid = rid;
527 mapping.id2.idtype = IDMAP_GID;
528
529 bzero(&results, sizeof (idmap_ids_res));
530
531 args.idmap_mapping_batch_len = 1;
532 args.idmap_mapping_batch_val = &mapping;
533
534 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
535 (caddr_t)&args, xdr_idmap_ids_res,
536 (caddr_t)&results) == 0) {
537 /* Door call succeded */
538 if (results.retcode != IDMAP_SUCCESS) {
539 status = results.retcode;
540 *gid = GID_NOBODY;
541 } else if (results.ids.ids_len >= 1 &&
542 results.ids.ids_val[0].id.idtype == IDMAP_GID) {
543 status = results.ids.ids_val[0].retcode;
544 *gid = results.ids.ids_val[0].id.idmap_id_u.gid;
545 if (status == IDMAP_SUCCESS) {
546 new_sid_prefix = kidmap_find_sid_prefix(
547 sid_prefix);
548 kidmap_cache_add_sid2gid(&zs->cache,
549 new_sid_prefix, rid, *gid,
550 results.ids.ids_val[0].direction);
551 }
552 } else {
553 status = IDMAP_ERR_NOMAPPING;
554 *gid = GID_NOBODY;
555 }
556 xdr_free(xdr_idmap_ids_res, (char *)&results);
557 } else {
558 /* Door call failed */
559 status = IDMAP_ERR_NOMAPPING;
560 *gid = GID_NOBODY;
561 }
562 return (status);
563 }
564
565 /*
566 * Given Domain SID and RID, get Posix ID
567 *
568 * Input:
569 * sid_prefix - Domain SID in canonical form
570 * rid - RID
571 *
572 * Output:
573 * pid - POSIX ID if return == IDMAP_SUCCESS
574 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS
575 *
576 * Return:
577 * Success return IDMAP_SUCCESS else IDMAP error
578 */
579 idmap_stat
kidmap_getpidbysid(zone_t * zone,const char * sid_prefix,uint32_t rid,uid_t * pid,int * is_user)580 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
581 uid_t *pid, int *is_user)
582 {
583 idmap_zone_specific_t *zs;
584 idmap_mapping_batch args;
585 idmap_mapping mapping;
586 idmap_ids_res results;
587 uint32_t op = IDMAP_GET_MAPPED_IDS;
588 const char *new_sid_prefix;
589 idmap_stat status;
590
591 if (sid_prefix == NULL || pid == NULL || is_user == NULL)
592 return (IDMAP_ERR_ARG);
593
594 zs = idmap_get_zone_specific(zone);
595
596 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid,
597 is_user) == IDMAP_SUCCESS)
598 return (IDMAP_SUCCESS);
599
600 bzero(&mapping, sizeof (idmap_mapping));
601 mapping.id1.idtype = IDMAP_SID;
602 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
603 mapping.id1.idmap_id_u.sid.rid = rid;
604 mapping.id2.idtype = IDMAP_POSIXID;
605
606 bzero(&results, sizeof (idmap_ids_res));
607
608 args.idmap_mapping_batch_len = 1;
609 args.idmap_mapping_batch_val = &mapping;
610
611 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
612 (caddr_t)&args, xdr_idmap_ids_res,
613 (caddr_t)&results) == 0) {
614 /* Door call succeded */
615 if (results.retcode != IDMAP_SUCCESS) {
616 status = results.retcode;
617 *is_user = 1;
618 *pid = UID_NOBODY;
619 } else if (results.ids.ids_len >= 1 && (
620 results.ids.ids_val[0].id.idtype == IDMAP_UID ||
621 results.ids.ids_val[0].id.idtype == IDMAP_GID)) {
622 status = results.ids.ids_val[0].retcode;
623 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) {
624 *is_user = 1;
625 *pid = results.ids.ids_val[0].id.idmap_id_u.uid;
626 } else {
627 *is_user = 0;
628 *pid = results.ids.ids_val[0].id.idmap_id_u.gid;
629 }
630 if (status == IDMAP_SUCCESS) {
631 new_sid_prefix = kidmap_find_sid_prefix(
632 sid_prefix);
633 kidmap_cache_add_sid2pid(&zs->cache,
634 new_sid_prefix, rid, *pid,
635 *is_user,
636 results.ids.ids_val[0].direction);
637 }
638 } else {
639 status = IDMAP_ERR_NOMAPPING;
640 *is_user = 1;
641 *pid = UID_NOBODY;
642 }
643 xdr_free(xdr_idmap_ids_res, (char *)&results);
644 } else {
645 /* Door call failed */
646 status = IDMAP_ERR_NOMAPPING;
647 *is_user = 1;
648 *pid = UID_NOBODY;
649 }
650 return (status);
651 }
652
653
654 /*
655 * Given UID, get Domain SID and RID
656 *
657 * Input:
658 * uid - Posix UID
659 *
660 * Output:
661 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
662 * rid - RID if return == IDMAP_SUCCESS
663 *
664 * Return:
665 * Success return IDMAP_SUCCESS else IDMAP error
666 */
667 idmap_stat
kidmap_getsidbyuid(zone_t * zone,uid_t uid,const char ** sid_prefix,uint32_t * rid)668 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
669 uint32_t *rid)
670 {
671 idmap_zone_specific_t *zs;
672 idmap_mapping_batch args;
673 idmap_mapping mapping;
674 idmap_ids_res results;
675 uint32_t op = IDMAP_GET_MAPPED_IDS;
676 idmap_stat status;
677 time_t entry_ttl;
678 idmap_id *id;
679
680 if (sid_prefix == NULL || rid == NULL)
681 return (IDMAP_ERR_ARG);
682
683 zs = idmap_get_zone_specific(zone);
684
685 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid)
686 == IDMAP_SUCCESS) {
687 return (IDMAP_SUCCESS);
688 }
689
690 bzero(&mapping, sizeof (idmap_mapping));
691 mapping.id1.idtype = IDMAP_UID;
692 mapping.id1.idmap_id_u.uid = uid;
693 mapping.id2.idtype = IDMAP_SID;
694
695 bzero(&results, sizeof (idmap_ids_res));
696
697 args.idmap_mapping_batch_len = 1;
698 args.idmap_mapping_batch_val = &mapping;
699
700 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
701 (caddr_t)&args, xdr_idmap_ids_res,
702 (caddr_t)&results) == 0) {
703 /* Door call succeded */
704 if (results.retcode != IDMAP_SUCCESS) {
705 status = results.retcode;
706 *rid = 0;
707 *sid_prefix = NULL;
708 } else if (results.ids.ids_len >= 1 &&
709 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
710 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
711 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
712 status = results.ids.ids_val[0].retcode;
713 id = &results.ids.ids_val[0].id;
714 *sid_prefix = kidmap_find_sid_prefix(
715 id->idmap_id_u.sid.prefix);
716 *rid = id->idmap_id_u.sid.rid;
717 if (status == IDMAP_SUCCESS) {
718 kidmap_cache_add_sid2uid(&zs->cache,
719 *sid_prefix, *rid, uid,
720 results.ids.ids_val[0].direction);
721 }
722 } else {
723 status = IDMAP_ERR_NOMAPPING;
724 *rid = 0;
725 *sid_prefix = NULL;
726 }
727 xdr_free(xdr_idmap_ids_res, (char *)&results);
728 } else {
729 /* Door call failed */
730 status = IDMAP_ERR_NOMAPPING;
731 *rid = 0;
732 *sid_prefix = NULL;
733 }
734 return (status);
735 }
736
737
738 /*
739 * Given GID, get Domain SID and RID
740 *
741 * Input:
742 * gid - Posix GID
743 *
744 * Output:
745 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
746 * rid - RID if return == IDMAP_SUCCESS
747 *
748 * Return:
749 * Success return IDMAP_SUCCESS else IDMAP error
750 */
751 idmap_stat
kidmap_getsidbygid(zone_t * zone,gid_t gid,const char ** sid_prefix,uint32_t * rid)752 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
753 uint32_t *rid)
754 {
755 idmap_zone_specific_t *zs;
756 idmap_mapping_batch args;
757 idmap_mapping mapping;
758 idmap_ids_res results;
759 uint32_t op = IDMAP_GET_MAPPED_IDS;
760 idmap_stat status;
761 idmap_id *id;
762
763 if (sid_prefix == NULL || rid == NULL)
764 return (IDMAP_ERR_ARG);
765
766 zs = idmap_get_zone_specific(zone);
767
768 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid)
769 == IDMAP_SUCCESS) {
770 return (IDMAP_SUCCESS);
771 }
772
773 bzero(&mapping, sizeof (idmap_mapping));
774 mapping.id1.idtype = IDMAP_GID;
775 mapping.id1.idmap_id_u.uid = gid;
776 mapping.id2.idtype = IDMAP_SID;
777
778 bzero(&results, sizeof (idmap_ids_res));
779
780 args.idmap_mapping_batch_len = 1;
781 args.idmap_mapping_batch_val = &mapping;
782
783 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
784 (caddr_t)&args, xdr_idmap_ids_res,
785 (caddr_t)&results) == 0) {
786 /* Door call succeded */
787 if (results.retcode != IDMAP_SUCCESS) {
788 status = results.retcode;
789 *rid = 0;
790 *sid_prefix = NULL;
791 } else if (results.ids.ids_len >= 1 &&
792 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
793 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
794 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
795 status = results.ids.ids_val[0].retcode;
796 id = &results.ids.ids_val[0].id;
797 *sid_prefix = kidmap_find_sid_prefix(
798 id->idmap_id_u.sid.prefix);
799 *rid = id->idmap_id_u.sid.rid;
800 if (status == IDMAP_SUCCESS) {
801 kidmap_cache_add_sid2gid(&zs->cache,
802 *sid_prefix, *rid, gid,
803 results.ids.ids_val[0].direction);
804 }
805 } else {
806 status = IDMAP_ERR_NOMAPPING;
807 *rid = 0;
808 *sid_prefix = NULL;
809 }
810 xdr_free(xdr_idmap_ids_res, (char *)&results);
811 } else {
812 /* Door call failed */
813 status = IDMAP_ERR_NOMAPPING;
814 *rid = 0;
815 *sid_prefix = NULL;
816 }
817 return (status);
818 }
819
820 /*
821 * Create handle to get SID to UID/GID mapping entries
822 *
823 * Input:
824 * none
825 * Return:
826 * get_handle
827 *
828 */
829 idmap_get_handle_t *
kidmap_get_create(zone_t * zone)830 kidmap_get_create(zone_t *zone)
831 {
832 idmap_zone_specific_t *zs;
833 idmap_get_handle_t *handle;
834 #define INIT_MAPPING_SIZE 32
835
836 zs = idmap_get_zone_specific(zone);
837
838 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP);
839
840 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) *
841 INIT_MAPPING_SIZE, KM_SLEEP);
842
843 handle->result = kmem_zalloc((sizeof (idmap_get_res)) *
844 INIT_MAPPING_SIZE, KM_SLEEP);
845 handle->mapping_size = INIT_MAPPING_SIZE;
846 handle->zs = zs;
847
848 return (handle);
849 }
850
851 /*
852 * Internal routine to extend a "get_handle"
853 */
854 static void
kidmap_get_extend(idmap_get_handle_t * get_handle)855 kidmap_get_extend(idmap_get_handle_t *get_handle)
856 {
857 idmap_mapping *mapping;
858 idmap_get_res *result;
859 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE;
860
861 mapping = kmem_zalloc((sizeof (idmap_mapping)) *
862 new_size, KM_SLEEP);
863 (void) memcpy(mapping, get_handle->mapping,
864 (sizeof (idmap_mapping)) * get_handle->mapping_size);
865
866 result = kmem_zalloc((sizeof (idmap_get_res)) *
867 new_size, KM_SLEEP);
868 (void) memcpy(result, get_handle->result,
869 (sizeof (idmap_get_res)) * get_handle->mapping_size);
870
871 kmem_free(get_handle->mapping,
872 (sizeof (idmap_mapping)) * get_handle->mapping_size);
873 get_handle->mapping = mapping;
874
875 kmem_free(get_handle->result,
876 (sizeof (idmap_get_res)) * get_handle->mapping_size);
877 get_handle->result = result;
878
879 get_handle->mapping_size = new_size;
880 }
881
882
883 /*
884 * Given Domain SID and RID, get UID
885 *
886 * Input:
887 * sid_prefix - Domain SID in canonical form
888 * rid - RID
889 *
890 * Output:
891 * stat - status of the get request
892 * uid - POSIX UID if stat == IDMAP_SUCCESS
893 *
894 * Notes:
895 * The output parameters will be set by idmap_get_mappings()
896 * The sid_prefix is copied.
897 */
898 idmap_stat
kidmap_batch_getuidbysid(idmap_get_handle_t * get_handle,const char * sid_prefix,uint32_t rid,uid_t * uid,idmap_stat * stat)899 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
900 uint32_t rid, uid_t *uid, idmap_stat *stat)
901 {
902 idmap_mapping *mapping;
903 idmap_get_res *result;
904
905 if (get_handle == NULL || sid_prefix == NULL ||
906 uid == NULL || stat == NULL)
907 return (IDMAP_ERR_ARG);
908
909 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix,
910 rid, uid) == IDMAP_SUCCESS) {
911 *stat = IDMAP_SUCCESS;
912 return (IDMAP_SUCCESS);
913 }
914
915 /* Get a copy of sid_prefix */
916 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
917
918 if (get_handle->mapping_num >= get_handle->mapping_size)
919 kidmap_get_extend(get_handle);
920
921 mapping = &get_handle->mapping[get_handle->mapping_num];
922 mapping->flag = 0;
923 mapping->id1.idtype = IDMAP_SID;
924 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
925 mapping->id1.idmap_id_u.sid.rid = rid;
926 mapping->id2.idtype = IDMAP_UID;
927
928 result = &get_handle->result[get_handle->mapping_num];
929 result->idtype = IDMAP_UID;
930 result->uid = uid;
931 result->gid = NULL;
932 result->pid = NULL;
933 result->sid_prefix = NULL;
934 result->rid = NULL;
935 result->is_user = NULL;
936 result->stat = stat;
937
938 get_handle->mapping_num++;
939
940 return (IDMAP_SUCCESS);
941 }
942
943
944 /*
945 * Given Domain SID and RID, get GID
946 *
947 * Input:
948 * sid_prefix - Domain SID in canonical form
949 * rid - RID
950 *
951 * Output:
952 * stat - status of the get request
953 * gid - POSIX GID if stat == IDMAP_SUCCESS
954 *
955 * Notes:
956 * The output parameters will be set by idmap_get_mappings()
957 * The sid_prefix is copied.
958 */
959 idmap_stat
kidmap_batch_getgidbysid(idmap_get_handle_t * get_handle,const char * sid_prefix,uint32_t rid,uid_t * gid,idmap_stat * stat)960 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
961 uint32_t rid, uid_t *gid, idmap_stat *stat)
962 {
963 idmap_mapping *mapping;
964 idmap_get_res *result;
965
966 if (get_handle == NULL || sid_prefix == NULL ||
967 gid == NULL || stat == NULL)
968 return (IDMAP_ERR_ARG);
969
970 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix,
971 rid, gid) == IDMAP_SUCCESS) {
972 *stat = IDMAP_SUCCESS;
973 return (IDMAP_SUCCESS);
974 }
975
976 /* Get a copy of sid_prefix */
977 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
978
979 if (get_handle->mapping_num >= get_handle->mapping_size)
980 kidmap_get_extend(get_handle);
981
982 mapping = &get_handle->mapping[get_handle->mapping_num];
983 mapping->flag = 0;
984 mapping->id1.idtype = IDMAP_SID;
985 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
986 mapping->id1.idmap_id_u.sid.rid = rid;
987 mapping->id2.idtype = IDMAP_GID;
988
989 result = &get_handle->result[get_handle->mapping_num];
990 result->idtype = IDMAP_GID;
991 result->uid = NULL;
992 result->gid = gid;
993 result->pid = NULL;
994 result->sid_prefix = NULL;
995 result->rid = NULL;
996 result->is_user = NULL;
997 result->stat = stat;
998
999 get_handle->mapping_num++;
1000
1001 return (IDMAP_SUCCESS);
1002 }
1003
1004
1005 /*
1006 * Given Domain SID and RID, get Posix ID
1007 *
1008 * Input:
1009 * sid_prefix - Domain SID in canonical form
1010 * rid - RID
1011 *
1012 * Output:
1013 * stat - status of the get request
1014 * is_user - user or group
1015 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
1016 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
1017 *
1018 * Notes:
1019 * The output parameters will be set by idmap_get_mappings()
1020 * The sid_prefix is copied.
1021 */
1022 idmap_stat
kidmap_batch_getpidbysid(idmap_get_handle_t * get_handle,const char * sid_prefix,uint32_t rid,uid_t * pid,int * is_user,idmap_stat * stat)1023 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
1024 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat)
1025 {
1026 idmap_mapping *mapping;
1027 idmap_get_res *result;
1028
1029 if (get_handle == NULL || sid_prefix == NULL || pid == NULL ||
1030 is_user == NULL || stat == NULL)
1031 return (IDMAP_ERR_ARG);
1032
1033 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix,
1034 rid, pid, is_user) == IDMAP_SUCCESS) {
1035 *stat = IDMAP_SUCCESS;
1036 return (IDMAP_SUCCESS);
1037 }
1038
1039 /* Get a copy of sid_prefix */
1040 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
1041
1042 if (get_handle->mapping_num >= get_handle->mapping_size)
1043 kidmap_get_extend(get_handle);
1044
1045 mapping = &get_handle->mapping[get_handle->mapping_num];
1046 mapping->flag = 0;
1047 mapping->id1.idtype = IDMAP_SID;
1048 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
1049 mapping->id1.idmap_id_u.sid.rid = rid;
1050 mapping->id2.idtype = IDMAP_POSIXID;
1051
1052 result = &get_handle->result[get_handle->mapping_num];
1053 result->idtype = IDMAP_POSIXID;
1054 result->uid = NULL;
1055 result->gid = NULL;
1056 result->pid = pid;
1057 result->sid_prefix = NULL;
1058 result->rid = NULL;
1059 result->is_user = is_user;
1060 result->stat = stat;
1061
1062 get_handle->mapping_num++;
1063
1064 return (IDMAP_SUCCESS);
1065 }
1066
1067
1068 /*
1069 * Given UID, get SID and RID
1070 *
1071 * Input:
1072 * uid - POSIX UID
1073 *
1074 * Output:
1075 * stat - status of the get request
1076 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1077 * rid - RID (if stat == IDMAP_SUCCESS)
1078 *
1079 * Note: The output parameters will be set by idmap_get_mappings()
1080 */
1081 idmap_stat
kidmap_batch_getsidbyuid(idmap_get_handle_t * get_handle,uid_t uid,const char ** sid_prefix,uint32_t * rid,idmap_stat * stat)1082 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
1083 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1084 {
1085 idmap_mapping *mapping;
1086 idmap_get_res *result;
1087
1088 if (get_handle == NULL || sid_prefix == NULL ||
1089 rid == NULL || stat == NULL)
1090 return (IDMAP_ERR_ARG);
1091
1092 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache,
1093 sid_prefix, rid, uid) == IDMAP_SUCCESS) {
1094 *stat = IDMAP_SUCCESS;
1095 return (IDMAP_SUCCESS);
1096 }
1097
1098 if (get_handle->mapping_num >= get_handle->mapping_size)
1099 kidmap_get_extend(get_handle);
1100
1101 mapping = &get_handle->mapping[get_handle->mapping_num];
1102 mapping->flag = 0;
1103 mapping->id1.idtype = IDMAP_UID;
1104 mapping->id1.idmap_id_u.uid = uid;
1105 mapping->id2.idtype = IDMAP_SID;
1106
1107 result = &get_handle->result[get_handle->mapping_num];
1108 result->idtype = IDMAP_SID;
1109 result->uid = NULL;
1110 result->gid = NULL;
1111 result->pid = NULL;
1112 result->sid_prefix = sid_prefix;
1113 result->rid = rid;
1114 result->is_user = NULL;
1115 result->stat = stat;
1116
1117 get_handle->mapping_num++;
1118
1119 return (IDMAP_SUCCESS);
1120 }
1121
1122
1123 /*
1124 * Given GID, get SID and RID
1125 *
1126 * Input:
1127 * gid - POSIX GID
1128 *
1129 * Output:
1130 * stat - status of the get request
1131 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1132 * rid - RID (if stat == IDMAP_SUCCESS)
1133 *
1134 * Note: The output parameters will be set by idmap_get_mappings()
1135 */
1136 idmap_stat
kidmap_batch_getsidbygid(idmap_get_handle_t * get_handle,gid_t gid,const char ** sid_prefix,uint32_t * rid,idmap_stat * stat)1137 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
1138 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1139 {
1140 idmap_mapping *mapping;
1141 idmap_get_res *result;
1142
1143 if (get_handle == NULL || sid_prefix == NULL ||
1144 rid == NULL || stat == NULL)
1145 return (IDMAP_ERR_ARG);
1146
1147 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache,
1148 sid_prefix, rid, gid) == IDMAP_SUCCESS) {
1149 *stat = IDMAP_SUCCESS;
1150 return (IDMAP_SUCCESS);
1151 }
1152
1153 if (get_handle->mapping_num >= get_handle->mapping_size)
1154 kidmap_get_extend(get_handle);
1155
1156 mapping = &get_handle->mapping[get_handle->mapping_num];
1157 mapping->flag = 0;
1158 mapping->id1.idtype = IDMAP_GID;
1159 mapping->id1.idmap_id_u.gid = gid;
1160 mapping->id2.idtype = IDMAP_SID;
1161
1162 result = &get_handle->result[get_handle->mapping_num];
1163 result->idtype = IDMAP_SID;
1164 result->uid = NULL;
1165 result->gid = NULL;
1166 result->pid = NULL;
1167 result->sid_prefix = sid_prefix;
1168 result->rid = rid;
1169 result->is_user = NULL;
1170 result->stat = stat;
1171
1172 get_handle->mapping_num++;
1173
1174 return (IDMAP_SUCCESS);
1175 }
1176
1177
1178 /*
1179 * Process the batched "get mapping" requests. The results (i.e.
1180 * status and identity) will be available in the data areas
1181 * provided by individual requests.
1182 *
1183 * If the door call fails the status IDMAP_ERR_NOMAPPING is
1184 * return and the UID or UID result is set to "nobody"
1185 */
1186
1187 idmap_stat
kidmap_get_mappings(idmap_get_handle_t * get_handle)1188 kidmap_get_mappings(idmap_get_handle_t *get_handle)
1189 {
1190 idmap_mapping_batch rpc_args;
1191 idmap_ids_res rpc_res;
1192 uint32_t op = IDMAP_GET_MAPPED_IDS;
1193 idmap_mapping *request;
1194 idmap_get_res *result;
1195 idmap_id *id;
1196 int status;
1197 int i;
1198 const char *sid_prefix;
1199 int is_user;
1200 idmap_cache_t *cache;
1201 int direction;
1202
1203 if (get_handle == NULL)
1204 return (IDMAP_ERR_ARG);
1205
1206 if (get_handle->mapping_num == 0)
1207 return (IDMAP_SUCCESS);
1208 cache = &get_handle->zs->cache;
1209
1210 bzero(&rpc_res, sizeof (idmap_ids_res));
1211
1212 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num;
1213 rpc_args.idmap_mapping_batch_val = get_handle->mapping;
1214
1215 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch,
1216 (caddr_t)&rpc_args, xdr_idmap_ids_res,
1217 (caddr_t)&rpc_res) != 0) {
1218 /* Door call failed */
1219 status = IDMAP_ERR_NOMAPPING;
1220 goto error;
1221 }
1222
1223 status = rpc_res.retcode;
1224 if (status != IDMAP_SUCCESS) {
1225 /* RPC returned idmap error code */
1226 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1227 goto error;
1228 }
1229
1230 for (i = 0; i < get_handle->mapping_num; i++) {
1231 request = &get_handle->mapping[i];
1232 result = &get_handle->result[i];
1233
1234 if (i >= rpc_res.ids.ids_len) {
1235 *result->stat = IDMAP_ERR_NOMAPPING;
1236 if (result->uid)
1237 *result->uid = UID_NOBODY;
1238 if (result->gid)
1239 *result->gid = GID_NOBODY;
1240 if (result->pid)
1241 *result->pid = UID_NOBODY;
1242 if (result->is_user)
1243 *result->is_user = 1;
1244 if (result->sid_prefix)
1245 *result->sid_prefix = NULL;
1246 if (result->rid)
1247 *result->rid = 0;
1248 continue;
1249 }
1250
1251 *result->stat = rpc_res.ids.ids_val[i].retcode;
1252
1253 id = &rpc_res.ids.ids_val[i].id;
1254 direction = rpc_res.ids.ids_val[i].direction;
1255
1256 switch (id->idtype) {
1257 case IDMAP_UID:
1258 if (result->uid)
1259 *result->uid = id->idmap_id_u.uid;
1260 if (result->pid)
1261 *result->pid = id->idmap_id_u.uid;
1262 if (result->is_user)
1263 *result->is_user = 1;
1264 sid_prefix = kidmap_find_sid_prefix(
1265 request->id1.idmap_id_u.sid.prefix);
1266 if (*result->stat == IDMAP_SUCCESS && result->uid)
1267 kidmap_cache_add_sid2uid(
1268 cache, sid_prefix,
1269 request->id1.idmap_id_u.sid.rid,
1270 id->idmap_id_u.uid,
1271 direction);
1272 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1273 kidmap_cache_add_sid2pid(
1274 cache, sid_prefix,
1275 request->id1.idmap_id_u.sid.rid,
1276 id->idmap_id_u.uid, 1,
1277 direction);
1278 break;
1279
1280 case IDMAP_GID:
1281 if (result->gid)
1282 *result->gid = id->idmap_id_u.gid;
1283 if (result->pid)
1284 *result->pid = id->idmap_id_u.gid;
1285 if (result->is_user)
1286 *result->is_user = 0;
1287 sid_prefix = kidmap_find_sid_prefix(
1288 request->id1.idmap_id_u.sid.prefix);
1289 if (*result->stat == IDMAP_SUCCESS && result->gid)
1290 kidmap_cache_add_sid2gid(
1291 cache, sid_prefix,
1292 request->id1.idmap_id_u.sid.rid,
1293 id->idmap_id_u.gid,
1294 direction);
1295 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1296 kidmap_cache_add_sid2pid(
1297 cache, sid_prefix,
1298 request->id1.idmap_id_u.sid.rid,
1299 id->idmap_id_u.gid, 0,
1300 direction);
1301 break;
1302
1303 case IDMAP_SID:
1304 case IDMAP_USID:
1305 case IDMAP_GSID:
1306 sid_prefix = kidmap_find_sid_prefix(
1307 id->idmap_id_u.sid.prefix);
1308 if (result->sid_prefix && result->rid) {
1309 *result->sid_prefix = sid_prefix;
1310 *result->rid = id->idmap_id_u.sid.rid;
1311 }
1312 if (*result->stat == IDMAP_ERR_NOTFOUND &&
1313 sid_prefix != NULL) {
1314 /* IDMAP generated a local SID. Use it. */
1315 *result->stat = IDMAP_SUCCESS;
1316 }
1317
1318 if (*result->stat == IDMAP_SUCCESS &&
1319 request->id1.idtype == IDMAP_UID)
1320 kidmap_cache_add_sid2uid(
1321 cache, sid_prefix,
1322 id->idmap_id_u.sid.rid,
1323 request->id1.idmap_id_u.uid,
1324 direction);
1325 else if (*result->stat == IDMAP_SUCCESS &&
1326 request->id1.idtype == IDMAP_GID)
1327 kidmap_cache_add_sid2gid(
1328 cache, sid_prefix,
1329 id->idmap_id_u.sid.rid,
1330 request->id1.idmap_id_u.gid,
1331 direction);
1332 break;
1333
1334 default:
1335 *result->stat = IDMAP_ERR_NORESULT;
1336 if (result->uid)
1337 *result->uid = UID_NOBODY;
1338 if (result->gid)
1339 *result->gid = GID_NOBODY;
1340 if (result->pid)
1341 *result->pid = UID_NOBODY;
1342 if (result->is_user)
1343 *result->is_user = 1;
1344 if (result->sid_prefix)
1345 *result->sid_prefix = NULL;
1346 if (result->rid)
1347 *result->rid = 0;
1348 break;
1349 }
1350 }
1351 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1352
1353 /* Reset get_handle for new resquests */
1354 get_handle->mapping_num = 0;
1355 return (status);
1356
1357 error:
1358 for (i = 0; i < get_handle->mapping_num; i++) {
1359 result = &get_handle->result[i];
1360
1361 *result->stat = status;
1362 if (result->uid)
1363 *result->uid = UID_NOBODY;
1364 if (result->gid)
1365 *result->gid = GID_NOBODY;
1366 if (result->pid)
1367 *result->pid = UID_NOBODY;
1368 if (result->is_user)
1369 *result->is_user = 1;
1370 if (result->sid_prefix)
1371 *result->sid_prefix = NULL;
1372 if (result->rid)
1373 *result->rid = 0;
1374 }
1375
1376 /* Reset get_handle for new resquests */
1377 get_handle->mapping_num = 0;
1378 return (status);
1379 }
1380
1381
1382 /*
1383 * Destroy the "get mapping" handle
1384 */
1385 void
kidmap_get_destroy(idmap_get_handle_t * get_handle)1386 kidmap_get_destroy(idmap_get_handle_t *get_handle)
1387 {
1388 if (get_handle == NULL)
1389 return;
1390
1391 kmem_free(get_handle->mapping,
1392 (sizeof (idmap_mapping)) * get_handle->mapping_size);
1393 get_handle->mapping = NULL;
1394
1395 kmem_free(get_handle->result,
1396 (sizeof (idmap_get_res)) * get_handle->mapping_size);
1397 get_handle->result = NULL;
1398
1399 kmem_free(get_handle, sizeof (idmap_get_handle_t));
1400 }
1401
1402
1403 static int
kidmap_rpc_call(idmap_zone_specific_t * zs,uint32_t op,xdrproc_t xdr_args,caddr_t args,xdrproc_t xdr_res,caddr_t res)1404 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args,
1405 caddr_t args, xdrproc_t xdr_res, caddr_t res)
1406 {
1407 XDR xdr_ctx;
1408 struct rpc_msg reply_msg;
1409 char *inbuf_ptr = NULL;
1410 size_t inbuf_size = 4096;
1411 char *outbuf_ptr = NULL;
1412 size_t outbuf_size = 4096;
1413 size_t size;
1414 int status = 0;
1415 door_arg_t params;
1416 int retry = 0;
1417 struct rpc_msg call_msg;
1418
1419 params.rbuf = NULL;
1420 params.rsize = 0;
1421
1422 retry:
1423 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP);
1424 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP);
1425
1426 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE);
1427
1428 call_msg.rm_call.cb_prog = IDMAP_PROG;
1429 call_msg.rm_call.cb_vers = IDMAP_V1;
1430 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id);
1431
1432 if (!xdr_callhdr(&xdr_ctx, &call_msg)) {
1433 #ifdef DEBUG
1434 zcmn_err(zs->zone_id, CE_WARN,
1435 "idmap: xdr encoding header error");
1436 #endif /* DEBUG */
1437 status = -1;
1438 goto exit;
1439 }
1440
1441 if (!xdr_uint32(&xdr_ctx, &op) ||
1442 /* Auth none */
1443 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1444 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1445 /* RPC args */
1446 !xdr_args(&xdr_ctx, args)) {
1447 #ifdef DEBUG
1448 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error");
1449 #endif /* DEBUG */
1450 if (retry > 2) {
1451 status = -1;
1452 goto exit;
1453 }
1454 retry++;
1455 if (inbuf_ptr) {
1456 kmem_free(inbuf_ptr, inbuf_size);
1457 inbuf_ptr = NULL;
1458 }
1459 if (outbuf_ptr) {
1460 kmem_free(outbuf_ptr, outbuf_size);
1461 outbuf_ptr = NULL;
1462 }
1463 if ((size = xdr_sizeof(xdr_args, args)) == 0) {
1464 #ifdef DEBUG
1465 zcmn_err(zs->zone_id, CE_WARN,
1466 "idmap: xdr_sizeof error");
1467 #endif /* DEBUG */
1468 status = -1;
1469 goto exit;
1470 }
1471 inbuf_size = size + 1024;
1472 outbuf_size = size + 1024;
1473 goto retry;
1474 }
1475
1476 params.data_ptr = inbuf_ptr;
1477 params.data_size = XDR_GETPOS(&xdr_ctx);
1478 params.desc_ptr = NULL;
1479 params.desc_num = 0;
1480 params.rbuf = outbuf_ptr;
1481 params.rsize = outbuf_size;
1482
1483 if (kidmap_call_door(zs, ¶ms) != 0) {
1484 status = -1;
1485 goto exit;
1486 }
1487
1488 reply_msg.acpted_rply.ar_verf = _null_auth;
1489 reply_msg.acpted_rply.ar_results.where = res;
1490 reply_msg.acpted_rply.ar_results.proc = xdr_res;
1491 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE);
1492 if (xdr_replymsg(&xdr_ctx, &reply_msg)) {
1493 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED ||
1494 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
1495 status = -1;
1496 goto exit;
1497 }
1498 } else {
1499 #ifdef DEBUG
1500 zcmn_err(zs->zone_id, CE_WARN,
1501 "idmap: xdr decoding reply message error");
1502 #endif /* DEBUG */
1503 status = -1;
1504 }
1505
1506 exit:
1507 if (outbuf_ptr != params.rbuf && params.rbuf != NULL)
1508 kmem_free(params.rbuf, params.rsize);
1509 if (inbuf_ptr)
1510 kmem_free(inbuf_ptr, inbuf_size);
1511 if (outbuf_ptr)
1512 kmem_free(outbuf_ptr, outbuf_size);
1513 return (status);
1514 }
1515