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