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