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