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