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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 /* 27 * libidmap API 28 */ 29 30 #include <stdlib.h> 31 #include <sys/varargs.h> 32 #include <inttypes.h> 33 #include <errno.h> 34 #include <strings.h> 35 #include <ctype.h> 36 #include <sys/param.h> 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <dlfcn.h> 40 #include <libintl.h> 41 #include <ucontext.h> 42 #include <syslog.h> 43 #include <assert.h> 44 #include "idmap_impl.h" 45 #include "idmap_cache.h" 46 47 static struct timeval TIMEOUT = { 25, 0 }; 48 49 static int idmap_stat2errno(idmap_stat); 50 static idmap_stat idmap_strdupnull(char **, const char *); 51 52 #define __ITER_CREATE(itera, argu, handl, ityp)\ 53 if (handl == NULL) {\ 54 errno = EINVAL;\ 55 return (IDMAP_ERR_ARG);\ 56 }\ 57 itera = calloc(1, sizeof (*itera));\ 58 if (itera == NULL) {\ 59 errno = ENOMEM;\ 60 return (IDMAP_ERR_MEMORY);\ 61 }\ 62 argu = calloc(1, sizeof (*argu));\ 63 if (argu == NULL) {\ 64 free(itera);\ 65 errno = ENOMEM;\ 66 return (IDMAP_ERR_MEMORY);\ 67 }\ 68 itera->ih = handl;\ 69 itera->type = ityp;\ 70 itera->retcode = IDMAP_NEXT;\ 71 itera->limit = 1024;\ 72 itera->arg = argu; 73 74 75 #define __ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\ 76 if (argu) {\ 77 xdr_free(xdr_argu, (caddr_t)argu);\ 78 free(argu);\ 79 }\ 80 if (itera)\ 81 free(itera);\ 82 return (iretcod); 83 84 85 #define __ITER_CHECK(itera, ityp)\ 86 if (itera == NULL) {\ 87 errno = EINVAL;\ 88 return (IDMAP_ERR_ARG);\ 89 }\ 90 if (itera->type != ityp) {\ 91 errno = EINVAL;\ 92 return (IDMAP_ERR_ARG);\ 93 } 94 95 /* 96 * Free memory allocated by libidmap API 97 * 98 * Input: 99 * ptr - memory to be freed 100 */ 101 void 102 idmap_free(void *ptr) 103 { 104 free(ptr); 105 } 106 107 108 #define MIN_STACK_NEEDS 65536 109 110 /* 111 * Create and Initialize idmap client handle for rpc/doors 112 * 113 * Output: 114 * handle - idmap handle 115 */ 116 idmap_stat 117 idmap_init(idmap_handle_t **handle) 118 { 119 CLIENT *clnt = NULL; 120 struct idmap_handle *hptr; 121 uint_t sendsz = 0; 122 stack_t st; 123 124 *handle = NULL; 125 hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr)); 126 if (hptr == NULL) 127 return (IDMAP_ERR_MEMORY); 128 129 /* 130 * clnt_door_call() alloca()s sendsz bytes (twice too, once for 131 * the call args buffer and once for the call result buffer), so 132 * we want to pick a sendsz that will be large enough, but not 133 * too large. 134 */ 135 if (stack_getbounds(&st) == 0) { 136 /* 137 * Estimate how much stack space is left; 138 * st.ss_sp is the top of stack. 139 */ 140 if ((char *)&sendsz < (char *)st.ss_sp) 141 /* stack grows up */ 142 sendsz = ((char *)st.ss_sp - (char *)&sendsz); 143 else 144 /* stack grows down */ 145 sendsz = ((char *)&sendsz - (char *)st.ss_sp); 146 147 if (sendsz <= MIN_STACK_NEEDS) { 148 sendsz = 0; /* RPC call may fail */ 149 } else { 150 /* Leave 64Kb (just a guess) for our needs */ 151 sendsz -= MIN_STACK_NEEDS; 152 153 /* Divide the stack space left by two */ 154 sendsz = RNDUP(sendsz / 2); 155 156 /* Limit sendsz to 256KB */ 157 if (sendsz > IDMAP_MAX_DOOR_RPC) 158 sendsz = IDMAP_MAX_DOOR_RPC; 159 } 160 } 161 162 clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz); 163 if (clnt == NULL) { 164 free(hptr); 165 return (IDMAP_ERR_RPC); 166 } 167 hptr->type = _IDMAP_HANDLE_RPC_DOORS; 168 hptr->privhandle = clnt; 169 *handle = hptr; 170 return (IDMAP_SUCCESS); 171 } 172 173 174 /* 175 * Finalize idmap handle 176 * 177 * Input: 178 * handle - idmap handle 179 */ 180 idmap_stat 181 idmap_fini(idmap_handle_t *handle) 182 { 183 CLIENT *clnt; 184 struct idmap_handle *hptr; 185 186 if (handle == NULL) 187 return (IDMAP_SUCCESS); 188 189 hptr = (struct idmap_handle *)handle; 190 191 switch (hptr->type) { 192 case _IDMAP_HANDLE_RPC_DOORS: 193 clnt = (CLIENT *)hptr->privhandle; 194 if (clnt) { 195 if (clnt->cl_auth) 196 auth_destroy(clnt->cl_auth); 197 clnt_destroy(clnt); 198 } 199 break; 200 default: 201 break; 202 } 203 free(hptr); 204 return (IDMAP_SUCCESS); 205 } 206 207 208 static idmap_stat 209 idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res) 210 { 211 CLIENT *clnt; 212 enum clnt_stat clntstat; 213 214 215 (void) memset(res, 0, sizeof (*res)); 216 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 217 218 clntstat = clnt_call(clnt, IDMAP_GET_PROP, 219 (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr, 220 (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT); 221 222 if (clntstat != RPC_SUCCESS) { 223 return (_idmap_rpc2stat(clnt)); 224 } 225 226 return (res->retcode); /* This might not be IDMAP_SUCCESS! */ 227 } 228 229 230 idmap_stat 231 idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr, 232 idmap_ad_disc_ds_t *dc) 233 { 234 idmap_prop_res res; 235 idmap_stat rc = IDMAP_SUCCESS; 236 237 rc = idmap_get_prop(handle, pr, &res); 238 if (rc < 0) 239 return (rc); 240 241 dc->port = res.value.idmap_prop_val_u.dsval.port; 242 (void) strlcpy(dc->host, res.value.idmap_prop_val_u.dsval.host, 243 AD_DISC_MAXHOSTNAME); 244 245 /* xdr doesn't guarantee 0-termination of char[]: */ 246 dc->host[AD_DISC_MAXHOSTNAME - 1] = '\0'; 247 248 return (rc); 249 } 250 251 252 /* 253 * Sometimes the property is not set. In that case, str is set to NULL but 254 * otherwise IDMAP_SUCCESS is returned. 255 */ 256 idmap_stat 257 idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str) 258 { 259 idmap_prop_res res; 260 idmap_stat rc = IDMAP_SUCCESS; 261 262 rc = idmap_get_prop(handle, pr, &res); 263 if (rc < 0) 264 return (rc); 265 266 rc = idmap_strdupnull(str, res.value.idmap_prop_val_u.utf8val); 267 return (rc); 268 } 269 270 /* 271 * Create/Initialize handle for updates 272 * 273 * Output: 274 * udthandle - update handle 275 */ 276 idmap_stat 277 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) 278 { 279 idmap_udt_handle_t *tmp; 280 281 if (handle == NULL || udthandle == NULL) { 282 errno = EINVAL; 283 return (IDMAP_ERR_ARG); 284 } 285 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 286 errno = ENOMEM; 287 return (IDMAP_ERR_MEMORY); 288 } 289 290 tmp->ih = handle; 291 *udthandle = tmp; 292 return (IDMAP_SUCCESS); 293 } 294 295 296 /* 297 * All the updates specified by the update handle are committed 298 * in a single transaction. i.e either all succeed or none. 299 * 300 * Input: 301 * udthandle - update handle with the update requests 302 * 303 * Return value: 304 * Status of the commit 305 */ 306 idmap_stat 307 idmap_udt_commit(idmap_udt_handle_t *udthandle) 308 { 309 CLIENT *clnt; 310 enum clnt_stat clntstat; 311 idmap_update_res res; 312 idmap_stat retcode; 313 314 if (udthandle == NULL) { 315 errno = EINVAL; 316 return (IDMAP_ERR_ARG); 317 } 318 319 (void) memset(&res, 0, sizeof (res)); 320 321 _IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt); 322 clntstat = clnt_call(clnt, IDMAP_UPDATE, 323 (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch, 324 (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res, 325 TIMEOUT); 326 327 if (clntstat != RPC_SUCCESS) { 328 retcode = _idmap_rpc2stat(clnt); 329 goto out; 330 } 331 332 retcode = udthandle->commit_stat = res.retcode; 333 udthandle->error_index = res.error_index; 334 335 if (retcode != IDMAP_SUCCESS) { 336 337 if (udthandle->error_index < 0) 338 goto out; 339 340 retcode = idmap_namerule_cpy(&udthandle->error_rule, 341 &res.error_rule); 342 if (retcode != IDMAP_SUCCESS) { 343 udthandle->error_index = -2; 344 goto out; 345 } 346 347 retcode = idmap_namerule_cpy(&udthandle->conflict_rule, 348 &res.conflict_rule); 349 if (retcode != IDMAP_SUCCESS) { 350 udthandle->error_index = -2; 351 goto out; 352 } 353 } 354 355 retcode = res.retcode; 356 357 358 out: 359 /* reset handle so that it can be used again */ 360 if (retcode == IDMAP_SUCCESS) { 361 _IDMAP_RESET_UDT_HANDLE(udthandle); 362 } 363 364 (void) xdr_free(xdr_idmap_update_res, (caddr_t)&res); 365 errno = idmap_stat2errno(retcode); 366 return (retcode); 367 } 368 369 370 static void 371 idmap_namerule_parts_clear(char **windomain, char **winname, 372 char **unixname, boolean_t *is_user, boolean_t *is_wuser, 373 boolean_t *is_nt4, int *direction) 374 { 375 if (windomain) 376 *windomain = NULL; 377 if (winname) 378 *winname = NULL; 379 if (unixname) 380 *unixname = NULL; 381 382 if (is_nt4) 383 *is_nt4 = 0; 384 if (is_user) 385 *is_user = -1; 386 if (is_wuser) 387 *is_wuser = -1; 388 if (direction) 389 *direction = IDMAP_DIRECTION_UNDEF; 390 } 391 392 static idmap_stat 393 idmap_namerule2parts(idmap_namerule *rule, 394 char **windomain, char **winname, 395 char **unixname, boolean_t *is_user, boolean_t *is_wuser, 396 boolean_t *is_nt4, int *direction) 397 { 398 idmap_stat retcode; 399 400 if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 401 return (IDMAP_ERR_NORESULT); 402 403 404 retcode = idmap_strdupnull(windomain, rule->windomain); 405 if (retcode != IDMAP_SUCCESS) 406 goto errout; 407 408 retcode = idmap_strdupnull(winname, rule->winname); 409 if (retcode != IDMAP_SUCCESS) 410 goto errout; 411 412 retcode = idmap_strdupnull(unixname, rule->unixname); 413 if (retcode != IDMAP_SUCCESS) 414 goto errout; 415 416 417 if (is_user) 418 *is_user = rule->is_user; 419 if (is_wuser) 420 *is_wuser = rule->is_wuser; 421 if (is_nt4) 422 *is_nt4 = rule->is_nt4; 423 if (direction) 424 *direction = rule->direction; 425 426 427 return (IDMAP_SUCCESS); 428 429 errout: 430 if (windomain && *windomain) 431 free(*windomain); 432 if (winname && *winname) 433 free(*winname); 434 if (unixname && *unixname) 435 free(*unixname); 436 437 idmap_namerule_parts_clear(windomain, winname, 438 unixname, is_user, is_wuser, is_nt4, direction); 439 440 return (retcode); 441 442 } 443 444 /* 445 * Retrieve the index of the failed batch element. error_index == -1 446 * indicates failure at the beginning, -2 at the end. 447 * 448 * If idmap_udt_commit didn't return error, the returned value is undefined. 449 * 450 * Return value: 451 * IDMAP_SUCCESS 452 */ 453 454 idmap_stat 455 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle, 456 int64_t *error_index) 457 { 458 if (error_index) 459 *error_index = udthandle->error_index; 460 461 return (IDMAP_SUCCESS); 462 } 463 464 465 /* 466 * Retrieve the rule which caused the batch to fail. If 467 * idmap_udt_commit didn't return error or if error_index is < 0, the 468 * retrieved rule is undefined. 469 * 470 * Return value: 471 * IDMAP_ERR_NORESULT if there is no error rule. 472 * IDMAP_SUCCESS if the rule was obtained OK. 473 * other error code (IDMAP_ERR_NOMEMORY etc) 474 */ 475 476 idmap_stat 477 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle, 478 char **windomain, char **winname, 479 char **unixname, boolean_t *is_user, boolean_t *is_wuser, 480 boolean_t *is_nt4, int *direction) 481 { 482 idmap_namerule_parts_clear(windomain, winname, 483 unixname, is_user, is_wuser, is_nt4, direction); 484 485 if (udthandle->commit_stat == IDMAP_SUCCESS || 486 udthandle->error_index < 0) 487 return (IDMAP_ERR_NORESULT); 488 489 return (idmap_namerule2parts( 490 &udthandle->error_rule, 491 windomain, 492 winname, 493 unixname, 494 is_user, 495 is_wuser, 496 is_nt4, 497 direction)); 498 } 499 500 /* 501 * Retrieve the rule with which there was a conflict. TODO: retrieve 502 * the value. 503 * 504 * Return value: 505 * IDMAP_ERR_NORESULT if there is no error rule. 506 * IDMAP_SUCCESS if the rule was obtained OK. 507 * other error code (IDMAP_ERR_NOMEMORY etc) 508 */ 509 510 idmap_stat 511 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle, 512 char **windomain, char **winname, 513 char **unixname, boolean_t *is_user, boolean_t *is_wuser, 514 boolean_t *is_nt4, int *direction) 515 { 516 idmap_namerule_parts_clear(windomain, winname, 517 unixname, is_user, is_wuser, is_nt4, direction); 518 519 if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT && 520 udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) { 521 return (IDMAP_ERR_NORESULT); 522 } 523 524 return (idmap_namerule2parts( 525 &udthandle->conflict_rule, 526 windomain, 527 winname, 528 unixname, 529 is_user, 530 is_wuser, 531 is_nt4, 532 direction)); 533 } 534 535 536 /* 537 * Destroy the update handle 538 */ 539 void 540 idmap_udt_destroy(idmap_udt_handle_t *udthandle) 541 { 542 if (udthandle == NULL) 543 return; 544 (void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch); 545 (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule); 546 (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule); 547 free(udthandle); 548 } 549 550 551 idmap_stat 552 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain, 553 boolean_t is_user, boolean_t is_wuser, const char *winname, 554 const char *unixname, boolean_t is_nt4, int direction) 555 { 556 idmap_retcode retcode; 557 idmap_namerule *rule = NULL; 558 559 retcode = _udt_extend_batch(udthandle); 560 if (retcode != IDMAP_SUCCESS) 561 goto errout; 562 563 rule = &udthandle->batch. 564 idmap_update_batch_val[udthandle->next]. 565 idmap_update_op_u.rule; 566 rule->is_user = is_user; 567 rule->is_wuser = is_wuser; 568 rule->direction = direction; 569 rule->is_nt4 = is_nt4; 570 571 retcode = idmap_strdupnull(&rule->windomain, windomain); 572 if (retcode != IDMAP_SUCCESS) 573 goto errout; 574 575 retcode = idmap_strdupnull(&rule->winname, winname); 576 if (retcode != IDMAP_SUCCESS) 577 goto errout; 578 579 retcode = idmap_strdupnull(&rule->unixname, unixname); 580 if (retcode != IDMAP_SUCCESS) 581 goto errout; 582 583 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 584 OP_ADD_NAMERULE; 585 udthandle->next++; 586 return (IDMAP_SUCCESS); 587 588 errout: 589 /* The batch should still be usable */ 590 if (rule) 591 (void) xdr_free(xdr_idmap_namerule, (caddr_t)rule); 592 errno = idmap_stat2errno(retcode); 593 return (retcode); 594 } 595 596 597 /* ARGSUSED */ 598 idmap_stat 599 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user, 600 boolean_t is_wuser, const char *windomain, const char *winname, 601 const char *unixname, int direction) 602 { 603 idmap_retcode retcode; 604 idmap_namerule *rule = NULL; 605 606 retcode = _udt_extend_batch(udthandle); 607 if (retcode != IDMAP_SUCCESS) 608 goto errout; 609 610 rule = &udthandle->batch. 611 idmap_update_batch_val[udthandle->next]. 612 idmap_update_op_u.rule; 613 rule->is_user = is_user; 614 rule->is_wuser = is_wuser; 615 rule->direction = direction; 616 617 retcode = idmap_strdupnull(&rule->windomain, windomain); 618 if (retcode != IDMAP_SUCCESS) 619 goto errout; 620 621 retcode = idmap_strdupnull(&rule->winname, winname); 622 if (retcode != IDMAP_SUCCESS) 623 goto errout; 624 625 retcode = idmap_strdupnull(&rule->unixname, unixname); 626 if (retcode != IDMAP_SUCCESS) 627 goto errout; 628 629 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 630 OP_RM_NAMERULE; 631 udthandle->next++; 632 return (IDMAP_SUCCESS); 633 634 errout: 635 if (rule) 636 (void) xdr_free(xdr_idmap_namerule, (caddr_t)rule); 637 errno = idmap_stat2errno(retcode); 638 return (retcode); 639 } 640 641 642 /* ARGSUSED */ 643 idmap_stat 644 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle) 645 { 646 idmap_retcode retcode; 647 648 retcode = _udt_extend_batch(udthandle); 649 if (retcode != IDMAP_SUCCESS) 650 goto errout; 651 652 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 653 OP_FLUSH_NAMERULES; 654 udthandle->next++; 655 return (IDMAP_SUCCESS); 656 657 errout: 658 errno = idmap_stat2errno(retcode); 659 return (retcode); 660 } 661 662 663 /* 664 * Set the number of entries requested per batch by the iterator 665 * 666 * Input: 667 * iter - iterator 668 * limit - number of entries requested per batch 669 */ 670 idmap_stat 671 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) 672 { 673 if (iter == NULL) { 674 errno = EINVAL; 675 return (IDMAP_ERR_ARG); 676 } 677 iter->limit = limit; 678 return (IDMAP_SUCCESS); 679 } 680 681 682 /* 683 * Create iterator to get name-based mapping rules 684 * 685 * Input: 686 * windomain - Windows domain 687 * is_user - user or group rules 688 * winname - Windows user or group name 689 * unixname - Unix user or group name 690 * 691 * Output: 692 * iter - iterator 693 */ 694 idmap_stat 695 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain, 696 boolean_t is_user, boolean_t is_wuser, const char *winname, 697 const char *unixname, idmap_iter_t **iter) 698 { 699 700 idmap_iter_t *tmpiter; 701 idmap_list_namerules_1_argument *arg = NULL; 702 idmap_namerule *rule; 703 idmap_retcode retcode; 704 705 __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES); 706 707 rule = &arg->rule; 708 rule->is_user = is_user; 709 rule->is_wuser = is_wuser; 710 rule->direction = IDMAP_DIRECTION_UNDEF; 711 712 retcode = idmap_strdupnull(&rule->windomain, windomain); 713 if (retcode != IDMAP_SUCCESS) 714 goto errout; 715 716 retcode = idmap_strdupnull(&rule->winname, winname); 717 if (retcode != IDMAP_SUCCESS) 718 goto errout; 719 720 retcode = idmap_strdupnull(&rule->unixname, unixname); 721 if (retcode != IDMAP_SUCCESS) 722 goto errout; 723 724 *iter = tmpiter; 725 return (IDMAP_SUCCESS); 726 727 errout: 728 __ITER_ERR_RETURN(tmpiter, arg, 729 xdr_idmap_list_namerules_1_argument, retcode); 730 } 731 732 733 /* 734 * Iterate through the name-based mapping rules 735 * 736 * Input: 737 * iter - iterator 738 * 739 * Output: 740 * windomain - Windows domain 741 * winname - Windows user or group name 742 * unixname - Unix user or group name 743 * is_nt4 - NT4 or AD 744 * direction - bi(0), win2unix(1), unix2win(2) 745 * 746 * Return value: 747 * 0 - done 748 * 1 - more results available 749 * < 0 - error 750 */ 751 idmap_stat 752 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain, 753 char **winname, char **unixname, boolean_t *is_user, 754 boolean_t *is_wuser, boolean_t *is_nt4, int *direction) 755 { 756 idmap_namerules_res *namerules; 757 idmap_list_namerules_1_argument *arg; 758 idmap_retcode retcode; 759 760 idmap_namerule_parts_clear(windomain, winname, 761 unixname, is_user, is_wuser, is_nt4, direction); 762 763 764 __ITER_CHECK(iter, IDMAP_LIST_NAMERULES); 765 766 namerules = (idmap_namerules_res *)iter->retlist; 767 if (iter->retcode == IDMAP_NEXT && (namerules == NULL || 768 iter->next >= namerules->rules.rules_len)) { 769 770 if ((arg = iter->arg) == NULL) { 771 errno = EINVAL; 772 return (IDMAP_ERR_ARG); 773 } 774 arg->limit = iter->limit; 775 776 retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES, 777 iter, arg, 778 (uchar_t **)&namerules, sizeof (*namerules), 779 (xdrproc_t)xdr_idmap_list_namerules_1_argument, 780 (xdrproc_t)xdr_idmap_namerules_res); 781 if (retcode != IDMAP_SUCCESS) 782 return (retcode); 783 784 if (IDMAP_ERROR(namerules->retcode)) { 785 retcode = namerules->retcode; 786 xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules); 787 free(namerules); 788 iter->retlist = NULL; 789 return (retcode); 790 } 791 iter->retcode = namerules->retcode; 792 arg->lastrowid = namerules->lastrowid; 793 } 794 795 if (namerules == NULL || namerules->rules.rules_len == 0) 796 return (IDMAP_SUCCESS); 797 798 if (iter->next >= namerules->rules.rules_len) { 799 return (IDMAP_ERR_ARG); 800 } 801 802 retcode = idmap_strdupnull(windomain, 803 namerules->rules.rules_val[iter->next].windomain); 804 if (retcode != IDMAP_SUCCESS) 805 goto errout; 806 807 retcode = idmap_strdupnull(winname, 808 namerules->rules.rules_val[iter->next].winname); 809 if (retcode != IDMAP_SUCCESS) 810 goto errout; 811 812 retcode = idmap_strdupnull(unixname, 813 namerules->rules.rules_val[iter->next].unixname); 814 if (retcode != IDMAP_SUCCESS) 815 goto errout; 816 817 if (is_nt4) 818 *is_nt4 = namerules->rules.rules_val[iter->next].is_nt4; 819 if (is_user) 820 *is_user = namerules->rules.rules_val[iter->next].is_user; 821 if (is_wuser) 822 *is_wuser = namerules->rules.rules_val[iter->next].is_wuser; 823 if (direction) 824 *direction = namerules->rules.rules_val[iter->next].direction; 825 iter->next++; 826 827 if (iter->next == namerules->rules.rules_len) 828 return (iter->retcode); 829 else 830 return (IDMAP_NEXT); 831 832 errout: 833 if (windomain && *windomain) 834 free(*windomain); 835 if (winname && *winname) 836 free(*winname); 837 if (unixname && *unixname) 838 free(*unixname); 839 return (retcode); 840 } 841 842 843 /* 844 * Create iterator to get SID to UID/GID mappings 845 * 846 * Output: 847 * iter - iterator 848 */ 849 idmap_stat 850 idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag) 851 { 852 idmap_iter_t *tmpiter; 853 idmap_list_mappings_1_argument *arg = NULL; 854 855 __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS); 856 857 arg->flag = flag; 858 *iter = tmpiter; 859 return (IDMAP_SUCCESS); 860 } 861 862 863 /* 864 * Iterate through the SID to UID/GID mappings 865 * 866 * Input: 867 * iter - iterator 868 * 869 * Output: 870 * sid - SID in canonical form 871 * pid - UID or GID 872 * 873 * Return value: 874 * 0 - done 875 * 1 - more results available 876 * < 0 - error 877 */ 878 idmap_stat 879 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix, 880 idmap_rid_t *rid, uid_t *pid, char **winname, 881 char **windomain, char **unixname, boolean_t *is_user, 882 boolean_t *is_wuser, int *direction, idmap_info *info) 883 { 884 idmap_mappings_res *mappings; 885 idmap_list_mappings_1_argument *arg; 886 idmap_retcode retcode; 887 char *str; 888 889 if (sidprefix) 890 *sidprefix = NULL; 891 if (rid) 892 *rid = UINT32_MAX; 893 if (winname) 894 *winname = NULL; 895 if (windomain) 896 *windomain = NULL; 897 if (unixname) 898 *unixname = NULL; 899 if (pid) 900 *pid = UINT32_MAX; 901 if (is_user) 902 *is_user = -1; 903 if (is_wuser) 904 *is_wuser = -1; 905 if (direction) 906 *direction = IDMAP_DIRECTION_UNDEF; 907 908 __ITER_CHECK(iter, IDMAP_LIST_MAPPINGS); 909 910 mappings = (idmap_mappings_res *)iter->retlist; 911 if (iter->retcode == IDMAP_NEXT && (mappings == NULL || 912 iter->next >= mappings->mappings.mappings_len)) { 913 914 if ((arg = iter->arg) == NULL) { 915 errno = EINVAL; 916 return (IDMAP_ERR_ARG); 917 } 918 arg->limit = iter->limit; 919 920 retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS, 921 iter, arg, 922 (uchar_t **)&mappings, sizeof (*mappings), 923 (xdrproc_t)xdr_idmap_list_mappings_1_argument, 924 (xdrproc_t)xdr_idmap_mappings_res); 925 if (retcode != IDMAP_SUCCESS) 926 return (retcode); 927 928 if (IDMAP_ERROR(mappings->retcode)) { 929 retcode = mappings->retcode; 930 xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings); 931 free(mappings); 932 iter->retlist = NULL; 933 return (retcode); 934 } 935 iter->retcode = mappings->retcode; 936 arg->lastrowid = mappings->lastrowid; 937 } 938 939 if (mappings == NULL || mappings->mappings.mappings_len == 0) 940 return (IDMAP_SUCCESS); 941 942 if (iter->next >= mappings->mappings.mappings_len) { 943 return (IDMAP_ERR_ARG); 944 } 945 946 if (sidprefix) { 947 str = mappings->mappings.mappings_val[iter->next].id1. 948 idmap_id_u.sid.prefix; 949 if (str && *str != '\0') { 950 *sidprefix = strdup(str); 951 if (*sidprefix == NULL) { 952 retcode = IDMAP_ERR_MEMORY; 953 goto errout; 954 } 955 } 956 } 957 if (rid) 958 *rid = mappings->mappings.mappings_val[iter->next].id1. 959 idmap_id_u.sid.rid; 960 961 retcode = idmap_strdupnull(windomain, 962 mappings->mappings.mappings_val[iter->next].id1domain); 963 if (retcode != IDMAP_SUCCESS) 964 goto errout; 965 966 retcode = idmap_strdupnull(winname, 967 mappings->mappings.mappings_val[iter->next].id1name); 968 if (retcode != IDMAP_SUCCESS) 969 goto errout; 970 971 retcode = idmap_strdupnull(unixname, 972 mappings->mappings.mappings_val[iter->next].id2name); 973 if (retcode != IDMAP_SUCCESS) 974 goto errout; 975 976 977 if (pid) 978 *pid = mappings->mappings.mappings_val[iter->next].id2. 979 idmap_id_u.uid; 980 if (direction) 981 *direction = mappings->mappings.mappings_val[iter->next]. 982 direction; 983 if (is_user) 984 *is_user = (mappings->mappings.mappings_val[iter->next].id2 985 .idtype == IDMAP_UID)?1:0; 986 if (is_wuser) 987 *is_wuser = (mappings->mappings.mappings_val[iter->next].id1 988 .idtype == IDMAP_USID)?1:0; 989 990 if (info) { 991 idmap_info_mov(info, 992 &mappings->mappings.mappings_val[iter->next].info); 993 } 994 iter->next++; 995 996 if (iter->next == mappings->mappings.mappings_len) 997 return (iter->retcode); 998 else 999 return (IDMAP_NEXT); 1000 1001 errout: 1002 if (sidprefix && *sidprefix) 1003 free(*sidprefix); 1004 if (winname && *winname) 1005 free(*winname); 1006 if (windomain && *windomain) 1007 free(*windomain); 1008 if (unixname && *unixname) 1009 free(*unixname); 1010 return (retcode); 1011 } 1012 1013 1014 /* 1015 * Destroy the iterator 1016 */ 1017 void 1018 idmap_iter_destroy(idmap_iter_t *iter) 1019 { 1020 xdrproc_t _xdr_argument, _xdr_result; 1021 1022 if (iter == NULL) 1023 return; 1024 1025 switch (iter->type) { 1026 case IDMAP_LIST_NAMERULES: 1027 _xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument; 1028 _xdr_result = (xdrproc_t)xdr_idmap_namerules_res; 1029 break; 1030 case IDMAP_LIST_MAPPINGS: 1031 _xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument; 1032 _xdr_result = (xdrproc_t)xdr_idmap_mappings_res; 1033 break; 1034 default: 1035 free(iter); 1036 return; 1037 }; 1038 1039 if (iter->arg) { 1040 xdr_free(_xdr_argument, (caddr_t)iter->arg); 1041 free(iter->arg); 1042 } 1043 if (iter->retlist) { 1044 xdr_free(_xdr_result, (caddr_t)iter->retlist); 1045 free(iter->retlist); 1046 } 1047 free(iter); 1048 } 1049 1050 1051 /* 1052 * Create handle to get SID to UID/GID mapping entries 1053 * 1054 * Input: 1055 * gh - "get mapping" handle 1056 */ 1057 idmap_stat 1058 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) 1059 { 1060 idmap_get_handle_t *tmp; 1061 1062 /* sanity checks */ 1063 if (handle == NULL || gh == NULL) { 1064 errno = EINVAL; 1065 return (IDMAP_ERR_ARG); 1066 } 1067 1068 /* allocate the handle */ 1069 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 1070 errno = ENOMEM; 1071 return (IDMAP_ERR_MEMORY); 1072 } 1073 1074 tmp->ih = handle; 1075 *gh = tmp; 1076 return (IDMAP_SUCCESS); 1077 } 1078 1079 1080 /* 1081 * Given SID, get UID 1082 * 1083 * Input: 1084 * sidprefix - SID prefix 1085 * rid - RID 1086 * flag - flag 1087 * 1088 * Output: 1089 * stat - status of the get request 1090 * uid - POSIX UID if stat = 0 1091 * 1092 * Note: The output parameters will be set by idmap_get_mappings() 1093 */ 1094 idmap_stat 1095 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1096 int flag, uid_t *uid, idmap_stat *stat) 1097 { 1098 return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid, 1099 NULL, stat)); 1100 } 1101 1102 /* 1103 * Given SID, get UID 1104 * 1105 * Input: 1106 * sidprefix - SID prefix 1107 * rid - RID 1108 * flag - flag 1109 * 1110 * Output: 1111 * stat - status of the get request 1112 * uid - POSIX UID if stat = 0 1113 * how - mapping type if stat = 0 1114 * 1115 * Note: The output parameters will be set by idmap_get_mappings() 1116 */ 1117 1118 idmap_stat 1119 idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1120 int flag, uid_t *uid, idmap_info *info, idmap_stat *stat) 1121 { 1122 idmap_retcode retcode; 1123 idmap_mapping *mapping = NULL; 1124 1125 /* sanity checks */ 1126 if (gh == NULL) 1127 return (IDMAP_ERR_ARG); 1128 if (uid == NULL || sidprefix == NULL) 1129 return (IDMAP_ERR_ARG); 1130 1131 if ((flag & IDMAP_REQ_FLG_USE_CACHE) && 1132 !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) { 1133 retcode = idmap_cache_lookup_uidbysid(sidprefix, rid, uid); 1134 if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) { 1135 *stat = retcode; 1136 return (retcode); 1137 } 1138 } 1139 1140 /* Extend the request array and the return list */ 1141 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1142 goto errout; 1143 1144 /* Setup the request */ 1145 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1146 mapping->flag = flag; 1147 mapping->id1.idtype = IDMAP_SID; 1148 mapping->id1.idmap_id_u.sid.rid = rid; 1149 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1150 retcode = IDMAP_ERR_MEMORY; 1151 goto errout; 1152 } 1153 mapping->id2.idtype = IDMAP_UID; 1154 1155 /* Setup pointers for the result */ 1156 gh->retlist[gh->next].idtype = IDMAP_UID; 1157 gh->retlist[gh->next].uid = uid; 1158 gh->retlist[gh->next].stat = stat; 1159 gh->retlist[gh->next].info = info; 1160 gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE; 1161 1162 gh->next++; 1163 return (IDMAP_SUCCESS); 1164 1165 errout: 1166 /* Batch created so far should still be usable */ 1167 if (mapping) 1168 (void) memset(mapping, 0, sizeof (*mapping)); 1169 errno = idmap_stat2errno(retcode); 1170 return (retcode); 1171 } 1172 1173 1174 /* 1175 * Given SID, get GID 1176 * 1177 * Input: 1178 * sidprefix - SID prefix 1179 * rid - rid 1180 * flag - flag 1181 * 1182 * Output: 1183 * stat - status of the get request 1184 * gid - POSIX GID if stat = 0 1185 * 1186 * Note: The output parameters will be set by idmap_get_mappings() 1187 */ 1188 idmap_stat 1189 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1190 int flag, gid_t *gid, idmap_stat *stat) 1191 { 1192 return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid, 1193 NULL, stat)); 1194 } 1195 1196 1197 /* 1198 * Given SID, get GID 1199 * 1200 * Input: 1201 * sidprefix - SID prefix 1202 * rid - rid 1203 * flag - flag 1204 * 1205 * Output: 1206 * stat - status of the get request 1207 * gid - POSIX GID if stat = 0 1208 * how - mapping type if stat = 0 1209 * 1210 * Note: The output parameters will be set by idmap_get_mappings() 1211 */ 1212 idmap_stat 1213 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1214 int flag, gid_t *gid, idmap_info *info, idmap_stat *stat) 1215 { 1216 1217 idmap_retcode retcode; 1218 idmap_mapping *mapping = NULL; 1219 1220 /* sanity checks */ 1221 if (gh == NULL) 1222 return (IDMAP_ERR_ARG); 1223 if (gid == NULL || sidprefix == NULL) 1224 return (IDMAP_ERR_ARG); 1225 1226 if ((flag & IDMAP_REQ_FLG_USE_CACHE) && 1227 !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) { 1228 retcode = idmap_cache_lookup_gidbysid(sidprefix, rid, gid); 1229 if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) { 1230 *stat = retcode; 1231 return (retcode); 1232 } 1233 } 1234 1235 /* Extend the request array and the return list */ 1236 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1237 goto errout; 1238 1239 /* Setup the request */ 1240 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1241 mapping->flag = flag; 1242 mapping->id1.idtype = IDMAP_SID; 1243 mapping->id1.idmap_id_u.sid.rid = rid; 1244 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1245 retcode = IDMAP_ERR_MEMORY; 1246 goto errout; 1247 } 1248 mapping->id2.idtype = IDMAP_GID; 1249 1250 /* Setup pointers for the result */ 1251 gh->retlist[gh->next].idtype = IDMAP_GID; 1252 gh->retlist[gh->next].gid = gid; 1253 gh->retlist[gh->next].stat = stat; 1254 gh->retlist[gh->next].info = info; 1255 gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE; 1256 1257 gh->next++; 1258 return (IDMAP_SUCCESS); 1259 1260 errout: 1261 if (mapping) 1262 (void) memset(mapping, 0, sizeof (*mapping)); 1263 errno = idmap_stat2errno(retcode); 1264 return (retcode); 1265 } 1266 1267 1268 1269 /* 1270 * Given SID, get POSIX ID i.e. UID/GID 1271 * 1272 * Input: 1273 * sidprefix - SID prefix 1274 * rid - rid 1275 * flag - flag 1276 * 1277 * Output: 1278 * stat - status of the get request 1279 * is_user - user or group 1280 * pid - POSIX UID if stat = 0 and is_user = 1 1281 * POSIX GID if stat = 0 and is_user = 0 1282 * 1283 * Note: The output parameters will be set by idmap_get_mappings() 1284 */ 1285 idmap_stat 1286 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1287 int flag, uid_t *pid, int *is_user, idmap_stat *stat) 1288 { 1289 return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user, 1290 NULL, stat)); 1291 } 1292 1293 1294 1295 /* 1296 * Given SID, get POSIX ID i.e. UID/GID 1297 * 1298 * Input: 1299 * sidprefix - SID prefix 1300 * rid - rid 1301 * flag - flag 1302 * 1303 * Output: 1304 * stat - status of the get request 1305 * is_user - user or group 1306 * pid - POSIX UID if stat = 0 and is_user = 1 1307 * POSIX GID if stat = 0 and is_user = 0 1308 * how - mapping type if stat = 0 1309 * 1310 * Note: The output parameters will be set by idmap_get_mappings() 1311 */ 1312 idmap_stat 1313 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1314 int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat) 1315 { 1316 idmap_retcode retcode; 1317 idmap_mapping *mapping = NULL; 1318 1319 /* sanity checks */ 1320 if (gh == NULL) 1321 return (IDMAP_ERR_ARG); 1322 if (pid == NULL || sidprefix == NULL || is_user == NULL) 1323 return (IDMAP_ERR_ARG); 1324 1325 if ((flag & IDMAP_REQ_FLG_USE_CACHE) && 1326 !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) { 1327 retcode = idmap_cache_lookup_pidbysid(sidprefix, rid, pid, 1328 is_user); 1329 if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) { 1330 *stat = retcode; 1331 return (retcode); 1332 } 1333 } 1334 1335 /* Extend the request array and the return list */ 1336 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1337 goto errout; 1338 1339 /* Setup the request */ 1340 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1341 mapping->flag = flag; 1342 mapping->id1.idtype = IDMAP_SID; 1343 mapping->id1.idmap_id_u.sid.rid = rid; 1344 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1345 retcode = IDMAP_ERR_MEMORY; 1346 goto errout; 1347 } 1348 mapping->id2.idtype = IDMAP_POSIXID; 1349 1350 /* Setup pointers for the result */ 1351 gh->retlist[gh->next].idtype = IDMAP_POSIXID; 1352 gh->retlist[gh->next].uid = pid; 1353 gh->retlist[gh->next].gid = pid; 1354 gh->retlist[gh->next].is_user = is_user; 1355 gh->retlist[gh->next].stat = stat; 1356 gh->retlist[gh->next].info = info; 1357 gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE; 1358 1359 gh->next++; 1360 return (IDMAP_SUCCESS); 1361 1362 errout: 1363 if (mapping) 1364 (void) memset(mapping, 0, sizeof (*mapping)); 1365 errno = idmap_stat2errno(retcode); 1366 return (retcode); 1367 } 1368 1369 1370 /* 1371 * Given UID, get SID 1372 * 1373 * Input: 1374 * uid - POSIX UID 1375 * flag - flag 1376 * 1377 * Output: 1378 * stat - status of the get request 1379 * sid - SID prefix (if stat == 0) 1380 * rid - rid 1381 * 1382 * Note: The output parameters will be set by idmap_get_mappings() 1383 */ 1384 idmap_stat 1385 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, 1386 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) 1387 { 1388 return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid, 1389 NULL, stat)); 1390 } 1391 1392 1393 /* 1394 * Given UID, get SID 1395 * 1396 * Input: 1397 * uid - POSIX UID 1398 * flag - flag 1399 * 1400 * Output: 1401 * stat - status of the get request 1402 * sid - SID prefix (if stat == 0) 1403 * rid - rid 1404 * how - mapping type if stat = 0 1405 * 1406 * Note: The output parameters will be set by idmap_get_mappings() 1407 */ 1408 idmap_stat 1409 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, 1410 char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) 1411 { 1412 1413 idmap_retcode retcode; 1414 idmap_mapping *mapping = NULL; 1415 1416 /* sanity checks */ 1417 if (gh == NULL) 1418 return (IDMAP_ERR_ARG); 1419 if (sidprefix == NULL) 1420 return (IDMAP_ERR_ARG); 1421 1422 if ((flag & IDMAP_REQ_FLG_USE_CACHE) && 1423 !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) { 1424 retcode = idmap_cache_lookup_sidbyuid(sidprefix, rid, uid); 1425 if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) { 1426 *stat = retcode; 1427 return (retcode); 1428 } 1429 } 1430 1431 /* Extend the request array and the return list */ 1432 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1433 goto errout; 1434 1435 /* Setup the request */ 1436 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1437 mapping->flag = flag; 1438 mapping->id1.idtype = IDMAP_UID; 1439 mapping->id1.idmap_id_u.uid = uid; 1440 mapping->id2.idtype = IDMAP_SID; 1441 1442 /* Setup pointers for the result */ 1443 gh->retlist[gh->next].idtype = IDMAP_SID; 1444 gh->retlist[gh->next].sidprefix = sidprefix; 1445 gh->retlist[gh->next].rid = rid; 1446 gh->retlist[gh->next].stat = stat; 1447 gh->retlist[gh->next].info = info; 1448 gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE; 1449 1450 gh->next++; 1451 return (IDMAP_SUCCESS); 1452 1453 errout: 1454 if (mapping) 1455 (void) memset(mapping, 0, sizeof (*mapping)); 1456 errno = idmap_stat2errno(retcode); 1457 return (retcode); 1458 } 1459 1460 1461 /* 1462 * Given GID, get SID 1463 * 1464 * Input: 1465 * gid - POSIX GID 1466 * flag - flag 1467 * 1468 * Output: 1469 * stat - status of the get request 1470 * sidprefix - SID prefix (if stat == 0) 1471 * rid - rid 1472 * 1473 * Note: The output parameters will be set by idmap_get_mappings() 1474 */ 1475 idmap_stat 1476 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, 1477 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) 1478 { 1479 return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid, 1480 NULL, stat)); 1481 } 1482 1483 1484 /* 1485 * Given GID, get SID 1486 * 1487 * Input: 1488 * gid - POSIX GID 1489 * flag - flag 1490 * 1491 * Output: 1492 * stat - status of the get request 1493 * sidprefix - SID prefix (if stat == 0) 1494 * rid - rid 1495 * how - mapping type if stat = 0 1496 * 1497 * Note: The output parameters will be set by idmap_get_mappings() 1498 */ 1499 idmap_stat 1500 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, 1501 char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) 1502 { 1503 1504 idmap_retcode retcode; 1505 idmap_mapping *mapping = NULL; 1506 1507 /* sanity checks */ 1508 if (gh == NULL) 1509 return (IDMAP_ERR_ARG); 1510 if (sidprefix == NULL) 1511 return (IDMAP_ERR_ARG); 1512 1513 if ((flag & IDMAP_REQ_FLG_USE_CACHE) && 1514 !(flag & IDMAP_REQ_FLG_MAPPING_INFO)) { 1515 retcode = idmap_cache_lookup_sidbygid(sidprefix, rid, gid); 1516 if (retcode == IDMAP_SUCCESS || retcode == IDMAP_ERR_MEMORY) { 1517 *stat = retcode; 1518 return (retcode); 1519 } 1520 } 1521 1522 /* Extend the request array and the return list */ 1523 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1524 goto errout; 1525 1526 /* Setup the request */ 1527 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1528 mapping->flag = flag; 1529 mapping->id1.idtype = IDMAP_GID; 1530 mapping->id1.idmap_id_u.gid = gid; 1531 mapping->id2.idtype = IDMAP_SID; 1532 1533 /* Setup pointers for the result */ 1534 gh->retlist[gh->next].idtype = IDMAP_SID; 1535 gh->retlist[gh->next].sidprefix = sidprefix; 1536 gh->retlist[gh->next].rid = rid; 1537 gh->retlist[gh->next].stat = stat; 1538 gh->retlist[gh->next].info = info; 1539 gh->retlist[gh->next].cache_res = flag & IDMAP_REQ_FLG_USE_CACHE; 1540 1541 gh->next++; 1542 return (IDMAP_SUCCESS); 1543 1544 errout: 1545 if (mapping) 1546 (void) memset(mapping, 0, sizeof (*mapping)); 1547 errno = idmap_stat2errno(retcode); 1548 return (retcode); 1549 } 1550 1551 1552 /* 1553 * Process the batched "get mapping" requests. The results (i.e. 1554 * status and identity) will be available in the data areas 1555 * provided by individual requests. 1556 */ 1557 idmap_stat 1558 idmap_get_mappings(idmap_get_handle_t *gh) 1559 { 1560 CLIENT *clnt; 1561 enum clnt_stat clntstat; 1562 idmap_retcode retcode; 1563 idmap_ids_res res; 1564 idmap_id *res_id; 1565 int i; 1566 idmap_id *req_id; 1567 int direction; 1568 1569 if (gh == NULL) { 1570 errno = EINVAL; 1571 return (IDMAP_ERR_ARG); 1572 } 1573 _IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt); 1574 1575 (void) memset(&res, 0, sizeof (idmap_ids_res)); 1576 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS, 1577 (xdrproc_t)xdr_idmap_mapping_batch, 1578 (caddr_t)&gh->batch, 1579 (xdrproc_t)xdr_idmap_ids_res, 1580 (caddr_t)&res, 1581 TIMEOUT); 1582 if (clntstat != RPC_SUCCESS) { 1583 retcode = _idmap_rpc2stat(clnt); 1584 goto out; 1585 } 1586 if (res.retcode != IDMAP_SUCCESS) { 1587 retcode = res.retcode; 1588 goto out; 1589 } 1590 for (i = 0; i < gh->next; i++) { 1591 if (i >= res.ids.ids_len) { 1592 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1593 continue; 1594 } 1595 *gh->retlist[i].stat = res.ids.ids_val[i].retcode; 1596 res_id = &res.ids.ids_val[i].id; 1597 direction = res.ids.ids_val[i].direction; 1598 req_id = &gh->batch.idmap_mapping_batch_val[i].id1; 1599 switch (res_id->idtype) { 1600 case IDMAP_UID: 1601 if (gh->retlist[i].uid) 1602 *gh->retlist[i].uid = res_id->idmap_id_u.uid; 1603 if (gh->retlist[i].is_user) 1604 *gh->retlist[i].is_user = 1; 1605 1606 if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS && 1607 gh->retlist[i].cache_res) { 1608 if (gh->retlist[i].is_user != NULL) 1609 idmap_cache_add_sid2pid( 1610 req_id->idmap_id_u.sid.prefix, 1611 req_id->idmap_id_u.sid.rid, 1612 res_id->idmap_id_u.uid, 1, 1613 direction); 1614 else 1615 idmap_cache_add_sid2uid( 1616 req_id->idmap_id_u.sid.prefix, 1617 req_id->idmap_id_u.sid.rid, 1618 res_id->idmap_id_u.uid, 1619 direction); 1620 } 1621 break; 1622 1623 case IDMAP_GID: 1624 if (gh->retlist[i].gid) 1625 *gh->retlist[i].gid = res_id->idmap_id_u.gid; 1626 if (gh->retlist[i].is_user) 1627 *gh->retlist[i].is_user = 0; 1628 1629 if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS && 1630 gh->retlist[i].cache_res) { 1631 if (gh->retlist[i].is_user != NULL) 1632 idmap_cache_add_sid2pid( 1633 req_id->idmap_id_u.sid.prefix, 1634 req_id->idmap_id_u.sid.rid, 1635 res_id->idmap_id_u.gid, 0, 1636 direction); 1637 else 1638 idmap_cache_add_sid2gid( 1639 req_id->idmap_id_u.sid.prefix, 1640 req_id->idmap_id_u.sid.rid, 1641 res_id->idmap_id_u.gid, 1642 direction); 1643 } 1644 break; 1645 1646 case IDMAP_POSIXID: 1647 if (gh->retlist[i].uid) 1648 *gh->retlist[i].uid = 60001; 1649 if (gh->retlist[i].is_user) 1650 *gh->retlist[i].is_user = -1; 1651 break; 1652 1653 case IDMAP_SID: 1654 case IDMAP_USID: 1655 case IDMAP_GSID: 1656 if (gh->retlist[i].rid) 1657 *gh->retlist[i].rid = 1658 res_id->idmap_id_u.sid.rid; 1659 if (gh->retlist[i].sidprefix) { 1660 if (res_id->idmap_id_u.sid.prefix == NULL || 1661 *res_id->idmap_id_u.sid.prefix == '\0') { 1662 *gh->retlist[i].sidprefix = NULL; 1663 break; 1664 } 1665 *gh->retlist[i].sidprefix = 1666 strdup(res_id->idmap_id_u.sid.prefix); 1667 if (*gh->retlist[i].sidprefix == NULL) 1668 *gh->retlist[i].stat = 1669 IDMAP_ERR_MEMORY; 1670 } 1671 if (res.ids.ids_val[i].retcode == IDMAP_SUCCESS && 1672 gh->retlist[i].cache_res) { 1673 if (req_id->idtype == IDMAP_UID) 1674 idmap_cache_add_sid2uid( 1675 res_id->idmap_id_u.sid.prefix, 1676 res_id->idmap_id_u.sid.rid, 1677 req_id->idmap_id_u.uid, 1678 direction); 1679 else /* req_id->idtype == IDMAP_GID */ 1680 idmap_cache_add_sid2gid( 1681 res_id->idmap_id_u.sid.prefix, 1682 res_id->idmap_id_u.sid.rid, 1683 req_id->idmap_id_u.gid, 1684 direction); 1685 } 1686 break; 1687 1688 case IDMAP_NONE: 1689 break; 1690 1691 default: 1692 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1693 break; 1694 } 1695 if (gh->retlist[i].info != NULL) { 1696 idmap_info_mov(gh->retlist[i].info, 1697 &res.ids.ids_val[i].info); 1698 } 1699 } 1700 retcode = IDMAP_SUCCESS; 1701 1702 out: 1703 _IDMAP_RESET_GET_HANDLE(gh); 1704 (void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res); 1705 errno = idmap_stat2errno(retcode); 1706 return (retcode); 1707 } 1708 1709 1710 /* 1711 * Destroy the "get mapping" handle 1712 */ 1713 void 1714 idmap_get_destroy(idmap_get_handle_t *gh) 1715 { 1716 if (gh == NULL) 1717 return; 1718 (void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch); 1719 if (gh->retlist) 1720 free(gh->retlist); 1721 free(gh); 1722 } 1723 1724 1725 /* 1726 * Get windows to unix mapping 1727 */ 1728 idmap_stat 1729 idmap_get_w2u_mapping(idmap_handle_t *handle, 1730 const char *sidprefix, idmap_rid_t *rid, 1731 const char *winname, const char *windomain, 1732 int flag, int *is_user, int *is_wuser, 1733 uid_t *pid, char **unixname, int *direction, idmap_info *info) 1734 { 1735 CLIENT *clnt; 1736 enum clnt_stat clntstat; 1737 idmap_mapping request, *mapping; 1738 idmap_mappings_res result; 1739 idmap_retcode retcode, rc; 1740 1741 if (handle == NULL) { 1742 errno = EINVAL; 1743 return (IDMAP_ERR_ARG); 1744 } 1745 1746 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1747 1748 (void) memset(&request, 0, sizeof (request)); 1749 (void) memset(&result, 0, sizeof (result)); 1750 1751 if (pid) 1752 *pid = UINT32_MAX; 1753 if (unixname) 1754 *unixname = NULL; 1755 if (direction) 1756 *direction = IDMAP_DIRECTION_UNDEF; 1757 1758 request.flag = flag; 1759 request.id1.idtype = IDMAP_SID; 1760 if (sidprefix && rid) { 1761 request.id1.idmap_id_u.sid.prefix = (char *)sidprefix; 1762 request.id1.idmap_id_u.sid.rid = *rid; 1763 } else if (winname) { 1764 retcode = idmap_strdupnull(&request.id1name, winname); 1765 if (retcode != IDMAP_SUCCESS) 1766 goto out; 1767 1768 retcode = idmap_strdupnull(&request.id1domain, windomain); 1769 if (retcode != IDMAP_SUCCESS) 1770 goto out; 1771 1772 request.id1.idmap_id_u.sid.prefix = NULL; 1773 } else { 1774 errno = EINVAL; 1775 return (IDMAP_ERR_ARG); 1776 } 1777 1778 if (*is_user == 1) 1779 request.id2.idtype = IDMAP_UID; 1780 else if (*is_user == 0) 1781 request.id2.idtype = IDMAP_GID; 1782 else 1783 request.id2.idtype = IDMAP_POSIXID; 1784 1785 if (*is_wuser == 1) 1786 request.id1.idtype = IDMAP_USID; 1787 else if (*is_wuser == 0) 1788 request.id1.idtype = IDMAP_GSID; 1789 else 1790 request.id1.idtype = IDMAP_SID; 1791 1792 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1793 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1794 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1795 TIMEOUT); 1796 1797 if (clntstat != RPC_SUCCESS) 1798 return (_idmap_rpc2stat(clnt)); 1799 1800 retcode = result.retcode; 1801 1802 if ((mapping = result.mappings.mappings_val) == NULL) { 1803 if (retcode == IDMAP_SUCCESS) 1804 retcode = IDMAP_ERR_NORESULT; 1805 goto out; 1806 } 1807 1808 if (info != NULL) 1809 idmap_info_mov(info, &mapping->info); 1810 1811 if (mapping->id2.idtype == IDMAP_UID) { 1812 *is_user = 1; 1813 } else if (mapping->id2.idtype == IDMAP_GID) { 1814 *is_user = 0; 1815 } else { 1816 goto out; 1817 } 1818 1819 if (mapping->id1.idtype == IDMAP_USID) { 1820 *is_wuser = 1; 1821 } else if (mapping->id1.idtype == IDMAP_GSID) { 1822 *is_wuser = 0; 1823 } else { 1824 goto out; 1825 } 1826 1827 if (direction) 1828 *direction = mapping->direction; 1829 if (pid) 1830 *pid = mapping->id2.idmap_id_u.uid; 1831 1832 rc = idmap_strdupnull(unixname, mapping->id2name); 1833 if (rc != IDMAP_SUCCESS) 1834 retcode = rc; 1835 1836 out: 1837 if (request.id1name != NULL) 1838 free(request.id1name); 1839 if (request.id1domain != NULL) 1840 free(request.id1domain); 1841 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1842 if (retcode != IDMAP_SUCCESS) 1843 errno = idmap_stat2errno(retcode); 1844 return (retcode); 1845 } 1846 1847 1848 /* 1849 * Get unix to windows mapping 1850 */ 1851 idmap_stat 1852 idmap_get_u2w_mapping(idmap_handle_t *handle, 1853 uid_t *pid, const char *unixname, 1854 int flag, int is_user, int *is_wuser, 1855 char **sidprefix, idmap_rid_t *rid, 1856 char **winname, char **windomain, 1857 int *direction, idmap_info *info) 1858 { 1859 CLIENT *clnt; 1860 enum clnt_stat clntstat; 1861 idmap_mapping request, *mapping; 1862 idmap_mappings_res result; 1863 idmap_retcode retcode, rc; 1864 1865 if (handle == NULL) { 1866 errno = EINVAL; 1867 return (IDMAP_ERR_ARG); 1868 } 1869 1870 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1871 1872 if (sidprefix) 1873 *sidprefix = NULL; 1874 if (winname) 1875 *winname = NULL; 1876 if (windomain) 1877 *windomain = NULL; 1878 if (rid) 1879 *rid = UINT32_MAX; 1880 if (direction) 1881 *direction = IDMAP_DIRECTION_UNDEF; 1882 1883 (void) memset(&request, 0, sizeof (request)); 1884 (void) memset(&result, 0, sizeof (result)); 1885 1886 request.flag = flag; 1887 request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID; 1888 1889 if (pid && *pid != UINT32_MAX) { 1890 request.id1.idmap_id_u.uid = *pid; 1891 } else if (unixname) { 1892 request.id1name = (char *)unixname; 1893 request.id1.idmap_id_u.uid = UINT32_MAX; 1894 } else { 1895 errno = EINVAL; 1896 return (IDMAP_ERR_ARG); 1897 } 1898 1899 if (is_wuser == NULL) 1900 request.id2.idtype = IDMAP_SID; 1901 else if (*is_wuser == -1) 1902 request.id2.idtype = IDMAP_SID; 1903 else if (*is_wuser == 0) 1904 request.id2.idtype = IDMAP_GSID; 1905 else if (*is_wuser == 1) 1906 request.id2.idtype = IDMAP_USID; 1907 1908 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1909 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1910 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1911 TIMEOUT); 1912 1913 if (clntstat != RPC_SUCCESS) 1914 return (_idmap_rpc2stat(clnt)); 1915 1916 retcode = result.retcode; 1917 1918 if ((mapping = result.mappings.mappings_val) == NULL) { 1919 if (retcode == IDMAP_SUCCESS) 1920 retcode = IDMAP_ERR_NORESULT; 1921 goto out; 1922 } 1923 1924 if (info != NULL) 1925 idmap_info_mov(info, &mapping->info); 1926 1927 if (direction != NULL) 1928 *direction = mapping->direction; 1929 1930 if (is_wuser != NULL) { 1931 if (mapping->id2.idtype == IDMAP_USID) 1932 *is_wuser = 1; 1933 else if (mapping->id2.idtype == IDMAP_GSID) 1934 *is_wuser = 0; 1935 else 1936 *is_wuser = -1; 1937 } 1938 1939 if (sidprefix && mapping->id2.idmap_id_u.sid.prefix && 1940 *mapping->id2.idmap_id_u.sid.prefix != '\0') { 1941 *sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix); 1942 if (*sidprefix == NULL) { 1943 retcode = IDMAP_ERR_MEMORY; 1944 goto errout; 1945 } 1946 } 1947 if (rid) 1948 *rid = mapping->id2.idmap_id_u.sid.rid; 1949 1950 rc = idmap_strdupnull(winname, mapping->id2name); 1951 if (rc != IDMAP_SUCCESS) 1952 retcode = rc; 1953 1954 rc = idmap_strdupnull(windomain, mapping->id2domain); 1955 if (rc != IDMAP_SUCCESS) 1956 retcode = rc; 1957 1958 goto out; 1959 1960 errout: 1961 if (sidprefix && *sidprefix) { 1962 free(*sidprefix); 1963 *sidprefix = NULL; 1964 } 1965 if (winname && *winname) { 1966 free(*winname); 1967 *winname = NULL; 1968 } 1969 if (windomain && *windomain) { 1970 free(*windomain); 1971 *windomain = NULL; 1972 } 1973 1974 out: 1975 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1976 if (retcode != IDMAP_SUCCESS) 1977 errno = idmap_stat2errno(retcode); 1978 return (retcode); 1979 } 1980 1981 1982 1983 #define gettext(s) s 1984 static stat_table_t stattable[] = { 1985 {IDMAP_SUCCESS, gettext("Success"), 0}, 1986 {IDMAP_NEXT, gettext("More results available"), 0}, 1987 {IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL}, 1988 {IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL}, 1989 {IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM}, 1990 {IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL}, 1991 {IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL}, 1992 {IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL}, 1993 {IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP}, 1994 {IDMAP_ERR_W2U_NAMERULE, 1995 gettext("Invalid Windows to UNIX name-based rule"), EINVAL}, 1996 {IDMAP_ERR_U2W_NAMERULE, 1997 gettext("Invalid UNIX to Windows name-based rule"), EINVAL}, 1998 {IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL}, 1999 {IDMAP_ERR_DB, gettext("Invalid database"), EINVAL}, 2000 {IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL}, 2001 {IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL}, 2002 {IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL}, 2003 {IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF}, 2004 {IDMAP_ERR_RPC, gettext("RPC error"), EINVAL}, 2005 {IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL}, 2006 {IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY}, 2007 {IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES}, 2008 {IDMAP_ERR_NOMAPPING, 2009 gettext("Mapping not found or inhibited"), EINVAL}, 2010 {IDMAP_ERR_NEW_ID_ALLOC_REQD, 2011 gettext("New mapping needs to be created"), EINVAL}, 2012 {IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL}, 2013 {IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL}, 2014 {IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL}, 2015 {IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL}, 2016 {IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL}, 2017 {IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL}, 2018 {IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL}, 2019 {IDMAP_ERR_NOTMAPPED_WELLKNOWN, 2020 gettext("No mapping for well-known SID"), EINVAL}, 2021 {IDMAP_ERR_RETRIABLE_NET_ERR, 2022 gettext("Windows lookup failed"), EINVAL}, 2023 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 2024 gettext("Duplicate rule or conflicts with an existing " 2025 "Windows to UNIX name-based rule"), EINVAL}, 2026 {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 2027 gettext("Duplicate rule or conflicts with an existing " 2028 "Unix to Windows name-based rule"), EINVAL}, 2029 {IDMAP_ERR_BAD_UTF8, 2030 gettext("Invalid or illegal UTF-8 sequence found in " 2031 "a given Windows entity name or domain name"), EINVAL}, 2032 {IDMAP_ERR_NONE_GENERATED, 2033 gettext("Mapping not found and none created (see -c option)"), 2034 EINVAL}, 2035 {IDMAP_ERR_PROP_UNKNOWN, 2036 gettext("Undefined property"), 2037 EINVAL}, 2038 {IDMAP_ERR_NS_LDAP_CFG, 2039 gettext("Native LDAP configuration error"), EINVAL}, 2040 {IDMAP_ERR_NS_LDAP_PARTIAL, 2041 gettext("Partial result from Native LDAP"), EINVAL}, 2042 {IDMAP_ERR_NS_LDAP_OP_FAILED, 2043 gettext("Native LDAP operation failed"), EINVAL}, 2044 {IDMAP_ERR_NS_LDAP_BAD_WINNAME, 2045 gettext("Improper winname form found in Native LDAP"), EINVAL}, 2046 {IDMAP_ERR_NO_ACTIVEDIRECTORY, 2047 gettext("No AD servers"), 2048 EINVAL}, 2049 {-1, NULL, 0} 2050 }; 2051 #undef gettext 2052 2053 2054 /* 2055 * Get description of status code 2056 * 2057 * Input: 2058 * status - Status code returned by libidmap API call 2059 * 2060 * Return Value: 2061 * human-readable localized description of idmap_stat 2062 */ 2063 /* ARGSUSED */ 2064 const char * 2065 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) 2066 { 2067 int i; 2068 2069 for (i = 0; stattable[i].msg; i++) { 2070 if (stattable[i].retcode == status) 2071 return (dgettext(TEXT_DOMAIN, stattable[i].msg)); 2072 } 2073 return (dgettext(TEXT_DOMAIN, "Unknown error")); 2074 } 2075 2076 2077 static int 2078 idmap_stat2errno(idmap_stat stat) 2079 { 2080 int i; 2081 for (i = 0; stattable[i].msg; i++) { 2082 if (stattable[i].retcode == stat) 2083 return (stattable[i].errnum); 2084 } 2085 return (EINVAL); 2086 } 2087 2088 2089 /* 2090 * Get status code from string 2091 */ 2092 idmap_stat 2093 idmap_string2stat(const char *str) 2094 { 2095 if (str == NULL) 2096 return (IDMAP_ERR_INTERNAL); 2097 2098 #define return_cmp(a) \ 2099 if (0 == strcmp(str, "IDMAP_ERR_" #a)) \ 2100 return (IDMAP_ERR_ ## a); 2101 2102 return_cmp(OTHER); 2103 return_cmp(INTERNAL); 2104 return_cmp(MEMORY); 2105 return_cmp(NORESULT); 2106 return_cmp(NOTUSER); 2107 return_cmp(NOTGROUP); 2108 return_cmp(NOTSUPPORTED); 2109 return_cmp(W2U_NAMERULE); 2110 return_cmp(U2W_NAMERULE); 2111 return_cmp(CACHE); 2112 return_cmp(DB); 2113 return_cmp(ARG); 2114 return_cmp(SID); 2115 return_cmp(IDTYPE); 2116 return_cmp(RPC_HANDLE); 2117 return_cmp(RPC); 2118 return_cmp(CLIENT_HANDLE); 2119 return_cmp(BUSY); 2120 return_cmp(PERMISSION_DENIED); 2121 return_cmp(NOMAPPING); 2122 return_cmp(NEW_ID_ALLOC_REQD); 2123 return_cmp(DOMAIN); 2124 return_cmp(SECURITY); 2125 return_cmp(NOTFOUND); 2126 return_cmp(DOMAIN_NOTFOUND); 2127 return_cmp(MEMORY); 2128 return_cmp(UPDATE_NOTALLOWED); 2129 return_cmp(CFG); 2130 return_cmp(CFG_CHANGE); 2131 return_cmp(NOTMAPPED_WELLKNOWN); 2132 return_cmp(RETRIABLE_NET_ERR); 2133 return_cmp(W2U_NAMERULE_CONFLICT); 2134 return_cmp(U2W_NAMERULE_CONFLICT); 2135 return_cmp(BAD_UTF8); 2136 return_cmp(NONE_GENERATED); 2137 return_cmp(PROP_UNKNOWN); 2138 return_cmp(NS_LDAP_CFG); 2139 return_cmp(NS_LDAP_PARTIAL); 2140 return_cmp(NS_LDAP_OP_FAILED); 2141 return_cmp(NS_LDAP_BAD_WINNAME); 2142 return_cmp(NO_ACTIVEDIRECTORY); 2143 #undef return_cmp 2144 2145 return (IDMAP_ERR_OTHER); 2146 } 2147 2148 2149 /* 2150 * Map the given status to one that can be returned by the protocol 2151 */ 2152 idmap_stat 2153 idmap_stat4prot(idmap_stat status) 2154 { 2155 switch (status) { 2156 case IDMAP_ERR_MEMORY: 2157 case IDMAP_ERR_CACHE: 2158 return (IDMAP_ERR_INTERNAL); 2159 } 2160 return (status); 2161 } 2162 2163 2164 /* 2165 * This is a convenience routine which duplicates a string after 2166 * checking for NULL pointers. This function will return success if 2167 * either the 'to' OR 'from' pointers are NULL. 2168 */ 2169 static idmap_stat 2170 idmap_strdupnull(char **to, const char *from) 2171 { 2172 if (to == NULL) 2173 return (IDMAP_SUCCESS); 2174 2175 if (from == NULL || *from == '\0') { 2176 *to = NULL; 2177 return (IDMAP_SUCCESS); 2178 } 2179 2180 *to = strdup(from); 2181 if (*to == NULL) 2182 return (IDMAP_ERR_MEMORY); 2183 return (IDMAP_SUCCESS); 2184 } 2185 2186 2187 idmap_stat 2188 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) 2189 { 2190 idmap_stat retval; 2191 2192 if (to == NULL) 2193 return (IDMAP_SUCCESS); 2194 2195 (void) memcpy(to, from, sizeof (idmap_namerule)); 2196 to->windomain = NULL; 2197 to->winname = NULL; 2198 to->unixname = NULL; 2199 2200 retval = idmap_strdupnull(&to->windomain, from->windomain); 2201 if (retval != IDMAP_SUCCESS) 2202 return (retval); 2203 2204 retval = idmap_strdupnull(&to->winname, from->winname); 2205 if (retval != IDMAP_SUCCESS) { 2206 free(to->windomain); 2207 to->windomain = NULL; 2208 return (retval); 2209 } 2210 2211 retval = idmap_strdupnull(&to->unixname, from->unixname); 2212 if (retval != IDMAP_SUCCESS) { 2213 free(to->windomain); 2214 to->windomain = NULL; 2215 free(to->winname); 2216 to->winname = NULL; 2217 return (retval); 2218 } 2219 2220 return (retval); 2221 } 2222 2223 2224 /* 2225 * Move the contents of the "info" structure from "from" to "to". 2226 */ 2227 void 2228 idmap_info_mov(idmap_info *to, idmap_info *from) 2229 { 2230 (void) memcpy(to, from, sizeof (idmap_info)); 2231 (void) memset(from, 0, sizeof (idmap_info)); 2232 } 2233 2234 2235 void 2236 idmap_info_free(idmap_info *info) 2237 { 2238 if (info == NULL) 2239 return; 2240 2241 xdr_free(xdr_idmap_info, (caddr_t)info); 2242 (void) memset(info, 0, sizeof (idmap_info)); 2243 } 2244 2245 2246 void 2247 idmap_how_clear(idmap_how *how) 2248 { 2249 xdr_free(xdr_idmap_how, (caddr_t)how); 2250 (void) memset(how, 0, sizeof (*how)); 2251 } 2252 2253 2254 /* 2255 * Get uid given Windows name 2256 */ 2257 idmap_stat 2258 idmap_getuidbywinname(const char *name, const char *domain, int flag, 2259 uid_t *uid) 2260 { 2261 idmap_handle_t *ih; 2262 idmap_retcode rc; 2263 int is_user = 1; 2264 int is_wuser = -1; 2265 int direction; 2266 2267 if (uid == NULL) 2268 return (IDMAP_ERR_ARG); 2269 2270 if (flag & IDMAP_REQ_FLG_USE_CACHE) { 2271 rc = idmap_cache_lookup_uidbywinname(name, domain, uid); 2272 if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY) 2273 return (rc); 2274 } 2275 /* Get mapping */ 2276 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2277 return (rc); 2278 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag, 2279 &is_user, &is_wuser, uid, NULL, &direction, NULL); 2280 (void) idmap_fini(ih); 2281 2282 if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) { 2283 /* If we have not got the domain don't store UID to winname */ 2284 if (domain == NULL) 2285 direction = IDMAP_DIRECTION_W2U; 2286 idmap_cache_add_winname2uid(name, domain, *uid, direction); 2287 } 2288 2289 return (rc); 2290 } 2291 2292 2293 /* 2294 * Get gid given Windows name 2295 */ 2296 idmap_stat 2297 idmap_getgidbywinname(const char *name, const char *domain, int flag, 2298 gid_t *gid) 2299 { 2300 idmap_handle_t *ih; 2301 idmap_retcode rc; 2302 int is_user = 0; 2303 int is_wuser = -1; 2304 int direction; 2305 2306 if (gid == NULL) 2307 return (IDMAP_ERR_ARG); 2308 2309 if (flag & IDMAP_REQ_FLG_USE_CACHE) { 2310 rc = idmap_cache_lookup_gidbywinname(name, domain, gid); 2311 if (rc == IDMAP_SUCCESS || rc == IDMAP_ERR_MEMORY) 2312 return (rc); 2313 } 2314 2315 /* Get mapping */ 2316 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2317 return (rc); 2318 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag, 2319 &is_user, &is_wuser, gid, NULL, &direction, NULL); 2320 (void) idmap_fini(ih); 2321 2322 if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) { 2323 /* If we have not got the domain don't store GID to winname */ 2324 if (domain == NULL) 2325 direction = IDMAP_DIRECTION_W2U; 2326 idmap_cache_add_winname2gid(name, domain, *gid, direction); 2327 } 2328 2329 return (rc); 2330 } 2331 2332 2333 /* 2334 * Get winname given pid 2335 */ 2336 static idmap_retcode 2337 idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name, 2338 char **domain) 2339 { 2340 idmap_handle_t *ih; 2341 idmap_retcode rc; 2342 int len; 2343 char *winname, *windomain; 2344 int direction; 2345 2346 if (name == NULL) 2347 return (IDMAP_ERR_ARG); 2348 2349 if (flag & IDMAP_REQ_FLG_USE_CACHE) { 2350 if (is_user) 2351 rc = idmap_cache_lookup_winnamebyuid(&winname, 2352 &windomain, pid); 2353 else 2354 rc = idmap_cache_lookup_winnamebygid(&winname, 2355 &windomain, pid); 2356 if (rc == IDMAP_SUCCESS) 2357 goto out; 2358 if (rc == IDMAP_ERR_MEMORY) 2359 return (rc); 2360 } 2361 2362 /* Get mapping */ 2363 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2364 return (rc); 2365 rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL, 2366 NULL, NULL, &winname, &windomain, &direction, NULL); 2367 (void) idmap_fini(ih); 2368 2369 /* Return on error */ 2370 if (rc != IDMAP_SUCCESS) 2371 return (rc); 2372 2373 /* 2374 * The given PID may have been mapped to a locally 2375 * generated SID in which case there isn't any 2376 * Windows name 2377 */ 2378 if (winname == NULL || windomain == NULL) { 2379 idmap_free(winname); 2380 idmap_free(windomain); 2381 return (IDMAP_ERR_NORESULT); 2382 } 2383 2384 if (flag & IDMAP_REQ_FLG_USE_CACHE) { 2385 if (is_user) 2386 idmap_cache_add_winname2uid(winname, windomain, 2387 pid, direction); 2388 else 2389 idmap_cache_add_winname2gid(winname, windomain, 2390 pid, direction); 2391 } 2392 2393 out: 2394 if (domain != NULL) { 2395 *name = winname; 2396 *domain = windomain; 2397 } else { 2398 len = strlen(winname) + strlen(windomain) + 2; 2399 if ((*name = malloc(len)) != NULL) 2400 (void) snprintf(*name, len, "%s@%s", winname, 2401 windomain); 2402 else 2403 rc = IDMAP_ERR_MEMORY; 2404 idmap_free(winname); 2405 idmap_free(windomain); 2406 } 2407 2408 return (rc); 2409 } 2410 2411 2412 /* 2413 * Get winname given uid 2414 */ 2415 idmap_stat 2416 idmap_getwinnamebyuid(uid_t uid, int flag, char **name, char **domain) 2417 { 2418 return (idmap_getwinnamebypid(uid, 1, flag, name, domain)); 2419 } 2420 2421 2422 /* 2423 * Get winname given gid 2424 */ 2425 idmap_stat 2426 idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain) 2427 { 2428 return (idmap_getwinnamebypid(gid, 0, flag, name, domain)); 2429 } 2430 2431 idmap_stat 2432 idmap_flush(idmap_handle_t *handle, idmap_flush_op op) 2433 { 2434 CLIENT *clnt; 2435 enum clnt_stat clntstat; 2436 idmap_retcode res; 2437 2438 res = IDMAP_SUCCESS; 2439 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 2440 2441 clntstat = clnt_call(clnt, IDMAP_FLUSH, 2442 (xdrproc_t)xdr_idmap_flush_op, (caddr_t)&op, 2443 (xdrproc_t)xdr_idmap_retcode, (caddr_t)&res, TIMEOUT); 2444 2445 if (clntstat != RPC_SUCCESS) { 2446 return (_idmap_rpc2stat(clnt)); 2447 } 2448 return (res); 2449 } 2450 2451 2452 /* 2453 * syslog is the default logger. 2454 * It can be overwritten by supplying a logger 2455 * with idmap_set_logger() 2456 */ 2457 idmap_logger_t logger = syslog; 2458 2459 2460 void 2461 idmap_set_logger(idmap_logger_t funct) 2462 { 2463 logger = funct; 2464 } 2465 2466 /* 2467 * Helper functions that concatenate two parts of a name and then 2468 * look up a value, so that the same set of functions can be used to 2469 * process both "in" and "out" parameters. 2470 */ 2471 static 2472 boolean_t 2473 idmap_trace_get_str(nvlist_t *entry, char *n1, char *n2, char **ret) 2474 { 2475 char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is about 11 */ 2476 int err; 2477 2478 (void) strlcpy(name, n1, sizeof (name)); 2479 if (n2 != NULL) 2480 (void) strlcat(name, n2, sizeof (name)); 2481 2482 err = nvlist_lookup_string(entry, name, ret); 2483 return (err == 0); 2484 } 2485 2486 static 2487 boolean_t 2488 idmap_trace_get_int(nvlist_t *entry, char *n1, char *n2, int64_t *ret) 2489 { 2490 char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is about 11 */ 2491 int err; 2492 2493 (void) strlcpy(name, n1, sizeof (name)); 2494 if (n2 != NULL) 2495 (void) strlcat(name, n2, sizeof (name)); 2496 2497 err = nvlist_lookup_int64(entry, name, ret); 2498 return (err == 0); 2499 } 2500 2501 static 2502 void 2503 idmap_trace_print_id(FILE *out, nvlist_t *entry, char *fromto) 2504 { 2505 char *s; 2506 int64_t i64; 2507 2508 if (idmap_trace_get_int(entry, fromto, IDMAP_TRACE_TYPE, &i64)) { 2509 switch (i64) { 2510 case IDMAP_POSIXID: 2511 (void) fprintf(out, "unixname "); 2512 break; 2513 case IDMAP_UID: 2514 (void) fprintf(out, "unixuser "); 2515 break; 2516 case IDMAP_GID: 2517 (void) fprintf(out, "unixgroup "); 2518 break; 2519 case IDMAP_SID: 2520 (void) fprintf(out, "winname "); 2521 break; 2522 case IDMAP_USID: 2523 (void) fprintf(out, "winuser "); 2524 break; 2525 case IDMAP_GSID: 2526 (void) fprintf(out, "wingroup "); 2527 break; 2528 case IDMAP_NONE: 2529 (void) fprintf(out, gettext("unknown ")); 2530 break; 2531 default: 2532 (void) fprintf(out, gettext("bad %d "), (int)i64); 2533 break; 2534 } 2535 } 2536 2537 if (idmap_trace_get_str(entry, fromto, IDMAP_TRACE_NAME, &s)) 2538 (void) fprintf(out, "%s ", s); 2539 2540 if (idmap_trace_get_str(entry, fromto, IDMAP_TRACE_SID, &s)) 2541 (void) fprintf(out, "%s ", s); 2542 2543 if (idmap_trace_get_int(entry, fromto, IDMAP_TRACE_UNIXID, &i64)) 2544 (void) fprintf(out, "%u ", (uid_t)i64); 2545 } 2546 2547 void 2548 idmap_trace_print_1(FILE *out, char *prefix, nvlist_t *entry) 2549 { 2550 char *s; 2551 int64_t i64; 2552 2553 (void) fprintf(out, "%s", prefix); 2554 idmap_trace_print_id(out, entry, "from"); 2555 (void) fprintf(out, "-> "); 2556 idmap_trace_print_id(out, entry, "to"); 2557 if (idmap_trace_get_int(entry, IDMAP_TRACE_ERROR, NULL, &i64)) 2558 (void) fprintf(out, gettext("Error %d "), (int)i64); 2559 (void) fprintf(out, "-"); 2560 if (idmap_trace_get_str(entry, IDMAP_TRACE_MESSAGE, NULL, &s)) 2561 (void) fprintf(out, " %s", s); 2562 (void) fprintf(out, "\n"); 2563 } 2564 2565 void 2566 idmap_trace_print(FILE *out, char *prefix, nvlist_t *trace) 2567 { 2568 nvpair_t *nvp; 2569 2570 for (nvp = nvlist_next_nvpair(trace, NULL); 2571 nvp != NULL; 2572 nvp = nvlist_next_nvpair(trace, nvp)) { 2573 nvlist_t *entry; 2574 int err; 2575 2576 err = nvpair_value_nvlist(nvp, &entry); 2577 assert(err == 0); 2578 2579 idmap_trace_print_1(out, prefix, entry); 2580 } 2581 } 2582