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