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