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