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 2008 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 "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 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 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 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 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 * 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 */ 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 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 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 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 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 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 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 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 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 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 * 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 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 * Note: The output parameters will be set by idmap_get_mappings() 894 */ 895 idmap_stat 896 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 897 uint32_t rid, uid_t *uid, idmap_stat *stat) 898 { 899 idmap_mapping *mapping; 900 idmap_get_res *result; 901 902 if (get_handle == NULL || sid_prefix == NULL || 903 uid == NULL || stat == NULL) 904 return (IDMAP_ERR_ARG); 905 906 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 907 rid, uid) == IDMAP_SUCCESS) { 908 *stat = IDMAP_SUCCESS; 909 return (IDMAP_SUCCESS); 910 } 911 912 if (get_handle->mapping_num >= get_handle->mapping_size) 913 kidmap_get_extend(get_handle); 914 915 mapping = &get_handle->mapping[get_handle->mapping_num]; 916 mapping->flag = 0; 917 mapping->id1.idtype = IDMAP_SID; 918 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 919 mapping->id1.idmap_id_u.sid.rid = rid; 920 mapping->id2.idtype = IDMAP_UID; 921 922 result = &get_handle->result[get_handle->mapping_num]; 923 result->idtype = IDMAP_UID; 924 result->uid = uid; 925 result->gid = NULL; 926 result->pid = NULL; 927 result->sid_prefix = NULL; 928 result->rid = NULL; 929 result->is_user = NULL; 930 result->stat = stat; 931 932 get_handle->mapping_num++; 933 934 return (IDMAP_SUCCESS); 935 } 936 937 938 /* 939 * Given Domain SID and RID, get GID 940 * 941 * Input: 942 * sid_prefix - Domain SID in canonical form 943 * rid - RID 944 * 945 * Output: 946 * stat - status of the get request 947 * gid - POSIX GID if stat == IDMAP_SUCCESS 948 * 949 * Note: The output parameters will be set by idmap_get_mappings() 950 */ 951 idmap_stat 952 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 953 uint32_t rid, uid_t *gid, idmap_stat *stat) 954 { 955 idmap_mapping *mapping; 956 idmap_get_res *result; 957 958 if (get_handle == NULL || sid_prefix == NULL || 959 gid == NULL || stat == NULL) 960 return (IDMAP_ERR_ARG); 961 962 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 963 rid, gid) == IDMAP_SUCCESS) { 964 *stat = IDMAP_SUCCESS; 965 return (IDMAP_SUCCESS); 966 } 967 968 if (get_handle->mapping_num >= get_handle->mapping_size) 969 kidmap_get_extend(get_handle); 970 971 mapping = &get_handle->mapping[get_handle->mapping_num]; 972 mapping->flag = 0; 973 mapping->id1.idtype = IDMAP_SID; 974 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 975 mapping->id1.idmap_id_u.sid.rid = rid; 976 mapping->id2.idtype = IDMAP_GID; 977 978 result = &get_handle->result[get_handle->mapping_num]; 979 result->idtype = IDMAP_GID; 980 result->uid = NULL; 981 result->gid = gid; 982 result->pid = NULL; 983 result->sid_prefix = NULL; 984 result->rid = NULL; 985 result->is_user = NULL; 986 result->stat = stat; 987 988 get_handle->mapping_num++; 989 990 return (IDMAP_SUCCESS); 991 } 992 993 994 /* 995 * Given Domain SID and RID, get Posix ID 996 * 997 * Input: 998 * sid_prefix - Domain SID in canonical form 999 * rid - RID 1000 * 1001 * Output: 1002 * stat - status of the get request 1003 * is_user - user or group 1004 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 1005 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 1006 * 1007 * Note: The output parameters will be set by idmap_get_mappings() 1008 */ 1009 idmap_stat 1010 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 1011 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 1012 { 1013 idmap_mapping *mapping; 1014 idmap_get_res *result; 1015 1016 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 1017 is_user == NULL || stat == NULL) 1018 return (IDMAP_ERR_ARG); 1019 1020 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 1021 rid, pid, is_user) == IDMAP_SUCCESS) { 1022 *stat = IDMAP_SUCCESS; 1023 return (IDMAP_SUCCESS); 1024 } 1025 1026 1027 if (get_handle->mapping_num >= get_handle->mapping_size) 1028 kidmap_get_extend(get_handle); 1029 1030 mapping = &get_handle->mapping[get_handle->mapping_num]; 1031 mapping->flag = 0; 1032 mapping->id1.idtype = IDMAP_SID; 1033 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 1034 mapping->id1.idmap_id_u.sid.rid = rid; 1035 mapping->id2.idtype = IDMAP_POSIXID; 1036 1037 result = &get_handle->result[get_handle->mapping_num]; 1038 result->idtype = IDMAP_POSIXID; 1039 result->uid = NULL; 1040 result->gid = NULL; 1041 result->pid = pid; 1042 result->sid_prefix = NULL; 1043 result->rid = NULL; 1044 result->is_user = is_user; 1045 result->stat = stat; 1046 1047 get_handle->mapping_num++; 1048 1049 return (IDMAP_SUCCESS); 1050 } 1051 1052 1053 /* 1054 * Given UID, get SID and RID 1055 * 1056 * Input: 1057 * uid - POSIX UID 1058 * 1059 * Output: 1060 * stat - status of the get request 1061 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1062 * rid - RID (if stat == IDMAP_SUCCESS) 1063 * 1064 * Note: The output parameters will be set by idmap_get_mappings() 1065 */ 1066 idmap_stat 1067 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 1068 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1069 { 1070 idmap_mapping *mapping;