1c5c4113dSnw /* 2c5c4113dSnw * CDDL HEADER START 3c5c4113dSnw * 4c5c4113dSnw * The contents of this file are subject to the terms of the 5c5c4113dSnw * Common Development and Distribution License (the "License"). 6c5c4113dSnw * You may not use this file except in compliance with the License. 7c5c4113dSnw * 8c5c4113dSnw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw * See the License for the specific language governing permissions 11c5c4113dSnw * and limitations under the License. 12c5c4113dSnw * 13c5c4113dSnw * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw * 19c5c4113dSnw * CDDL HEADER END 20c5c4113dSnw */ 21c5c4113dSnw /* 22c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24c5c4113dSnw */ 25c5c4113dSnw 26c5c4113dSnw 27c5c4113dSnw /* 28c5c4113dSnw * Config routines common to idmap(1M) and idmapd(1M) 29c5c4113dSnw */ 30c5c4113dSnw 31c5c4113dSnw #include <stdlib.h> 32c5c4113dSnw #include <strings.h> 33c5c4113dSnw #include <libintl.h> 34c5c4113dSnw #include <ctype.h> 35c5c4113dSnw #include <errno.h> 36c5c4113dSnw #include <stdio.h> 37c5c4113dSnw #include <stdarg.h> 388edda628Sbaban #include <uuid/uuid.h> 39c8e26105Sjp #include <pthread.h> 40c8e26105Sjp #include <port.h> 41*b3700b07SGordon Ross #include <sys/socket.h> 420dcc7149Snw #include <net/route.h> 434d61c878SJulian Pullen #include <sys/u8_textprep.h> 44*b3700b07SGordon Ross #include <netinet/in.h> 45*b3700b07SGordon Ross #include <arpa/inet.h> 46*b3700b07SGordon Ross #include <netdb.h> 47148c5f43SAlan Wright #include <note.h> 48*b3700b07SGordon Ross #include "idmapd.h" 49c8e26105Sjp #include "addisc.h" 50c5c4113dSnw 514aa0a5e7Snw #define MACHINE_SID_LEN (9 + 3 * 11) 520dcc7149Snw #define FMRI_BASE "svc:/system/idmap" 530dcc7149Snw #define CONFIG_PG "config" 54148c5f43SAlan Wright #define DEBUG_PG "debug" 550dcc7149Snw #define RECONFIGURE 1 560dcc7149Snw #define POKE_AUTO_DISCOVERY 2 57*b3700b07SGordon Ross #define KICK_AUTO_DISCOVERY 3 58c5c4113dSnw 5948cd229bSGordon Ross /* 6048cd229bSGordon Ross * Default cache timeouts. Can override via svccfg 6148cd229bSGordon Ross * config/id_cache_timeout = count: seconds 6248cd229bSGordon Ross * config/name_cache_timeout = count: seconds 6348cd229bSGordon Ross */ 643f1de28dSBayard Bell #define ID_CACHE_TMO_DEFAULT 86400 653f1de28dSBayard Bell #define NAME_CACHE_TMO_DEFAULT 604800 6648cd229bSGordon Ross 67*b3700b07SGordon Ross /* 68*b3700b07SGordon Ross * Default maximum time between rediscovery runs. 69*b3700b07SGordon Ross * config/rediscovery_interval = count: seconds 70*b3700b07SGordon Ross */ 71*b3700b07SGordon Ross #define REDISCOVERY_INTERVAL_DEFAULT 3600 72*b3700b07SGordon Ross 73*b3700b07SGordon Ross /* 74*b3700b07SGordon Ross * Mininum time between rediscovery runs, in case adutils gives us a 75*b3700b07SGordon Ross * really short TTL (which it never should, but be defensive) 76*b3700b07SGordon Ross * (not configurable) seconds. 77*b3700b07SGordon Ross */ 78*b3700b07SGordon Ross #define MIN_REDISCOVERY_INTERVAL 60 79*b3700b07SGordon Ross 80c5866007SKeyur Desai enum event_type { 81c5866007SKeyur Desai EVENT_NOTHING, /* Woke up for no good reason */ 82c5866007SKeyur Desai EVENT_TIMEOUT, /* Timeout expired */ 83c5866007SKeyur Desai EVENT_ROUTING, /* An interesting routing event happened */ 84*b3700b07SGordon Ross EVENT_POKED, /* Requested from degrade_svc() */ 85*b3700b07SGordon Ross EVENT_KICKED, /* Force rediscovery, i.e. DC failed. */ 86c5866007SKeyur Desai EVENT_REFRESH, /* SMF refresh */ 87c5866007SKeyur Desai }; 88c5866007SKeyur Desai 89c8e26105Sjp 90*b3700b07SGordon Ross static void idmapd_set_krb5_realm(char *); 91c8e26105Sjp 92c8e26105Sjp static pthread_t update_thread_handle = 0; 93c8e26105Sjp 940dcc7149Snw static int idmapd_ev_port = -1; 950dcc7149Snw static int rt_sock = -1; 96c8e26105Sjp 97e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = { 98e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NONE, "none" }, 99e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NAME, "name" }, 100e3f2c991SKeyur Desai { DIRECTORY_MAPPING_IDMU, "idmu" }, 101e3f2c991SKeyur Desai { 0, NULL }, 102e3f2c991SKeyur Desai }; 103e3f2c991SKeyur Desai 104148c5f43SAlan Wright struct enum_lookup_map trust_dir_map[] = { 105148c5f43SAlan Wright { 1, "they trust us" }, 106148c5f43SAlan Wright { 2, "we trust them" }, 107148c5f43SAlan Wright { 3, "we trust each other" }, 108148c5f43SAlan Wright { 0, NULL }, 109148c5f43SAlan Wright }; 110148c5f43SAlan Wright 1118edda628Sbaban static int 11212b65585SGordon Ross generate_machine_uuid(char **machine_uuid) 1134edd44c5Sjp { 1148edda628Sbaban uuid_t uu; 1158edda628Sbaban 11612b65585SGordon Ross *machine_uuid = calloc(1, UUID_PRINTABLE_STRING_LENGTH + 1); 11712b65585SGordon Ross if (*machine_uuid == NULL) { 11871590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 1198edda628Sbaban return (-1); 1208edda628Sbaban } 1218edda628Sbaban 1228edda628Sbaban uuid_clear(uu); 12312b65585SGordon Ross uuid_generate_time(uu); 12412b65585SGordon Ross uuid_unparse(uu, *machine_uuid); 12512b65585SGordon Ross 12612b65585SGordon Ross return (0); 12712b65585SGordon Ross } 12812b65585SGordon Ross 12912b65585SGordon Ross static int 13012b65585SGordon Ross generate_machine_sid(char **machine_sid, char *machine_uuid) 13112b65585SGordon Ross { 13212b65585SGordon Ross union { 13312b65585SGordon Ross uuid_t uu; 13412b65585SGordon Ross uint32_t v[4]; 13512b65585SGordon Ross } uv; 13612b65585SGordon Ross int len; 13712b65585SGordon Ross 13812b65585SGordon Ross /* 13912b65585SGordon Ross * Split the 128-bit machine UUID into three 32-bit values 14012b65585SGordon Ross * we'll use as the "sub-authorities" of the machine SID. 14112b65585SGordon Ross * The machine_sid will have the form S-1-5-21-J-K-L 14212b65585SGordon Ross * (that's four sub-authorities altogether) where: 14312b65585SGordon Ross * J = last 4 bytes of node_addr, 14412b65585SGordon Ross * K = time_mid, time_hi_and_version 14512b65585SGordon Ross * L = time_low 14612b65585SGordon Ross * (see struct uuid) 14712b65585SGordon Ross */ 14812b65585SGordon Ross 14912b65585SGordon Ross (void) memset(&uv, 0, sizeof (uv)); 15012b65585SGordon Ross (void) uuid_parse(machine_uuid, uv.uu); 1518edda628Sbaban 15212b65585SGordon Ross len = asprintf(machine_sid, "S-1-5-21-%u-%u-%u", 15312b65585SGordon Ross uv.v[3], uv.v[0], uv.v[1]); 1544aa0a5e7Snw 15512b65585SGordon Ross if (len == -1 || *machine_sid == NULL) { 15612b65585SGordon Ross idmapdlog(LOG_ERR, "Out of memory"); 15712b65585SGordon Ross return (-1); 1588edda628Sbaban } 1598edda628Sbaban 1608edda628Sbaban return (0); 1618edda628Sbaban } 1628edda628Sbaban 163479ac375Sdm 164479ac375Sdm /* In the case of error, exists is set to FALSE anyway */ 165479ac375Sdm static int 166e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists) 16771590c90Snw { 16871590c90Snw 169479ac375Sdm scf_property_t *scf_prop; 170479ac375Sdm 1717a8a68f5SJulian Pullen *exists = B_FALSE; 172479ac375Sdm 173148c5f43SAlan Wright scf_prop = scf_property_create(handles->main); 174148c5f43SAlan Wright if (scf_prop == NULL) { 175148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 176148c5f43SAlan Wright scf_strerror(scf_error())); 177148c5f43SAlan Wright return (-1); 178148c5f43SAlan Wright } 179148c5f43SAlan Wright 180148c5f43SAlan Wright if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0) 181148c5f43SAlan Wright *exists = B_TRUE; 182148c5f43SAlan Wright 183148c5f43SAlan Wright scf_property_destroy(scf_prop); 184148c5f43SAlan Wright 185148c5f43SAlan Wright return (0); 186148c5f43SAlan Wright } 187148c5f43SAlan Wright 188148c5f43SAlan Wright static int 189148c5f43SAlan Wright get_debug(idmap_cfg_handles_t *handles, const char *name) 190148c5f43SAlan Wright { 191148c5f43SAlan Wright int64_t i64 = 0; 192148c5f43SAlan Wright 193148c5f43SAlan Wright scf_property_t *scf_prop; 194148c5f43SAlan Wright scf_value_t *value; 195148c5f43SAlan Wright 196148c5f43SAlan Wright scf_prop = scf_property_create(handles->main); 197148c5f43SAlan Wright if (scf_prop == NULL) { 198148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 199148c5f43SAlan Wright scf_strerror(scf_error())); 200148c5f43SAlan Wright abort(); 201148c5f43SAlan Wright } 202148c5f43SAlan Wright value = scf_value_create(handles->main); 203148c5f43SAlan Wright if (value == NULL) { 204148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 205148c5f43SAlan Wright scf_strerror(scf_error())); 206148c5f43SAlan Wright abort(); 207148c5f43SAlan Wright } 208148c5f43SAlan Wright 209148c5f43SAlan Wright if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) { 210148c5f43SAlan Wright /* this is OK: the property is just undefined */ 211148c5f43SAlan Wright goto destruction; 212148c5f43SAlan Wright } 213148c5f43SAlan Wright 214148c5f43SAlan Wright 215148c5f43SAlan Wright if (scf_property_get_value(scf_prop, value) < 0) { 216148c5f43SAlan Wright /* It is still OK when a property doesn't have any value */ 217148c5f43SAlan Wright goto destruction; 218148c5f43SAlan Wright } 219148c5f43SAlan Wright 220148c5f43SAlan Wright if (scf_value_get_integer(value, &i64) != 0) { 221148c5f43SAlan Wright idmapdlog(LOG_ERR, "Can not retrieve %s/%s: %s", 222148c5f43SAlan Wright DEBUG_PG, name, scf_strerror(scf_error())); 223148c5f43SAlan Wright abort(); 224148c5f43SAlan Wright } 225148c5f43SAlan Wright 226148c5f43SAlan Wright destruction: 227148c5f43SAlan Wright scf_value_destroy(value); 228148c5f43SAlan Wright scf_property_destroy(scf_prop); 229148c5f43SAlan Wright 230148c5f43SAlan Wright return ((int)i64); 231148c5f43SAlan Wright } 232148c5f43SAlan Wright 233148c5f43SAlan Wright static int 234148c5f43SAlan Wright get_val_bool(idmap_cfg_handles_t *handles, const char *name, 235148c5f43SAlan Wright boolean_t *val, boolean_t default_val) 236148c5f43SAlan Wright { 237148c5f43SAlan Wright int rc = 0; 238148c5f43SAlan Wright 239148c5f43SAlan Wright scf_property_t *scf_prop; 240148c5f43SAlan Wright scf_value_t *value; 241148c5f43SAlan Wright 242148c5f43SAlan Wright *val = default_val; 243148c5f43SAlan Wright 244479ac375Sdm scf_prop = scf_property_create(handles->main); 245479ac375Sdm if (scf_prop == NULL) { 246479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 247479ac375Sdm scf_strerror(scf_error())); 248479ac375Sdm return (-1); 249479ac375Sdm } 250479ac375Sdm value = scf_value_create(handles->main); 251479ac375Sdm if (value == NULL) { 252479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 253479ac375Sdm scf_strerror(scf_error())); 254479ac375Sdm scf_property_destroy(scf_prop); 255479ac375Sdm return (-1); 256479ac375Sdm } 25771590c90Snw 258148c5f43SAlan Wright /* It is OK if the property is undefined */ 259148c5f43SAlan Wright if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 260148c5f43SAlan Wright goto destruction; 261148c5f43SAlan Wright 262148c5f43SAlan Wright 263148c5f43SAlan Wright /* It is still OK when a property doesn't have any value */ 264148c5f43SAlan Wright if (scf_property_get_value(scf_prop, value) < 0) 265148c5f43SAlan Wright goto destruction; 266148c5f43SAlan Wright 267148c5f43SAlan Wright uint8_t b; 268148c5f43SAlan Wright rc = scf_value_get_boolean(value, &b); 26971590c90Snw 270148c5f43SAlan Wright if (rc == 0) 271148c5f43SAlan Wright *val = (boolean_t)b; 272148c5f43SAlan Wright 273148c5f43SAlan Wright destruction: 27471590c90Snw scf_value_destroy(value); 27571590c90Snw scf_property_destroy(scf_prop); 27671590c90Snw 277148c5f43SAlan Wright return (rc); 27871590c90Snw } 27971590c90Snw 280c5c4113dSnw static int 281e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name, 282c8e26105Sjp void *val, scf_type_t type) 283c5c4113dSnw { 284c5c4113dSnw int rc = 0; 285c5c4113dSnw 286479ac375Sdm scf_property_t *scf_prop; 287479ac375Sdm scf_value_t *value; 288479ac375Sdm 2894aa0a5e7Snw switch (type) { 2904aa0a5e7Snw case SCF_TYPE_COUNT: 2914aa0a5e7Snw *(uint64_t *)val = 0; 2924aa0a5e7Snw break; 2934aa0a5e7Snw case SCF_TYPE_INTEGER: 2944aa0a5e7Snw *(int64_t *)val = 0; 2954aa0a5e7Snw break; 2964aa0a5e7Snw default: 2974aa0a5e7Snw idmapdlog(LOG_ERR, "Invalid scf integer type (%d)", 2984aa0a5e7Snw type); 2994aa0a5e7Snw abort(); 3004aa0a5e7Snw } 3014aa0a5e7Snw 302479ac375Sdm scf_prop = scf_property_create(handles->main); 303479ac375Sdm if (scf_prop == NULL) { 304479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 305479ac375Sdm scf_strerror(scf_error())); 306479ac375Sdm return (-1); 307479ac375Sdm } 308479ac375Sdm value = scf_value_create(handles->main); 309479ac375Sdm if (value == NULL) { 310479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 311479ac375Sdm scf_strerror(scf_error())); 312479ac375Sdm scf_property_destroy(scf_prop); 313479ac375Sdm return (-1); 314479ac375Sdm } 315c5c4113dSnw 316c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 317c5c4113dSnw /* this is OK: the property is just undefined */ 318c5c4113dSnw goto destruction; 319c5c4113dSnw 320c5c4113dSnw 321c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) 322c5c4113dSnw /* It is still OK when a property doesn't have any value */ 323c5c4113dSnw goto destruction; 324c5c4113dSnw 325c5c4113dSnw switch (type) { 326c5c4113dSnw case SCF_TYPE_COUNT: 327c5c4113dSnw rc = scf_value_get_count(value, val); 328c5c4113dSnw break; 329c5c4113dSnw case SCF_TYPE_INTEGER: 330c5c4113dSnw rc = scf_value_get_integer(value, val); 331c5c4113dSnw break; 332e3f2c991SKeyur Desai default: 333e3f2c991SKeyur Desai abort(); /* tested above */ 334e3f2c991SKeyur Desai /* NOTREACHED */ 335c5c4113dSnw } 336c5c4113dSnw 337e3f2c991SKeyur Desai if (rc != 0) { 338e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 339e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 340e3f2c991SKeyur Desai } 341c5c4113dSnw 342c5c4113dSnw destruction: 343c5c4113dSnw scf_value_destroy(value); 344c5c4113dSnw scf_property_destroy(scf_prop); 345c5c4113dSnw 346c5c4113dSnw return (rc); 347c5c4113dSnw } 348c5c4113dSnw 349c5c4113dSnw static char * 350e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value) 3514edd44c5Sjp { 352e3f2c991SKeyur Desai static size_t max_val = 0; 353c5c4113dSnw 354e3f2c991SKeyur Desai if (max_val == 0) 355e3f2c991SKeyur Desai max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 356c5c4113dSnw 357e3f2c991SKeyur Desai char buf[max_val + 1]; 358e3f2c991SKeyur Desai if (scf_value_get_astring(value, buf, max_val + 1) < 0) { 359e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 360e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 361e3f2c991SKeyur Desai return (NULL); 362c5c4113dSnw } 363c5c4113dSnw 364e3f2c991SKeyur Desai char *s = strdup(buf); 365e3f2c991SKeyur Desai if (s == NULL) 366e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Out of memory"); 367c5c4113dSnw 368e3f2c991SKeyur Desai return (s); 369c5c4113dSnw } 370c5c4113dSnw 371c8e26105Sjp static int 372c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport, 373*b3700b07SGordon Ross ad_disc_ds_t **val) 374c8e26105Sjp { 375*b3700b07SGordon Ross char port_str[8]; 376*b3700b07SGordon Ross struct addrinfo hints; 377*b3700b07SGordon Ross struct addrinfo *ai; 378*b3700b07SGordon Ross ad_disc_ds_t *servers = NULL; 379c8e26105Sjp scf_property_t *scf_prop; 380c8e26105Sjp scf_value_t *value; 381c8e26105Sjp scf_iter_t *iter; 382c8e26105Sjp char *host, *portstr; 383*b3700b07SGordon Ross int err, len, i; 384c8e26105Sjp int count = 0; 385e3c2d6aaSnw int rc = -1; 386c8e26105Sjp 387c8e26105Sjp *val = NULL; 388c8e26105Sjp 389c8e26105Sjp restart: 390c8e26105Sjp scf_prop = scf_property_create(handles->main); 391479ac375Sdm if (scf_prop == NULL) { 392479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 393479ac375Sdm scf_strerror(scf_error())); 394479ac375Sdm return (-1); 395479ac375Sdm } 396479ac375Sdm 397c8e26105Sjp value = scf_value_create(handles->main); 398479ac375Sdm if (value == NULL) { 399479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 400479ac375Sdm scf_strerror(scf_error())); 401479ac375Sdm scf_property_destroy(scf_prop); 402479ac375Sdm return (-1); 403479ac375Sdm } 404479ac375Sdm 405c8e26105Sjp iter = scf_iter_create(handles->main); 406479ac375Sdm if (iter == NULL) { 407479ac375Sdm idmapdlog(LOG_ERR, "scf_iter_create() failed: %s", 408479ac375Sdm scf_strerror(scf_error())); 409479ac375Sdm scf_value_destroy(value); 410479ac375Sdm scf_property_destroy(scf_prop); 411479ac375Sdm return (-1); 412479ac375Sdm } 413c8e26105Sjp 414e3c2d6aaSnw if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) { 415c8e26105Sjp /* this is OK: the property is just undefined */ 416e3c2d6aaSnw rc = 0; 417c8e26105Sjp goto destruction; 418e3c2d6aaSnw } 419c8e26105Sjp 420c8e26105Sjp if (scf_iter_property_values(iter, scf_prop) < 0) { 421c8e26105Sjp idmapdlog(LOG_ERR, 42271590c90Snw "scf_iter_property_values(%s) failed: %s", 42371590c90Snw name, scf_strerror(scf_error())); 424c8e26105Sjp goto destruction; 425c8e26105Sjp } 426c8e26105Sjp 427c8e26105Sjp /* Workaround scf bugs -- can't reset an iteration */ 428c8e26105Sjp if (count == 0) { 429c8e26105Sjp while (scf_iter_next_value(iter, value) > 0) 430c8e26105Sjp count++; 431c8e26105Sjp 432e3c2d6aaSnw if (count == 0) { 433c8e26105Sjp /* no values */ 434e3c2d6aaSnw rc = 0; 435c8e26105Sjp goto destruction; 436e3c2d6aaSnw } 437c8e26105Sjp 438c8e26105Sjp scf_value_destroy(value); 439c8e26105Sjp scf_iter_destroy(iter); 440c8e26105Sjp scf_property_destroy(scf_prop); 441c8e26105Sjp goto restart; 442c8e26105Sjp } 443c8e26105Sjp 444c8e26105Sjp if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) { 44571590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 446c8e26105Sjp goto destruction; 447c8e26105Sjp } 448c8e26105Sjp 449*b3700b07SGordon Ross (void) memset(&hints, 0, sizeof (hints)); 450*b3700b07SGordon Ross hints.ai_protocol = IPPROTO_TCP; 451*b3700b07SGordon Ross hints.ai_socktype = SOCK_STREAM; 452*b3700b07SGordon Ross host = NULL; 453*b3700b07SGordon Ross 454e3c2d6aaSnw i = 0; 455e3c2d6aaSnw while (i < count && scf_iter_next_value(iter, value) > 0) { 456*b3700b07SGordon Ross if (host) { 457*b3700b07SGordon Ross free(host); 458*b3700b07SGordon Ross host = NULL; 459*b3700b07SGordon Ross } 460e3c2d6aaSnw servers[i].priority = 0; 461e3c2d6aaSnw servers[i].weight = 100; 462e3c2d6aaSnw servers[i].port = defport; 463*b3700b07SGordon Ross if ((host = scf_value2string(name, value)) == NULL) 464*b3700b07SGordon Ross continue; 465c8e26105Sjp if ((portstr = strchr(host, ':')) != NULL) { 466c8e26105Sjp *portstr++ = '\0'; 467e3c2d6aaSnw servers[i].port = strtol(portstr, 468c8e26105Sjp (char **)NULL, 10); 469e3c2d6aaSnw if (servers[i].port == 0) 470e3c2d6aaSnw servers[i].port = defport; 471c8e26105Sjp } 472c8e26105Sjp 473*b3700b07SGordon Ross /* 474*b3700b07SGordon Ross * Ignore this server if the hostname is too long 475*b3700b07SGordon Ross * or empty (continue without i++) 476*b3700b07SGordon Ross */ 477*b3700b07SGordon Ross len = strlen(host); 478*b3700b07SGordon Ross if (len == 0) { 479*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 480*b3700b07SGordon Ross idmapdlog(LOG_INFO, "%s host=\"\"", name); 481*b3700b07SGordon Ross } 482*b3700b07SGordon Ross continue; 483*b3700b07SGordon Ross } 484*b3700b07SGordon Ross if (len >= sizeof (servers->host)) { 485*b3700b07SGordon Ross idmapdlog(LOG_ERR, "Host name too long: %s", host); 486*b3700b07SGordon Ross idmapdlog(LOG_ERR, "ignoring %s value", name); 487*b3700b07SGordon Ross continue; 488*b3700b07SGordon Ross } 489*b3700b07SGordon Ross 490*b3700b07SGordon Ross /* 491*b3700b07SGordon Ross * Get the host address too. If we can't, then 492*b3700b07SGordon Ross * log an error and skip this host. 493*b3700b07SGordon Ross */ 494*b3700b07SGordon Ross (void) snprintf(port_str, sizeof (port_str), 495*b3700b07SGordon Ross "%d", servers[i].port); 496*b3700b07SGordon Ross ai = NULL; 497*b3700b07SGordon Ross err = getaddrinfo(host, port_str, &hints, &ai); 498*b3700b07SGordon Ross if (err != 0) { 499*b3700b07SGordon Ross idmapdlog(LOG_ERR, "No address for host: %s (%s)", 500*b3700b07SGordon Ross host, gai_strerror(err)); 501*b3700b07SGordon Ross idmapdlog(LOG_ERR, "ignoring %s value", name); 502*b3700b07SGordon Ross continue; 503*b3700b07SGordon Ross } 504*b3700b07SGordon Ross 505*b3700b07SGordon Ross (void) strlcpy(servers[i].host, host, 506*b3700b07SGordon Ross sizeof (servers->host)); 507*b3700b07SGordon Ross (void) memcpy(&servers[i].addr, ai->ai_addr, ai->ai_addrlen); 508*b3700b07SGordon Ross freeaddrinfo(ai); 509c8e26105Sjp 510*b3700b07SGordon Ross /* Added a DS to the array. */ 511*b3700b07SGordon Ross i++; 512c8e26105Sjp } 513*b3700b07SGordon Ross free(host); 514c8e26105Sjp 515*b3700b07SGordon Ross if (i == 0) { 516*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 517*b3700b07SGordon Ross idmapdlog(LOG_INFO, "%s is empty", name); 518*b3700b07SGordon Ross } 519*b3700b07SGordon Ross free(servers); 520*b3700b07SGordon Ross servers = NULL; 521*b3700b07SGordon Ross } 522c8e26105Sjp *val = servers; 523c8e26105Sjp 524e3c2d6aaSnw rc = 0; 525e3c2d6aaSnw 526c8e26105Sjp destruction: 527c8e26105Sjp scf_value_destroy(value); 528c8e26105Sjp scf_iter_destroy(iter); 529c8e26105Sjp scf_property_destroy(scf_prop); 530c8e26105Sjp 531c8e26105Sjp if (rc < 0) { 532c8e26105Sjp if (servers) 533c8e26105Sjp free(servers); 534c8e26105Sjp *val = NULL; 535c8e26105Sjp } 536c8e26105Sjp 537c8e26105Sjp return (rc); 538c8e26105Sjp } 539c8e26105Sjp 540c5c4113dSnw static int 541e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val) 542c5c4113dSnw { 543c5c4113dSnw int rc = 0; 544c5c4113dSnw 545479ac375Sdm scf_property_t *scf_prop; 546479ac375Sdm scf_value_t *value; 547479ac375Sdm 548479ac375Sdm scf_prop = scf_property_create(handles->main); 549479ac375Sdm if (scf_prop == NULL) { 550479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 551479ac375Sdm scf_strerror(scf_error())); 552479ac375Sdm return (-1); 553479ac375Sdm } 554479ac375Sdm value = scf_value_create(handles->main); 555479ac375Sdm if (value == NULL) { 556479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 557479ac375Sdm scf_strerror(scf_error())); 558479ac375Sdm scf_property_destroy(scf_prop); 559479ac375Sdm return (-1); 560479ac375Sdm } 561c5c4113dSnw 562c8e26105Sjp *val = NULL; 563c5c4113dSnw 564c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 565c5c4113dSnw /* this is OK: the property is just undefined */ 566c5c4113dSnw goto destruction; 567c5c4113dSnw 568c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) { 569651c0131Sbaban idmapdlog(LOG_ERR, 57071590c90Snw "scf_property_get_value(%s) failed: %s", 57171590c90Snw name, scf_strerror(scf_error())); 572c5c4113dSnw rc = -1; 573c5c4113dSnw goto destruction; 574c5c4113dSnw } 575c5c4113dSnw 576e3f2c991SKeyur Desai *val = scf_value2string(name, value); 577e3f2c991SKeyur Desai if (*val == NULL) 578c5c4113dSnw rc = -1; 579c5c4113dSnw 580c5c4113dSnw destruction: 581c5c4113dSnw scf_value_destroy(value); 582c5c4113dSnw scf_property_destroy(scf_prop); 583c5c4113dSnw 584c5c4113dSnw if (rc < 0) { 585c5c4113dSnw if (*val) 586c5c4113dSnw free(*val); 587c5c4113dSnw *val = NULL; 588c5c4113dSnw } 589c5c4113dSnw 590c5c4113dSnw return (rc); 591c5c4113dSnw } 592c5c4113dSnw 593c8e26105Sjp 5948edda628Sbaban static int 595148c5f43SAlan Wright del_val( 596148c5f43SAlan Wright idmap_cfg_handles_t *handles, 597148c5f43SAlan Wright scf_propertygroup_t *pg, 598148c5f43SAlan Wright const char *name) 599e3f2c991SKeyur Desai { 600e3f2c991SKeyur Desai int rc = -1; 601e3f2c991SKeyur Desai int ret; 602e3f2c991SKeyur Desai scf_transaction_t *tx = NULL; 603e3f2c991SKeyur Desai scf_transaction_entry_t *ent = NULL; 604e3f2c991SKeyur Desai 605e3f2c991SKeyur Desai if ((tx = scf_transaction_create(handles->main)) == NULL) { 606e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 607e3f2c991SKeyur Desai "scf_transaction_create() failed: %s", 608e3f2c991SKeyur Desai scf_strerror(scf_error())); 609e3f2c991SKeyur Desai goto destruction; 610e3f2c991SKeyur Desai } 611e3f2c991SKeyur Desai if ((ent = scf_entry_create(handles->main)) == NULL) { 612e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 613e3f2c991SKeyur Desai "scf_entry_create() failed: %s", 614e3f2c991SKeyur Desai scf_strerror(scf_error())); 615e3f2c991SKeyur Desai goto destruction; 616e3f2c991SKeyur Desai } 617e3f2c991SKeyur Desai 618e3f2c991SKeyur Desai do { 619148c5f43SAlan Wright if (scf_pg_update(pg) == -1) { 620e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 621e3f2c991SKeyur Desai "scf_pg_update(%s) failed: %s", 622e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 623e3f2c991SKeyur Desai goto destruction; 624e3f2c991SKeyur Desai } 625148c5f43SAlan Wright if (scf_transaction_start(tx, pg) != 0) { 626e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 627e3f2c991SKeyur Desai "scf_transaction_start(%s) failed: %s", 628e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 629e3f2c991SKeyur Desai goto destruction; 630e3f2c991SKeyur Desai } 631e3f2c991SKeyur Desai 632e3f2c991SKeyur Desai if (scf_transaction_property_delete(tx, ent, name) != 0) { 633e3f2c991SKeyur Desai /* Don't complain if it already doesn't exist. */ 634e3f2c991SKeyur Desai if (scf_error() != SCF_ERROR_NOT_FOUND) { 635e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 636e3f2c991SKeyur Desai "scf_transaction_property_delete() failed:" 637e3f2c991SKeyur Desai " %s", 638e3f2c991SKeyur Desai scf_strerror(scf_error())); 639e3f2c991SKeyur Desai } 640e3f2c991SKeyur Desai goto destruction; 641e3f2c991SKeyur Desai } 642e3f2c991SKeyur Desai 643e3f2c991SKeyur Desai ret = scf_transaction_commit(tx); 644e3f2c991SKeyur Desai 645e3f2c991SKeyur Desai if (ret == 0) 646e3f2c991SKeyur Desai scf_transaction_reset(tx); 647e3f2c991SKeyur Desai } while (ret == 0); 648e3f2c991SKeyur Desai 649e3f2c991SKeyur Desai if (ret == -1) { 650e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 651e3f2c991SKeyur Desai "scf_transaction_commit(%s) failed: %s", 652e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 653e3f2c991SKeyur Desai goto destruction; 654e3f2c991SKeyur Desai } 655e3f2c991SKeyur Desai 656e3f2c991SKeyur Desai rc = 0; 657e3f2c991SKeyur Desai 658e3f2c991SKeyur Desai destruction: 659e3f2c991SKeyur Desai if (ent != NULL) 660e3f2c991SKeyur Desai scf_entry_destroy(ent); 661e3f2c991SKeyur Desai if (tx != NULL) 662e3f2c991SKeyur Desai scf_transaction_destroy(tx); 663e3f2c991SKeyur Desai return (rc); 664e3f2c991SKeyur Desai } 665e3f2c991SKeyur Desai 666e3f2c991SKeyur Desai 667e3f2c991SKeyur Desai static int 668148c5f43SAlan Wright set_val( 669148c5f43SAlan Wright idmap_cfg_handles_t *handles, 670148c5f43SAlan Wright scf_propertygroup_t *pg, 671148c5f43SAlan Wright const char *name, 672148c5f43SAlan Wright scf_value_t *value) 6738edda628Sbaban { 674e3c2d6aaSnw int rc = -1; 675e3c2d6aaSnw int i; 676148c5f43SAlan Wright scf_property_t *prop = NULL; 6778edda628Sbaban scf_transaction_t *tx = NULL; 6788edda628Sbaban scf_transaction_entry_t *ent = NULL; 6798edda628Sbaban 680148c5f43SAlan Wright if ((prop = scf_property_create(handles->main)) == NULL || 681c8e26105Sjp (tx = scf_transaction_create(handles->main)) == NULL || 682c8e26105Sjp (ent = scf_entry_create(handles->main)) == NULL) { 68371590c90Snw idmapdlog(LOG_ERR, "Unable to set property %s", 68471590c90Snw name, scf_strerror(scf_error())); 6858edda628Sbaban goto destruction; 6868edda628Sbaban } 6878edda628Sbaban 688148c5f43SAlan Wright for (i = 0; i < MAX_TRIES; i++) { 689148c5f43SAlan Wright int ret; 690148c5f43SAlan Wright 691148c5f43SAlan Wright if (scf_pg_update(pg) == -1) { 6928edda628Sbaban idmapdlog(LOG_ERR, 693148c5f43SAlan Wright "scf_pg_update() failed: %s", 694148c5f43SAlan Wright scf_strerror(scf_error())); 6958edda628Sbaban goto destruction; 6968edda628Sbaban } 6978edda628Sbaban 698148c5f43SAlan Wright if (scf_transaction_start(tx, pg) == -1) { 6998edda628Sbaban idmapdlog(LOG_ERR, 700148c5f43SAlan Wright "scf_transaction_start(%s) failed: %s", 701148c5f43SAlan Wright name, scf_strerror(scf_error())); 7028edda628Sbaban goto destruction; 7038edda628Sbaban } 7048edda628Sbaban 705148c5f43SAlan Wright ret = scf_pg_get_property(pg, name, prop); 706148c5f43SAlan Wright if (ret == SCF_SUCCESS) { 707148c5f43SAlan Wright if (scf_transaction_property_change_type(tx, ent, name, 708148c5f43SAlan Wright scf_value_type(value)) < 0) { 709148c5f43SAlan Wright idmapdlog(LOG_ERR, 710148c5f43SAlan Wright "scf_transaction_property_change_type(%s)" 711148c5f43SAlan Wright " failed: %s", 712148c5f43SAlan Wright name, scf_strerror(scf_error())); 713148c5f43SAlan Wright goto destruction; 714148c5f43SAlan Wright } 715148c5f43SAlan Wright } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 716148c5f43SAlan Wright if (scf_transaction_property_new(tx, ent, name, 717148c5f43SAlan Wright scf_value_type(value)) < 0) { 718148c5f43SAlan Wright idmapdlog(LOG_ERR, 719148c5f43SAlan Wright "scf_transaction_property_new() failed: %s", 720148c5f43SAlan Wright scf_strerror(scf_error())); 721148c5f43SAlan Wright goto destruction; 722148c5f43SAlan Wright } 723148c5f43SAlan Wright } else { 7248edda628Sbaban idmapdlog(LOG_ERR, 725148c5f43SAlan Wright "scf_pg_get_property(%s) failed: %s", 726148c5f43SAlan Wright name, scf_strerror(scf_error())); 7278edda628Sbaban goto destruction; 7288edda628Sbaban } 7298edda628Sbaban 7308edda628Sbaban if (scf_entry_add_value(ent, value) == -1) { 7318edda628Sbaban idmapdlog(LOG_ERR, 73271590c90Snw "scf_entry_add_value() failed: %s", 73371590c90Snw scf_strerror(scf_error())); 7348edda628Sbaban goto destruction; 7358edda628Sbaban } 7368edda628Sbaban 737148c5f43SAlan Wright ret = scf_transaction_commit(tx); 738148c5f43SAlan Wright if (ret == 0) { 7398edda628Sbaban /* 7408edda628Sbaban * Property group set in scf_transaction_start() 7418edda628Sbaban * is not the most recent. Update pg, reset tx and 7428edda628Sbaban * retry tx. 7438edda628Sbaban */ 7448edda628Sbaban idmapdlog(LOG_WARNING, 745148c5f43SAlan Wright "scf_transaction_commit(%s) failed: %s", 74671590c90Snw name, scf_strerror(scf_error())); 7478edda628Sbaban scf_transaction_reset(tx); 748148c5f43SAlan Wright continue; 749148c5f43SAlan Wright } 750148c5f43SAlan Wright if (ret != 1) { 751148c5f43SAlan Wright idmapdlog(LOG_ERR, 752148c5f43SAlan Wright "scf_transaction_commit(%s) failed: %s", 753148c5f43SAlan Wright name, scf_strerror(scf_error())); 754148c5f43SAlan Wright goto destruction; 7558edda628Sbaban } 756148c5f43SAlan Wright /* Success! */ 757148c5f43SAlan Wright rc = 0; 758148c5f43SAlan Wright break; 7598edda628Sbaban } 7608edda628Sbaban 761148c5f43SAlan Wright destruction: 762148c5f43SAlan Wright scf_entry_destroy(ent); 763148c5f43SAlan Wright scf_transaction_destroy(tx); 764148c5f43SAlan Wright scf_property_destroy(prop); 765148c5f43SAlan Wright return (rc); 766148c5f43SAlan Wright } 767e3c2d6aaSnw 768148c5f43SAlan Wright static int 769148c5f43SAlan Wright set_val_integer( 770148c5f43SAlan Wright idmap_cfg_handles_t *handles, 771148c5f43SAlan Wright scf_propertygroup_t *pg, 772148c5f43SAlan Wright const char *name, 773148c5f43SAlan Wright int64_t val) 774148c5f43SAlan Wright { 775148c5f43SAlan Wright scf_value_t *value = NULL; 776148c5f43SAlan Wright int rc; 777148c5f43SAlan Wright 778148c5f43SAlan Wright if ((value = scf_value_create(handles->main)) == NULL) { 779148c5f43SAlan Wright idmapdlog(LOG_ERR, "Unable to set property %s", 78071590c90Snw name, scf_strerror(scf_error())); 781148c5f43SAlan Wright return (-1); 782148c5f43SAlan Wright } 783148c5f43SAlan Wright 784148c5f43SAlan Wright scf_value_set_integer(value, val); 785148c5f43SAlan Wright 786148c5f43SAlan Wright rc = set_val(handles, pg, name, value); 7878edda628Sbaban 7888edda628Sbaban scf_value_destroy(value); 789148c5f43SAlan Wright 790148c5f43SAlan Wright return (rc); 791148c5f43SAlan Wright } 792148c5f43SAlan Wright 793148c5f43SAlan Wright 794148c5f43SAlan Wright static int 795148c5f43SAlan Wright set_val_astring( 796148c5f43SAlan Wright idmap_cfg_handles_t *handles, 797148c5f43SAlan Wright scf_propertygroup_t *pg, 798148c5f43SAlan Wright const char *name, 799148c5f43SAlan Wright const char *val) 800148c5f43SAlan Wright { 801148c5f43SAlan Wright scf_value_t *value = NULL; 802148c5f43SAlan Wright int rc = -1; 803148c5f43SAlan Wright 804148c5f43SAlan Wright if ((value = scf_value_create(handles->main)) == NULL) { 805148c5f43SAlan Wright idmapdlog(LOG_ERR, "Unable to set property %s", 806148c5f43SAlan Wright name, scf_strerror(scf_error())); 807148c5f43SAlan Wright goto out; 808148c5f43SAlan Wright } 809148c5f43SAlan Wright 810148c5f43SAlan Wright if (scf_value_set_astring(value, val) == -1) { 811148c5f43SAlan Wright idmapdlog(LOG_ERR, 812148c5f43SAlan Wright "scf_value_set_astring() failed: %s", 813148c5f43SAlan Wright scf_strerror(scf_error())); 814148c5f43SAlan Wright goto out; 815148c5f43SAlan Wright } 816148c5f43SAlan Wright 817148c5f43SAlan Wright rc = set_val(handles, pg, name, value); 818148c5f43SAlan Wright 819148c5f43SAlan Wright out: 820148c5f43SAlan Wright scf_value_destroy(value); 8218edda628Sbaban return (rc); 8228edda628Sbaban } 8238edda628Sbaban 8244d61c878SJulian Pullen 8254d61c878SJulian Pullen 8264d61c878SJulian Pullen /* 8274d61c878SJulian Pullen * This function updates a boolean value. 8284d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 8294d61c878SJulian Pullen */ 830c8e26105Sjp static int 8317a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name) 8324aa0a5e7Snw { 8334aa0a5e7Snw if (*value == *new) 8344aa0a5e7Snw return (0); 8354aa0a5e7Snw 836148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 837148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 838148c5f43SAlan Wright *new ? "true" : "false"); 839148c5f43SAlan Wright } 840148c5f43SAlan Wright 8414aa0a5e7Snw *value = *new; 8424aa0a5e7Snw return (1); 8434aa0a5e7Snw } 8444aa0a5e7Snw 84548cd229bSGordon Ross /* 84648cd229bSGordon Ross * This function updates a uint64_t value. 84748cd229bSGordon Ross * If nothing has changed it returns 0 else 1 84848cd229bSGordon Ross */ 84948cd229bSGordon Ross static int 85048cd229bSGordon Ross update_uint64(uint64_t *value, uint64_t *new, char *name) 85148cd229bSGordon Ross { 85248cd229bSGordon Ross if (*value == *new) 85348cd229bSGordon Ross return (0); 85448cd229bSGordon Ross 85548cd229bSGordon Ross if (DBG(CONFIG, 1)) 85648cd229bSGordon Ross idmapdlog(LOG_INFO, "change %s=%llu", name, *new); 85748cd229bSGordon Ross 85848cd229bSGordon Ross *value = *new; 85948cd229bSGordon Ross return (1); 86048cd229bSGordon Ross } 86148cd229bSGordon Ross 8624d61c878SJulian Pullen /* 8634d61c878SJulian Pullen * This function updates a string value. 8644d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 8654d61c878SJulian Pullen */ 8664aa0a5e7Snw static int 8674aa0a5e7Snw update_string(char **value, char **new, char *name) 868c8e26105Sjp { 869148c5f43SAlan Wright int changed; 870148c5f43SAlan Wright 871148c5f43SAlan Wright if (*new == NULL && *value != NULL) 872148c5f43SAlan Wright changed = 1; 873148c5f43SAlan Wright else if (*new != NULL && *value == NULL) 874148c5f43SAlan Wright changed = 1; 875148c5f43SAlan Wright else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0) 876148c5f43SAlan Wright changed = 1; 877148c5f43SAlan Wright else 878148c5f43SAlan Wright changed = 0; 879c8e26105Sjp 880148c5f43SAlan Wright /* 881148c5f43SAlan Wright * Note that even if unchanged we can't just return; we must free one 882148c5f43SAlan Wright * of the values. 883148c5f43SAlan Wright */ 884c8e26105Sjp 885148c5f43SAlan Wright if (DBG(CONFIG, 1) && changed) 886148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new)); 887148c5f43SAlan Wright 888148c5f43SAlan Wright free(*value); 889c8e26105Sjp *value = *new; 890c8e26105Sjp *new = NULL; 891148c5f43SAlan Wright return (changed); 892c8e26105Sjp } 893c8e26105Sjp 894e3f2c991SKeyur Desai static int 895e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map) 896e3f2c991SKeyur Desai { 897e3f2c991SKeyur Desai if (*value == *new) 898e3f2c991SKeyur Desai return (0); 899e3f2c991SKeyur Desai 900148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 901148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 902148c5f43SAlan Wright enum_lookup(*new, map)); 903148c5f43SAlan Wright } 904e3f2c991SKeyur Desai 905e3f2c991SKeyur Desai *value = *new; 906e3f2c991SKeyur Desai 907e3f2c991SKeyur Desai return (1); 908e3f2c991SKeyur Desai } 9094d61c878SJulian Pullen 9104d61c878SJulian Pullen /* 9114d61c878SJulian Pullen * This function updates a directory service structure. 9124d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 9134d61c878SJulian Pullen */ 914c8e26105Sjp static int 915*b3700b07SGordon Ross update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name) 916c8e26105Sjp { 917c8e26105Sjp 9180dcc7149Snw if (*value == *new) 9190dcc7149Snw /* Nothing to do */ 920349d5d8fSnw return (0); 921c8e26105Sjp 9220dcc7149Snw if (*value != NULL && *new != NULL && 9230dcc7149Snw ad_disc_compare_ds(*value, *new) == 0) { 924c8e26105Sjp free(*new); 925c8e26105Sjp *new = NULL; 926349d5d8fSnw return (0); 927c8e26105Sjp } 928c8e26105Sjp 9294d61c878SJulian Pullen if (*value != NULL) 930c8e26105Sjp free(*value); 931c8e26105Sjp 932c8e26105Sjp *value = *new; 933c8e26105Sjp *new = NULL; 9340dcc7149Snw 9350dcc7149Snw if (*value == NULL) { 9360dcc7149Snw /* We're unsetting this DS property */ 937148c5f43SAlan Wright if (DBG(CONFIG, 1)) 938148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 939349d5d8fSnw return (1); 9400dcc7149Snw } 9410dcc7149Snw 942148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 943148c5f43SAlan Wright /* List all the new DSs */ 944*b3700b07SGordon Ross char buf[64]; 945*b3700b07SGordon Ross ad_disc_ds_t *ds; 946*b3700b07SGordon Ross for (ds = *value; ds->host[0] != '\0'; ds++) { 947*b3700b07SGordon Ross if (ad_disc_getnameinfo(buf, sizeof (buf), &ds->addr)) 948*b3700b07SGordon Ross (void) strlcpy(buf, "?", sizeof (buf)); 949*b3700b07SGordon Ross idmapdlog(LOG_INFO, "change %s=%s addr=%s port=%d", 950*b3700b07SGordon Ross name, ds->host, buf, ds->port); 951148c5f43SAlan Wright } 952148c5f43SAlan Wright } 953349d5d8fSnw return (1); 954c8e26105Sjp } 955c8e26105Sjp 9564d61c878SJulian Pullen /* 9574d61c878SJulian Pullen * This function updates a trusted domains structure. 9584d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 9594d61c878SJulian Pullen */ 9604d61c878SJulian Pullen static int 9614d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value, 9624d61c878SJulian Pullen ad_disc_trusteddomains_t **new, char *name) 9634d61c878SJulian Pullen { 9644d61c878SJulian Pullen int i; 9654d61c878SJulian Pullen 9664d61c878SJulian Pullen if (*value == *new) 9674d61c878SJulian Pullen /* Nothing to do */ 9684d61c878SJulian Pullen return (0); 9694d61c878SJulian Pullen 9704d61c878SJulian Pullen if (*value != NULL && *new != NULL && 9714d61c878SJulian Pullen ad_disc_compare_trusteddomains(*value, *new) == 0) { 9724d61c878SJulian Pullen free(*new); 9734d61c878SJulian Pullen *new = NULL; 9744d61c878SJulian Pullen return (0); 9754d61c878SJulian Pullen } 9764d61c878SJulian Pullen 9774d61c878SJulian Pullen if (*value != NULL) 9784d61c878SJulian Pullen free(*value); 9794d61c878SJulian Pullen 9804d61c878SJulian Pullen *value = *new; 9814d61c878SJulian Pullen *new = NULL; 9824d61c878SJulian Pullen 9834d61c878SJulian Pullen if (*value == NULL) { 9844d61c878SJulian Pullen /* We're unsetting this DS property */ 985148c5f43SAlan Wright if (DBG(CONFIG, 1)) 986148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 9874d61c878SJulian Pullen return (1); 9884d61c878SJulian Pullen } 9894d61c878SJulian Pullen 990148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 991148c5f43SAlan Wright /* List all the new domains */ 992148c5f43SAlan Wright for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 993148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s direction=%s", name, 994148c5f43SAlan Wright (*value)[i].domain, 995148c5f43SAlan Wright enum_lookup((*value)[i].direction, trust_dir_map)); 996148c5f43SAlan Wright } 997148c5f43SAlan Wright } 9984d61c878SJulian Pullen return (1); 9994d61c878SJulian Pullen } 10004d61c878SJulian Pullen 10014d61c878SJulian Pullen 10024d61c878SJulian Pullen /* 10034d61c878SJulian Pullen * This function updates a domains in a forest structure. 10044d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 10054d61c878SJulian Pullen */ 10064d61c878SJulian Pullen static int 10074d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value, 10084d61c878SJulian Pullen ad_disc_domainsinforest_t **new, char *name) 10094d61c878SJulian Pullen { 10104d61c878SJulian Pullen int i; 10114d61c878SJulian Pullen 10124d61c878SJulian Pullen if (*value == *new) 10134d61c878SJulian Pullen /* Nothing to do */ 10144d61c878SJulian Pullen return (0); 10154d61c878SJulian Pullen 10164d61c878SJulian Pullen if (*value != NULL && *new != NULL && 10174d61c878SJulian Pullen ad_disc_compare_domainsinforest(*value, *new) == 0) { 10184d61c878SJulian Pullen free(*new); 10194d61c878SJulian Pullen *new = NULL; 10204d61c878SJulian Pullen return (0); 10214d61c878SJulian Pullen } 10224d61c878SJulian Pullen 10234d61c878SJulian Pullen if (*value != NULL) 10244d61c878SJulian Pullen free(*value); 10254d61c878SJulian Pullen 10264d61c878SJulian Pullen *value = *new; 10274d61c878SJulian Pullen *new = NULL; 10284d61c878SJulian Pullen 10294d61c878SJulian Pullen if (*value == NULL) { 10304d61c878SJulian Pullen /* We're unsetting this DS property */ 1031148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1032148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 10334d61c878SJulian Pullen return (1); 10344d61c878SJulian Pullen } 10354d61c878SJulian Pullen 1036148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1037148c5f43SAlan Wright /* List all the new domains */ 1038148c5f43SAlan Wright for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 1039148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 1040148c5f43SAlan Wright (*value)[i].domain); 1041148c5f43SAlan Wright } 1042148c5f43SAlan Wright } 10434d61c878SJulian Pullen return (1); 10444d61c878SJulian Pullen } 10454d61c878SJulian Pullen 10464d61c878SJulian Pullen 10474d61c878SJulian Pullen static void 10484d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values) 10494d61c878SJulian Pullen { 10504d61c878SJulian Pullen int i; 10514d61c878SJulian Pullen 10524d61c878SJulian Pullen for (i = 0; i < *num_values; i++) { 10534d61c878SJulian Pullen free((*value)[i].forest_name); 10544d61c878SJulian Pullen free((*value)[i].global_catalog); 10554d61c878SJulian Pullen free((*value)[i].domains_in_forest); 10564d61c878SJulian Pullen } 10574d61c878SJulian Pullen free(*value); 10584d61c878SJulian Pullen *value = NULL; 10594d61c878SJulian Pullen *num_values = 0; 10604d61c878SJulian Pullen } 10614d61c878SJulian Pullen 10624d61c878SJulian Pullen 10634d61c878SJulian Pullen static int 10644d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1, 10654d61c878SJulian Pullen ad_disc_domainsinforest_t *df2) 10664d61c878SJulian Pullen { 10677a8a68f5SJulian Pullen int i, j; 10687a8a68f5SJulian Pullen int num_df1 = 0; 10697a8a68f5SJulian Pullen int num_df2 = 0; 10707a8a68f5SJulian Pullen boolean_t match; 10714d61c878SJulian Pullen 10724d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) 10734d61c878SJulian Pullen if (df1[i].trusted) 10744d61c878SJulian Pullen num_df1++; 10754d61c878SJulian Pullen 10764d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) 10774d61c878SJulian Pullen if (df2[j].trusted) 10784d61c878SJulian Pullen num_df2++; 10794d61c878SJulian Pullen 10804d61c878SJulian Pullen if (num_df1 != num_df2) 10814d61c878SJulian Pullen return (1); 10824d61c878SJulian Pullen 10834d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) { 10844d61c878SJulian Pullen if (df1[i].trusted) { 10857a8a68f5SJulian Pullen match = B_FALSE; 10864d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) { 10874d61c878SJulian Pullen if (df2[j].trusted && 10881fcced4cSJordan Brown domain_eq(df1[i].domain, df2[j].domain) && 10891fcced4cSJordan Brown strcmp(df1[i].sid, df2[j].sid) == 0) { 10907a8a68f5SJulian Pullen match = B_TRUE; 10914d61c878SJulian Pullen break; 10924d61c878SJulian Pullen } 10934d61c878SJulian Pullen } 10944d61c878SJulian Pullen if (!match) 10954d61c878SJulian Pullen return (1); 10964d61c878SJulian Pullen } 10974d61c878SJulian Pullen } 10984d61c878SJulian Pullen return (0); 10994d61c878SJulian Pullen } 11004d61c878SJulian Pullen 11014d61c878SJulian Pullen 11024d61c878SJulian Pullen 11034d61c878SJulian Pullen /* 11044d61c878SJulian Pullen * This function updates trusted forest structure. 11054d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 11064d61c878SJulian Pullen */ 11074d61c878SJulian Pullen static int 11084d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value, 11094d61c878SJulian Pullen idmap_trustedforest_t **new, int *num_new, char *name) 11104d61c878SJulian Pullen { 11114d61c878SJulian Pullen int i, j; 11127a8a68f5SJulian Pullen boolean_t match; 11134d61c878SJulian Pullen 11144d61c878SJulian Pullen if (*value == *new) 11154d61c878SJulian Pullen /* Nothing to do */ 11164d61c878SJulian Pullen return (0); 11174d61c878SJulian Pullen 11184d61c878SJulian Pullen if (*value != NULL && *new != NULL) { 11194d61c878SJulian Pullen if (*num_value != *num_new) 11204d61c878SJulian Pullen goto not_equal; 11214d61c878SJulian Pullen for (i = 0; i < *num_value; i++) { 11227a8a68f5SJulian Pullen match = B_FALSE; 11234d61c878SJulian Pullen for (j = 0; j < *num_new; j++) { 11244d61c878SJulian Pullen if (strcmp((*value)[i].forest_name, 11254d61c878SJulian Pullen (*new)[j].forest_name) == 0 && 11264d61c878SJulian Pullen ad_disc_compare_ds( 11274d61c878SJulian Pullen (*value)[i].global_catalog, 11281fcced4cSJordan Brown (*new)[j].global_catalog) == 0 && 11294d61c878SJulian Pullen compare_trusteddomainsinforest( 11304d61c878SJulian Pullen (*value)[i].domains_in_forest, 11311fcced4cSJordan Brown (*new)[j].domains_in_forest) == 0) { 11327a8a68f5SJulian Pullen match = B_TRUE; 11334d61c878SJulian Pullen break; 11344d61c878SJulian Pullen } 11354d61c878SJulian Pullen } 11364d61c878SJulian Pullen if (!match) 11374d61c878SJulian Pullen goto not_equal; 11384d61c878SJulian Pullen } 11394d61c878SJulian Pullen free_trusted_forests(new, num_new); 11404d61c878SJulian Pullen return (0); 11414d61c878SJulian Pullen } 11424d61c878SJulian Pullen not_equal: 11434d61c878SJulian Pullen if (*value != NULL) 11444d61c878SJulian Pullen free_trusted_forests(value, num_value); 11454d61c878SJulian Pullen *value = *new; 11464d61c878SJulian Pullen *num_value = *num_new; 11474d61c878SJulian Pullen *new = NULL; 11484d61c878SJulian Pullen *num_new = 0; 11494d61c878SJulian Pullen 11504d61c878SJulian Pullen if (*value == NULL) { 11514d61c878SJulian Pullen /* We're unsetting this DS property */ 1152148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1153148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 11544d61c878SJulian Pullen return (1); 11554d61c878SJulian Pullen } 11564d61c878SJulian Pullen 1157148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1158148c5f43SAlan Wright /* List all the trusted forests */ 1159148c5f43SAlan Wright for (i = 0; i < *num_value; i++) { 1160148c5f43SAlan Wright idmap_trustedforest_t *f = &(*value)[i]; 1161148c5f43SAlan Wright for (j = 0; 1162148c5f43SAlan Wright f->domains_in_forest[j].domain[0] != '\0'; 1163148c5f43SAlan Wright j++) { 1164148c5f43SAlan Wright /* List trusted Domains in the forest. */ 1165148c5f43SAlan Wright if (f->domains_in_forest[j].trusted) 1166148c5f43SAlan Wright idmapdlog(LOG_INFO, 1167148c5f43SAlan Wright "change %s=%s domain=%s", 1168148c5f43SAlan Wright name, f->forest_name, 1169148c5f43SAlan Wright f->domains_in_forest[j].domain); 1170148c5f43SAlan Wright } 1171148c5f43SAlan Wright /* List the hosts */ 1172148c5f43SAlan Wright for (j = 0; 1173148c5f43SAlan Wright f->global_catalog[j].host[0] != '\0'; 1174148c5f43SAlan Wright j++) { 1175148c5f43SAlan Wright idmapdlog(LOG_INFO, 1176148c5f43SAlan Wright "change %s=%s host=%s port=%d", 1177148c5f43SAlan Wright name, f->forest_name, 1178148c5f43SAlan Wright f->global_catalog[j].host, 1179148c5f43SAlan Wright f->global_catalog[j].port); 1180148c5f43SAlan Wright } 11814d61c878SJulian Pullen } 11824d61c878SJulian Pullen } 11834d61c878SJulian Pullen return (1); 11844d61c878SJulian Pullen } 11854d61c878SJulian Pullen 1186e3f2c991SKeyur Desai const char * 1187e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map) 1188e3f2c991SKeyur Desai { 1189e3f2c991SKeyur Desai for (; map->string != NULL; map++) { 1190e3f2c991SKeyur Desai if (value == map->value) { 1191e3f2c991SKeyur Desai return (map->string); 1192e3f2c991SKeyur Desai } 1193e3f2c991SKeyur Desai } 1194e3f2c991SKeyur Desai return ("(invalid)"); 1195e3f2c991SKeyur Desai } 1196c8e26105Sjp 1197c8e26105Sjp /* 11980dcc7149Snw * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the 11990dcc7149Snw * interfaces. 1200c8e26105Sjp * 12010dcc7149Snw * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON. 1202c8e26105Sjp */ 1203c8e26105Sjp static 1204c5866007SKeyur Desai boolean_t 12050dcc7149Snw pfroute_event_is_interesting(int rt_sock) 1206c8e26105Sjp { 12070dcc7149Snw int nbytes; 12080dcc7149Snw int64_t msg[2048 / 8]; 12090dcc7149Snw struct rt_msghdr *rtm; 1210c5866007SKeyur Desai boolean_t is_interesting = B_FALSE; 1211c8e26105Sjp 12120dcc7149Snw for (;;) { 12130dcc7149Snw if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0) 12140dcc7149Snw break; 12150dcc7149Snw rtm = (struct rt_msghdr *)msg; 12160dcc7149Snw if (rtm->rtm_version != RTM_VERSION) 12170dcc7149Snw continue; 12180dcc7149Snw if (nbytes < rtm->rtm_msglen) 12190dcc7149Snw continue; 12200dcc7149Snw switch (rtm->rtm_type) { 12210dcc7149Snw case RTM_NEWADDR: 12220dcc7149Snw case RTM_DELADDR: 12230dcc7149Snw case RTM_IFINFO: 1224c5866007SKeyur Desai is_interesting = B_TRUE; 12250dcc7149Snw break; 12260dcc7149Snw default: 12270dcc7149Snw break; 12280dcc7149Snw } 1229c8e26105Sjp } 12300dcc7149Snw return (is_interesting); 12310dcc7149Snw } 12320dcc7149Snw 12330dcc7149Snw /* 1234c5866007SKeyur Desai * Wait for an event, and report what kind of event occurred. 12350dcc7149Snw * 1236c5866007SKeyur Desai * Note that there are cases where we are awoken but don't care about 1237c5866007SKeyur Desai * the lower-level event. We can't just loop here because we can't 1238c5866007SKeyur Desai * readily calculate how long to sleep the next time. We return 1239c5866007SKeyur Desai * EVENT_NOTHING and let the caller loop. 12400dcc7149Snw */ 12410dcc7149Snw static 1242c5866007SKeyur Desai enum event_type 1243c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp) 12440dcc7149Snw { 12450dcc7149Snw port_event_t pe; 1246c8e26105Sjp 1247148c5f43SAlan Wright (void) memset(&pe, 0, sizeof (pe)); 1248349d5d8fSnw if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) { 1249c8e26105Sjp switch (errno) { 1250c8e26105Sjp case EINTR: 1251c5866007SKeyur Desai return (EVENT_NOTHING); 1252c8e26105Sjp case ETIME: 1253c8e26105Sjp /* Timeout */ 1254c5866007SKeyur Desai return (EVENT_TIMEOUT); 1255c8e26105Sjp default: 12560dcc7149Snw /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */ 12570dcc7149Snw idmapdlog(LOG_ERR, "Event port failed: %s", 12580dcc7149Snw strerror(errno)); 12590dcc7149Snw exit(1); 12600dcc7149Snw /* NOTREACHED */ 1261c8e26105Sjp } 1262c8e26105Sjp } 1263c8e26105Sjp 12640dcc7149Snw 1265c5866007SKeyur Desai switch (pe.portev_source) { 1266c5866007SKeyur Desai case 0: 12670dcc7149Snw /* 1268c5866007SKeyur Desai * This isn't documented, but seems to be what you get if 1269c5866007SKeyur Desai * the timeout is zero seconds and there are no events 1270c5866007SKeyur Desai * pending. 12710dcc7149Snw */ 1272c5866007SKeyur Desai return (EVENT_TIMEOUT); 1273c8e26105Sjp 1274c5866007SKeyur Desai case PORT_SOURCE_USER: 1275*b3700b07SGordon Ross switch (pe.portev_events) { 1276*b3700b07SGordon Ross case RECONFIGURE: 1277c5866007SKeyur Desai return (EVENT_REFRESH); 1278*b3700b07SGordon Ross case POKE_AUTO_DISCOVERY: 1279*b3700b07SGordon Ross return (EVENT_POKED); 1280*b3700b07SGordon Ross case KICK_AUTO_DISCOVERY: 1281*b3700b07SGordon Ross return (EVENT_KICKED); 1282*b3700b07SGordon Ross } 1283*b3700b07SGordon Ross return (EVENT_NOTHING); 1284e3c2d6aaSnw 1285c5866007SKeyur Desai case PORT_SOURCE_FD: 1286c5866007SKeyur Desai if (pe.portev_object == rt_sock) { 1287c5866007SKeyur Desai /* 1288c5866007SKeyur Desai * PF_ROUTE socket read event: 1289c5866007SKeyur Desai * re-associate fd 1290c5866007SKeyur Desai * handle event 1291c5866007SKeyur Desai */ 1292c5866007SKeyur Desai if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 1293c5866007SKeyur Desai rt_sock, POLLIN, NULL) != 0) { 1294c5866007SKeyur Desai idmapdlog(LOG_ERR, "Failed to re-associate the " 1295c5866007SKeyur Desai "routing socket with the event port: %s", 1296c5866007SKeyur Desai strerror(errno)); 1297c5866007SKeyur Desai abort(); 1298c5866007SKeyur Desai } 1299c5866007SKeyur Desai /* 1300c5866007SKeyur Desai * The network configuration may still be in flux. 1301c5866007SKeyur Desai * No matter, the resolver will re-transmit and 1302c5866007SKeyur Desai * timeout if need be. 1303c5866007SKeyur Desai */ 1304c5866007SKeyur Desai if (pfroute_event_is_interesting(rt_sock)) { 1305148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1306148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1307148c5f43SAlan Wright "Interesting routing event"); 1308148c5f43SAlan Wright } 1309c5866007SKeyur Desai return (EVENT_ROUTING); 1310c5866007SKeyur Desai } else { 1311148c5f43SAlan Wright if (DBG(CONFIG, 2)) { 1312148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1313148c5f43SAlan Wright "Boring routing event"); 1314148c5f43SAlan Wright } 1315c5866007SKeyur Desai return (EVENT_NOTHING); 1316c5866007SKeyur Desai } 1317349d5d8fSnw } 1318c5866007SKeyur Desai /* Event on an FD other than the routing FD? Ignore it. */ 1319c5866007SKeyur Desai break; 1320c8e26105Sjp } 1321c8e26105Sjp 1322c5866007SKeyur Desai return (EVENT_NOTHING); 1323c8e26105Sjp } 1324c8e26105Sjp 1325c8e26105Sjp void * 1326c8e26105Sjp idmap_cfg_update_thread(void *arg) 1327c8e26105Sjp { 1328148c5f43SAlan Wright NOTE(ARGUNUSED(arg)) 1329*b3700b07SGordon Ross idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg; 1330c5866007SKeyur Desai const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx; 1331*b3700b07SGordon Ross int flags = CFG_DISCOVER; 13320dcc7149Snw 1333c5866007SKeyur Desai for (;;) { 1334c5866007SKeyur Desai struct timespec timeout; 1335c5866007SKeyur Desai struct timespec *timeoutp; 1336c5866007SKeyur Desai int rc; 1337*b3700b07SGordon Ross int ttl, max_ttl; 13380dcc7149Snw 13390dcc7149Snw (void) ad_disc_SubnetChanged(ad_ctx); 1340c8e26105Sjp 1341*b3700b07SGordon Ross rc = idmap_cfg_load(_idmapdstate.cfg, flags); 1342c5866007SKeyur Desai if (rc < -1) { 13437a8a68f5SJulian Pullen idmapdlog(LOG_ERR, "Fatal errors while reading " 1344349d5d8fSnw "SMF properties"); 1345349d5d8fSnw exit(1); 1346c5866007SKeyur Desai } else if (rc == -1) { 1347c5866007SKeyur Desai idmapdlog(LOG_WARNING, 1348c5866007SKeyur Desai "Errors re-loading configuration may cause AD " 1349c5866007SKeyur Desai "lookups to fail"); 1350349d5d8fSnw } 1351c8e26105Sjp 1352c5866007SKeyur Desai /* 1353c5866007SKeyur Desai * Wait for an interesting event. Note that we might get 1354c5866007SKeyur Desai * boring events between interesting events. If so, we loop. 1355c5866007SKeyur Desai */ 1356*b3700b07SGordon Ross flags = CFG_DISCOVER; 1357c5866007SKeyur Desai for (;;) { 1358*b3700b07SGordon Ross /* 1359*b3700b07SGordon Ross * If we don't know our domain name, don't bother 1360*b3700b07SGordon Ross * with rediscovery until the next config change. 1361*b3700b07SGordon Ross * Avoids hourly noise in workgroup mode. 1362*b3700b07SGordon Ross */ 1363*b3700b07SGordon Ross if (pgcfg->domain_name == NULL) 1364*b3700b07SGordon Ross ttl = -1; 1365*b3700b07SGordon Ross else 1366*b3700b07SGordon Ross ttl = ad_disc_get_TTL(ad_ctx); 1367c5866007SKeyur Desai if (ttl < 0) { 1368c5866007SKeyur Desai timeoutp = NULL; 1369c5866007SKeyur Desai } else { 1370*b3700b07SGordon Ross max_ttl = (int)pgcfg->rediscovery_interval; 1371*b3700b07SGordon Ross if (ttl > max_ttl) 1372*b3700b07SGordon Ross ttl = max_ttl; 1373*b3700b07SGordon Ross if (ttl < MIN_REDISCOVERY_INTERVAL) 1374*b3700b07SGordon Ross ttl = MIN_REDISCOVERY_INTERVAL; 1375c5866007SKeyur Desai timeout.tv_sec = ttl; 1376c5866007SKeyur Desai timeout.tv_nsec = 0; 1377*b3700b07SGordon Ross timeoutp = &timeout; 1378c5866007SKeyur Desai } 1379c5866007SKeyur Desai 1380*b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1381*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, 1382*b3700b07SGordon Ross "_cfg_update_thread waiting"); 1383*b3700b07SGordon Ross 1384c5866007SKeyur Desai switch (wait_for_event(timeoutp)) { 1385c5866007SKeyur Desai case EVENT_NOTHING: 1386148c5f43SAlan Wright if (DBG(CONFIG, 2)) 1387148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "Boring event."); 1388c5866007SKeyur Desai continue; 1389c5866007SKeyur Desai case EVENT_REFRESH: 1390148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1391148c5f43SAlan Wright idmapdlog(LOG_INFO, "SMF refresh"); 1392*b3700b07SGordon Ross /* 1393*b3700b07SGordon Ross * Forget any DC we had previously. 1394*b3700b07SGordon Ross */ 1395*b3700b07SGordon Ross flags |= CFG_FORGET_DC; 1396*b3700b07SGordon Ross 1397c5866007SKeyur Desai /* 1398c5866007SKeyur Desai * Blow away the ccache, we might have 1399c5866007SKeyur Desai * re-joined the domain or joined a new one 1400c5866007SKeyur Desai */ 1401c5866007SKeyur Desai (void) unlink(IDMAP_CACHEDIR "/ccache"); 1402c5866007SKeyur Desai break; 1403*b3700b07SGordon Ross case EVENT_POKED: 1404*b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1405*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "poked"); 1406*b3700b07SGordon Ross break; 1407*b3700b07SGordon Ross case EVENT_KICKED: 1408*b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1409*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "kicked"); 1410*b3700b07SGordon Ross flags |= CFG_FORGET_DC; 1411c5866007SKeyur Desai break; 1412c5866007SKeyur Desai case EVENT_TIMEOUT: 1413148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1414148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "TTL expired"); 1415c5866007SKeyur Desai break; 1416c5866007SKeyur Desai case EVENT_ROUTING: 1417c5866007SKeyur Desai /* Already logged to DEBUG */ 1418c5866007SKeyur Desai break; 1419c5866007SKeyur Desai } 1420c5866007SKeyur Desai /* An interesting event! */ 1421c5866007SKeyur Desai break; 1422c5866007SKeyur Desai } 1423c8e26105Sjp } 1424c5866007SKeyur Desai /* 1425c5866007SKeyur Desai * Lint isn't happy with the concept of a function declared to 1426c5866007SKeyur Desai * return something, that doesn't return. Of course, merely adding 1427c5866007SKeyur Desai * the return isn't enough, because it's never reached... 1428c5866007SKeyur Desai */ 1429c8e26105Sjp /*NOTREACHED*/ 1430c8e26105Sjp return (NULL); 1431c8e26105Sjp } 1432c8e26105Sjp 1433c8e26105Sjp int 14340dcc7149Snw idmap_cfg_start_updates(void) 1435c8e26105Sjp { 14360dcc7149Snw if ((idmapd_ev_port = port_create()) < 0) { 143771590c90Snw idmapdlog(LOG_ERR, "Failed to create event port: %s", 143871590c90Snw strerror(errno)); 1439c8e26105Sjp return (-1); 14400dcc7149Snw } 14410dcc7149Snw 14420dcc7149Snw if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 144371590c90Snw idmapdlog(LOG_ERR, "Failed to open routing socket: %s", 144471590c90Snw strerror(errno)); 14450dcc7149Snw (void) close(idmapd_ev_port); 14460dcc7149Snw return (-1); 14470dcc7149Snw } 14480dcc7149Snw 14490dcc7149Snw if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) { 145071590c90Snw idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s", 145171590c90Snw strerror(errno)); 14520dcc7149Snw (void) close(rt_sock); 14530dcc7149Snw (void) close(idmapd_ev_port); 14540dcc7149Snw return (-1); 14550dcc7149Snw } 14560dcc7149Snw 14570dcc7149Snw if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 14580dcc7149Snw rt_sock, POLLIN, NULL) != 0) { 145971590c90Snw idmapdlog(LOG_ERR, "Failed to associate the routing " 146071590c90Snw "socket with the event port: %s", strerror(errno)); 14610dcc7149Snw (void) close(rt_sock); 14620dcc7149Snw (void) close(idmapd_ev_port); 14630dcc7149Snw return (-1); 14640dcc7149Snw } 14650dcc7149Snw 14660dcc7149Snw if ((errno = pthread_create(&update_thread_handle, NULL, 14670dcc7149Snw idmap_cfg_update_thread, NULL)) != 0) { 146871590c90Snw idmapdlog(LOG_ERR, "Failed to start update thread: %s", 146971590c90Snw strerror(errno)); 14700dcc7149Snw (void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock); 14710dcc7149Snw (void) close(rt_sock); 14720dcc7149Snw (void) close(idmapd_ev_port); 14730dcc7149Snw return (-1); 14740dcc7149Snw } 14750dcc7149Snw 14760dcc7149Snw return (0); 1477c8e26105Sjp } 1478c8e26105Sjp 1479479ac375Sdm /* 1480479ac375Sdm * Reject attribute names with invalid characters. 1481479ac375Sdm */ 1482479ac375Sdm static 1483479ac375Sdm int 1484479ac375Sdm valid_ldap_attr(const char *attr) { 1485479ac375Sdm for (; *attr; attr++) { 1486479ac375Sdm if (!isalnum(*attr) && *attr != '-' && 1487479ac375Sdm *attr != '_' && *attr != '.' && *attr != ';') 1488479ac375Sdm return (0); 1489479ac375Sdm } 1490479ac375Sdm return (1); 1491479ac375Sdm } 1492479ac375Sdm 1493e3f2c991SKeyur Desai static 1494148c5f43SAlan Wright void 1495148c5f43SAlan Wright idmapd_set_debug( 1496148c5f43SAlan Wright idmap_cfg_handles_t *handles, 1497148c5f43SAlan Wright enum idmapd_debug item, 1498148c5f43SAlan Wright const char *name) 1499e3f2c991SKeyur Desai { 1500148c5f43SAlan Wright int val; 1501e3f2c991SKeyur Desai 1502148c5f43SAlan Wright if (item < 0 || item > IDMAPD_DEBUG_MAX) 1503148c5f43SAlan Wright return; 1504e3f2c991SKeyur Desai 1505148c5f43SAlan Wright val = get_debug(handles, name); 1506e3f2c991SKeyur Desai 1507148c5f43SAlan Wright if (val != _idmapdstate.debug[item]) 1508148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val); 1509148c5f43SAlan Wright 1510148c5f43SAlan Wright _idmapdstate.debug[item] = val; 1511148c5f43SAlan Wright } 1512148c5f43SAlan Wright 1513148c5f43SAlan Wright static 1514148c5f43SAlan Wright void 1515148c5f43SAlan Wright check_smf_debug_mode(idmap_cfg_handles_t *handles) 1516148c5f43SAlan Wright { 1517148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all"); 1518148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config"); 1519148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping"); 1520148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery"); 1521148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns"); 1522148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap"); 1523148c5f43SAlan Wright 1524148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]); 1525148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]); 1526148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]); 1527148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]); 1528e3f2c991SKeyur Desai } 1529e3f2c991SKeyur Desai 1530349d5d8fSnw /* 1531349d5d8fSnw * This is the half of idmap_cfg_load() that loads property values from 1532349d5d8fSnw * SMF (using the config/ property group of the idmap FMRI). 1533349d5d8fSnw * 1534349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1535479ac375Sdm * -3 -> hard smf config failures 1536349d5d8fSnw * reading from SMF. 1537349d5d8fSnw */ 1538*b3700b07SGordon Ross static int 1539349d5d8fSnw idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, 1540e3f2c991SKeyur Desai int * const errors) 1541c5c4113dSnw { 1542e3c2d6aaSnw int rc; 1543e3f2c991SKeyur Desai char *s; 1544e3f2c991SKeyur Desai 1545e3f2c991SKeyur Desai *errors = 0; 1546c8e26105Sjp 1547c8e26105Sjp if (scf_pg_update(handles->config_pg) < 0) { 154871590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 154971590c90Snw scf_strerror(scf_error())); 1550349d5d8fSnw return (-2); 1551c5c4113dSnw } 1552c5c4113dSnw 1553148c5f43SAlan Wright if (scf_pg_update(handles->debug_pg) < 0) { 155471590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 155571590c90Snw scf_strerror(scf_error())); 1556349d5d8fSnw return (-2); 1557c5c4113dSnw } 1558c5c4113dSnw 1559148c5f43SAlan Wright check_smf_debug_mode(handles); 1560148c5f43SAlan Wright 1561148c5f43SAlan Wright rc = get_val_bool(handles, "unresolvable_sid_mapping", 1562148c5f43SAlan Wright &pgcfg->eph_map_unres_sids, B_TRUE); 1563479ac375Sdm if (rc != 0) 1564e3f2c991SKeyur Desai (*errors)++; 156571590c90Snw 15661ed6b69aSGordon Ross rc = get_val_bool(handles, "use_ads", 15671ed6b69aSGordon Ross &pgcfg->use_ads, B_TRUE); 15681ed6b69aSGordon Ross if (rc != 0) 15691ed6b69aSGordon Ross (*errors)++; 15701ed6b69aSGordon Ross 1571148c5f43SAlan Wright rc = get_val_bool(handles, "use_lsa", 1572148c5f43SAlan Wright &pgcfg->use_lsa, B_TRUE); 1573148c5f43SAlan Wright if (rc != 0) 1574148c5f43SAlan Wright (*errors)++; 1575148c5f43SAlan Wright 1576148c5f43SAlan Wright rc = get_val_bool(handles, "disable_cross_forest_trusts", 1577148c5f43SAlan Wright &pgcfg->disable_cross_forest_trusts, B_TRUE); 15784aa0a5e7Snw if (rc != 0) 1579e3f2c991SKeyur Desai (*errors)++; 1580e3f2c991SKeyur Desai 1581e3f2c991SKeyur Desai rc = get_val_astring(handles, "directory_based_mapping", &s); 1582e3f2c991SKeyur Desai if (rc != 0) 1583e3f2c991SKeyur Desai (*errors)++; 1584e3f2c991SKeyur Desai else if (s == NULL || strcasecmp(s, "none") == 0) 1585e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1586e3f2c991SKeyur Desai else if (strcasecmp(s, "name") == 0) 1587e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME; 1588e3f2c991SKeyur Desai else if (strcasecmp(s, "idmu") == 0) 1589e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU; 1590e3f2c991SKeyur Desai else { 1591e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1592e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 1593e3f2c991SKeyur Desai "config/directory_based_mapping: invalid value \"%s\" ignored", 1594e3f2c991SKeyur Desai s); 1595e3f2c991SKeyur Desai (*errors)++; 1596e3f2c991SKeyur Desai } 1597e3f2c991SKeyur Desai free(s); 15984aa0a5e7Snw 1599c8e26105Sjp rc = get_val_int(handles, "list_size_limit", 1600c8e26105Sjp &pgcfg->list_size_limit, SCF_TYPE_COUNT); 16014aa0a5e7Snw if (rc != 0) 1602e3f2c991SKeyur Desai (*errors)++; 1603c5c4113dSnw 160448cd229bSGordon Ross rc = get_val_int(handles, "id_cache_timeout", 160548cd229bSGordon Ross &pgcfg->id_cache_timeout, SCF_TYPE_COUNT); 160648cd229bSGordon Ross if (rc != 0) 160748cd229bSGordon Ross (*errors)++; 160848cd229bSGordon Ross if (pgcfg->id_cache_timeout == 0) 160948cd229bSGordon Ross pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT; 161048cd229bSGordon Ross 161148cd229bSGordon Ross rc = get_val_int(handles, "name_cache_timeout", 161248cd229bSGordon Ross &pgcfg->name_cache_timeout, SCF_TYPE_COUNT); 161348cd229bSGordon Ross if (rc != 0) 161448cd229bSGordon Ross (*errors)++; 161548cd229bSGordon Ross if (pgcfg->name_cache_timeout == 0) 161648cd229bSGordon Ross pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT; 161748cd229bSGordon Ross 1618*b3700b07SGordon Ross rc = get_val_int(handles, "rediscovery_interval", 1619*b3700b07SGordon Ross &pgcfg->rediscovery_interval, SCF_TYPE_COUNT); 1620*b3700b07SGordon Ross if (rc != 0) 1621*b3700b07SGordon Ross (*errors)++; 1622*b3700b07SGordon Ross if (pgcfg->rediscovery_interval == 0) 1623*b3700b07SGordon Ross pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT; 1624*b3700b07SGordon Ross 1625c8e26105Sjp rc = get_val_astring(handles, "domain_name", 1626c8e26105Sjp &pgcfg->domain_name); 1627e3c2d6aaSnw if (rc != 0) 1628e3f2c991SKeyur Desai (*errors)++; 16294d61c878SJulian Pullen else { 1630148c5f43SAlan Wright if (pgcfg->domain_name != NULL && 1631148c5f43SAlan Wright pgcfg->domain_name[0] == '\0') { 1632148c5f43SAlan Wright free(pgcfg->domain_name); 1633148c5f43SAlan Wright pgcfg->domain_name = NULL; 1634148c5f43SAlan Wright } 1635349d5d8fSnw (void) ad_disc_set_DomainName(handles->ad_ctx, 1636349d5d8fSnw pgcfg->domain_name); 16377a8a68f5SJulian Pullen pgcfg->domain_name_auto_disc = B_FALSE; 16384d61c878SJulian Pullen } 1639c8e26105Sjp 1640c8e26105Sjp rc = get_val_astring(handles, "default_domain", 1641c8e26105Sjp &pgcfg->default_domain); 1642c8e26105Sjp if (rc != 0) { 1643e3c2d6aaSnw /* 1644e3c2d6aaSnw * SCF failures fetching config/default_domain we treat 1645e3c2d6aaSnw * as fatal as they may leave ID mapping rules that 1646e3c2d6aaSnw * match unqualified winnames flapping in the wind. 1647e3c2d6aaSnw */ 1648349d5d8fSnw return (-2); 1649c8e26105Sjp } 1650c8e26105Sjp 1651e3f2c991SKeyur Desai if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) { 1652e3f2c991SKeyur Desai pgcfg->default_domain = strdup(pgcfg->domain_name); 1653c5c4113dSnw } 1654c5c4113dSnw 1655*b3700b07SGordon Ross rc = get_val_astring(handles, "domain_guid", &s); 1656*b3700b07SGordon Ross if (rc != 0) { 1657*b3700b07SGordon Ross (*errors)++; 1658*b3700b07SGordon Ross } else if (s == NULL || s[0] == '\0') { 1659*b3700b07SGordon Ross /* OK, not set. */ 1660*b3700b07SGordon Ross free(s); 1661*b3700b07SGordon Ross } else { 1662*b3700b07SGordon Ross uuid_t u; 1663*b3700b07SGordon Ross 1664*b3700b07SGordon Ross if (uuid_parse(s, u) != 0) { 1665*b3700b07SGordon Ross idmapdlog(LOG_ERR, 1666*b3700b07SGordon Ross "config/domain_guid: invalid value \"%s\" ignored", s); 1667*b3700b07SGordon Ross free(s); 1668*b3700b07SGordon Ross (*errors)++; 1669*b3700b07SGordon Ross } else { 1670*b3700b07SGordon Ross pgcfg->domain_guid = s; 1671*b3700b07SGordon Ross pgcfg->domain_guid_auto_disc = B_FALSE; 1672*b3700b07SGordon Ross (void) ad_disc_set_DomainGUID(handles->ad_ctx, u); 1673*b3700b07SGordon Ross } 1674*b3700b07SGordon Ross } 1675*b3700b07SGordon Ross 167612b65585SGordon Ross rc = get_val_astring(handles, "machine_uuid", &pgcfg->machine_uuid); 167712b65585SGordon Ross if (rc != 0) 167812b65585SGordon Ross (*errors)++; 167912b65585SGordon Ross if (pgcfg->machine_uuid == NULL) { 168012b65585SGordon Ross /* If machine_uuid not configured, generate one */ 168112b65585SGordon Ross if (generate_machine_uuid(&pgcfg->machine_uuid) < 0) 168212b65585SGordon Ross return (-2); 168312b65585SGordon Ross rc = set_val_astring(handles, handles->config_pg, 168412b65585SGordon Ross "machine_uuid", pgcfg->machine_uuid); 168512b65585SGordon Ross if (rc != 0) 168612b65585SGordon Ross (*errors)++; 168712b65585SGordon Ross } 168812b65585SGordon Ross 1689c8e26105Sjp rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); 1690e3c2d6aaSnw if (rc != 0) 1691e3f2c991SKeyur Desai (*errors)++; 1692c8e26105Sjp if (pgcfg->machine_sid == NULL) { 169312b65585SGordon Ross /* 169412b65585SGordon Ross * If machine_sid not configured, generate one 169512b65585SGordon Ross * from the machine UUID. 169612b65585SGordon Ross */ 169712b65585SGordon Ross if (generate_machine_sid(&pgcfg->machine_sid, 169812b65585SGordon Ross pgcfg->machine_uuid) < 0) 1699349d5d8fSnw return (-2); 1700148c5f43SAlan Wright rc = set_val_astring(handles, handles->config_pg, 1701148c5f43SAlan Wright "machine_sid", pgcfg->machine_sid); 1702e3c2d6aaSnw if (rc != 0) 1703e3f2c991SKeyur Desai (*errors)++; 17048edda628Sbaban } 1705c5c4113dSnw 1706c8e26105Sjp rc = get_val_ds(handles, "domain_controller", 389, 1707c8e26105Sjp &pgcfg->domain_controller); 1708e3c2d6aaSnw if (rc != 0) 1709e3f2c991SKeyur Desai (*errors)++; 17104d61c878SJulian Pullen else { 1711349d5d8fSnw (void) ad_disc_set_DomainController(handles->ad_ctx, 1712e3c2d6aaSnw pgcfg->domain_controller); 17137a8a68f5SJulian Pullen pgcfg->domain_controller_auto_disc = B_FALSE; 17144d61c878SJulian Pullen } 1715c5c4113dSnw 1716*b3700b07SGordon Ross rc = get_val_ds(handles, "preferred_dc", 389, 1717*b3700b07SGordon Ross &pgcfg->preferred_dc); 1718*b3700b07SGordon Ross if (rc != 0) 1719*b3700b07SGordon Ross (*errors)++; 1720*b3700b07SGordon Ross else { 1721*b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(handles->ad_ctx, 1722*b3700b07SGordon Ross pgcfg->preferred_dc); 1723*b3700b07SGordon Ross pgcfg->preferred_dc_auto_disc = B_FALSE; 1724*b3700b07SGordon Ross } 1725*b3700b07SGordon Ross 1726c8e26105Sjp rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); 1727e3c2d6aaSnw if (rc != 0) 1728e3f2c991SKeyur Desai (*errors)++; 17294d61c878SJulian Pullen else { 1730349d5d8fSnw (void) ad_disc_set_ForestName(handles->ad_ctx, 1731349d5d8fSnw pgcfg->forest_name); 17327a8a68f5SJulian Pullen pgcfg->forest_name_auto_disc = B_FALSE; 17334d61c878SJulian Pullen } 1734c8e26105Sjp 1735c8e26105Sjp rc = get_val_astring(handles, "site_name", &pgcfg->site_name); 1736e3c2d6aaSnw if (rc != 0) 1737e3f2c991SKeyur Desai (*errors)++; 1738e3c2d6aaSnw else 1739349d5d8fSnw (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name); 1740c8e26105Sjp 1741c8e26105Sjp rc = get_val_ds(handles, "global_catalog", 3268, 1742c8e26105Sjp &pgcfg->global_catalog); 1743e3c2d6aaSnw if (rc != 0) 1744e3f2c991SKeyur Desai (*errors)++; 17454d61c878SJulian Pullen else { 1746349d5d8fSnw (void) ad_disc_set_GlobalCatalog(handles->ad_ctx, 1747349d5d8fSnw pgcfg->global_catalog); 17487a8a68f5SJulian Pullen pgcfg->global_catalog_auto_disc = B_FALSE; 17494d61c878SJulian Pullen } 1750c8e26105Sjp 1751e3f2c991SKeyur Desai /* Unless we're doing directory-based name mapping, we're done. */ 1752e3f2c991SKeyur Desai if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME) 1753e3f2c991SKeyur Desai return (0); 1754e8c27ec8Sbaban 1755349d5d8fSnw rc = get_val_astring(handles, "ad_unixuser_attr", 1756349d5d8fSnw &pgcfg->ad_unixuser_attr); 1757349d5d8fSnw if (rc != 0) 1758349d5d8fSnw return (-2); 1759479ac375Sdm if (pgcfg->ad_unixuser_attr != NULL && 1760479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixuser_attr)) { 1761479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a " 1762479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixuser_attr); 1763479ac375Sdm return (-3); 1764479ac375Sdm } 1765e8c27ec8Sbaban 1766349d5d8fSnw rc = get_val_astring(handles, "ad_unixgroup_attr", 1767349d5d8fSnw &pgcfg->ad_unixgroup_attr); 1768349d5d8fSnw if (rc != 0) 1769349d5d8fSnw return (-2); 1770479ac375Sdm if (pgcfg->ad_unixgroup_attr != NULL && 1771479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) { 1772479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a " 1773479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixgroup_attr); 1774479ac375Sdm return (-3); 1775479ac375Sdm } 1776e8c27ec8Sbaban 1777349d5d8fSnw rc = get_val_astring(handles, "nldap_winname_attr", 1778349d5d8fSnw &pgcfg->nldap_winname_attr); 1779349d5d8fSnw if (rc != 0) 1780349d5d8fSnw return (-2); 1781479ac375Sdm if (pgcfg->nldap_winname_attr != NULL && 1782479ac375Sdm !valid_ldap_attr(pgcfg->nldap_winname_attr)) { 1783479ac375Sdm idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a " 1784479ac375Sdm "valid LDAP attribute name", pgcfg->nldap_winname_attr); 1785349d5d8fSnw return (-3); 1786e8c27ec8Sbaban } 1787349d5d8fSnw if (pgcfg->ad_unixuser_attr == NULL && 1788479ac375Sdm pgcfg->ad_unixgroup_attr == NULL && 1789479ac375Sdm pgcfg->nldap_winname_attr == NULL) { 1790349d5d8fSnw idmapdlog(LOG_ERR, 1791e3f2c991SKeyur Desai "If config/directory_based_mapping property is set to " 1792e3f2c991SKeyur Desai "\"name\" then at least one of the following name mapping " 1793349d5d8fSnw "attributes must be specified. (config/ad_unixuser_attr OR " 1794479ac375Sdm "config/ad_unixgroup_attr OR config/nldap_winname_attr)"); 1795349d5d8fSnw return (-3); 1796349d5d8fSnw } 1797c8e26105Sjp 1798349d5d8fSnw return (rc); 1799349d5d8fSnw } 1800349d5d8fSnw 1801148c5f43SAlan Wright static 1802148c5f43SAlan Wright void 1803148c5f43SAlan Wright log_if_unable(const void *val, const char *what) 1804148c5f43SAlan Wright { 1805148c5f43SAlan Wright if (val == NULL) { 1806148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "unable to discover %s", what); 1807148c5f43SAlan Wright } 1808148c5f43SAlan Wright } 18094d61c878SJulian Pullen 1810349d5d8fSnw static 1811349d5d8fSnw void 1812148c5f43SAlan Wright discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx) 1813349d5d8fSnw { 18144d61c878SJulian Pullen ad_disc_t trusted_ctx; 18154d61c878SJulian Pullen int i, j, k, l; 18164d61c878SJulian Pullen char *forestname; 18174d61c878SJulian Pullen int num_trusteddomains; 18187a8a68f5SJulian Pullen boolean_t new_forest; 18194d61c878SJulian Pullen char *trusteddomain; 1820*b3700b07SGordon Ross ad_disc_ds_t *globalcatalog; 18214d61c878SJulian Pullen idmap_trustedforest_t *trustedforests; 18224d61c878SJulian Pullen ad_disc_domainsinforest_t *domainsinforest; 1823349d5d8fSnw 18244d61c878SJulian Pullen pgcfg->trusted_domains = 18254d61c878SJulian Pullen ad_disc_get_TrustedDomains(ad_ctx, NULL); 18264d61c878SJulian Pullen 18274d61c878SJulian Pullen if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL && 18284d61c878SJulian Pullen pgcfg->trusted_domains[0].domain[0] != '\0') { 18294d61c878SJulian Pullen /* 18304d61c878SJulian Pullen * We have trusted domains. We need to go through every 18314d61c878SJulian Pullen * one and find its forest. If it is a new forest we then need 18324d61c878SJulian Pullen * to find its Global Catalog and the domains in the forest 18334d61c878SJulian Pullen */ 18344d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) 18354d61c878SJulian Pullen continue; 18364d61c878SJulian Pullen num_trusteddomains = i; 18374d61c878SJulian Pullen 18384d61c878SJulian Pullen trustedforests = calloc(num_trusteddomains, 18394d61c878SJulian Pullen sizeof (idmap_trustedforest_t)); 18404d61c878SJulian Pullen j = 0; 18414d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) { 18424d61c878SJulian Pullen trusteddomain = pgcfg->trusted_domains[i].domain; 18434d61c878SJulian Pullen trusted_ctx = ad_disc_init(); 1844148c5f43SAlan Wright (void) ad_disc_set_DomainName(trusted_ctx, 18454d61c878SJulian Pullen trusteddomain); 18464d61c878SJulian Pullen forestname = 18474d61c878SJulian Pullen ad_disc_get_ForestName(trusted_ctx, NULL); 18484d61c878SJulian Pullen if (forestname == NULL) { 1849148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1850148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1851148c5f43SAlan Wright "unable to discover Forest Name" 1852148c5f43SAlan Wright " for the trusted domain %s", 1853148c5f43SAlan Wright trusteddomain); 1854148c5f43SAlan Wright } 18554d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 18564d61c878SJulian Pullen continue; 18574d61c878SJulian Pullen } 18584d61c878SJulian Pullen 18594d61c878SJulian Pullen if (strcasecmp(forestname, pgcfg->forest_name) == 0) { 18604d61c878SJulian Pullen /* 18614d61c878SJulian Pullen * Ignore the domain as it is part of 18624d61c878SJulian Pullen * the primary forest 18634d61c878SJulian Pullen */ 18644d61c878SJulian Pullen free(forestname); 18654d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 18664d61c878SJulian Pullen continue; 18674d61c878SJulian Pullen } 18684d61c878SJulian Pullen 18694d61c878SJulian Pullen /* Is this a new forest? */ 18707a8a68f5SJulian Pullen new_forest = B_TRUE; 18714d61c878SJulian Pullen for (k = 0; k < j; k++) { 18724d61c878SJulian Pullen if (strcasecmp(forestname, 18734d61c878SJulian Pullen trustedforests[k].forest_name) == 0) { 18747a8a68f5SJulian Pullen new_forest = B_FALSE; 18754d61c878SJulian Pullen domainsinforest = 18764d61c878SJulian Pullen trustedforests[k].domains_in_forest; 18774d61c878SJulian Pullen break; 18784d61c878SJulian Pullen } 18794d61c878SJulian Pullen } 18804d61c878SJulian Pullen if (!new_forest) { 18814d61c878SJulian Pullen /* Mark the domain as trusted */ 18824d61c878SJulian Pullen for (l = 0; 18834d61c878SJulian Pullen domainsinforest[l].domain[0] != '\0'; l++) { 18841fcced4cSJordan Brown if (domain_eq(trusteddomain, 18851fcced4cSJordan Brown domainsinforest[l].domain)) { 18864d61c878SJulian Pullen domainsinforest[l].trusted = 18874d61c878SJulian Pullen TRUE; 18884d61c878SJulian Pullen break; 18894d61c878SJulian Pullen } 18904d61c878SJulian Pullen } 18914d61c878SJulian Pullen free(forestname); 18924d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 18934d61c878SJulian Pullen continue; 18944d61c878SJulian Pullen } 18954d61c878SJulian Pullen 18964d61c878SJulian Pullen /* 18974d61c878SJulian Pullen * Get the Global Catalog and the domains in 18984d61c878SJulian Pullen * this new forest. 18994d61c878SJulian Pullen */ 19004d61c878SJulian Pullen globalcatalog = 19014d61c878SJulian Pullen ad_disc_get_GlobalCatalog(trusted_ctx, 19024d61c878SJulian Pullen AD_DISC_PREFER_SITE, NULL); 19034d61c878SJulian Pullen if (globalcatalog == NULL) { 1904148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1905148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1906148c5f43SAlan Wright "unable to discover Global Catalog" 1907148c5f43SAlan Wright " for the trusted domain %s", 1908148c5f43SAlan Wright trusteddomain); 1909148c5f43SAlan Wright } 19104d61c878SJulian Pullen free(forestname); 19114d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19124d61c878SJulian Pullen continue; 19134d61c878SJulian Pullen } 19144d61c878SJulian Pullen domainsinforest = 1915*b3700b07SGordon Ross ad_disc_get_DomainsInForest(trusted_ctx, NULL); 19164d61c878SJulian Pullen if (domainsinforest == NULL) { 1917148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1918148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1919148c5f43SAlan Wright "unable to discover Domains in the" 1920148c5f43SAlan Wright " Forest for the trusted domain %s", 1921148c5f43SAlan Wright trusteddomain); 1922148c5f43SAlan Wright } 19234d61c878SJulian Pullen free(globalcatalog); 19244d61c878SJulian Pullen free(forestname); 19254d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19264d61c878SJulian Pullen continue; 19274d61c878SJulian Pullen } 19284d61c878SJulian Pullen 19294d61c878SJulian Pullen trustedforests[j].forest_name = forestname; 19304d61c878SJulian Pullen trustedforests[j].global_catalog = globalcatalog; 19314d61c878SJulian Pullen trustedforests[j].domains_in_forest = domainsinforest; 19324d61c878SJulian Pullen j++; 19334d61c878SJulian Pullen /* Mark the domain as trusted */ 19344d61c878SJulian Pullen for (l = 0; domainsinforest[l].domain[0] != '\0'; 19354d61c878SJulian Pullen l++) { 19361fcced4cSJordan Brown if (domain_eq(trusteddomain, 19371fcced4cSJordan Brown domainsinforest[l].domain)) { 19384d61c878SJulian Pullen domainsinforest[l].trusted = TRUE; 19394d61c878SJulian Pullen break; 19404d61c878SJulian Pullen } 19414d61c878SJulian Pullen } 19424d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19434d61c878SJulian Pullen } 19444d61c878SJulian Pullen if (j > 0) { 19454d61c878SJulian Pullen pgcfg->num_trusted_forests = j; 19464d61c878SJulian Pullen pgcfg->trusted_forests = trustedforests; 19471fcced4cSJordan Brown } else { 19481fcced4cSJordan Brown free(trustedforests); 19494d61c878SJulian Pullen } 19504d61c878SJulian Pullen } 1951148c5f43SAlan Wright } 1952349d5d8fSnw 1953148c5f43SAlan Wright /* 1954148c5f43SAlan Wright * This is the half of idmap_cfg_load() that auto-discovers values of 1955148c5f43SAlan Wright * discoverable properties that weren't already set via SMF properties. 1956148c5f43SAlan Wright * 1957148c5f43SAlan Wright * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it 1958148c5f43SAlan Wright * needs to be careful not to overwrite any properties set in SMF. 1959148c5f43SAlan Wright */ 1960*b3700b07SGordon Ross static void 1961*b3700b07SGordon Ross idmap_cfg_discover1(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 1962148c5f43SAlan Wright { 1963148c5f43SAlan Wright ad_disc_t ad_ctx = handles->ad_ctx; 1964*b3700b07SGordon Ross FILE *status_fp = NULL; 1965*b3700b07SGordon Ross time_t t0, t1; 1966148c5f43SAlan Wright 1967*b3700b07SGordon Ross t0 = time(NULL); 1968148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1969*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Running domain discovery."); 1970148c5f43SAlan Wright 1971*b3700b07SGordon Ross (void) unlink(IDMAP_CACHEDIR "/discovery.log"); 1972*b3700b07SGordon Ross status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "w"); 1973*b3700b07SGordon Ross if (status_fp) { 1974*b3700b07SGordon Ross (void) fchmod(fileno(status_fp), 0644); 1975*b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, status_fp); 1976*b3700b07SGordon Ross } 1977148c5f43SAlan Wright 1978148c5f43SAlan Wright if (pgcfg->domain_name == NULL) { 1979148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "No domain name specified."); 1980*b3700b07SGordon Ross if (status_fp) 1981*b3700b07SGordon Ross (void) fprintf(status_fp, "(no domain name)\n"); 1982*b3700b07SGordon Ross goto out; 1983*b3700b07SGordon Ross } 1984148c5f43SAlan Wright 1985*b3700b07SGordon Ross if (pgcfg->domain_controller == NULL) 1986*b3700b07SGordon Ross pgcfg->domain_controller = 1987*b3700b07SGordon Ross ad_disc_get_DomainController(ad_ctx, 1988*b3700b07SGordon Ross AD_DISC_PREFER_SITE, 1989*b3700b07SGordon Ross &pgcfg->domain_controller_auto_disc); 1990*b3700b07SGordon Ross 1991*b3700b07SGordon Ross if (pgcfg->domain_guid == NULL) { 1992*b3700b07SGordon Ross char buf[UUID_PRINTABLE_STRING_LENGTH]; 1993*b3700b07SGordon Ross uchar_t *u = ad_disc_get_DomainGUID(ad_ctx, 1994*b3700b07SGordon Ross &pgcfg->domain_guid_auto_disc); 1995*b3700b07SGordon Ross (void) memset(buf, 0, sizeof (buf)); 1996*b3700b07SGordon Ross if (u != NULL) { 1997*b3700b07SGordon Ross uuid_unparse(u, buf); 1998*b3700b07SGordon Ross pgcfg->domain_guid = strdup(buf); 1999*b3700b07SGordon Ross } 2000*b3700b07SGordon Ross } 2001*b3700b07SGordon Ross 2002*b3700b07SGordon Ross if (pgcfg->forest_name == NULL) 2003*b3700b07SGordon Ross pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx, 2004*b3700b07SGordon Ross &pgcfg->forest_name_auto_disc); 2005*b3700b07SGordon Ross 2006*b3700b07SGordon Ross if (pgcfg->site_name == NULL) 2007*b3700b07SGordon Ross pgcfg->site_name = ad_disc_get_SiteName(ad_ctx, 2008*b3700b07SGordon Ross &pgcfg->site_name_auto_disc); 2009*b3700b07SGordon Ross 2010*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2011*b3700b07SGordon Ross log_if_unable(pgcfg->domain_name, "Domain Name"); 2012*b3700b07SGordon Ross log_if_unable(pgcfg->domain_controller, 2013*b3700b07SGordon Ross "Domain Controller"); 2014*b3700b07SGordon Ross log_if_unable(pgcfg->domain_guid, "Domain GUID"); 2015*b3700b07SGordon Ross log_if_unable(pgcfg->forest_name, "Forest Name"); 2016*b3700b07SGordon Ross log_if_unable(pgcfg->site_name, "Site Name"); 2017*b3700b07SGordon Ross } 2018*b3700b07SGordon Ross 2019*b3700b07SGordon Ross out: 2020*b3700b07SGordon Ross if (status_fp) { 2021*b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, NULL); 2022*b3700b07SGordon Ross (void) fclose(status_fp); 2023*b3700b07SGordon Ross status_fp = NULL; 2024*b3700b07SGordon Ross } 2025*b3700b07SGordon Ross 2026*b3700b07SGordon Ross if (DBG(CONFIG, 1)) 2027*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Domain discovery done."); 2028*b3700b07SGordon Ross 2029*b3700b07SGordon Ross /* 2030*b3700b07SGordon Ross * Log when this took more than 15 sec. 2031*b3700b07SGordon Ross */ 2032*b3700b07SGordon Ross t1 = time(NULL); 2033*b3700b07SGordon Ross if (t1 > (t0 + 15)) { 2034*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Domain discovery took %d sec.", 2035*b3700b07SGordon Ross (int)(t1 - t0)); 2036*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Check the DNS configuration."); 2037*b3700b07SGordon Ross } 2038*b3700b07SGordon Ross } 2039*b3700b07SGordon Ross 2040*b3700b07SGordon Ross /* 2041*b3700b07SGordon Ross * This is the second part of discovery, which can take a while. 2042*b3700b07SGordon Ross * We don't want to hold up parties who just want to know what 2043*b3700b07SGordon Ross * domain controller we're using (like smbd), so this part runs 2044*b3700b07SGordon Ross * after we've updated that info in the "live" config and told 2045*b3700b07SGordon Ross * such consumers to go ahead. 2046*b3700b07SGordon Ross * 2047*b3700b07SGordon Ross * This is a lot like idmap_cfg_discover(), but used LDAP queries 2048*b3700b07SGordon Ross * get the forest information from the global catalog servers. 2049*b3700b07SGordon Ross * 2050*b3700b07SGordon Ross * Note: the previous update_* calls have usually nuked any 2051*b3700b07SGordon Ross * useful information from pgcfg before we get here, so we 2052*b3700b07SGordon Ross * can only use it store discovery results, not to read. 2053*b3700b07SGordon Ross */ 2054*b3700b07SGordon Ross static void 2055*b3700b07SGordon Ross idmap_cfg_discover2(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 2056*b3700b07SGordon Ross { 2057*b3700b07SGordon Ross ad_disc_t ad_ctx = handles->ad_ctx; 2058*b3700b07SGordon Ross FILE *status_fp = NULL; 2059*b3700b07SGordon Ross time_t t0, t1; 2060*b3700b07SGordon Ross 2061*b3700b07SGordon Ross t0 = time(NULL); 2062*b3700b07SGordon Ross if (DBG(CONFIG, 1)) 2063*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Running forest discovery."); 2064*b3700b07SGordon Ross 2065*b3700b07SGordon Ross status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "a"); 2066*b3700b07SGordon Ross if (status_fp) 2067*b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, status_fp); 2068*b3700b07SGordon Ross 2069*b3700b07SGordon Ross if (pgcfg->global_catalog == NULL) 2070*b3700b07SGordon Ross pgcfg->global_catalog = 2071*b3700b07SGordon Ross ad_disc_get_GlobalCatalog(ad_ctx, 2072*b3700b07SGordon Ross AD_DISC_PREFER_SITE, 2073*b3700b07SGordon Ross &pgcfg->global_catalog_auto_disc); 2074*b3700b07SGordon Ross 2075*b3700b07SGordon Ross if (pgcfg->global_catalog != NULL) { 2076148c5f43SAlan Wright pgcfg->domains_in_forest = 2077148c5f43SAlan Wright ad_disc_get_DomainsInForest(ad_ctx, NULL); 2078148c5f43SAlan Wright 2079148c5f43SAlan Wright if (!pgcfg->disable_cross_forest_trusts) 2080148c5f43SAlan Wright discover_trusted_domains(pgcfg, ad_ctx); 2081*b3700b07SGordon Ross } 2082148c5f43SAlan Wright 2083*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2084*b3700b07SGordon Ross log_if_unable(pgcfg->global_catalog, "Global Catalog"); 2085*b3700b07SGordon Ross log_if_unable(pgcfg->domains_in_forest, 2086*b3700b07SGordon Ross "Domains in the Forest"); 2087*b3700b07SGordon Ross /* Empty trusted domains list is OK. */ 2088148c5f43SAlan Wright } 2089c5866007SKeyur Desai 2090*b3700b07SGordon Ross if (status_fp) { 2091*b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, NULL); 2092*b3700b07SGordon Ross (void) fclose(status_fp); 2093*b3700b07SGordon Ross status_fp = NULL; 2094*b3700b07SGordon Ross } 2095148c5f43SAlan Wright 2096148c5f43SAlan Wright if (DBG(CONFIG, 1)) 2097*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Forest discovery done."); 2098*b3700b07SGordon Ross 2099*b3700b07SGordon Ross /* 2100*b3700b07SGordon Ross * Log when this took more than 30 sec. 2101*b3700b07SGordon Ross */ 2102*b3700b07SGordon Ross t1 = time(NULL); 2103*b3700b07SGordon Ross if (t1 > (t0 + 30)) { 2104*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Forest discovery took %d sec.", 2105*b3700b07SGordon Ross (int)(t1 - t0)); 2106*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Check AD join status."); 2107*b3700b07SGordon Ross } 2108349d5d8fSnw } 2109349d5d8fSnw 21104d61c878SJulian Pullen 2111349d5d8fSnw /* 2112349d5d8fSnw * idmap_cfg_load() is called at startup, and periodically via the 2113349d5d8fSnw * update thread when the auto-discovery TTLs expire, as well as part of 2114349d5d8fSnw * the refresh method, to update the current configuration. It always 2115349d5d8fSnw * reads from SMF, but you still have to refresh the service after 2116349d5d8fSnw * changing the config pg in order for the changes to take effect. 2117349d5d8fSnw * 2118148c5f43SAlan Wright * There is one flag: 2119349d5d8fSnw * 2120349d5d8fSnw * - CFG_DISCOVER 2121349d5d8fSnw * 2122349d5d8fSnw * If CFG_DISCOVER is set then idmap_cfg_load() calls 2123349d5d8fSnw * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property 2124349d5d8fSnw * values that weren't set in SMF. 2125349d5d8fSnw * 2126148c5f43SAlan Wright * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration 2127148c5f43SAlan Wright * changed. 2128349d5d8fSnw * 2129349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 2130349d5d8fSnw * reading from SMF. 2131349d5d8fSnw */ 2132349d5d8fSnw int 2133349d5d8fSnw idmap_cfg_load(idmap_cfg_t *cfg, int flags) 2134349d5d8fSnw { 2135*b3700b07SGordon Ross const ad_disc_t ad_ctx = cfg->handles.ad_ctx; 2136349d5d8fSnw int rc = 0; 2137e3f2c991SKeyur Desai int errors; 2138349d5d8fSnw int changed = 0; 2139*b3700b07SGordon Ross int dc_changed = 0; 21404d61c878SJulian Pullen int ad_reload_required = 0; 2141349d5d8fSnw idmap_pg_config_t new_pgcfg, *live_pgcfg; 2142349d5d8fSnw 2143148c5f43SAlan Wright if (DBG(CONFIG, 1)) 2144148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "Loading configuration."); 2145148c5f43SAlan Wright 2146349d5d8fSnw live_pgcfg = &cfg->pgcfg; 2147349d5d8fSnw (void) memset(&new_pgcfg, 0, sizeof (new_pgcfg)); 2148349d5d8fSnw 2149148c5f43SAlan Wright (void) pthread_mutex_lock(&cfg->handles.mutex); 2150349d5d8fSnw 2151349d5d8fSnw if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1) 2152349d5d8fSnw goto err; 2153349d5d8fSnw 2154*b3700b07SGordon Ross if (flags & CFG_DISCOVER) { 2155*b3700b07SGordon Ross 2156*b3700b07SGordon Ross ad_disc_refresh(ad_ctx); 2157*b3700b07SGordon Ross 2158*b3700b07SGordon Ross /* 2159*b3700b07SGordon Ross * Unless we've been asked to forget the current DC, 2160*b3700b07SGordon Ross * give preference (in order) to the preferred DC if 2161*b3700b07SGordon Ross * configured, or the current DC. These preferences 2162*b3700b07SGordon Ross * reduce undesirable DC changes. 2163*b3700b07SGordon Ross */ 2164*b3700b07SGordon Ross if (flags & CFG_FORGET_DC) { 2165*b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, NULL); 2166*b3700b07SGordon Ross } else if (new_pgcfg.preferred_dc != NULL) { 2167*b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, 2168*b3700b07SGordon Ross new_pgcfg.preferred_dc); 2169*b3700b07SGordon Ross } else if (live_pgcfg->domain_controller != NULL) { 2170*b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, 2171*b3700b07SGordon Ross live_pgcfg->domain_controller); 2172*b3700b07SGordon Ross } else { 2173*b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, NULL); 2174*b3700b07SGordon Ross } 2175*b3700b07SGordon Ross 2176*b3700b07SGordon Ross /* 2177*b3700b07SGordon Ross * We want a way to tell adspriv_getdcname_1_svc() 2178*b3700b07SGordon Ross * (and others) that discovery is running and therefore 2179*b3700b07SGordon Ross * they may want to wait a bit or return an error... 2180*b3700b07SGordon Ross */ 2181*b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2182*b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_RUNNING; 2183*b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2184*b3700b07SGordon Ross 2185*b3700b07SGordon Ross idmap_cfg_discover1(&cfg->handles, &new_pgcfg); 2186*b3700b07SGordon Ross 2187*b3700b07SGordon Ross WRLOCK_CONFIG(); 2188*b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2189*b3700b07SGordon Ross _idmapdstate.addisc_st = 0; 2190*b3700b07SGordon Ross (void) cond_broadcast(&_idmapdstate.addisc_cv); 2191*b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2192*b3700b07SGordon Ross } else { 2193*b3700b07SGordon Ross WRLOCK_CONFIG(); 2194*b3700b07SGordon Ross } 2195349d5d8fSnw 2196349d5d8fSnw /* Non-discoverable props updated here */ 219748cd229bSGordon Ross 219848cd229bSGordon Ross changed += update_uint64(&live_pgcfg->list_size_limit, 219948cd229bSGordon Ross &new_pgcfg.list_size_limit, "list_size_limit"); 220048cd229bSGordon Ross 220148cd229bSGordon Ross changed += update_uint64(&live_pgcfg->id_cache_timeout, 220248cd229bSGordon Ross &new_pgcfg.id_cache_timeout, "id_cache_timeout"); 220348cd229bSGordon Ross 220448cd229bSGordon Ross changed += update_uint64(&live_pgcfg->name_cache_timeout, 220548cd229bSGordon Ross &new_pgcfg.name_cache_timeout, "name_cache_timeout"); 220648cd229bSGordon Ross 2207*b3700b07SGordon Ross changed += update_uint64(&live_pgcfg->rediscovery_interval, 2208*b3700b07SGordon Ross &new_pgcfg.rediscovery_interval, "rediscovery_interval"); 2209*b3700b07SGordon Ross 22104aa0a5e7Snw changed += update_string(&live_pgcfg->machine_sid, 2211349d5d8fSnw &new_pgcfg.machine_sid, "machine_sid"); 2212349d5d8fSnw 22134aa0a5e7Snw changed += update_bool(&live_pgcfg->eph_map_unres_sids, 22144aa0a5e7Snw &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); 22154aa0a5e7Snw 22161ed6b69aSGordon Ross changed += update_bool(&live_pgcfg->use_ads, 22171ed6b69aSGordon Ross &new_pgcfg.use_ads, "use_ads"); 22181ed6b69aSGordon Ross 2219148c5f43SAlan Wright changed += update_bool(&live_pgcfg->use_lsa, 2220148c5f43SAlan Wright &new_pgcfg.use_lsa, "use_lsa"); 2221148c5f43SAlan Wright 2222148c5f43SAlan Wright changed += update_bool(&live_pgcfg->disable_cross_forest_trusts, 2223148c5f43SAlan Wright &new_pgcfg.disable_cross_forest_trusts, 2224148c5f43SAlan Wright "disable_cross_forest_trusts"); 2225148c5f43SAlan Wright 2226e3f2c991SKeyur Desai changed += update_enum(&live_pgcfg->directory_based_mapping, 2227e3f2c991SKeyur Desai &new_pgcfg.directory_based_mapping, "directory_based_mapping", 2228e3f2c991SKeyur Desai directory_mapping_map); 2229349d5d8fSnw 22304aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixuser_attr, 2231349d5d8fSnw &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr"); 2232349d5d8fSnw 22334aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixgroup_attr, 2234349d5d8fSnw &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr"); 2235349d5d8fSnw 22364aa0a5e7Snw changed += update_string(&live_pgcfg->nldap_winname_attr, 2237349d5d8fSnw &new_pgcfg.nldap_winname_attr, "nldap_winname_attr"); 2238349d5d8fSnw 2239e3f2c991SKeyur Desai changed += update_string(&live_pgcfg->default_domain, 2240e3f2c991SKeyur Desai &new_pgcfg.default_domain, "default_domain"); 2241349d5d8fSnw 2242*b3700b07SGordon Ross changed += update_dirs(&live_pgcfg->preferred_dc, 2243*b3700b07SGordon Ross &new_pgcfg.preferred_dc, "preferred_dc"); 2244*b3700b07SGordon Ross 2245*b3700b07SGordon Ross /* Props that can be discovered or set in SMF updated here */ 2246*b3700b07SGordon Ross 2247*b3700b07SGordon Ross if (update_string(&live_pgcfg->domain_name, 2248*b3700b07SGordon Ross &new_pgcfg.domain_name, "domain_name")) { 2249*b3700b07SGordon Ross changed++; 2250*b3700b07SGordon Ross ad_reload_required = TRUE; 2251*b3700b07SGordon Ross idmapd_set_krb5_realm(live_pgcfg->domain_name); 2252*b3700b07SGordon Ross } 22534d61c878SJulian Pullen live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc; 2254349d5d8fSnw 2255*b3700b07SGordon Ross changed += update_string(&live_pgcfg->domain_guid, 2256*b3700b07SGordon Ross &new_pgcfg.domain_guid, "domain_guid"); 2257*b3700b07SGordon Ross live_pgcfg->domain_guid_auto_disc = new_pgcfg.domain_guid_auto_disc; 2258*b3700b07SGordon Ross 2259*b3700b07SGordon Ross dc_changed = update_dirs(&live_pgcfg->domain_controller, 2260349d5d8fSnw &new_pgcfg.domain_controller, "domain_controller"); 2261*b3700b07SGordon Ross changed += dc_changed; 22624d61c878SJulian Pullen live_pgcfg->domain_controller_auto_disc = 22634d61c878SJulian Pullen new_pgcfg.domain_controller_auto_disc; 2264349d5d8fSnw 22654aa0a5e7Snw changed += update_string(&live_pgcfg->forest_name, 2266349d5d8fSnw &new_pgcfg.forest_name, "forest_name"); 22674d61c878SJulian Pullen live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc; 2268349d5d8fSnw 22694aa0a5e7Snw changed += update_string(&live_pgcfg->site_name, 2270349d5d8fSnw &new_pgcfg.site_name, "site_name"); 22714d61c878SJulian Pullen live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc; 2272349d5d8fSnw 2273*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2274*b3700b07SGordon Ross if (changed) 2275*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Configuration changed"); 2276*b3700b07SGordon Ross else 2277*b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Configuration unchanged"); 2278*b3700b07SGordon Ross } 2279*b3700b07SGordon Ross 2280*b3700b07SGordon Ross UNLOCK_CONFIG(); 2281*b3700b07SGordon Ross 2282*b3700b07SGordon Ross if (dc_changed != 0) { 2283*b3700b07SGordon Ross notify_dc_changed(); 2284349d5d8fSnw } 2285*b3700b07SGordon Ross 2286*b3700b07SGordon Ross /* 2287*b3700b07SGordon Ross * Discovery2 can take a while. 2288*b3700b07SGordon Ross */ 2289*b3700b07SGordon Ross if (flags & CFG_DISCOVER) { 2290*b3700b07SGordon Ross if (live_pgcfg->domain_name != NULL && 2291*b3700b07SGordon Ross live_pgcfg->forest_name != NULL) 2292*b3700b07SGordon Ross idmap_cfg_discover2(&cfg->handles, &new_pgcfg); 2293*b3700b07SGordon Ross ad_disc_done(ad_ctx); 2294*b3700b07SGordon Ross } 2295*b3700b07SGordon Ross 2296*b3700b07SGordon Ross WRLOCK_CONFIG(); 2297*b3700b07SGordon Ross 2298*b3700b07SGordon Ross /* More props that can be discovered or set in SMF */ 2299*b3700b07SGordon Ross 2300*b3700b07SGordon Ross changed += update_dirs(&live_pgcfg->global_catalog, 2301*b3700b07SGordon Ross &new_pgcfg.global_catalog, "global_catalog"); 23024d61c878SJulian Pullen live_pgcfg->global_catalog_auto_disc = 23034d61c878SJulian Pullen new_pgcfg.global_catalog_auto_disc; 23044d61c878SJulian Pullen 2305*b3700b07SGordon Ross /* Props that are only discovered (never in SMF) */ 2306*b3700b07SGordon Ross 23074d61c878SJulian Pullen if (update_domains_in_forest(&live_pgcfg->domains_in_forest, 23084d61c878SJulian Pullen &new_pgcfg.domains_in_forest, "domains_in_forest")) { 23094d61c878SJulian Pullen changed++; 23104d61c878SJulian Pullen ad_reload_required = TRUE; 23114d61c878SJulian Pullen } 23124d61c878SJulian Pullen 23134d61c878SJulian Pullen if (update_trusted_domains(&live_pgcfg->trusted_domains, 23144d61c878SJulian Pullen &new_pgcfg.trusted_domains, "trusted_domains")) { 23154d61c878SJulian Pullen changed++; 23164d61c878SJulian Pullen if (live_pgcfg->trusted_domains != NULL && 23174d61c878SJulian Pullen live_pgcfg->trusted_domains[0].domain[0] != '\0') 23184d61c878SJulian Pullen ad_reload_required = TRUE; 23194d61c878SJulian Pullen } 23204d61c878SJulian Pullen 23214d61c878SJulian Pullen if (update_trusted_forest(&live_pgcfg->trusted_forests, 23224d61c878SJulian Pullen &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests, 23234d61c878SJulian Pullen &new_pgcfg.num_trusted_forests, "trusted_forest")) { 23244d61c878SJulian Pullen changed++; 23254d61c878SJulian Pullen if (live_pgcfg->trusted_forests != NULL) 23264d61c878SJulian Pullen ad_reload_required = TRUE; 23274d61c878SJulian Pullen } 23284d61c878SJulian Pullen 2329148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 2330148c5f43SAlan Wright if (changed) 2331148c5f43SAlan Wright idmapdlog(LOG_NOTICE, "Configuration changed"); 2332148c5f43SAlan Wright else 2333148c5f43SAlan Wright idmapdlog(LOG_NOTICE, "Configuration unchanged"); 2334c8e26105Sjp } 2335e3c2d6aaSnw 2336349d5d8fSnw UNLOCK_CONFIG(); 2337349d5d8fSnw 2338*b3700b07SGordon Ross if (ad_reload_required) 2339*b3700b07SGordon Ross reload_ad(); 2340*b3700b07SGordon Ross 2341*b3700b07SGordon Ross idmap_cfg_unload(&new_pgcfg); 2342*b3700b07SGordon Ross 2343349d5d8fSnw err: 2344148c5f43SAlan Wright (void) pthread_mutex_unlock(&cfg->handles.mutex); 2345c5c4113dSnw 2346e8c27ec8Sbaban if (rc < -1) 2347e3c2d6aaSnw return (rc); 2348e3c2d6aaSnw 2349e3c2d6aaSnw return ((errors == 0) ? 0 : -1); 2350c5c4113dSnw } 2351c5c4113dSnw 2352651c0131Sbaban /* 2353651c0131Sbaban * Initialize 'cfg'. 2354651c0131Sbaban */ 2355c5c4113dSnw idmap_cfg_t * 23564edd44c5Sjp idmap_cfg_init() 23574edd44c5Sjp { 2358c8e26105Sjp idmap_cfg_handles_t *handles; 2359c5c4113dSnw 2360c5c4113dSnw /* First the smf repository handles: */ 2361c5c4113dSnw idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t)); 2362c5c4113dSnw if (!cfg) { 236371590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 2364c5c4113dSnw return (NULL); 2365c5c4113dSnw } 2366c8e26105Sjp handles = &cfg->handles; 2367c5c4113dSnw 2368c8e26105Sjp (void) pthread_mutex_init(&handles->mutex, NULL); 2369c8e26105Sjp 2370c8e26105Sjp if (!(handles->main = scf_handle_create(SCF_VERSION))) { 237171590c90Snw idmapdlog(LOG_ERR, "scf_handle_create() failed: %s", 237271590c90Snw scf_strerror(scf_error())); 2373c5c4113dSnw goto error; 2374c5c4113dSnw } 2375c5c4113dSnw 2376c8e26105Sjp if (scf_handle_bind(handles->main) < 0) { 237771590c90Snw idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s", 237871590c90Snw scf_strerror(scf_error())); 2379c5c4113dSnw goto error; 2380c5c4113dSnw } 2381c5c4113dSnw 2382c8e26105Sjp if (!(handles->service = scf_service_create(handles->main)) || 2383c8e26105Sjp !(handles->instance = scf_instance_create(handles->main)) || 2384c8e26105Sjp !(handles->config_pg = scf_pg_create(handles->main)) || 2385148c5f43SAlan Wright !(handles->debug_pg = scf_pg_create(handles->main))) { 238671590c90Snw idmapdlog(LOG_ERR, "scf handle creation failed: %s", 238771590c90Snw scf_strerror(scf_error())); 2388c5c4113dSnw goto error; 2389c5c4113dSnw } 2390c5c4113dSnw 2391c8e26105Sjp if (scf_handle_decode_fmri(handles->main, 23924edd44c5Sjp FMRI_BASE "/:properties/" CONFIG_PG, 23934edd44c5Sjp NULL, /* scope */ 23944edd44c5Sjp handles->service, /* service */ 23954edd44c5Sjp handles->instance, /* instance */ 23964edd44c5Sjp handles->config_pg, /* pg */ 23974edd44c5Sjp NULL, /* prop */ 23984edd44c5Sjp SCF_DECODE_FMRI_EXACT) < 0) { 239971590c90Snw idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s", 240071590c90Snw scf_strerror(scf_error())); 2401c5c4113dSnw goto error; 2402c5c4113dSnw } 2403c5c4113dSnw 2404c8e26105Sjp if (scf_service_get_pg(handles->service, 2405148c5f43SAlan Wright DEBUG_PG, handles->debug_pg) < 0) { 2406148c5f43SAlan Wright idmapdlog(LOG_ERR, "Property group \"%s\": %s", 2407148c5f43SAlan Wright DEBUG_PG, scf_strerror(scf_error())); 2408c5c4113dSnw goto error; 2409c5c4113dSnw } 2410c5c4113dSnw 2411148c5f43SAlan Wright check_smf_debug_mode(handles); 2412e3f2c991SKeyur Desai 2413c8e26105Sjp /* Initialize AD Auto Discovery context */ 2414c8e26105Sjp handles->ad_ctx = ad_disc_init(); 2415c8e26105Sjp if (handles->ad_ctx == NULL) 2416c8e26105Sjp goto error; 2417c8e26105Sjp 2418c5c4113dSnw return (cfg); 2419c5c4113dSnw 2420c5c4113dSnw error: 2421c5c4113dSnw (void) idmap_cfg_fini(cfg); 2422c5c4113dSnw return (NULL); 2423c5c4113dSnw } 2424c5c4113dSnw 2425c8e26105Sjp void 24264edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg) 24274edd44c5Sjp { 2428c8e26105Sjp 2429c8e26105Sjp if (pgcfg->default_domain) { 2430c8e26105Sjp free(pgcfg->default_domain); 2431c8e26105Sjp pgcfg->default_domain = NULL; 2432c8e26105Sjp } 2433c8e26105Sjp if (pgcfg->domain_name) { 2434c8e26105Sjp free(pgcfg->domain_name); 2435c8e26105Sjp pgcfg->domain_name = NULL; 2436c8e26105Sjp } 2437*b3700b07SGordon Ross if (pgcfg->domain_guid) { 2438*b3700b07SGordon Ross free(pgcfg->domain_guid); 2439*b3700b07SGordon Ross pgcfg->domain_guid = NULL; 2440*b3700b07SGordon Ross } 2441c8e26105Sjp if (pgcfg->machine_sid) { 2442c8e26105Sjp free(pgcfg->machine_sid); 2443c8e26105Sjp pgcfg->machine_sid = NULL; 2444c8e26105Sjp } 2445c8e26105Sjp if (pgcfg->domain_controller) { 2446c5c4113dSnw free(pgcfg->domain_controller); 2447c8e26105Sjp pgcfg->domain_controller = NULL; 2448c8e26105Sjp } 2449c8e26105Sjp if (pgcfg->forest_name) { 2450c8e26105Sjp free(pgcfg->forest_name); 2451c8e26105Sjp pgcfg->forest_name = NULL; 2452c8e26105Sjp } 2453c8e26105Sjp if (pgcfg->site_name) { 2454c8e26105Sjp free(pgcfg->site_name); 2455c8e26105Sjp pgcfg->site_name = NULL; 2456c8e26105Sjp } 2457c8e26105Sjp if (pgcfg->global_catalog) { 2458c8e26105Sjp free(pgcfg->global_catalog); 2459c8e26105Sjp pgcfg->global_catalog = NULL; 2460c8e26105Sjp } 24614d61c878SJulian Pullen if (pgcfg->trusted_domains) { 24624d61c878SJulian Pullen free(pgcfg->trusted_domains); 24634d61c878SJulian Pullen pgcfg->trusted_domains = NULL; 24644d61c878SJulian Pullen } 24654d61c878SJulian Pullen if (pgcfg->trusted_forests) 24664d61c878SJulian Pullen free_trusted_forests(&pgcfg->trusted_forests, 24674d61c878SJulian Pullen &pgcfg->num_trusted_forests); 24684d61c878SJulian Pullen 2469e8c27ec8Sbaban if (pgcfg->ad_unixuser_attr) { 2470e8c27ec8Sbaban free(pgcfg->ad_unixuser_attr); 2471e8c27ec8Sbaban pgcfg->ad_unixuser_attr = NULL; 2472e8c27ec8Sbaban } 2473e8c27ec8Sbaban if (pgcfg->ad_unixgroup_attr) { 2474e8c27ec8Sbaban free(pgcfg->ad_unixgroup_attr); 2475e8c27ec8Sbaban pgcfg->ad_unixgroup_attr = NULL; 2476e8c27ec8Sbaban } 2477e8c27ec8Sbaban if (pgcfg->nldap_winname_attr) { 2478e8c27ec8Sbaban free(pgcfg->nldap_winname_attr); 2479e8c27ec8Sbaban pgcfg->nldap_winname_attr = NULL; 2480e8c27ec8Sbaban } 2481c5c4113dSnw } 2482c5c4113dSnw 2483c5c4113dSnw int 2484c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg) 2485c5c4113dSnw { 2486c8e26105Sjp idmap_cfg_handles_t *handles = &cfg->handles; 2487c8e26105Sjp idmap_cfg_unload(&cfg->pgcfg); 2488c8e26105Sjp 2489c8e26105Sjp (void) pthread_mutex_destroy(&handles->mutex); 2490c8e26105Sjp scf_pg_destroy(handles->config_pg); 2491148c5f43SAlan Wright if (handles->debug_pg != NULL) 2492148c5f43SAlan Wright scf_pg_destroy(handles->debug_pg); 2493c8e26105Sjp scf_instance_destroy(handles->instance); 2494c8e26105Sjp scf_service_destroy(handles->service); 2495c8e26105Sjp scf_handle_destroy(handles->main); 2496e8c27ec8Sbaban if (handles->ad_ctx != NULL) 2497e8c27ec8Sbaban ad_disc_fini(handles->ad_ctx); 2498c5c4113dSnw free(cfg); 2499c5c4113dSnw 2500c5c4113dSnw return (0); 2501c5c4113dSnw } 25020dcc7149Snw 25030dcc7149Snw void 25040dcc7149Snw idmap_cfg_poke_updates(void) 25050dcc7149Snw { 2506*b3700b07SGordon Ross int prev_st; 2507*b3700b07SGordon Ross 2508*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2509*b3700b07SGordon Ross idmapdlog(LOG_INFO, "idmap_cfg_poke_updates"); 2510*b3700b07SGordon Ross } 2511*b3700b07SGordon Ross 2512*b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2513*b3700b07SGordon Ross prev_st = _idmapdstate.addisc_st; 2514*b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED; 2515*b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2516*b3700b07SGordon Ross 2517*b3700b07SGordon Ross if (prev_st & ADDISC_ST_REQUESTED) { 2518*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "already poked"); 2519*b3700b07SGordon Ross } else { 2520*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "port send poke"); 2521349d5d8fSnw (void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL); 2522*b3700b07SGordon Ross } 2523*b3700b07SGordon Ross } 2524*b3700b07SGordon Ross 2525*b3700b07SGordon Ross void 2526*b3700b07SGordon Ross idmap_cfg_force_rediscovery(void) 2527*b3700b07SGordon Ross { 2528*b3700b07SGordon Ross int prev_st; 2529*b3700b07SGordon Ross 2530*b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2531*b3700b07SGordon Ross idmapdlog(LOG_INFO, "idmap_cfg_force_rediscovery"); 2532*b3700b07SGordon Ross } 2533*b3700b07SGordon Ross 2534*b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2535*b3700b07SGordon Ross prev_st = _idmapdstate.addisc_st; 2536*b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED; 2537*b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2538*b3700b07SGordon Ross 2539*b3700b07SGordon Ross if (prev_st & ADDISC_ST_REQUESTED) { 2540*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "already kicked"); 2541*b3700b07SGordon Ross } else { 2542*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "port send kick"); 2543*b3700b07SGordon Ross (void) port_send(idmapd_ev_port, KICK_AUTO_DISCOVERY, NULL); 2544*b3700b07SGordon Ross } 25450dcc7149Snw } 25460dcc7149Snw 25470dcc7149Snw /*ARGSUSED*/ 25480dcc7149Snw void 2549349d5d8fSnw idmap_cfg_hup_handler(int sig) 2550349d5d8fSnw { 25510dcc7149Snw if (idmapd_ev_port >= 0) 25520dcc7149Snw (void) port_send(idmapd_ev_port, RECONFIGURE, NULL); 25530dcc7149Snw } 2554e3f2c991SKeyur Desai 2555148c5f43SAlan Wright /* 2556148c5f43SAlan Wright * Upgrade the debug flags. 2557148c5f43SAlan Wright * 2558148c5f43SAlan Wright * We're replacing a single debug flag with a fine-grained mechanism that 2559148c5f43SAlan Wright * is also capable of considerably more verbosity. We'll take a stab at 2560148c5f43SAlan Wright * producing roughly the same level of output. 2561148c5f43SAlan Wright */ 2562148c5f43SAlan Wright static 2563148c5f43SAlan Wright int 2564148c5f43SAlan Wright upgrade_debug(idmap_cfg_handles_t *handles) 2565148c5f43SAlan Wright { 2566148c5f43SAlan Wright boolean_t debug_present; 2567148c5f43SAlan Wright const char DEBUG_PROP[] = "debug"; 2568148c5f43SAlan Wright int rc; 2569148c5f43SAlan Wright 2570148c5f43SAlan Wright rc = prop_exists(handles, DEBUG_PROP, &debug_present); 2571148c5f43SAlan Wright 2572148c5f43SAlan Wright if (rc != 0) 2573148c5f43SAlan Wright return (rc); 2574148c5f43SAlan Wright 2575148c5f43SAlan Wright if (!debug_present) 2576148c5f43SAlan Wright return (0); 2577148c5f43SAlan Wright 2578148c5f43SAlan Wright idmapdlog(LOG_INFO, 2579148c5f43SAlan Wright "Upgrading old %s/%s setting to %s/* settings.", 2580148c5f43SAlan Wright CONFIG_PG, DEBUG_PROP, DEBUG_PG); 2581148c5f43SAlan Wright 2582148c5f43SAlan Wright rc = set_val_integer(handles, handles->debug_pg, "config", 1); 2583148c5f43SAlan Wright if (rc != 0) 2584148c5f43SAlan Wright return (rc); 2585148c5f43SAlan Wright rc = set_val_integer(handles, handles->debug_pg, "discovery", 1); 2586148c5f43SAlan Wright if (rc != 0) 2587148c5f43SAlan Wright return (rc); 2588148c5f43SAlan Wright 2589148c5f43SAlan Wright rc = del_val(handles, handles->config_pg, DEBUG_PROP); 2590148c5f43SAlan Wright if (rc != 0) 2591148c5f43SAlan Wright return (rc); 2592148c5f43SAlan Wright 2593148c5f43SAlan Wright return (0); 2594148c5f43SAlan Wright } 2595148c5f43SAlan Wright 2596e3f2c991SKeyur Desai /* 2597e3f2c991SKeyur Desai * Upgrade the DS mapping flags. 2598e3f2c991SKeyur Desai * 2599e3f2c991SKeyur Desai * If the old ds_name_mapping_enabled flag is present, then 2600e3f2c991SKeyur Desai * if the new directory_based_mapping value is present, then 2601e3f2c991SKeyur Desai * if the two are compatible, delete the old and note it 2602e3f2c991SKeyur Desai * else delete the old and warn 2603e3f2c991SKeyur Desai * else 2604e3f2c991SKeyur Desai * set the new based on the old, and note it 2605e3f2c991SKeyur Desai * delete the old 2606e3f2c991SKeyur Desai */ 2607e3f2c991SKeyur Desai static 2608e3f2c991SKeyur Desai int 2609e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles) 2610e3f2c991SKeyur Desai { 2611e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_present; 2612e3f2c991SKeyur Desai const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled"; 2613e3f2c991SKeyur Desai const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping"; 2614e3f2c991SKeyur Desai int rc; 2615e3f2c991SKeyur Desai 2616e3f2c991SKeyur Desai rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED, 2617e3f2c991SKeyur Desai &legacy_ds_name_mapping_present); 2618e3f2c991SKeyur Desai 2619e3f2c991SKeyur Desai if (rc != 0) 2620e3f2c991SKeyur Desai return (rc); 2621e3f2c991SKeyur Desai 2622e3f2c991SKeyur Desai if (!legacy_ds_name_mapping_present) 2623e3f2c991SKeyur Desai return (0); 2624e3f2c991SKeyur Desai 2625e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_enabled; 2626148c5f43SAlan Wright rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED, 2627148c5f43SAlan Wright &legacy_ds_name_mapping_enabled, B_FALSE); 2628e3f2c991SKeyur Desai if (rc != 0) 2629e3f2c991SKeyur Desai return (rc); 2630e3f2c991SKeyur Desai 2631e3f2c991SKeyur Desai char *legacy_mode; 2632e3f2c991SKeyur Desai char *legacy_bool_string; 2633e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled) { 2634e3f2c991SKeyur Desai legacy_mode = "name"; 2635e3f2c991SKeyur Desai legacy_bool_string = "true"; 2636e3f2c991SKeyur Desai } else { 2637e3f2c991SKeyur Desai legacy_mode = "none"; 2638e3f2c991SKeyur Desai legacy_bool_string = "false"; 2639e3f2c991SKeyur Desai } 2640e3f2c991SKeyur Desai 2641e3f2c991SKeyur Desai char *directory_based_mapping; 2642e3f2c991SKeyur Desai rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING, 2643e3f2c991SKeyur Desai &directory_based_mapping); 2644e3f2c991SKeyur Desai if (rc != 0) 2645e3f2c991SKeyur Desai return (rc); 2646e3f2c991SKeyur Desai 2647e3f2c991SKeyur Desai if (directory_based_mapping == NULL) { 2648e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 2649e3f2c991SKeyur Desai "Upgrading old %s=%s setting\n" 2650e3f2c991SKeyur Desai "to %s=%s.", 2651e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2652e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, legacy_mode); 2653148c5f43SAlan Wright rc = set_val_astring(handles, handles->config_pg, 2654148c5f43SAlan Wright DIRECTORY_BASED_MAPPING, legacy_mode); 2655e3f2c991SKeyur Desai if (rc != 0) 2656e3f2c991SKeyur Desai return (rc); 2657e3f2c991SKeyur Desai } else { 2658e3f2c991SKeyur Desai boolean_t new_name_mapping; 2659e3f2c991SKeyur Desai if (strcasecmp(directory_based_mapping, "name") == 0) 2660e3f2c991SKeyur Desai new_name_mapping = B_TRUE; 2661e3f2c991SKeyur Desai else 2662e3f2c991SKeyur Desai new_name_mapping = B_FALSE; 2663e3f2c991SKeyur Desai 2664e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled == new_name_mapping) { 2665e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 2666e3f2c991SKeyur Desai "Automatically removing old %s=%s setting\n" 2667e3f2c991SKeyur Desai "in favor of %s=%s.", 2668e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2669e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 2670e3f2c991SKeyur Desai } else { 2671e3f2c991SKeyur Desai idmapdlog(LOG_WARNING, 2672e3f2c991SKeyur Desai "Removing conflicting %s=%s setting\n" 2673e3f2c991SKeyur Desai "in favor of %s=%s.", 2674e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2675e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 2676e3f2c991SKeyur Desai } 2677e3f2c991SKeyur Desai free(directory_based_mapping); 2678e3f2c991SKeyur Desai } 2679e3f2c991SKeyur Desai 2680148c5f43SAlan Wright rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED); 2681e3f2c991SKeyur Desai if (rc != 0) 2682e3f2c991SKeyur Desai return (rc); 2683e3f2c991SKeyur Desai 2684e3f2c991SKeyur Desai return (0); 2685e3f2c991SKeyur Desai } 2686e3f2c991SKeyur Desai 2687e3f2c991SKeyur Desai /* 2688e3f2c991SKeyur Desai * Do whatever is necessary to upgrade idmap's configuration before 2689e3f2c991SKeyur Desai * we load it. 2690e3f2c991SKeyur Desai */ 2691e3f2c991SKeyur Desai int 2692e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg) 2693e3f2c991SKeyur Desai { 2694e3f2c991SKeyur Desai int rc; 2695e3f2c991SKeyur Desai 2696e3f2c991SKeyur Desai rc = upgrade_directory_mapping(&cfg->handles); 2697e3f2c991SKeyur Desai if (rc != 0) 2698e3f2c991SKeyur Desai return (rc); 2699e3f2c991SKeyur Desai 2700148c5f43SAlan Wright rc = upgrade_debug(&cfg->handles); 2701148c5f43SAlan Wright if (rc != 0) 2702148c5f43SAlan Wright return (rc); 2703148c5f43SAlan Wright 2704e3f2c991SKeyur Desai return (0); 2705e3f2c991SKeyur Desai } 2706*b3700b07SGordon Ross 2707*b3700b07SGordon Ross /* 2708*b3700b07SGordon Ross * The LDAP code passes principal names lacking any 2709*b3700b07SGordon Ross * realm information, which causes mech_krb5 to do 2710*b3700b07SGordon Ross * awful things trying to figure out the realm. 2711*b3700b07SGordon Ross * Avoid that by making sure it has a default, 2712*b3700b07SGordon Ross * even when krb5.conf is not configured. 2713*b3700b07SGordon Ross */ 2714*b3700b07SGordon Ross static void 2715*b3700b07SGordon Ross idmapd_set_krb5_realm(char *domain) 2716*b3700b07SGordon Ross { 2717*b3700b07SGordon Ross static char realm[MAXHOSTNAMELEN]; 2718*b3700b07SGordon Ross size_t ilen, olen; 2719*b3700b07SGordon Ross int err; 2720*b3700b07SGordon Ross 2721*b3700b07SGordon Ross if (domain == NULL) { 2722*b3700b07SGordon Ross (void) unsetenv("KRB5_DEFAULT_REALM"); 2723*b3700b07SGordon Ross return; 2724*b3700b07SGordon Ross } 2725*b3700b07SGordon Ross 2726*b3700b07SGordon Ross /* Convert to upper case, in place. */ 2727*b3700b07SGordon Ross (void) strlcpy(realm, domain, sizeof (realm)); 2728*b3700b07SGordon Ross olen = ilen = strlen(realm); 2729*b3700b07SGordon Ross (void) u8_textprep_str(realm, &ilen, realm, &olen, 2730*b3700b07SGordon Ross U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err); 2731*b3700b07SGordon Ross 2732*b3700b07SGordon Ross (void) setenv("KRB5_DEFAULT_REALM", realm, 1); 2733*b3700b07SGordon Ross } 2734