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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Windows to Solaris Identity Mapping kernel API
29 * This module provides an API to map Windows SIDs to
30 * Solaris UID and GIDs.
34 #include <sys/types.h>
35 #include <sys/ksynch.h>
37 #include <rpc/rpc_msg.h>
40 #include <rpc/rpc_sztypes.h>
42 #include <sys/cmn_err.h>
45 #include <sys/sunddi.h>
46 #include <sys/param.h>
47 #include <sys/atomic.h>
48 #include <sys/sysmacros.h>
50 #include <sys/kidmap.h>
52 #include <rpcsvc/idmap_prot.h>
53 #include "kidmap_priv.h"
62 * This structure holds pointers for the
63 * batch mapping results.
65 typedef struct idmap_get_res
{
71 const char **sid_prefix
;
76 /* Batch mapping handle structure */
77 struct idmap_get_handle
{
78 struct idmap_zone_specific
*zs
;
81 idmap_mapping
*mapping
;
82 idmap_get_res
*result
;
86 /* Zone specific data */
87 typedef struct idmap_zone_specific
{
91 door_handle_t door_handle
;
95 } idmap_zone_specific_t
;
103 static kmutex_t idmap_zone_mutex
;
104 static zone_key_t idmap_zone_key
;
108 * Local function definitions
113 kidmap_rpc_call(idmap_zone_specific_t
*zs
, uint32_t op
,
114 xdrproc_t xdr_args
, caddr_t args
, xdrproc_t xdr_res
, caddr_t res
);
117 kidmap_call_door(idmap_zone_specific_t
*zs
, door_arg_t
*arg
);
119 static idmap_zone_specific_t
*
120 idmap_get_zone_specific(zone_t
*zone
);
125 idmap_reg_dh(zone_t
*zone
, door_handle_t dh
)
127 idmap_zone_specific_t
*zs
;
129 zs
= idmap_get_zone_specific(zone
);
131 mutex_enter(&zs
->zone_mutex
);
134 door_ki_rele(zs
->door_handle
);
136 zs
->door_handle
= dh
;
139 mutex_exit(&zs
->zone_mutex
);
147 * This routine is called by system call idmap_unreg().
148 * idmap_unreg() calls door_ki_rele() on the supplied
149 * door handle after this routine returns. We only
150 * need to perform one door release on zs->door_handle
153 idmap_unreg_dh(zone_t
*zone
, door_handle_t dh
)
155 idmap_zone_specific_t
*zs
;
157 zs
= idmap_get_zone_specific(zone
);
159 kidmap_cache_purge(&zs
->cache
);
161 mutex_enter(&zs
->zone_mutex
);
163 if (!zs
->door_valid
|| zs
->door_handle
!= dh
) {
164 mutex_exit(&zs
->zone_mutex
);
168 door_ki_rele(zs
->door_handle
);
171 zs
->door_retried
= 0;
172 mutex_exit(&zs
->zone_mutex
);
179 * IMPORTANT. This function idmap_get_cache_data() is project
180 * private and is for use of the test system only and should
181 * not be used for other purposes.
184 idmap_get_cache_data(zone_t
*zone
, size_t *uidbysid
, size_t *gidbysid
,
185 size_t *pidbysid
, size_t *sidbyuid
, size_t *sidbygid
)
187 idmap_zone_specific_t
*zs
;
189 zs
= idmap_get_zone_specific(zone
);
191 kidmap_cache_get_data(&zs
->cache
, uidbysid
, gidbysid
,
192 pidbysid
, sidbyuid
, sidbygid
);
196 kidmap_call_door(idmap_zone_specific_t
*zs
, door_arg_t
*arg
)
202 int door_retried
= 0;
205 mutex_enter(&zs
->zone_mutex
);
206 if (zs
->door_valid
) {
207 dh
= zs
->door_handle
;
211 door_retried
= zs
->door_retried
;
213 mutex_exit(&zs
->zone_mutex
);
216 /* The door has been retried before so dont wait */
221 * There is no door handle yet. Give
222 * smf a chance to restart idmapd
224 if (num_retries
-- > 0) {
230 zcmn_err(zs
->zone_id
, CE_WARN
,
231 "idmap: Error no registered door to call the "
234 mutex_enter(&zs
->zone_mutex
);
236 zs
->door_retried
= 1;
237 mutex_exit(&zs
->zone_mutex
);
242 status
= door_ki_upcall_limited(dh
, arg
, NULL
, SIZE_MAX
, 0);
245 case 0: /* Success */
250 /* If we took an interrupt we have to bail out. */
251 if (ttolwp(curthread
) && ISSIG(curthread
, JUSTLOOKING
)) {
254 zcmn_err(zs
->zone_id
, CE_WARN
,
255 "idmap: Interrupted\n");
260 * Just retry and see what happens.
265 /* A resouce problem */
267 /* Back off before retrying */
269 zcmn_err(zs
->zone_id
, CE_WARN
,
270 "idmap: Door call returned error %d. Retrying\n", status
);
276 /* Stale door handle. See if smf restarts the daemon. */
278 mutex_enter(&zs
->zone_mutex
);
279 if (zs
->door_valid
&& dh
== zs
->door_handle
) {
281 zs
->door_retried
= 0;
282 door_ki_rele(zs
->door_handle
);
284 mutex_exit(&zs
->zone_mutex
);
285 /* Back off before retrying */
287 zcmn_err(zs
->zone_id
, CE_WARN
,
288 "idmap: Door call returned error %d. Retrying\n", status
);
296 zcmn_err(zs
->zone_id
, CE_WARN
,
297 "idmap: Door call returned error %d.\n", status
);
305 static idmap_zone_specific_t
*
306 idmap_get_zone_specific(zone_t
*zone
)
308 idmap_zone_specific_t
*zs
;
310 ASSERT(zone
!= NULL
);
312 zs
= zone_getspecific(idmap_zone_key
, zone
);
316 mutex_enter(&idmap_zone_mutex
);
317 zs
= zone_getspecific(idmap_zone_key
, zone
);
319 zs
= kmem_zalloc(sizeof (idmap_zone_specific_t
), KM_SLEEP
);
320 mutex_init(&zs
->zone_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
321 kidmap_cache_create(&zs
->cache
);
322 zs
->zone_id
= zone
->zone_id
;
323 (void) zone_setspecific(idmap_zone_key
, zone
, zs
);
324 mutex_exit(&idmap_zone_mutex
);
327 mutex_exit(&idmap_zone_mutex
);
335 idmap_zone_destroy(zoneid_t zone_id
, void *arg
)
337 idmap_zone_specific_t
*zs
= arg
;
339 kidmap_cache_delete(&zs
->cache
);
340 if (zs
->door_valid
) {
341 door_ki_rele(zs
->door_handle
);
343 mutex_destroy(&zs
->zone_mutex
);
344 kmem_free(zs
, sizeof (idmap_zone_specific_t
));
352 mutex_init(&idmap_zone_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
353 zone_key_create(&idmap_zone_key
, NULL
, NULL
, idmap_zone_destroy
);
354 kidmap_sid_prefix_store_init();
370 * This is called by the system call allocids() to get the door for the
374 idmap_get_door(zone_t
*zone
)
376 door_handle_t dh
= NULL
;
377 idmap_zone_specific_t
*zs
;
379 zs
= idmap_get_zone_specific(zone
);
381 mutex_enter(&zs
->zone_mutex
);
382 if (zs
->door_valid
) {
383 dh
= zs
->door_handle
;
386 mutex_exit(&zs
->zone_mutex
);
394 * This is called by the system call allocids() to purge the cache for the
398 idmap_purge_cache(zone_t
*zone
)
400 idmap_zone_specific_t
*zs
;
402 zs
= idmap_get_zone_specific(zone
);
404 kidmap_cache_purge(&zs
->cache
);
411 * Given Domain SID and RID, get UID
414 * sid_prefix - Domain SID in canonical form
418 * uid - POSIX UID if return == IDMAP_SUCCESS
421 * Success return IDMAP_SUCCESS else IDMAP error
424 kidmap_getuidbysid(zone_t
*zone
, const char *sid_prefix
, uint32_t rid
,
427 idmap_zone_specific_t
*zs
;
428 idmap_mapping_batch args
;
429 idmap_mapping mapping
;
430 idmap_ids_res results
;
431 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
432 const char *new_sid_prefix
;
435 if (sid_prefix
== NULL
|| uid
== NULL
)
436 return (IDMAP_ERR_ARG
);
438 zs
= idmap_get_zone_specific(zone
);
440 if (kidmap_cache_lookup_uidbysid(&zs
->cache
, sid_prefix
, rid
, uid
)
442 return (IDMAP_SUCCESS
);
444 bzero(&mapping
, sizeof (idmap_mapping
));
445 mapping
.id1
.idtype
= IDMAP_SID
;
446 mapping
.id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
447 mapping
.id1
.idmap_id_u
.sid
.rid
= rid
;
448 mapping
.id2
.idtype
= IDMAP_UID
;
450 bzero(&results
, sizeof (idmap_ids_res
));
452 args
.idmap_mapping_batch_len
= 1;
453 args
.idmap_mapping_batch_val
= &mapping
;
455 if (kidmap_rpc_call(zs
, op
, xdr_idmap_mapping_batch
,
456 (caddr_t
)&args
, xdr_idmap_ids_res
,
457 (caddr_t
)&results
) == 0) {
458 /* Door call succeded */
459 if (results
.retcode
!= IDMAP_SUCCESS
) {
460 status
= results
.retcode
;
462 } else if (results
.ids
.ids_len
>= 1 &&
463 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_UID
) {
464 status
= results
.ids
.ids_val
[0].retcode
;
465 *uid
= results
.ids
.ids_val
[0].id
.idmap_id_u
.uid
;
466 if (status
== IDMAP_SUCCESS
) {
467 new_sid_prefix
= kidmap_find_sid_prefix(
469 kidmap_cache_add_sid2uid(&zs
->cache
,
470 new_sid_prefix
, rid
, *uid
,
471 results
.ids
.ids_val
[0].direction
);
474 status
= IDMAP_ERR_NOMAPPING
;
477 xdr_free(xdr_idmap_ids_res
, (char *)&results
);
479 /* Door call failed */
480 status
= IDMAP_ERR_NOMAPPING
;
488 * Given Domain SID and RID, get GID
491 * sid_prefix - Domain SID in canonical form
495 * gid - POSIX UID if return == IDMAP_SUCCESS
498 * Success return IDMAP_SUCCESS else IDMAP error
501 kidmap_getgidbysid(zone_t
*zone
, const char *sid_prefix
, uint32_t rid
,
504 idmap_zone_specific_t
*zs
;
505 idmap_mapping_batch args
;
506 idmap_mapping mapping
;
507 idmap_ids_res results
;
508 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
509 const char *new_sid_prefix
;
512 if (sid_prefix
== NULL
|| gid
== NULL
)
513 return (IDMAP_ERR_ARG
);
515 zs
= idmap_get_zone_specific(zone
);
517 if (kidmap_cache_lookup_gidbysid(&zs
->cache
, sid_prefix
, rid
, gid
)
519 return (IDMAP_SUCCESS
);
521 bzero(&mapping
, sizeof (idmap_mapping
));
522 mapping
.id1
.idtype
= IDMAP_SID
;
523 mapping
.id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
524 mapping
.id1
.idmap_id_u
.sid
.rid
= rid
;
525 mapping
.id2
.idtype
= IDMAP_GID
;
527 bzero(&results
, sizeof (idmap_ids_res
));
529 args
.idmap_mapping_batch_len
= 1;
530 args
.idmap_mapping_batch_val
= &mapping
;
532 if (kidmap_rpc_call(zs
, op
, xdr_idmap_mapping_batch
,
533 (caddr_t
)&args
, xdr_idmap_ids_res
,
534 (caddr_t
)&results
) == 0) {
535 /* Door call succeded */
536 if (results
.retcode
!= IDMAP_SUCCESS
) {
537 status
= results
.retcode
;
539 } else if (results
.ids
.ids_len
>= 1 &&
540 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_GID
) {
541 status
= results
.ids
.ids_val
[0].retcode
;
542 *gid
= results
.ids
.ids_val
[0].id
.idmap_id_u
.gid
;
543 if (status
== IDMAP_SUCCESS
) {
544 new_sid_prefix
= kidmap_find_sid_prefix(
546 kidmap_cache_add_sid2gid(&zs
->cache
,
547 new_sid_prefix
, rid
, *gid
,
548 results
.ids
.ids_val
[0].direction
);
551 status
= IDMAP_ERR_NOMAPPING
;
554 xdr_free(xdr_idmap_ids_res
, (char *)&results
);
556 /* Door call failed */
557 status
= IDMAP_ERR_NOMAPPING
;
564 * Given Domain SID and RID, get Posix ID
567 * sid_prefix - Domain SID in canonical form
571 * pid - POSIX ID if return == IDMAP_SUCCESS
572 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS
575 * Success return IDMAP_SUCCESS else IDMAP error
578 kidmap_getpidbysid(zone_t
*zone
, const char *sid_prefix
, uint32_t rid
,
579 uid_t
*pid
, int *is_user
)
581 idmap_zone_specific_t
*zs
;
582 idmap_mapping_batch args
;
583 idmap_mapping mapping
;
584 idmap_ids_res results
;
585 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
586 const char *new_sid_prefix
;
589 if (sid_prefix
== NULL
|| pid
== NULL
|| is_user
== NULL
)
590 return (IDMAP_ERR_ARG
);
592 zs
= idmap_get_zone_specific(zone
);
594 if (kidmap_cache_lookup_pidbysid(&zs
->cache
, sid_prefix
, rid
, pid
,
595 is_user
) == IDMAP_SUCCESS
)
596 return (IDMAP_SUCCESS
);
598 bzero(&mapping
, sizeof (idmap_mapping
));
599 mapping
.id1
.idtype
= IDMAP_SID
;
600 mapping
.id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
601 mapping
.id1
.idmap_id_u
.sid
.rid
= rid
;
602 mapping
.id2
.idtype
= IDMAP_POSIXID
;
604 bzero(&results
, sizeof (idmap_ids_res
));
606 args
.idmap_mapping_batch_len
= 1;
607 args
.idmap_mapping_batch_val
= &mapping
;
609 if (kidmap_rpc_call(zs
, op
, xdr_idmap_mapping_batch
,
610 (caddr_t
)&args
, xdr_idmap_ids_res
,
611 (caddr_t
)&results
) == 0) {
612 /* Door call succeded */
613 if (results
.retcode
!= IDMAP_SUCCESS
) {
614 status
= results
.retcode
;
617 } else if (results
.ids
.ids_len
>= 1 && (
618 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_UID
||
619 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_GID
)) {
620 status
= results
.ids
.ids_val
[0].retcode
;
621 if (results
.ids
.ids_val
[0].id
.idtype
== IDMAP_UID
) {
623 *pid
= results
.ids
.ids_val
[0].id
.idmap_id_u
.uid
;
626 *pid
= results
.ids
.ids_val
[0].id
.idmap_id_u
.gid
;
628 if (status
== IDMAP_SUCCESS
) {
629 new_sid_prefix
= kidmap_find_sid_prefix(
631 kidmap_cache_add_sid2pid(&zs
->cache
,
632 new_sid_prefix
, rid
, *pid
,
634 results
.ids
.ids_val
[0].direction
);
637 status
= IDMAP_ERR_NOMAPPING
;
641 xdr_free(xdr_idmap_ids_res
, (char *)&results
);
643 /* Door call failed */
644 status
= IDMAP_ERR_NOMAPPING
;
653 * Given UID, get Domain SID and RID
659 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
660 * rid - RID if return == IDMAP_SUCCESS
663 * Success return IDMAP_SUCCESS else IDMAP error
666 kidmap_getsidbyuid(zone_t
*zone
, uid_t uid
, const char **sid_prefix
,
669 idmap_zone_specific_t
*zs
;
670 idmap_mapping_batch args
;
671 idmap_mapping mapping
;
672 idmap_ids_res results
;
673 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
678 if (sid_prefix
== NULL
|| rid
== NULL
)
679 return (IDMAP_ERR_ARG
);
681 zs
= idmap_get_zone_specific(zone
);
683 if (kidmap_cache_lookup_sidbyuid(&zs
->cache
, sid_prefix
, rid
, uid
)
685 return (IDMAP_SUCCESS
);
688 bzero(&mapping
, sizeof (idmap_mapping
));
689 mapping
.id1
.idtype
= IDMAP_UID
;
690 mapping
.id1
.idmap_id_u
.uid
= uid
;
691 mapping
.id2
.idtype
= IDMAP_SID
;
693 bzero(&results
, sizeof (idmap_ids_res
));
695 args
.idmap_mapping_batch_len
= 1;
696 args
.idmap_mapping_batch_val
= &mapping
;
698 if (kidmap_rpc_call(zs
, op
, xdr_idmap_mapping_batch
,
699 (caddr_t
)&args
, xdr_idmap_ids_res
,
700 (caddr_t
)&results
) == 0) {
701 /* Door call succeded */
702 if (results
.retcode
!= IDMAP_SUCCESS
) {
703 status
= results
.retcode
;
706 } else if (results
.ids
.ids_len
>= 1 &&
707 (results
.ids
.ids_val
[0].id
.idtype
== IDMAP_SID
||
708 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_USID
||
709 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_GSID
)) {
710 status
= results
.ids
.ids_val
[0].retcode
;
711 id
= &results
.ids
.ids_val
[0].id
;
712 *sid_prefix
= kidmap_find_sid_prefix(
713 id
->idmap_id_u
.sid
.prefix
);
714 *rid
= id
->idmap_id_u
.sid
.rid
;
715 if (status
== IDMAP_SUCCESS
) {
716 kidmap_cache_add_sid2uid(&zs
->cache
,
717 *sid_prefix
, *rid
, uid
,
718 results
.ids
.ids_val
[0].direction
);
721 status
= IDMAP_ERR_NOMAPPING
;
725 xdr_free(xdr_idmap_ids_res
, (char *)&results
);
727 /* Door call failed */
728 status
= IDMAP_ERR_NOMAPPING
;
737 * Given GID, get Domain SID and RID
743 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
744 * rid - RID if return == IDMAP_SUCCESS
747 * Success return IDMAP_SUCCESS else IDMAP error
750 kidmap_getsidbygid(zone_t
*zone
, gid_t gid
, const char **sid_prefix
,
753 idmap_zone_specific_t
*zs
;
754 idmap_mapping_batch args
;
755 idmap_mapping mapping
;
756 idmap_ids_res results
;
757 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
761 if (sid_prefix
== NULL
|| rid
== NULL
)
762 return (IDMAP_ERR_ARG
);
764 zs
= idmap_get_zone_specific(zone
);
766 if (kidmap_cache_lookup_sidbygid(&zs
->cache
, sid_prefix
, rid
, gid
)
768 return (IDMAP_SUCCESS
);
771 bzero(&mapping
, sizeof (idmap_mapping
));
772 mapping
.id1
.idtype
= IDMAP_GID
;
773 mapping
.id1
.idmap_id_u
.uid
= gid
;
774 mapping
.id2
.idtype
= IDMAP_SID
;
776 bzero(&results
, sizeof (idmap_ids_res
));
778 args
.idmap_mapping_batch_len
= 1;
779 args
.idmap_mapping_batch_val
= &mapping
;
781 if (kidmap_rpc_call(zs
, op
, xdr_idmap_mapping_batch
,
782 (caddr_t
)&args
, xdr_idmap_ids_res
,
783 (caddr_t
)&results
) == 0) {
784 /* Door call succeded */
785 if (results
.retcode
!= IDMAP_SUCCESS
) {
786 status
= results
.retcode
;
789 } else if (results
.ids
.ids_len
>= 1 &&
790 (results
.ids
.ids_val
[0].id
.idtype
== IDMAP_SID
||
791 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_USID
||
792 results
.ids
.ids_val
[0].id
.idtype
== IDMAP_GSID
)) {
793 status
= results
.ids
.ids_val
[0].retcode
;
794 id
= &results
.ids
.ids_val
[0].id
;
795 *sid_prefix
= kidmap_find_sid_prefix(
796 id
->idmap_id_u
.sid
.prefix
);
797 *rid
= id
->idmap_id_u
.sid
.rid
;
798 if (status
== IDMAP_SUCCESS
) {
799 kidmap_cache_add_sid2gid(&zs
->cache
,
800 *sid_prefix
, *rid
, gid
,
801 results
.ids
.ids_val
[0].direction
);
804 status
= IDMAP_ERR_NOMAPPING
;
808 xdr_free(xdr_idmap_ids_res
, (char *)&results
);
810 /* Door call failed */
811 status
= IDMAP_ERR_NOMAPPING
;
819 * Create handle to get SID to UID/GID mapping entries
828 kidmap_get_create(zone_t
*zone
)
830 idmap_zone_specific_t
*zs
;
831 idmap_get_handle_t
*handle
;
832 #define INIT_MAPPING_SIZE 32
834 zs
= idmap_get_zone_specific(zone
);
836 handle
= kmem_zalloc(sizeof (idmap_get_handle_t
), KM_SLEEP
);
838 handle
->mapping
= kmem_zalloc((sizeof (idmap_mapping
)) *
839 INIT_MAPPING_SIZE
, KM_SLEEP
);
841 handle
->result
= kmem_zalloc((sizeof (idmap_get_res
)) *
842 INIT_MAPPING_SIZE
, KM_SLEEP
);
843 handle
->mapping_size
= INIT_MAPPING_SIZE
;
850 * Internal routine to extend a "get_handle"
853 kidmap_get_extend(idmap_get_handle_t
*get_handle
)
855 idmap_mapping
*mapping
;
856 idmap_get_res
*result
;
857 int new_size
= get_handle
->mapping_size
+ INIT_MAPPING_SIZE
;
859 mapping
= kmem_zalloc((sizeof (idmap_mapping
)) *
861 (void) memcpy(mapping
, get_handle
->mapping
,
862 (sizeof (idmap_mapping
)) * get_handle
->mapping_size
);
864 result
= kmem_zalloc((sizeof (idmap_get_res
)) *
866 (void) memcpy(result
, get_handle
->result
,
867 (sizeof (idmap_get_res
)) * get_handle
->mapping_size
);
869 kmem_free(get_handle
->mapping
,
870 (sizeof (idmap_mapping
)) * get_handle
->mapping_size
);
871 get_handle
->mapping
= mapping
;
873 kmem_free(get_handle
->result
,
874 (sizeof (idmap_get_res
)) * get_handle
->mapping_size
);
875 get_handle
->result
= result
;
877 get_handle
->mapping_size
= new_size
;
882 * Given Domain SID and RID, get UID
885 * sid_prefix - Domain SID in canonical form
889 * stat - status of the get request
890 * uid - POSIX UID if stat == IDMAP_SUCCESS
893 * The output parameters will be set by idmap_get_mappings()
894 * The sid_prefix is copied.
897 kidmap_batch_getuidbysid(idmap_get_handle_t
*get_handle
, const char *sid_prefix
,
898 uint32_t rid
, uid_t
*uid
, idmap_stat
*stat
)
900 idmap_mapping
*mapping
;
901 idmap_get_res
*result
;
903 if (get_handle
== NULL
|| sid_prefix
== NULL
||
904 uid
== NULL
|| stat
== NULL
)
905 return (IDMAP_ERR_ARG
);
907 if (kidmap_cache_lookup_uidbysid(&get_handle
->zs
->cache
, sid_prefix
,
908 rid
, uid
) == IDMAP_SUCCESS
) {
909 *stat
= IDMAP_SUCCESS
;
910 return (IDMAP_SUCCESS
);
913 /* Get a copy of sid_prefix */
914 sid_prefix
= kidmap_find_sid_prefix(sid_prefix
);
916 if (get_handle
->mapping_num
>= get_handle
->mapping_size
)
917 kidmap_get_extend(get_handle
);
919 mapping
= &get_handle
->mapping
[get_handle
->mapping_num
];
921 mapping
->id1
.idtype
= IDMAP_SID
;
922 mapping
->id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
923 mapping
->id1
.idmap_id_u
.sid
.rid
= rid
;
924 mapping
->id2
.idtype
= IDMAP_UID
;
926 result
= &get_handle
->result
[get_handle
->mapping_num
];
927 result
->idtype
= IDMAP_UID
;
931 result
->sid_prefix
= NULL
;
933 result
->is_user
= NULL
;
936 get_handle
->mapping_num
++;
938 return (IDMAP_SUCCESS
);
943 * Given Domain SID and RID, get GID
946 * sid_prefix - Domain SID in canonical form
950 * stat - status of the get request
951 * gid - POSIX GID if stat == IDMAP_SUCCESS
954 * The output parameters will be set by idmap_get_mappings()
955 * The sid_prefix is copied.
958 kidmap_batch_getgidbysid(idmap_get_handle_t
*get_handle
, const char *sid_prefix
,
959 uint32_t rid
, uid_t
*gid
, idmap_stat
*stat
)
961 idmap_mapping
*mapping
;
962 idmap_get_res
*result
;
964 if (get_handle
== NULL
|| sid_prefix
== NULL
||
965 gid
== NULL
|| stat
== NULL
)
966 return (IDMAP_ERR_ARG
);
968 if (kidmap_cache_lookup_gidbysid(&get_handle
->zs
->cache
, sid_prefix
,
969 rid
, gid
) == IDMAP_SUCCESS
) {
970 *stat
= IDMAP_SUCCESS
;
971 return (IDMAP_SUCCESS
);
974 /* Get a copy of sid_prefix */
975 sid_prefix
= kidmap_find_sid_prefix(sid_prefix
);
977 if (get_handle
->mapping_num
>= get_handle
->mapping_size
)
978 kidmap_get_extend(get_handle
);
980 mapping
= &get_handle
->mapping
[get_handle
->mapping_num
];
982 mapping
->id1
.idtype
= IDMAP_SID
;
983 mapping
->id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
984 mapping
->id1
.idmap_id_u
.sid
.rid
= rid
;
985 mapping
->id2
.idtype
= IDMAP_GID
;
987 result
= &get_handle
->result
[get_handle
->mapping_num
];
988 result
->idtype
= IDMAP_GID
;
992 result
->sid_prefix
= NULL
;
994 result
->is_user
= NULL
;
997 get_handle
->mapping_num
++;
999 return (IDMAP_SUCCESS
);
1004 * Given Domain SID and RID, get Posix ID
1007 * sid_prefix - Domain SID in canonical form
1011 * stat - status of the get request
1012 * is_user - user or group
1013 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
1014 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
1017 * The output parameters will be set by idmap_get_mappings()
1018 * The sid_prefix is copied.
1021 kidmap_batch_getpidbysid(idmap_get_handle_t
*get_handle
, const char *sid_prefix
,
1022 uint32_t rid
, uid_t
*pid
, int *is_user
, idmap_stat
*stat
)
1024 idmap_mapping
*mapping
;
1025 idmap_get_res
*result
;
1027 if (get_handle
== NULL
|| sid_prefix
== NULL
|| pid
== NULL
||
1028 is_user
== NULL
|| stat
== NULL
)
1029 return (IDMAP_ERR_ARG
);
1031 if (kidmap_cache_lookup_pidbysid(&get_handle
->zs
->cache
, sid_prefix
,
1032 rid
, pid
, is_user
) == IDMAP_SUCCESS
) {
1033 *stat
= IDMAP_SUCCESS
;
1034 return (IDMAP_SUCCESS
);
1037 /* Get a copy of sid_prefix */
1038 sid_prefix
= kidmap_find_sid_prefix(sid_prefix
);
1040 if (get_handle
->mapping_num
>= get_handle
->mapping_size
)
1041 kidmap_get_extend(get_handle
);
1043 mapping
= &get_handle
->mapping
[get_handle
->mapping_num
];
1045 mapping
->id1
.idtype
= IDMAP_SID
;
1046 mapping
->id1
.idmap_id_u
.sid
.prefix
= (char *)sid_prefix
;
1047 mapping
->id1
.idmap_id_u
.sid
.rid
= rid
;
1048 mapping
->id2
.idtype
= IDMAP_POSIXID
;
1050 result
= &get_handle
->result
[get_handle
->mapping_num
];
1051 result
->idtype
= IDMAP_POSIXID
;
1055 result
->sid_prefix
= NULL
;
1057 result
->is_user
= is_user
;
1058 result
->stat
= stat
;
1060 get_handle
->mapping_num
++;
1062 return (IDMAP_SUCCESS
);
1067 * Given UID, get SID and RID
1073 * stat - status of the get request
1074 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1075 * rid - RID (if stat == IDMAP_SUCCESS)
1077 * Note: The output parameters will be set by idmap_get_mappings()
1080 kidmap_batch_getsidbyuid(idmap_get_handle_t
*get_handle
, uid_t uid
,
1081 const char **sid_prefix
, uint32_t *rid
, idmap_stat
*stat
)
1083 idmap_mapping
*mapping
;
1084 idmap_get_res
*result
;
1086 if (get_handle
== NULL
|| sid_prefix
== NULL
||
1087 rid
== NULL
|| stat
== NULL
)
1088 return (IDMAP_ERR_ARG
);
1090 if (kidmap_cache_lookup_sidbyuid(&get_handle
->zs
->cache
,
1091 sid_prefix
, rid
, uid
) == IDMAP_SUCCESS
) {
1092 *stat
= IDMAP_SUCCESS
;
1093 return (IDMAP_SUCCESS
);
1096 if (get_handle
->mapping_num
>= get_handle
->mapping_size
)
1097 kidmap_get_extend(get_handle
);
1099 mapping
= &get_handle
->mapping
[get_handle
->mapping_num
];
1101 mapping
->id1
.idtype
= IDMAP_UID
;
1102 mapping
->id1
.idmap_id_u
.uid
= uid
;
1103 mapping
->id2
.idtype
= IDMAP_SID
;
1105 result
= &get_handle
->result
[get_handle
->mapping_num
];
1106 result
->idtype
= IDMAP_SID
;
1110 result
->sid_prefix
= sid_prefix
;
1112 result
->is_user
= NULL
;
1113 result
->stat
= stat
;
1115 get_handle
->mapping_num
++;
1117 return (IDMAP_SUCCESS
);
1122 * Given GID, get SID and RID
1128 * stat - status of the get request
1129 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1130 * rid - RID (if stat == IDMAP_SUCCESS)
1132 * Note: The output parameters will be set by idmap_get_mappings()
1135 kidmap_batch_getsidbygid(idmap_get_handle_t
*get_handle
, gid_t gid
,
1136 const char **sid_prefix
, uint32_t *rid
, idmap_stat
*stat
)
1138 idmap_mapping
*mapping
;
1139 idmap_get_res
*result
;
1141 if (get_handle
== NULL
|| sid_prefix
== NULL
||
1142 rid
== NULL
|| stat
== NULL
)
1143 return (IDMAP_ERR_ARG
);
1145 if (kidmap_cache_lookup_sidbygid(&get_handle
->zs
->cache
,
1146 sid_prefix
, rid
, gid
) == IDMAP_SUCCESS
) {
1147 *stat
= IDMAP_SUCCESS
;
1148 return (IDMAP_SUCCESS
);
1151 if (get_handle
->mapping_num
>= get_handle
->mapping_size
)
1152 kidmap_get_extend(get_handle
);
1154 mapping
= &get_handle
->mapping
[get_handle
->mapping_num
];
1156 mapping
->id1
.idtype
= IDMAP_GID
;
1157 mapping
->id1
.idmap_id_u
.gid
= gid
;
1158 mapping
->id2
.idtype
= IDMAP_SID
;
1160 result
= &get_handle
->result
[get_handle
->mapping_num
];
1161 result
->idtype
= IDMAP_SID
;
1165 result
->sid_prefix
= sid_prefix
;
1167 result
->is_user
= NULL
;
1168 result
->stat
= stat
;
1170 get_handle
->mapping_num
++;
1172 return (IDMAP_SUCCESS
);
1177 * Process the batched "get mapping" requests. The results (i.e.
1178 * status and identity) will be available in the data areas
1179 * provided by individual requests.
1181 * If the door call fails the status IDMAP_ERR_NOMAPPING is
1182 * return and the UID or UID result is set to "nobody"
1186 kidmap_get_mappings(idmap_get_handle_t
*get_handle
)
1188 idmap_mapping_batch rpc_args
;
1189 idmap_ids_res rpc_res
;
1190 uint32_t op
= IDMAP_GET_MAPPED_IDS
;
1191 idmap_mapping
*request
;
1192 idmap_get_res
*result
;
1196 const char *sid_prefix
;
1198 idmap_cache_t
*cache
;
1201 if (get_handle
== NULL
)
1202 return (IDMAP_ERR_ARG
);
1204 if (get_handle
->mapping_num
== 0)
1205 return (IDMAP_SUCCESS
);
1206 cache
= &get_handle
->zs
->cache
;
1208 bzero(&rpc_res
, sizeof (idmap_ids_res
));
1210 rpc_args
.idmap_mapping_batch_len
= get_handle
->mapping_num
;
1211 rpc_args
.idmap_mapping_batch_val
= get_handle
->mapping
;
1213 if (kidmap_rpc_call(get_handle
->zs
, op
, xdr_idmap_mapping_batch
,
1214 (caddr_t
)&rpc_args
, xdr_idmap_ids_res
,
1215 (caddr_t
)&rpc_res
) != 0) {
1216 /* Door call failed */
1217 status
= IDMAP_ERR_NOMAPPING
;
1221 status
= rpc_res
.retcode
;
1222 if (status
!= IDMAP_SUCCESS
) {
1223 /* RPC returned idmap error code */
1224 xdr_free(xdr_idmap_ids_res
, (char *)&rpc_res
);
1228 for (i
= 0; i
< get_handle
->mapping_num
; i
++) {
1229 request
= &get_handle
->mapping
[i
];
1230 result
= &get_handle
->result
[i
];
1232 if (i
>= rpc_res
.ids
.ids_len
) {
1233 *result
->stat
= IDMAP_ERR_NOMAPPING
;
1235 *result
->uid
= UID_NOBODY
;
1237 *result
->gid
= GID_NOBODY
;
1239 *result
->pid
= UID_NOBODY
;
1240 if (result
->is_user
)
1241 *result
->is_user
= 1;
1242 if (result
->sid_prefix
)
1243 *result
->sid_prefix
= NULL
;
1249 *result
->stat
= rpc_res
.ids
.ids_val
[i
].retcode
;
1251 id
= &rpc_res
.ids
.ids_val
[i
].id
;
1252 direction
= rpc_res
.ids
.ids_val
[i
].direction
;
1254 switch (id
->idtype
) {
1257 *result
->uid
= id
->idmap_id_u
.uid
;
1259 *result
->pid
= id
->idmap_id_u
.uid
;
1260 if (result
->is_user
)
1261 *result
->is_user
= 1;
1262 sid_prefix
= kidmap_find_sid_prefix(
1263 request
->id1
.idmap_id_u
.sid
.prefix
);
1264 if (*result
->stat
== IDMAP_SUCCESS
&& result
->uid
)
1265 kidmap_cache_add_sid2uid(
1267 request
->id1
.idmap_id_u
.sid
.rid
,
1270 else if (*result
->stat
== IDMAP_SUCCESS
&& result
->pid
)
1271 kidmap_cache_add_sid2pid(
1273 request
->id1
.idmap_id_u
.sid
.rid
,
1274 id
->idmap_id_u
.uid
, 1,
1280 *result
->gid
= id
->idmap_id_u
.gid
;
1282 *result
->pid
= id
->idmap_id_u
.gid
;
1283 if (result
->is_user
)
1284 *result
->is_user
= 0;
1285 sid_prefix
= kidmap_find_sid_prefix(
1286 request
->id1
.idmap_id_u
.sid
.prefix
);
1287 if (*result
->stat
== IDMAP_SUCCESS
&& result
->gid
)
1288 kidmap_cache_add_sid2gid(
1290 request
->id1
.idmap_id_u
.sid
.rid
,
1293 else if (*result
->stat
== IDMAP_SUCCESS
&& result
->pid
)
1294 kidmap_cache_add_sid2pid(
1296 request
->id1
.idmap_id_u
.sid
.rid
,
1297 id
->idmap_id_u
.gid
, 0,
1304 sid_prefix
= kidmap_find_sid_prefix(
1305 id
->idmap_id_u
.sid
.prefix
);
1306 if (result
->sid_prefix
&& result
->rid
) {
1307 *result
->sid_prefix
= sid_prefix
;
1308 *result
->rid
= id
->idmap_id_u
.sid
.rid
;
1310 if (*result
->stat
== IDMAP_SUCCESS
&&
1311 request
->id1
.idtype
== IDMAP_UID
)
1312 kidmap_cache_add_sid2uid(
1314 id
->idmap_id_u
.sid
.rid
,
1315 request
->id1
.idmap_id_u
.uid
,
1317 else if (*result
->stat
== IDMAP_SUCCESS
&&
1318 request
->id1
.idtype
== IDMAP_GID
)
1319 kidmap_cache_add_sid2gid(
1321 id
->idmap_id_u
.sid
.rid
,
1322 request
->id1
.idmap_id_u
.gid
,
1327 *result
->stat
= IDMAP_ERR_NORESULT
;
1329 *result
->uid
= UID_NOBODY
;
1331 *result
->gid
= GID_NOBODY
;
1333 *result
->pid
= UID_NOBODY
;
1334 if (result
->is_user
)
1335 *result
->is_user
= 1;
1336 if (result
->sid_prefix
)
1337 *result
->sid_prefix
= NULL
;
1343 xdr_free(xdr_idmap_ids_res
, (char *)&rpc_res
);
1345 /* Reset get_handle for new resquests */
1346 get_handle
->mapping_num
= 0;
1350 for (i
= 0; i
< get_handle
->mapping_num
; i
++) {
1351 result
= &get_handle
->result
[i
];
1353 *result
->stat
= status
;
1355 *result
->uid
= UID_NOBODY
;
1357 *result
->gid
= GID_NOBODY
;
1359 *result
->pid
= UID_NOBODY
;
1360 if (result
->is_user
)
1361 *result
->is_user
= 1;
1362 if (result
->sid_prefix
)
1363 *result
->sid_prefix
= NULL
;
1368 /* Reset get_handle for new resquests */
1369 get_handle
->mapping_num
= 0;
1375 * Destroy the "get mapping" handle
1378 kidmap_get_destroy(idmap_get_handle_t
*get_handle
)
1380 if (get_handle
== NULL
)
1383 kmem_free(get_handle
->mapping
,
1384 (sizeof (idmap_mapping
)) * get_handle
->mapping_size
);
1385 get_handle
->mapping
= NULL
;
1387 kmem_free(get_handle
->result
,
1388 (sizeof (idmap_get_res
)) * get_handle
->mapping_size
);
1389 get_handle
->result
= NULL
;
1391 kmem_free(get_handle
, sizeof (idmap_get_handle_t
));
1396 kidmap_rpc_call(idmap_zone_specific_t
*zs
, uint32_t op
, xdrproc_t xdr_args
,
1397 caddr_t args
, xdrproc_t xdr_res
, caddr_t res
)
1400 struct rpc_msg reply_msg
;
1401 char *inbuf_ptr
= NULL
;
1402 size_t inbuf_size
= 4096;
1403 char *outbuf_ptr
= NULL
;
1404 size_t outbuf_size
= 4096;
1409 struct rpc_msg call_msg
;
1415 inbuf_ptr
= kmem_alloc(inbuf_size
, KM_SLEEP
);
1416 outbuf_ptr
= kmem_alloc(outbuf_size
, KM_SLEEP
);
1418 xdrmem_create(&xdr_ctx
, inbuf_ptr
, inbuf_size
, XDR_ENCODE
);
1420 call_msg
.rm_call
.cb_prog
= IDMAP_PROG
;
1421 call_msg
.rm_call
.cb_vers
= IDMAP_V1
;
1422 call_msg
.rm_xid
= atomic_inc_32_nv(&zs
->message_id
);
1424 if (!xdr_callhdr(&xdr_ctx
, &call_msg
)) {
1426 zcmn_err(zs
->zone_id
, CE_WARN
,
1427 "idmap: xdr encoding header error");
1433 if (!xdr_uint32(&xdr_ctx
, &op
) ||
1435 !xdr_opaque_auth(&xdr_ctx
, &_null_auth
) ||
1436 !xdr_opaque_auth(&xdr_ctx
, &_null_auth
) ||
1438 !xdr_args(&xdr_ctx
, args
)) {
1440 zcmn_err(zs
->zone_id
, CE_WARN
, "idmap: xdr encoding error");
1448 kmem_free(inbuf_ptr
, inbuf_size
);
1452 kmem_free(outbuf_ptr
, outbuf_size
);
1455 if ((size
= xdr_sizeof(xdr_args
, args
)) == 0) {
1457 zcmn_err(zs
->zone_id
, CE_WARN
,
1458 "idmap: xdr_sizeof error");
1463 inbuf_size
= size
+ 1024;
1464 outbuf_size
= size
+ 1024;
1468 params
.data_ptr
= inbuf_ptr
;
1469 params
.data_size
= XDR_GETPOS(&xdr_ctx
);
1470 params
.desc_ptr
= NULL
;
1471 params
.desc_num
= 0;
1472 params
.rbuf
= outbuf_ptr
;
1473 params
.rsize
= outbuf_size
;
1475 if (kidmap_call_door(zs
, ¶ms
) != 0) {
1480 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
1481 reply_msg
.acpted_rply
.ar_results
.where
= res
;
1482 reply_msg
.acpted_rply
.ar_results
.proc
= xdr_res
;
1483 xdrmem_create(&xdr_ctx
, params
.data_ptr
, params
.data_size
, XDR_DECODE
);
1484 if (xdr_replymsg(&xdr_ctx
, &reply_msg
)) {
1485 if (reply_msg
.rm_reply
.rp_stat
!= MSG_ACCEPTED
||
1486 reply_msg
.rm_reply
.rp_acpt
.ar_stat
!= SUCCESS
) {
1492 zcmn_err(zs
->zone_id
, CE_WARN
,
1493 "idmap: xdr decoding reply message error");
1499 if (outbuf_ptr
!= params
.rbuf
&& params
.rbuf
!= NULL
)
1500 kmem_free(params
.rbuf
, params
.rsize
);
1502 kmem_free(inbuf_ptr
, inbuf_size
);
1504 kmem_free(outbuf_ptr
, outbuf_size
);