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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 27 /* 28 * Config routines common to idmap(1M) and idmapd(1M) 29 */ 30 31 #include <stdlib.h> 32 #include <strings.h> 33 #include <libintl.h> 34 #include <ctype.h> 35 #include <errno.h> 36 #include "idmapd.h" 37 #include <stdio.h> 38 #include <stdarg.h> 39 #include <uuid/uuid.h> 40 #include <pthread.h> 41 #include <port.h> 42 #include <net/route.h> 43 #include <sys/u8_textprep.h> 44 #include <note.h> 45 #include "addisc.h" 46 47 #define MACHINE_SID_LEN (9 + 3 * 11) 48 #define FMRI_BASE "svc:/system/idmap" 49 #define CONFIG_PG "config" 50 #define DEBUG_PG "debug" 51 #define RECONFIGURE 1 52 #define POKE_AUTO_DISCOVERY 2 53 54 /* 55 * Default cache timeouts. Can override via svccfg 56 * config/id_cache_timeout = count: seconds 57 * config/name_cache_timeout = count: seconds 58 */ 59 #define ID_CACHE_TMO_DEFAULT 86400 60 #define NAME_CACHE_TMO_DEFAULT 604800 61 62 enum event_type { 63 EVENT_NOTHING, /* Woke up for no good reason */ 64 EVENT_TIMEOUT, /* Timeout expired */ 65 EVENT_ROUTING, /* An interesting routing event happened */ 66 EVENT_DEGRADE, /* An error occurred in the mainline */ 67 EVENT_REFRESH, /* SMF refresh */ 68 }; 69 70 71 72 static pthread_t update_thread_handle = 0; 73 74 static int idmapd_ev_port = -1; 75 static int rt_sock = -1; 76 77 struct enum_lookup_map directory_mapping_map[] = { 78 { DIRECTORY_MAPPING_NONE, "none" }, 79 { DIRECTORY_MAPPING_NAME, "name" }, 80 { DIRECTORY_MAPPING_IDMU, "idmu" }, 81 { 0, NULL }, 82 }; 83 84 struct enum_lookup_map trust_dir_map[] = { 85 { 1, "they trust us" }, 86 { 2, "we trust them" }, 87 { 3, "we trust each other" }, 88 { 0, NULL }, 89 }; 90 91 static int 92 generate_machine_sid(char **machine_sid) 93 { 94 char *p; 95 uuid_t uu; 96 int i, j, len, rlen; 97 uint32_t rid; 98 99 /* 100 * Generate and split 128-bit UUID into three 32-bit RIDs The 101 * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's 102 * four RIDs altogether). 103 * 104 * Technically we could use up to 14 random RIDs here, but it 105 * turns out that with some versions of Windows using SIDs with 106 * more than five RIDs in security descriptors causes problems. 107 */ 108 109 *machine_sid = calloc(1, MACHINE_SID_LEN); 110 if (*machine_sid == NULL) { 111 idmapdlog(LOG_ERR, "Out of memory"); 112 return (-1); 113 } 114 (void) strcpy(*machine_sid, "S-1-5-21"); 115 p = *machine_sid + strlen("S-1-5-21"); 116 len = MACHINE_SID_LEN - strlen("S-1-5-21"); 117 118 uuid_clear(uu); 119 uuid_generate_random(uu); 120 121 #if UUID_LEN != 16 122 #error UUID size is not 16! 123 #endif 124 125 for (i = 0; i < 3; i++) { 126 j = i * 4; 127 rid = (uu[j] << 24) | (uu[j + 1] << 16) | 128 (uu[j + 2] << 8) | (uu[j + 3]); 129 rlen = snprintf(p, len, "-%u", rid); 130 p += rlen; 131 len -= rlen; 132 } 133 134 return (0); 135 } 136 137 138 /* In the case of error, exists is set to FALSE anyway */ 139 static int 140 prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists) 141 { 142 143 scf_property_t *scf_prop; 144 145 *exists = B_FALSE; 146 147 scf_prop = scf_property_create(handles->main); 148 if (scf_prop == NULL) { 149 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 150 scf_strerror(scf_error())); 151 return (-1); 152 } 153 154 if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0) 155 *exists = B_TRUE; 156 157 scf_property_destroy(scf_prop); 158 159 return (0); 160 } 161 162 static int 163 get_debug(idmap_cfg_handles_t *handles, const char *name) 164 { 165 int64_t i64 = 0; 166 167 scf_property_t *scf_prop; 168 scf_value_t *value; 169 170 scf_prop = scf_property_create(handles->main); 171 if (scf_prop == NULL) { 172 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 173 scf_strerror(scf_error())); 174 abort(); 175 } 176 value = scf_value_create(handles->main); 177 if (value == NULL) { 178 idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 179 scf_strerror(scf_error())); 180 abort(); 181 } 182 183 if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) { 184 /* this is OK: the property is just undefined */ 185 goto destruction; 186 } 187 188 189 if (scf_property_get_value(scf_prop, value) < 0) { 190 /* It is still OK when a property doesn't have any value */ 191 goto destruction; 192 } 193 194 if (scf_value_get_integer(value, &i64) != 0) { 195 idmapdlog(LOG_ERR, "Can not retrieve %s/%s: %s", 196 DEBUG_PG, name, scf_strerror(scf_error())); 197 abort(); 198 } 199 200 destruction: 201 scf_value_destroy(value); 202 scf_property_destroy(scf_prop); 203 204 return ((int)i64); 205 } 206 207 static int 208 get_val_bool(idmap_cfg_handles_t *handles, const char *name, 209 boolean_t *val, boolean_t default_val) 210 { 211 int rc = 0; 212 213 scf_property_t *scf_prop; 214 scf_value_t *value; 215 216 *val = default_val; 217 218 scf_prop = scf_property_create(handles->main); 219 if (scf_prop == NULL) { 220 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 221 scf_strerror(scf_error())); 222 return (-1); 223 } 224 value = scf_value_create(handles->main); 225 if (value == NULL) { 226 idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 227 scf_strerror(scf_error())); 228 scf_property_destroy(scf_prop); 229 return (-1); 230 } 231 232 /* It is OK if the property is undefined */ 233 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 234 goto destruction; 235 236 237 /* It is still OK when a property doesn't have any value */ 238 if (scf_property_get_value(scf_prop, value) < 0) 239 goto destruction; 240 241 uint8_t b; 242 rc = scf_value_get_boolean(value, &b); 243 244 if (rc == 0) 245 *val = (boolean_t)b; 246 247 destruction: 248 scf_value_destroy(value); 249 scf_property_destroy(scf_prop); 250 251 return (rc); 252 } 253 254 static int 255 get_val_int(idmap_cfg_handles_t *handles, const char *name, 256 void *val, scf_type_t type) 257 { 258 int rc = 0; 259 260 scf_property_t *scf_prop; 261 scf_value_t *value; 262 263 switch (type) { 264 case SCF_TYPE_COUNT: 265 *(uint64_t *)val = 0; 266 break; 267 case SCF_TYPE_INTEGER: 268 *(int64_t *)val = 0; 269 break; 270 default: 271 idmapdlog(LOG_ERR, "Invalid scf integer type (%d)", 272 type); 273 abort(); 274 } 275 276 scf_prop = scf_property_create(handles->main); 277 if (scf_prop == NULL) { 278 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 279 scf_strerror(scf_error())); 280 return (-1); 281 } 282 value = scf_value_create(handles->main); 283 if (value == NULL) { 284 idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 285 scf_strerror(scf_error())); 286 scf_property_destroy(scf_prop); 287 return (-1); 288 } 289 290 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 291 /* this is OK: the property is just undefined */ 292 goto destruction; 293 294 295 if (scf_property_get_value(scf_prop, value) < 0) 296 /* It is still OK when a property doesn't have any value */ 297 goto destruction; 298 299 switch (type) { 300 case SCF_TYPE_COUNT: 301 rc = scf_value_get_count(value, val); 302 break; 303 case SCF_TYPE_INTEGER: 304 rc = scf_value_get_integer(value, val); 305 break; 306 default: 307 abort(); /* tested above */ 308 /* NOTREACHED */ 309 } 310 311 if (rc != 0) { 312 idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 313 name, scf_strerror(scf_error())); 314 } 315 316 destruction: 317 scf_value_destroy(value); 318 scf_property_destroy(scf_prop); 319 320 return (rc); 321 } 322 323 static char * 324 scf_value2string(const char *name, scf_value_t *value) 325 { 326 static size_t max_val = 0; 327 328 if (max_val == 0) 329 max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 330 331 char buf[max_val + 1]; 332 if (scf_value_get_astring(value, buf, max_val + 1) < 0) { 333 idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 334 name, scf_strerror(scf_error())); 335 return (NULL); 336 } 337 338 char *s = strdup(buf); 339 if (s == NULL) 340 idmapdlog(LOG_ERR, "Out of memory"); 341 342 return (s); 343 } 344 345 static int 346 get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport, 347 idmap_ad_disc_ds_t **val) 348 { 349 idmap_ad_disc_ds_t *servers = NULL; 350 scf_property_t *scf_prop; 351 scf_value_t *value; 352 scf_iter_t *iter; 353 char *host, *portstr; 354 int len, i; 355 int count = 0; 356 int rc = -1; 357 358 *val = NULL; 359 360 restart: 361 scf_prop = scf_property_create(handles->main); 362 if (scf_prop == NULL) { 363 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 364 scf_strerror(scf_error())); 365 return (-1); 366 } 367 368 value = scf_value_create(handles->main); 369 if (value == NULL) { 370 idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 371 scf_strerror(scf_error())); 372 scf_property_destroy(scf_prop); 373 return (-1); 374 } 375 376 iter = scf_iter_create(handles->main); 377 if (iter == NULL) { 378 idmapdlog(LOG_ERR, "scf_iter_create() failed: %s", 379 scf_strerror(scf_error())); 380 scf_value_destroy(value); 381 scf_property_destroy(scf_prop); 382 return (-1); 383 } 384 385 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) { 386 /* this is OK: the property is just undefined */ 387 rc = 0; 388 goto destruction; 389 } 390 391 if (scf_iter_property_values(iter, scf_prop) < 0) { 392 idmapdlog(LOG_ERR, 393 "scf_iter_property_values(%s) failed: %s", 394 name, scf_strerror(scf_error())); 395 goto destruction; 396 } 397 398 /* Workaround scf bugs -- can't reset an iteration */ 399 if (count == 0) { 400 while (scf_iter_next_value(iter, value) > 0) 401 count++; 402 403 if (count == 0) { 404 /* no values */ 405 rc = 0; 406 goto destruction; 407 } 408 409 scf_value_destroy(value); 410 scf_iter_destroy(iter); 411 scf_property_destroy(scf_prop); 412 goto restart; 413 } 414 415 if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) { 416 idmapdlog(LOG_ERR, "Out of memory"); 417 goto destruction; 418 } 419 420 i = 0; 421 while (i < count && scf_iter_next_value(iter, value) > 0) { 422 servers[i].priority = 0; 423 servers[i].weight = 100; 424 servers[i].port = defport; 425 if ((host = scf_value2string(name, value)) == NULL) { 426 goto destruction; 427 } 428 if ((portstr = strchr(host, ':')) != NULL) { 429 *portstr++ = '\0'; 430 servers[i].port = strtol(portstr, 431 (char **)NULL, 10); 432 if (servers[i].port == 0) 433 servers[i].port = defport; 434 } 435 len = strlcpy(servers[i].host, host, 436 sizeof (servers->host)); 437 438 free(host); 439 440 /* Ignore this server if the hostname is too long */ 441 if (len < sizeof (servers->host)) 442 i++; 443 } 444 445 *val = servers; 446 447 rc = 0; 448 449 destruction: 450 scf_value_destroy(value); 451 scf_iter_destroy(iter); 452 scf_property_destroy(scf_prop); 453 454 if (rc < 0) { 455 if (servers) 456 free(servers); 457 *val = NULL; 458 } 459 460 return (rc); 461 } 462 463 464 static int 465 get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val) 466 { 467 int rc = 0; 468 469 scf_property_t *scf_prop; 470 scf_value_t *value; 471 472 scf_prop = scf_property_create(handles->main); 473 if (scf_prop == NULL) { 474 idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 475 scf_strerror(scf_error())); 476 return (-1); 477 } 478 value = scf_value_create(handles->main); 479 if (value == NULL) { 480 idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 481 scf_strerror(scf_error())); 482 scf_property_destroy(scf_prop); 483 return (-1); 484 } 485 486 *val = NULL; 487 488 if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 489 /* this is OK: the property is just undefined */ 490 goto destruction; 491 492 if (scf_property_get_value(scf_prop, value) < 0) { 493 idmapdlog(LOG_ERR, 494 "scf_property_get_value(%s) failed: %s", 495 name, scf_strerror(scf_error())); 496 rc = -1; 497 goto destruction; 498 } 499 500 *val = scf_value2string(name, value); 501 if (*val == NULL) 502 rc = -1; 503 504 destruction: 505 scf_value_destroy(value); 506 scf_property_destroy(scf_prop); 507 508 if (rc < 0) { 509 if (*val) 510 free(*val); 511 *val = NULL; 512 } 513 514 return (rc); 515 } 516 517 518 static int 519 del_val( 520 idmap_cfg_handles_t *handles, 521 scf_propertygroup_t *pg, 522 const char *name) 523 { 524 int rc = -1; 525 int ret; 526 scf_transaction_t *tx = NULL; 527 scf_transaction_entry_t *ent = NULL; 528 529 if ((tx = scf_transaction_create(handles->main)) == NULL) { 530 idmapdlog(LOG_ERR, 531 "scf_transaction_create() failed: %s", 532 scf_strerror(scf_error())); 533 goto destruction; 534 } 535 if ((ent = scf_entry_create(handles->main)) == NULL) { 536 idmapdlog(LOG_ERR, 537 "scf_entry_create() failed: %s", 538 scf_strerror(scf_error())); 539 goto destruction; 540 } 541 542 do { 543 if (scf_pg_update(pg) == -1) { 544 idmapdlog(LOG_ERR, 545 "scf_pg_update(%s) failed: %s", 546 name, scf_strerror(scf_error())); 547 goto destruction; 548 } 549 if (scf_transaction_start(tx, pg) != 0) { 550 idmapdlog(LOG_ERR, 551 "scf_transaction_start(%s) failed: %s", 552 name, scf_strerror(scf_error())); 553 goto destruction; 554 } 555 556 if (scf_transaction_property_delete(tx, ent, name) != 0) { 557 /* Don't complain if it already doesn't exist. */ 558 if (scf_error() != SCF_ERROR_NOT_FOUND) { 559 idmapdlog(LOG_ERR, 560 "scf_transaction_property_delete() failed:" 561 " %s", 562 scf_strerror(scf_error())); 563 } 564 goto destruction; 565 } 566 567 ret = scf_transaction_commit(tx); 568 569 if (ret == 0) 570 scf_transaction_reset(tx); 571 } while (ret == 0); 572 573 if (ret == -1) { 574 idmapdlog(LOG_ERR, 575 "scf_transaction_commit(%s) failed: %s", 576 name, scf_strerror(scf_error())); 577 goto destruction; 578 } 579 580 rc = 0; 581 582 destruction: 583 if (ent != NULL) 584 scf_entry_destroy(ent); 585 if (tx != NULL) 586 scf_transaction_destroy(tx); 587 return (rc); 588 } 589 590 591 static int 592 set_val( 593 idmap_cfg_handles_t *handles, 594 scf_propertygroup_t *pg, 595 const char *name, 596 scf_value_t *value) 597 { 598 int rc = -1; 599 int i; 600 scf_property_t *prop = NULL; 601 scf_transaction_t *tx = NULL; 602 scf_transaction_entry_t *ent = NULL; 603 604 if ((prop = scf_property_create(handles->main)) == NULL || 605 (tx = scf_transaction_create(handles->main)) == NULL || 606 (ent = scf_entry_create(handles->main)) == NULL) { 607 idmapdlog(LOG_ERR, "Unable to set property %s", 608 name, scf_strerror(scf_error())); 609 goto destruction; 610 } 611 612 for (i = 0; i < MAX_TRIES; i++) { 613 int ret; 614 615 if (scf_pg_update(pg) == -1) { 616 idmapdlog(LOG_ERR, 617 "scf_pg_update() failed: %s", 618 scf_strerror(scf_error())); 619 goto destruction; 620 } 621 622 if (scf_transaction_start(tx, pg) == -1) { 623 idmapdlog(LOG_ERR, 624 "scf_transaction_start(%s) failed: %s", 625 name, scf_strerror(scf_error())); 626 goto destruction; 627 } 628 629 ret = scf_pg_get_property(pg, name, prop); 630 if (ret == SCF_SUCCESS) { 631 if (scf_transaction_property_change_type(tx, ent, name, 632 scf_value_type(value)) < 0) { 633 idmapdlog(LOG_ERR, 634 "scf_transaction_property_change_type(%s)" 635 " failed: %s", 636 name, scf_strerror(scf_error())); 637 goto destruction; 638 } 639 } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 640 if (scf_transaction_property_new(tx, ent, name, 641 scf_value_type(value)) < 0) { 642 idmapdlog(LOG_ERR, 643 "scf_transaction_property_new() failed: %s", 644 scf_strerror(scf_error())); 645 goto destruction; 646 } 647 } else { 648 idmapdlog(LOG_ERR, 649 "scf_pg_get_property(%s) failed: %s", 650 name, scf_strerror(scf_error())); 651 goto destruction; 652 } 653 654 if (scf_entry_add_value(ent, value) == -1) { 655 idmapdlog(LOG_ERR, 656 "scf_entry_add_value() failed: %s", 657 scf_strerror(scf_error())); 658 goto destruction; 659 } 660 661 ret = scf_transaction_commit(tx); 662 if (ret == 0) { 663 /* 664 * Property group set in scf_transaction_start() 665 * is not the most recent. Update pg, reset tx and 666 * retry tx. 667 */ 668 idmapdlog(LOG_WARNING, 669 "scf_transaction_commit(%s) failed: %s", 670 name, scf_strerror(scf_error())); 671 scf_transaction_reset(tx); 672 continue; 673 } 674 if (ret != 1) { 675 idmapdlog(LOG_ERR, 676 "scf_transaction_commit(%s) failed: %s", 677 name, scf_strerror(scf_error())); 678 goto destruction; 679 } 680 /* Success! */ 681 rc = 0; 682 break; 683 } 684 685 destruction: 686 scf_entry_destroy(ent); 687 scf_transaction_destroy(tx); 688 scf_property_destroy(prop); 689 return (rc); 690 } 691 692 static int 693 set_val_integer( 694 idmap_cfg_handles_t *handles, 695 scf_propertygroup_t *pg, 696 const char *name, 697 int64_t val) 698 { 699 scf_value_t *value = NULL; 700 int rc; 701 702 if ((value = scf_value_create(handles->main)) == NULL) { 703 idmapdlog(LOG_ERR, "Unable to set property %s", 704 name, scf_strerror(scf_error())); 705 return (-1); 706 } 707 708 scf_value_set_integer(value, val); 709 710 rc = set_val(handles, pg, name, value); 711 712 scf_value_destroy(value); 713 714 return (rc); 715 } 716 717 718 static int 719 set_val_astring( 720 idmap_cfg_handles_t *handles, 721 scf_propertygroup_t *pg, 722 const char *name, 723 const char *val) 724 { 725 scf_value_t *value = NULL; 726 int rc = -1; 727 728 if ((value = scf_value_create(handles->main)) == NULL) { 729 idmapdlog(LOG_ERR, "Unable to set property %s", 730 name, scf_strerror(scf_error())); 731 goto out; 732 } 733 734 if (scf_value_set_astring(value, val) == -1) { 735 idmapdlog(LOG_ERR, 736 "scf_value_set_astring() failed: %s", 737 scf_strerror(scf_error())); 738 goto out; 739 } 740 741 rc = set_val(handles, pg, name, value); 742 743 out: 744 scf_value_destroy(value); 745 return (rc); 746 } 747 748 749 750 /* 751 * This function updates a boolean value. 752 * If nothing has changed it returns 0 else 1 753 */ 754 static int 755 update_bool(boolean_t *value, boolean_t *new, char *name) 756 { 757 if (*value == *new) 758 return (0); 759 760 if (DBG(CONFIG, 1)) { 761 idmapdlog(LOG_INFO, "change %s=%s", name, 762 *new ? "true" : "false"); 763 } 764 765 *value = *new; 766 return (1); 767 } 768 769 /* 770 * This function updates a uint64_t value. 771 * If nothing has changed it returns 0 else 1 772 */ 773 static int 774 update_uint64(uint64_t *value, uint64_t *new, char *name) 775 { 776 if (*value == *new) 777 return (0); 778 779 if (DBG(CONFIG, 1)) 780 idmapdlog(LOG_INFO, "change %s=%llu", name, *new); 781 782 *value = *new; 783 return (1); 784 } 785 786 /* 787 * This function updates a string value. 788 * If nothing has changed it returns 0 else 1 789 */ 790 static int 791 update_string(char **value, char **new, char *name) 792 { 793 int changed; 794 795 if (*new == NULL && *value != NULL) 796 changed = 1; 797 else if (*new != NULL && *value == NULL) 798 changed = 1; 799 else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0) 800 changed = 1; 801 else 802 changed = 0; 803 804 /* 805 * Note that even if unchanged we can't just return; we must free one 806 * of the values. 807 */ 808 809 if (DBG(CONFIG, 1) && changed) 810 idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new)); 811 812 free(*value); 813 *value = *new; 814 *new = NULL; 815 return (changed); 816 } 817 818 static int 819 update_enum(int *value, int *new, char *name, struct enum_lookup_map *map) 820 { 821 if (*value == *new) 822 return (0); 823 824 if (DBG(CONFIG, 1)) { 825 idmapdlog(LOG_INFO, "change %s=%s", name, 826 enum_lookup(*new, map)); 827 } 828 829 *value = *new; 830 831 return (1); 832 } 833 834 /* 835 * This function updates a directory service structure. 836 * If nothing has changed it returns 0 else 1 837 */ 838 static int 839 update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name) 840 { 841 int i; 842 843 if (*value == *new) 844 /* Nothing to do */ 845 return (0); 846 847 if (*value != NULL && *new != NULL && 848 ad_disc_compare_ds(*value, *new) == 0) { 849 free(*new); 850 *new = NULL; 851 return (0); 852 } 853 854 if (*value != NULL) 855 free(*value); 856 857 *value = *new; 858 *new = NULL; 859 860 if (*value == NULL) { 861 /* We're unsetting this DS property */ 862 if (DBG(CONFIG, 1)) 863 idmapdlog(LOG_INFO, "change %s=<none>", name); 864 return (1); 865 } 866 867 if (DBG(CONFIG, 1)) { 868 /* List all the new DSs */ 869 for (i = 0; (*value)[i].host[0] != '\0'; i++) { 870 idmapdlog(LOG_INFO, "change %s=%s port=%d", name, 871 (*value)[i].host, (*value)[i].port); 872 } 873 } 874 return (1); 875 } 876 877 /* 878 * This function updates a trusted domains structure. 879 * If nothing has changed it returns 0 else 1 880 */ 881 static int 882 update_trusted_domains(ad_disc_trusteddomains_t **value, 883 ad_disc_trusteddomains_t **new, char *name) 884 { 885 int i; 886 887 if (*value == *new) 888 /* Nothing to do */ 889 return (0); 890 891 if (*value != NULL && *new != NULL && 892 ad_disc_compare_trusteddomains(*value, *new) == 0) { 893 free(*new); 894 *new = NULL; 895 return (0); 896 } 897 898 if (*value != NULL) 899 free(*value); 900 901 *value = *new; 902 *new = NULL; 903 904 if (*value == NULL) { 905 /* We're unsetting this DS property */ 906 if (DBG(CONFIG, 1)) 907 idmapdlog(LOG_INFO, "change %s=<none>", name); 908 return (1); 909 } 910 911 if (DBG(CONFIG, 1)) { 912 /* List all the new domains */ 913 for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 914 idmapdlog(LOG_INFO, "change %s=%s direction=%s", name, 915 (*value)[i].domain, 916 enum_lookup((*value)[i].direction, trust_dir_map)); 917 } 918 } 919 return (1); 920 } 921 922 923 /* 924 * This function updates a domains in a forest structure. 925 * If nothing has changed it returns 0 else 1 926 */ 927 static int 928 update_domains_in_forest(ad_disc_domainsinforest_t **value, 929 ad_disc_domainsinforest_t **new, char *name) 930 { 931 int i; 932 933 if (*value == *new) 934 /* Nothing to do */ 935 return (0); 936 937 if (*value != NULL && *new != NULL && 938 ad_disc_compare_domainsinforest(*value, *new) == 0) { 939 free(*new); 940 *new = NULL; 941 return (0); 942 } 943 944 if (*value != NULL) 945 free(*value); 946 947 *value = *new; 948 *new = NULL; 949 950 if (*value == NULL) { 951 /* We're unsetting this DS property */ 952 if (DBG(CONFIG, 1)) 953 idmapdlog(LOG_INFO, "change %s=<none>", name); 954 return (1); 955 } 956 957 if (DBG(CONFIG, 1)) { 958 /* List all the new domains */ 959 for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 960 idmapdlog(LOG_INFO, "change %s=%s", name, 961 (*value)[i].domain); 962 } 963 } 964 return (1); 965 } 966 967 968 static void 969 free_trusted_forests(idmap_trustedforest_t **value, int *num_values) 970 { 971 int i; 972 973 for (i = 0; i < *num_values; i++) { 974 free((*value)[i].forest_name); 975 free((*value)[i].global_catalog); 976 free((*value)[i].domains_in_forest); 977 } 978 free(*value); 979 *value = NULL; 980 *num_values = 0; 981 } 982 983 984 static int 985 compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1, 986 ad_disc_domainsinforest_t *df2) 987 { 988 int i, j; 989 int num_df1 = 0; 990 int num_df2 = 0; 991 boolean_t match; 992 993 for (i = 0; df1[i].domain[0] != '\0'; i++) 994 if (df1[i].trusted) 995 num_df1++; 996 997 for (j = 0; df2[j].domain[0] != '\0'; j++) 998 if (df2[j].trusted) 999 num_df2++; 1000 1001 if (num_df1 != num_df2) 1002 return (1); 1003 1004 for (i = 0; df1[i].domain[0] != '\0'; i++) { 1005 if (df1[i].trusted) { 1006 match = B_FALSE; 1007 for (j = 0; df2[j].domain[0] != '\0'; j++) { 1008 if (df2[j].trusted && 1009 domain_eq(df1[i].domain, df2[j].domain) && 1010 strcmp(df1[i].sid, df2[j].sid) == 0) { 1011 match = B_TRUE; 1012 break; 1013 } 1014 } 1015 if (!match) 1016 return (1); 1017 } 1018 } 1019 return (0); 1020 } 1021 1022 1023 1024 /* 1025 * This function updates trusted forest structure. 1026 * If nothing has changed it returns 0 else 1 1027 */ 1028 static int 1029 update_trusted_forest(idmap_trustedforest_t **value, int *num_value, 1030 idmap_trustedforest_t **new, int *num_new, char *name) 1031 { 1032 int i, j; 1033 boolean_t match; 1034 1035 if (*value == *new) 1036 /* Nothing to do */ 1037 return (0); 1038 1039 if (*value != NULL && *new != NULL) { 1040 if (*num_value != *num_new) 1041 goto not_equal; 1042 for (i = 0; i < *num_value; i++) { 1043 match = B_FALSE; 1044 for (j = 0; j < *num_new; j++) { 1045 if (strcmp((*value)[i].forest_name, 1046 (*new)[j].forest_name) == 0 && 1047 ad_disc_compare_ds( 1048 (*value)[i].global_catalog, 1049 (*new)[j].global_catalog) == 0 && 1050 compare_trusteddomainsinforest( 1051 (*value)[i].domains_in_forest, 1052 (*new)[j].domains_in_forest) == 0) { 1053 match = B_TRUE; 1054 break; 1055 } 1056 } 1057 if (!match) 1058 goto not_equal; 1059 } 1060 free_trusted_forests(new, num_new); 1061 return (0); 1062 } 1063 not_equal: 1064 if (*value != NULL) 1065 free_trusted_forests(value, num_value); 1066 *value = *new; 1067 *num_value = *num_new; 1068 *new = NULL; 1069 *num_new = 0; 1070 1071 if (*value == NULL) { 1072 /* We're unsetting this DS property */ 1073 if (DBG(CONFIG, 1)) 1074 idmapdlog(LOG_INFO, "change %s=<none>", name); 1075 return (1); 1076 } 1077 1078 if (DBG(CONFIG, 1)) { 1079 /* List all the trusted forests */ 1080 for (i = 0; i < *num_value; i++) { 1081 idmap_trustedforest_t *f = &(*value)[i]; 1082 for (j = 0; 1083 f->domains_in_forest[j].domain[0] != '\0'; 1084 j++) { 1085 /* List trusted Domains in the forest. */ 1086 if (f->domains_in_forest[j].trusted) 1087 idmapdlog(LOG_INFO, 1088 "change %s=%s domain=%s", 1089 name, f->forest_name, 1090 f->domains_in_forest[j].domain); 1091 } 1092 /* List the hosts */ 1093 for (j = 0; 1094 f->global_catalog[j].host[0] != '\0'; 1095 j++) { 1096 idmapdlog(LOG_INFO, 1097 "change %s=%s host=%s port=%d", 1098 name, f->forest_name, 1099 f->global_catalog[j].host, 1100 f->global_catalog[j].port); 1101 } 1102 } 1103 } 1104 return (1); 1105 } 1106 1107 const char * 1108 enum_lookup(int value, struct enum_lookup_map *map) 1109 { 1110 for (; map->string != NULL; map++) { 1111 if (value == map->value) { 1112 return (map->string); 1113 } 1114 } 1115 return ("(invalid)"); 1116 } 1117 1118 /* 1119 * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the 1120 * interfaces. 1121 * 1122 * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON. 1123 */ 1124 static 1125 boolean_t 1126 pfroute_event_is_interesting(int rt_sock) 1127 { 1128 int nbytes; 1129 int64_t msg[2048 / 8]; 1130 struct rt_msghdr *rtm; 1131 boolean_t is_interesting = B_FALSE; 1132 1133 for (;;) { 1134 if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0) 1135 break; 1136 rtm = (struct rt_msghdr *)msg; 1137 if (rtm->rtm_version != RTM_VERSION) 1138 continue; 1139 if (nbytes < rtm->rtm_msglen) 1140 continue; 1141 switch (rtm->rtm_type) { 1142 case RTM_NEWADDR: 1143 case RTM_DELADDR: 1144 case RTM_IFINFO: 1145 is_interesting = B_TRUE; 1146 break; 1147 default: 1148 break; 1149 } 1150 } 1151 return (is_interesting); 1152 } 1153 1154 /* 1155 * Wait for an event, and report what kind of event occurred. 1156 * 1157 * Note that there are cases where we are awoken but don't care about 1158 * the lower-level event. We can't just loop here because we can't 1159 * readily calculate how long to sleep the next time. We return 1160 * EVENT_NOTHING and let the caller loop. 1161 */ 1162 static 1163 enum event_type 1164 wait_for_event(struct timespec *timeoutp) 1165 { 1166 port_event_t pe; 1167 1168 (void) memset(&pe, 0, sizeof (pe)); 1169 if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) { 1170 switch (errno) { 1171 case EINTR: 1172 return (EVENT_NOTHING); 1173 case ETIME: 1174 /* Timeout */ 1175 return (EVENT_TIMEOUT); 1176 default: 1177 /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */ 1178 idmapdlog(LOG_ERR, "Event port failed: %s", 1179 strerror(errno)); 1180 exit(1); 1181 /* NOTREACHED */ 1182 } 1183 } 1184 1185 1186 switch (pe.portev_source) { 1187 case 0: 1188 /* 1189 * This isn't documented, but seems to be what you get if 1190 * the timeout is zero seconds and there are no events 1191 * pending. 1192 */ 1193 return (EVENT_TIMEOUT); 1194 1195 case PORT_SOURCE_USER: 1196 if (pe.portev_events == POKE_AUTO_DISCOVERY) 1197 return (EVENT_DEGRADE); 1198 if (pe.portev_events == RECONFIGURE) 1199 return (EVENT_REFRESH); 1200 break; 1201 1202 case PORT_SOURCE_FD: 1203 if (pe.portev_object == rt_sock) { 1204 /* 1205 * PF_ROUTE socket read event: 1206 * re-associate fd 1207 * handle event 1208 */ 1209 if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 1210 rt_sock, POLLIN, NULL) != 0) { 1211 idmapdlog(LOG_ERR, "Failed to re-associate the " 1212 "routing socket with the event port: %s", 1213 strerror(errno)); 1214 abort(); 1215 } 1216 /* 1217 * The network configuration may still be in flux. 1218 * No matter, the resolver will re-transmit and 1219 * timeout if need be. 1220 */ 1221 if (pfroute_event_is_interesting(rt_sock)) { 1222 if (DBG(CONFIG, 1)) { 1223 idmapdlog(LOG_DEBUG, 1224 "Interesting routing event"); 1225 } 1226 return (EVENT_ROUTING); 1227 } else { 1228 if (DBG(CONFIG, 2)) { 1229 idmapdlog(LOG_DEBUG, 1230 "Boring routing event"); 1231 } 1232 return (EVENT_NOTHING); 1233 } 1234 } 1235 /* Event on an FD other than the routing FD? Ignore it. */ 1236 break; 1237 } 1238 1239 return (EVENT_NOTHING); 1240 } 1241 1242 void * 1243 idmap_cfg_update_thread(void *arg) 1244 { 1245 NOTE(ARGUNUSED(arg)) 1246 1247 const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx; 1248 1249 for (;;) { 1250 struct timespec timeout; 1251 struct timespec *timeoutp; 1252 int rc; 1253 int ttl; 1254 1255 (void) ad_disc_SubnetChanged(ad_ctx); 1256 1257 rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER); 1258 if (rc < -1) { 1259 idmapdlog(LOG_ERR, "Fatal errors while reading " 1260 "SMF properties"); 1261 exit(1); 1262 } else if (rc == -1) { 1263 idmapdlog(LOG_WARNING, 1264 "Errors re-loading configuration may cause AD " 1265 "lookups to fail"); 1266 } 1267 1268 /* 1269 * Wait for an interesting event. Note that we might get 1270 * boring events between interesting events. If so, we loop. 1271 */ 1272 for (;;) { 1273 ttl = ad_disc_get_TTL(ad_ctx); 1274 1275 if (ttl < 0) { 1276 timeoutp = NULL; 1277 } else { 1278 timeoutp = &timeout; 1279 timeout.tv_sec = ttl; 1280 timeout.tv_nsec = 0; 1281 } 1282 1283 switch (wait_for_event(timeoutp)) { 1284 case EVENT_NOTHING: 1285 if (DBG(CONFIG, 2)) 1286 idmapdlog(LOG_DEBUG, "Boring event."); 1287 continue; 1288 case EVENT_REFRESH: 1289 if (DBG(CONFIG, 1)) 1290 idmapdlog(LOG_INFO, "SMF refresh"); 1291 /* 1292 * Blow away the ccache, we might have 1293 * re-joined the domain or joined a new one 1294 */ 1295 (void) unlink(IDMAP_CACHEDIR "/ccache"); 1296 break; 1297 case EVENT_DEGRADE: 1298 if (DBG(CONFIG, 1)) { 1299 idmapdlog(LOG_DEBUG, 1300 "Service degraded"); 1301 } 1302 break; 1303 case EVENT_TIMEOUT: 1304 if (DBG(CONFIG, 1)) 1305 idmapdlog(LOG_DEBUG, "TTL expired"); 1306 break; 1307 case EVENT_ROUTING: 1308 /* Already logged to DEBUG */ 1309 break; 1310 } 1311 /* An interesting event! */ 1312 break; 1313 } 1314 } 1315 /* 1316 * Lint isn't happy with the concept of a function declared to 1317 * return something, that doesn't return. Of course, merely adding 1318 * the return isn't enough, because it's never reached... 1319 */ 1320 /*NOTREACHED*/ 1321 return (NULL); 1322 } 1323 1324 int 1325 idmap_cfg_start_updates(void) 1326 { 1327 if ((idmapd_ev_port = port_create()) < 0) { 1328 idmapdlog(LOG_ERR, "Failed to create event port: %s", 1329 strerror(errno)); 1330 return (-1); 1331 } 1332 1333 if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 1334 idmapdlog(LOG_ERR, "Failed to open routing socket: %s", 1335 strerror(errno)); 1336 (void) close(idmapd_ev_port); 1337 return (-1); 1338 } 1339 1340 if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) { 1341 idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s", 1342 strerror(errno)); 1343 (void) close(rt_sock); 1344 (void) close(idmapd_ev_port); 1345 return (-1); 1346 } 1347 1348 if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 1349 rt_sock, POLLIN, NULL) != 0) { 1350 idmapdlog(LOG_ERR, "Failed to associate the routing " 1351 "socket with the event port: %s", strerror(errno)); 1352 (void) close(rt_sock); 1353 (void) close(idmapd_ev_port); 1354 return (-1); 1355 } 1356 1357 if ((errno = pthread_create(&update_thread_handle, NULL, 1358 idmap_cfg_update_thread, NULL)) != 0) { 1359 idmapdlog(LOG_ERR, "Failed to start update thread: %s", 1360 strerror(errno)); 1361 (void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock); 1362 (void) close(rt_sock); 1363 (void) close(idmapd_ev_port); 1364 return (-1); 1365 } 1366 1367 return (0); 1368 } 1369 1370 /* 1371 * Reject attribute names with invalid characters. 1372 */ 1373 static 1374 int 1375 valid_ldap_attr(const char *attr) { 1376 for (; *attr; attr++) { 1377 if (!isalnum(*attr) && *attr != '-' && 1378 *attr != '_' && *attr != '.' && *attr != ';') 1379 return (0); 1380 } 1381 return (1); 1382 } 1383 1384 static 1385 void 1386 idmapd_set_debug( 1387 idmap_cfg_handles_t *handles, 1388 enum idmapd_debug item, 1389 const char *name) 1390 { 1391 int val; 1392 1393 if (item < 0 || item > IDMAPD_DEBUG_MAX) 1394 return; 1395 1396 val = get_debug(handles, name); 1397 1398 if (val != _idmapdstate.debug[item]) 1399 idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val); 1400 1401 _idmapdstate.debug[item] = val; 1402 } 1403 1404 static 1405 void 1406 check_smf_debug_mode(idmap_cfg_handles_t *handles) 1407 { 1408 idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all"); 1409 idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config"); 1410 idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping"); 1411 idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery"); 1412 idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns"); 1413 idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap"); 1414 1415 adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]); 1416 adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]); 1417 adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]); 1418 adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]); 1419 } 1420 1421 /* 1422 * This is the half of idmap_cfg_load() that loads property values from 1423 * SMF (using the config/ property group of the idmap FMRI). 1424 * 1425 * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1426 * -3 -> hard smf config failures 1427 * reading from SMF. 1428 */ 1429 static 1430 int 1431 idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, 1432 int * const errors) 1433 { 1434 int rc; 1435 char *s; 1436 1437 *errors = 0; 1438 1439 if (scf_pg_update(handles->config_pg) < 0) { 1440 idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 1441 scf_strerror(scf_error())); 1442 return (-2); 1443 } 1444 1445 if (scf_pg_update(handles->debug_pg) < 0) { 1446 idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 1447 scf_strerror(scf_error())); 1448 return (-2); 1449 } 1450 1451 check_smf_debug_mode(handles); 1452 1453 rc = get_val_bool(handles, "unresolvable_sid_mapping", 1454 &pgcfg->eph_map_unres_sids, B_TRUE); 1455 if (rc != 0) 1456 (*errors)++; 1457 1458 rc = get_val_bool(handles, "use_ads", 1459 &pgcfg->use_ads, B_TRUE); 1460 if (rc != 0) 1461 (*errors)++; 1462 1463 rc = get_val_bool(handles, "use_lsa", 1464 &pgcfg->use_lsa, B_TRUE); 1465 if (rc != 0) 1466 (*errors)++; 1467 1468 rc = get_val_bool(handles, "disable_cross_forest_trusts", 1469 &pgcfg->disable_cross_forest_trusts, B_TRUE); 1470 if (rc != 0) 1471 (*errors)++; 1472 1473 rc = get_val_astring(handles, "directory_based_mapping", &s); 1474 if (rc != 0) 1475 (*errors)++; 1476 else if (s == NULL || strcasecmp(s, "none") == 0) 1477 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1478 else if (strcasecmp(s, "name") == 0) 1479 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME; 1480 else if (strcasecmp(s, "idmu") == 0) 1481 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU; 1482 else { 1483 pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1484 idmapdlog(LOG_ERR, 1485 "config/directory_based_mapping: invalid value \"%s\" ignored", 1486 s); 1487 (*errors)++; 1488 } 1489 free(s); 1490 1491 rc = get_val_int(handles, "list_size_limit", 1492 &pgcfg->list_size_limit, SCF_TYPE_COUNT); 1493 if (rc != 0) 1494 (*errors)++; 1495 1496 rc = get_val_int(handles, "id_cache_timeout", 1497 &pgcfg->id_cache_timeout, SCF_TYPE_COUNT); 1498 if (rc != 0) 1499 (*errors)++; 1500 if (pgcfg->id_cache_timeout == 0) 1501 pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT; 1502 1503 rc = get_val_int(handles, "name_cache_timeout", 1504 &pgcfg->name_cache_timeout, SCF_TYPE_COUNT); 1505 if (rc != 0) 1506 (*errors)++; 1507 if (pgcfg->name_cache_timeout == 0) 1508 pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT; 1509 1510 rc = get_val_astring(handles, "domain_name", 1511 &pgcfg->domain_name); 1512 if (rc != 0) 1513 (*errors)++; 1514 else { 1515 if (pgcfg->domain_name != NULL && 1516 pgcfg->domain_name[0] == '\0') { 1517 free(pgcfg->domain_name); 1518 pgcfg->domain_name = NULL; 1519 } 1520 (void) ad_disc_set_DomainName(handles->ad_ctx, 1521 pgcfg->domain_name); 1522 pgcfg->domain_name_auto_disc = B_FALSE; 1523 } 1524 1525 rc = get_val_astring(handles, "default_domain", 1526 &pgcfg->default_domain); 1527 if (rc != 0) { 1528 /* 1529 * SCF failures fetching config/default_domain we treat 1530 * as fatal as they may leave ID mapping rules that 1531 * match unqualified winnames flapping in the wind. 1532 */ 1533 return (-2); 1534 } 1535 1536 if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) { 1537 pgcfg->default_domain = strdup(pgcfg->domain_name); 1538 } 1539 1540 rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); 1541 if (rc != 0) 1542 (*errors)++; 1543 if (pgcfg->machine_sid == NULL) { 1544 /* If machine_sid not configured, generate one */ 1545 if (generate_machine_sid(&pgcfg->machine_sid) < 0) 1546 return (-2); 1547 rc = set_val_astring(handles, handles->config_pg, 1548 "machine_sid", pgcfg->machine_sid); 1549 if (rc != 0) 1550 (*errors)++; 1551 } 1552 1553 rc = get_val_ds(handles, "domain_controller", 389, 1554 &pgcfg->domain_controller); 1555 if (rc != 0) 1556 (*errors)++; 1557 else { 1558 (void) ad_disc_set_DomainController(handles->ad_ctx, 1559 pgcfg->domain_controller); 1560 pgcfg->domain_controller_auto_disc = B_FALSE; 1561 } 1562 1563 rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); 1564 if (rc != 0) 1565 (*errors)++; 1566 else { 1567 (void) ad_disc_set_ForestName(handles->ad_ctx, 1568 pgcfg->forest_name); 1569 pgcfg->forest_name_auto_disc = B_FALSE; 1570 } 1571 1572 rc = get_val_astring(handles, "site_name", &pgcfg->site_name); 1573 if (rc != 0) 1574 (*errors)++; 1575 else 1576 (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name); 1577 1578 rc = get_val_ds(handles, "global_catalog", 3268, 1579 &pgcfg->global_catalog); 1580 if (rc != 0) 1581 (*errors)++; 1582 else { 1583 (void) ad_disc_set_GlobalCatalog(handles->ad_ctx, 1584 pgcfg->global_catalog); 1585 pgcfg->global_catalog_auto_disc = B_FALSE; 1586 } 1587 1588 /* Unless we're doing directory-based name mapping, we're done. */ 1589 if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME) 1590 return (0); 1591 1592 rc = get_val_astring(handles, "ad_unixuser_attr", 1593 &pgcfg->ad_unixuser_attr); 1594 if (rc != 0) 1595 return (-2); 1596 if (pgcfg->ad_unixuser_attr != NULL && 1597 !valid_ldap_attr(pgcfg->ad_unixuser_attr)) { 1598 idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a " 1599 "valid LDAP attribute name", pgcfg->ad_unixuser_attr); 1600 return (-3); 1601 } 1602 1603 rc = get_val_astring(handles, "ad_unixgroup_attr", 1604 &pgcfg->ad_unixgroup_attr); 1605 if (rc != 0) 1606 return (-2); 1607 if (pgcfg->ad_unixgroup_attr != NULL && 1608 !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) { 1609 idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a " 1610 "valid LDAP attribute name", pgcfg->ad_unixgroup_attr); 1611 return (-3); 1612 } 1613 1614 rc = get_val_astring(handles, "nldap_winname_attr", 1615 &pgcfg->nldap_winname_attr); 1616 if (rc != 0) 1617 return (-2); 1618 if (pgcfg->nldap_winname_attr != NULL && 1619 !valid_ldap_attr(pgcfg->nldap_winname_attr)) { 1620 idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a " 1621 "valid LDAP attribute name", pgcfg->nldap_winname_attr); 1622 return (-3); 1623 } 1624 if (pgcfg->ad_unixuser_attr == NULL && 1625 pgcfg->ad_unixgroup_attr == NULL && 1626 pgcfg->nldap_winname_attr == NULL) { 1627 idmapdlog(LOG_ERR, 1628 "If config/directory_based_mapping property is set to " 1629 "\"name\" then at least one of the following name mapping " 1630 "attributes must be specified. (config/ad_unixuser_attr OR " 1631 "config/ad_unixgroup_attr OR config/nldap_winname_attr)"); 1632 return (-3); 1633 } 1634 1635 return (rc); 1636 1637 } 1638 1639 static 1640 void 1641 log_if_unable(const void *val, const char *what) 1642 { 1643 if (val == NULL) { 1644 idmapdlog(LOG_DEBUG, "unable to discover %s", what); 1645 } 1646 } 1647 1648 static 1649 void 1650 discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx) 1651 { 1652 ad_disc_t trusted_ctx; 1653 int i, j, k, l; 1654 char *forestname; 1655 int num_trusteddomains; 1656 boolean_t new_forest; 1657 char *trusteddomain; 1658 idmap_ad_disc_ds_t *globalcatalog; 1659 idmap_trustedforest_t *trustedforests; 1660 ad_disc_domainsinforest_t *domainsinforest; 1661 1662 pgcfg->trusted_domains = 1663 ad_disc_get_TrustedDomains(ad_ctx, NULL); 1664 1665 if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL && 1666 pgcfg->trusted_domains[0].domain[0] != '\0') { 1667 /* 1668 * We have trusted domains. We need to go through every 1669 * one and find its forest. If it is a new forest we then need 1670 * to find its Global Catalog and the domains in the forest 1671 */ 1672 for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) 1673 continue; 1674 num_trusteddomains = i; 1675 1676 trustedforests = calloc(num_trusteddomains, 1677 sizeof (idmap_trustedforest_t)); 1678 j = 0; 1679 for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) { 1680 trusteddomain = pgcfg->trusted_domains[i].domain; 1681 trusted_ctx = ad_disc_init(); 1682 (void) ad_disc_set_DomainName(trusted_ctx, 1683 trusteddomain); 1684 forestname = 1685 ad_disc_get_ForestName(trusted_ctx, NULL); 1686 if (forestname == NULL) { 1687 if (DBG(CONFIG, 1)) { 1688 idmapdlog(LOG_DEBUG, 1689 "unable to discover Forest Name" 1690 " for the trusted domain %s", 1691 trusteddomain); 1692 } 1693 ad_disc_fini(trusted_ctx); 1694 continue; 1695 } 1696 1697 if (strcasecmp(forestname, pgcfg->forest_name) == 0) { 1698 /* 1699 * Ignore the domain as it is part of 1700 * the primary forest 1701 */ 1702 free(forestname); 1703 ad_disc_fini(trusted_ctx); 1704 continue; 1705 } 1706 1707 /* Is this a new forest? */ 1708 new_forest = B_TRUE; 1709 for (k = 0; k < j; k++) { 1710 if (strcasecmp(forestname, 1711 trustedforests[k].forest_name) == 0) { 1712 new_forest = B_FALSE; 1713 domainsinforest = 1714 trustedforests[k].domains_in_forest; 1715 break; 1716 } 1717 } 1718 if (!new_forest) { 1719 /* Mark the domain as trusted */ 1720 for (l = 0; 1721 domainsinforest[l].domain[0] != '\0'; l++) { 1722 if (domain_eq(trusteddomain, 1723 domainsinforest[l].domain)) { 1724 domainsinforest[l].trusted = 1725 TRUE; 1726 break; 1727 } 1728 } 1729 free(forestname); 1730 ad_disc_fini(trusted_ctx); 1731 continue; 1732 } 1733 1734 /* 1735 * Get the Global Catalog and the domains in 1736 * this new forest. 1737 */ 1738 globalcatalog = 1739 ad_disc_get_GlobalCatalog(trusted_ctx, 1740 AD_DISC_PREFER_SITE, NULL); 1741 if (globalcatalog == NULL) { 1742 if (DBG(CONFIG, 1)) { 1743 idmapdlog(LOG_DEBUG, 1744 "unable to discover Global Catalog" 1745 " for the trusted domain %s", 1746 trusteddomain); 1747 } 1748 free(forestname); 1749 ad_disc_fini(trusted_ctx); 1750 continue; 1751 } 1752 domainsinforest = 1753 ad_disc_get_DomainsInForest(trusted_ctx, 1754 NULL); 1755 if (domainsinforest == NULL) { 1756 if (DBG(CONFIG, 1)) { 1757 idmapdlog(LOG_DEBUG, 1758 "unable to discover Domains in the" 1759 " Forest for the trusted domain %s", 1760 trusteddomain); 1761 } 1762 free(globalcatalog); 1763 free(forestname); 1764 ad_disc_fini(trusted_ctx); 1765 continue; 1766 } 1767 1768 trustedforests[j].forest_name = forestname; 1769 trustedforests[j].global_catalog = globalcatalog; 1770 trustedforests[j].domains_in_forest = domainsinforest; 1771 j++; 1772 /* Mark the domain as trusted */ 1773 for (l = 0; domainsinforest[l].domain[0] != '\0'; 1774 l++) { 1775 if (domain_eq(trusteddomain, 1776 domainsinforest[l].domain)) { 1777 domainsinforest[l].trusted = TRUE; 1778 break; 1779 } 1780 } 1781 ad_disc_fini(trusted_ctx); 1782 } 1783 if (j > 0) { 1784 pgcfg->num_trusted_forests = j; 1785 pgcfg->trusted_forests = trustedforests; 1786 } else { 1787 free(trustedforests); 1788 } 1789 } 1790 } 1791 1792 /* 1793 * This is the half of idmap_cfg_load() that auto-discovers values of 1794 * discoverable properties that weren't already set via SMF properties. 1795 * 1796 * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it 1797 * needs to be careful not to overwrite any properties set in SMF. 1798 */ 1799 static 1800 void 1801 idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 1802 { 1803 ad_disc_t ad_ctx = handles->ad_ctx; 1804 1805 if (pgcfg->use_ads == B_FALSE) { 1806 if (DBG(CONFIG, 1)) 1807 idmapdlog(LOG_DEBUG, "ADS disabled."); 1808 return; 1809 } 1810 1811 if (DBG(CONFIG, 1)) 1812 idmapdlog(LOG_DEBUG, "Running discovery."); 1813 1814 ad_disc_refresh(ad_ctx); 1815 1816 if (pgcfg->domain_name == NULL) { 1817 idmapdlog(LOG_DEBUG, "No domain name specified."); 1818 } else { 1819 if (pgcfg->domain_controller == NULL) 1820 pgcfg->domain_controller = 1821 ad_disc_get_DomainController(ad_ctx, 1822 AD_DISC_PREFER_SITE, 1823 &pgcfg->domain_controller_auto_disc); 1824 1825 if (pgcfg->forest_name == NULL) 1826 pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx, 1827 &pgcfg->forest_name_auto_disc); 1828 1829 if (pgcfg->site_name == NULL) 1830 pgcfg->site_name = ad_disc_get_SiteName(ad_ctx, 1831 &pgcfg->site_name_auto_disc); 1832 1833 if (pgcfg->global_catalog == NULL) 1834 pgcfg->global_catalog = 1835 ad_disc_get_GlobalCatalog(ad_ctx, 1836 AD_DISC_PREFER_SITE, 1837 &pgcfg->global_catalog_auto_disc); 1838 1839 pgcfg->domains_in_forest = 1840 ad_disc_get_DomainsInForest(ad_ctx, NULL); 1841 1842 if (!pgcfg->disable_cross_forest_trusts) 1843 discover_trusted_domains(pgcfg, ad_ctx); 1844 1845 if (DBG(CONFIG, 1)) { 1846 log_if_unable(pgcfg->domain_name, "Domain Name"); 1847 log_if_unable(pgcfg->domain_controller, 1848 "Domain Controller"); 1849 log_if_unable(pgcfg->forest_name, "Forest Name"); 1850 log_if_unable(pgcfg->site_name, "Site Name"); 1851 log_if_unable(pgcfg->global_catalog, "Global Catalog"); 1852 log_if_unable(pgcfg->domains_in_forest, 1853 "Domains in the Forest"); 1854 if (!pgcfg->disable_cross_forest_trusts) { 1855 log_if_unable(pgcfg->trusted_domains, 1856 "Trusted Domains"); 1857 } 1858 } 1859 } 1860 1861 ad_disc_done(ad_ctx); 1862 1863 if (DBG(CONFIG, 1)) 1864 idmapdlog(LOG_DEBUG, "Discovery done."); 1865 } 1866 1867 1868 /* 1869 * idmap_cfg_load() is called at startup, and periodically via the 1870 * update thread when the auto-discovery TTLs expire, as well as part of 1871 * the refresh method, to update the current configuration. It always 1872 * reads from SMF, but you still have to refresh the service after 1873 * changing the config pg in order for the changes to take effect. 1874 * 1875 * There is one flag: 1876 * 1877 * - CFG_DISCOVER 1878 * 1879 * If CFG_DISCOVER is set then idmap_cfg_load() calls 1880 * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property 1881 * values that weren't set in SMF. 1882 * 1883 * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration 1884 * changed. 1885 * 1886 * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1887 * reading from SMF. 1888 */ 1889 int 1890 idmap_cfg_load(idmap_cfg_t *cfg, int flags) 1891 { 1892 int rc = 0; 1893 int errors; 1894 int changed = 0; 1895 int ad_reload_required = 0; 1896 idmap_pg_config_t new_pgcfg, *live_pgcfg; 1897 1898 if (DBG(CONFIG, 1)) 1899 idmapdlog(LOG_DEBUG, "Loading configuration."); 1900 1901 live_pgcfg = &cfg->pgcfg; 1902 (void) memset(&new_pgcfg, 0, sizeof (new_pgcfg)); 1903 1904 (void) pthread_mutex_lock(&cfg->handles.mutex); 1905 1906 if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1) 1907 goto err; 1908 1909 if (flags & CFG_DISCOVER) 1910 idmap_cfg_discover(&cfg->handles, &new_pgcfg); 1911 1912 WRLOCK_CONFIG(); 1913 /* Non-discoverable props updated here */ 1914 1915 changed += update_uint64(&live_pgcfg->list_size_limit, 1916 &new_pgcfg.list_size_limit, "list_size_limit"); 1917 1918 changed += update_uint64(&live_pgcfg->id_cache_timeout, 1919 &new_pgcfg.id_cache_timeout, "id_cache_timeout"); 1920 1921 changed += update_uint64(&live_pgcfg->name_cache_timeout, 1922 &new_pgcfg.name_cache_timeout, "name_cache_timeout"); 1923 1924 changed += update_string(&live_pgcfg->machine_sid, 1925 &new_pgcfg.machine_sid, "machine_sid"); 1926 1927 changed += update_bool(&live_pgcfg->eph_map_unres_sids, 1928 &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); 1929 1930 changed += update_bool(&live_pgcfg->use_ads, 1931 &new_pgcfg.use_ads, "use_ads"); 1932 1933 changed += update_bool(&live_pgcfg->use_lsa, 1934 &new_pgcfg.use_lsa, "use_lsa"); 1935 1936 changed += update_bool(&live_pgcfg->disable_cross_forest_trusts, 1937 &new_pgcfg.disable_cross_forest_trusts, 1938 "disable_cross_forest_trusts"); 1939 1940 changed += update_enum(&live_pgcfg->directory_based_mapping, 1941 &new_pgcfg.directory_based_mapping, "directory_based_mapping", 1942 directory_mapping_map); 1943 1944 changed += update_string(&live_pgcfg->ad_unixuser_attr, 1945 &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr"); 1946 1947 changed += update_string(&live_pgcfg->ad_unixgroup_attr, 1948 &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr"); 1949 1950 changed += update_string(&live_pgcfg->nldap_winname_attr, 1951 &new_pgcfg.nldap_winname_attr, "nldap_winname_attr"); 1952 1953 /* Props that can be discovered and set in SMF updated here */ 1954 changed += update_string(&live_pgcfg->default_domain, 1955 &new_pgcfg.default_domain, "default_domain"); 1956 1957 changed += update_string(&live_pgcfg->domain_name, 1958 &new_pgcfg.domain_name, "domain_name"); 1959 live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc; 1960 1961 changed += update_dirs(&live_pgcfg->domain_controller, 1962 &new_pgcfg.domain_controller, "domain_controller"); 1963 live_pgcfg->domain_controller_auto_disc = 1964 new_pgcfg.domain_controller_auto_disc; 1965 1966 changed += update_string(&live_pgcfg->forest_name, 1967 &new_pgcfg.forest_name, "forest_name"); 1968 live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc; 1969 1970 changed += update_string(&live_pgcfg->site_name, 1971 &new_pgcfg.site_name, "site_name"); 1972 live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc; 1973 1974 if (update_dirs(&live_pgcfg->global_catalog, 1975 &new_pgcfg.global_catalog, "global_catalog")) { 1976 changed++; 1977 if (live_pgcfg->global_catalog != NULL && 1978 live_pgcfg->global_catalog[0].host[0] != '\0') 1979 ad_reload_required = TRUE; 1980 } 1981 live_pgcfg->global_catalog_auto_disc = 1982 new_pgcfg.global_catalog_auto_disc; 1983 1984 if (update_domains_in_forest(&live_pgcfg->domains_in_forest, 1985 &new_pgcfg.domains_in_forest, "domains_in_forest")) { 1986 changed++; 1987 ad_reload_required = TRUE; 1988 } 1989 1990 if (update_trusted_domains(&live_pgcfg->trusted_domains, 1991 &new_pgcfg.trusted_domains, "trusted_domains")) { 1992 changed++; 1993 if (live_pgcfg->trusted_domains != NULL && 1994 live_pgcfg->trusted_domains[0].domain[0] != '\0') 1995 ad_reload_required = TRUE; 1996 } 1997 1998 if (update_trusted_forest(&live_pgcfg->trusted_forests, 1999 &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests, 2000 &new_pgcfg.num_trusted_forests, "trusted_forest")) { 2001 changed++; 2002 if (live_pgcfg->trusted_forests != NULL) 2003 ad_reload_required = TRUE; 2004 } 2005 2006 if (ad_reload_required) 2007 reload_ad(); 2008 2009 idmap_cfg_unload(&new_pgcfg); 2010 2011 if (DBG(CONFIG, 1)) { 2012 if (changed) 2013 idmapdlog(LOG_NOTICE, "Configuration changed"); 2014 else 2015 idmapdlog(LOG_NOTICE, "Configuration unchanged"); 2016 } 2017 2018 UNLOCK_CONFIG(); 2019 2020 err: 2021 (void) pthread_mutex_unlock(&cfg->handles.mutex); 2022 2023 if (rc < -1) 2024 return (rc); 2025 2026 return ((errors == 0) ? 0 : -1); 2027 } 2028 2029 /* 2030 * Initialize 'cfg'. 2031 */ 2032 idmap_cfg_t * 2033 idmap_cfg_init() 2034 { 2035 idmap_cfg_handles_t *handles; 2036 2037 /* First the smf repository handles: */ 2038 idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t)); 2039 if (!cfg) { 2040 idmapdlog(LOG_ERR, "Out of memory"); 2041 return (NULL); 2042 } 2043 handles = &cfg->handles; 2044 2045 (void) pthread_mutex_init(&handles->mutex, NULL); 2046 2047 if (!(handles->main = scf_handle_create(SCF_VERSION))) { 2048 idmapdlog(LOG_ERR, "scf_handle_create() failed: %s", 2049 scf_strerror(scf_error())); 2050 goto error; 2051 } 2052 2053 if (scf_handle_bind(handles->main) < 0) { 2054 idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s", 2055 scf_strerror(scf_error())); 2056 goto error; 2057 } 2058 2059 if (!(handles->service = scf_service_create(handles->main)) || 2060 !(handles->instance = scf_instance_create(handles->main)) || 2061 !(handles->config_pg = scf_pg_create(handles->main)) || 2062 !(handles->debug_pg = scf_pg_create(handles->main))) { 2063 idmapdlog(LOG_ERR, "scf handle creation failed: %s", 2064 scf_strerror(scf_error())); 2065 goto error; 2066 } 2067 2068 if (scf_handle_decode_fmri(handles->main, 2069 FMRI_BASE "/:properties/" CONFIG_PG, 2070 NULL, /* scope */ 2071 handles->service, /* service */ 2072 handles->instance, /* instance */ 2073 handles->config_pg, /* pg */ 2074 NULL, /* prop */ 2075 SCF_DECODE_FMRI_EXACT) < 0) { 2076 idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s", 2077 scf_strerror(scf_error())); 2078 goto error; 2079 } 2080 2081 if (scf_service_get_pg(handles->service, 2082 DEBUG_PG, handles->debug_pg) < 0) { 2083 idmapdlog(LOG_ERR, "Property group \"%s\": %s", 2084 DEBUG_PG, scf_strerror(scf_error())); 2085 goto error; 2086 } 2087 2088 check_smf_debug_mode(handles); 2089 2090 /* Initialize AD Auto Discovery context */ 2091 handles->ad_ctx = ad_disc_init(); 2092 if (handles->ad_ctx == NULL) 2093 goto error; 2094 2095 return (cfg); 2096 2097 error: 2098 (void) idmap_cfg_fini(cfg); 2099 return (NULL); 2100 } 2101 2102 void 2103 idmap_cfg_unload(idmap_pg_config_t *pgcfg) 2104 { 2105 2106 if (pgcfg->default_domain) { 2107 free(pgcfg->default_domain); 2108 pgcfg->default_domain = NULL; 2109 } 2110 if (pgcfg->domain_name) { 2111 free(pgcfg->domain_name); 2112 pgcfg->domain_name = NULL; 2113 } 2114 if (pgcfg->machine_sid) { 2115 free(pgcfg->machine_sid); 2116 pgcfg->machine_sid = NULL; 2117 } 2118 if (pgcfg->domain_controller) { 2119 free(pgcfg->domain_controller); 2120 pgcfg->domain_controller = NULL; 2121 } 2122 if (pgcfg->forest_name) { 2123 free(pgcfg->forest_name); 2124 pgcfg->forest_name = NULL; 2125 } 2126 if (pgcfg->site_name) { 2127 free(pgcfg->site_name); 2128 pgcfg->site_name = NULL; 2129 } 2130 if (pgcfg->global_catalog) { 2131 free(pgcfg->global_catalog); 2132 pgcfg->global_catalog = NULL; 2133 } 2134 if (pgcfg->trusted_domains) { 2135 free(pgcfg->trusted_domains); 2136 pgcfg->trusted_domains = NULL; 2137 } 2138 if (pgcfg->trusted_forests) 2139 free_trusted_forests(&pgcfg->trusted_forests, 2140 &pgcfg->num_trusted_forests); 2141 2142 if (pgcfg->ad_unixuser_attr) { 2143 free(pgcfg->ad_unixuser_attr); 2144 pgcfg->ad_unixuser_attr = NULL; 2145 } 2146 if (pgcfg->ad_unixgroup_attr) { 2147 free(pgcfg->ad_unixgroup_attr); 2148 pgcfg->ad_unixgroup_attr = NULL; 2149 } 2150 if (pgcfg->nldap_winname_attr) { 2151 free(pgcfg->nldap_winname_attr); 2152 pgcfg->nldap_winname_attr = NULL; 2153 } 2154 } 2155 2156 int 2157 idmap_cfg_fini(idmap_cfg_t *cfg) 2158 { 2159 idmap_cfg_handles_t *handles = &cfg->handles; 2160 idmap_cfg_unload(&cfg->pgcfg); 2161 2162 (void) pthread_mutex_destroy(&handles->mutex); 2163 scf_pg_destroy(handles->config_pg); 2164 if (handles->debug_pg != NULL) 2165 scf_pg_destroy(handles->debug_pg); 2166 scf_instance_destroy(handles->instance); 2167 scf_service_destroy(handles->service); 2168 scf_handle_destroy(handles->main); 2169 if (handles->ad_ctx != NULL) 2170 ad_disc_fini(handles->ad_ctx); 2171 free(cfg); 2172 2173 return (0); 2174 } 2175 2176 void 2177 idmap_cfg_poke_updates(void) 2178 { 2179 if (idmapd_ev_port != -1) 2180 (void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL); 2181 } 2182 2183 /*ARGSUSED*/ 2184 void 2185 idmap_cfg_hup_handler(int sig) 2186 { 2187 if (idmapd_ev_port >= 0) 2188 (void) port_send(idmapd_ev_port, RECONFIGURE, NULL); 2189 } 2190 2191 /* 2192 * Upgrade the debug flags. 2193 * 2194 * We're replacing a single debug flag with a fine-grained mechanism that 2195 * is also capable of considerably more verbosity. We'll take a stab at 2196 * producing roughly the same level of output. 2197 */ 2198 static 2199 int 2200 upgrade_debug(idmap_cfg_handles_t *handles) 2201 { 2202 boolean_t debug_present; 2203 const char DEBUG_PROP[] = "debug"; 2204 int rc; 2205 2206 rc = prop_exists(handles, DEBUG_PROP, &debug_present); 2207 2208 if (rc != 0) 2209 return (rc); 2210 2211 if (!debug_present) 2212 return (0); 2213 2214 idmapdlog(LOG_INFO, 2215 "Upgrading old %s/%s setting to %s/* settings.", 2216 CONFIG_PG, DEBUG_PROP, DEBUG_PG); 2217 2218 rc = set_val_integer(handles, handles->debug_pg, "config", 1); 2219 if (rc != 0) 2220 return (rc); 2221 rc = set_val_integer(handles, handles->debug_pg, "discovery", 1); 2222 if (rc != 0) 2223 return (rc); 2224 2225 rc = del_val(handles, handles->config_pg, DEBUG_PROP); 2226 if (rc != 0) 2227 return (rc); 2228 2229 return (0); 2230 } 2231 2232 /* 2233 * Upgrade the DS mapping flags. 2234 * 2235 * If the old ds_name_mapping_enabled flag is present, then 2236 * if the new directory_based_mapping value is present, then 2237 * if the two are compatible, delete the old and note it 2238 * else delete the old and warn 2239 * else 2240 * set the new based on the old, and note it 2241 * delete the old 2242 */ 2243 static 2244 int 2245 upgrade_directory_mapping(idmap_cfg_handles_t *handles) 2246 { 2247 boolean_t legacy_ds_name_mapping_present; 2248 const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled"; 2249 const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping"; 2250 int rc; 2251 2252 rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED, 2253 &legacy_ds_name_mapping_present); 2254 2255 if (rc != 0) 2256 return (rc); 2257 2258 if (!legacy_ds_name_mapping_present) 2259 return (0); 2260 2261 boolean_t legacy_ds_name_mapping_enabled; 2262 rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED, 2263 &legacy_ds_name_mapping_enabled, B_FALSE); 2264 if (rc != 0) 2265 return (rc); 2266 2267 char *legacy_mode; 2268 char *legacy_bool_string; 2269 if (legacy_ds_name_mapping_enabled) { 2270 legacy_mode = "name"; 2271 legacy_bool_string = "true"; 2272 } else { 2273 legacy_mode = "none"; 2274 legacy_bool_string = "false"; 2275 } 2276 2277 char *directory_based_mapping; 2278 rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING, 2279 &directory_based_mapping); 2280 if (rc != 0) 2281 return (rc); 2282 2283 if (directory_based_mapping == NULL) { 2284 idmapdlog(LOG_INFO, 2285 "Upgrading old %s=%s setting\n" 2286 "to %s=%s.", 2287 DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2288 DIRECTORY_BASED_MAPPING, legacy_mode); 2289 rc = set_val_astring(handles, handles->config_pg, 2290 DIRECTORY_BASED_MAPPING, legacy_mode); 2291 if (rc != 0) 2292 return (rc); 2293 } else { 2294 boolean_t new_name_mapping; 2295 if (strcasecmp(directory_based_mapping, "name") == 0) 2296 new_name_mapping = B_TRUE; 2297 else 2298 new_name_mapping = B_FALSE; 2299 2300 if (legacy_ds_name_mapping_enabled == new_name_mapping) { 2301 idmapdlog(LOG_INFO, 2302 "Automatically removing old %s=%s setting\n" 2303 "in favor of %s=%s.", 2304 DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2305 DIRECTORY_BASED_MAPPING, directory_based_mapping); 2306 } else { 2307 idmapdlog(LOG_WARNING, 2308 "Removing conflicting %s=%s setting\n" 2309 "in favor of %s=%s.", 2310 DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2311 DIRECTORY_BASED_MAPPING, directory_based_mapping); 2312 } 2313 free(directory_based_mapping); 2314 } 2315 2316 rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED); 2317 if (rc != 0) 2318 return (rc); 2319 2320 return (0); 2321 } 2322 2323 /* 2324 * Do whatever is necessary to upgrade idmap's configuration before 2325 * we load it. 2326 */ 2327 int 2328 idmap_cfg_upgrade(idmap_cfg_t *cfg) 2329 { 2330 int rc; 2331 2332 rc = upgrade_directory_mapping(&cfg->handles); 2333 if (rc != 0) 2334 return (rc); 2335 2336 rc = upgrade_debug(&cfg->handles); 2337 if (rc != 0) 2338 return (rc); 2339 2340 return (0); 2341 } 2342