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