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