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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * libidmap API 30 */ 31 32 #include <stdlib.h> 33 #include <sys/varargs.h> 34 #include <inttypes.h> 35 #include <errno.h> 36 #include <strings.h> 37 #include <ctype.h> 38 #include <sys/param.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <dlfcn.h> 42 #include <libintl.h> 43 #include <ucontext.h> 44 #include "idmap_impl.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 /* Extend the request array and the return list */ 1165 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1166 goto errout; 1167 1168 /* Setup the request */ 1169 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1170 mapping->flag = flag; 1171 mapping->id1.idtype = IDMAP_SID; 1172 mapping->id1.idmap_id_u.sid.rid = rid; 1173 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1174 retcode = IDMAP_ERR_MEMORY; 1175 goto errout; 1176 } 1177 mapping->id2.idtype = IDMAP_UID; 1178 1179 /* Setup pointers for the result */ 1180 gh->retlist[gh->next].idtype = IDMAP_UID; 1181 gh->retlist[gh->next].uid = uid; 1182 gh->retlist[gh->next].stat = stat; 1183 gh->retlist[gh->next].info = info; 1184 1185 gh->next++; 1186 return (IDMAP_SUCCESS); 1187 1188 errout: 1189 /* Batch created so far should still be usable */ 1190 if (mapping) 1191 (void) memset(mapping, 0, sizeof (*mapping)); 1192 errno = idmap_stat2errno(retcode); 1193 return (retcode); 1194 } 1195 1196 1197 /* 1198 * Given SID, get GID 1199 * 1200 * Input: 1201 * sidprefix - SID prefix 1202 * rid - rid 1203 * flag - flag 1204 * 1205 * Output: 1206 * stat - status of the get request 1207 * gid - POSIX GID if stat = 0 1208 * 1209 * Note: The output parameters will be set by idmap_get_mappings() 1210 */ 1211 idmap_stat 1212 idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1213 int flag, gid_t *gid, idmap_stat *stat) 1214 { 1215 return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid, 1216 NULL, stat)); 1217 } 1218 1219 1220 /* 1221 * Given SID, get GID 1222 * 1223 * Input: 1224 * sidprefix - SID prefix 1225 * rid - rid 1226 * flag - flag 1227 * 1228 * Output: 1229 * stat - status of the get request 1230 * gid - POSIX GID if stat = 0 1231 * how - mapping type if stat = 0 1232 * 1233 * Note: The output parameters will be set by idmap_get_mappings() 1234 */ 1235 idmap_stat 1236 idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1237 int flag, gid_t *gid, idmap_info *info, idmap_stat *stat) 1238 { 1239 1240 idmap_retcode retcode; 1241 idmap_mapping *mapping = NULL; 1242 1243 /* sanity checks */ 1244 if (gh == NULL) 1245 return (IDMAP_ERR_ARG); 1246 if (gid == NULL || sidprefix == NULL) 1247 return (IDMAP_ERR_ARG); 1248 1249 /* Extend the request array and the return list */ 1250 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1251 goto errout; 1252 1253 /* Setup the request */ 1254 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1255 mapping->flag = flag; 1256 mapping->id1.idtype = IDMAP_SID; 1257 mapping->id1.idmap_id_u.sid.rid = rid; 1258 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1259 retcode = IDMAP_ERR_MEMORY; 1260 goto errout; 1261 } 1262 mapping->id2.idtype = IDMAP_GID; 1263 1264 /* Setup pointers for the result */ 1265 gh->retlist[gh->next].idtype = IDMAP_GID; 1266 gh->retlist[gh->next].gid = gid; 1267 gh->retlist[gh->next].stat = stat; 1268 gh->retlist[gh->next].info = info; 1269 1270 gh->next++; 1271 return (IDMAP_SUCCESS); 1272 1273 errout: 1274 if (mapping) 1275 (void) memset(mapping, 0, sizeof (*mapping)); 1276 errno = idmap_stat2errno(retcode); 1277 return (retcode); 1278 } 1279 1280 1281 1282 /* 1283 * Given SID, get POSIX ID i.e. UID/GID 1284 * 1285 * Input: 1286 * sidprefix - SID prefix 1287 * rid - rid 1288 * flag - flag 1289 * 1290 * Output: 1291 * stat - status of the get request 1292 * is_user - user or group 1293 * pid - POSIX UID if stat = 0 and is_user = 1 1294 * POSIX GID if stat = 0 and is_user = 0 1295 * 1296 * Note: The output parameters will be set by idmap_get_mappings() 1297 */ 1298 idmap_stat 1299 idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1300 int flag, uid_t *pid, int *is_user, idmap_stat *stat) 1301 { 1302 return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user, 1303 NULL, stat)); 1304 } 1305 1306 1307 1308 /* 1309 * Given SID, get POSIX ID i.e. UID/GID 1310 * 1311 * Input: 1312 * sidprefix - SID prefix 1313 * rid - rid 1314 * flag - flag 1315 * 1316 * Output: 1317 * stat - status of the get request 1318 * is_user - user or group 1319 * pid - POSIX UID if stat = 0 and is_user = 1 1320 * POSIX GID if stat = 0 and is_user = 0 1321 * how - mapping type if stat = 0 1322 * 1323 * Note: The output parameters will be set by idmap_get_mappings() 1324 */ 1325 idmap_stat 1326 idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, 1327 int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat) 1328 { 1329 idmap_retcode retcode; 1330 idmap_mapping *mapping = NULL; 1331 1332 /* sanity checks */ 1333 if (gh == NULL) 1334 return (IDMAP_ERR_ARG); 1335 if (pid == NULL || sidprefix == NULL || is_user == NULL) 1336 return (IDMAP_ERR_ARG); 1337 1338 /* Extend the request array and the return list */ 1339 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1340 goto errout; 1341 1342 /* Setup the request */ 1343 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1344 mapping->flag = flag; 1345 mapping->id1.idtype = IDMAP_SID; 1346 mapping->id1.idmap_id_u.sid.rid = rid; 1347 if ((mapping->id1.idmap_id_u.sid.prefix = strdup(sidprefix)) == NULL) { 1348 retcode = IDMAP_ERR_MEMORY; 1349 goto errout; 1350 } 1351 mapping->id2.idtype = IDMAP_POSIXID; 1352 1353 /* Setup pointers for the result */ 1354 gh->retlist[gh->next].idtype = IDMAP_POSIXID; 1355 gh->retlist[gh->next].uid = pid; 1356 gh->retlist[gh->next].gid = pid; 1357 gh->retlist[gh->next].is_user = is_user; 1358 gh->retlist[gh->next].stat = stat; 1359 gh->retlist[gh->next].info = info; 1360 1361 gh->next++; 1362 return (IDMAP_SUCCESS); 1363 1364 errout: 1365 if (mapping) 1366 (void) memset(mapping, 0, sizeof (*mapping)); 1367 errno = idmap_stat2errno(retcode); 1368 return (retcode); 1369 } 1370 1371 1372 /* 1373 * Given UID, get SID 1374 * 1375 * Input: 1376 * uid - POSIX UID 1377 * flag - flag 1378 * 1379 * Output: 1380 * stat - status of the get request 1381 * sid - SID prefix (if stat == 0) 1382 * rid - rid 1383 * 1384 * Note: The output parameters will be set by idmap_get_mappings() 1385 */ 1386 idmap_stat 1387 idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, 1388 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) 1389 { 1390 return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid, 1391 NULL, stat)); 1392 } 1393 1394 1395 /* 1396 * Given UID, get SID 1397 * 1398 * Input: 1399 * uid - POSIX UID 1400 * flag - flag 1401 * 1402 * Output: 1403 * stat - status of the get request 1404 * sid - SID prefix (if stat == 0) 1405 * rid - rid 1406 * how - mapping type if stat = 0 1407 * 1408 * Note: The output parameters will be set by idmap_get_mappings() 1409 */ 1410 idmap_stat 1411 idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, 1412 char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) 1413 { 1414 1415 idmap_retcode retcode; 1416 idmap_mapping *mapping = NULL; 1417 1418 /* sanity checks */ 1419 if (gh == NULL) 1420 return (IDMAP_ERR_ARG); 1421 if (sidprefix == NULL) 1422 return (IDMAP_ERR_ARG); 1423 1424 /* Extend the request array and the return list */ 1425 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1426 goto errout; 1427 1428 /* Setup the request */ 1429 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1430 mapping->flag = flag; 1431 mapping->id1.idtype = IDMAP_UID; 1432 mapping->id1.idmap_id_u.uid = uid; 1433 mapping->id2.idtype = IDMAP_SID; 1434 1435 /* Setup pointers for the result */ 1436 gh->retlist[gh->next].idtype = IDMAP_SID; 1437 gh->retlist[gh->next].sidprefix = sidprefix; 1438 gh->retlist[gh->next].rid = rid; 1439 gh->retlist[gh->next].stat = stat; 1440 gh->retlist[gh->next].info = info; 1441 1442 gh->next++; 1443 return (IDMAP_SUCCESS); 1444 1445 errout: 1446 if (mapping) 1447 (void) memset(mapping, 0, sizeof (*mapping)); 1448 errno = idmap_stat2errno(retcode); 1449 return (retcode); 1450 } 1451 1452 1453 /* 1454 * Given GID, get SID 1455 * 1456 * Input: 1457 * gid - POSIX GID 1458 * flag - flag 1459 * 1460 * Output: 1461 * stat - status of the get request 1462 * sidprefix - SID prefix (if stat == 0) 1463 * rid - rid 1464 * 1465 * Note: The output parameters will be set by idmap_get_mappings() 1466 */ 1467 idmap_stat 1468 idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, 1469 char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) 1470 { 1471 return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid, 1472 NULL, stat)); 1473 } 1474 1475 1476 /* 1477 * Given GID, get SID 1478 * 1479 * Input: 1480 * gid - POSIX GID 1481 * flag - flag 1482 * 1483 * Output: 1484 * stat - status of the get request 1485 * sidprefix - SID prefix (if stat == 0) 1486 * rid - rid 1487 * how - mapping type if stat = 0 1488 * 1489 * Note: The output parameters will be set by idmap_get_mappings() 1490 */ 1491 idmap_stat 1492 idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, 1493 char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) 1494 { 1495 1496 idmap_retcode retcode; 1497 idmap_mapping *mapping = NULL; 1498 1499 /* sanity checks */ 1500 if (gh == NULL) 1501 return (IDMAP_ERR_ARG); 1502 if (sidprefix == NULL) 1503 return (IDMAP_ERR_ARG); 1504 1505 /* Extend the request array and the return list */ 1506 if ((retcode = _get_ids_extend_batch(gh)) != IDMAP_SUCCESS) 1507 goto errout; 1508 1509 /* Setup the request */ 1510 mapping = &gh->batch.idmap_mapping_batch_val[gh->next]; 1511 mapping->flag = flag; 1512 mapping->id1.idtype = IDMAP_GID; 1513 mapping->id1.idmap_id_u.gid = gid; 1514 mapping->id2.idtype = IDMAP_SID; 1515 1516 /* Setup pointers for the result */ 1517 gh->retlist[gh->next].idtype = IDMAP_SID; 1518 gh->retlist[gh->next].sidprefix = sidprefix; 1519 gh->retlist[gh->next].rid = rid; 1520 gh->retlist[gh->next].stat = stat; 1521 gh->retlist[gh->next].info = info; 1522 1523 gh->next++; 1524 return (IDMAP_SUCCESS); 1525 1526 errout: 1527 if (mapping) 1528 (void) memset(mapping, 0, sizeof (*mapping)); 1529 errno = idmap_stat2errno(retcode); 1530 return (retcode); 1531 } 1532 1533 1534 /* 1535 * Process the batched "get mapping" requests. The results (i.e. 1536 * status and identity) will be available in the data areas 1537 * provided by individual requests. 1538 */ 1539 idmap_stat 1540 idmap_get_mappings(idmap_get_handle_t *gh) 1541 { 1542 CLIENT *clnt; 1543 enum clnt_stat clntstat; 1544 idmap_retcode retcode; 1545 idmap_ids_res res; 1546 idmap_id *id; 1547 int i; 1548 1549 if (gh == NULL) { 1550 errno = EINVAL; 1551 return (IDMAP_ERR_ARG); 1552 } 1553 _IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt); 1554 1555 (void) memset(&res, 0, sizeof (idmap_ids_res)); 1556 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS, 1557 (xdrproc_t)xdr_idmap_mapping_batch, 1558 (caddr_t)&gh->batch, 1559 (xdrproc_t)xdr_idmap_ids_res, 1560 (caddr_t)&res, 1561 TIMEOUT); 1562 if (clntstat != RPC_SUCCESS) { 1563 retcode = _idmap_rpc2stat(clnt); 1564 goto out; 1565 } 1566 if (res.retcode != IDMAP_SUCCESS) { 1567 retcode = res.retcode; 1568 goto out; 1569 } 1570 for (i = 0; i < gh->next; i++) { 1571 if (i >= res.ids.ids_len) { 1572 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1573 continue; 1574 } 1575 *gh->retlist[i].stat = res.ids.ids_val[i].retcode; 1576 id = &res.ids.ids_val[i].id; 1577 switch (id->idtype) { 1578 case IDMAP_UID: 1579 if (gh->retlist[i].uid) 1580 *gh->retlist[i].uid = id->idmap_id_u.uid; 1581 if (gh->retlist[i].is_user) 1582 *gh->retlist[i].is_user = 1; 1583 break; 1584 case IDMAP_GID: 1585 if (gh->retlist[i].gid) 1586 *gh->retlist[i].gid = id->idmap_id_u.gid; 1587 if (gh->retlist[i].is_user) 1588 *gh->retlist[i].is_user = 0; 1589 break; 1590 case IDMAP_POSIXID: 1591 if (gh->retlist[i].uid) 1592 *gh->retlist[i].uid = 60001; 1593 if (gh->retlist[i].is_user) 1594 *gh->retlist[i].is_user = -1; 1595 break; 1596 case IDMAP_SID: 1597 case IDMAP_USID: 1598 case IDMAP_GSID: 1599 if (gh->retlist[i].rid) 1600 *gh->retlist[i].rid = id->idmap_id_u.sid.rid; 1601 if (gh->retlist[i].sidprefix) { 1602 if (id->idmap_id_u.sid.prefix == NULL || 1603 *id->idmap_id_u.sid.prefix == '\0') { 1604 *gh->retlist[i].sidprefix = NULL; 1605 break; 1606 } 1607 *gh->retlist[i].sidprefix = 1608 strdup(id->idmap_id_u.sid.prefix); 1609 if (*gh->retlist[i].sidprefix == NULL) 1610 *gh->retlist[i].stat = 1611 IDMAP_ERR_MEMORY; 1612 } 1613 break; 1614 case IDMAP_NONE: 1615 break; 1616 default: 1617 *gh->retlist[i].stat = IDMAP_ERR_NORESULT; 1618 break; 1619 } 1620 if (gh->retlist[i].info != NULL) 1621 (void) idmap_info_cpy(gh->retlist[i].info, 1622 &res.ids.ids_val[i].info); 1623 } 1624 retcode = IDMAP_SUCCESS; 1625 1626 out: 1627 _IDMAP_RESET_GET_HANDLE(gh); 1628 (void) xdr_free(xdr_idmap_ids_res, (caddr_t)&res); 1629 errno = idmap_stat2errno(retcode); 1630 return (retcode); 1631 } 1632 1633 1634 /* 1635 * Destroy the "get mapping" handle 1636 */ 1637 void 1638 idmap_get_destroy(idmap_get_handle_t *gh) 1639 { 1640 if (gh == NULL) 1641 return; 1642 (void) xdr_free(xdr_idmap_mapping_batch, (caddr_t)&gh->batch); 1643 if (gh->retlist) 1644 free(gh->retlist); 1645 free(gh); 1646 } 1647 1648 1649 /* 1650 * Get windows to unix mapping 1651 */ 1652 idmap_stat 1653 idmap_get_w2u_mapping(idmap_handle_t *handle, 1654 const char *sidprefix, idmap_rid_t *rid, 1655 const char *winname, const char *windomain, 1656 int flag, int *is_user, int *is_wuser, 1657 uid_t *pid, char **unixname, int *direction, idmap_info *info) 1658 { 1659 CLIENT *clnt; 1660 enum clnt_stat clntstat; 1661 idmap_mapping request, *mapping; 1662 idmap_mappings_res result; 1663 idmap_retcode retcode, rc; 1664 1665 if (handle == NULL) { 1666 errno = EINVAL; 1667 return (IDMAP_ERR_ARG); 1668 } 1669 1670 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1671 1672 (void) memset(&request, 0, sizeof (request)); 1673 (void) memset(&result, 0, sizeof (result)); 1674 1675 if (pid) 1676 *pid = UINT32_MAX; 1677 if (unixname) 1678 *unixname = NULL; 1679 if (direction) 1680 *direction = IDMAP_DIRECTION_UNDEF; 1681 1682 request.flag = flag; 1683 request.id1.idtype = IDMAP_SID; 1684 if (sidprefix && rid) { 1685 request.id1.idmap_id_u.sid.prefix = (char *)sidprefix; 1686 request.id1.idmap_id_u.sid.rid = *rid; 1687 } else if (winname) { 1688 retcode = idmap_strdupnull(&request.id1name, winname); 1689 if (retcode != IDMAP_SUCCESS) 1690 goto out; 1691 1692 retcode = idmap_strdupnull(&request.id1domain, windomain); 1693 if (retcode != IDMAP_SUCCESS) 1694 goto out; 1695 1696 request.id1.idmap_id_u.sid.prefix = NULL; 1697 } else { 1698 errno = EINVAL; 1699 return (IDMAP_ERR_ARG); 1700 } 1701 1702 if (*is_user == 1) 1703 request.id2.idtype = IDMAP_UID; 1704 else if (*is_user == 0) 1705 request.id2.idtype = IDMAP_GID; 1706 else 1707 request.id2.idtype = IDMAP_POSIXID; 1708 1709 if (*is_wuser == 1) 1710 request.id1.idtype = IDMAP_USID; 1711 else if (*is_wuser == 0) 1712 request.id1.idtype = IDMAP_GSID; 1713 else 1714 request.id1.idtype = IDMAP_SID; 1715 1716 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1717 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1718 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1719 TIMEOUT); 1720 1721 if (clntstat != RPC_SUCCESS) 1722 return (_idmap_rpc2stat(clnt)); 1723 1724 retcode = result.retcode; 1725 1726 if ((mapping = result.mappings.mappings_val) == NULL) { 1727 if (retcode == IDMAP_SUCCESS) 1728 retcode = IDMAP_ERR_NORESULT; 1729 goto out; 1730 } 1731 1732 if (mapping->id2.idtype == IDMAP_UID) { 1733 *is_user = 1; 1734 } else if (mapping->id2.idtype == IDMAP_GID) { 1735 *is_user = 0; 1736 } else { 1737 goto out; 1738 } 1739 1740 if (mapping->id1.idtype == IDMAP_USID) { 1741 *is_wuser = 1; 1742 } else if (mapping->id1.idtype == IDMAP_GSID) { 1743 *is_wuser = 0; 1744 } else { 1745 goto out; 1746 } 1747 1748 if (direction) 1749 *direction = mapping->direction; 1750 if (pid) 1751 *pid = mapping->id2.idmap_id_u.uid; 1752 1753 rc = idmap_strdupnull(unixname, mapping->id2name); 1754 if (rc != IDMAP_SUCCESS) 1755 retcode = rc; 1756 1757 rc = idmap_info_cpy(info, &mapping->info); 1758 if (rc != IDMAP_SUCCESS) 1759 retcode = rc; 1760 1761 out: 1762 if (request.id1name != NULL) 1763 free(request.id1name); 1764 if (request.id1domain != NULL) 1765 free(request.id1domain); 1766 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1767 if (retcode != IDMAP_SUCCESS) 1768 errno = idmap_stat2errno(retcode); 1769 return (retcode); 1770 } 1771 1772 1773 /* 1774 * Get unix to windows mapping 1775 */ 1776 idmap_stat 1777 idmap_get_u2w_mapping(idmap_handle_t *handle, 1778 uid_t *pid, const char *unixname, 1779 int flag, int is_user, int *is_wuser, 1780 char **sidprefix, idmap_rid_t *rid, 1781 char **winname, char **windomain, 1782 int *direction, idmap_info *info) 1783 { 1784 CLIENT *clnt; 1785 enum clnt_stat clntstat; 1786 idmap_mapping request, *mapping; 1787 idmap_mappings_res result; 1788 idmap_retcode retcode, rc; 1789 1790 if (handle == NULL) { 1791 errno = EINVAL; 1792 return (IDMAP_ERR_ARG); 1793 } 1794 1795 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1796 1797 if (sidprefix) 1798 *sidprefix = NULL; 1799 if (winname) 1800 *winname = NULL; 1801 if (windomain) 1802 *windomain = NULL; 1803 if (rid) 1804 *rid = UINT32_MAX; 1805 if (direction) 1806 *direction = IDMAP_DIRECTION_UNDEF; 1807 1808 (void) memset(&request, 0, sizeof (request)); 1809 (void) memset(&result, 0, sizeof (result)); 1810 1811 request.flag = flag; 1812 request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID; 1813 1814 if (pid && *pid != UINT32_MAX) { 1815 request.id1.idmap_id_u.uid = *pid; 1816 } else if (unixname) { 1817 request.id1name = (char *)unixname; 1818 request.id1.idmap_id_u.uid = UINT32_MAX; 1819 } else { 1820 errno = EINVAL; 1821 return (IDMAP_ERR_ARG); 1822 } 1823 1824 if (is_wuser == NULL) 1825 request.id2.idtype = IDMAP_SID; 1826 else if (*is_wuser == -1) 1827 request.id2.idtype = IDMAP_SID; 1828 else if (*is_wuser == 0) 1829 request.id2.idtype = IDMAP_GSID; 1830 else if (*is_wuser == 1) 1831 request.id2.idtype = IDMAP_USID; 1832 1833 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1834 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1835 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1836 TIMEOUT); 1837 1838 if (clntstat != RPC_SUCCESS) 1839 return (_idmap_rpc2stat(clnt)); 1840 1841 retcode = result.retcode; 1842 1843 if ((mapping = result.mappings.mappings_val) == NULL) { 1844 if (retcode == IDMAP_SUCCESS) 1845 retcode = IDMAP_ERR_NORESULT; 1846 goto out; 1847 } 1848 1849 if (direction != NULL) 1850 *direction = mapping->direction; 1851 1852 if (is_wuser != NULL) { 1853 if (mapping->id2.idtype == IDMAP_USID) 1854 *is_wuser = 1; 1855 else if (mapping->id2.idtype == IDMAP_GSID) 1856 *is_wuser = 0; 1857 else 1858 *is_wuser = -1; 1859 } 1860 1861 if (sidprefix && mapping->id2.idmap_id_u.sid.prefix && 1862 *mapping->id2.idmap_id_u.sid.prefix != '\0') { 1863 *sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix); 1864 if (*sidprefix == NULL) { 1865 retcode = IDMAP_ERR_MEMORY; 1866 goto errout; 1867 } 1868 } 1869 if (rid) 1870 *rid = mapping->id2.idmap_id_u.sid.rid; 1871 1872 rc = idmap_strdupnull(winname, mapping->id2name); 1873 if (rc != IDMAP_SUCCESS) 1874 retcode = rc; 1875 1876 rc = idmap_strdupnull(windomain, mapping->id2domain); 1877 if (rc != IDMAP_SUCCESS) 1878 retcode = rc; 1879 1880 rc = idmap_info_cpy(info, &mapping->info); 1881 if (rc != IDMAP_SUCCESS) 1882 retcode = rc; 1883 1884 goto out; 1885 1886 errout: 1887 if (sidprefix && *sidprefix) { 1888 free(*sidprefix); 1889 *sidprefix = NULL; 1890 } 1891 if (winname && *winname) { 1892 free(*winname); 1893 *winname = NULL; 1894 } 1895 if (windomain && *windomain) { 1896 free(*windomain); 1897 *windomain = NULL; 1898 } 1899 1900 out: 1901 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1902 if (retcode != IDMAP_SUCCESS) 1903 errno = idmap_stat2errno(retcode); 1904 return (retcode); 1905 } 1906 1907 1908 1909 #define gettext(s) s 1910 static stat_table_t stattable[] = { 1911 {IDMAP_SUCCESS, gettext("Success"), 0}, 1912 {IDMAP_NEXT, gettext("More results available"), 0}, 1913 {IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL}, 1914 {IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL}, 1915 {IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM}, 1916 {IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL}, 1917 {IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL}, 1918 {IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL}, 1919 {IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP}, 1920 {IDMAP_ERR_W2U_NAMERULE, 1921 gettext("Invalid Windows to UNIX name-based rule"), EINVAL}, 1922 {IDMAP_ERR_U2W_NAMERULE, 1923 gettext("Invalid UNIX to Windows name-based rule"), EINVAL}, 1924 {IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL}, 1925 {IDMAP_ERR_DB, gettext("Invalid database"), EINVAL}, 1926 {IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL}, 1927 {IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL}, 1928 {IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL}, 1929 {IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF}, 1930 {IDMAP_ERR_RPC, gettext("RPC error"), EINVAL}, 1931 {IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL}, 1932 {IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY}, 1933 {IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES}, 1934 {IDMAP_ERR_NOMAPPING, 1935 gettext("Mapping not found or inhibited"), EINVAL}, 1936 {IDMAP_ERR_NEW_ID_ALLOC_REQD, 1937 gettext("New mapping needs to be created"), EINVAL}, 1938 {IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL}, 1939 {IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL}, 1940 {IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL}, 1941 {IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL}, 1942 {IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL}, 1943 {IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL}, 1944 {IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL}, 1945 {IDMAP_ERR_NOTMAPPED_WELLKNOWN, 1946 gettext("No mapping for well-known SID"), EINVAL}, 1947 {IDMAP_ERR_RETRIABLE_NET_ERR, 1948 gettext("Windows lookup failed"), EINVAL}, 1949 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 1950 gettext("Duplicate rule or conflicts with an existing " 1951 "Windows to UNIX name-based rule"), EINVAL}, 1952 {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 1953 gettext("Duplicate rule or conflicts with an existing " 1954 "Unix to Windows name-based rule"), EINVAL}, 1955 {IDMAP_ERR_BAD_UTF8, 1956 gettext("Invalid or illegal UTF-8 sequence found in " 1957 "a given Windows entity name or domain name"), EINVAL}, 1958 {IDMAP_ERR_NONEGENERATED, 1959 gettext("Mapping not found and none created (see -c option)"), 1960 EINVAL}, 1961 {IDMAP_ERR_PROP_UNKNOWN, 1962 gettext("Undefined property"), 1963 EINVAL}, 1964 {IDMAP_ERR_NS_LDAP_CFG, 1965 gettext("Native LDAP configuration error"), EINVAL}, 1966 {IDMAP_ERR_NS_LDAP_PARTIAL, 1967 gettext("Partial result from Native LDAP"), EINVAL}, 1968 {IDMAP_ERR_NS_LDAP_OP_FAILED, 1969 gettext("Native LDAP operation failed"), EINVAL}, 1970 {IDMAP_ERR_NS_LDAP_BAD_WINNAME, 1971 gettext("Improper winname form found in Native LDAP"), EINVAL}, 1972 {-1, NULL, 0} 1973 }; 1974 #undef gettext 1975 1976 1977 /* 1978 * Get description of status code 1979 * 1980 * Input: 1981 * status - Status code returned by libidmap API call 1982 * 1983 * Return Value: 1984 * human-readable localized description of idmap_stat 1985 */ 1986 /* ARGSUSED */ 1987 const char * 1988 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) 1989 { 1990 int i; 1991 1992 for (i = 0; stattable[i].msg; i++) { 1993 if (stattable[i].retcode == status) 1994 return (gettext(stattable[i].msg)); 1995 } 1996 return (gettext("Unknown error")); 1997 } 1998 1999 2000 static int 2001 idmap_stat2errno(idmap_stat stat) 2002 { 2003 int i; 2004 for (i = 0; stattable[i].msg; i++) { 2005 if (stattable[i].retcode == stat) 2006 return (stattable[i].errnum); 2007 } 2008 return (EINVAL); 2009 } 2010 2011 2012 /* 2013 * Get status code from string 2014 */ 2015 idmap_stat 2016 idmap_string2stat(const char *str) 2017 { 2018 if (str == NULL) 2019 return (IDMAP_ERR_INTERNAL); 2020 2021 #define return_cmp(a) \ 2022 if (0 == strcmp(str, "IDMAP_ERR_" #a)) \ 2023 return (IDMAP_ERR_ ## a); 2024 2025 return_cmp(OTHER); 2026 return_cmp(INTERNAL); 2027 return_cmp(MEMORY); 2028 return_cmp(NORESULT); 2029 return_cmp(NOTUSER); 2030 return_cmp(NOTGROUP); 2031 return_cmp(NOTSUPPORTED); 2032 return_cmp(W2U_NAMERULE); 2033 return_cmp(U2W_NAMERULE); 2034 return_cmp(CACHE); 2035 return_cmp(DB); 2036 return_cmp(ARG); 2037 return_cmp(SID); 2038 return_cmp(IDTYPE); 2039 return_cmp(RPC_HANDLE); 2040 return_cmp(RPC); 2041 return_cmp(CLIENT_HANDLE); 2042 return_cmp(BUSY); 2043 return_cmp(PERMISSION_DENIED); 2044 return_cmp(NOMAPPING); 2045 return_cmp(NEW_ID_ALLOC_REQD); 2046 return_cmp(DOMAIN); 2047 return_cmp(SECURITY); 2048 return_cmp(NOTFOUND); 2049 return_cmp(DOMAIN_NOTFOUND); 2050 return_cmp(MEMORY); 2051 return_cmp(UPDATE_NOTALLOWED); 2052 return_cmp(CFG); 2053 return_cmp(CFG_CHANGE); 2054 return_cmp(NOTMAPPED_WELLKNOWN); 2055 return_cmp(RETRIABLE_NET_ERR); 2056 return_cmp(W2U_NAMERULE_CONFLICT); 2057 return_cmp(U2W_NAMERULE_CONFLICT); 2058 return_cmp(BAD_UTF8); 2059 return_cmp(NONEGENERATED); 2060 return_cmp(PROP_UNKNOWN); 2061 return_cmp(NS_LDAP_CFG); 2062 return_cmp(NS_LDAP_PARTIAL); 2063 return_cmp(NS_LDAP_OP_FAILED); 2064 return_cmp(NS_LDAP_BAD_WINNAME); 2065 #undef return_cmp 2066 2067 return (IDMAP_ERR_OTHER); 2068 } 2069 2070 2071 /* 2072 * Map the given status to one that can be returned by the protocol 2073 */ 2074 idmap_stat 2075 idmap_stat4prot(idmap_stat status) 2076 { 2077 switch (status) { 2078 case IDMAP_ERR_MEMORY: 2079 case IDMAP_ERR_CACHE: 2080 return (IDMAP_ERR_INTERNAL); 2081 } 2082 return (status); 2083 } 2084 2085 2086 /* 2087 * This is a convenience routine which duplicates a string after 2088 * checking for NULL pointers. This function will return success if 2089 * either the 'to' OR 'from' pointers are NULL. 2090 */ 2091 static idmap_stat 2092 idmap_strdupnull(char **to, const char *from) 2093 { 2094 if (to == NULL) 2095 return (IDMAP_SUCCESS); 2096 2097 if (from == NULL || *from == '\0') { 2098 *to = NULL; 2099 return (IDMAP_SUCCESS); 2100 } 2101 2102 *to = strdup(from); 2103 if (*to == NULL) 2104 return (IDMAP_ERR_MEMORY); 2105 return (IDMAP_SUCCESS); 2106 } 2107 2108 2109 idmap_stat 2110 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) 2111 { 2112 idmap_stat retval; 2113 2114 if (to == NULL) 2115 return (IDMAP_SUCCESS); 2116 2117 (void) memcpy(to, from, sizeof (idmap_namerule)); 2118 to->windomain = NULL; 2119 to->winname = NULL; 2120 to->unixname = NULL; 2121 2122 retval = idmap_strdupnull(&to->windomain, from->windomain); 2123 if (retval != IDMAP_SUCCESS) 2124 return (retval); 2125 2126 retval = idmap_strdupnull(&to->winname, from->winname); 2127 if (retval != IDMAP_SUCCESS) { 2128 free(to->windomain); 2129 to->windomain = NULL; 2130 return (retval); 2131 } 2132 2133 retval = idmap_strdupnull(&to->unixname, from->unixname); 2134 if (retval != IDMAP_SUCCESS) { 2135 free(to->windomain); 2136 to->windomain = NULL; 2137 free(to->winname); 2138 to->winname = NULL; 2139 return (retval); 2140 } 2141 2142 return (retval); 2143 } 2144 2145 2146 static 2147 idmap_stat 2148 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from) 2149 { 2150 idmap_stat retval; 2151 2152 if (to == NULL) 2153 return (IDMAP_SUCCESS); 2154 2155 retval = idmap_strdupnull(&to->dn, from->dn); 2156 if (retval != IDMAP_SUCCESS) 2157 return (retval); 2158 2159 retval = idmap_strdupnull(&to->attr, from->attr); 2160 if (retval != IDMAP_SUCCESS) { 2161 free(to->dn); 2162 to->dn = NULL; 2163 return (retval); 2164 } 2165 2166 retval = idmap_strdupnull(&to->value, from->value); 2167 if (retval != IDMAP_SUCCESS) { 2168 free(to->dn); 2169 to->dn = NULL; 2170 free(to->attr); 2171 to->attr = NULL; 2172 return (retval); 2173 } 2174 2175 return (retval); 2176 } 2177 2178 2179 idmap_stat 2180 idmap_info_cpy(idmap_info *to, idmap_info *from) 2181 { 2182 idmap_stat retval = IDMAP_SUCCESS; 2183 2184 if (to == NULL) 2185 return (IDMAP_SUCCESS); 2186 2187 (void) memset(to, 0, sizeof (idmap_info)); 2188 2189 to->src = from->src; 2190 to->how.map_type = from->how.map_type; 2191 switch (to->how.map_type) { 2192 case IDMAP_MAP_TYPE_DS_AD: 2193 retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad, 2194 &from->how.idmap_how_u.ad); 2195 break; 2196 2197 case IDMAP_MAP_TYPE_DS_NLDAP: 2198 retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap, 2199 &from->how.idmap_how_u.nldap); 2200 break; 2201 2202 case IDMAP_MAP_TYPE_RULE_BASED: 2203 retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule, 2204 &from->how.idmap_how_u.rule); 2205 break; 2206 2207 case IDMAP_MAP_TYPE_EPHEMERAL: 2208 break; 2209 2210 case IDMAP_MAP_TYPE_LOCAL_SID: 2211 break; 2212 2213 case IDMAP_MAP_TYPE_KNOWN_SID: 2214 break; 2215 } 2216 return (retval); 2217 } 2218 2219 2220 /* 2221 * This routine is similar to idmap_info_cpy, but the strings 2222 * are moved from the "from" info to the "to" info. 2223 * This routine is equivelent of: 2224 * 2225 * idmap_info_cpy(to,from); 2226 * idmap_info_free(from); 2227 */ 2228 idmap_stat 2229 idmap_info_mov(idmap_info *to, idmap_info *from) 2230 { 2231 idmap_stat retval = IDMAP_SUCCESS; 2232 2233 if (to == NULL) { 2234 idmap_info_free(from); 2235 return (IDMAP_SUCCESS); 2236 } 2237 (void) memcpy(to, from, sizeof (idmap_info)); 2238 2239 (void) memset(from, 0, sizeof (idmap_info)); 2240 2241 return (retval); 2242 } 2243 2244 2245 void 2246 idmap_info_free(idmap_info *info) 2247 { 2248 idmap_how *how; 2249 2250 if (info == NULL) 2251 return; 2252 2253 how = &info->how; 2254 switch (how->map_type) { 2255 case IDMAP_MAP_TYPE_DS_AD: 2256 free(how->idmap_how_u.ad.dn); 2257 how->idmap_how_u.ad.dn = NULL; 2258 free(how->idmap_how_u.ad.attr); 2259 how->idmap_how_u.ad.attr = NULL; 2260 free(how->idmap_how_u.ad.value); 2261 how->idmap_how_u.ad.value = NULL; 2262 break; 2263 2264 case IDMAP_MAP_TYPE_DS_NLDAP: 2265 free(how->idmap_how_u.nldap.dn); 2266 how->idmap_how_u.nldap.dn = NULL; 2267 free(how->idmap_how_u.nldap.attr); 2268 how->idmap_how_u.nldap.attr = NULL; 2269 free(how->idmap_how_u.nldap.value); 2270 how->idmap_how_u.nldap.value = NULL; 2271 break; 2272 2273 case IDMAP_MAP_TYPE_RULE_BASED: 2274 free(how->idmap_how_u.rule.windomain); 2275 how->idmap_how_u.rule.windomain = NULL; 2276 free(how->idmap_how_u.rule.winname); 2277 how->idmap_how_u.rule.winname = NULL; 2278 free(how->idmap_how_u.rule.unixname); 2279 how->idmap_how_u.rule.unixname = NULL; 2280 break; 2281 2282 case IDMAP_MAP_TYPE_EPHEMERAL: 2283 break; 2284 2285 case IDMAP_MAP_TYPE_LOCAL_SID: 2286 break; 2287 } 2288 how->map_type = IDMAP_MAP_TYPE_UNKNOWN; 2289 info->src = IDMAP_MAP_SRC_UNKNOWN; 2290 } 2291 2292 2293 /* 2294 * Get uid given Windows name 2295 */ 2296 idmap_stat 2297 idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) 2298 { 2299 idmap_handle_t *ih; 2300 idmap_retcode rc; 2301 int is_user = 1; 2302 int is_wuser = -1; 2303 2304 if (uid == NULL) 2305 return (IDMAP_ERR_ARG); 2306 2307 /* Get mapping */ 2308 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2309 return (rc); 2310 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 2311 &is_user, &is_wuser, uid, NULL, NULL, NULL); 2312 (void) idmap_fini(ih); 2313 2314 /* 2315 * XXX Until we have diagonal mapping support, check if 2316 * the given name belongs to a user 2317 */ 2318 if (rc == IDMAP_SUCCESS && !is_user) 2319 return (IDMAP_ERR_NOTUSER); 2320 return (rc); 2321 } 2322 2323 2324 /* 2325 * Get gid given Windows name 2326 */ 2327 idmap_stat 2328 idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) 2329 { 2330 idmap_handle_t *ih; 2331 idmap_retcode rc; 2332 int is_user = 0; 2333 int is_wuser = -1; 2334 2335 if (gid == NULL) 2336 return (IDMAP_ERR_ARG); 2337 2338 /* Get mapping */ 2339 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2340 return (rc); 2341 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 2342 &is_user, &is_wuser, gid, NULL, NULL, NULL); 2343 (void) idmap_fini(ih); 2344 2345 /* 2346 * XXX Until we have diagonal mapping support, check if 2347 * the given name belongs to a group 2348 */ 2349 if (rc == IDMAP_SUCCESS && is_user) 2350 return (IDMAP_ERR_NOTGROUP); 2351 return (rc); 2352 } 2353 2354 2355 /* 2356 * Get winname given pid 2357 */ 2358 static idmap_retcode 2359 idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) 2360 { 2361 idmap_handle_t *ih; 2362 idmap_retcode rc; 2363 int len; 2364 char *winname, *windomain; 2365 2366 if (name == NULL) 2367 return (IDMAP_ERR_ARG); 2368 2369 /* Get mapping */ 2370 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2371 return (rc); 2372 rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, NULL, 2373 NULL, &winname, &windomain, NULL, NULL); 2374 (void) idmap_fini(ih); 2375 2376 /* Return on error */ 2377 if (rc != IDMAP_SUCCESS) 2378 return (rc); 2379 2380 /* 2381 * The given PID may have been mapped to a locally 2382 * generated SID in which case there isn't any 2383 * Windows name 2384 */ 2385 if (winname == NULL || windomain == NULL) { 2386 idmap_free(winname); 2387 idmap_free(windomain); 2388 return (IDMAP_ERR_NORESULT); 2389 } 2390 2391 if (domain != NULL) { 2392 *name = winname; 2393 *domain = windomain; 2394 } else { 2395 len = strlen(winname) + strlen(windomain) + 2; 2396 if ((*name = malloc(len)) != NULL) 2397 (void) snprintf(*name, len, "%s@%s", winname, 2398 windomain); 2399 else 2400 rc = IDMAP_ERR_MEMORY; 2401 idmap_free(winname); 2402 idmap_free(windomain); 2403 } 2404 return (rc); 2405 } 2406 2407 2408 /* 2409 * Get winname given uid 2410 */ 2411 idmap_stat 2412 idmap_getwinnamebyuid(uid_t uid, char **name, char **domain) 2413 { 2414 return (idmap_getwinnamebypid(uid, 1, name, domain)); 2415 } 2416 2417 2418 /* 2419 * Get winname given gid 2420 */ 2421 idmap_stat 2422 idmap_getwinnamebygid(gid_t gid, char **name, char **domain) 2423 { 2424 return (idmap_getwinnamebypid(gid, 0, name, domain)); 2425 } 2426 2427 2428 /* printflike */ 2429 void 2430 idmapdlog(int pri, const char *format, ...) { 2431 va_list args; 2432 2433 va_start(args, format); 2434 if (pri <= logstate.max_pri) { 2435 (void) vfprintf(stderr, format, args); 2436 (void) fprintf(stderr, "\n"); 2437 } 2438 2439 /* 2440 * We don't want to fill up the logs with useless messages when 2441 * we're degraded, but we still want to log. 2442 */ 2443 if (logstate.degraded) 2444 pri = LOG_DEBUG; 2445 2446 if (logstate.write_syslog) 2447 (void) vsyslog(pri, format, args); 2448 va_end(args); 2449 } 2450 2451 void 2452 idmap_log_stderr(int pri) 2453 { 2454 logstate.max_pri = pri; 2455 } 2456 2457 void 2458 idmap_log_syslog(bool_t what) 2459 { 2460 logstate.write_syslog = what; 2461 } 2462 2463 void 2464 idmap_log_degraded(bool_t what) 2465 { 2466 logstate.degraded = what; 2467 } 2468