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