1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Windows to Solaris Identity Mapping kernel API 29 * This module provides an API to map Windows SIDs to 30 * Solaris UID and GIDs. 31 */ 32 33 34 #include <sys/types.h> 35 #include <sys/ksynch.h> 36 #include <sys/door.h> 37 #include <rpc/rpc_msg.h> 38 #include <rpc/xdr.h> 39 #include <rpc/auth.h> 40 #include <rpc/rpc_sztypes.h> 41 #ifdef DEBUG 42 #include <sys/cmn_err.h> 43 #endif /* DEBUG */ 44 #include <sys/proc.h> 45 #include <sys/sunddi.h> 46 #include <sys/param.h> 47 #include <sys/atomic.h> 48 #include <sys/sysmacros.h> 49 #include <sys/disp.h> 50 #include <sys/kidmap.h> 51 #include <sys/zone.h> 52 #include <rpcsvc/idmap_prot.h> 53 #include "kidmap_priv.h" 54 55 56 /* 57 * Defined types 58 */ 59 60 61 /* 62 * This structure holds pointers for the 63 * batch mapping results. 64 */ 65 typedef struct idmap_get_res { 66 idmap_id_type idtype; 67 uid_t *uid; 68 gid_t *gid; 69 uid_t *pid; 70 int *is_user; 71 const char **sid_prefix; 72 uint32_t *rid; 73 idmap_stat *stat; 74 } idmap_get_res; 75 76 /* Batch mapping handle structure */ 77 struct idmap_get_handle { 78 struct idmap_zone_specific *zs; 79 int mapping_num; 80 int mapping_size; 81 idmap_mapping *mapping; 82 idmap_get_res *result; 83 }; 84 85 86 /* Zone specific data */ 87 typedef struct idmap_zone_specific { 88 zoneid_t zone_id; 89 kmutex_t zone_mutex; 90 idmap_cache_t cache; 91 door_handle_t door_handle; 92 int door_valid; 93 int door_retried; 94 uint32_t message_id; 95 } idmap_zone_specific_t; 96 97 98 99 /* 100 * Module global data 101 */ 102 103 static kmutex_t idmap_zone_mutex; 104 static zone_key_t idmap_zone_key; 105 106 107 /* 108 * Local function definitions 109 */ 110 111 112 static int 113 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, 114 xdrproc_t xdr_args, caddr_t args, 115 xdrproc_t xdr_res, caddr_t res); 116 117 static int 118 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg); 119 120 static idmap_zone_specific_t * 121 idmap_get_zone_specific(zone_t *zone); 122 123 124 125 int 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 * Notes: 894 * The output parameters will be set by idmap_get_mappings() 895 * The sid_prefix is copied. 896 */ 897 idmap_stat 898 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 899 uint32_t rid, uid_t *uid, idmap_stat *stat) 900 { 901 idmap_mapping *mapping; 902 idmap_get_res *result; 903 904 if (get_handle == NULL || sid_prefix == NULL || 905 uid == NULL || stat == NULL) 906 return (IDMAP_ERR_ARG); 907 908 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 909 rid, uid) == IDMAP_SUCCESS) { 910 *stat = IDMAP_SUCCESS; 911 return (IDMAP_SUCCESS); 912 } 913 914 /* Get a copy of sid_prefix */ 915 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 916 917 if (get_handle->mapping_num >= get_handle->mapping_size) 918 kidmap_get_extend(get_handle); 919 920 mapping = &get_handle->mapping[get_handle->mapping_num]; 921 mapping->flag = 0; 922 mapping->id1.idtype = IDMAP_SID; 923 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 924 mapping->id1.idmap_id_u.sid.rid = rid; 925 mapping->id2.idtype = IDMAP_UID; 926 927 result = &get_handle->result[get_handle->mapping_num]; 928 result->idtype = IDMAP_UID; 929 result->uid = uid; 930 result->gid = NULL; 931 result->pid = NULL; 932 result->sid_prefix = NULL; 933 result->rid = NULL; 934 result->is_user = NULL; 935 result->stat = stat; 936 937 get_handle->mapping_num++; 938 939 return (IDMAP_SUCCESS); 940 } 941 942 943 /* 944 * Given Domain SID and RID, get GID 945 * 946 * Input: 947 * sid_prefix - Domain SID in canonical form 948 * rid - RID 949 * 950 * Output: 951 * stat - status of the get request 952 * gid - POSIX GID if stat == IDMAP_SUCCESS 953 * 954 * Notes: 955 * The output parameters will be set by idmap_get_mappings() 956 * The sid_prefix is copied. 957 */ 958 idmap_stat 959 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 960 uint32_t rid, uid_t *gid, idmap_stat *stat) 961 { 962 idmap_mapping *mapping; 963 idmap_get_res *result; 964 965 if (get_handle == NULL || sid_prefix == NULL || 966 gid == NULL || stat == NULL) 967 return (IDMAP_ERR_ARG); 968 969 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 970 rid, gid) == IDMAP_SUCCESS) { 971 *stat = IDMAP_SUCCESS; 972 return (IDMAP_SUCCESS); 973 } 974 975 /* Get a copy of sid_prefix */ 976 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 977 978 if (get_handle->mapping_num >= get_handle->mapping_size) 979 kidmap_get_extend(get_handle); 980 981 mapping = &get_handle->mapping[get_handle->mapping_num]; 982 mapping->flag = 0; 983 mapping->id1.idtype = IDMAP_SID; 984 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 985 mapping->id1.idmap_id_u.sid.rid = rid; 986 mapping->id2.idtype = IDMAP_GID; 987 988 result = &get_handle->result[get_handle->mapping_num]; 989 result->idtype = IDMAP_GID; 990 result->uid = NULL; 991 result->gid = gid; 992 result->pid = NULL; 993 result->sid_prefix = NULL; 994 result->rid = NULL; 995 result->is_user = NULL; 996 result->stat = stat; 997 998 get_handle->mapping_num++; 999 1000 return (IDMAP_SUCCESS); 1001 } 1002 1003 1004 /* 1005 * Given Domain SID and RID, get Posix ID 1006 * 1007 * Input: 1008 * sid_prefix - Domain SID in canonical form 1009 * rid - RID 1010 * 1011 * Output: 1012 * stat - status of the get request 1013 * is_user - user or group 1014 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 1015 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 1016 * 1017 * Notes: 1018 * The output parameters will be set by idmap_get_mappings() 1019 * The sid_prefix is copied. 1020 */ 1021 idmap_stat 1022 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 1023 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 1024 { 1025 idmap_mapping *mapping; 1026 idmap_get_res *result; 1027 1028 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 1029 is_user == NULL || stat == NULL) 1030 return (IDMAP_ERR_ARG); 1031 1032 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 1033 rid, pid, is_user) == IDMAP_SUCCESS) { 1034 *stat = IDMAP_SUCCESS; 1035 return (IDMAP_SUCCESS); 1036 } 1037 1038 /* Get a copy of sid_prefix */ 1039 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 1040 1041 if (get_handle->mapping_num >= get_handle->mapping_size) 1042 kidmap_get_extend(get_handle); 1043 1044 mapping = &get_handle->mapping[get_handle->mapping_num]; 1045 mapping->flag = 0; 1046 mapping->id1.idtype = IDMAP_SID; 1047 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 1048 mapping->id1.idmap_id_u.sid.rid = rid; 1049 mapping->id2.idtype = IDMAP_POSIXID; 1050 1051 result = &get_handle->result[get_handle->mapping_num]; 1052 result->idtype = IDMAP_POSIXID; 1053 result->uid = NULL; 1054 result->gid = NULL; 1055 result->pid = pid; 1056 result->sid_prefix = NULL; 1057 result->rid = NULL; 1058 result->is_user = is_user; 1059 result->stat = stat; 1060 1061 get_handle->mapping_num++; 1062 1063 return (IDMAP_SUCCESS); 1064 } 1065 1066 1067 /* 1068 * Given UID, get SID and RID 1069 * 1070 * Input: 1071 * uid - POSIX UID 1072 * 1073 * Output: 1074 * stat - status of the get request 1075 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1076 * rid - RID (if stat == IDMAP_SUCCESS) 1077 * 1078 * Note: The output parameters will be set by idmap_get_mappings() 1079 */ 1080 idmap_stat 1081 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 1082 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1083 { 1084 idmap_mapping *mapping; 1085 idmap_get_res *result; 1086 1087 if (get_handle == NULL || sid_prefix == NULL || 1088 rid == NULL || stat == NULL) 1089 return (IDMAP_ERR_ARG); 1090 1091 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache, 1092 sid_prefix, rid, uid) == IDMAP_SUCCESS) { 1093 *stat = IDMAP_SUCCESS; 1094 return (IDMAP_SUCCESS); 1095 } 1096 1097 if (get_handle->mapping_num >= get_handle->mapping_size) 1098 kidmap_get_extend(get_handle); 1099 1100 mapping = &get_handle->mapping[get_handle->mapping_num]; 1101 mapping->flag = 0; 1102 mapping->id1.idtype = IDMAP_UID; 1103 mapping->id1.idmap_id_u.uid = uid; 1104 mapping->id2.idtype = IDMAP_SID; 1105 1106 result = &get_handle->result[get_handle->mapping_num]; 1107 result->idtype = IDMAP_SID; 1108 result->uid = NULL; 1109 result->gid = NULL; 1110 result->pid = NULL; 1111 result->sid_prefix = sid_prefix; 1112 result->rid = rid; 1113 result->is_user = NULL; 1114 result->stat = stat; 1115 1116 get_handle->mapping_num++; 1117 1118 return (IDMAP_SUCCESS); 1119 } 1120 1121 1122 /* 1123 * Given GID, get SID and RID 1124 * 1125 * Input: 1126 * gid - POSIX GID 1127 * 1128 * Output: 1129 * stat - status of the get request 1130 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1131 * rid - RID (if stat == IDMAP_SUCCESS) 1132 * 1133 * Note: The output parameters will be set by idmap_get_mappings() 1134 */ 1135 idmap_stat 1136 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 1137 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1138 { 1139 idmap_mapping *mapping; 1140 idmap_get_res *result; 1141 1142 if (get_handle == NULL || sid_prefix == NULL || 1143 rid == NULL || stat == NULL) 1144 return (IDMAP_ERR_ARG); 1145 1146 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache, 1147 sid_prefix, rid, gid) == IDMAP_SUCCESS) { 1148 *stat = IDMAP_SUCCESS; 1149 return (IDMAP_SUCCESS); 1150 } 1151 1152 if (get_handle->mapping_num >= get_handle->mapping_size) 1153 kidmap_get_extend(get_handle); 1154 1155 mapping = &get_handle->mapping[get_handle->mapping_num]; 1156 mapping->flag = 0; 1157 mapping->id1.idtype = IDMAP_GID; 1158 mapping->id1.idmap_id_u.gid = gid; 1159 mapping->id2.idtype = IDMAP_SID; 1160 1161 result = &get_handle->result[get_handle->mapping_num]; 1162 result->idtype = IDMAP_SID; 1163 result->uid = NULL; 1164 result->gid = NULL; 1165 result->pid = NULL; 1166 result->sid_prefix = sid_prefix; 1167 result->rid = rid; 1168 result->is_user = NULL; 1169 result->stat = stat; 1170 1171 get_handle->mapping_num++; 1172 1173 return (IDMAP_SUCCESS); 1174 } 1175 1176 1177 /* 1178 * Process the batched "get mapping" requests. The results (i.e. 1179 * status and identity) will be available in the data areas 1180 * provided by individual requests. 1181 * 1182 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1183 * return and the UID or UID result is set to "nobody" 1184 */ 1185 1186 idmap_stat 1187 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1188 { 1189 idmap_mapping_batch rpc_args; 1190 idmap_ids_res rpc_res; 1191 uint32_t op = IDMAP_GET_MAPPED_IDS; 1192 idmap_mapping *request; 1193 idmap_get_res *result; 1194 idmap_id *id; 1195 int status; 1196 int i; 1197 const char *sid_prefix; 1198 int is_user; 1199 idmap_cache_t *cache; 1200 int direction; 1201 1202 if (get_handle == NULL) 1203 return (IDMAP_ERR_ARG); 1204 1205 if (get_handle->mapping_num == 0) 1206 return (IDMAP_SUCCESS); 1207 cache = &get_handle->zs->cache; 1208 1209 bzero(&rpc_res, sizeof (idmap_ids_res)); 1210 1211 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num; 1212 rpc_args.idmap_mapping_batch_val = get_handle->mapping; 1213 1214 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch, 1215 (caddr_t)&rpc_args, xdr_idmap_ids_res, 1216 (caddr_t)&rpc_res) != 0) { 1217 /* Door call failed */ 1218 status = IDMAP_ERR_NOMAPPING; 1219 goto error; 1220 } 1221 1222 status = rpc_res.retcode; 1223 if (status != IDMAP_SUCCESS) { 1224 /* RPC returned idmap error code */ 1225 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1226 goto error; 1227 } 1228 1229 for (i = 0; i < get_handle->mapping_num; i++) { 1230 request = &get_handle->mapping[i]; 1231 result = &get_handle->result[i]; 1232 1233 if (i >= rpc_res.ids.ids_len) { 1234 *result->stat = IDMAP_ERR_NOMAPPING; 1235 if (result->uid) 1236 *result->uid = UID_NOBODY; 1237 if (result->gid) 1238 *result->gid = GID_NOBODY; 1239 if (result->pid) 1240 *result->pid = UID_NOBODY; 1241 if (result->is_user) 1242 *result->is_user = 1; 1243 if (result->sid_prefix) 1244 *result->sid_prefix = NULL; 1245 if (result->rid) 1246 *result->rid = 0; 1247 continue; 1248 } 1249 1250 *result->stat = rpc_res.ids.ids_val[i].retcode; 1251 1252 id = &rpc_res.ids.ids_val[i].id; 1253 direction = rpc_res.ids.ids_val[i].direction; 1254 1255 switch (id->idtype) { 1256 case IDMAP_UID: 1257 if (result->uid) 1258 *result->uid = id->idmap_id_u.uid; 1259 if (result->pid) 1260 *result->pid = id->idmap_id_u.uid; 1261 if (result->is_user) 1262 *result->is_user = 1; 1263 sid_prefix = kidmap_find_sid_prefix( 1264 request->id1.idmap_id_u.sid.prefix); 1265 if (*result->stat == IDMAP_SUCCESS && result->uid) 1266 kidmap_cache_add_sid2uid( 1267 cache, sid_prefix, 1268 request->id1.idmap_id_u.sid.rid, 1269 id->idmap_id_u.uid, 1270 direction); 1271 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1272 kidmap_cache_add_sid2pid( 1273 cache, sid_prefix, 1274 request->id1.idmap_id_u.sid.rid, 1275 id->idmap_id_u.uid, 1, 1276 direction); 1277 break; 1278 1279 case IDMAP_GID: 1280 if (result->gid) 1281 *result->gid = id->idmap_id_u.gid; 1282 if (result->pid) 1283 *result->pid = id->idmap_id_u.gid; 1284 if (result->is_user) 1285 *result->is_user = 0; 1286 sid_prefix = kidmap_find_sid_prefix( 1287 request->id1.idmap_id_u.sid.prefix); 1288 if (*result->stat == IDMAP_SUCCESS && result->gid) 1289 kidmap_cache_add_sid2gid( 1290 cache, sid_prefix, 1291 request->id1.idmap_id_u.sid.rid, 1292 id->idmap_id_u.gid, 1293 direction); 1294 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1295 kidmap_cache_add_sid2pid( 1296 cache, sid_prefix, 1297 request->id1.idmap_id_u.sid.rid, 1298 id->idmap_id_u.gid, 0, 1299 direction); 1300 break; 1301 1302 case IDMAP_SID: 1303 case IDMAP_USID: 1304 case IDMAP_GSID: 1305 sid_prefix = kidmap_find_sid_prefix( 1306 id->idmap_id_u.sid.prefix); 1307 if (result->sid_prefix && result->rid) { 1308 *result->sid_prefix = sid_prefix; 1309 *result->rid = id->idmap_id_u.sid.rid; 1310 } 1311 if (*result->stat == IDMAP_SUCCESS && 1312 request->id1.idtype == IDMAP_UID) 1313 kidmap_cache_add_sid2uid( 1314 cache, sid_prefix, 1315 id->idmap_id_u.sid.rid, 1316 request->id1.idmap_id_u.uid, 1317 direction); 1318 else if (*result->stat == IDMAP_SUCCESS && 1319 request->id1.idtype == IDMAP_GID) 1320 kidmap_cache_add_sid2gid( 1321 cache, sid_prefix, 1322 id->idmap_id_u.sid.rid, 1323 request->id1.idmap_id_u.gid, 1324 direction); 1325 break; 1326 1327 default: 1328 *result->stat = IDMAP_ERR_NORESULT; 1329 if (result->uid) 1330 *result->uid = UID_NOBODY; 1331 if (result->gid) 1332 *result->gid = GID_NOBODY; 1333 if (result->pid) 1334 *result->pid = UID_NOBODY; 1335 if (result->is_user) 1336 *result->is_user = 1; 1337 if (result->sid_prefix) 1338 *result->sid_prefix = NULL; 1339 if (result->rid) 1340 *result->rid = 0; 1341 break; 1342 } 1343 } 1344 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1345 1346 /* Reset get_handle for new resquests */ 1347 get_handle->mapping_num = 0; 1348 return (status); 1349 1350 error: 1351 for (i = 0; i < get_handle->mapping_num; i++) { 1352 result = &get_handle->result[i]; 1353 1354 *result->stat = status; 1355 if (result->uid) 1356 *result->uid = UID_NOBODY; 1357 if (result->gid) 1358 *result->gid = GID_NOBODY; 1359 if (result->pid) 1360 *result->pid = UID_NOBODY; 1361 if (result->is_user) 1362 *result->is_user = 1; 1363 if (result->sid_prefix) 1364 *result->sid_prefix = NULL; 1365 if (result->rid) 1366 *result->rid = 0; 1367 } 1368 1369 /* Reset get_handle for new resquests */ 1370 get_handle->mapping_num = 0; 1371 return (status); 1372 } 1373 1374 1375 /* 1376 * Destroy the "get mapping" handle 1377 */ 1378 void 1379 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1380 { 1381 if (get_handle == NULL) 1382 return; 1383 1384 kmem_free(get_handle->mapping, 1385 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1386 get_handle->mapping = NULL; 1387 1388 kmem_free(get_handle->result, 1389 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1390 get_handle->result = NULL; 1391 1392 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1393 } 1394 1395 1396 static int 1397 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args, 1398 caddr_t args, xdrproc_t xdr_res, caddr_t res) 1399 { 1400 XDR xdr_ctx; 1401 struct rpc_msg reply_msg; 1402 char *inbuf_ptr = NULL; 1403 size_t inbuf_size = 4096; 1404 char *outbuf_ptr = NULL; 1405 size_t outbuf_size = 4096; 1406 size_t size; 1407 int status = 0; 1408 door_arg_t params; 1409 int retry = 0; 1410 struct rpc_msg call_msg; 1411 1412 params.rbuf = NULL; 1413 params.rsize = 0; 1414 1415 retry: 1416 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1417 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1418 1419 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1420 1421 call_msg.rm_call.cb_prog = IDMAP_PROG; 1422 call_msg.rm_call.cb_vers = IDMAP_V1; 1423 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id); 1424 1425 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1426 #ifdef DEBUG 1427 zcmn_err(zs->zone_id, CE_WARN, 1428 "idmap: xdr encoding header error"); 1429 #endif /* DEBUG */ 1430 status = -1; 1431 goto exit; 1432 } 1433 1434 if (!xdr_uint32(&xdr_ctx, &op) || 1435 /* Auth none */ 1436 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1437 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1438 /* RPC args */ 1439 !xdr_args(&xdr_ctx, args)) { 1440 #ifdef DEBUG 1441 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error"); 1442 #endif /* DEBUG */ 1443 if (retry > 2) { 1444 status = -1; 1445 goto exit; 1446 } 1447 retry++; 1448 if (inbuf_ptr) { 1449 kmem_free(inbuf_ptr, inbuf_size); 1450 inbuf_ptr = NULL; 1451 } 1452 if (outbuf_ptr) { 1453 kmem_free(outbuf_ptr, outbuf_size); 1454 outbuf_ptr = NULL; 1455 } 1456 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1457 #ifdef DEBUG 1458 zcmn_err(zs->zone_id, CE_WARN, 1459 "idmap: xdr_sizeof error"); 1460 #endif /* DEBUG */ 1461 status = -1; 1462 goto exit; 1463 } 1464 inbuf_size = size + 1024; 1465 outbuf_size = size + 1024; 1466 goto retry; 1467 } 1468 1469 params.data_ptr = inbuf_ptr; 1470 params.data_size = XDR_GETPOS(&xdr_ctx); 1471 params.desc_ptr = NULL; 1472 params.desc_num = 0; 1473 params.rbuf = outbuf_ptr; 1474 params.rsize = outbuf_size; 1475 1476 if (kidmap_call_door(zs, ¶ms) != 0) { 1477 status = -1; 1478 goto exit; 1479 } 1480 1481 reply_msg.acpted_rply.ar_verf = _null_auth; 1482 reply_msg.acpted_rply.ar_results.where = res; 1483 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1484 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1485 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1486 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1487 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1488 status = -1; 1489 goto exit; 1490 } 1491 } else { 1492 #ifdef DEBUG 1493 zcmn_err(zs->zone_id, CE_WARN, 1494 "idmap: xdr decoding reply message error"); 1495 #endif /* DEBUG */ 1496 status = -1; 1497 } 1498 1499 exit: 1500 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1501 kmem_free(params.rbuf, params.rsize); 1502 if (inbuf_ptr) 1503 kmem_free(inbuf_ptr, inbuf_size); 1504 if (outbuf_ptr) 1505 kmem_free(outbuf_ptr, outbuf_size); 1506 return (status); 1507 } 1508