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