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