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 results.ids.ids_val[0].id.idtype == IDMAP_USID || 562 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 563 status = results.ids.ids_val[0].retcode; 564 id = &results.ids.ids_val[0].id; 565 *sid_prefix = kidmap_find_sid_prefix( 566 id->idmap_id_u.sid.prefix); 567 *rid = id->idmap_id_u.sid.rid; 568 if (status == IDMAP_SUCCESS) { 569 kidmap_cache_add_sidbyuid(&idmap_cache, 570 *sid_prefix, *rid, uid); 571 } 572 } else { 573 status = IDMAP_ERR_NOMAPPING; 574 *rid = 0; 575 *sid_prefix = NULL; 576 } 577 xdr_free(xdr_idmap_ids_res, (char *)&results); 578 } else { 579 /* Door call failed */ 580 status = IDMAP_ERR_NOMAPPING; 581 *rid = 0; 582 *sid_prefix = NULL; 583 } 584 return (status); 585 } 586 587 588 /* 589 * Given GID, get Domain SID and RID 590 * 591 * Input: 592 * gid - Posix GID 593 * 594 * Output: 595 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 596 * rid - RID if return == IDMAP_SUCCESS 597 * 598 * Return: 599 * Success return IDMAP_SUCCESS else IDMAP error 600 */ 601 idmap_stat 602 kidmap_getsidbygid(gid_t gid, const char **sid_prefix, uint32_t *rid) 603 { 604 idmap_mapping_batch args; 605 idmap_mapping mapping; 606 idmap_ids_res results; 607 uint32_t op = IDMAP_GET_MAPPED_IDS; 608 idmap_stat status; 609 idmap_id *id; 610 611 if (sid_prefix == NULL || rid == NULL) 612 return (IDMAP_ERR_ARG); 613 614 if (kidmap_cache_lookup_sidbygid(&idmap_cache, sid_prefix, rid, gid) 615 == IDMAP_SUCCESS) { 616 return (IDMAP_SUCCESS); 617 } 618 619 bzero(&mapping, sizeof (idmap_mapping)); 620 mapping.id1.idtype = IDMAP_GID; 621 mapping.id1.idmap_id_u.uid = gid; 622 mapping.id2.idtype = IDMAP_SID; 623 624 bzero(&results, sizeof (idmap_ids_res)); 625 626 args.idmap_mapping_batch_len = 1; 627 args.idmap_mapping_batch_val = &mapping; 628 629 if (kidmap_rpc_call(op, xdr_idmap_mapping_batch, 630 (caddr_t)&args, xdr_idmap_ids_res, 631 (caddr_t)&results) == 0) { 632 /* Door call succeded */ 633 if (results.ids.ids_len >= 1 && 634 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 635 results.ids.ids_val[0].id.idtype == IDMAP_USID || 636 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 637 status = results.ids.ids_val[0].retcode; 638 id = &results.ids.ids_val[0].id; 639 *sid_prefix = kidmap_find_sid_prefix( 640 id->idmap_id_u.sid.prefix); 641 *rid = id->idmap_id_u.sid.rid; 642 if (status == IDMAP_SUCCESS) { 643 kidmap_cache_add_sidbygid(&idmap_cache, 644 *sid_prefix, *rid, gid); 645 } 646 } else { 647 status = IDMAP_ERR_NOMAPPING; 648 *rid = 0; 649 *sid_prefix = NULL; 650 } 651 xdr_free(xdr_idmap_ids_res, (char *)&results); 652 } else { 653 /* Door call failed */ 654 status = IDMAP_ERR_NOMAPPING; 655 *rid = 0; 656 *sid_prefix = NULL; 657 } 658 return (status); 659 } 660 661 /* 662 * Create handle to get SID to UID/GID mapping entries 663 * 664 * Input: 665 * none 666 * Return: 667 * get_handle 668 * 669 */ 670 idmap_get_handle_t * 671 kidmap_get_create(void) 672 { 673 idmap_get_handle_t *handle; 674 #define INIT_MAPPING_SIZE 6 675 676 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP); 677 678 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) * 679 INIT_MAPPING_SIZE, KM_SLEEP); 680 681 handle->result = kmem_zalloc((sizeof (idmap_get_res)) * 682 INIT_MAPPING_SIZE, KM_SLEEP); 683 handle->mapping_size = INIT_MAPPING_SIZE; 684 handle->cache = &idmap_cache; 685 686 return (handle); 687 } 688 689 /* 690 * Internal routine to extend a "get_handle" 691 */ 692 static void 693 kidmap_get_extend(idmap_get_handle_t *get_handle) 694 { 695 idmap_mapping *mapping; 696 idmap_get_res *result; 697 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE; 698 699 mapping = kmem_zalloc((sizeof (idmap_mapping)) * 700 new_size, KM_SLEEP); 701 (void) memcpy(mapping, get_handle->mapping, 702 (sizeof (idmap_mapping)) * get_handle->mapping_size); 703 704 result = kmem_zalloc((sizeof (idmap_get_res)) * 705 new_size, KM_SLEEP); 706 (void) memcpy(result, get_handle->result, 707 (sizeof (idmap_get_res)) * get_handle->mapping_size); 708 709 kmem_free(get_handle->mapping, 710 (sizeof (idmap_mapping)) * get_handle->mapping_size); 711 get_handle->mapping = mapping; 712 713 kmem_free(get_handle->result, 714 (sizeof (idmap_get_res)) * get_handle->mapping_size); 715 get_handle->result = result; 716 717 get_handle->mapping_size = new_size; 718 } 719 720 721 /* 722 * Given Domain SID and RID, get UID 723 * 724 * Input: 725 * sid_prefix - Domain SID in canonical form 726 * rid - RID 727 * 728 * Output: 729 * stat - status of the get request 730 * uid - POSIX UID if stat == IDMAP_SUCCESS 731 * 732 * Note: The output parameters will be set by idmap_get_mappings() 733 */ 734 idmap_stat 735 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 736 uint32_t rid, uid_t *uid, idmap_stat *stat) 737 { 738 idmap_mapping *mapping; 739 idmap_get_res *result; 740 741 if (get_handle == NULL || sid_prefix == NULL || 742 uid == NULL || stat == NULL) 743 return (IDMAP_ERR_ARG); 744 745 if (kidmap_cache_lookup_uidbysid(get_handle->cache, sid_prefix, 746 rid, uid) == IDMAP_SUCCESS) { 747 *stat = IDMAP_SUCCESS; 748 return (IDMAP_SUCCESS); 749 } 750 751 if (get_handle->mapping_num >= get_handle->mapping_size) 752 kidmap_get_extend(get_handle); 753 754 mapping = &get_handle->mapping[get_handle->mapping_num]; 755 mapping->flag = 0; 756 mapping->id1.idtype = IDMAP_SID; 757 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 758 mapping->id1.idmap_id_u.sid.rid = rid; 759 mapping->id2.idtype = IDMAP_UID; 760 761 result = &get_handle->result[get_handle->mapping_num]; 762 result->idtype = IDMAP_UID; 763 result->uid = uid; 764 result->gid = NULL; 765 result->pid = NULL; 766 result->sid_prefix = NULL; 767 result->rid = NULL; 768 result->is_user = NULL; 769 result->stat = stat; 770 771 get_handle->mapping_num++; 772 773 return (IDMAP_SUCCESS); 774 } 775 776 777 /* 778 * Given Domain SID and RID, get GID 779 * 780 * Input: 781 * sid_prefix - Domain SID in canonical form 782 * rid - RID 783 * 784 * Output: 785 * stat - status of the get request 786 * gid - POSIX GID if stat == IDMAP_SUCCESS 787 * 788 * Note: The output parameters will be set by idmap_get_mappings() 789 */ 790 idmap_stat 791 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 792 uint32_t rid, uid_t *gid, idmap_stat *stat) 793 { 794 idmap_mapping *mapping; 795 idmap_get_res *result; 796 797 if (get_handle == NULL || sid_prefix == NULL || 798 gid == NULL || stat == NULL) 799 return (IDMAP_ERR_ARG); 800 801 if (kidmap_cache_lookup_gidbysid(get_handle->cache, sid_prefix, 802 rid, gid) == IDMAP_SUCCESS) { 803 *stat = IDMAP_SUCCESS; 804 return (IDMAP_SUCCESS); 805 } 806 807 if (get_handle->mapping_num >= get_handle->mapping_size) 808 kidmap_get_extend(get_handle); 809 810 mapping = &get_handle->mapping[get_handle->mapping_num]; 811 mapping->flag = 0; 812 mapping->id1.idtype = IDMAP_SID; 813 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 814 mapping->id1.idmap_id_u.sid.rid = rid; 815 mapping->id2.idtype = IDMAP_GID; 816 817 result = &get_handle->result[get_handle->mapping_num]; 818 result->idtype = IDMAP_GID; 819 result->uid = NULL; 820 result->gid = gid; 821 result->pid = NULL; 822 result->sid_prefix = NULL; 823 result->rid = NULL; 824 result->is_user = NULL; 825 result->stat = stat; 826 827 get_handle->mapping_num++; 828 829 return (IDMAP_SUCCESS); 830 } 831 832 833 /* 834 * Given Domain SID and RID, get Posix ID 835 * 836 * Input: 837 * sid_prefix - Domain SID in canonical form 838 * rid - RID 839 * 840 * Output: 841 * stat - status of the get request 842 * is_user - user or group 843 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 844 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 845 * 846 * Note: The output parameters will be set by idmap_get_mappings() 847 */ 848 idmap_stat 849 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 850 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 851 { 852 idmap_mapping *mapping; 853 idmap_get_res *result; 854 855 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 856 is_user == NULL || stat == NULL) 857 return (IDMAP_ERR_ARG); 858 859 if (kidmap_cache_lookup_pidbysid(get_handle->cache, sid_prefix, 860 rid, pid, is_user) == IDMAP_SUCCESS) { 861 *stat = IDMAP_SUCCESS; 862 return (IDMAP_SUCCESS); 863 } 864 865 866 if (get_handle->mapping_num >= get_handle->mapping_size) 867 kidmap_get_extend(get_handle); 868 869 mapping = &get_handle->mapping[get_handle->mapping_num]; 870 mapping->flag = 0; 871 mapping->id1.idtype = IDMAP_SID; 872 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 873 mapping->id1.idmap_id_u.sid.rid = rid; 874 mapping->id2.idtype = IDMAP_POSIXID; 875 876 result = &get_handle->result[get_handle->mapping_num]; 877 result->idtype = IDMAP_POSIXID; 878 result->uid = NULL; 879 result->gid = NULL; 880 result->pid = pid; 881 result->sid_prefix = NULL; 882 result->rid = NULL; 883 result->is_user = is_user; 884 result->stat = stat; 885 886 get_handle->mapping_num++; 887 888 return (IDMAP_SUCCESS); 889 } 890 891 892 /* 893 * Given UID, get SID and RID 894 * 895 * Input: 896 * uid - POSIX UID 897 * 898 * Output: 899 * stat - status of the get request 900 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 901 * rid - RID (if stat == IDMAP_SUCCESS) 902 * 903 * Note: The output parameters will be set by idmap_get_mappings() 904 */ 905 idmap_stat 906 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 907 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 908 { 909 idmap_mapping *mapping; 910 idmap_get_res *result; 911 912 if (get_handle == NULL || sid_prefix == NULL || 913 rid == NULL || stat == NULL) 914 return (IDMAP_ERR_ARG); 915 916 if (kidmap_cache_lookup_sidbyuid(get_handle->cache, sid_prefix, 917 rid, uid) == IDMAP_SUCCESS) { 918 *stat = IDMAP_SUCCESS; 919 return (IDMAP_SUCCESS); 920 } 921 922 if (get_handle->mapping_num >= get_handle->mapping_size) 923 kidmap_get_extend(get_handle); 924 925 mapping = &get_handle->mapping[get_handle->mapping_num]; 926 mapping->flag = 0; 927 mapping->id1.idtype = IDMAP_UID; 928 mapping->id1.idmap_id_u.uid = uid; 929 mapping->id2.idtype = IDMAP_SID; 930 931 result = &get_handle->result[get_handle->mapping_num]; 932 result->idtype = IDMAP_SID; 933 result->uid = NULL; 934 result->gid = NULL; 935 result->pid = NULL; 936 result->sid_prefix = sid_prefix; 937 result->rid = rid; 938 result->is_user = NULL; 939 result->stat = stat; 940 941 get_handle->mapping_num++; 942 943 return (IDMAP_SUCCESS); 944 } 945 946 947 /* 948 * Given GID, get SID and RID 949 * 950 * Input: 951 * gid - POSIX GID 952 * 953 * Output: 954 * stat - status of the get request 955 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 956 * rid - RID (if stat == IDMAP_SUCCESS) 957 * 958 * Note: The output parameters will be set by idmap_get_mappings() 959 */ 960 idmap_stat 961 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 962 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 963 { 964 idmap_mapping *mapping; 965 idmap_get_res *result; 966 967 if (get_handle == NULL || sid_prefix == NULL || 968 rid == NULL || stat == NULL) 969 return (IDMAP_ERR_ARG); 970 971 if (kidmap_cache_lookup_sidbygid(get_handle->cache, sid_prefix, 972 rid, gid) == IDMAP_SUCCESS) { 973 *stat = IDMAP_SUCCESS; 974 return (IDMAP_SUCCESS); 975 } 976 977 if (get_handle->mapping_num >= get_handle->mapping_size) 978 kidmap_get_extend(get_handle); 979 980 mapping = &get_handle->mapping[get_handle->mapping_num]; 981 mapping->flag = 0; 982 mapping->id1.idtype = IDMAP_GID; 983 mapping->id1.idmap_id_u.gid = gid; 984 mapping->id2.idtype = IDMAP_SID; 985 986 result = &get_handle->result[get_handle->mapping_num]; 987 result->idtype = IDMAP_SID; 988 result->uid = NULL; 989 result->gid = NULL; 990 result->pid = NULL; 991 result->sid_prefix = sid_prefix; 992 result->rid = rid; 993 result->is_user = NULL; 994 result->stat = stat; 995 996 get_handle->mapping_num++; 997 998 return (IDMAP_SUCCESS); 999 } 1000 1001 1002 /* 1003 * Process the batched "get mapping" requests. The results (i.e. 1004 * status and identity) will be available in the data areas 1005 * provided by individual requests. 1006 * 1007 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1008 * return and the UID or UID result is set to "nobody" 1009 */ 1010 1011 idmap_stat 1012 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1013 { 1014 idmap_mapping_batch args; 1015 idmap_ids_res results; 1016 uint32_t op = IDMAP_GET_MAPPED_IDS; 1017 idmap_mapping *mapping; 1018 idmap_get_res *result; 1019 idmap_id *id; 1020 int status; 1021 int i; 1022 const char *sid_prefix; 1023 int is_user; 1024 1025 if (get_handle == NULL) 1026 return (IDMAP_ERR_ARG); 1027 1028 if (get_handle->mapping_num == 0) 1029 return (IDMAP_SUCCESS); 1030 1031 bzero(&results, sizeof (idmap_ids_res)); 1032 1033 args.idmap_mapping_batch_len = get_handle->mapping_num; 1034 args.idmap_mapping_batch_val = get_handle->mapping; 1035 1036 if (kidmap_rpc_call(op, xdr_idmap_mapping_batch, 1037 (caddr_t)&args, xdr_idmap_ids_res, 1038 (caddr_t)&results) == 0) { 1039 /* Door call succeded */ 1040 status = IDMAP_SUCCESS; 1041 for (i = 0; i < get_handle->mapping_num; i++) { 1042 mapping = &get_handle->mapping[i]; 1043 result = &get_handle->result[i]; 1044 1045 if (i > results.ids.ids_len) { 1046 *result->stat = IDMAP_ERR_NOMAPPING; 1047 if (result->uid) 1048 *result->uid = UID_NOBODY; 1049 if (result->gid) 1050 *result->gid = GID_NOBODY; 1051 if (result->pid) 1052 *result->pid = UID_NOBODY; 1053 if (result->is_user) 1054 *result->is_user = 1; 1055 if (result->sid_prefix) 1056 *result->sid_prefix = NULL; 1057 if (result->rid) 1058 *result->rid = 0; 1059 continue; 1060 } 1061 *result->stat = results.ids.ids_val[i].retcode; 1062 1063 id = &results.ids.ids_val[i].id; 1064 switch (id->idtype) { 1065 case IDMAP_UID: 1066 if (result->uid) 1067 *result->uid = id->idmap_id_u.uid; 1068 if (result->pid) 1069 *result->pid = id->idmap_id_u.uid; 1070 if (result->is_user) 1071 *result->is_user = 1; 1072 sid_prefix = kidmap_find_sid_prefix( 1073 mapping->id1.idmap_id_u.sid.prefix); 1074 if (*result->stat == IDMAP_SUCCESS && 1075 result->uid) 1076 kidmap_cache_add_uidbysid( 1077 get_handle->cache, 1078 sid_prefix, 1079 mapping->id1.idmap_id_u.sid.rid, 1080 id->idmap_id_u.uid); 1081 else if (*result->stat == IDMAP_SUCCESS && 1082 result->pid) 1083 kidmap_cache_add_pidbysid( 1084 get_handle->cache, 1085 sid_prefix, 1086 mapping->id1.idmap_id_u.sid.rid, 1087 id->idmap_id_u.uid, 1); 1088 break; 1089 1090 case IDMAP_GID: 1091 if (result->gid) 1092 *result->gid = id->idmap_id_u.gid; 1093 if (result->pid) 1094 *result->pid = id->idmap_id_u.gid; 1095 if (result->is_user) 1096 *result->is_user = 0; 1097 sid_prefix = kidmap_find_sid_prefix( 1098 mapping->id1.idmap_id_u.sid.prefix); 1099 if (*result->stat == IDMAP_SUCCESS && 1100 result->gid) 1101 kidmap_cache_add_gidbysid( 1102 get_handle->cache, 1103 sid_prefix, 1104 mapping->id1.idmap_id_u.sid.rid, 1105 id->idmap_id_u.gid); 1106 else if (*result->stat == IDMAP_SUCCESS && 1107 result->pid) 1108 kidmap_cache_add_pidbysid( 1109 get_handle->cache, 1110 sid_prefix, 1111 mapping->id1.idmap_id_u.sid.rid, 1112 id->idmap_id_u.gid, 0); 1113 break; 1114 1115 case IDMAP_SID: 1116 case IDMAP_USID: 1117 case IDMAP_GSID: 1118 sid_prefix = kidmap_find_sid_prefix( 1119 id->idmap_id_u.sid.prefix); 1120 if (result->sid_prefix && result->rid) { 1121 *result->sid_prefix = sid_prefix; 1122 *result->rid = id->idmap_id_u.sid.rid; 1123 } 1124 if (*result->stat == IDMAP_SUCCESS && 1125 mapping->id1.idtype == IDMAP_UID) 1126 kidmap_cache_add_sidbyuid( 1127 get_handle->cache, 1128 sid_prefix, 1129 id->idmap_id_u.sid.rid, 1130 mapping->id1.idmap_id_u.uid); 1131 else if (*result->stat == IDMAP_SUCCESS && 1132 mapping->id1.idtype == IDMAP_GID) 1133 kidmap_cache_add_sidbygid( 1134 get_handle->cache, 1135 sid_prefix, 1136 id->idmap_id_u.sid.rid, 1137 mapping->id1.idmap_id_u.gid); 1138 break; 1139 1140 default: 1141 *result->stat = IDMAP_ERR_NORESULT; 1142 if (result->uid) 1143 *result->uid = UID_NOBODY; 1144 if (result->gid) 1145 *result->gid = GID_NOBODY; 1146 if (result->pid) 1147 *result->pid = UID_NOBODY; 1148 if (result->is_user) 1149 *result->is_user = 1; 1150 if (result->sid_prefix) 1151 *result->sid_prefix = NULL; 1152 if (result->rid) 1153 *result->rid = 0; 1154 break; 1155 } 1156 } 1157 xdr_free(xdr_idmap_ids_res, (char *)&results); 1158 } else { 1159 /* Door call failed */ 1160 status = IDMAP_ERR_NOMAPPING; 1161 for (i = 0; i < get_handle->mapping_num; i++) { 1162 result = &get_handle->result[i]; 1163 1164 *result->stat = IDMAP_ERR_NOMAPPING; 1165 if (result->uid) 1166 *result->uid = UID_NOBODY; 1167 if (result->gid) 1168 *result->gid = GID_NOBODY; 1169 if (result->pid) 1170 *result->pid = UID_NOBODY; 1171 if (result->is_user) 1172 *result->is_user = 1; 1173 if (result->sid_prefix) 1174 *result->sid_prefix = NULL; 1175 if (result->rid) 1176 *result->rid = 0; 1177 } 1178 } 1179 1180 /* Reset get_handle for new resquests */ 1181 get_handle->mapping_num = 0; 1182 return (status); 1183 } 1184 1185 1186 /* 1187 * Destroy the "get mapping" handle 1188 */ 1189 void 1190 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1191 { 1192 if (get_handle == NULL) 1193 return; 1194 1195 kmem_free(get_handle->mapping, 1196 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1197 get_handle->mapping = NULL; 1198 1199 kmem_free(get_handle->result, 1200 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1201 get_handle->result = NULL; 1202 1203 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1204 } 1205 1206 1207 static int 1208 kidmap_rpc_call(uint32_t op, xdrproc_t xdr_args, caddr_t args, 1209 xdrproc_t xdr_res, caddr_t res) 1210 { 1211 XDR xdr_ctx; 1212 struct rpc_msg reply_msg; 1213 char *inbuf_ptr = NULL; 1214 size_t inbuf_size = 4096; 1215 char *outbuf_ptr = NULL; 1216 size_t outbuf_size = 4096; 1217 size_t size; 1218 int status = 0; 1219 door_arg_t params; 1220 int retry = 0; 1221 1222 params.rbuf = NULL; 1223 params.rsize = 0; 1224 1225 retry: 1226 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1227 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1228 1229 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1230 atomic_inc_32(&call_msg.rm_xid); 1231 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1232 #ifdef DEBUG 1233 cmn_err(CE_WARN, "idmap: xdr encoding header error"); 1234 #endif /* DEBUG */ 1235 status = -1; 1236 goto exit; 1237 } 1238 1239 if (!xdr_uint32(&xdr_ctx, &op) || 1240 /* Auth none */ 1241 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1242 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1243 /* RPC args */ 1244 !xdr_args(&xdr_ctx, args)) { 1245 #ifdef DEBUG 1246 cmn_err(CE_WARN, "idmap: xdr encoding error"); 1247 #endif /* DEBUG */ 1248 if (retry > 2) { 1249 status = -1; 1250 goto exit; 1251 } 1252 retry++; 1253 if (inbuf_ptr) { 1254 kmem_free(inbuf_ptr, inbuf_size); 1255 inbuf_ptr = NULL; 1256 } 1257 if (outbuf_ptr) { 1258 kmem_free(outbuf_ptr, outbuf_size); 1259 outbuf_ptr = NULL; 1260 } 1261 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1262 #ifdef DEBUG 1263 cmn_err(CE_WARN, "idmap: xdr_sizeof error"); 1264 #endif /* DEBUG */ 1265 status = -1; 1266 goto exit; 1267 } 1268 inbuf_size = size + 1024; 1269 outbuf_size = size + 1024; 1270 goto retry; 1271 } 1272 1273 params.data_ptr = inbuf_ptr; 1274 params.data_size = XDR_GETPOS(&xdr_ctx); 1275 params.desc_ptr = NULL; 1276 params.desc_num = 0; 1277 params.rbuf = outbuf_ptr; 1278 params.rsize = outbuf_size; 1279 1280 if (kidmap_call_door(¶ms) != 0) { 1281 status = -1; 1282 goto exit; 1283 } 1284 1285 reply_msg.acpted_rply.ar_verf = _null_auth; 1286 reply_msg.acpted_rply.ar_results.where = res; 1287 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1288 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1289 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1290 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1291 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1292 status = -1; 1293 goto exit; 1294 } 1295 } else { 1296 #ifdef DEBUG 1297 cmn_err(CE_WARN, "idmap: xdr decoding reply message error"); 1298 #endif /* DEBUG */ 1299 status = -1; 1300 } 1301 1302 exit: 1303 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1304 kmem_free(params.rbuf, params.rsize); 1305 if (inbuf_ptr) 1306 kmem_free(inbuf_ptr, inbuf_size); 1307 if (outbuf_ptr) 1308 kmem_free(outbuf_ptr, outbuf_size); 1309 return (status); 1310 } 1311