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.retcode != IDMAP_SUCCESS) { 377 status = results.retcode; 378 *uid = UID_NOBODY; 379 } else if (results.ids.ids_len >= 1 && 380 results.ids.ids_val[0].id.idtype == IDMAP_UID) { 381 status = results.ids.ids_val[0].retcode; 382 *uid = results.ids.ids_val[0].id.idmap_id_u.uid; 383 if (status == IDMAP_SUCCESS) { 384 new_sid_prefix = kidmap_find_sid_prefix( 385 sid_prefix); 386 kidmap_cache_add_uidbysid(&zs->cache, 387 new_sid_prefix, rid, *uid); 388 } 389 } else { 390 status = IDMAP_ERR_NOMAPPING; 391 *uid = UID_NOBODY; 392 } 393 xdr_free(xdr_idmap_ids_res, (char *)&results); 394 } else { 395 /* Door call failed */ 396 status = IDMAP_ERR_NOMAPPING; 397 *uid = UID_NOBODY; 398 } 399 return (status); 400 } 401 402 403 /* 404 * Given Domain SID and RID, get GID 405 * 406 * Input: 407 * sid_prefix - Domain SID in canonical form 408 * rid - RID 409 * 410 * Output: 411 * gid - POSIX UID if return == IDMAP_SUCCESS 412 * 413 * Return: 414 * Success return IDMAP_SUCCESS else IDMAP error 415 */ 416 idmap_stat 417 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 418 gid_t *gid) 419 { 420 idmap_zone_specific_t *zs; 421 idmap_mapping_batch args; 422 idmap_mapping mapping; 423 idmap_ids_res results; 424 uint32_t op = IDMAP_GET_MAPPED_IDS; 425 const char *new_sid_prefix; 426 idmap_stat status; 427 428 if (sid_prefix == NULL || gid == NULL) 429 return (IDMAP_ERR_ARG); 430 431 zs = idmap_get_zone_specific(zone); 432 433 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid) 434 == IDMAP_SUCCESS) 435 return (IDMAP_SUCCESS); 436 437 bzero(&mapping, sizeof (idmap_mapping)); 438 mapping.id1.idtype = IDMAP_SID; 439 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 440 mapping.id1.idmap_id_u.sid.rid = rid; 441 mapping.id2.idtype = IDMAP_GID; 442 443 bzero(&results, sizeof (idmap_ids_res)); 444 445 args.idmap_mapping_batch_len = 1; 446 args.idmap_mapping_batch_val = &mapping; 447 448 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 449 (caddr_t)&args, xdr_idmap_ids_res, 450 (caddr_t)&results) == 0) { 451 /* Door call succeded */ 452 if (results.retcode != IDMAP_SUCCESS) { 453 status = results.retcode; 454 *gid = GID_NOBODY; 455 } else if (results.ids.ids_len >= 1 && 456 results.ids.ids_val[0].id.idtype == IDMAP_GID) { 457 status = results.ids.ids_val[0].retcode; 458 *gid = results.ids.ids_val[0].id.idmap_id_u.gid; 459 if (status == IDMAP_SUCCESS) { 460 new_sid_prefix = kidmap_find_sid_prefix( 461 sid_prefix); 462 kidmap_cache_add_gidbysid(&zs->cache, 463 new_sid_prefix, rid, *gid); 464 } 465 } else { 466 status = IDMAP_ERR_NOMAPPING; 467 *gid = GID_NOBODY; 468 } 469 xdr_free(xdr_idmap_ids_res, (char *)&results); 470 } else { 471 /* Door call failed */ 472 status = IDMAP_ERR_NOMAPPING; 473 *gid = GID_NOBODY; 474 } 475 return (status); 476 } 477 478 /* 479 * Given Domain SID and RID, get Posix ID 480 * 481 * Input: 482 * sid_prefix - Domain SID in canonical form 483 * rid - RID 484 * 485 * Output: 486 * pid - POSIX ID if return == IDMAP_SUCCESS 487 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS 488 * 489 * Return: 490 * Success return IDMAP_SUCCESS else IDMAP error 491 */ 492 idmap_stat 493 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 494 uid_t *pid, int *is_user) 495 { 496 idmap_zone_specific_t *zs; 497 idmap_mapping_batch args; 498 idmap_mapping mapping; 499 idmap_ids_res results; 500 uint32_t op = IDMAP_GET_MAPPED_IDS; 501 const char *new_sid_prefix; 502 idmap_stat status; 503 504 if (sid_prefix == NULL || pid == NULL || is_user == NULL) 505 return (IDMAP_ERR_ARG); 506 507 zs = idmap_get_zone_specific(zone); 508 509 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid, 510 is_user) == IDMAP_SUCCESS) 511 return (IDMAP_SUCCESS); 512 513 bzero(&mapping, sizeof (idmap_mapping)); 514 mapping.id1.idtype = IDMAP_SID; 515 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 516 mapping.id1.idmap_id_u.sid.rid = rid; 517 mapping.id2.idtype = IDMAP_POSIXID; 518 519 bzero(&results, sizeof (idmap_ids_res)); 520 521 args.idmap_mapping_batch_len = 1; 522 args.idmap_mapping_batch_val = &mapping; 523 524 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 525 (caddr_t)&args, xdr_idmap_ids_res, 526 (caddr_t)&results) == 0) { 527 /* Door call succeded */ 528 if (results.retcode != IDMAP_SUCCESS) { 529 status = results.retcode; 530 *is_user = 1; 531 *pid = UID_NOBODY; 532 } else if (results.ids.ids_len >= 1 && ( 533 results.ids.ids_val[0].id.idtype == IDMAP_UID || 534 results.ids.ids_val[0].id.idtype == IDMAP_GID)) { 535 status = results.ids.ids_val[0].retcode; 536 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) { 537 *is_user = 1; 538 *pid = results.ids.ids_val[0].id.idmap_id_u.uid; 539 } else { 540 *is_user = 0; 541 *pid = results.ids.ids_val[0].id.idmap_id_u.gid; 542 } 543 if (status == IDMAP_SUCCESS) { 544 new_sid_prefix = kidmap_find_sid_prefix( 545 sid_prefix); 546 kidmap_cache_add_pidbysid(&zs->cache, 547 new_sid_prefix, rid, *pid, 548 *is_user); 549 } 550 } else { 551 status = IDMAP_ERR_NOMAPPING; 552 *is_user = 1; 553 *pid = UID_NOBODY; 554 } 555 xdr_free(xdr_idmap_ids_res, (char *)&results); 556 } else { 557 /* Door call failed */ 558 status = IDMAP_ERR_NOMAPPING; 559 *is_user = 1; 560 *pid = UID_NOBODY; 561 } 562 return (status); 563 } 564 565 566 /* 567 * Given UID, get Domain SID and RID 568 * 569 * Input: 570 * uid - Posix UID 571 * 572 * Output: 573 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 574 * rid - RID if return == IDMAP_SUCCESS 575 * 576 * Return: 577 * Success return IDMAP_SUCCESS else IDMAP error 578 */ 579 idmap_stat 580 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix, 581 uint32_t *rid) 582 { 583 idmap_zone_specific_t *zs; 584 idmap_mapping_batch args; 585 idmap_mapping mapping; 586 idmap_ids_res results; 587 uint32_t op = IDMAP_GET_MAPPED_IDS; 588 idmap_stat status; 589 time_t entry_ttl; 590 idmap_id *id; 591 592 if (sid_prefix == NULL || rid == NULL) 593 return (IDMAP_ERR_ARG); 594 595 zs = idmap_get_zone_specific(zone); 596 597 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid) 598 == IDMAP_SUCCESS) { 599 return (IDMAP_SUCCESS); 600 } 601 602 bzero(&mapping, sizeof (idmap_mapping)); 603 mapping.id1.idtype = IDMAP_UID; 604 mapping.id1.idmap_id_u.uid = uid; 605 mapping.id2.idtype = IDMAP_SID; 606 607 bzero(&results, sizeof (idmap_ids_res)); 608 609 args.idmap_mapping_batch_len = 1; 610 args.idmap_mapping_batch_val = &mapping; 611 612 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 613 (caddr_t)&args, xdr_idmap_ids_res, 614 (caddr_t)&results) == 0) { 615 /* Door call succeded */ 616 if (results.retcode != IDMAP_SUCCESS) { 617 status = results.retcode; 618 *rid = 0; 619 *sid_prefix = NULL; 620 } else if (results.ids.ids_len >= 1 && 621 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 622 results.ids.ids_val[0].id.idtype == IDMAP_USID || 623 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 624 status = results.ids.ids_val[0].retcode; 625 id = &results.ids.ids_val[0].id; 626 *sid_prefix = kidmap_find_sid_prefix( 627 id->idmap_id_u.sid.prefix); 628 *rid = id->idmap_id_u.sid.rid; 629 if (status == IDMAP_SUCCESS) { 630 kidmap_cache_add_sidbyuid(&zs->cache, 631 *sid_prefix, *rid, uid); 632 } 633 } else { 634 status = IDMAP_ERR_NOMAPPING; 635 *rid = 0; 636 *sid_prefix = NULL; 637 } 638 xdr_free(xdr_idmap_ids_res, (char *)&results); 639 } else { 640 /* Door call failed */ 641 status = IDMAP_ERR_NOMAPPING; 642 *rid = 0; 643 *sid_prefix = NULL; 644 } 645 return (status); 646 } 647 648 649 /* 650 * Given GID, get Domain SID and RID 651 * 652 * Input: 653 * gid - Posix GID 654 * 655 * Output: 656 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 657 * rid - RID if return == IDMAP_SUCCESS 658 * 659 * Return: 660 * Success return IDMAP_SUCCESS else IDMAP error 661 */ 662 idmap_stat 663 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix, 664 uint32_t *rid) 665 { 666 idmap_zone_specific_t *zs; 667 idmap_mapping_batch args; 668 idmap_mapping mapping; 669 idmap_ids_res results; 670 uint32_t op = IDMAP_GET_MAPPED_IDS; 671 idmap_stat status; 672 idmap_id *id; 673 674 if (sid_prefix == NULL || rid == NULL) 675 return (IDMAP_ERR_ARG); 676 677 zs = idmap_get_zone_specific(zone); 678 679 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid) 680 == IDMAP_SUCCESS) { 681 return (IDMAP_SUCCESS); 682 } 683 684 bzero(&mapping, sizeof (idmap_mapping)); 685 mapping.id1.idtype = IDMAP_GID; 686 mapping.id1.idmap_id_u.uid = gid; 687 mapping.id2.idtype = IDMAP_SID; 688 689 bzero(&results, sizeof (idmap_ids_res)); 690 691 args.idmap_mapping_batch_len = 1; 692 args.idmap_mapping_batch_val = &mapping; 693 694 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 695 (caddr_t)&args, xdr_idmap_ids_res, 696 (caddr_t)&results) == 0) { 697 /* Door call succeded */ 698 if (results.retcode != IDMAP_SUCCESS) { 699 status = results.retcode; 700 *rid = 0; 701 *sid_prefix = NULL; 702 } else if (results.ids.ids_len >= 1 && 703 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 704 results.ids.ids_val[0].id.idtype == IDMAP_USID || 705 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 706 status = results.ids.ids_val[0].retcode; 707 id = &results.ids.ids_val[0].id; 708 *sid_prefix = kidmap_find_sid_prefix( 709 id->idmap_id_u.sid.prefix); 710 *rid = id->idmap_id_u.sid.rid; 711 if (status == IDMAP_SUCCESS) { 712 kidmap_cache_add_sidbygid(&zs->cache, 713 *sid_prefix, *rid, gid); 714 } 715 } else { 716 status = IDMAP_ERR_NOMAPPING; 717 *rid = 0; 718 *sid_prefix = NULL; 719 } 720 xdr_free(xdr_idmap_ids_res, (char *)&results); 721 } else { 722 /* Door call failed */ 723 status = IDMAP_ERR_NOMAPPING; 724 *rid = 0; 725 *sid_prefix = NULL; 726 } 727 return (status); 728 } 729 730 /* 731 * Create handle to get SID to UID/GID mapping entries 732 * 733 * Input: 734 * none 735 * Return: 736 * get_handle 737 * 738 */ 739 idmap_get_handle_t * 740 kidmap_get_create(zone_t *zone) 741 { 742 idmap_zone_specific_t *zs; 743 idmap_get_handle_t *handle; 744 #define INIT_MAPPING_SIZE 32 745 746 zs = idmap_get_zone_specific(zone); 747 748 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP); 749 750 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) * 751 INIT_MAPPING_SIZE, KM_SLEEP); 752 753 handle->result = kmem_zalloc((sizeof (idmap_get_res)) * 754 INIT_MAPPING_SIZE, KM_SLEEP); 755 handle->mapping_size = INIT_MAPPING_SIZE; 756 handle->zs = zs; 757 758 return (handle); 759 } 760 761 /* 762 * Internal routine to extend a "get_handle" 763 */ 764 static void 765 kidmap_get_extend(idmap_get_handle_t *get_handle) 766 { 767 idmap_mapping *mapping; 768 idmap_get_res *result; 769 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE; 770 771 mapping = kmem_zalloc((sizeof (idmap_mapping)) * 772 new_size, KM_SLEEP); 773 (void) memcpy(mapping, get_handle->mapping, 774 (sizeof (idmap_mapping)) * get_handle->mapping_size); 775 776 result = kmem_zalloc((sizeof (idmap_get_res)) * 777 new_size, KM_SLEEP); 778 (void) memcpy(result, get_handle->result, 779 (sizeof (idmap_get_res)) * get_handle->mapping_size); 780 781 kmem_free(get_handle->mapping, 782 (sizeof (idmap_mapping)) * get_handle->mapping_size); 783 get_handle->mapping = mapping; 784 785 kmem_free(get_handle->result, 786 (sizeof (idmap_get_res)) * get_handle->mapping_size); 787 get_handle->result = result; 788 789 get_handle->mapping_size = new_size; 790 } 791 792 793 /* 794 * Given Domain SID and RID, get UID 795 * 796 * Input: 797 * sid_prefix - Domain SID in canonical form 798 * rid - RID 799 * 800 * Output: 801 * stat - status of the get request 802 * uid - POSIX UID if stat == IDMAP_SUCCESS 803 * 804 * Note: The output parameters will be set by idmap_get_mappings() 805 */ 806 idmap_stat 807 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 808 uint32_t rid, uid_t *uid, idmap_stat *stat) 809 { 810 idmap_mapping *mapping; 811 idmap_get_res *result; 812 813 if (get_handle == NULL || sid_prefix == NULL || 814 uid == NULL || stat == NULL) 815 return (IDMAP_ERR_ARG); 816 817 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 818 rid, uid) == IDMAP_SUCCESS) { 819 *stat = IDMAP_SUCCESS; 820 return (IDMAP_SUCCESS); 821 } 822 823 if (get_handle->mapping_num >= get_handle->mapping_size) 824 kidmap_get_extend(get_handle); 825 826 mapping = &get_handle->mapping[get_handle->mapping_num]; 827 mapping->flag = 0; 828 mapping->id1.idtype = IDMAP_SID; 829 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 830 mapping->id1.idmap_id_u.sid.rid = rid; 831 mapping->id2.idtype = IDMAP_UID; 832 833 result = &get_handle->result[get_handle->mapping_num]; 834 result->idtype = IDMAP_UID; 835 result->uid = uid; 836 result->gid = NULL; 837 result->pid = NULL; 838 result->sid_prefix = NULL; 839 result->rid = NULL; 840 result->is_user = NULL; 841 result->stat = stat; 842 843 get_handle->mapping_num++; 844 845 return (IDMAP_SUCCESS); 846 } 847 848 849 /* 850 * Given Domain SID and RID, get GID 851 * 852 * Input: 853 * sid_prefix - Domain SID in canonical form 854 * rid - RID 855 * 856 * Output: 857 * stat - status of the get request 858 * gid - POSIX GID if stat == IDMAP_SUCCESS 859 * 860 * Note: The output parameters will be set by idmap_get_mappings() 861 */ 862 idmap_stat 863 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 864 uint32_t rid, uid_t *gid, idmap_stat *stat) 865 { 866 idmap_mapping *mapping; 867 idmap_get_res *result; 868 869 if (get_handle == NULL || sid_prefix == NULL || 870 gid == NULL || stat == NULL) 871 return (IDMAP_ERR_ARG); 872 873 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 874 rid, gid) == IDMAP_SUCCESS) { 875 *stat = IDMAP_SUCCESS; 876 return (IDMAP_SUCCESS); 877 } 878 879 if (get_handle->mapping_num >= get_handle->mapping_size) 880 kidmap_get_extend(get_handle); 881 882 mapping = &get_handle->mapping[get_handle->mapping_num]; 883 mapping->flag = 0; 884 mapping->id1.idtype = IDMAP_SID; 885 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 886 mapping->id1.idmap_id_u.sid.rid = rid; 887 mapping->id2.idtype = IDMAP_GID; 888 889 result = &get_handle->result[get_handle->mapping_num]; 890 result->idtype = IDMAP_GID; 891 result->uid = NULL; 892 result->gid = gid; 893 result->pid = NULL; 894 result->sid_prefix = NULL; 895 result->rid = NULL; 896 result->is_user = NULL; 897 result->stat = stat; 898 899 get_handle->mapping_num++; 900 901 return (IDMAP_SUCCESS); 902 } 903 904 905 /* 906 * Given Domain SID and RID, get Posix ID 907 * 908 * Input: 909 * sid_prefix - Domain SID in canonical form 910 * rid - RID 911 * 912 * Output: 913 * stat - status of the get request 914 * is_user - user or group 915 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 916 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 917 * 918 * Note: The output parameters will be set by idmap_get_mappings() 919 */ 920 idmap_stat 921 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 922 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 923 { 924 idmap_mapping *mapping; 925 idmap_get_res *result; 926 927 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 928 is_user == NULL || stat == NULL) 929 return (IDMAP_ERR_ARG); 930 931 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 932 rid, pid, is_user) == IDMAP_SUCCESS) { 933 *stat = IDMAP_SUCCESS; 934 return (IDMAP_SUCCESS); 935 } 936 937 938 if (get_handle->mapping_num >= get_handle->mapping_size) 939 kidmap_get_extend(get_handle); 940 941 mapping = &get_handle->mapping[get_handle->mapping_num]; 942 mapping->flag = 0; 943 mapping->id1.idtype = IDMAP_SID; 944 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 945 mapping->id1.idmap_id_u.sid.rid = rid; 946 mapping->id2.idtype = IDMAP_POSIXID; 947 948 result = &get_handle->result[get_handle->mapping_num]; 949 result->idtype = IDMAP_POSIXID; 950 result->uid = NULL; 951 result->gid = NULL; 952 result->pid = pid; 953 result->sid_prefix = NULL; 954 result->rid = NULL; 955 result->is_user = is_user; 956 result->stat = stat; 957 958 get_handle->mapping_num++; 959 960 return (IDMAP_SUCCESS); 961 } 962 963 964 /* 965 * Given UID, get SID and RID 966 * 967 * Input: 968 * uid - POSIX UID 969 * 970 * Output: 971 * stat - status of the get request 972 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 973 * rid - RID (if stat == IDMAP_SUCCESS) 974 * 975 * Note: The output parameters will be set by idmap_get_mappings() 976 */ 977 idmap_stat 978 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 979 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 980 { 981 idmap_mapping *mapping; 982 idmap_get_res *result; 983 984 if (get_handle == NULL || sid_prefix == NULL || 985 rid == NULL || stat == NULL) 986 return (IDMAP_ERR_ARG); 987 988 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache, 989 sid_prefix, rid, uid) == IDMAP_SUCCESS) { 990 *stat = IDMAP_SUCCESS; 991 return (IDMAP_SUCCESS); 992 } 993 994 if (get_handle->mapping_num >= get_handle->mapping_size) 995 kidmap_get_extend(get_handle); 996 997 mapping = &get_handle->mapping[get_handle->mapping_num]; 998 mapping->flag = 0; 999 mapping->id1.idtype = IDMAP_UID; 1000 mapping->id1.idmap_id_u.uid = uid; 1001 mapping->id2.idtype = IDMAP_SID; 1002 1003 result = &get_handle->result[get_handle->mapping_num]; 1004 result->idtype = IDMAP_SID; 1005 result->uid = NULL; 1006 result->gid = NULL; 1007 result->pid = NULL; 1008 result->sid_prefix = sid_prefix; 1009 result->rid = rid; 1010 result->is_user = NULL; 1011 result->stat = stat; 1012 1013 get_handle->mapping_num++; 1014 1015 return (IDMAP_SUCCESS); 1016 } 1017 1018 1019 /* 1020 * Given GID, get SID and RID 1021 * 1022 * Input: 1023 * gid - POSIX GID 1024 * 1025 * Output: 1026 * stat - status of the get request 1027 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1028 * rid - RID (if stat == IDMAP_SUCCESS) 1029 * 1030 * Note: The output parameters will be set by idmap_get_mappings() 1031 */ 1032 idmap_stat 1033 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 1034 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1035 { 1036 idmap_mapping *mapping; 1037 idmap_get_res *result; 1038 1039 if (get_handle == NULL || sid_prefix == NULL || 1040 rid == NULL || stat == NULL) 1041 return (IDMAP_ERR_ARG); 1042 1043 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache, 1044 sid_prefix, rid, gid) == IDMAP_SUCCESS) { 1045 *stat = IDMAP_SUCCESS; 1046 return (IDMAP_SUCCESS); 1047 } 1048 1049 if (get_handle->mapping_num >= get_handle->mapping_size) 1050 kidmap_get_extend(get_handle); 1051 1052 mapping = &get_handle->mapping[get_handle->mapping_num]; 1053 mapping->flag = 0; 1054 mapping->id1.idtype = IDMAP_GID; 1055 mapping->id1.idmap_id_u.gid = gid; 1056 mapping->id2.idtype = IDMAP_SID; 1057 1058 result = &get_handle->result[get_handle->mapping_num]; 1059 result->idtype = IDMAP_SID; 1060 result->uid = NULL; 1061 result->gid = NULL; 1062 result->pid = NULL; 1063 result->sid_prefix = sid_prefix; 1064 result->rid = rid; 1065 result->is_user = NULL; 1066 result->stat = stat; 1067 1068 get_handle->mapping_num++; 1069 1070 return (IDMAP_SUCCESS); 1071 } 1072 1073 1074 /* 1075 * Process the batched "get mapping" requests. The results (i.e. 1076 * status and identity) will be available in the data areas 1077 * provided by individual requests. 1078 * 1079 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1080 * return and the UID or UID result is set to "nobody" 1081 */ 1082 1083 idmap_stat 1084 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1085 { 1086 idmap_mapping_batch rpc_args; 1087 idmap_ids_res rpc_res; 1088 uint32_t op = IDMAP_GET_MAPPED_IDS; 1089 idmap_mapping *mapping; 1090 idmap_get_res *result; 1091 idmap_id *id; 1092 int status; 1093 int i; 1094 const char *sid_prefix; 1095 int is_user; 1096 idmap_cache_t *cache; 1097 1098 if (get_handle == NULL) 1099 return (IDMAP_ERR_ARG); 1100 1101 if (get_handle->mapping_num == 0) 1102 return (IDMAP_SUCCESS); 1103 cache = &get_handle->zs->cache; 1104 1105 bzero(&rpc_res, sizeof (idmap_ids_res)); 1106 1107 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num; 1108 rpc_args.idmap_mapping_batch_val = get_handle->mapping; 1109 1110 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch, 1111 (caddr_t)&rpc_args, xdr_idmap_ids_res, 1112 (caddr_t)&rpc_res) != 0) { 1113 /* Door call failed */ 1114 status = IDMAP_ERR_NOMAPPING; 1115 goto error; 1116 } 1117 1118 status = rpc_res.retcode; 1119 if (status != IDMAP_SUCCESS) { 1120 /* RPC returned idmap error code */ 1121 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1122 goto error; 1123 } 1124 1125 for (i = 0; i < get_handle->mapping_num; i++) { 1126 mapping = &get_handle->mapping[i]; 1127 result = &get_handle->result[i]; 1128 1129 if (i >= rpc_res.ids.ids_len) { 1130 *result->stat = IDMAP_ERR_NOMAPPING; 1131 if (result->uid) 1132 *result->uid = UID_NOBODY; 1133 if (result->gid) 1134 *result->gid = GID_NOBODY; 1135 if (result->pid) 1136 *result->pid = UID_NOBODY; 1137 if (result->is_user) 1138 *result->is_user = 1; 1139 if (result->sid_prefix) 1140 *result->sid_prefix = NULL; 1141 if (result->rid) 1142 *result->rid = 0; 1143 continue; 1144 } 1145 1146 *result->stat = rpc_res.ids.ids_val[i].retcode; 1147 1148 id = &rpc_res.ids.ids_val[i].id; 1149 switch (id->idtype) { 1150 case IDMAP_UID: 1151 if (result->uid) 1152 *result->uid = id->idmap_id_u.uid; 1153 if (result->pid) 1154 *result->pid = id->idmap_id_u.uid; 1155 if (result->is_user) 1156 *result->is_user = 1; 1157 sid_prefix = kidmap_find_sid_prefix( 1158 mapping->id1.idmap_id_u.sid.prefix); 1159 if (*result->stat == IDMAP_SUCCESS && result->uid) 1160 kidmap_cache_add_uidbysid( 1161 cache, sid_prefix, 1162 mapping->id1.idmap_id_u.sid.rid, 1163 id->idmap_id_u.uid); 1164 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1165 kidmap_cache_add_uidbysid( 1166 cache, sid_prefix, 1167 mapping->id1.idmap_id_u.sid.rid, 1168 id->idmap_id_u.uid); 1169 break; 1170 1171 case IDMAP_GID: 1172 if (result->gid) 1173 *result->gid = id->idmap_id_u.gid; 1174 if (result->pid) 1175 *result->pid = id->idmap_id_u.gid; 1176 if (result->is_user) 1177 *result->is_user = 0; 1178 sid_prefix = kidmap_find_sid_prefix( 1179 mapping->id1.idmap_id_u.sid.prefix); 1180 if (*result->stat == IDMAP_SUCCESS && result->gid) 1181 kidmap_cache_add_gidbysid( 1182 cache, sid_prefix, 1183 mapping->id1.idmap_id_u.sid.rid, 1184 id->idmap_id_u.gid); 1185 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1186 kidmap_cache_add_gidbysid( 1187 cache, sid_prefix, 1188 mapping->id1.idmap_id_u.sid.rid, 1189 id->idmap_id_u.gid); 1190 break; 1191 1192 case IDMAP_SID: 1193 case IDMAP_USID: 1194 case IDMAP_GSID: 1195 sid_prefix = kidmap_find_sid_prefix( 1196 id->idmap_id_u.sid.prefix); 1197 if (result->sid_prefix && result->rid) { 1198 *result->sid_prefix = sid_prefix; 1199 *result->rid = id->idmap_id_u.sid.rid; 1200 } 1201 if (*result->stat == IDMAP_SUCCESS && 1202 mapping->id1.idtype == IDMAP_UID) 1203 kidmap_cache_add_sidbyuid( 1204 cache, sid_prefix, 1205 id->idmap_id_u.sid.rid, 1206 mapping->id1.idmap_id_u.uid); 1207 else if (*result->stat == IDMAP_SUCCESS && 1208 mapping->id1.idtype == IDMAP_GID) 1209 kidmap_cache_add_sidbygid( 1210 cache, sid_prefix, 1211 id->idmap_id_u.sid.rid, 1212 mapping->id1.idmap_id_u.gid); 1213 break; 1214 1215 default: 1216 *result->stat = IDMAP_ERR_NORESULT; 1217 if (result->uid) 1218 *result->uid = UID_NOBODY; 1219 if (result->gid) 1220 *result->gid = GID_NOBODY; 1221 if (result->pid) 1222 *result->pid = UID_NOBODY; 1223 if (result->is_user) 1224 *result->is_user = 1; 1225 if (result->sid_prefix) 1226 *result->sid_prefix = NULL; 1227 if (result->rid) 1228 *result->rid = 0; 1229 break; 1230 } 1231 } 1232 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1233 1234 /* Reset get_handle for new resquests */ 1235 get_handle->mapping_num = 0; 1236 return (status); 1237 1238 error: 1239 for (i = 0; i < get_handle->mapping_num; i++) { 1240 result = &get_handle->result[i]; 1241 1242 *result->stat = status; 1243 if (result->uid) 1244 *result->uid = UID_NOBODY; 1245 if (result->gid) 1246 *result->gid = GID_NOBODY; 1247 if (result->pid) 1248 *result->pid = UID_NOBODY; 1249 if (result->is_user) 1250 *result->is_user = 1; 1251 if (result->sid_prefix) 1252 *result->sid_prefix = NULL; 1253 if (result->rid) 1254 *result->rid = 0; 1255 } 1256 1257 /* Reset get_handle for new resquests */ 1258 get_handle->mapping_num = 0; 1259 return (status); 1260 } 1261 1262 1263 /* 1264 * Destroy the "get mapping" handle 1265 */ 1266 void 1267 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1268 { 1269 if (get_handle == NULL) 1270 return; 1271 1272 kmem_free(get_handle->mapping, 1273 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1274 get_handle->mapping = NULL; 1275 1276 kmem_free(get_handle->result, 1277 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1278 get_handle->result = NULL; 1279 1280 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1281 } 1282 1283 1284 static int 1285 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args, 1286 caddr_t args, xdrproc_t xdr_res, caddr_t res) 1287 { 1288 XDR xdr_ctx; 1289 struct rpc_msg reply_msg; 1290 char *inbuf_ptr = NULL; 1291 size_t inbuf_size = 4096; 1292 char *outbuf_ptr = NULL; 1293 size_t outbuf_size = 4096; 1294 size_t size; 1295 int status = 0; 1296 door_arg_t params; 1297 int retry = 0; 1298 struct rpc_msg call_msg; 1299 1300 params.rbuf = NULL; 1301 params.rsize = 0; 1302 1303 retry: 1304 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1305 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1306 1307 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1308 1309 call_msg.rm_call.cb_prog = IDMAP_PROG; 1310 call_msg.rm_call.cb_vers = IDMAP_V1; 1311 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id); 1312 1313 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1314 #ifdef DEBUG 1315 cmn_err(CE_WARN, "idmap: xdr encoding header error"); 1316 #endif /* DEBUG */ 1317 status = -1; 1318 goto exit; 1319 } 1320 1321 if (!xdr_uint32(&xdr_ctx, &op) || 1322 /* Auth none */ 1323 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1324 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1325 /* RPC args */ 1326 !xdr_args(&xdr_ctx, args)) { 1327 #ifdef DEBUG 1328 cmn_err(CE_WARN, "idmap: xdr encoding error"); 1329 #endif /* DEBUG */ 1330 if (retry > 2) { 1331 status = -1; 1332 goto exit; 1333 } 1334 retry++; 1335 if (inbuf_ptr) { 1336 kmem_free(inbuf_ptr, inbuf_size); 1337 inbuf_ptr = NULL; 1338 } 1339 if (outbuf_ptr) { 1340 kmem_free(outbuf_ptr, outbuf_size); 1341 outbuf_ptr = NULL; 1342 } 1343 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1344 #ifdef DEBUG 1345 cmn_err(CE_WARN, "idmap: xdr_sizeof error"); 1346 #endif /* DEBUG */ 1347 status = -1; 1348 goto exit; 1349 } 1350 inbuf_size = size + 1024; 1351 outbuf_size = size + 1024; 1352 goto retry; 1353 } 1354 1355 params.data_ptr = inbuf_ptr; 1356 params.data_size = XDR_GETPOS(&xdr_ctx); 1357 params.desc_ptr = NULL; 1358 params.desc_num = 0; 1359 params.rbuf = outbuf_ptr; 1360 params.rsize = outbuf_size; 1361 1362 if (kidmap_call_door(zs, ¶ms) != 0) { 1363 status = -1; 1364 goto exit; 1365 } 1366 1367 reply_msg.acpted_rply.ar_verf = _null_auth; 1368 reply_msg.acpted_rply.ar_results.where = res; 1369 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1370 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1371 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1372 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1373 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1374 status = -1; 1375 goto exit; 1376 } 1377 } else { 1378 #ifdef DEBUG 1379 cmn_err(CE_WARN, "idmap: xdr decoding reply message error"); 1380 #endif /* DEBUG */ 1381 status = -1; 1382 } 1383 1384 exit: 1385 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1386 kmem_free(params.rbuf, params.rsize); 1387 if (inbuf_ptr) 1388 kmem_free(inbuf_ptr, inbuf_size); 1389 if (outbuf_ptr) 1390 kmem_free(outbuf_ptr, outbuf_size); 1391 return (status); 1392 } 1393