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