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 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1765 if (retcode != IDMAP_SUCCESS) 1766 errno = idmap_stat2errno(retcode); 1767 return (retcode); 1768 } 1769 1770 1771 /* 1772 * Get unix to windows mapping 1773 */ 1774 idmap_stat 1775 idmap_get_u2w_mapping(idmap_handle_t *handle, 1776 uid_t *pid, const char *unixname, 1777 int flag, int is_user, int *is_wuser, 1778 char **sidprefix, idmap_rid_t *rid, 1779 char **winname, char **windomain, 1780 int *direction, idmap_info *info) 1781 { 1782 CLIENT *clnt; 1783 enum clnt_stat clntstat; 1784 idmap_mapping request, *mapping; 1785 idmap_mappings_res result; 1786 idmap_retcode retcode, rc; 1787 1788 if (handle == NULL) { 1789 errno = EINVAL; 1790 return (IDMAP_ERR_ARG); 1791 } 1792 1793 _IDMAP_GET_CLIENT_HANDLE(handle, clnt); 1794 1795 if (sidprefix) 1796 *sidprefix = NULL; 1797 if (winname) 1798 *winname = NULL; 1799 if (windomain) 1800 *windomain = NULL; 1801 if (rid) 1802 *rid = UINT32_MAX; 1803 if (direction) 1804 *direction = IDMAP_DIRECTION_UNDEF; 1805 1806 (void) memset(&request, 0, sizeof (request)); 1807 (void) memset(&result, 0, sizeof (result)); 1808 1809 request.flag = flag; 1810 request.id1.idtype = is_user?IDMAP_UID:IDMAP_GID; 1811 1812 if (pid && *pid != UINT32_MAX) { 1813 request.id1.idmap_id_u.uid = *pid; 1814 } else if (unixname) { 1815 request.id1name = (char *)unixname; 1816 request.id1.idmap_id_u.uid = UINT32_MAX; 1817 } else { 1818 errno = EINVAL; 1819 return (IDMAP_ERR_ARG); 1820 } 1821 1822 if (is_wuser == NULL) 1823 request.id2.idtype = IDMAP_SID; 1824 else if (*is_wuser == -1) 1825 request.id2.idtype = IDMAP_SID; 1826 else if (*is_wuser == 0) 1827 request.id2.idtype = IDMAP_GSID; 1828 else if (*is_wuser == 1) 1829 request.id2.idtype = IDMAP_USID; 1830 1831 clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, 1832 (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, 1833 (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, 1834 TIMEOUT); 1835 1836 if (clntstat != RPC_SUCCESS) 1837 return (_idmap_rpc2stat(clnt)); 1838 1839 retcode = result.retcode; 1840 1841 if ((mapping = result.mappings.mappings_val) == NULL) { 1842 if (retcode == IDMAP_SUCCESS) 1843 retcode = IDMAP_ERR_NORESULT; 1844 goto out; 1845 } 1846 1847 if (direction != NULL) 1848 *direction = mapping->direction; 1849 1850 if (is_wuser != NULL) { 1851 if (mapping->id2.idtype == IDMAP_USID) 1852 *is_wuser = 1; 1853 else if (mapping->id2.idtype == IDMAP_GSID) 1854 *is_wuser = 0; 1855 else 1856 *is_wuser = -1; 1857 } 1858 1859 if (sidprefix && mapping->id2.idmap_id_u.sid.prefix && 1860 *mapping->id2.idmap_id_u.sid.prefix != '\0') { 1861 *sidprefix = strdup(mapping->id2.idmap_id_u.sid.prefix); 1862 if (*sidprefix == NULL) { 1863 retcode = IDMAP_ERR_MEMORY; 1864 goto errout; 1865 } 1866 } 1867 if (rid) 1868 *rid = mapping->id2.idmap_id_u.sid.rid; 1869 1870 rc = idmap_strdupnull(winname, mapping->id2name); 1871 if (rc != IDMAP_SUCCESS) 1872 retcode = rc; 1873 1874 rc = idmap_strdupnull(windomain, mapping->id2domain); 1875 if (rc != IDMAP_SUCCESS) 1876 retcode = rc; 1877 1878 rc = idmap_info_cpy(info, &mapping->info); 1879 if (rc != IDMAP_SUCCESS) 1880 retcode = rc; 1881 1882 goto out; 1883 1884 errout: 1885 if (sidprefix && *sidprefix) { 1886 free(*sidprefix); 1887 *sidprefix = NULL; 1888 } 1889 if (winname && *winname) { 1890 free(*winname); 1891 *winname = NULL; 1892 } 1893 if (windomain && *windomain) { 1894 free(*windomain); 1895 *windomain = NULL; 1896 } 1897 1898 out: 1899 xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); 1900 if (retcode != IDMAP_SUCCESS) 1901 errno = idmap_stat2errno(retcode); 1902 return (retcode); 1903 } 1904 1905 1906 1907 #define gettext(s) s 1908 static stat_table_t stattable[] = { 1909 {IDMAP_SUCCESS, gettext("Success"), 0}, 1910 {IDMAP_NEXT, gettext("More results available"), 0}, 1911 {IDMAP_ERR_OTHER, gettext("Undefined error"), EINVAL}, 1912 {IDMAP_ERR_INTERNAL, gettext("Internal error"), EINVAL}, 1913 {IDMAP_ERR_MEMORY, gettext("Out of memory"), ENOMEM}, 1914 {IDMAP_ERR_NORESULT, gettext("No results available"), EINVAL}, 1915 {IDMAP_ERR_NOTUSER, gettext("Not a user"), EINVAL}, 1916 {IDMAP_ERR_NOTGROUP, gettext("Not a group"), EINVAL}, 1917 {IDMAP_ERR_NOTSUPPORTED, gettext("Operation not supported"), ENOTSUP}, 1918 {IDMAP_ERR_W2U_NAMERULE, 1919 gettext("Invalid Windows to UNIX name-based rule"), EINVAL}, 1920 {IDMAP_ERR_U2W_NAMERULE, 1921 gettext("Invalid UNIX to Windows name-based rule"), EINVAL}, 1922 {IDMAP_ERR_CACHE, gettext("Invalid cache"), EINVAL}, 1923 {IDMAP_ERR_DB, gettext("Invalid database"), EINVAL}, 1924 {IDMAP_ERR_ARG, gettext("Invalid argument"), EINVAL}, 1925 {IDMAP_ERR_SID, gettext("Invalid SID"), EINVAL}, 1926 {IDMAP_ERR_IDTYPE, gettext("Invalid identity type"), EINVAL}, 1927 {IDMAP_ERR_RPC_HANDLE, gettext("Bad RPC handle"), EBADF}, 1928 {IDMAP_ERR_RPC, gettext("RPC error"), EINVAL}, 1929 {IDMAP_ERR_CLIENT_HANDLE, gettext("Bad client handle"), EINVAL}, 1930 {IDMAP_ERR_BUSY, gettext("Server is busy"), EBUSY}, 1931 {IDMAP_ERR_PERMISSION_DENIED, gettext("Permission denied"), EACCES}, 1932 {IDMAP_ERR_NOMAPPING, 1933 gettext("Mapping not found or inhibited"), EINVAL}, 1934 {IDMAP_ERR_NEW_ID_ALLOC_REQD, 1935 gettext("New mapping needs to be created"), EINVAL}, 1936 {IDMAP_ERR_DOMAIN, gettext("Invalid domain"), EINVAL}, 1937 {IDMAP_ERR_SECURITY, gettext("Security issue"), EINVAL}, 1938 {IDMAP_ERR_NOTFOUND, gettext("Not found"), EINVAL}, 1939 {IDMAP_ERR_DOMAIN_NOTFOUND, gettext("Domain not found"), EINVAL}, 1940 {IDMAP_ERR_UPDATE_NOTALLOWED, gettext("Update not allowed"), EINVAL}, 1941 {IDMAP_ERR_CFG, gettext("Configuration error"), EINVAL}, 1942 {IDMAP_ERR_CFG_CHANGE, gettext("Invalid configuration change"), EINVAL}, 1943 {IDMAP_ERR_NOTMAPPED_WELLKNOWN, 1944 gettext("No mapping for well-known SID"), EINVAL}, 1945 {IDMAP_ERR_RETRIABLE_NET_ERR, 1946 gettext("Windows lookup failed"), EINVAL}, 1947 {IDMAP_ERR_W2U_NAMERULE_CONFLICT, 1948 gettext("Duplicate rule or conflicts with an existing " 1949 "Windows to UNIX name-based rule"), EINVAL}, 1950 {IDMAP_ERR_U2W_NAMERULE_CONFLICT, 1951 gettext("Duplicate rule or conflicts with an existing " 1952 "Unix to Windows name-based rule"), EINVAL}, 1953 {IDMAP_ERR_BAD_UTF8, 1954 gettext("Invalid or illegal UTF-8 sequence found in " 1955 "a given Windows entity name or domain name"), EINVAL}, 1956 {IDMAP_ERR_NONEGENERATED, 1957 gettext("Mapping not found and none created (see -c option)"), 1958 EINVAL}, 1959 {IDMAP_ERR_PROP_UNKNOWN, 1960 gettext("Undefined property"), 1961 EINVAL}, 1962 {IDMAP_ERR_NS_LDAP_CFG, 1963 gettext("Native LDAP configuration error"), EINVAL}, 1964 {IDMAP_ERR_NS_LDAP_PARTIAL, 1965 gettext("Partial result from Native LDAP"), EINVAL}, 1966 {IDMAP_ERR_NS_LDAP_OP_FAILED, 1967 gettext("Native LDAP operation failed"), EINVAL}, 1968 {IDMAP_ERR_NS_LDAP_BAD_WINNAME, 1969 gettext("Improper winname form found in Native LDAP"), EINVAL}, 1970 {-1, NULL, 0} 1971 }; 1972 #undef gettext 1973 1974 1975 /* 1976 * Get description of status code 1977 * 1978 * Input: 1979 * status - Status code returned by libidmap API call 1980 * 1981 * Return Value: 1982 * human-readable localized description of idmap_stat 1983 */ 1984 /* ARGSUSED */ 1985 const char * 1986 idmap_stat2string(idmap_handle_t *handle, idmap_stat status) 1987 { 1988 int i; 1989 1990 for (i = 0; stattable[i].msg; i++) { 1991 if (stattable[i].retcode == status) 1992 return (gettext(stattable[i].msg)); 1993 } 1994 return (gettext("Unknown error")); 1995 } 1996 1997 1998 static int 1999 idmap_stat2errno(idmap_stat stat) 2000 { 2001 int i; 2002 for (i = 0; stattable[i].msg; i++) { 2003 if (stattable[i].retcode == stat) 2004 return (stattable[i].errnum); 2005 } 2006 return (EINVAL); 2007 } 2008 2009 2010 /* 2011 * Get status code from string 2012 */ 2013 idmap_stat 2014 idmap_string2stat(const char *str) 2015 { 2016 if (str == NULL) 2017 return (IDMAP_ERR_INTERNAL); 2018 2019 #define return_cmp(a) \ 2020 if (0 == strcmp(str, "IDMAP_ERR_" #a)) \ 2021 return (IDMAP_ERR_ ## a); 2022 2023 return_cmp(OTHER); 2024 return_cmp(INTERNAL); 2025 return_cmp(MEMORY); 2026 return_cmp(NORESULT); 2027 return_cmp(NOTUSER); 2028 return_cmp(NOTGROUP); 2029 return_cmp(NOTSUPPORTED); 2030 return_cmp(W2U_NAMERULE); 2031 return_cmp(U2W_NAMERULE); 2032 return_cmp(CACHE); 2033 return_cmp(DB); 2034 return_cmp(ARG); 2035 return_cmp(SID); 2036 return_cmp(IDTYPE); 2037 return_cmp(RPC_HANDLE); 2038 return_cmp(RPC); 2039 return_cmp(CLIENT_HANDLE); 2040 return_cmp(BUSY); 2041 return_cmp(PERMISSION_DENIED); 2042 return_cmp(NOMAPPING); 2043 return_cmp(NEW_ID_ALLOC_REQD); 2044 return_cmp(DOMAIN); 2045 return_cmp(SECURITY); 2046 return_cmp(NOTFOUND); 2047 return_cmp(DOMAIN_NOTFOUND); 2048 return_cmp(MEMORY); 2049 return_cmp(UPDATE_NOTALLOWED); 2050 return_cmp(CFG); 2051 return_cmp(CFG_CHANGE); 2052 return_cmp(NOTMAPPED_WELLKNOWN); 2053 return_cmp(RETRIABLE_NET_ERR); 2054 return_cmp(W2U_NAMERULE_CONFLICT); 2055 return_cmp(U2W_NAMERULE_CONFLICT); 2056 return_cmp(BAD_UTF8); 2057 return_cmp(NONEGENERATED); 2058 return_cmp(PROP_UNKNOWN); 2059 return_cmp(NS_LDAP_CFG); 2060 return_cmp(NS_LDAP_PARTIAL); 2061 return_cmp(NS_LDAP_OP_FAILED); 2062 return_cmp(NS_LDAP_BAD_WINNAME); 2063 #undef return_cmp 2064 2065 return (IDMAP_ERR_OTHER); 2066 } 2067 2068 2069 /* 2070 * Map the given status to one that can be returned by the protocol 2071 */ 2072 idmap_stat 2073 idmap_stat4prot(idmap_stat status) 2074 { 2075 switch (status) { 2076 case IDMAP_ERR_MEMORY: 2077 case IDMAP_ERR_CACHE: 2078 return (IDMAP_ERR_INTERNAL); 2079 } 2080 return (status); 2081 } 2082 2083 2084 /* 2085 * This is a convenience routine which duplicates a string after 2086 * checking for NULL pointers. This function will return success if 2087 * either the 'to' OR 'from' pointers are NULL. 2088 */ 2089 static idmap_stat 2090 idmap_strdupnull(char **to, const char *from) 2091 { 2092 if (to == NULL) 2093 return (IDMAP_SUCCESS); 2094 2095 if (from == NULL || *from == '\0') { 2096 *to = NULL; 2097 return (IDMAP_SUCCESS); 2098 } 2099 2100 *to = strdup(from); 2101 if (*to == NULL) 2102 return (IDMAP_ERR_MEMORY); 2103 return (IDMAP_SUCCESS); 2104 } 2105 2106 2107 idmap_stat 2108 idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) 2109 { 2110 idmap_stat retval; 2111 2112 if (to == NULL) 2113 return (IDMAP_SUCCESS); 2114 2115 (void) memcpy(to, from, sizeof (idmap_namerule)); 2116 to->windomain = NULL; 2117 to->winname = NULL; 2118 to->unixname = NULL; 2119 2120 retval = idmap_strdupnull(&to->windomain, from->windomain); 2121 if (retval != IDMAP_SUCCESS) 2122 return (retval); 2123 2124 retval = idmap_strdupnull(&to->winname, from->winname); 2125 if (retval != IDMAP_SUCCESS) { 2126 free(to->windomain); 2127 to->windomain = NULL; 2128 return (retval); 2129 } 2130 2131 retval = idmap_strdupnull(&to->unixname, from->unixname); 2132 if (retval != IDMAP_SUCCESS) { 2133 free(to->windomain); 2134 to->windomain = NULL; 2135 free(to->winname); 2136 to->winname = NULL; 2137 return (retval); 2138 } 2139 2140 return (retval); 2141 } 2142 2143 2144 static 2145 idmap_stat 2146 idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from) 2147 { 2148 idmap_stat retval; 2149 2150 if (to == NULL) 2151 return (IDMAP_SUCCESS); 2152 2153 retval = idmap_strdupnull(&to->dn, from->dn); 2154 if (retval != IDMAP_SUCCESS) 2155 return (retval); 2156 2157 retval = idmap_strdupnull(&to->attr, from->attr); 2158 if (retval != IDMAP_SUCCESS) { 2159 free(to->dn); 2160 to->dn = NULL; 2161 return (retval); 2162 } 2163 2164 retval = idmap_strdupnull(&to->value, from->value); 2165 if (retval != IDMAP_SUCCESS) { 2166 free(to->dn); 2167 to->dn = NULL; 2168 free(to->attr); 2169 to->attr = NULL; 2170 return (retval); 2171 } 2172 2173 return (retval); 2174 } 2175 2176 2177 idmap_stat 2178 idmap_info_cpy(idmap_info *to, idmap_info *from) 2179 { 2180 idmap_stat retval = IDMAP_SUCCESS; 2181 2182 if (to == NULL) 2183 return (IDMAP_SUCCESS); 2184 2185 (void) memset(to, 0, sizeof (idmap_info)); 2186 2187 to->src = from->src; 2188 to->how.map_type = from->how.map_type; 2189 switch (to->how.map_type) { 2190 case IDMAP_MAP_TYPE_DS_AD: 2191 retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad, 2192 &from->how.idmap_how_u.ad); 2193 break; 2194 2195 case IDMAP_MAP_TYPE_DS_NLDAP: 2196 retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap, 2197 &from->how.idmap_how_u.nldap); 2198 break; 2199 2200 case IDMAP_MAP_TYPE_RULE_BASED: 2201 retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule, 2202 &from->how.idmap_how_u.rule); 2203 break; 2204 2205 case IDMAP_MAP_TYPE_EPHEMERAL: 2206 break; 2207 2208 case IDMAP_MAP_TYPE_LOCAL_SID: 2209 break; 2210 2211 case IDMAP_MAP_TYPE_KNOWN_SID: 2212 break; 2213 } 2214 return (retval); 2215 } 2216 2217 2218 /* 2219 * This routine is similar to idmap_info_cpy, but the strings 2220 * are moved from the "from" info to the "to" info. 2221 * This routine is equivelent of: 2222 * 2223 * idmap_info_cpy(to,from); 2224 * idmap_info_free(from); 2225 */ 2226 idmap_stat 2227 idmap_info_mov(idmap_info *to, idmap_info *from) 2228 { 2229 idmap_stat retval = IDMAP_SUCCESS; 2230 2231 if (to == NULL) { 2232 idmap_info_free(from); 2233 return (IDMAP_SUCCESS); 2234 } 2235 (void) memcpy(to, from, sizeof (idmap_info)); 2236 2237 (void) memset(from, 0, sizeof (idmap_info)); 2238 2239 return (retval); 2240 } 2241 2242 2243 void 2244 idmap_info_free(idmap_info *info) 2245 { 2246 idmap_how *how; 2247 2248 if (info == NULL) 2249 return; 2250 2251 how = &info->how; 2252 switch (how->map_type) { 2253 case IDMAP_MAP_TYPE_DS_AD: 2254 free(how->idmap_how_u.ad.dn); 2255 how->idmap_how_u.ad.dn = NULL; 2256 free(how->idmap_how_u.ad.attr); 2257 how->idmap_how_u.ad.attr = NULL; 2258 free(how->idmap_how_u.ad.value); 2259 how->idmap_how_u.ad.value = NULL; 2260 break; 2261 2262 case IDMAP_MAP_TYPE_DS_NLDAP: 2263 free(how->idmap_how_u.nldap.dn); 2264 how->idmap_how_u.nldap.dn = NULL; 2265 free(how->idmap_how_u.nldap.attr); 2266 how->idmap_how_u.nldap.attr = NULL; 2267 free(how->idmap_how_u.nldap.value); 2268 how->idmap_how_u.nldap.value = NULL; 2269 break; 2270 2271 case IDMAP_MAP_TYPE_RULE_BASED: 2272 free(how->idmap_how_u.rule.windomain); 2273 how->idmap_how_u.rule.windomain = NULL; 2274 free(how->idmap_how_u.rule.winname); 2275 how->idmap_how_u.rule.winname = NULL; 2276 free(how->idmap_how_u.rule.unixname); 2277 how->idmap_how_u.rule.unixname = NULL; 2278 break; 2279 2280 case IDMAP_MAP_TYPE_EPHEMERAL: 2281 break; 2282 2283 case IDMAP_MAP_TYPE_LOCAL_SID: 2284 break; 2285 } 2286 how->map_type = IDMAP_MAP_TYPE_UNKNOWN; 2287 info->src = IDMAP_MAP_SRC_UNKNOWN; 2288 } 2289 2290 2291 /* 2292 * Get uid given Windows name 2293 */ 2294 idmap_stat 2295 idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) 2296 { 2297 idmap_handle_t *ih; 2298 idmap_retcode rc; 2299 int is_user = 1; 2300 int is_wuser = -1; 2301 2302 if (uid == NULL) 2303 return (IDMAP_ERR_ARG); 2304 2305 /* Get mapping */ 2306 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2307 return (rc); 2308 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 2309 &is_user, &is_wuser, uid, NULL, NULL, NULL); 2310 (void) idmap_fini(ih); 2311 2312 /* 2313 * XXX Until we have diagonal mapping support, check if 2314 * the given name belongs to a user 2315 */ 2316 if (rc == IDMAP_SUCCESS && !is_user) 2317 return (IDMAP_ERR_NOTUSER); 2318 return (rc); 2319 } 2320 2321 2322 /* 2323 * Get gid given Windows name 2324 */ 2325 idmap_stat 2326 idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) 2327 { 2328 idmap_handle_t *ih; 2329 idmap_retcode rc; 2330 int is_user = 0; 2331 int is_wuser = -1; 2332 2333 if (gid == NULL) 2334 return (IDMAP_ERR_ARG); 2335 2336 /* Get mapping */ 2337 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2338 return (rc); 2339 rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, 2340 &is_user, &is_wuser, gid, NULL, NULL, NULL); 2341 (void) idmap_fini(ih); 2342 2343 /* 2344 * XXX Until we have diagonal mapping support, check if 2345 * the given name belongs to a group 2346 */ 2347 if (rc == IDMAP_SUCCESS && is_user) 2348 return (IDMAP_ERR_NOTGROUP); 2349 return (rc); 2350 } 2351 2352 2353 /* 2354 * Get winname given pid 2355 */ 2356 static idmap_retcode 2357 idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) 2358 { 2359 idmap_handle_t *ih; 2360 idmap_retcode rc; 2361 int len; 2362 char *winname, *windomain; 2363 2364 if (name == NULL) 2365 return (IDMAP_ERR_ARG); 2366 2367 /* Get mapping */ 2368 if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) 2369 return (rc); 2370 rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, NULL, 2371 NULL, &winname, &windomain, NULL, NULL); 2372 (void) idmap_fini(ih); 2373 2374 /* Return on error */ 2375 if (rc != IDMAP_SUCCESS) 2376 return (rc); 2377 2378 /* 2379 * The given PID may have been mapped to a locally 2380 * generated SID in which case there isn't any 2381 * Windows name 2382 */ 2383 if (winname == NULL || windomain == NULL) { 2384 idmap_free(winname); 2385 idmap_free(windomain); 2386 return (IDMAP_ERR_NORESULT); 2387 } 2388 2389 if (domain != NULL) { 2390 *name = winname; 2391 *domain = windomain; 2392 } else { 2393 len = strlen(winname) + strlen(windomain) + 2; 2394 if ((*name = malloc(len)) != NULL) 2395 (void) snprintf(*name, len, "%s@%s", winname, 2396 windomain); 2397 else 2398 rc = IDMAP_ERR_MEMORY; 2399 idmap_free(winname); 2400 idmap_free(windomain); 2401 } 2402 return (rc); 2403 } 2404 2405 2406 /* 2407 * Get winname given uid 2408 */ 2409 idmap_stat 2410 idmap_getwinnamebyuid(uid_t uid, char **name, char **domain) 2411 { 2412 return (idmap_getwinnamebypid(uid, 1, name, domain)); 2413 } 2414 2415 2416 /* 2417 * Get winname given gid 2418 */ 2419 idmap_stat 2420 idmap_getwinnamebygid(gid_t gid, char **name, char **domain) 2421 { 2422 return (idmap_getwinnamebypid(gid, 0, name, domain)); 2423 } 2424 2425 2426 /* printflike */ 2427 void 2428 idmapdlog(int pri, const char *format, ...) { 2429 va_list args; 2430 2431 va_start(args, format); 2432 if (pri <= logstate.max_pri) { 2433 (void) vfprintf(stderr, format, args); 2434 (void) fprintf(stderr, "\n"); 2435 } 2436 2437 /* 2438 * We don't want to fill up the logs with useless messages when 2439 * we're degraded, but we still want to log. 2440 */ 2441 if (logstate.degraded) 2442 pri = LOG_DEBUG; 2443 2444 if (logstate.write_syslog) 2445 (void) vsyslog(pri, format, args); 2446 va_end(args); 2447 } 2448 2449 void 2450 idmap_log_stderr(int pri) 2451 { 2452 logstate.max_pri = pri; 2453 } 2454 2455 void 2456 idmap_log_syslog(bool_t what) 2457 { 2458 logstate.write_syslog = what; 2459 } 2460 2461 void 2462 idmap_log_degraded(bool_t what) 2463 { 2464 logstate.degraded = what; 2465 } 2466