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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * libidmap API 30 */ 31 32 #include <stdlib.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 "idmap_impl.h" 43 44 static struct timeval TIMEOUT = { 25, 0 }; 45 46 static int idmap_stat2errno(idmap_stat); 47 static idmap_stat idmap_strdupnull(char **, const char *); 48 49 #define __ITER_CREATE(itera, argu, handl, ityp)\ 50 if (handl == NULL) {\ 51 errno = EINVAL;\ 52 return (IDMAP_ERR_ARG);\ 53 }\ 54 itera = calloc(1, sizeof (*itera));\ 55 if (itera == NULL) {\ 56 errno = ENOMEM;\ 57 return (IDMAP_ERR_MEMORY);\ 58 }\ 59 argu = calloc(1, sizeof (*argu));\ 60 if (argu == NULL) {\ 61 free(itera);\ 62 errno = ENOMEM;\ 63 return (IDMAP_ERR_MEMORY);\ 64 }\ 65 itera->ih = handl;\ 66 itera->type = ityp;\ 67 itera->retcode = IDMAP_NEXT;\ 68 itera->limit = 1024;\ 69 itera->arg = argu; 70 71 72 #define __ITER_ERR_RETURN(itera, argu, xdr_argu, iretcod)\ 73 if (argu) {\ 74 xdr_free(xdr_argu, (caddr_t)argu);\ 75 free(argu);\ 76 }\ 77 if (itera)\ 78 free(itera);\ 79 return (iretcod); 80 81 82 #define __ITER_CHECK(itera, ityp)\ 83 if (itera == NULL) {\ 84 errno = EINVAL;\ 85 return (IDMAP_ERR_ARG);\ 86 }\ 87 if (itera->type != ityp) {\ 88 errno = EINVAL;\ 89 return (IDMAP_ERR_ARG);\ 90 } 91 92 #define EMPTY_STRING(str) (str == NULL || *str == '\0') 93 94 /* 95 * Free memory allocated by libidmap API 96 * 97 * Input: 98 * ptr - memory to be freed 99 */ 100 void 101 idmap_free(void *ptr) { 102 free(ptr); 103 } 104 105 106 /* 107 * Create and Initialize idmap client handle for rpc/doors 108 * 109 * Output: 110 * handle - idmap handle 111 */ 112 idmap_stat 113 idmap_init(idmap_handle_t **handle) { 114 CLIENT *clnt = NULL; 115 struct idmap_handle *hptr; 116 117 *handle = NULL; 118 hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr)); 119 if (hptr == NULL) 120 return (IDMAP_ERR_MEMORY); 121 122 clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, 0); 123 if (clnt == NULL) { 124 free(hptr); 125 return (IDMAP_ERR_RPC); 126 } 127 hptr->type = _IDMAP_HANDLE_RPC_DOORS; 128 hptr->privhandle = clnt; 129 *handle = hptr; 130 return (IDMAP_SUCCESS); 131 } 132 133 134 /* 135 * Finalize idmap handle 136 * 137 * Input: 138 * handle - idmap handle 139 */ 140 idmap_stat 141 idmap_fini(idmap_handle_t *handle) { 142 CLIENT *clnt; 143 struct idmap_handle *hptr; 144 145 if (handle == NULL) 146 return (IDMAP_SUCCESS); 147 148 hptr = (struct idmap_handle *)handle; 149 150 switch (hptr->type) { 151 case _IDMAP_HANDLE_RPC_DOORS: 152 clnt = (CLIENT *)hptr->privhandle; 153 if (clnt) { 154 if (clnt->cl_auth) 155 auth_destroy(clnt->cl_auth); 156 clnt_destroy(clnt); 157 } 158 break; 159 default: 160 break; 161 } 162 free(hptr); 163 return (IDMAP_SUCCESS); 164 } 165 166 167 168 /* 169 * Create/Initialize handle for updates 170 * 171 * Output: 172 * udthandle - update handle 173 */ 174 idmap_stat 175 idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) { 176 idmap_udt_handle_t *tmp; 177 178 if (handle == NULL || udthandle == NULL) { 179 errno = EINVAL; 180 return (IDMAP_ERR_ARG); 181 } 182 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 183 errno = ENOMEM; 184 return (IDMAP_ERR_MEMORY); 185 } 186 187 tmp->ih = handle; 188 *udthandle = tmp; 189 return (IDMAP_SUCCESS); 190 } 191 192 193 /* 194 * All the updates specified by the update handle are committed 195 * in a single transaction. i.e either all succeed or none. 196 * 197 * Input: 198 * udthandle - update handle with the update requests 199 * 200 * Return value: 201 * Status of the commit 202 */ 203 idmap_stat 204 idmap_udt_commit(idmap_udt_handle_t *udthandle) { 205 CLIENT *clnt; 206 enum clnt_stat clntstat; 207 idmap_update_res res; 208 idmap_stat retcode; 209 210 if (udthandle == NULL) { 211 errno = EINVAL; 212 return (IDMAP_ERR_ARG); 213 } 214 215 (void) memset(&res, 0, sizeof (res)); 216 217 _IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt); 218 clntstat = clnt_call(clnt, IDMAP_UPDATE, 219 (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch, 220 (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res, 221 TIMEOUT); 222 223 if (clntstat != RPC_SUCCESS) { 224 retcode = _idmap_rpc2stat(clnt); 225 goto out; 226 } 227 228 retcode = udthandle->commit_stat = res.retcode; 229 udthandle->error_index = res.error_index; 230 231 if (retcode != IDMAP_SUCCESS) { 232 233 if (udthandle->error_index < 0) 234 goto out; 235 236 retcode = idmap_namerule_cpy(&udthandle->error_rule, 237 &res.error_rule); 238 if (retcode != IDMAP_SUCCESS) { 239 udthandle->error_index = -2; 240 goto out; 241 } 242 243 retcode = idmap_namerule_cpy(&udthandle->conflict_rule, 244 &res.conflict_rule); 245 if (retcode != IDMAP_SUCCESS) { 246 udthandle->error_index = -2; 247 goto out; 248 } 249 } 250 251 retcode = res.retcode; 252 253 254 out: 255 /* reset handle so that it can be used again */ 256 if (retcode == IDMAP_SUCCESS) { 257 _IDMAP_RESET_UDT_HANDLE(udthandle); 258 } 259 260 (void) xdr_free(xdr_idmap_update_res, (caddr_t)&res); 261 errno = idmap_stat2errno(retcode); 262 return (retcode); 263 } 264 265 266 static void 267 idmap_namerule_parts_clear(char **windomain, char **winname, 268 char **unixname, boolean_t *is_user, boolean_t *is_nt4, 269 int *direction) { 270 if (windomain) 271 *windomain = NULL; 272 if (winname) 273 *winname = NULL; 274 if (unixname) 275 *unixname = NULL; 276 277 if (is_nt4) 278 *is_nt4 = 0; 279 if (is_user) 280 *is_user = -1; 281 if (direction) 282 *direction = IDMAP_DIRECTION_UNDEF; 283 } 284 285 static idmap_stat 286 idmap_namerule2parts(idmap_namerule *rule, 287 char **windomain, char **winname, 288 char **unixname, boolean_t *is_user, boolean_t *is_nt4, 289 int *direction) { 290 idmap_stat retcode; 291 292 if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) 293 return (IDMAP_ERR_NORESULT); 294 295 296 retcode = idmap_strdupnull(windomain, rule->windomain); 297 if (retcode != IDMAP_SUCCESS) 298 goto errout; 299 300 retcode = idmap_strdupnull(winname, rule->winname); 301 if (retcode != IDMAP_SUCCESS) 302 goto errout; 303 304 retcode = idmap_strdupnull(unixname, rule->unixname); 305 if (retcode != IDMAP_SUCCESS) 306 goto errout; 307 308 309 if (is_user) 310 *is_user = rule->is_user; 311 if (is_nt4) 312 *is_nt4 = rule->is_nt4; 313 if (direction) 314 *direction = rule->direction; 315 316 317 return (IDMAP_SUCCESS); 318 319 errout: 320 if (windomain && *windomain) 321 free(*windomain); 322 if (winname && *winname) 323 free(*winname); 324 if (unixname && *unixname) 325 free(*unixname); 326 327 idmap_namerule_parts_clear(windomain, winname, 328 unixname, is_user, is_nt4, direction); 329 330 return (retcode); 331 332 } 333 334 /* 335 * Retrieve the index of the failed batch element. error_index == -1 336 * indicates failure at the beginning, -2 at the end. 337 * 338 * If idmap_udt_commit didn't return error, the returned value is undefined. 339 * 340 * Return value: 341 * IDMAP_SUCCESS 342 */ 343 344 idmap_stat 345 idmap_udt_get_error_index(idmap_udt_handle_t *udthandle, 346 int64_t *error_index) { 347 if (error_index) 348 *error_index = udthandle->error_index; 349 350 return (IDMAP_SUCCESS); 351 } 352 353 354 /* 355 * Retrieve the rule which caused the batch to fail. If 356 * idmap_udt_commit didn't return error or if error_index is < 0, the 357 * retrieved rule is undefined. 358 * 359 * Return value: 360 * IDMAP_ERR_NORESULT if there is no error rule. 361 * IDMAP_SUCCESS if the rule was obtained OK. 362 * other error code (IDMAP_ERR_NOMEMORY etc) 363 */ 364 365 idmap_stat 366 idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle, 367 char **windomain, char **winname, 368 char **unixname, boolean_t *is_user, boolean_t *is_nt4, 369 int *direction) { 370 idmap_namerule_parts_clear(windomain, winname, 371 unixname, is_user, is_nt4, direction); 372 373 if (udthandle->commit_stat == IDMAP_SUCCESS || 374 udthandle->error_index < 0) 375 return (IDMAP_ERR_NORESULT); 376 377 return (idmap_namerule2parts( 378 &udthandle->error_rule, 379 windomain, 380 winname, 381 unixname, 382 is_user, 383 is_nt4, 384 direction)); 385 } 386 387 /* 388 * Retrieve the rule with which there was a conflict. TODO: retrieve 389 * the value. 390 * 391 * Return value: 392 * IDMAP_ERR_NORESULT if there is no error rule. 393 * IDMAP_SUCCESS if the rule was obtained OK. 394 * other error code (IDMAP_ERR_NOMEMORY etc) 395 */ 396 397 idmap_stat 398 idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle, 399 char **windomain, char **winname, 400 char **unixname, boolean_t *is_user, boolean_t *is_nt4, 401 int *direction) { 402 idmap_namerule_parts_clear(windomain, winname, 403 unixname, is_user, is_nt4, direction); 404 405 if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT && 406 udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) { 407 return (IDMAP_ERR_NORESULT); 408 } 409 410 return (idmap_namerule2parts( 411 &udthandle->conflict_rule, 412 windomain, 413 winname, 414 unixname, 415 is_user, 416 is_nt4, 417 direction)); 418 } 419 420 421 /* 422 * Destroy the update handle 423 */ 424 void 425 idmap_udt_destroy(idmap_udt_handle_t *udthandle) { 426 if (udthandle == NULL) 427 return; 428 (void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch); 429 (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule); 430 (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule); 431 free(udthandle); 432 } 433 434 435 idmap_stat 436 idmap_udt_add_namerule(idmap_udt_handle_t *udthandle, const char *windomain, 437 boolean_t is_user, const char *winname, const char *unixname, 438 boolean_t is_nt4, int direction) { 439 idmap_retcode retcode; 440 idmap_namerule *rule = NULL; 441 442 retcode = _udt_extend_batch(udthandle); 443 if (retcode != IDMAP_SUCCESS) 444 goto errout; 445 446 rule = &udthandle->batch. 447 idmap_update_batch_val[udthandle->next]. 448 idmap_update_op_u.rule; 449 rule->is_user = is_user; 450 rule->direction = direction; 451 rule->is_nt4 = is_nt4; 452 453 retcode = idmap_strdupnull(&rule->windomain, windomain); 454 if (retcode != IDMAP_SUCCESS) 455 goto errout; 456 457 retcode = idmap_strdupnull(&rule->winname, winname); 458 if (retcode != IDMAP_SUCCESS) 459 goto errout; 460 461 retcode = idmap_strdupnull(&rule->unixname, unixname); 462 if (retcode != IDMAP_SUCCESS) 463 goto errout; 464 465 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 466 OP_ADD_NAMERULE; 467 udthandle->next++; 468 return (IDMAP_SUCCESS); 469 470 errout: 471 /* The batch should still be usable */ 472 if (rule) 473 (void) xdr_free(xdr_idmap_namerule, (caddr_t)rule); 474 errno = idmap_stat2errno(retcode); 475 return (retcode); 476 } 477 478 479 /* ARGSUSED */ 480 idmap_stat 481 idmap_udt_rm_namerule(idmap_udt_handle_t *udthandle, boolean_t is_user, 482 const char *windomain, const char *winname, 483 const char *unixname, int direction) { 484 idmap_retcode retcode; 485 idmap_namerule *rule = NULL; 486 487 retcode = _udt_extend_batch(udthandle); 488 if (retcode != IDMAP_SUCCESS) 489 goto errout; 490 491 rule = &udthandle->batch. 492 idmap_update_batch_val[udthandle->next]. 493 idmap_update_op_u.rule; 494 rule->is_user = is_user; 495 rule->direction = direction; 496 497 retcode = idmap_strdupnull(&rule->windomain, windomain); 498 if (retcode != IDMAP_SUCCESS) 499 goto errout; 500 501 retcode = idmap_strdupnull(&rule->winname, winname); 502 if (retcode != IDMAP_SUCCESS) 503 goto errout; 504 505 retcode = idmap_strdupnull(&rule->unixname, unixname); 506 if (retcode != IDMAP_SUCCESS) 507 goto errout; 508 509 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 510 OP_RM_NAMERULE; 511 udthandle->next++; 512 return (IDMAP_SUCCESS); 513 514 errout: 515 if (rule) 516 (void) xdr_free(xdr_idmap_namerule, (caddr_t)rule); 517 errno = idmap_stat2errno(retcode); 518 return (retcode); 519 } 520 521 522 /* ARGSUSED */ 523 idmap_stat 524 idmap_udt_flush_namerules(idmap_udt_handle_t *udthandle, boolean_t is_user) { 525 idmap_retcode retcode; 526 527 retcode = _udt_extend_batch(udthandle); 528 if (retcode != IDMAP_SUCCESS) 529 goto errout; 530 531 udthandle->batch.idmap_update_batch_val[udthandle->next]. 532 idmap_update_op_u.is_user = is_user; 533 534 udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = 535 OP_FLUSH_NAMERULES; 536 udthandle->next++; 537 return (IDMAP_SUCCESS); 538 539 errout: 540 errno = idmap_stat2errno(retcode); 541 return (retcode); 542 } 543 544 545 /* 546 * Set the number of entries requested per batch by the iterator 547 * 548 * Input: 549 * iter - iterator 550 * limit - number of entries requested per batch 551 */ 552 idmap_stat 553 idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) { 554 if (iter == NULL) { 555 errno = EINVAL; 556 return (IDMAP_ERR_ARG); 557 } 558 iter->limit = limit; 559 return (IDMAP_SUCCESS); 560 } 561 562 563 /* 564 * Create iterator to get name-based mapping rules 565 * 566 * Input: 567 * windomain - Windows domain 568 * is_user - user or group rules 569 * winname - Windows user or group name 570 * unixname - Unix user or group name 571 * 572 * Output: 573 * iter - iterator 574 */ 575 idmap_stat 576 idmap_iter_namerules(idmap_handle_t *handle, const char *windomain, 577 boolean_t is_user, const char *winname, 578 const char *unixname, idmap_iter_t **iter) { 579 580 idmap_iter_t *tmpiter; 581 idmap_list_namerules_1_argument *arg = NULL; 582 idmap_namerule *rule; 583 idmap_retcode retcode; 584 585 __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES); 586 587 rule = &arg->rule; 588 rule->is_user = is_user; 589 rule->direction = IDMAP_DIRECTION_UNDEF; 590 591 retcode = idmap_strdupnull(&rule->windomain, windomain); 592 if (retcode != IDMAP_SUCCESS) 593 goto errout; 594 595 retcode = idmap_strdupnull(&rule->winname, winname); 596 if (retcode != IDMAP_SUCCESS) 597 goto errout; 598 599 retcode = idmap_strdupnull(&rule->unixname, unixname); 600 if (retcode != IDMAP_SUCCESS) 601 goto errout; 602 603 *iter = tmpiter; 604 return (IDMAP_SUCCESS); 605 606 errout: 607 __ITER_ERR_RETURN(tmpiter, arg, 608 xdr_idmap_list_namerules_1_argument, retcode); 609 } 610 611 612 /* 613 * Iterate through the name-based mapping rules 614 * 615 * Input: 616 * iter - iterator 617 * 618 * Output: 619 * windomain - Windows domain 620 * winname - Windows user or group name 621 * unixname - Unix user or group name 622 * is_nt4 - NT4 or AD 623 * direction - bi(0), win2unix(1), unix2win(2) 624 * 625 * Return value: 626 * 0 - done 627 * 1 - more results available 628 * < 0 - error 629 */ 630 idmap_stat 631 idmap_iter_next_namerule(idmap_iter_t *iter, char **windomain, 632 char **winname, char **unixname, boolean_t *is_nt4, 633 int *direction) { 634 idmap_namerules_res *namerules; 635 idmap_list_namerules_1_argument *arg; 636 idmap_retcode retcode; 637 638 if (windomain) 639 *windomain = NULL; 640 if (winname) 641 *winname = NULL; 642 if (unixname) 643 *unixname = NULL; 644 if (is_nt4) 645 *is_nt4 = 0; 646 if (direction) 647 *direction = IDMAP_DIRECTION_UNDEF; 648 649 __ITER_CHECK(iter, IDMAP_LIST_NAMERULES); 650 651 namerules = (idmap_namerules_res *)iter->retlist; 652 if (iter->retcode == IDMAP_NEXT && (namerules == NULL || 653 iter->next >= namerules->rules.rules_len)) { 654 655 if ((arg = iter->arg) == NULL) { 656 errno = EINVAL; 657 return (IDMAP_ERR_ARG); 658 } 659 arg->limit = iter->limit; 660 661 retcode = _iter_get_next_list(IDMAP_LIST_NAMERULES, 662 iter, arg, 663 (uchar_t **)&namerules, sizeof (*namerules), 664 (xdrproc_t)xdr_idmap_list_namerules_1_argument, 665 (xdrproc_t)xdr_idmap_namerules_res); 666 if (retcode != IDMAP_SUCCESS) 667 return (retcode); 668 669 if (IDMAP_ERROR(namerules->retcode)) { 670 retcode = namerules->retcode; 671 xdr_free(xdr_idmap_namerules_res, (caddr_t)namerules); 672 free(namerules); 673 iter->retlist = NULL; 674 return (retcode); 675 } 676 iter->retcode = namerules->retcode; 677 arg->lastrowid = namerules->lastrowid; 678 } 679 680 if (namerules == NULL || namerules->rules.rules_len == 0) 681 return (IDMAP_SUCCESS); 682 683 if (iter->next >= namerules->rules.rules_len) { 684 return (IDMAP_ERR_ARG); 685 } 686 687 retcode = idmap_strdupnull(windomain, 688 namerules->rules.rules_val[iter->next].windomain); 689 if (retcode != IDMAP_SUCCESS) 690 goto errout; 691 692 retcode = idmap_strdupnull(winname, 693 namerules->rules.rules_val[iter->next].winname); 694 if (retcode != IDMAP_SUCCESS) 695 goto errout; 696 697 retcode = idmap_strdupnull(unixname, 698 namerules->rules.rules_val[iter->next].unixname); 699 if (retcode != IDMAP_SUCCESS) 700 goto errout; 701 702 if (is_nt4) 703 *is_nt4 = namerules->rules.rules_val[iter->next].is_nt4; 704 if (direction) 705 *direction = namerules->rules.rules_val[iter->next].direction; 706 iter->next++; 707 708 if (iter->next == namerules->rules.rules_len) 709 return (iter->retcode); 710 else 711 return (IDMAP_NEXT); 712 713 errout: 714 if (windomain && *windomain) 715 free(*windomain); 716 if (winname && *winname) 717 free(*winname); 718 if (unixname && *unixname) 719 free(*unixname); 720 return (retcode); 721 } 722 723 724 /* 725 * Create iterator to get SID to UID/GID mappings 726 * 727 * Input: 728 * is_user - user or group 729 * 730 * Output: 731 * iter - iterator 732 */ 733 idmap_stat 734 idmap_iter_mappings(idmap_handle_t *handle, boolean_t is_user, 735 idmap_iter_t **iter) { 736 idmap_iter_t *tmpiter; 737 idmap_list_mappings_1_argument *arg = NULL; 738 739 __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS); 740 741 arg->is_user = is_user; 742 *iter = tmpiter; 743 return (IDMAP_SUCCESS); 744 } 745 746 747 /* 748 * Iterate through the SID to UID/GID mappings 749 * 750 * Input: 751 * iter - iterator 752 * 753 * Output: 754 * sid - SID in canonical form 755 * pid - UID or GID 756 * 757 * Return value: 758 * 0 - done 759 * 1 - more results available 760 * < 0 - error 761 */ 762 idmap_stat 763 idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix, 764 idmap_rid_t *rid, uid_t *pid, char **winname, 765 char **windomain, char **unixname, int *direction) { 766 idmap_mappings_res *mappings; 767 idmap_list_mappings_1_argument *arg; 768 idmap_retcode retcode; 769 char *str; 770 771 if (sidprefix) 772 *sidprefix = NULL; 773 if (rid) 774 *rid = UINT32_MAX; 775 if (winname) 776 *winname = NULL; 777 if (windomain) 778 *windomain = NULL; 779 if (unixname) 780 *unixname = NULL; 781 if (pid) 782 *pid = UINT32_MAX; 783 if (direction) 784 *direction = IDMAP_DIRECTION_UNDEF; 785 786 __ITER_CHECK(iter, IDMAP_LIST_MAPPINGS); 787 788 mappings = (idmap_mappings_res *)iter->retlist; 789 if (iter->retcode == IDMAP_NEXT && (mappings == NULL || 790 iter->next >= mappings->mappings.mappings_len)) { 791 792 if ((arg = iter->arg) == NULL) { 793 errno = EINVAL; 794 return (IDMAP_ERR_ARG); 795 } 796 arg->limit = iter->limit; 797 798 retcode = _iter_get_next_list(IDMAP_LIST_MAPPINGS, 799 iter, arg, 800 (uchar_t **)&mappings, sizeof (*mappings), 801 (xdrproc_t)xdr_idmap_list_mappings_1_argument, 802 (xdrproc_t)xdr_idmap_mappings_res); 803 if (retcode != IDMAP_SUCCESS) 804 return (retcode); 805 806 if (IDMAP_ERROR(mappings->retcode)) { 807 retcode = mappings->retcode; 808 xdr_free(xdr_idmap_mappings_res, (caddr_t)mappings); 809 free(mappings); 810 iter->retlist = NULL; 811 return (retcode); 812 } 813 iter->retcode = mappings->retcode; 814 arg->lastrowid = mappings->lastrowid; 815 } 816 817 if (mappings == NULL || mappings->mappings.mappings_len == 0) 818 return (IDMAP_SUCCESS); 819 820 if (iter->next >= mappings->mappings.mappings_len) { 821 return (IDMAP_ERR_ARG); 822 } 823 824 if (sidprefix) { 825 str = mappings->mappings.mappings_val[iter->next].id1. 826 idmap_id_u.sid.prefix; 827 if (str && *str != '\0') { 828 *sidprefix = strdup(str); 829 if (*sidprefix == NULL) { 830 retcode = IDMAP_ERR_MEMORY; 831 goto errout; 832 } 833 } 834 } 835 if (rid) 836 *rid = mappings->mappings.mappings_val[iter->next].id1. 837 idmap_id_u.sid.rid; 838 839 retcode = idmap_strdupnull(windomain, 840 mappings->mappings.mappings_val[iter->next].id1domain); 841 if (retcode != IDMAP_SUCCESS) 842 goto errout; 843 844 retcode = idmap_strdupnull(winname, 845 mappings->mappings.mappings_val[iter->next].id1name); 846 if (retcode != IDMAP_SUCCESS) 847 goto errout; 848 849 retcode = idmap_strdupnull(unixname, 850 mappings->mappings.mappings_val[iter->next].id2name); 851 if (retcode != IDMAP_SUCCESS) 852 goto errout; 853 854 855 if (pid) 856 *pid = mappings->mappings.mappings_val[iter->next].id2. 857 idmap_id_u.uid; 858 if (direction) 859 *direction = mappings->mappings.mappings_val[iter->next]. 860 direction; 861 iter->next++; 862 863 if (iter->next == mappings->mappings.mappings_len) 864 return (iter->retcode); 865 else 866 return (IDMAP_NEXT); 867 868 errout: 869 if (sidprefix && *sidprefix) 870 free(*sidprefix); 871 if (winname && *winname) 872 free(*winname); 873 if (windomain && *windomain) 874 free(*windomain); 875 if (unixname && *unixname) 876 free(*unixname); 877 return (retcode); 878 } 879 880 881 /* 882 * Destroy the iterator 883 */ 884 void 885 idmap_iter_destroy(idmap_iter_t *iter) { 886 xdrproc_t _xdr_argument, _xdr_result; 887 888 if (iter == NULL) 889 return; 890 891 switch (iter->type) { 892 case IDMAP_LIST_NAMERULES: 893 _xdr_argument = (xdrproc_t)xdr_idmap_list_namerules_1_argument; 894 _xdr_result = (xdrproc_t)xdr_idmap_namerules_res; 895 break; 896 case IDMAP_LIST_MAPPINGS: 897 _xdr_argument = (xdrproc_t)xdr_idmap_list_mappings_1_argument; 898 _xdr_result = (xdrproc_t)xdr_idmap_mappings_res; 899 break; 900 default: 901 free(iter); 902 return; 903 }; 904 905 if (iter->arg) { 906 xdr_free(_xdr_argument, (caddr_t)iter->arg); 907 free(iter->arg); 908 } 909 if (iter->retlist) { 910 xdr_free(_xdr_result, (caddr_t)iter->retlist); 911 free(iter->retlist); 912 } 913 free(iter); 914 } 915 916 917 /* 918 * Create handle to get SID to UID/GID mapping entries 919 * 920 * Input: 921 * gh - "get mapping" handle 922 */ 923 idmap_stat 924 idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) { 925 idmap_get_handle_t *tmp; 926 927 /* sanity checks */ 928 if (handle == NULL || gh == NULL) { 929 errno = EINVAL; 930 return (IDMAP_ERR_ARG); 931 } 932 933 /* allocate the handle */ 934 if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { 935 errno = ENOMEM; 936 return (IDMAP_ERR_MEMORY); 937 } 938 939 tmp->ih = handle; 940 *gh = tmp; 941 return (IDMAP_SUCCESS); 942 } 943 944 945 /* 946 * Given SID, get UID 947 * 948 * Input: 949 * sidprefix - SID prefix 950 * rid - RID 951 * flag - flag 952 * 953 * Output: 954 * stat - status of the get request 955 * uid - POSIX UID if stat = 0 956 * 957 * Note: The output parameters will be set by idmap_get_mappings() 958 */ 959 idmap_stat 960 idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 961 int flag, uid_t *uid, idmap_stat *stat) { 962 963 idmap_retcode retcode; 964 idmap_mapping *mapping = NULL; 965 966 /* sanity checks */ 967 if (gh == NULL) 968 return (IDMAP_ERR_ARG); 969 if (uid == NULL || sidprefix == NULL) 970 return (IDMAP_ERR_ARG); 971 972 /* Extend the request array and the return list */ 973 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 974 goto errout; 975 976 /* Setup the request */ 977 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 978 mapping->flag = flag; 979 mapping->id1.idtype = IDMAP_SID; 980 mapping->id1.idmap_id_u.sid.rid = rid; 981 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 982 retcode = IDMAP_ERR_MEMORY; 983 goto errout; 984 } 985 mapping->id2.idtype = IDMAP_UID; 986 987 /* Setup pointers for the result */ 988 gh->retlist[gh->next].idtype = IDMAP_UID; 989 gh->retlist[gh->next].uid = uid; 990 gh->retlist[gh->next].stat = stat; 991 992 gh->next++; 993 return (IDMAP_SUCCESS); 994 995 errout: 996 /* Batch created so far should still be usable */ 997 if (mapping) 998 (void) memset(mapping, 0, sizeof (*mapping)); 999 errno = idmap_stat2errno(retcode); 1000 return (retcode); 1001 } 1002 1003 1004 /* 1005 * Given SID, get GID 1006 * 1007 * Input: 1008 * sidprefix - SID prefix 1009 * rid - rid 1010 * flag - flag 1011 * 1012 * Output: 1013 * stat - status of the get request 1014 * gid - POSIX GID if stat = 0 1015 * 1016 * Note: The output parameters will be set by idmap_get_mappings() 1017 */ 1018 idmap_stat 1019 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1020 int flag, gid_t *gid, idmap_stat *stat) { 1021 1022 idmap_retcode retcode; 1023 idmap_mapping *mapping = NULL; 1024 1025 /* sanity checks */ 1026 if (gh == NULL) 1027 return (IDMAP_ERR_ARG); 1028 if (gid == NULL || sidprefix == NULL) 1029 return (IDMAP_ERR_ARG); 1030 1031 /* Extend the request array and the return list */ 1032 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1033 goto errout; 1034 1035 /* Setup the request */ 1036 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1037 mapping->flag = flag; 1038 mapping->id1.idtype = IDMAP_SID; 1039 mapping->id1.idmap_id_u.sid.rid = rid; 1040 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1041 retcode = IDMAP_ERR_MEMORY; 1042 goto errout; 1043 } 1044 mapping->id2.idtype = IDMAP_GID; 1045 1046 /* Setup pointers for the result */ 1047 gh->retlist[gh->next].idtype = IDMAP_GID; 1048 gh->retlist[gh->next].gid = gid; 1049 gh->retlist[gh->next].stat = stat; 1050 1051 gh->next++; 1052 return (IDMAP_SUCCESS); 1053 1054 errout: 1055 if (mapping) 1056 (void) memset(mapping, 0, sizeof (*mapping)); 1057 errno = idmap_stat2errno(retcode); 1058 return (retcode); 1059 } 1060 1061 1062 /* 1063 * Given SID, get POSIX ID i.e. UID/GID 1064 * 1065 * Input: 1066 * sidprefix - SID prefix 1067 * rid - rid 1068 * flag - flag 1069 * 1070 * Output: 1071 * stat - status of the get request 1072 * is_user - user or group 1073 * pid - POSIX UID if stat = 0 and is_user = 1 1074 * POSIX GID if stat = 0 and is_user = 0 1075 * 1076 * Note: The output parameters will be set by idmap_get_mappings() 1077 */ 1078 idmap_stat 1079 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1080 int flag, uid_t *pid, int *is_user, idmap_stat *stat) { 1081 idmap_retcode retcode; 1082 idmap_mapping *mapping = NULL; 1083 1084 /* sanity checks */ 1085 if (gh == NULL) 1086 return (IDMAP_ERR_ARG); 1087 if (pid == NULL || sidprefix == NULL || is_user == NULL) 1088 return (IDMAP_ERR_ARG); 1089 1090 /* Extend the request array and the return list */ 1091 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1092 goto errout; 1093 1094 /* Setup the request */ 1095 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1096 mapping->flag = flag; 1097 mapping->id1.idtype = IDMAP_SID; 1098 mapping->id1.idmap_id_u.sid.rid = rid; 1099 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1100 retcode = IDMAP_ERR_MEMORY; 1101 goto errout; 1102 } 1103 mapping->id2.idtype = IDMAP_POSIXID; 1104 1105 /* Setup pointers for the result */ 1106 gh->retlist[gh->next].idtype = IDMAP_POSIXID; 1107 gh->retlist[gh->next].uid = pid; 1108 gh->retlist[gh->next].gid = pid; 1109 gh->retlist[gh->next].is_user = is_user; 1110 gh->retlist[gh->next].stat = stat; 1111 1112 gh->next++; 1113 return (IDMAP_SUCCESS); 1114 1115 errout: 1116 if (mapping) 1117 (void) memset(mapping, 0, sizeof (*mapping)); 1118 errno = idmap_stat2errno(retcode); 1119 return (retcode); 1120 } 1121 1122 1123 /* 1124 * Given UID, get SID 1125 * 1126 * Input: 1127 * uid - POSIX UID 1128 * flag - flag 1129 * 1130 * Output: 1131 * stat - status of the get request 1132 * sid - SID prefix (if stat == 0) 1133 * rid - rid 1134 * 1135 * Note: The output parameters will be set by idmap_get_mappings() 1136 */ 1137 idmap_stat 1138 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, 1139 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) { 1140 1141 idmap_retcode retcode; 1142 idmap_mapping *mapping = NULL; 1143 1144 /* sanity checks */ 1145 if (gh == NULL) 1146 return (IDMAP_ERR_ARG); 1147 if (sidprefix == NULL) 1148 return (IDMAP_ERR_ARG); 1149 1150 /* Extend the request array and the return list */ 1151 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1152 goto errout; 1153 1154 /* Setup the request */ 1155 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1156 mapping->flag = flag; 1157 mapping->id1.idtype = IDMAP_UID; 1158 mapping->id1.idmap_id_u.uid = uid; 1159 mapping->id2.idtype = IDMAP_SID; 1160 1161 /* Setup pointers for the result */ 1162 gh->retlist[gh->next].idtype = IDMAP_SID; 1163 gh->retlist[gh->next].sidprefix = sidprefix; 1164 gh->retlist[gh->next].rid = rid; 1165 gh->retlist[gh->next].stat = stat; 1166 1167 gh->next++; 1168 return (IDMAP_SUCCESS); 1169 1170 errout: 1171 if (mapping) 1172 (void) memset(mapping, 0, sizeof (*mapping)); 1173 errno = idmap_stat2errno(retcode); 1174 return (retcode); 1175 } 1176 1177 1178 /* 1179 * Given GID, get SID 1180 * 1181 * Input: 1182 * gid - POSIX GID 1183 * flag - flag 1184 * 1185 * Output: 1186 * stat - status of the get request 1187 * sidprefix - SID prefix (if stat == 0) 1188 * rid - rid 1189 * 1190 * Note: The output parameters will be set by idmap_get_mappings() 1191 */ 1192 idmap_stat 1193 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, 1194 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) { 1195 1196 idmap_retcode retcode; 1197 idmap_mapping *mapping = NULL; 1198 1199 /* sanity checks */ 1200 if (gh == NULL) 1201 return (IDMAP_ERR_ARG); 1202 if (sidprefix == NULL) 1203 return (IDMAP_ERR_ARG); 1204 1205 /* Extend the request array and the return list */ 1206 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1207 goto errout; 1208 1209 /* Setup the request */ 1210 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1211 mapping->flag = flag; 1212 mapping->id1.idtype = IDMAP_GID; 1213 mapping->id1.idmap_id_u.gid = gid; 1214 mapping->id2.idtype = IDMAP_SID; 1215 1216 /* Setup pointers for the result */ 1217 gh->retlist[gh->next].idtype = IDMAP_SID; 1218 gh->retlist[gh->next].sidprefix = sidprefix; 1219 gh->retlist[gh->next].rid = rid; 1220 gh->retlist[gh->next].stat = stat; 1221 1222 gh->next++; 1223 return (IDMAP_SUCCESS); 1224 1225 errout: 1226 if (mapping) 1227 (void) memset(mapping, 0, sizeof (*mapping)); 1228 errno = idmap_stat2errno(retcode); 1229 return (retcode); 1230 } 1231 1232 1233 /* 1234 * Process the batched "get mapping" requests. The results (i.e. 1235 * status and identity) will be available in the data areas 1236 * provided by individual requests. 1237 */ 1238 idmap_stat 1239 idmap_get_mappings(idmap_get_handle_t *gh) { 1240 CLIENT *clnt; 1241 enum clnt_stat clntstat; 1242 idmap_retcode retcode; 1243 idmap_ids_res res; 1244 idmap_id *id; 1245 int i; 1246 1247 if (gh == NULL) { 1248 errno = EINVAL; 1249 return (IDMAP_ERR_ARG); 1250 } 1251 _IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt); 1252 1253 (void) memset(&res, 0, sizeof (idmap_ids_res)); 1254 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS, 1255 (xdrproc_t)xdr_idmap_mapping_batch, 1256 (caddr_t)&gh->batch, 1257 (xdrproc_t)xdr_idmap_ids_res, 1258 (caddr_t)&res, 1259 TIMEOUT); 1260 if (clntstat != RPC_SUCCESS) { 1261 retcode = _idmap_rpc2stat(clnt); 1262 goto out; 1263 } 1264 if (res.retcode != IDMAP_SUCCESS) { 1265 retcode = res.retcode; 1266 goto out; 1267 } 1268 for (i = 0; i < gh->next; i++) { 1269 if (i >= res.ids.ids_len) { 1270 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1271 continue; 1272 } 1273 *gh->retlist[i].stat = res.ids.ids_val[i].retcode; 1274 id = &res.ids.ids_val[i].id; 1275 switch (id->idtype) { 1276 case IDMAP_UID: 1277 if (gh->retlist[i].uid) 1278 *gh->retlist[i].uid = id->idmap_id_u.uid; 1279 if (gh->retlist[i].is_user) 1280 *gh->retlist[i].is_user = 1; 1281 break; 1282 case IDMAP_GID: 1283 if (gh->retlist[i].gid) 1284 *gh->retlist[i].gid = id->idmap_id_u.gid; 1285 if (gh->retlist[i].is_user) 1286 *gh->retlist[i].is_user = 0; 1287 break; 1288 case IDMAP_POSIXID: 1289 if (gh->retlist[i].uid) 1290 *gh->retlist[i].uid = 60001; 1291 if (gh->retlist[i].is_user) 1292 *gh->retlist[i].is_user = -1; 1293 break; 1294 case IDMAP_SID: 1295 if (gh->retlist[i].rid) 1296 *gh->retlist[i].rid = id->idmap_id_u.sid.rid; 1297 if (gh->retlist[i].sidprefix) { 1298 if (id->idmap_id_u.sid.prefix == NULL || 1299 *id->idmap_id_u.sid.prefix == '\0') { 1300 *gh->retlist[i].sidprefix = NULL; 1301 break; 1302 } 1303 *gh->retlist[i].sidprefix = 1304 strdup(id->idmap_id_u.sid.prefix); 1305 if (*gh->retlist[i].sidprefix == NULL) 1306 *gh->retlist[i].stat = 1307 IDMAP_ERR_MEMORY; 1308 } 1309 break; 1310 case IDMAP_NONE: 1311 break; 1312 default: 1313 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1314 break; 1315 } 1316 } 1317 retcode = IDMAP_SUCCESS; 1318 1319 out: 1320 _IDMAP_RESET_GET_HANDLE(gh); 1321 (void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res); 1322 errno = idmap_stat2errno(retcode); 1323 return (retcode); 1324 } 1325 1326 1327 /* 1328 * Destroy the "get mapping" handle 1329 */ 1330 void 1331 idmap_get_destroy(idmap_get_handle_t *gh) { 1332 if (gh == NULL) 1333 return; 1334 (void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch); 1335 if (gh->retlist) 1336 free(gh->retlist); 1337 free(gh); 1338 } 1339 1340 1341 /* 1342 * Get windows to unix mapping 1343 */ 1344 idmap_stat 1345 idmap_get_w2u_mapping(idmap_handle_t *handle, 1346 const char *sidprefix, idmap_rid_t *rid, 1347 const char *winname, const char *windomain, 1348 int flag, int *is_user, 1349 uid_t *pid, char **unixname, int *direction) { 1350 CLIENT *clnt; 1351 enum clnt_stat clntstat; 1352 idmap_mapping request, *mapping; 1353 idmap_mappings_res result; 1354 idmap_retcode retcode, rc; 1355 1356 if (handle == NULL) { 1357 errno = EINVAL; 1358 return (IDMAP_ERR_ARG); 1359 } 1360 1361 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1362 1363 (void) memset(&request, 0, sizeof (request)); 1364 (void) memset(&result, 0, sizeof (result)); 1365 1366 if (is_user) 1367 *is_user = -1; 1368 if (pid) 1369 *pid = UINT32_MAX; 1370 if (unixname) 1371 *unixname = NULL; 1372 if (direction) 1373 *direction = IDMAP_DIRECTION_UNDEF; 1374 1375 request.flag = flag; 1376 request.id1.idtype = IDMAP_SID; 1377 if (sidprefix && rid) { 1378 request.id1.idmap_id_u.sid.prefix = (char *)sidprefix; 1379 request.id1.idmap_id_u.sid.rid = *rid; 1380 } else if (winname) { 1381 retcode = idmap_strdupnull(&request.id1name, winname); 1382 if (retcode != SUCCESS) 1383 goto out; 1384 1385 retcode = idmap_strdupnull(&request.id1domain, windomain); 1386 if (retcode != SUCCESS) 1387 goto out; 1388 1389 request.id1.idmap_id_u.sid.prefix = NULL; 1390 } else { 1391 errno = EINVAL; 1392 return (IDMAP_ERR_ARG); 1393 } 1394 1395 if (is_user == NULL) 1396 request.id2.idtype = IDMAP_POSIXID; 1397 else if (*is_user == 1) 1398 request.id2.idtype = IDMAP_UID; 1399 else if (*is_user == 0) 1400 request.id2.idtype = IDMAP_GID; 1401 else 1402 request.id2.idtype = IDMAP_POSIXID; 1403 1404 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1405 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1406 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1407 TIMEOUT); 1408 1409 if (clntstat != RPC_SUCCESS) 1410 return (_idmap_rpc2stat(clnt)); 1411 1412 retcode = result.retcode; 1413 1414 if ((mapping = result.mappings.mappings_val) == NULL) { 1415 if (retcode == IDMAP_SUCCESS) 1416 retcode = IDMAP_ERR_NORESULT; 1417 goto out; 1418 } 1419 1420 if (mapping->id2.idtype == IDMAP_UID) { 1421 if (is_user) *is_user = 1; 1422 } else if (mapping->id2.idtype == IDMAP_GID) { 1423 if (is_user) *is_user = 0; 1424 } else { 1425 goto out; 1426 } 1427 if (direction) 1428 *direction = mapping->direction; 1429 if (pid) 1430 *pid = mapping->id2.idmap_id_u.uid; 1431 1432 rc = idmap_strdupnull(unixname, mapping->id2name); 1433 if (rc != IDMAP_SUCCESS) 1434 retcode = rc; 1435 1436 out: 1437 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1438 if (retcode != IDMAP_SUCCESS) 1439 errno = idmap_stat2errno(retcode); 1440 return (retcode); 1441 } 1442 1443 1444 /* 1445 * Get unix to windows mapping 1446 */ 1447 idmap_stat 1448 idmap_get_u2w_mapping(idmap_handle_t *handle, 1449 uid_t *pid, const char *unixname, 1450 int flag, int is_user, 1451 char **sidprefix, idmap_rid_t *rid, 1452 char **winname, char **windomain, 1453 int *direction) { 1454 CLIENT *clnt; 1455 enum clnt_stat clntstat; 1456 idmap_mapping request, *mapping; 1457 idmap_mappings_res result; 1458 idmap_retcode retcode, rc; 1459 1460 if (handle == NULL) { 1461 errno = EINVAL; 1462 return (IDMAP_ERR_ARG); 1463 } 1464 1465 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1466 1467 if (sidprefix) 1468 *sidprefix = NULL; 1469 if (winname) 1470 *winname = NULL; 1471 if (windomain) 1472 *windomain = NULL; 1473 if (rid) 1474 *rid = UINT32_MAX; 1475 if (direction) 1476 *direction = IDMAP_DIRECTION_UNDEF; 1477 1478 (void) memset(&request, 0, sizeof (request)); 1479 (void) memset(&result, 0, sizeof (result)); 1480 1481 request.flag = flag; 1482 request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID; 1483 1484 if (pid && *pid != UINT32_MAX) { 1485 request.id1.idmap_id_u.uid = *pid; 1486 } else if (unixname) { 1487 request.id1name = (char *)unixname; 1488 request.id1.idmap_id_u.uid = UINT32_MAX; 1489 } else { 1490 errno = EINVAL; 1491 return (IDMAP_ERR_ARG); 1492 } 1493 1494 request.id2.idtype = IDMAP_SID; 1495 1496 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1497 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1498 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1499 TIMEOUT); 1500 1501 if (clntstat != RPC_SUCCESS) 1502 return (_idmap_rpc2stat(clnt)); 1503 1504 retcode = result.retcode; 1505 1506 if ((mapping = result.mappings.mappings_val) == NULL) { 1507 if (retcode == IDMAP_SUCCESS) 1508 retcode = IDMAP_ERR_NORESULT; 1509 goto out; 1510 } 1511 1512 if (direction) 1513 *direction = mapping->direction; 1514 if (sidprefix && mapping->id2.idmap_id_u.sid.prefix && 1515 *mapping->id2.idmap_id_u.sid.prefix != '\0') { 1516 *sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix); 1517 if (*sidprefix == NULL) { 1518 retcode = IDMAP_ERR_MEMORY; 1519 goto errout; 1520 } 1521 } 1522 if (rid) 1523 *rid = mapping->id2.idmap_id_u.sid.rid; 1524 1525 rc = idmap_strdupnull(winname, mapping->id2name); 1526 if (rc != IDMAP_SUCCESS) 1527 retcode = rc; 1528 1529 rc = idmap_strdupnull(windomain, mapping->id2domain); 1530 if (rc != IDMAP_SUCCESS) 1531 retcode = rc; 1532 1533 goto out; 1534 1535 errout: 1536 if (sidprefix && *sidprefix) { 1537 free(*sidprefix); 1538 *sidprefix = NULL; 1539 } 1540 if (winname && *winname) { 1541 free(*winname); 1542 *winname = NULL; 1543 } 1544 if (windomain && *windomain) { 1545 free(*windomain); 1546 *windomain = NULL; 1547 } 1548 1549 out: 1550 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1551 if (retcode != IDMAP_SUCCESS) 1552 errno = idmap_stat2errno(retcode); 1553 return (retcode); 1554 } 1555 1556 1557 1558 #define gettext(s) s 1559 static stat_table_t stattable[] = { 1560 {IDMAP_SUCCESS, gettext("Success"), 0}, 1561 {IDMAP_NEXT, gettext("More results available"), 0}, 1562 {IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL}, 1563 {IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL}, 1564 {IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM}, 1565 {IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL}, 1566 {IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL}, 1567 {IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL}, 1568 {IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP}, 1569 {IDMAP_ERR_W2U_NAMERULE, 1570 gettext("Invalid Windows to UNIX name-based rule"), EINVAL}, 1571 {IDMAP_ERR_U2W_NAMERULE, 1572 gettext("Invalid UNIX to Windows name-based rule"), EINVAL}, 1573 {IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL}, 1574 {IDMAP_ERR_DB, gettext("Invalid database"), EINVAL}, 1575 {IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL}, 1576 {IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL}, 1577 {IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL}, 1578 {IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF}, 1579 {IDMAP_ERR_RPC, gettext("RPC error"), EINVAL}, 1580 {IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL}, 1581 {IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY}, 1582 {IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES}, 1583 {IDMAP_ERR_NOMAPPING, 1584 gettext("Mapping not found or inhibited"), EINVAL}, 1585 {IDMAP_ERR_NEW_ID_ALLOC_REQD, 1586 gettext("New mapping needs to be created"), EINVAL}, 1587 {IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL}, 1588 {IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL}, 1589 {IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL}, 1590 {IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL}, 1591 {IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL}, 1592 {IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL}, 1593 {IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL}, 1594 {IDMAP_ERR_NOTMAPPED_WELLKNOWN, 1595 gettext("No mapping for well-known SID"), EINVAL}, 1596 {IDMAP_ERR_RETRIABLE_NET_ERR, 1597 gettext("Windows lookup failed"), EINVAL}, 1598 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 1599 gettext("Duplicate rule or conflicts with an existing " 1600 "Windows to UNIX name-based rule"), EINVAL}, 1601 {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 1602 gettext("Duplicate rule or conflicts with an existing " 1603 "Unix to Windows name-based rule"), EINVAL}, 1604 {-1, NULL, 0} 1605 }; 1606 #undef gettext 1607 1608 1609 /* 1610 * Get description of status code 1611 * 1612 * Input: 1613 * status - Status code returned by libidmap API call 1614 * 1615 * Return Value: 1616 * human-readable localized description of idmap_stat 1617 */ 1618 /* ARGSUSED */ 1619 const char * 1620 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) { 1621 int i; 1622 1623 for (i = 0; stattable[i].msg; i++) { 1624 if (stattable[i].retcode == status) 1625 return (gettext(stattable[i].msg)); 1626 } 1627 return (gettext("Unknown error")); 1628 } 1629 1630 1631 static int 1632 idmap_stat2errno(idmap_stat stat) { 1633 int i; 1634 for (i = 0; stattable[i].msg; i++) { 1635 if (stattable[i].retcode == stat) 1636 return (stattable[i].errnum); 1637 } 1638 return (EINVAL); 1639 } 1640 1641 1642 /* 1643 * Get status code from string 1644 */ 1645 idmap_stat 1646 idmap_string2stat(const char *str) { 1647 if (str == NULL) 1648 return (IDMAP_ERR_INTERNAL); 1649 1650 #define return_cmp(a) \ 1651 if (0 == strcmp(str, "IDMAP_ERR_" #a)) \ 1652 return (IDMAP_ERR_ ## a); 1653 1654 return_cmp(OTHER); 1655 return_cmp(INTERNAL); 1656 return_cmp(MEMORY); 1657 return_cmp(NORESULT); 1658 return_cmp(NOTUSER); 1659 return_cmp(NOTGROUP); 1660 return_cmp(NOTSUPPORTED); 1661 return_cmp(W2U_NAMERULE); 1662 return_cmp(U2W_NAMERULE); 1663 return_cmp(CACHE); 1664 return_cmp(DB); 1665 return_cmp(ARG); 1666 return_cmp(SID); 1667 return_cmp(IDTYPE); 1668 return_cmp(RPC_HANDLE); 1669 return_cmp(RPC); 1670 return_cmp(CLIENT_HANDLE); 1671 return_cmp(BUSY); 1672 return_cmp(PERMISSION_DENIED); 1673 return_cmp(NOMAPPING); 1674 return_cmp(NEW_ID_ALLOC_REQD); 1675 return_cmp(DOMAIN); 1676 return_cmp(SECURITY); 1677 return_cmp(NOTFOUND); 1678 return_cmp(DOMAIN_NOTFOUND); 1679 return_cmp(MEMORY); 1680 return_cmp(UPDATE_NOTALLOWED); 1681 return_cmp(CFG); 1682 return_cmp(CFG_CHANGE); 1683 return_cmp(NOTMAPPED_WELLKNOWN); 1684 return_cmp(RETRIABLE_NET_ERR); 1685 return_cmp(W2U_NAMERULE_CONFLICT); 1686 return_cmp(U2W_NAMERULE_CONFLICT); 1687 #undef return_cmp 1688 1689 return (IDMAP_ERR_OTHER); 1690 } 1691 1692 1693 /* 1694 * Map the given status to one that can be returned by the protocol 1695 */ 1696 idmap_stat 1697 idmap_stat4prot(idmap_stat status) { 1698 switch (status) { 1699 case IDMAP_ERR_MEMORY: 1700 case IDMAP_ERR_CACHE: 1701 return (IDMAP_ERR_INTERNAL); 1702 } 1703 return (status); 1704 } 1705 1706 1707 /* 1708 * duplicate a string, possibly null 1709 */ 1710 static idmap_stat 1711 idmap_strdupnull(char **to, const char *from) { 1712 if (from == NULL || *from == '\0') { 1713 *to = NULL; 1714 return (IDMAP_SUCCESS); 1715 } 1716 1717 *to = strdup(from); 1718 if (*to == NULL) 1719 return (IDMAP_ERR_MEMORY); 1720 return (IDMAP_SUCCESS); 1721 } 1722 1723 idmap_stat 1724 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) { 1725 idmap_stat retval; 1726 1727 (void) memcpy(to, from, sizeof (idmap_namerule)); 1728 1729 retval = idmap_strdupnull(&to->windomain, from->windomain); 1730 if (retval != IDMAP_SUCCESS) 1731 return (retval); 1732 1733 retval = idmap_strdupnull(&to->winname, from->winname); 1734 if (retval != IDMAP_SUCCESS) 1735 return (retval); 1736 1737 retval = idmap_strdupnull(&to->unixname, from->unixname); 1738 1739 return (retval); 1740 } 1741 1742 1743 /* 1744 * Get uid given Windows name 1745 */ 1746 idmap_stat 1747 idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) { 1748 idmap_handle_t *ih; 1749 idmap_retcode rc; 1750 int is_user; 1751 1752 if (uid == NULL) 1753 return (IDMAP_ERR_ARG); 1754 1755 /* Get mapping */ 1756 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 1757 return (rc); 1758 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 1759 &is_user, uid, NULL, NULL); 1760 (void) idmap_fini(ih); 1761 1762 /* 1763 * XXX Until we have diagonal mapping support, check if 1764 * the given name belongs to a user 1765 */ 1766 if (rc == IDMAP_SUCCESS && !is_user) 1767 return (IDMAP_ERR_NOTUSER); 1768 return (rc); 1769 } 1770 1771 1772 /* 1773 * Get gid given Windows name 1774 */ 1775 idmap_stat 1776 idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) { 1777 idmap_handle_t *ih; 1778 idmap_retcode rc; 1779 int is_user; 1780 1781 if (gid == NULL) 1782 return (IDMAP_ERR_ARG); 1783 1784 /* Get mapping */ 1785 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 1786 return (rc); 1787 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 1788 &is_user, gid, NULL, NULL); 1789 (void) idmap_fini(ih); 1790 1791 /* 1792 * XXX Until we have diagonal mapping support, check if 1793 * the given name belongs to a group 1794 */ 1795 if (rc == IDMAP_SUCCESS && is_user) 1796 return (IDMAP_ERR_NOTGROUP); 1797 return (rc); 1798 } 1799 1800 1801 /* 1802 * Get winname given pid 1803 */ 1804 static idmap_retcode 1805 idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) { 1806 idmap_handle_t *ih; 1807 idmap_retcode rc; 1808 int len; 1809 char *winname, *windomain; 1810 1811 if (name == NULL) 1812 return (IDMAP_ERR_ARG); 1813 1814 /* Get mapping */ 1815 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 1816 return (rc); 1817 rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, 1818 NULL, &winname, &windomain, NULL); 1819 (void) idmap_fini(ih); 1820 1821 /* Return on error */ 1822 if (rc != IDMAP_SUCCESS) 1823 return (rc); 1824 1825 /* 1826 * The given PID may have been mapped to a locally 1827 * generated SID in which case there isn't any 1828 * Windows name 1829 */ 1830 if (winname == NULL || windomain == NULL) { 1831 idmap_free(winname); 1832 idmap_free(windomain); 1833 return (IDMAP_ERR_NORESULT); 1834 } 1835 1836 if (domain != NULL) { 1837 *name = winname; 1838 *domain = windomain; 1839 } else { 1840 len = strlen(winname) + strlen(windomain) + 2; 1841 if ((*name = malloc(len)) != NULL) 1842 (void) snprintf(*name, len, "%s@%s", winname, 1843 windomain); 1844 else 1845 rc = IDMAP_ERR_MEMORY; 1846 idmap_free(winname); 1847 idmap_free(windomain); 1848 } 1849 return (rc); 1850 } 1851 1852 1853 /* 1854 * Get winname given uid 1855 */ 1856 idmap_stat 1857 idmap_getwinnamebyuid(uid_t uid, char **name, char **domain) { 1858 return (idmap_getwinnamebypid(uid, 1, name, domain)); 1859 } 1860 1861 1862 /* 1863 * Get winname given gid 1864 */ 1865 idmap_stat 1866 idmap_getwinnamebygid(gid_t gid, char **name, char **domain) { 1867 return (idmap_getwinnamebypid(gid, 0, name, domain)); 1868 } 1869