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