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, 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 || zs->door_handle != dh) { 164 mutex_exit(&zs->zone_mutex); 165 return (EINVAL); 166 } 167 168 door_ki_rele(zs->door_handle); 169 170 zs->door_valid = 0; 171 zs->door_retried = 0; 172 mutex_exit(&zs->zone_mutex); 173 174 return (0); 175 } 176 177 178 /* 179 * IMPORTANT. This function idmap_get_cache_data() is project 180 * private and is for use of the test system only and should 181 * not be used for other purposes. 182 */ 183 void 184 idmap_get_cache_data(zone_t *zone, size_t *uidbysid, size_t *gidbysid, 185 size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid) 186 { 187 idmap_zone_specific_t *zs; 188 189 zs = idmap_get_zone_specific(zone); 190 191 kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid, 192 pidbysid, sidbyuid, sidbygid); 193 } 194 195 static int 196 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg) 197 { 198 door_handle_t dh; 199 door_info_t di; 200 int status = 0; 201 int num_retries = 5; 202 int door_retried = 0; 203 204 retry: 205 mutex_enter(&zs->zone_mutex); 206 if (zs->door_valid) { 207 dh = zs->door_handle; 208 door_ki_hold(dh); 209 } else { 210 dh = NULL; 211 door_retried = zs->door_retried; 212 } 213 mutex_exit(&zs->zone_mutex); 214 215 if (dh == NULL) { 216 /* The door has been retried before so dont wait */ 217 if (door_retried) 218 return (-1); 219 220 /* 221 * There is no door handle yet. Give 222 * smf a chance to restart idmapd 223 */ 224 if (num_retries-- > 0) { 225 delay(hz); 226 goto retry; 227 } 228 229 #ifdef DEBUG 230 zcmn_err(zs->zone_id, CE_WARN, 231 "idmap: Error no registered door to call the " 232 "idmap daemon\n"); 233 #endif 234 mutex_enter(&zs->zone_mutex); 235 if (!zs->door_valid) 236 zs->door_retried = 1; 237 mutex_exit(&zs->zone_mutex); 238 239 return (-1); 240 } 241 242 status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0); 243 244 switch (status) { 245 case 0: /* Success */ 246 door_ki_rele(dh); 247 return (0); 248 249 case EINTR: 250 /* If we took an interrupt we have to bail out. */ 251 if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) { 252 door_ki_rele(dh); 253 #ifdef DEBUG 254 zcmn_err(zs->zone_id, CE_WARN, 255 "idmap: Interrupted\n"); 256 #endif 257 return (-1); 258 } 259 /* 260 * Just retry and see what happens. 261 */ 262 /* FALLTHROUGH */ 263 264 case EAGAIN: 265 /* A resouce problem */ 266 door_ki_rele(dh); 267 /* Back off before retrying */ 268 #ifdef DEBUG 269 zcmn_err(zs->zone_id, CE_WARN, 270 "idmap: Door call returned error %d. Retrying\n", status); 271 #endif /* DEBUG */ 272 delay(hz); 273 goto retry; 274 275 case EBADF: 276 /* Stale door handle. See if smf restarts the daemon. */ 277 door_ki_rele(dh); 278 mutex_enter(&zs->zone_mutex); 279 if (zs->door_valid && dh == zs->door_handle) { 280 zs->door_valid = 0; 281 zs->door_retried = 0; 282 door_ki_rele(zs->door_handle); 283 } 284 mutex_exit(&zs->zone_mutex); 285 /* Back off before retrying */ 286 #ifdef DEBUG 287 zcmn_err(zs->zone_id, CE_WARN, 288 "idmap: Door call returned error %d. Retrying\n", status); 289 #endif /* DEBUG */ 290 delay(hz); 291 goto retry; 292 293 default: 294 /* Unknown error */ 295 #ifdef DEBUG 296 zcmn_err(zs->zone_id, CE_WARN, 297 "idmap: Door call returned error %d.\n", status); 298 #endif /* DEBUG */ 299 door_ki_rele(dh); 300 return (-1); 301 } 302 } 303 304 305 static idmap_zone_specific_t * 306 idmap_get_zone_specific(zone_t *zone) 307 { 308 idmap_zone_specific_t *zs; 309 310 ASSERT(zone != NULL); 311 312 zs = zone_getspecific(idmap_zone_key, zone); 313 if (zs != NULL) 314 return (zs); 315 316 mutex_enter(&idmap_zone_mutex); 317 zs = zone_getspecific(idmap_zone_key, zone); 318 if (zs == NULL) { 319 zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP); 320 mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL); 321 kidmap_cache_create(&zs->cache); 322 zs->zone_id = zone->zone_id; 323 (void) zone_setspecific(idmap_zone_key, zone, zs); 324 mutex_exit(&idmap_zone_mutex); 325 return (zs); 326 } 327 mutex_exit(&idmap_zone_mutex); 328 329 return (zs); 330 } 331 332 333 static void 334 /* ARGSUSED */ 335 idmap_zone_destroy(zoneid_t zone_id, void *arg) 336 { 337 idmap_zone_specific_t *zs = arg; 338 if (zs != NULL) { 339 kidmap_cache_delete(&zs->cache); 340 if (zs->door_valid) { 341 door_ki_rele(zs->door_handle); 342 } 343 mutex_destroy(&zs->zone_mutex); 344 kmem_free(zs, sizeof (idmap_zone_specific_t)); 345 } 346 } 347 348 349 int 350 kidmap_start(void) 351 { 352 mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL); 353 zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy); 354 kidmap_sid_prefix_store_init(); 355 356 return (0); 357 } 358 359 360 int 361 kidmap_stop(void) 362 { 363 return (EBUSY); 364 } 365 366 367 /* 368 * idmap_get_door 369 * 370 * This is called by the system call allocids() to get the door for the 371 * given zone. 372 */ 373 door_handle_t 374 idmap_get_door(zone_t *zone) 375 { 376 door_handle_t dh = NULL; 377 idmap_zone_specific_t *zs; 378 379 zs = idmap_get_zone_specific(zone); 380 381 mutex_enter(&zs->zone_mutex); 382 if (zs->door_valid) { 383 dh = zs->door_handle; 384 door_ki_hold(dh); 385 } 386 mutex_exit(&zs->zone_mutex); 387 return (dh); 388 } 389 390 391 /* 392 * idmap_purge_cache 393 * 394 * This is called by the system call allocids() to purge the cache for the 395 * given zone. 396 */ 397 void 398 idmap_purge_cache(zone_t *zone) 399 { 400 idmap_zone_specific_t *zs; 401 402 zs = idmap_get_zone_specific(zone); 403 404 kidmap_cache_purge(&zs->cache); 405 } 406 407 408 409 410 /* 411 * Given Domain SID and RID, get UID 412 * 413 * Input: 414 * sid_prefix - Domain SID in canonical form 415 * rid - RID 416 * 417 * Output: 418 * uid - POSIX UID if return == IDMAP_SUCCESS 419 * 420 * Return: 421 * Success return IDMAP_SUCCESS else IDMAP error 422 */ 423 idmap_stat 424 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 425 uid_t *uid) 426 { 427 idmap_zone_specific_t *zs; 428 idmap_mapping_batch args; 429 idmap_mapping mapping; 430 idmap_ids_res results; 431 uint32_t op = IDMAP_GET_MAPPED_IDS; 432 const char *new_sid_prefix; 433 idmap_stat status; 434 435 if (sid_prefix == NULL || uid == NULL) 436 return (IDMAP_ERR_ARG); 437 438 zs = idmap_get_zone_specific(zone); 439 440 if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid) 441 == IDMAP_SUCCESS) 442 return (IDMAP_SUCCESS); 443 444 bzero(&mapping, sizeof (idmap_mapping)); 445 mapping.id1.idtype = IDMAP_SID; 446 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 447 mapping.id1.idmap_id_u.sid.rid = rid; 448 mapping.id2.idtype = IDMAP_UID; 449 450 bzero(&results, sizeof (idmap_ids_res)); 451 452 args.idmap_mapping_batch_len = 1; 453 args.idmap_mapping_batch_val = &mapping; 454 455 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 456 (caddr_t)&args, xdr_idmap_ids_res, 457 (caddr_t)&results) == 0) { 458 /* Door call succeded */ 459 if (results.retcode != IDMAP_SUCCESS) { 460 status = results.retcode; 461 *uid = UID_NOBODY; 462 } else if (results.ids.ids_len >= 1 && 463 results.ids.ids_val[0].id.idtype == IDMAP_UID) { 464 status = results.ids.ids_val[0].retcode; 465 *uid = results.ids.ids_val[0].id.idmap_id_u.uid; 466 if (status == IDMAP_SUCCESS) { 467 new_sid_prefix = kidmap_find_sid_prefix( 468 sid_prefix); 469 kidmap_cache_add_sid2uid(&zs->cache, 470 new_sid_prefix, rid, *uid, 471 results.ids.ids_val[0].direction); 472 } 473 } else { 474 status = IDMAP_ERR_NOMAPPING; 475 *uid = UID_NOBODY; 476 } 477 xdr_free(xdr_idmap_ids_res, (char *)&results); 478 } else { 479 /* Door call failed */ 480 status = IDMAP_ERR_NOMAPPING; 481 *uid = UID_NOBODY; 482 } 483 return (status); 484 } 485 486 487 /* 488 * Given Domain SID and RID, get GID 489 * 490 * Input: 491 * sid_prefix - Domain SID in canonical form 492 * rid - RID 493 * 494 * Output: 495 * gid - POSIX UID if return == IDMAP_SUCCESS 496 * 497 * Return: 498 * Success return IDMAP_SUCCESS else IDMAP error 499 */ 500 idmap_stat 501 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 502 gid_t *gid) 503 { 504 idmap_zone_specific_t *zs; 505 idmap_mapping_batch args; 506 idmap_mapping mapping; 507 idmap_ids_res results; 508 uint32_t op = IDMAP_GET_MAPPED_IDS; 509 const char *new_sid_prefix; 510 idmap_stat status; 511 512 if (sid_prefix == NULL || gid == NULL) 513 return (IDMAP_ERR_ARG); 514 515 zs = idmap_get_zone_specific(zone); 516 517 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid) 518 == IDMAP_SUCCESS) 519 return (IDMAP_SUCCESS); 520 521 bzero(&mapping, sizeof (idmap_mapping)); 522 mapping.id1.idtype = IDMAP_SID; 523 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 524 mapping.id1.idmap_id_u.sid.rid = rid; 525 mapping.id2.idtype = IDMAP_GID; 526 527 bzero(&results, sizeof (idmap_ids_res)); 528 529 args.idmap_mapping_batch_len = 1; 530 args.idmap_mapping_batch_val = &mapping; 531 532 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 533 (caddr_t)&args, xdr_idmap_ids_res, 534 (caddr_t)&results) == 0) { 535 /* Door call succeded */ 536 if (results.retcode != IDMAP_SUCCESS) { 537 status = results.retcode; 538 *gid = GID_NOBODY; 539 } else if (results.ids.ids_len >= 1 && 540 results.ids.ids_val[0].id.idtype == IDMAP_GID) { 541 status = results.ids.ids_val[0].retcode; 542 *gid = results.ids.ids_val[0].id.idmap_id_u.gid; 543 if (status == IDMAP_SUCCESS) { 544 new_sid_prefix = kidmap_find_sid_prefix( 545 sid_prefix); 546 kidmap_cache_add_sid2gid(&zs->cache, 547 new_sid_prefix, rid, *gid, 548 results.ids.ids_val[0].direction); 549 } 550 } else { 551 status = IDMAP_ERR_NOMAPPING; 552 *gid = GID_NOBODY; 553 } 554 xdr_free(xdr_idmap_ids_res, (char *)&results); 555 } else { 556 /* Door call failed */ 557 status = IDMAP_ERR_NOMAPPING; 558 *gid = GID_NOBODY; 559 } 560 return (status); 561 } 562 563 /* 564 * Given Domain SID and RID, get Posix ID 565 * 566 * Input: 567 * sid_prefix - Domain SID in canonical form 568 * rid - RID 569 * 570 * Output: 571 * pid - POSIX ID if return == IDMAP_SUCCESS 572 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS 573 * 574 * Return: 575 * Success return IDMAP_SUCCESS else IDMAP error 576 */ 577 idmap_stat 578 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 579 uid_t *pid, int *is_user) 580 { 581 idmap_zone_specific_t *zs; 582 idmap_mapping_batch args; 583 idmap_mapping mapping; 584 idmap_ids_res results; 585 uint32_t op = IDMAP_GET_MAPPED_IDS; 586 const char *new_sid_prefix; 587 idmap_stat status; 588 589 if (sid_prefix == NULL || pid == NULL || is_user == NULL) 590 return (IDMAP_ERR_ARG); 591 592 zs = idmap_get_zone_specific(zone); 593 594 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid, 595 is_user) == IDMAP_SUCCESS) 596 return (IDMAP_SUCCESS); 597 598 bzero(&mapping, sizeof (idmap_mapping)); 599 mapping.id1.idtype = IDMAP_SID; 600 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 601 mapping.id1.idmap_id_u.sid.rid = rid; 602 mapping.id2.idtype = IDMAP_POSIXID; 603 604 bzero(&results, sizeof (idmap_ids_res)); 605 606 args.idmap_mapping_batch_len = 1; 607 args.idmap_mapping_batch_val = &mapping; 608 609 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 610 (caddr_t)&args, xdr_idmap_ids_res, 611 (caddr_t)&results) == 0) { 612 /* Door call succeded */ 613 if (results.retcode != IDMAP_SUCCESS) { 614 status = results.retcode; 615 *is_user = 1; 616 *pid = UID_NOBODY; 617 } else if (results.ids.ids_len >= 1 && ( 618 results.ids.ids_val[0].id.idtype == IDMAP_UID || 619 results.ids.ids_val[0].id.idtype == IDMAP_GID)) { 620 status = results.ids.ids_val[0].retcode; 621 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) { 622 *is_user = 1; 623 *pid = results.ids.ids_val[0].id.idmap_id_u.uid; 624 } else { 625 *is_user = 0; 626 *pid = results.ids.ids_val[0].id.idmap_id_u.gid; 627 } 628 if (status == IDMAP_SUCCESS) { 629 new_sid_prefix = kidmap_find_sid_prefix( 630 sid_prefix); 631 kidmap_cache_add_sid2pid(&zs->cache, 632 new_sid_prefix, rid, *pid, 633 *is_user, 634 results.ids.ids_val[0].direction); 635 } 636 } else { 637 status = IDMAP_ERR_NOMAPPING; 638 *is_user = 1; 639 *pid = UID_NOBODY; 640 } 641 xdr_free(xdr_idmap_ids_res, (char *)&results); 642 } else { 643 /* Door call failed */ 644 status = IDMAP_ERR_NOMAPPING; 645 *is_user = 1; 646 *pid = UID_NOBODY; 647 } 648 return (status); 649 } 650 651 652 /* 653 * Given UID, get Domain SID and RID 654 * 655 * Input: 656 * uid - Posix UID 657 * 658 * Output: 659 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 660 * rid - RID if return == IDMAP_SUCCESS 661 * 662 * Return: 663 * Success return IDMAP_SUCCESS else IDMAP error 664 */ 665 idmap_stat 666 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix, 667 uint32_t *rid) 668 { 669 idmap_zone_specific_t *zs; 670 idmap_mapping_batch args; 671 idmap_mapping mapping; 672 idmap_ids_res results; 673 uint32_t op = IDMAP_GET_MAPPED_IDS; 674 idmap_stat status; 675 time_t entry_ttl; 676 idmap_id *id; 677 678 if (sid_prefix == NULL || rid == NULL) 679 return (IDMAP_ERR_ARG); 680 681 zs = idmap_get_zone_specific(zone); 682 683 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid) 684 == IDMAP_SUCCESS) { 685 return (IDMAP_SUCCESS); 686 } 687 688 bzero(&mapping, sizeof (idmap_mapping)); 689 mapping.id1.idtype = IDMAP_UID; 690 mapping.id1.idmap_id_u.uid = uid; 691 mapping.id2.idtype = IDMAP_SID; 692 693 bzero(&results, sizeof (idmap_ids_res)); 694 695 args.idmap_mapping_batch_len = 1; 696 args.idmap_mapping_batch_val = &mapping; 697 698 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 699 (caddr_t)&args, xdr_idmap_ids_res, 700 (caddr_t)&results) == 0) { 701 /* Door call succeded */ 702 if (results.retcode != IDMAP_SUCCESS) { 703 status = results.retcode; 704 *rid = 0; 705 *sid_prefix = NULL; 706 } else if (results.ids.ids_len >= 1 && 707 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 708 results.ids.ids_val[0].id.idtype == IDMAP_USID || 709 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 710 status = results.ids.ids_val[0].retcode; 711 id = &results.ids.ids_val[0].id; 712 *sid_prefix = kidmap_find_sid_prefix( 713 id->idmap_id_u.sid.prefix); 714 *rid = id->idmap_id_u.sid.rid; 715 if (status == IDMAP_SUCCESS) { 716 kidmap_cache_add_sid2uid(&zs->cache, 717 *sid_prefix, *rid, uid, 718 results.ids.ids_val[0].direction); 719 } 720 } else { 721 status = IDMAP_ERR_NOMAPPING; 722 *rid = 0; 723 *sid_prefix = NULL; 724 } 725 xdr_free(xdr_idmap_ids_res, (char *)&results); 726 } else { 727 /* Door call failed */ 728 status = IDMAP_ERR_NOMAPPING; 729 *rid = 0; 730 *sid_prefix = NULL; 731 } 732 return (status); 733 } 734 735 736 /* 737 * Given GID, get Domain SID and RID 738 * 739 * Input: 740 * gid - Posix GID 741 * 742 * Output: 743 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 744 * rid - RID if return == IDMAP_SUCCESS 745 * 746 * Return: 747 * Success return IDMAP_SUCCESS else IDMAP error 748 */ 749 idmap_stat 750 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix, 751 uint32_t *rid) 752 { 753 idmap_zone_specific_t *zs; 754 idmap_mapping_batch args; 755 idmap_mapping mapping; 756 idmap_ids_res results; 757 uint32_t op = IDMAP_GET_MAPPED_IDS; 758 idmap_stat status; 759 idmap_id *id; 760 761 if (sid_prefix == NULL || rid == NULL) 762 return (IDMAP_ERR_ARG); 763 764 zs = idmap_get_zone_specific(zone); 765 766 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid) 767 == IDMAP_SUCCESS) { 768 return (IDMAP_SUCCESS); 769 } 770 771 bzero(&mapping, sizeof (idmap_mapping)); 772 mapping.id1.idtype = IDMAP_GID; 773 mapping.id1.idmap_id_u.uid = gid; 774 mapping.id2.idtype = IDMAP_SID; 775 776 bzero(&results, sizeof (idmap_ids_res)); 777 778 args.idmap_mapping_batch_len = 1; 779 args.idmap_mapping_batch_val = &mapping; 780 781 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 782 (caddr_t)&args, xdr_idmap_ids_res, 783 (caddr_t)&results) == 0) { 784 /* Door call succeded */ 785 if (results.retcode != IDMAP_SUCCESS) { 786 status = results.retcode; 787 *rid = 0; 788 *sid_prefix = NULL; 789 } else if (results.ids.ids_len >= 1 && 790 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 791 results.ids.ids_val[0].id.idtype == IDMAP_USID || 792 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 793 status = results.ids.ids_val[0].retcode; 794 id = &results.ids.ids_val[0].id; 795 *sid_prefix = kidmap_find_sid_prefix( 796 id->idmap_id_u.sid.prefix); 797 *rid = id->idmap_id_u.sid.rid; 798 if (status == IDMAP_SUCCESS) { 799 kidmap_cache_add_sid2gid(&zs->cache, 800 *sid_prefix, *rid, gid, 801 results.ids.ids_val[0].direction); 802 } 803 } else { 804 status = IDMAP_ERR_NOMAPPING; 805 *rid = 0; 806 *sid_prefix = NULL; 807 } 808 xdr_free(xdr_idmap_ids_res, (char *)&results); 809 } else { 810 /* Door call failed */ 811 status = IDMAP_ERR_NOMAPPING; 812 *rid = 0; 813 *sid_prefix = NULL; 814 } 815 return (status); 816 } 817 818 /* 819 * Create handle to get SID to UID/GID mapping entries 820 * 821 * Input: 822 * none 823 * Return: 824 * get_handle 825 * 826 */ 827 idmap_get_handle_t * 828 kidmap_get_create(zone_t *zone) 829 { 830 idmap_zone_specific_t *zs; 831 idmap_get_handle_t *handle; 832 #define INIT_MAPPING_SIZE 32 833 834 zs = idmap_get_zone_specific(zone); 835 836 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP); 837 838 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) * 839 INIT_MAPPING_SIZE, KM_SLEEP); 840 841 handle->result = kmem_zalloc((sizeof (idmap_get_res)) * 842 INIT_MAPPING_SIZE, KM_SLEEP); 843 handle->mapping_size = INIT_MAPPING_SIZE; 844 handle->zs = zs; 845 846 return (handle); 847 } 848 849 /* 850 * Internal routine to extend a "get_handle" 851 */ 852 static void 853 kidmap_get_extend(idmap_get_handle_t *get_handle) 854 { 855 idmap_mapping *mapping; 856 idmap_get_res *result; 857 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE; 858 859 mapping = kmem_zalloc((sizeof (idmap_mapping)) * 860 new_size, KM_SLEEP); 861 (void) memcpy(mapping, get_handle->mapping, 862 (sizeof (idmap_mapping)) * get_handle->mapping_size); 863 864 result = kmem_zalloc((sizeof (idmap_get_res)) * 865 new_size, KM_SLEEP); 866 (void) memcpy(result, get_handle->result, 867 (sizeof (idmap_get_res)) * get_handle->mapping_size); 868 869 kmem_free(get_handle->mapping, 870 (sizeof (idmap_mapping)) * get_handle->mapping_size); 871 get_handle->mapping = mapping; 872 873 kmem_free(get_handle->result, 874 (sizeof (idmap_get_res)) * get_handle->mapping_size); 875 get_handle->result = result; 876 877 get_handle->mapping_size = new_size; 878 } 879 880 881 /* 882 * Given Domain SID and RID, get UID 883 * 884 * Input: 885 * sid_prefix - Domain SID in canonical form 886 * rid - RID 887 * 888 * Output: 889 * stat - status of the get request 890 * uid - POSIX UID if stat == IDMAP_SUCCESS 891 * 892 * Notes: 893 * The output parameters will be set by idmap_get_mappings() 894 * The sid_prefix is copied. 895 */ 896 idmap_stat 897 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 898 uint32_t rid, uid_t *uid, idmap_stat *stat) 899 { 900 idmap_mapping *mapping; 901 idmap_get_res *result; 902 903 if (get_handle == NULL || sid_prefix == NULL || 904 uid == NULL || stat == NULL) 905 return (IDMAP_ERR_ARG); 906 907 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 908 rid, uid) == IDMAP_SUCCESS) { 909 *stat = IDMAP_SUCCESS; 910 return (IDMAP_SUCCESS); 911 } 912 913 /* Get a copy of sid_prefix */ 914 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 915 916 if (get_handle->mapping_num >= get_handle->mapping_size) 917 kidmap_get_extend(get_handle); 918 919 mapping = &get_handle->mapping[get_handle->mapping_num]; 920 mapping->flag = 0; 921 mapping->id1.idtype = IDMAP_SID; 922 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 923 mapping->id1.idmap_id_u.sid.rid = rid; 924 mapping->id2.idtype = IDMAP_UID; 925 926 result = &get_handle->result[get_handle->mapping_num]; 927 result->idtype = IDMAP_UID; 928 result->uid = uid; 929 result->gid = NULL; 930 result->pid = NULL; 931 result->sid_prefix = NULL; 932 result->rid = NULL; 933 result->is_user = NULL; 934 result->stat = stat; 935 936 get_handle->mapping_num++; 937 938 return (IDMAP_SUCCESS); 939 } 940 941 942 /* 943 * Given Domain SID and RID, get GID 944 * 945 * Input: 946 * sid_prefix - Domain SID in canonical form 947 * rid - RID 948 * 949 * Output: 950 * stat - status of the get request 951 * gid - POSIX GID if stat == IDMAP_SUCCESS 952 * 953 * Notes: 954 * The output parameters will be set by idmap_get_mappings() 955 * The sid_prefix is copied. 956 */ 957 idmap_stat 958 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 959 uint32_t rid, uid_t *gid, idmap_stat *stat) 960 { 961 idmap_mapping *mapping; 962 idmap_get_res *result; 963 964 if (get_handle == NULL || sid_prefix == NULL || 965 gid == NULL || stat == NULL) 966 return (IDMAP_ERR_ARG); 967 968 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 969 rid, gid) == IDMAP_SUCCESS) { 970 *stat = IDMAP_SUCCESS; 971 return (IDMAP_SUCCESS); 972 } 973 974 /* Get a copy of sid_prefix */ 975 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 976 977 if (get_handle->mapping_num >= get_handle->mapping_size) 978 kidmap_get_extend(get_handle); 979 980 mapping = &get_handle->mapping[get_handle->mapping_num]; 981 mapping->flag = 0; 982 mapping->id1.idtype = IDMAP_SID; 983 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 984 mapping->id1.idmap_id_u.sid.rid = rid; 985 mapping->id2.idtype = IDMAP_GID; 986 987 result = &get_handle->result[get_handle->mapping_num]; 988 result->idtype = IDMAP_GID; 989 result->uid = NULL; 990 result->gid = gid; 991 result->pid = NULL; 992 result->sid_prefix = NULL; 993 result->rid = NULL; 994 result->is_user = NULL; 995 result->stat = stat; 996 997 get_handle->mapping_num++; 998 999 return (IDMAP_SUCCESS); 1000 } 1001 1002 1003 /* 1004 * Given Domain SID and RID, get Posix ID 1005 * 1006 * Input: 1007 * sid_prefix - Domain SID in canonical form 1008 * rid - RID 1009 * 1010 * Output: 1011 * stat - status of the get request 1012 * is_user - user or group 1013 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 1014 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 1015 * 1016 * Notes: 1017 * The output parameters will be set by idmap_get_mappings() 1018 * The sid_prefix is copied. 1019 */ 1020 idmap_stat 1021 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 1022 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 1023 { 1024 idmap_mapping *mapping; 1025 idmap_get_res *result; 1026 1027 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 1028 is_user == NULL || stat == NULL) 1029 return (IDMAP_ERR_ARG); 1030 1031 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 1032 rid, pid, is_user) == IDMAP_SUCCESS) { 1033 *stat = IDMAP_SUCCESS; 1034 return (IDMAP_SUCCESS); 1035 } 1036 1037 /* Get a copy of sid_prefix */ 1038 sid_prefix = kidmap_find_sid_prefix(sid_prefix); 1039 1040 if (get_handle->mapping_num >= get_handle->mapping_size) 1041 kidmap_get_extend(get_handle); 1042 1043 mapping = &get_handle->mapping[get_handle->mapping_num]; 1044 mapping->flag = 0; 1045 mapping->id1.idtype = IDMAP_SID; 1046 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 1047 mapping->id1.idmap_id_u.sid.rid = rid; 1048 mapping->id2.idtype = IDMAP_POSIXID; 1049 1050 result = &get_handle->result[get_handle->mapping_num]; 1051 result->idtype = IDMAP_POSIXID; 1052 result->uid = NULL; 1053 result->gid = NULL; 1054 result->pid = pid; 1055 result->sid_prefix = NULL; 1056 result->rid = NULL; 1057 result->is_user = is_user; 1058 result->stat = stat; 1059 1060 get_handle->mapping_num++; 1061 1062 return (IDMAP_SUCCESS); 1063 } 1064 1065 1066 /* 1067 * Given UID, get SID and RID 1068 * 1069 * Input: 1070 * uid - POSIX UID 1071 * 1072 * Output: 1073 * stat - status of the get request 1074 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1075 * rid - RID (if stat == IDMAP_SUCCESS) 1076 * 1077 * Note: The output parameters will be set by idmap_get_mappings() 1078 */ 1079 idmap_stat 1080 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 1081 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1082 { 1083 idmap_mapping *mapping; 1084 idmap_get_res *result; 1085 1086 if (get_handle == NULL || sid_prefix == NULL || 1087 rid == NULL || stat == NULL) 1088 return (IDMAP_ERR_ARG); 1089 1090 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache, 1091 sid_prefix, rid, uid) == IDMAP_SUCCESS) { 1092 *stat = IDMAP_SUCCESS; 1093 return (IDMAP_SUCCESS); 1094 } 1095 1096 if (get_handle->mapping_num >= get_handle->mapping_size) 1097 kidmap_get_extend(get_handle); 1098 1099 mapping = &get_handle->mapping[get_handle->mapping_num]; 1100 mapping->flag = 0; 1101 mapping->id1.idtype = IDMAP_UID; 1102 mapping->id1.idmap_id_u.uid = uid; 1103 mapping->id2.idtype = IDMAP_SID; 1104 1105 result = &get_handle->result[get_handle->mapping_num]; 1106 result->idtype = IDMAP_SID; 1107 result->uid = NULL; 1108 result->gid = NULL; 1109 result->pid = NULL; 1110 result->sid_prefix = sid_prefix; 1111 result->rid = rid; 1112 result->is_user = NULL; 1113 result->stat = stat; 1114 1115 get_handle->mapping_num++; 1116 1117 return (IDMAP_SUCCESS); 1118 } 1119 1120 1121 /* 1122 * Given GID, get SID and RID 1123 * 1124 * Input: 1125 * gid - POSIX GID 1126 * 1127 * Output: 1128 * stat - status of the get request 1129 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1130 * rid - RID (if stat == IDMAP_SUCCESS) 1131 * 1132 * Note: The output parameters will be set by idmap_get_mappings() 1133 */ 1134 idmap_stat 1135 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 1136 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1137 { 1138 idmap_mapping *mapping; 1139 idmap_get_res *result; 1140 1141 if (get_handle == NULL || sid_prefix == NULL || 1142 rid == NULL || stat == NULL) 1143 return (IDMAP_ERR_ARG); 1144 1145 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache, 1146 sid_prefix, rid, gid) == IDMAP_SUCCESS) { 1147 *stat = IDMAP_SUCCESS; 1148 return (IDMAP_SUCCESS); 1149 } 1150 1151 if (get_handle->mapping_num >= get_handle->mapping_size) 1152 kidmap_get_extend(get_handle); 1153 1154 mapping = &get_handle->mapping[get_handle->mapping_num]; 1155 mapping->flag = 0; 1156 mapping->id1.idtype = IDMAP_GID; 1157 mapping->id1.idmap_id_u.gid = gid; 1158 mapping->id2.idtype = IDMAP_SID; 1159 1160 result = &get_handle->result[get_handle->mapping_num]; 1161 result->idtype = IDMAP_SID; 1162 result->uid = NULL; 1163 result->gid = NULL; 1164 result->pid = NULL; 1165 result->sid_prefix = sid_prefix; 1166 result->rid = rid; 1167 result->is_user = NULL; 1168 result->stat = stat; 1169 1170 get_handle->mapping_num++; 1171 1172 return (IDMAP_SUCCESS); 1173 } 1174 1175 1176 /* 1177 * Process the batched "get mapping" requests. The results (i.e. 1178 * status and identity) will be available in the data areas 1179 * provided by individual requests. 1180 * 1181 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1182 * return and the UID or UID result is set to "nobody" 1183 */ 1184 1185 idmap_stat 1186 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1187 { 1188 idmap_mapping_batch rpc_args; 1189 idmap_ids_res rpc_res; 1190 uint32_t op = IDMAP_GET_MAPPED_IDS; 1191 idmap_mapping *request; 1192 idmap_get_res *result; 1193 idmap_id *id; 1194 int status; 1195 int i; 1196 const char *sid_prefix; 1197 int is_user; 1198 idmap_cache_t *cache; 1199 int direction; 1200 1201 if (get_handle == NULL) 1202 return (IDMAP_ERR_ARG); 1203 1204 if (get_handle->mapping_num == 0) 1205 return (IDMAP_SUCCESS); 1206 cache = &get_handle->zs->cache; 1207 1208 bzero(&rpc_res, sizeof (idmap_ids_res)); 1209 1210 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num; 1211 rpc_args.idmap_mapping_batch_val = get_handle->mapping; 1212 1213 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch, 1214 (caddr_t)&rpc_args, xdr_idmap_ids_res, 1215 (caddr_t)&rpc_res) != 0) { 1216 /* Door call failed */ 1217 status = IDMAP_ERR_NOMAPPING; 1218 goto error; 1219 } 1220 1221 status = rpc_res.retcode; 1222 if (status != IDMAP_SUCCESS) { 1223 /* RPC returned idmap error code */ 1224 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1225 goto error; 1226 } 1227 1228 for (i = 0; i < get_handle->mapping_num; i++) { 1229 request = &get_handle->mapping[i]; 1230 result = &get_handle->result[i]; 1231 1232 if (i >= rpc_res.ids.ids_len) { 1233 *result->stat = IDMAP_ERR_NOMAPPING; 1234 if (result->uid) 1235 *result->uid = UID_NOBODY; 1236 if (result->gid) 1237 *result->gid = GID_NOBODY; 1238 if (result->pid) 1239 *result->pid = UID_NOBODY; 1240 if (result->is_user) 1241 *result->is_user = 1; 1242 if (result->sid_prefix) 1243 *result->sid_prefix = NULL; 1244 if (result->rid) 1245 *result->rid = 0; 1246 continue; 1247 } 1248 1249 *result->stat = rpc_res.ids.ids_val[i].retcode; 1250 1251 id = &rpc_res.ids.ids_val[i].id; 1252 direction = rpc_res.ids.ids_val[i].direction; 1253 1254 switch (id->idtype) { 1255 case IDMAP_UID: 1256 if (result->uid) 1257 *result->uid = id->idmap_id_u.uid; 1258 if (result->pid) 1259 *result->pid = id->idmap_id_u.uid; 1260 if (result->is_user) 1261 *result->is_user = 1; 1262 sid_prefix = kidmap_find_sid_prefix( 1263 request->id1.idmap_id_u.sid.prefix); 1264 if (*result->stat == IDMAP_SUCCESS && result->uid) 1265 kidmap_cache_add_sid2uid( 1266 cache, sid_prefix, 1267 request->id1.idmap_id_u.sid.rid, 1268 id->idmap_id_u.uid, 1269 direction); 1270 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1271 kidmap_cache_add_sid2pid( 1272 cache, sid_prefix, 1273 request->id1.idmap_id_u.sid.rid, 1274 id->idmap_id_u.uid, 1, 1275 direction); 1276 break; 1277 1278 case IDMAP_GID: 1279 if (result->gid) 1280 *result->gid = id->idmap_id_u.gid; 1281 if (result->pid) 1282 *result->pid = id->idmap_id_u.gid; 1283 if (result->is_user) 1284 *result->is_user = 0; 1285 sid_prefix = kidmap_find_sid_prefix( 1286 request->id1.idmap_id_u.sid.prefix); 1287 if (*result->stat == IDMAP_SUCCESS && result->gid) 1288 kidmap_cache_add_sid2gid( 1289 cache, sid_prefix, 1290 request->id1.idmap_id_u.sid.rid, 1291 id->idmap_id_u.gid, 1292 direction); 1293 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1294 kidmap_cache_add_sid2pid( 1295 cache, sid_prefix, 1296 request->id1.idmap_id_u.sid.rid, 1297 id->idmap_id_u.gid, 0, 1298 direction); 1299 break; 1300 1301 case IDMAP_SID: 1302 case IDMAP_USID: 1303 case IDMAP_GSID: 1304 sid_prefix = kidmap_find_sid_prefix( 1305 id->idmap_id_u.sid.prefix); 1306 if (result->sid_prefix && result->rid) { 1307 *result->sid_prefix = sid_prefix; 1308 *result->rid = id->idmap_id_u.sid.rid; 1309 } 1310 if (*result->stat == IDMAP_SUCCESS && 1311 request->id1.idtype == IDMAP_UID) 1312 kidmap_cache_add_sid2uid( 1313 cache, sid_prefix, 1314 id->idmap_id_u.sid.rid, 1315 request->id1.idmap_id_u.uid, 1316 direction); 1317 else if (*result->stat == IDMAP_SUCCESS && 1318 request->id1.idtype == IDMAP_GID) 1319 kidmap_cache_add_sid2gid( 1320 cache, sid_prefix, 1321 id->idmap_id_u.sid.rid, 1322 request->id1.idmap_id_u.gid, 1323 direction); 1324 break; 1325 1326 default: 1327 *result->stat = IDMAP_ERR_NORESULT; 1328 if (result->uid) 1329 *result->uid = UID_NOBODY; 1330 if (result->gid) 1331 *result->gid = GID_NOBODY; 1332 if (result->pid) 1333 *result->pid = UID_NOBODY; 1334 if (result->is_user) 1335 *result->is_user = 1; 1336 if (result->sid_prefix) 1337 *result->sid_prefix = NULL; 1338 if (result->rid) 1339 *result->rid = 0; 1340 break; 1341 } 1342 } 1343 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1344 1345 /* Reset get_handle for new resquests */ 1346 get_handle->mapping_num = 0; 1347 return (status); 1348 1349 error: 1350 for (i = 0; i < get_handle->mapping_num; i++) { 1351 result = &get_handle->result[i]; 1352 1353 *result->stat = status; 1354 if (result->uid) 1355 *result->uid = UID_NOBODY; 1356 if (result->gid) 1357 *result->gid = GID_NOBODY; 1358 if (result->pid) 1359 *result->pid = UID_NOBODY; 1360 if (result->is_user) 1361 *result->is_user = 1; 1362 if (result->sid_prefix) 1363 *result->sid_prefix = NULL; 1364 if (result->rid) 1365 *result->rid = 0; 1366 } 1367 1368 /* Reset get_handle for new resquests */ 1369 get_handle->mapping_num = 0; 1370 return (status); 1371 } 1372 1373 1374 /* 1375 * Destroy the "get mapping" handle 1376 */ 1377 void 1378 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1379 { 1380 if (get_handle == NULL) 1381 return; 1382 1383 kmem_free(get_handle->mapping, 1384 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1385 get_handle->mapping = NULL; 1386 1387 kmem_free(get_handle->result, 1388 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1389 get_handle->result = NULL; 1390 1391 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1392 } 1393 1394 1395 static int 1396 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args, 1397 caddr_t args, xdrproc_t xdr_res, caddr_t res) 1398 { 1399 XDR xdr_ctx; 1400 struct rpc_msg reply_msg; 1401 char *inbuf_ptr = NULL; 1402 size_t inbuf_size = 4096; 1403 char *outbuf_ptr = NULL; 1404 size_t outbuf_size = 4096; 1405 size_t size; 1406 int status = 0; 1407 door_arg_t params; 1408 int retry = 0; 1409 struct rpc_msg call_msg; 1410 1411 params.rbuf = NULL; 1412 params.rsize = 0; 1413 1414 retry: 1415 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1416 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1417 1418 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1419 1420 call_msg.rm_call.cb_prog = IDMAP_PROG; 1421 call_msg.rm_call.cb_vers = IDMAP_V1; 1422 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id); 1423 1424 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1425 #ifdef DEBUG 1426 zcmn_err(zs->zone_id, CE_WARN, 1427 "idmap: xdr encoding header error"); 1428 #endif /* DEBUG */ 1429 status = -1; 1430 goto exit; 1431 } 1432 1433 if (!xdr_uint32(&xdr_ctx, &op) || 1434 /* Auth none */ 1435 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1436 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1437 /* RPC args */ 1438 !xdr_args(&xdr_ctx, args)) { 1439 #ifdef DEBUG 1440 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error"); 1441 #endif /* DEBUG */ 1442 if (retry > 2) { 1443 status = -1; 1444 goto exit; 1445 } 1446 retry++; 1447 if (inbuf_ptr) { 1448 kmem_free(inbuf_ptr, inbuf_size); 1449 inbuf_ptr = NULL; 1450 } 1451 if (outbuf_ptr) { 1452 kmem_free(outbuf_ptr, outbuf_size); 1453 outbuf_ptr = NULL; 1454 } 1455 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1456 #ifdef DEBUG 1457 zcmn_err(zs->zone_id, CE_WARN, 1458 "idmap: xdr_sizeof error"); 1459 #endif /* DEBUG */ 1460 status = -1; 1461 goto exit; 1462 } 1463 inbuf_size = size + 1024; 1464 outbuf_size = size + 1024; 1465 goto retry; 1466 } 1467 1468 params.data_ptr = inbuf_ptr; 1469 params.data_size = XDR_GETPOS(&xdr_ctx); 1470 params.desc_ptr = NULL; 1471 params.desc_num = 0; 1472 params.rbuf = outbuf_ptr; 1473 params.rsize = outbuf_size; 1474 1475 if (kidmap_call_door(zs, ¶ms) != 0) { 1476 status = -1; 1477 goto exit; 1478 } 1479 1480 reply_msg.acpted_rply.ar_verf = _null_auth; 1481 reply_msg.acpted_rply.ar_results.where = res; 1482 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1483 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1484 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1485 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1486 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1487 status = -1; 1488 goto exit; 1489 } 1490 } else { 1491 #ifdef DEBUG 1492 zcmn_err(zs->zone_id, CE_WARN, 1493 "idmap: xdr decoding reply message error"); 1494 #endif /* DEBUG */ 1495 status = -1; 1496 } 1497 1498 exit: 1499 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1500 kmem_free(params.rbuf, params.rsize); 1501 if (inbuf_ptr) 1502 kmem_free(inbuf_ptr, inbuf_size); 1503 if (outbuf_ptr) 1504 kmem_free(outbuf_ptr, outbuf_size); 1505 return (status); 1506 } 1507