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*fea136a0SMatt Barden * Copyright 2018 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> 41b3700b07SGordon Ross #include <sys/socket.h> 420dcc7149Snw #include <net/route.h> 434d61c878SJulian Pullen #include <sys/u8_textprep.h> 44b3700b07SGordon Ross #include <netinet/in.h> 45b3700b07SGordon Ross #include <arpa/inet.h> 46b3700b07SGordon Ross #include <netdb.h> 47148c5f43SAlan Wright #include <note.h> 48*fea136a0SMatt Barden #include <limits.h> 49b3700b07SGordon Ross #include "idmapd.h" 50c8e26105Sjp #include "addisc.h" 51c5c4113dSnw 524aa0a5e7Snw #define MACHINE_SID_LEN (9 + 3 * 11) 530dcc7149Snw #define FMRI_BASE "svc:/system/idmap" 540dcc7149Snw #define CONFIG_PG "config" 55148c5f43SAlan Wright #define DEBUG_PG "debug" 560dcc7149Snw #define RECONFIGURE 1 570dcc7149Snw #define POKE_AUTO_DISCOVERY 2 58b3700b07SGordon Ross #define KICK_AUTO_DISCOVERY 3 59c5c4113dSnw 6048cd229bSGordon Ross /* 6148cd229bSGordon Ross * Default cache timeouts. Can override via svccfg 6248cd229bSGordon Ross * config/id_cache_timeout = count: seconds 6348cd229bSGordon Ross * config/name_cache_timeout = count: seconds 6448cd229bSGordon Ross */ 653f1de28dSBayard Bell #define ID_CACHE_TMO_DEFAULT 86400 663f1de28dSBayard Bell #define NAME_CACHE_TMO_DEFAULT 604800 6748cd229bSGordon Ross 68b3700b07SGordon Ross /* 69b3700b07SGordon Ross * Default maximum time between rediscovery runs. 70b3700b07SGordon Ross * config/rediscovery_interval = count: seconds 71b3700b07SGordon Ross */ 72b3700b07SGordon Ross #define REDISCOVERY_INTERVAL_DEFAULT 3600 73b3700b07SGordon Ross 74b3700b07SGordon Ross /* 75b3700b07SGordon Ross * Mininum time between rediscovery runs, in case adutils gives us a 76b3700b07SGordon Ross * really short TTL (which it never should, but be defensive) 77b3700b07SGordon Ross * (not configurable) seconds. 78b3700b07SGordon Ross */ 79b3700b07SGordon Ross #define MIN_REDISCOVERY_INTERVAL 60 80b3700b07SGordon Ross 81*fea136a0SMatt Barden /* 82*fea136a0SMatt Barden * Max number of concurrent door calls 83*fea136a0SMatt Barden */ 84*fea136a0SMatt Barden #define MAX_THREADS_DEFAULT 40 85*fea136a0SMatt Barden 86c5866007SKeyur Desai enum event_type { 87c5866007SKeyur Desai EVENT_NOTHING, /* Woke up for no good reason */ 88c5866007SKeyur Desai EVENT_TIMEOUT, /* Timeout expired */ 89c5866007SKeyur Desai EVENT_ROUTING, /* An interesting routing event happened */ 90b3700b07SGordon Ross EVENT_POKED, /* Requested from degrade_svc() */ 91b3700b07SGordon Ross EVENT_KICKED, /* Force rediscovery, i.e. DC failed. */ 92c5866007SKeyur Desai EVENT_REFRESH, /* SMF refresh */ 93c5866007SKeyur Desai }; 94c5866007SKeyur Desai 95c8e26105Sjp 96b3700b07SGordon Ross static void idmapd_set_krb5_realm(char *); 97c8e26105Sjp 98c8e26105Sjp static pthread_t update_thread_handle = 0; 99c8e26105Sjp 1000dcc7149Snw static int idmapd_ev_port = -1; 1010dcc7149Snw static int rt_sock = -1; 102c8e26105Sjp 103e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = { 104e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NONE, "none" }, 105e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NAME, "name" }, 106e3f2c991SKeyur Desai { DIRECTORY_MAPPING_IDMU, "idmu" }, 107e3f2c991SKeyur Desai { 0, NULL }, 108e3f2c991SKeyur Desai }; 109e3f2c991SKeyur Desai 110148c5f43SAlan Wright struct enum_lookup_map trust_dir_map[] = { 111148c5f43SAlan Wright { 1, "they trust us" }, 112148c5f43SAlan Wright { 2, "we trust them" }, 113148c5f43SAlan Wright { 3, "we trust each other" }, 114148c5f43SAlan Wright { 0, NULL }, 115148c5f43SAlan Wright }; 116148c5f43SAlan Wright 1178edda628Sbaban static int 11812b65585SGordon Ross generate_machine_uuid(char **machine_uuid) 1194edd44c5Sjp { 1208edda628Sbaban uuid_t uu; 1218edda628Sbaban 12212b65585SGordon Ross *machine_uuid = calloc(1, UUID_PRINTABLE_STRING_LENGTH + 1); 12312b65585SGordon Ross if (*machine_uuid == NULL) { 12471590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 1258edda628Sbaban return (-1); 1268edda628Sbaban } 1278edda628Sbaban 1288edda628Sbaban uuid_clear(uu); 12912b65585SGordon Ross uuid_generate_time(uu); 13012b65585SGordon Ross uuid_unparse(uu, *machine_uuid); 13112b65585SGordon Ross 13212b65585SGordon Ross return (0); 13312b65585SGordon Ross } 13412b65585SGordon Ross 13512b65585SGordon Ross static int 13612b65585SGordon Ross generate_machine_sid(char **machine_sid, char *machine_uuid) 13712b65585SGordon Ross { 13812b65585SGordon Ross union { 13912b65585SGordon Ross uuid_t uu; 14012b65585SGordon Ross uint32_t v[4]; 14112b65585SGordon Ross } uv; 14212b65585SGordon Ross int len; 14312b65585SGordon Ross 14412b65585SGordon Ross /* 14512b65585SGordon Ross * Split the 128-bit machine UUID into three 32-bit values 14612b65585SGordon Ross * we'll use as the "sub-authorities" of the machine SID. 14712b65585SGordon Ross * The machine_sid will have the form S-1-5-21-J-K-L 14812b65585SGordon Ross * (that's four sub-authorities altogether) where: 14912b65585SGordon Ross * J = last 4 bytes of node_addr, 15012b65585SGordon Ross * K = time_mid, time_hi_and_version 15112b65585SGordon Ross * L = time_low 15212b65585SGordon Ross * (see struct uuid) 15312b65585SGordon Ross */ 15412b65585SGordon Ross 15512b65585SGordon Ross (void) memset(&uv, 0, sizeof (uv)); 15612b65585SGordon Ross (void) uuid_parse(machine_uuid, uv.uu); 1578edda628Sbaban 15812b65585SGordon Ross len = asprintf(machine_sid, "S-1-5-21-%u-%u-%u", 15912b65585SGordon Ross uv.v[3], uv.v[0], uv.v[1]); 1604aa0a5e7Snw 16112b65585SGordon Ross if (len == -1 || *machine_sid == NULL) { 16212b65585SGordon Ross idmapdlog(LOG_ERR, "Out of memory"); 16312b65585SGordon Ross return (-1); 1648edda628Sbaban } 1658edda628Sbaban 1668edda628Sbaban return (0); 1678edda628Sbaban } 1688edda628Sbaban 169479ac375Sdm 170479ac375Sdm /* In the case of error, exists is set to FALSE anyway */ 171479ac375Sdm static int 172e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists) 17371590c90Snw { 17471590c90Snw 175479ac375Sdm scf_property_t *scf_prop; 176479ac375Sdm 1777a8a68f5SJulian Pullen *exists = B_FALSE; 178479ac375Sdm 179148c5f43SAlan Wright scf_prop = scf_property_create(handles->main); 180148c5f43SAlan Wright if (scf_prop == NULL) { 181148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 182148c5f43SAlan Wright scf_strerror(scf_error())); 183148c5f43SAlan Wright return (-1); 184148c5f43SAlan Wright } 185148c5f43SAlan Wright 186148c5f43SAlan Wright if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0) 187148c5f43SAlan Wright *exists = B_TRUE; 188148c5f43SAlan Wright 189148c5f43SAlan Wright scf_property_destroy(scf_prop); 190148c5f43SAlan Wright 191148c5f43SAlan Wright return (0); 192148c5f43SAlan Wright } 193148c5f43SAlan Wright 194148c5f43SAlan Wright static int 195148c5f43SAlan Wright get_debug(idmap_cfg_handles_t *handles, const char *name) 196148c5f43SAlan Wright { 197148c5f43SAlan Wright int64_t i64 = 0; 198148c5f43SAlan Wright 199148c5f43SAlan Wright scf_property_t *scf_prop; 200148c5f43SAlan Wright scf_value_t *value; 201148c5f43SAlan Wright 202148c5f43SAlan Wright scf_prop = scf_property_create(handles->main); 203148c5f43SAlan Wright if (scf_prop == NULL) { 204148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 205148c5f43SAlan Wright scf_strerror(scf_error())); 206148c5f43SAlan Wright abort(); 207148c5f43SAlan Wright } 208148c5f43SAlan Wright value = scf_value_create(handles->main); 209148c5f43SAlan Wright if (value == NULL) { 210148c5f43SAlan Wright idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 211148c5f43SAlan Wright scf_strerror(scf_error())); 212148c5f43SAlan Wright abort(); 213148c5f43SAlan Wright } 214148c5f43SAlan Wright 215148c5f43SAlan Wright if (scf_pg_get_property(handles->debug_pg, name, scf_prop) < 0) { 216148c5f43SAlan Wright /* this is OK: the property is just undefined */ 217148c5f43SAlan Wright goto destruction; 218148c5f43SAlan Wright } 219148c5f43SAlan Wright 220148c5f43SAlan Wright 221148c5f43SAlan Wright if (scf_property_get_value(scf_prop, value) < 0) { 222148c5f43SAlan Wright /* It is still OK when a property doesn't have any value */ 223148c5f43SAlan Wright goto destruction; 224148c5f43SAlan Wright } 225148c5f43SAlan Wright 226148c5f43SAlan Wright if (scf_value_get_integer(value, &i64) != 0) { 227148c5f43SAlan Wright idmapdlog(LOG_ERR, "Can not retrieve %s/%s: %s", 228148c5f43SAlan Wright DEBUG_PG, name, scf_strerror(scf_error())); 229148c5f43SAlan Wright abort(); 230148c5f43SAlan Wright } 231148c5f43SAlan Wright 232148c5f43SAlan Wright destruction: 233148c5f43SAlan Wright scf_value_destroy(value); 234148c5f43SAlan Wright scf_property_destroy(scf_prop); 235148c5f43SAlan Wright 236148c5f43SAlan Wright return ((int)i64); 237148c5f43SAlan Wright } 238148c5f43SAlan Wright 239148c5f43SAlan Wright static int 240148c5f43SAlan Wright get_val_bool(idmap_cfg_handles_t *handles, const char *name, 241148c5f43SAlan Wright boolean_t *val, boolean_t default_val) 242148c5f43SAlan Wright { 243148c5f43SAlan Wright int rc = 0; 244148c5f43SAlan Wright 245148c5f43SAlan Wright scf_property_t *scf_prop; 246148c5f43SAlan Wright scf_value_t *value; 247148c5f43SAlan Wright 248148c5f43SAlan Wright *val = default_val; 249148c5f43SAlan Wright 250479ac375Sdm scf_prop = scf_property_create(handles->main); 251479ac375Sdm if (scf_prop == NULL) { 252479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 253479ac375Sdm scf_strerror(scf_error())); 254479ac375Sdm return (-1); 255479ac375Sdm } 256479ac375Sdm value = scf_value_create(handles->main); 257479ac375Sdm if (value == NULL) { 258479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 259479ac375Sdm scf_strerror(scf_error())); 260479ac375Sdm scf_property_destroy(scf_prop); 261479ac375Sdm return (-1); 262479ac375Sdm } 26371590c90Snw 264148c5f43SAlan Wright /* It is OK if the property is undefined */ 265148c5f43SAlan Wright if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 266148c5f43SAlan Wright goto destruction; 267148c5f43SAlan Wright 268148c5f43SAlan Wright 269148c5f43SAlan Wright /* It is still OK when a property doesn't have any value */ 270148c5f43SAlan Wright if (scf_property_get_value(scf_prop, value) < 0) 271148c5f43SAlan Wright goto destruction; 272148c5f43SAlan Wright 273148c5f43SAlan Wright uint8_t b; 274148c5f43SAlan Wright rc = scf_value_get_boolean(value, &b); 27571590c90Snw 276148c5f43SAlan Wright if (rc == 0) 277148c5f43SAlan Wright *val = (boolean_t)b; 278148c5f43SAlan Wright 279148c5f43SAlan Wright destruction: 28071590c90Snw scf_value_destroy(value); 28171590c90Snw scf_property_destroy(scf_prop); 28271590c90Snw 283148c5f43SAlan Wright return (rc); 28471590c90Snw } 28571590c90Snw 286c5c4113dSnw static int 287e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name, 288c8e26105Sjp void *val, scf_type_t type) 289c5c4113dSnw { 290c5c4113dSnw int rc = 0; 291c5c4113dSnw 292479ac375Sdm scf_property_t *scf_prop; 293479ac375Sdm scf_value_t *value; 294479ac375Sdm 2954aa0a5e7Snw switch (type) { 2964aa0a5e7Snw case SCF_TYPE_COUNT: 2974aa0a5e7Snw *(uint64_t *)val = 0; 2984aa0a5e7Snw break; 2994aa0a5e7Snw case SCF_TYPE_INTEGER: 3004aa0a5e7Snw *(int64_t *)val = 0; 3014aa0a5e7Snw break; 3024aa0a5e7Snw default: 3034aa0a5e7Snw idmapdlog(LOG_ERR, "Invalid scf integer type (%d)", 3044aa0a5e7Snw type); 3054aa0a5e7Snw abort(); 3064aa0a5e7Snw } 3074aa0a5e7Snw 308479ac375Sdm scf_prop = scf_property_create(handles->main); 309479ac375Sdm if (scf_prop == NULL) { 310479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 311479ac375Sdm scf_strerror(scf_error())); 312479ac375Sdm return (-1); 313479ac375Sdm } 314479ac375Sdm value = scf_value_create(handles->main); 315479ac375Sdm if (value == NULL) { 316479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 317479ac375Sdm scf_strerror(scf_error())); 318479ac375Sdm scf_property_destroy(scf_prop); 319479ac375Sdm return (-1); 320479ac375Sdm } 321c5c4113dSnw 322c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 323c5c4113dSnw /* this is OK: the property is just undefined */ 324c5c4113dSnw goto destruction; 325c5c4113dSnw 326c5c4113dSnw 327c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) 328c5c4113dSnw /* It is still OK when a property doesn't have any value */ 329c5c4113dSnw goto destruction; 330c5c4113dSnw 331c5c4113dSnw switch (type) { 332c5c4113dSnw case SCF_TYPE_COUNT: 333c5c4113dSnw rc = scf_value_get_count(value, val); 334c5c4113dSnw break; 335c5c4113dSnw case SCF_TYPE_INTEGER: 336c5c4113dSnw rc = scf_value_get_integer(value, val); 337c5c4113dSnw break; 338e3f2c991SKeyur Desai default: 339e3f2c991SKeyur Desai abort(); /* tested above */ 340e3f2c991SKeyur Desai /* NOTREACHED */ 341c5c4113dSnw } 342c5c4113dSnw 343e3f2c991SKeyur Desai if (rc != 0) { 344e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 345e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 346e3f2c991SKeyur Desai } 347c5c4113dSnw 348c5c4113dSnw destruction: 349c5c4113dSnw scf_value_destroy(value); 350c5c4113dSnw scf_property_destroy(scf_prop); 351c5c4113dSnw 352c5c4113dSnw return (rc); 353c5c4113dSnw } 354c5c4113dSnw 355c5c4113dSnw static char * 356e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value) 3574edd44c5Sjp { 358e3f2c991SKeyur Desai static size_t max_val = 0; 359c5c4113dSnw 360e3f2c991SKeyur Desai if (max_val == 0) 361e3f2c991SKeyur Desai max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 362c5c4113dSnw 363e3f2c991SKeyur Desai char buf[max_val + 1]; 364e3f2c991SKeyur Desai if (scf_value_get_astring(value, buf, max_val + 1) < 0) { 365e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 366e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 367e3f2c991SKeyur Desai return (NULL); 368c5c4113dSnw } 369c5c4113dSnw 370e3f2c991SKeyur Desai char *s = strdup(buf); 371e3f2c991SKeyur Desai if (s == NULL) 372e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Out of memory"); 373c5c4113dSnw 374e3f2c991SKeyur Desai return (s); 375c5c4113dSnw } 376c5c4113dSnw 377c8e26105Sjp static int 378c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport, 379b3700b07SGordon Ross ad_disc_ds_t **val) 380c8e26105Sjp { 381b3700b07SGordon Ross char port_str[8]; 382b3700b07SGordon Ross struct addrinfo hints; 383b3700b07SGordon Ross struct addrinfo *ai; 384b3700b07SGordon Ross ad_disc_ds_t *servers = NULL; 385c8e26105Sjp scf_property_t *scf_prop; 386c8e26105Sjp scf_value_t *value; 387c8e26105Sjp scf_iter_t *iter; 388c8e26105Sjp char *host, *portstr; 389b3700b07SGordon Ross int err, len, i; 390c8e26105Sjp int count = 0; 391e3c2d6aaSnw int rc = -1; 392c8e26105Sjp 393c8e26105Sjp *val = NULL; 394c8e26105Sjp 395c8e26105Sjp restart: 396c8e26105Sjp scf_prop = scf_property_create(handles->main); 397479ac375Sdm if (scf_prop == NULL) { 398479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 399479ac375Sdm scf_strerror(scf_error())); 400479ac375Sdm return (-1); 401479ac375Sdm } 402479ac375Sdm 403c8e26105Sjp value = scf_value_create(handles->main); 404479ac375Sdm if (value == NULL) { 405479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 406479ac375Sdm scf_strerror(scf_error())); 407479ac375Sdm scf_property_destroy(scf_prop); 408479ac375Sdm return (-1); 409479ac375Sdm } 410479ac375Sdm 411c8e26105Sjp iter = scf_iter_create(handles->main); 412479ac375Sdm if (iter == NULL) { 413479ac375Sdm idmapdlog(LOG_ERR, "scf_iter_create() failed: %s", 414479ac375Sdm scf_strerror(scf_error())); 415479ac375Sdm scf_value_destroy(value); 416479ac375Sdm scf_property_destroy(scf_prop); 417479ac375Sdm return (-1); 418479ac375Sdm } 419c8e26105Sjp 420e3c2d6aaSnw if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) { 421c8e26105Sjp /* this is OK: the property is just undefined */ 422e3c2d6aaSnw rc = 0; 423c8e26105Sjp goto destruction; 424e3c2d6aaSnw } 425c8e26105Sjp 426c8e26105Sjp if (scf_iter_property_values(iter, scf_prop) < 0) { 427c8e26105Sjp idmapdlog(LOG_ERR, 42871590c90Snw "scf_iter_property_values(%s) failed: %s", 42971590c90Snw name, scf_strerror(scf_error())); 430c8e26105Sjp goto destruction; 431c8e26105Sjp } 432c8e26105Sjp 433c8e26105Sjp /* Workaround scf bugs -- can't reset an iteration */ 434c8e26105Sjp if (count == 0) { 435c8e26105Sjp while (scf_iter_next_value(iter, value) > 0) 436c8e26105Sjp count++; 437c8e26105Sjp 438e3c2d6aaSnw if (count == 0) { 439c8e26105Sjp /* no values */ 440e3c2d6aaSnw rc = 0; 441c8e26105Sjp goto destruction; 442e3c2d6aaSnw } 443c8e26105Sjp 444c8e26105Sjp scf_value_destroy(value); 445c8e26105Sjp scf_iter_destroy(iter); 446c8e26105Sjp scf_property_destroy(scf_prop); 447c8e26105Sjp goto restart; 448c8e26105Sjp } 449c8e26105Sjp 450c8e26105Sjp if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) { 45171590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 452c8e26105Sjp goto destruction; 453c8e26105Sjp } 454c8e26105Sjp 455b3700b07SGordon Ross (void) memset(&hints, 0, sizeof (hints)); 456b3700b07SGordon Ross hints.ai_protocol = IPPROTO_TCP; 457b3700b07SGordon Ross hints.ai_socktype = SOCK_STREAM; 458b3700b07SGordon Ross host = NULL; 459b3700b07SGordon Ross 460e3c2d6aaSnw i = 0; 461e3c2d6aaSnw while (i < count && scf_iter_next_value(iter, value) > 0) { 462b3700b07SGordon Ross if (host) { 463b3700b07SGordon Ross free(host); 464b3700b07SGordon Ross host = NULL; 465b3700b07SGordon Ross } 466e3c2d6aaSnw servers[i].priority = 0; 467e3c2d6aaSnw servers[i].weight = 100; 468e3c2d6aaSnw servers[i].port = defport; 469b3700b07SGordon Ross if ((host = scf_value2string(name, value)) == NULL) 470b3700b07SGordon Ross continue; 471c8e26105Sjp if ((portstr = strchr(host, ':')) != NULL) { 472c8e26105Sjp *portstr++ = '\0'; 473e3c2d6aaSnw servers[i].port = strtol(portstr, 474c8e26105Sjp (char **)NULL, 10); 475e3c2d6aaSnw if (servers[i].port == 0) 476e3c2d6aaSnw servers[i].port = defport; 477c8e26105Sjp } 478c8e26105Sjp 479b3700b07SGordon Ross /* 480b3700b07SGordon Ross * Ignore this server if the hostname is too long 481b3700b07SGordon Ross * or empty (continue without i++) 482b3700b07SGordon Ross */ 483b3700b07SGordon Ross len = strlen(host); 484b3700b07SGordon Ross if (len == 0) { 485b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 486b3700b07SGordon Ross idmapdlog(LOG_INFO, "%s host=\"\"", name); 487b3700b07SGordon Ross } 488b3700b07SGordon Ross continue; 489b3700b07SGordon Ross } 490b3700b07SGordon Ross if (len >= sizeof (servers->host)) { 491b3700b07SGordon Ross idmapdlog(LOG_ERR, "Host name too long: %s", host); 492b3700b07SGordon Ross idmapdlog(LOG_ERR, "ignoring %s value", name); 493b3700b07SGordon Ross continue; 494b3700b07SGordon Ross } 495b3700b07SGordon Ross 496b3700b07SGordon Ross /* 497b3700b07SGordon Ross * Get the host address too. If we can't, then 498b3700b07SGordon Ross * log an error and skip this host. 499b3700b07SGordon Ross */ 500b3700b07SGordon Ross (void) snprintf(port_str, sizeof (port_str), 501b3700b07SGordon Ross "%d", servers[i].port); 502b3700b07SGordon Ross ai = NULL; 503b3700b07SGordon Ross err = getaddrinfo(host, port_str, &hints, &ai); 504b3700b07SGordon Ross if (err != 0) { 505b3700b07SGordon Ross idmapdlog(LOG_ERR, "No address for host: %s (%s)", 506b3700b07SGordon Ross host, gai_strerror(err)); 507b3700b07SGordon Ross idmapdlog(LOG_ERR, "ignoring %s value", name); 508b3700b07SGordon Ross continue; 509b3700b07SGordon Ross } 510b3700b07SGordon Ross 511b3700b07SGordon Ross (void) strlcpy(servers[i].host, host, 512b3700b07SGordon Ross sizeof (servers->host)); 513b3700b07SGordon Ross (void) memcpy(&servers[i].addr, ai->ai_addr, ai->ai_addrlen); 514b3700b07SGordon Ross freeaddrinfo(ai); 515c8e26105Sjp 516b3700b07SGordon Ross /* Added a DS to the array. */ 517b3700b07SGordon Ross i++; 518c8e26105Sjp } 519b3700b07SGordon Ross free(host); 520c8e26105Sjp 521b3700b07SGordon Ross if (i == 0) { 522b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 523b3700b07SGordon Ross idmapdlog(LOG_INFO, "%s is empty", name); 524b3700b07SGordon Ross } 525b3700b07SGordon Ross free(servers); 526b3700b07SGordon Ross servers = NULL; 527b3700b07SGordon Ross } 528c8e26105Sjp *val = servers; 529c8e26105Sjp 530e3c2d6aaSnw rc = 0; 531e3c2d6aaSnw 532c8e26105Sjp destruction: 533c8e26105Sjp scf_value_destroy(value); 534c8e26105Sjp scf_iter_destroy(iter); 535c8e26105Sjp scf_property_destroy(scf_prop); 536c8e26105Sjp 537c8e26105Sjp if (rc < 0) { 538c8e26105Sjp if (servers) 539c8e26105Sjp free(servers); 540c8e26105Sjp *val = NULL; 541c8e26105Sjp } 542c8e26105Sjp 543c8e26105Sjp return (rc); 544c8e26105Sjp } 545c8e26105Sjp 546c5c4113dSnw static int 547e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val) 548c5c4113dSnw { 549c5c4113dSnw int rc = 0; 550c5c4113dSnw 551479ac375Sdm scf_property_t *scf_prop; 552479ac375Sdm scf_value_t *value; 553479ac375Sdm 554479ac375Sdm scf_prop = scf_property_create(handles->main); 555479ac375Sdm if (scf_prop == NULL) { 556479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 557479ac375Sdm scf_strerror(scf_error())); 558479ac375Sdm return (-1); 559479ac375Sdm } 560479ac375Sdm value = scf_value_create(handles->main); 561479ac375Sdm if (value == NULL) { 562479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 563479ac375Sdm scf_strerror(scf_error())); 564479ac375Sdm scf_property_destroy(scf_prop); 565479ac375Sdm return (-1); 566479ac375Sdm } 567c5c4113dSnw 568c8e26105Sjp *val = NULL; 569c5c4113dSnw 570c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 571c5c4113dSnw /* this is OK: the property is just undefined */ 572c5c4113dSnw goto destruction; 573c5c4113dSnw 574c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) { 575651c0131Sbaban idmapdlog(LOG_ERR, 57671590c90Snw "scf_property_get_value(%s) failed: %s", 57771590c90Snw name, scf_strerror(scf_error())); 578c5c4113dSnw rc = -1; 579c5c4113dSnw goto destruction; 580c5c4113dSnw } 581c5c4113dSnw 582e3f2c991SKeyur Desai *val = scf_value2string(name, value); 583e3f2c991SKeyur Desai if (*val == NULL) 584c5c4113dSnw rc = -1; 585c5c4113dSnw 586c5c4113dSnw destruction: 587c5c4113dSnw scf_value_destroy(value); 588c5c4113dSnw scf_property_destroy(scf_prop); 589c5c4113dSnw 590c5c4113dSnw if (rc < 0) { 591c5c4113dSnw if (*val) 592c5c4113dSnw free(*val); 593c5c4113dSnw *val = NULL; 594c5c4113dSnw } 595c5c4113dSnw 596c5c4113dSnw return (rc); 597c5c4113dSnw } 598c5c4113dSnw 599c8e26105Sjp 6008edda628Sbaban static int 601148c5f43SAlan Wright del_val( 602148c5f43SAlan Wright idmap_cfg_handles_t *handles, 603148c5f43SAlan Wright scf_propertygroup_t *pg, 604148c5f43SAlan Wright const char *name) 605e3f2c991SKeyur Desai { 606e3f2c991SKeyur Desai int rc = -1; 607e3f2c991SKeyur Desai int ret; 608e3f2c991SKeyur Desai scf_transaction_t *tx = NULL; 609e3f2c991SKeyur Desai scf_transaction_entry_t *ent = NULL; 610e3f2c991SKeyur Desai 611e3f2c991SKeyur Desai if ((tx = scf_transaction_create(handles->main)) == NULL) { 612e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 613e3f2c991SKeyur Desai "scf_transaction_create() failed: %s", 614e3f2c991SKeyur Desai scf_strerror(scf_error())); 615e3f2c991SKeyur Desai goto destruction; 616e3f2c991SKeyur Desai } 617e3f2c991SKeyur Desai if ((ent = scf_entry_create(handles->main)) == NULL) { 618e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 619e3f2c991SKeyur Desai "scf_entry_create() failed: %s", 620e3f2c991SKeyur Desai scf_strerror(scf_error())); 621e3f2c991SKeyur Desai goto destruction; 622e3f2c991SKeyur Desai } 623e3f2c991SKeyur Desai 624e3f2c991SKeyur Desai do { 625148c5f43SAlan Wright if (scf_pg_update(pg) == -1) { 626e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 627e3f2c991SKeyur Desai "scf_pg_update(%s) failed: %s", 628e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 629e3f2c991SKeyur Desai goto destruction; 630e3f2c991SKeyur Desai } 631148c5f43SAlan Wright if (scf_transaction_start(tx, pg) != 0) { 632e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 633e3f2c991SKeyur Desai "scf_transaction_start(%s) failed: %s", 634e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 635e3f2c991SKeyur Desai goto destruction; 636e3f2c991SKeyur Desai } 637e3f2c991SKeyur Desai 638e3f2c991SKeyur Desai if (scf_transaction_property_delete(tx, ent, name) != 0) { 639e3f2c991SKeyur Desai /* Don't complain if it already doesn't exist. */ 640e3f2c991SKeyur Desai if (scf_error() != SCF_ERROR_NOT_FOUND) { 641e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 642e3f2c991SKeyur Desai "scf_transaction_property_delete() failed:" 643e3f2c991SKeyur Desai " %s", 644e3f2c991SKeyur Desai scf_strerror(scf_error())); 645e3f2c991SKeyur Desai } 646e3f2c991SKeyur Desai goto destruction; 647e3f2c991SKeyur Desai } 648e3f2c991SKeyur Desai 649e3f2c991SKeyur Desai ret = scf_transaction_commit(tx); 650e3f2c991SKeyur Desai 651e3f2c991SKeyur Desai if (ret == 0) 652e3f2c991SKeyur Desai scf_transaction_reset(tx); 653e3f2c991SKeyur Desai } while (ret == 0); 654e3f2c991SKeyur Desai 655e3f2c991SKeyur Desai if (ret == -1) { 656e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 657e3f2c991SKeyur Desai "scf_transaction_commit(%s) failed: %s", 658e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 659e3f2c991SKeyur Desai goto destruction; 660e3f2c991SKeyur Desai } 661e3f2c991SKeyur Desai 662e3f2c991SKeyur Desai rc = 0; 663e3f2c991SKeyur Desai 664e3f2c991SKeyur Desai destruction: 665e3f2c991SKeyur Desai if (ent != NULL) 666e3f2c991SKeyur Desai scf_entry_destroy(ent); 667e3f2c991SKeyur Desai if (tx != NULL) 668e3f2c991SKeyur Desai scf_transaction_destroy(tx); 669e3f2c991SKeyur Desai return (rc); 670e3f2c991SKeyur Desai } 671e3f2c991SKeyur Desai 672e3f2c991SKeyur Desai 673e3f2c991SKeyur Desai static int 674148c5f43SAlan Wright set_val( 675148c5f43SAlan Wright idmap_cfg_handles_t *handles, 676148c5f43SAlan Wright scf_propertygroup_t *pg, 677148c5f43SAlan Wright const char *name, 678148c5f43SAlan Wright scf_value_t *value) 6798edda628Sbaban { 680e3c2d6aaSnw int rc = -1; 681e3c2d6aaSnw int i; 682148c5f43SAlan Wright scf_property_t *prop = NULL; 6838edda628Sbaban scf_transaction_t *tx = NULL; 6848edda628Sbaban scf_transaction_entry_t *ent = NULL; 6858edda628Sbaban 686148c5f43SAlan Wright if ((prop = scf_property_create(handles->main)) == NULL || 687c8e26105Sjp (tx = scf_transaction_create(handles->main)) == NULL || 688c8e26105Sjp (ent = scf_entry_create(handles->main)) == NULL) { 68971590c90Snw idmapdlog(LOG_ERR, "Unable to set property %s", 69071590c90Snw name, scf_strerror(scf_error())); 6918edda628Sbaban goto destruction; 6928edda628Sbaban } 6938edda628Sbaban 694148c5f43SAlan Wright for (i = 0; i < MAX_TRIES; i++) { 695148c5f43SAlan Wright int ret; 696148c5f43SAlan Wright 697148c5f43SAlan Wright if (scf_pg_update(pg) == -1) { 6988edda628Sbaban idmapdlog(LOG_ERR, 699148c5f43SAlan Wright "scf_pg_update() failed: %s", 700148c5f43SAlan Wright scf_strerror(scf_error())); 7018edda628Sbaban goto destruction; 7028edda628Sbaban } 7038edda628Sbaban 704148c5f43SAlan Wright if (scf_transaction_start(tx, pg) == -1) { 7058edda628Sbaban idmapdlog(LOG_ERR, 706148c5f43SAlan Wright "scf_transaction_start(%s) failed: %s", 707148c5f43SAlan Wright name, scf_strerror(scf_error())); 7088edda628Sbaban goto destruction; 7098edda628Sbaban } 7108edda628Sbaban 711148c5f43SAlan Wright ret = scf_pg_get_property(pg, name, prop); 712148c5f43SAlan Wright if (ret == SCF_SUCCESS) { 713148c5f43SAlan Wright if (scf_transaction_property_change_type(tx, ent, name, 714148c5f43SAlan Wright scf_value_type(value)) < 0) { 715148c5f43SAlan Wright idmapdlog(LOG_ERR, 716148c5f43SAlan Wright "scf_transaction_property_change_type(%s)" 717148c5f43SAlan Wright " failed: %s", 718148c5f43SAlan Wright name, scf_strerror(scf_error())); 719148c5f43SAlan Wright goto destruction; 720148c5f43SAlan Wright } 721148c5f43SAlan Wright } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 722148c5f43SAlan Wright if (scf_transaction_property_new(tx, ent, name, 723148c5f43SAlan Wright scf_value_type(value)) < 0) { 724148c5f43SAlan Wright idmapdlog(LOG_ERR, 725148c5f43SAlan Wright "scf_transaction_property_new() failed: %s", 726148c5f43SAlan Wright scf_strerror(scf_error())); 727148c5f43SAlan Wright goto destruction; 728148c5f43SAlan Wright } 729148c5f43SAlan Wright } else { 7308edda628Sbaban idmapdlog(LOG_ERR, 731148c5f43SAlan Wright "scf_pg_get_property(%s) failed: %s", 732148c5f43SAlan Wright name, scf_strerror(scf_error())); 7338edda628Sbaban goto destruction; 7348edda628Sbaban } 7358edda628Sbaban 7368edda628Sbaban if (scf_entry_add_value(ent, value) == -1) { 7378edda628Sbaban idmapdlog(LOG_ERR, 73871590c90Snw "scf_entry_add_value() failed: %s", 73971590c90Snw scf_strerror(scf_error())); 7408edda628Sbaban goto destruction; 7418edda628Sbaban } 7428edda628Sbaban 743148c5f43SAlan Wright ret = scf_transaction_commit(tx); 744148c5f43SAlan Wright if (ret == 0) { 7458edda628Sbaban /* 7468edda628Sbaban * Property group set in scf_transaction_start() 7478edda628Sbaban * is not the most recent. Update pg, reset tx and 7488edda628Sbaban * retry tx. 7498edda628Sbaban */ 7508edda628Sbaban idmapdlog(LOG_WARNING, 751148c5f43SAlan Wright "scf_transaction_commit(%s) failed: %s", 75271590c90Snw name, scf_strerror(scf_error())); 7538edda628Sbaban scf_transaction_reset(tx); 754148c5f43SAlan Wright continue; 755148c5f43SAlan Wright } 756148c5f43SAlan Wright if (ret != 1) { 757148c5f43SAlan Wright idmapdlog(LOG_ERR, 758148c5f43SAlan Wright "scf_transaction_commit(%s) failed: %s", 759148c5f43SAlan Wright name, scf_strerror(scf_error())); 760148c5f43SAlan Wright goto destruction; 7618edda628Sbaban } 762148c5f43SAlan Wright /* Success! */ 763148c5f43SAlan Wright rc = 0; 764148c5f43SAlan Wright break; 7658edda628Sbaban } 7668edda628Sbaban 767148c5f43SAlan Wright destruction: 768148c5f43SAlan Wright scf_entry_destroy(ent); 769148c5f43SAlan Wright scf_transaction_destroy(tx); 770148c5f43SAlan Wright scf_property_destroy(prop); 771148c5f43SAlan Wright return (rc); 772148c5f43SAlan Wright } 773e3c2d6aaSnw 774148c5f43SAlan Wright static int 775148c5f43SAlan Wright set_val_integer( 776148c5f43SAlan Wright idmap_cfg_handles_t *handles, 777148c5f43SAlan Wright scf_propertygroup_t *pg, 778148c5f43SAlan Wright const char *name, 779148c5f43SAlan Wright int64_t val) 780148c5f43SAlan Wright { 781148c5f43SAlan Wright scf_value_t *value = NULL; 782148c5f43SAlan Wright int rc; 783148c5f43SAlan Wright 784148c5f43SAlan Wright if ((value = scf_value_create(handles->main)) == NULL) { 785148c5f43SAlan Wright idmapdlog(LOG_ERR, "Unable to set property %s", 78671590c90Snw name, scf_strerror(scf_error())); 787148c5f43SAlan Wright return (-1); 788148c5f43SAlan Wright } 789148c5f43SAlan Wright 790148c5f43SAlan Wright scf_value_set_integer(value, val); 791148c5f43SAlan Wright 792148c5f43SAlan Wright rc = set_val(handles, pg, name, value); 7938edda628Sbaban 7948edda628Sbaban scf_value_destroy(value); 795148c5f43SAlan Wright 796148c5f43SAlan Wright return (rc); 797148c5f43SAlan Wright } 798148c5f43SAlan Wright 799148c5f43SAlan Wright 800148c5f43SAlan Wright static int 801148c5f43SAlan Wright set_val_astring( 802148c5f43SAlan Wright idmap_cfg_handles_t *handles, 803148c5f43SAlan Wright scf_propertygroup_t *pg, 804148c5f43SAlan Wright const char *name, 805148c5f43SAlan Wright const char *val) 806148c5f43SAlan Wright { 807148c5f43SAlan Wright scf_value_t *value = NULL; 808148c5f43SAlan Wright int rc = -1; 809148c5f43SAlan Wright 810148c5f43SAlan Wright if ((value = scf_value_create(handles->main)) == NULL) { 811148c5f43SAlan Wright idmapdlog(LOG_ERR, "Unable to set property %s", 812148c5f43SAlan Wright name, scf_strerror(scf_error())); 813148c5f43SAlan Wright goto out; 814148c5f43SAlan Wright } 815148c5f43SAlan Wright 816148c5f43SAlan Wright if (scf_value_set_astring(value, val) == -1) { 817148c5f43SAlan Wright idmapdlog(LOG_ERR, 818148c5f43SAlan Wright "scf_value_set_astring() failed: %s", 819148c5f43SAlan Wright scf_strerror(scf_error())); 820148c5f43SAlan Wright goto out; 821148c5f43SAlan Wright } 822148c5f43SAlan Wright 823148c5f43SAlan Wright rc = set_val(handles, pg, name, value); 824148c5f43SAlan Wright 825148c5f43SAlan Wright out: 826148c5f43SAlan Wright scf_value_destroy(value); 8278edda628Sbaban return (rc); 8288edda628Sbaban } 8298edda628Sbaban 8304d61c878SJulian Pullen 8314d61c878SJulian Pullen 8324d61c878SJulian Pullen /* 8334d61c878SJulian Pullen * This function updates a boolean value. 8344d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 8354d61c878SJulian Pullen */ 836c8e26105Sjp static int 8377a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name) 8384aa0a5e7Snw { 8394aa0a5e7Snw if (*value == *new) 8404aa0a5e7Snw return (0); 8414aa0a5e7Snw 842148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 843148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 844148c5f43SAlan Wright *new ? "true" : "false"); 845148c5f43SAlan Wright } 846148c5f43SAlan Wright 8474aa0a5e7Snw *value = *new; 8484aa0a5e7Snw return (1); 8494aa0a5e7Snw } 8504aa0a5e7Snw 85148cd229bSGordon Ross /* 85248cd229bSGordon Ross * This function updates a uint64_t value. 85348cd229bSGordon Ross * If nothing has changed it returns 0 else 1 85448cd229bSGordon Ross */ 85548cd229bSGordon Ross static int 85648cd229bSGordon Ross update_uint64(uint64_t *value, uint64_t *new, char *name) 85748cd229bSGordon Ross { 85848cd229bSGordon Ross if (*value == *new) 85948cd229bSGordon Ross return (0); 86048cd229bSGordon Ross 86148cd229bSGordon Ross if (DBG(CONFIG, 1)) 86248cd229bSGordon Ross idmapdlog(LOG_INFO, "change %s=%llu", name, *new); 86348cd229bSGordon Ross 86448cd229bSGordon Ross *value = *new; 86548cd229bSGordon Ross return (1); 86648cd229bSGordon Ross } 86748cd229bSGordon Ross 8684d61c878SJulian Pullen /* 8694d61c878SJulian Pullen * This function updates a string value. 8704d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 8714d61c878SJulian Pullen */ 8724aa0a5e7Snw static int 8734aa0a5e7Snw update_string(char **value, char **new, char *name) 874c8e26105Sjp { 875148c5f43SAlan Wright int changed; 876148c5f43SAlan Wright 877148c5f43SAlan Wright if (*new == NULL && *value != NULL) 878148c5f43SAlan Wright changed = 1; 879148c5f43SAlan Wright else if (*new != NULL && *value == NULL) 880148c5f43SAlan Wright changed = 1; 881148c5f43SAlan Wright else if (*new != NULL && *value != NULL && strcmp(*new, *value) != 0) 882148c5f43SAlan Wright changed = 1; 883148c5f43SAlan Wright else 884148c5f43SAlan Wright changed = 0; 885c8e26105Sjp 886148c5f43SAlan Wright /* 887148c5f43SAlan Wright * Note that even if unchanged we can't just return; we must free one 888148c5f43SAlan Wright * of the values. 889148c5f43SAlan Wright */ 890c8e26105Sjp 891148c5f43SAlan Wright if (DBG(CONFIG, 1) && changed) 892148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new)); 893148c5f43SAlan Wright 894148c5f43SAlan Wright free(*value); 895c8e26105Sjp *value = *new; 896c8e26105Sjp *new = NULL; 897148c5f43SAlan Wright return (changed); 898c8e26105Sjp } 899c8e26105Sjp 900e3f2c991SKeyur Desai static int 901e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map) 902e3f2c991SKeyur Desai { 903e3f2c991SKeyur Desai if (*value == *new) 904e3f2c991SKeyur Desai return (0); 905e3f2c991SKeyur Desai 906148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 907148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 908148c5f43SAlan Wright enum_lookup(*new, map)); 909148c5f43SAlan Wright } 910e3f2c991SKeyur Desai 911e3f2c991SKeyur Desai *value = *new; 912e3f2c991SKeyur Desai 913e3f2c991SKeyur Desai return (1); 914e3f2c991SKeyur Desai } 9154d61c878SJulian Pullen 9164d61c878SJulian Pullen /* 9174d61c878SJulian Pullen * This function updates a directory service structure. 9184d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 9194d61c878SJulian Pullen */ 920c8e26105Sjp static int 921b3700b07SGordon Ross update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name) 922c8e26105Sjp { 923c8e26105Sjp 9240dcc7149Snw if (*value == *new) 9250dcc7149Snw /* Nothing to do */ 926349d5d8fSnw return (0); 927c8e26105Sjp 9280dcc7149Snw if (*value != NULL && *new != NULL && 9290dcc7149Snw ad_disc_compare_ds(*value, *new) == 0) { 930c8e26105Sjp free(*new); 931c8e26105Sjp *new = NULL; 932349d5d8fSnw return (0); 933c8e26105Sjp } 934c8e26105Sjp 9354d61c878SJulian Pullen if (*value != NULL) 936c8e26105Sjp free(*value); 937c8e26105Sjp 938c8e26105Sjp *value = *new; 939c8e26105Sjp *new = NULL; 9400dcc7149Snw 9410dcc7149Snw if (*value == NULL) { 9420dcc7149Snw /* We're unsetting this DS property */ 943148c5f43SAlan Wright if (DBG(CONFIG, 1)) 944148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 945349d5d8fSnw return (1); 9460dcc7149Snw } 9470dcc7149Snw 948148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 949148c5f43SAlan Wright /* List all the new DSs */ 950b3700b07SGordon Ross char buf[64]; 951b3700b07SGordon Ross ad_disc_ds_t *ds; 952b3700b07SGordon Ross for (ds = *value; ds->host[0] != '\0'; ds++) { 953b3700b07SGordon Ross if (ad_disc_getnameinfo(buf, sizeof (buf), &ds->addr)) 954b3700b07SGordon Ross (void) strlcpy(buf, "?", sizeof (buf)); 955b3700b07SGordon Ross idmapdlog(LOG_INFO, "change %s=%s addr=%s port=%d", 956b3700b07SGordon Ross name, ds->host, buf, ds->port); 957148c5f43SAlan Wright } 958148c5f43SAlan Wright } 959349d5d8fSnw return (1); 960c8e26105Sjp } 961c8e26105Sjp 9624d61c878SJulian Pullen /* 9634d61c878SJulian Pullen * This function updates a trusted domains structure. 9644d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 9654d61c878SJulian Pullen */ 9664d61c878SJulian Pullen static int 9674d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value, 9684d61c878SJulian Pullen ad_disc_trusteddomains_t **new, char *name) 9694d61c878SJulian Pullen { 9704d61c878SJulian Pullen int i; 9714d61c878SJulian Pullen 9724d61c878SJulian Pullen if (*value == *new) 9734d61c878SJulian Pullen /* Nothing to do */ 9744d61c878SJulian Pullen return (0); 9754d61c878SJulian Pullen 9764d61c878SJulian Pullen if (*value != NULL && *new != NULL && 9774d61c878SJulian Pullen ad_disc_compare_trusteddomains(*value, *new) == 0) { 9784d61c878SJulian Pullen free(*new); 9794d61c878SJulian Pullen *new = NULL; 9804d61c878SJulian Pullen return (0); 9814d61c878SJulian Pullen } 9824d61c878SJulian Pullen 9834d61c878SJulian Pullen if (*value != NULL) 9844d61c878SJulian Pullen free(*value); 9854d61c878SJulian Pullen 9864d61c878SJulian Pullen *value = *new; 9874d61c878SJulian Pullen *new = NULL; 9884d61c878SJulian Pullen 9894d61c878SJulian Pullen if (*value == NULL) { 9904d61c878SJulian Pullen /* We're unsetting this DS property */ 991148c5f43SAlan Wright if (DBG(CONFIG, 1)) 992148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 9934d61c878SJulian Pullen return (1); 9944d61c878SJulian Pullen } 9954d61c878SJulian Pullen 996148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 997148c5f43SAlan Wright /* List all the new domains */ 998148c5f43SAlan Wright for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 999148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s direction=%s", name, 1000148c5f43SAlan Wright (*value)[i].domain, 1001148c5f43SAlan Wright enum_lookup((*value)[i].direction, trust_dir_map)); 1002148c5f43SAlan Wright } 1003148c5f43SAlan Wright } 10044d61c878SJulian Pullen return (1); 10054d61c878SJulian Pullen } 10064d61c878SJulian Pullen 10074d61c878SJulian Pullen 10084d61c878SJulian Pullen /* 10094d61c878SJulian Pullen * This function updates a domains in a forest structure. 10104d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 10114d61c878SJulian Pullen */ 10124d61c878SJulian Pullen static int 10134d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value, 10144d61c878SJulian Pullen ad_disc_domainsinforest_t **new, char *name) 10154d61c878SJulian Pullen { 10164d61c878SJulian Pullen int i; 10174d61c878SJulian Pullen 10184d61c878SJulian Pullen if (*value == *new) 10194d61c878SJulian Pullen /* Nothing to do */ 10204d61c878SJulian Pullen return (0); 10214d61c878SJulian Pullen 10224d61c878SJulian Pullen if (*value != NULL && *new != NULL && 10234d61c878SJulian Pullen ad_disc_compare_domainsinforest(*value, *new) == 0) { 10244d61c878SJulian Pullen free(*new); 10254d61c878SJulian Pullen *new = NULL; 10264d61c878SJulian Pullen return (0); 10274d61c878SJulian Pullen } 10284d61c878SJulian Pullen 10294d61c878SJulian Pullen if (*value != NULL) 10304d61c878SJulian Pullen free(*value); 10314d61c878SJulian Pullen 10324d61c878SJulian Pullen *value = *new; 10334d61c878SJulian Pullen *new = NULL; 10344d61c878SJulian Pullen 10354d61c878SJulian Pullen if (*value == NULL) { 10364d61c878SJulian Pullen /* We're unsetting this DS property */ 1037148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1038148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 10394d61c878SJulian Pullen return (1); 10404d61c878SJulian Pullen } 10414d61c878SJulian Pullen 1042148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1043148c5f43SAlan Wright /* List all the new domains */ 1044148c5f43SAlan Wright for (i = 0; (*value)[i].domain[0] != '\0'; i++) { 1045148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=%s", name, 1046148c5f43SAlan Wright (*value)[i].domain); 1047148c5f43SAlan Wright } 1048148c5f43SAlan Wright } 10494d61c878SJulian Pullen return (1); 10504d61c878SJulian Pullen } 10514d61c878SJulian Pullen 10524d61c878SJulian Pullen 10534d61c878SJulian Pullen static void 10544d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values) 10554d61c878SJulian Pullen { 10564d61c878SJulian Pullen int i; 10574d61c878SJulian Pullen 10584d61c878SJulian Pullen for (i = 0; i < *num_values; i++) { 10594d61c878SJulian Pullen free((*value)[i].forest_name); 10604d61c878SJulian Pullen free((*value)[i].global_catalog); 10614d61c878SJulian Pullen free((*value)[i].domains_in_forest); 10624d61c878SJulian Pullen } 10634d61c878SJulian Pullen free(*value); 10644d61c878SJulian Pullen *value = NULL; 10654d61c878SJulian Pullen *num_values = 0; 10664d61c878SJulian Pullen } 10674d61c878SJulian Pullen 10684d61c878SJulian Pullen 10694d61c878SJulian Pullen static int 10704d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1, 10714d61c878SJulian Pullen ad_disc_domainsinforest_t *df2) 10724d61c878SJulian Pullen { 10737a8a68f5SJulian Pullen int i, j; 10747a8a68f5SJulian Pullen int num_df1 = 0; 10757a8a68f5SJulian Pullen int num_df2 = 0; 10767a8a68f5SJulian Pullen boolean_t match; 10774d61c878SJulian Pullen 10784d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) 10794d61c878SJulian Pullen if (df1[i].trusted) 10804d61c878SJulian Pullen num_df1++; 10814d61c878SJulian Pullen 10824d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) 10834d61c878SJulian Pullen if (df2[j].trusted) 10844d61c878SJulian Pullen num_df2++; 10854d61c878SJulian Pullen 10864d61c878SJulian Pullen if (num_df1 != num_df2) 10874d61c878SJulian Pullen return (1); 10884d61c878SJulian Pullen 10894d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) { 10904d61c878SJulian Pullen if (df1[i].trusted) { 10917a8a68f5SJulian Pullen match = B_FALSE; 10924d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) { 10934d61c878SJulian Pullen if (df2[j].trusted && 10941fcced4cSJordan Brown domain_eq(df1[i].domain, df2[j].domain) && 10951fcced4cSJordan Brown strcmp(df1[i].sid, df2[j].sid) == 0) { 10967a8a68f5SJulian Pullen match = B_TRUE; 10974d61c878SJulian Pullen break; 10984d61c878SJulian Pullen } 10994d61c878SJulian Pullen } 11004d61c878SJulian Pullen if (!match) 11014d61c878SJulian Pullen return (1); 11024d61c878SJulian Pullen } 11034d61c878SJulian Pullen } 11044d61c878SJulian Pullen return (0); 11054d61c878SJulian Pullen } 11064d61c878SJulian Pullen 11074d61c878SJulian Pullen 11084d61c878SJulian Pullen 11094d61c878SJulian Pullen /* 11104d61c878SJulian Pullen * This function updates trusted forest structure. 11114d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 11124d61c878SJulian Pullen */ 11134d61c878SJulian Pullen static int 11144d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value, 11154d61c878SJulian Pullen idmap_trustedforest_t **new, int *num_new, char *name) 11164d61c878SJulian Pullen { 11174d61c878SJulian Pullen int i, j; 11187a8a68f5SJulian Pullen boolean_t match; 11194d61c878SJulian Pullen 11204d61c878SJulian Pullen if (*value == *new) 11214d61c878SJulian Pullen /* Nothing to do */ 11224d61c878SJulian Pullen return (0); 11234d61c878SJulian Pullen 11244d61c878SJulian Pullen if (*value != NULL && *new != NULL) { 11254d61c878SJulian Pullen if (*num_value != *num_new) 11264d61c878SJulian Pullen goto not_equal; 11274d61c878SJulian Pullen for (i = 0; i < *num_value; i++) { 11287a8a68f5SJulian Pullen match = B_FALSE; 11294d61c878SJulian Pullen for (j = 0; j < *num_new; j++) { 11304d61c878SJulian Pullen if (strcmp((*value)[i].forest_name, 11314d61c878SJulian Pullen (*new)[j].forest_name) == 0 && 11324d61c878SJulian Pullen ad_disc_compare_ds( 11334d61c878SJulian Pullen (*value)[i].global_catalog, 11341fcced4cSJordan Brown (*new)[j].global_catalog) == 0 && 11354d61c878SJulian Pullen compare_trusteddomainsinforest( 11364d61c878SJulian Pullen (*value)[i].domains_in_forest, 11371fcced4cSJordan Brown (*new)[j].domains_in_forest) == 0) { 11387a8a68f5SJulian Pullen match = B_TRUE; 11394d61c878SJulian Pullen break; 11404d61c878SJulian Pullen } 11414d61c878SJulian Pullen } 11424d61c878SJulian Pullen if (!match) 11434d61c878SJulian Pullen goto not_equal; 11444d61c878SJulian Pullen } 11454d61c878SJulian Pullen free_trusted_forests(new, num_new); 11464d61c878SJulian Pullen return (0); 11474d61c878SJulian Pullen } 11484d61c878SJulian Pullen not_equal: 11494d61c878SJulian Pullen if (*value != NULL) 11504d61c878SJulian Pullen free_trusted_forests(value, num_value); 11514d61c878SJulian Pullen *value = *new; 11524d61c878SJulian Pullen *num_value = *num_new; 11534d61c878SJulian Pullen *new = NULL; 11544d61c878SJulian Pullen *num_new = 0; 11554d61c878SJulian Pullen 11564d61c878SJulian Pullen if (*value == NULL) { 11574d61c878SJulian Pullen /* We're unsetting this DS property */ 1158148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1159148c5f43SAlan Wright idmapdlog(LOG_INFO, "change %s=<none>", name); 11604d61c878SJulian Pullen return (1); 11614d61c878SJulian Pullen } 11624d61c878SJulian Pullen 1163148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1164148c5f43SAlan Wright /* List all the trusted forests */ 1165148c5f43SAlan Wright for (i = 0; i < *num_value; i++) { 1166148c5f43SAlan Wright idmap_trustedforest_t *f = &(*value)[i]; 1167148c5f43SAlan Wright for (j = 0; 1168148c5f43SAlan Wright f->domains_in_forest[j].domain[0] != '\0'; 1169148c5f43SAlan Wright j++) { 1170148c5f43SAlan Wright /* List trusted Domains in the forest. */ 1171148c5f43SAlan Wright if (f->domains_in_forest[j].trusted) 1172148c5f43SAlan Wright idmapdlog(LOG_INFO, 1173148c5f43SAlan Wright "change %s=%s domain=%s", 1174148c5f43SAlan Wright name, f->forest_name, 1175148c5f43SAlan Wright f->domains_in_forest[j].domain); 1176148c5f43SAlan Wright } 1177148c5f43SAlan Wright /* List the hosts */ 1178148c5f43SAlan Wright for (j = 0; 1179148c5f43SAlan Wright f->global_catalog[j].host[0] != '\0'; 1180148c5f43SAlan Wright j++) { 1181148c5f43SAlan Wright idmapdlog(LOG_INFO, 1182148c5f43SAlan Wright "change %s=%s host=%s port=%d", 1183148c5f43SAlan Wright name, f->forest_name, 1184148c5f43SAlan Wright f->global_catalog[j].host, 1185148c5f43SAlan Wright f->global_catalog[j].port); 1186148c5f43SAlan Wright } 11874d61c878SJulian Pullen } 11884d61c878SJulian Pullen } 11894d61c878SJulian Pullen return (1); 11904d61c878SJulian Pullen } 11914d61c878SJulian Pullen 1192e3f2c991SKeyur Desai const char * 1193e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map) 1194e3f2c991SKeyur Desai { 1195e3f2c991SKeyur Desai for (; map->string != NULL; map++) { 1196e3f2c991SKeyur Desai if (value == map->value) { 1197e3f2c991SKeyur Desai return (map->string); 1198e3f2c991SKeyur Desai } 1199e3f2c991SKeyur Desai } 1200e3f2c991SKeyur Desai return ("(invalid)"); 1201e3f2c991SKeyur Desai } 1202c8e26105Sjp 1203c8e26105Sjp /* 12040dcc7149Snw * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the 12050dcc7149Snw * interfaces. 1206c8e26105Sjp * 12070dcc7149Snw * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON. 1208c8e26105Sjp */ 1209c8e26105Sjp static 1210c5866007SKeyur Desai boolean_t 12110dcc7149Snw pfroute_event_is_interesting(int rt_sock) 1212c8e26105Sjp { 12130dcc7149Snw int nbytes; 12140dcc7149Snw int64_t msg[2048 / 8]; 12150dcc7149Snw struct rt_msghdr *rtm; 1216c5866007SKeyur Desai boolean_t is_interesting = B_FALSE; 1217c8e26105Sjp 12180dcc7149Snw for (;;) { 12190dcc7149Snw if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0) 12200dcc7149Snw break; 12210dcc7149Snw rtm = (struct rt_msghdr *)msg; 12220dcc7149Snw if (rtm->rtm_version != RTM_VERSION) 12230dcc7149Snw continue; 12240dcc7149Snw if (nbytes < rtm->rtm_msglen) 12250dcc7149Snw continue; 12260dcc7149Snw switch (rtm->rtm_type) { 12270dcc7149Snw case RTM_NEWADDR: 12280dcc7149Snw case RTM_DELADDR: 12290dcc7149Snw case RTM_IFINFO: 1230c5866007SKeyur Desai is_interesting = B_TRUE; 12310dcc7149Snw break; 12320dcc7149Snw default: 12330dcc7149Snw break; 12340dcc7149Snw } 1235c8e26105Sjp } 12360dcc7149Snw return (is_interesting); 12370dcc7149Snw } 12380dcc7149Snw 12390dcc7149Snw /* 1240c5866007SKeyur Desai * Wait for an event, and report what kind of event occurred. 12410dcc7149Snw * 1242c5866007SKeyur Desai * Note that there are cases where we are awoken but don't care about 1243c5866007SKeyur Desai * the lower-level event. We can't just loop here because we can't 1244c5866007SKeyur Desai * readily calculate how long to sleep the next time. We return 1245c5866007SKeyur Desai * EVENT_NOTHING and let the caller loop. 12460dcc7149Snw */ 12470dcc7149Snw static 1248c5866007SKeyur Desai enum event_type 1249c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp) 12500dcc7149Snw { 12510dcc7149Snw port_event_t pe; 1252c8e26105Sjp 1253148c5f43SAlan Wright (void) memset(&pe, 0, sizeof (pe)); 1254349d5d8fSnw if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) { 1255c8e26105Sjp switch (errno) { 1256c8e26105Sjp case EINTR: 1257c5866007SKeyur Desai return (EVENT_NOTHING); 1258c8e26105Sjp case ETIME: 1259c8e26105Sjp /* Timeout */ 1260c5866007SKeyur Desai return (EVENT_TIMEOUT); 1261c8e26105Sjp default: 12620dcc7149Snw /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */ 12630dcc7149Snw idmapdlog(LOG_ERR, "Event port failed: %s", 12640dcc7149Snw strerror(errno)); 12650dcc7149Snw exit(1); 12660dcc7149Snw /* NOTREACHED */ 1267c8e26105Sjp } 1268c8e26105Sjp } 1269c8e26105Sjp 12700dcc7149Snw 1271c5866007SKeyur Desai switch (pe.portev_source) { 1272c5866007SKeyur Desai case 0: 12730dcc7149Snw /* 1274c5866007SKeyur Desai * This isn't documented, but seems to be what you get if 1275c5866007SKeyur Desai * the timeout is zero seconds and there are no events 1276c5866007SKeyur Desai * pending. 12770dcc7149Snw */ 1278c5866007SKeyur Desai return (EVENT_TIMEOUT); 1279c8e26105Sjp 1280c5866007SKeyur Desai case PORT_SOURCE_USER: 1281b3700b07SGordon Ross switch (pe.portev_events) { 1282b3700b07SGordon Ross case RECONFIGURE: 1283c5866007SKeyur Desai return (EVENT_REFRESH); 1284b3700b07SGordon Ross case POKE_AUTO_DISCOVERY: 1285b3700b07SGordon Ross return (EVENT_POKED); 1286b3700b07SGordon Ross case KICK_AUTO_DISCOVERY: 1287b3700b07SGordon Ross return (EVENT_KICKED); 1288b3700b07SGordon Ross } 1289b3700b07SGordon Ross return (EVENT_NOTHING); 1290e3c2d6aaSnw 1291c5866007SKeyur Desai case PORT_SOURCE_FD: 1292c5866007SKeyur Desai if (pe.portev_object == rt_sock) { 1293c5866007SKeyur Desai /* 1294c5866007SKeyur Desai * PF_ROUTE socket read event: 1295c5866007SKeyur Desai * re-associate fd 1296c5866007SKeyur Desai * handle event 1297c5866007SKeyur Desai */ 1298c5866007SKeyur Desai if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 1299c5866007SKeyur Desai rt_sock, POLLIN, NULL) != 0) { 1300c5866007SKeyur Desai idmapdlog(LOG_ERR, "Failed to re-associate the " 1301c5866007SKeyur Desai "routing socket with the event port: %s", 1302c5866007SKeyur Desai strerror(errno)); 1303c5866007SKeyur Desai abort(); 1304c5866007SKeyur Desai } 1305c5866007SKeyur Desai /* 1306c5866007SKeyur Desai * The network configuration may still be in flux. 1307c5866007SKeyur Desai * No matter, the resolver will re-transmit and 1308c5866007SKeyur Desai * timeout if need be. 1309c5866007SKeyur Desai */ 1310c5866007SKeyur Desai if (pfroute_event_is_interesting(rt_sock)) { 1311148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1312148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1313148c5f43SAlan Wright "Interesting routing event"); 1314148c5f43SAlan Wright } 1315c5866007SKeyur Desai return (EVENT_ROUTING); 1316c5866007SKeyur Desai } else { 1317148c5f43SAlan Wright if (DBG(CONFIG, 2)) { 1318148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1319148c5f43SAlan Wright "Boring routing event"); 1320148c5f43SAlan Wright } 1321c5866007SKeyur Desai return (EVENT_NOTHING); 1322c5866007SKeyur Desai } 1323349d5d8fSnw } 1324c5866007SKeyur Desai /* Event on an FD other than the routing FD? Ignore it. */ 1325c5866007SKeyur Desai break; 1326c8e26105Sjp } 1327c8e26105Sjp 1328c5866007SKeyur Desai return (EVENT_NOTHING); 1329c8e26105Sjp } 1330c8e26105Sjp 1331c8e26105Sjp void * 1332c8e26105Sjp idmap_cfg_update_thread(void *arg) 1333c8e26105Sjp { 1334148c5f43SAlan Wright NOTE(ARGUNUSED(arg)) 1335b3700b07SGordon Ross idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg; 1336c5866007SKeyur Desai const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx; 1337b3700b07SGordon Ross int flags = CFG_DISCOVER; 13380dcc7149Snw 1339c5866007SKeyur Desai for (;;) { 1340c5866007SKeyur Desai struct timespec timeout; 1341c5866007SKeyur Desai struct timespec *timeoutp; 1342c5866007SKeyur Desai int rc; 1343b3700b07SGordon Ross int ttl, max_ttl; 13440dcc7149Snw 13450dcc7149Snw (void) ad_disc_SubnetChanged(ad_ctx); 1346c8e26105Sjp 1347b3700b07SGordon Ross rc = idmap_cfg_load(_idmapdstate.cfg, flags); 1348c5866007SKeyur Desai if (rc < -1) { 13497a8a68f5SJulian Pullen idmapdlog(LOG_ERR, "Fatal errors while reading " 1350349d5d8fSnw "SMF properties"); 1351349d5d8fSnw exit(1); 1352c5866007SKeyur Desai } else if (rc == -1) { 1353c5866007SKeyur Desai idmapdlog(LOG_WARNING, 1354c5866007SKeyur Desai "Errors re-loading configuration may cause AD " 1355c5866007SKeyur Desai "lookups to fail"); 1356349d5d8fSnw } 1357c8e26105Sjp 1358c5866007SKeyur Desai /* 1359c5866007SKeyur Desai * Wait for an interesting event. Note that we might get 1360c5866007SKeyur Desai * boring events between interesting events. If so, we loop. 1361c5866007SKeyur Desai */ 1362b3700b07SGordon Ross flags = CFG_DISCOVER; 1363c5866007SKeyur Desai for (;;) { 1364b3700b07SGordon Ross /* 1365b3700b07SGordon Ross * If we don't know our domain name, don't bother 1366b3700b07SGordon Ross * with rediscovery until the next config change. 1367b3700b07SGordon Ross * Avoids hourly noise in workgroup mode. 1368b3700b07SGordon Ross */ 1369b3700b07SGordon Ross if (pgcfg->domain_name == NULL) 1370b3700b07SGordon Ross ttl = -1; 1371b3700b07SGordon Ross else 1372b3700b07SGordon Ross ttl = ad_disc_get_TTL(ad_ctx); 1373c5866007SKeyur Desai if (ttl < 0) { 1374c5866007SKeyur Desai timeoutp = NULL; 1375c5866007SKeyur Desai } else { 1376b3700b07SGordon Ross max_ttl = (int)pgcfg->rediscovery_interval; 1377b3700b07SGordon Ross if (ttl > max_ttl) 1378b3700b07SGordon Ross ttl = max_ttl; 1379b3700b07SGordon Ross if (ttl < MIN_REDISCOVERY_INTERVAL) 1380b3700b07SGordon Ross ttl = MIN_REDISCOVERY_INTERVAL; 1381c5866007SKeyur Desai timeout.tv_sec = ttl; 1382c5866007SKeyur Desai timeout.tv_nsec = 0; 1383b3700b07SGordon Ross timeoutp = &timeout; 1384c5866007SKeyur Desai } 1385c5866007SKeyur Desai 1386b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1387b3700b07SGordon Ross idmapdlog(LOG_DEBUG, 1388b3700b07SGordon Ross "_cfg_update_thread waiting"); 1389b3700b07SGordon Ross 1390c5866007SKeyur Desai switch (wait_for_event(timeoutp)) { 1391c5866007SKeyur Desai case EVENT_NOTHING: 1392148c5f43SAlan Wright if (DBG(CONFIG, 2)) 1393148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "Boring event."); 1394c5866007SKeyur Desai continue; 1395c5866007SKeyur Desai case EVENT_REFRESH: 1396148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1397148c5f43SAlan Wright idmapdlog(LOG_INFO, "SMF refresh"); 1398b3700b07SGordon Ross /* 1399b3700b07SGordon Ross * Forget any DC we had previously. 1400b3700b07SGordon Ross */ 1401b3700b07SGordon Ross flags |= CFG_FORGET_DC; 1402b3700b07SGordon Ross 1403c5866007SKeyur Desai /* 1404c5866007SKeyur Desai * Blow away the ccache, we might have 1405c5866007SKeyur Desai * re-joined the domain or joined a new one 1406c5866007SKeyur Desai */ 1407c5866007SKeyur Desai (void) unlink(IDMAP_CACHEDIR "/ccache"); 1408c5866007SKeyur Desai break; 1409b3700b07SGordon Ross case EVENT_POKED: 1410b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1411b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "poked"); 1412b3700b07SGordon Ross break; 1413b3700b07SGordon Ross case EVENT_KICKED: 1414b3700b07SGordon Ross if (DBG(CONFIG, 1)) 1415b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "kicked"); 1416b3700b07SGordon Ross flags |= CFG_FORGET_DC; 1417c5866007SKeyur Desai break; 1418c5866007SKeyur Desai case EVENT_TIMEOUT: 1419148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1420148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "TTL expired"); 1421c5866007SKeyur Desai break; 1422c5866007SKeyur Desai case EVENT_ROUTING: 1423c5866007SKeyur Desai /* Already logged to DEBUG */ 1424c5866007SKeyur Desai break; 1425c5866007SKeyur Desai } 1426c5866007SKeyur Desai /* An interesting event! */ 1427c5866007SKeyur Desai break; 1428c5866007SKeyur Desai } 1429c8e26105Sjp } 1430c5866007SKeyur Desai /* 1431c5866007SKeyur Desai * Lint isn't happy with the concept of a function declared to 1432c5866007SKeyur Desai * return something, that doesn't return. Of course, merely adding 1433c5866007SKeyur Desai * the return isn't enough, because it's never reached... 1434c5866007SKeyur Desai */ 1435c8e26105Sjp /*NOTREACHED*/ 1436c8e26105Sjp return (NULL); 1437c8e26105Sjp } 1438c8e26105Sjp 1439c8e26105Sjp int 14400dcc7149Snw idmap_cfg_start_updates(void) 1441c8e26105Sjp { 14420dcc7149Snw if ((idmapd_ev_port = port_create()) < 0) { 144371590c90Snw idmapdlog(LOG_ERR, "Failed to create event port: %s", 144471590c90Snw strerror(errno)); 1445c8e26105Sjp return (-1); 14460dcc7149Snw } 14470dcc7149Snw 14480dcc7149Snw if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 144971590c90Snw idmapdlog(LOG_ERR, "Failed to open routing socket: %s", 145071590c90Snw strerror(errno)); 14510dcc7149Snw (void) close(idmapd_ev_port); 14520dcc7149Snw return (-1); 14530dcc7149Snw } 14540dcc7149Snw 14550dcc7149Snw if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) { 145671590c90Snw idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s", 145771590c90Snw strerror(errno)); 14580dcc7149Snw (void) close(rt_sock); 14590dcc7149Snw (void) close(idmapd_ev_port); 14600dcc7149Snw return (-1); 14610dcc7149Snw } 14620dcc7149Snw 14630dcc7149Snw if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 14640dcc7149Snw rt_sock, POLLIN, NULL) != 0) { 146571590c90Snw idmapdlog(LOG_ERR, "Failed to associate the routing " 146671590c90Snw "socket with the event port: %s", strerror(errno)); 14670dcc7149Snw (void) close(rt_sock); 14680dcc7149Snw (void) close(idmapd_ev_port); 14690dcc7149Snw return (-1); 14700dcc7149Snw } 14710dcc7149Snw 14720dcc7149Snw if ((errno = pthread_create(&update_thread_handle, NULL, 14730dcc7149Snw idmap_cfg_update_thread, NULL)) != 0) { 147471590c90Snw idmapdlog(LOG_ERR, "Failed to start update thread: %s", 147571590c90Snw strerror(errno)); 14760dcc7149Snw (void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock); 14770dcc7149Snw (void) close(rt_sock); 14780dcc7149Snw (void) close(idmapd_ev_port); 14790dcc7149Snw return (-1); 14800dcc7149Snw } 14810dcc7149Snw 14820dcc7149Snw return (0); 1483c8e26105Sjp } 1484c8e26105Sjp 1485479ac375Sdm /* 1486479ac375Sdm * Reject attribute names with invalid characters. 1487479ac375Sdm */ 1488479ac375Sdm static 1489479ac375Sdm int 1490479ac375Sdm valid_ldap_attr(const char *attr) { 1491479ac375Sdm for (; *attr; attr++) { 1492479ac375Sdm if (!isalnum(*attr) && *attr != '-' && 1493479ac375Sdm *attr != '_' && *attr != '.' && *attr != ';') 1494479ac375Sdm return (0); 1495479ac375Sdm } 1496479ac375Sdm return (1); 1497479ac375Sdm } 1498479ac375Sdm 1499e3f2c991SKeyur Desai static 1500148c5f43SAlan Wright void 1501148c5f43SAlan Wright idmapd_set_debug( 1502148c5f43SAlan Wright idmap_cfg_handles_t *handles, 1503148c5f43SAlan Wright enum idmapd_debug item, 1504148c5f43SAlan Wright const char *name) 1505e3f2c991SKeyur Desai { 1506148c5f43SAlan Wright int val; 1507e3f2c991SKeyur Desai 1508148c5f43SAlan Wright if (item < 0 || item > IDMAPD_DEBUG_MAX) 1509148c5f43SAlan Wright return; 1510e3f2c991SKeyur Desai 1511148c5f43SAlan Wright val = get_debug(handles, name); 1512e3f2c991SKeyur Desai 1513148c5f43SAlan Wright if (val != _idmapdstate.debug[item]) 1514148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "%s/%s = %d", DEBUG_PG, name, val); 1515148c5f43SAlan Wright 1516148c5f43SAlan Wright _idmapdstate.debug[item] = val; 1517148c5f43SAlan Wright } 1518148c5f43SAlan Wright 1519148c5f43SAlan Wright static 1520148c5f43SAlan Wright void 1521148c5f43SAlan Wright check_smf_debug_mode(idmap_cfg_handles_t *handles) 1522148c5f43SAlan Wright { 1523148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_ALL, "all"); 1524148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_CONFIG, "config"); 1525148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_MAPPING, "mapping"); 1526148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_DISC, "discovery"); 1527148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_DNS, "dns"); 1528148c5f43SAlan Wright idmapd_set_debug(handles, IDMAPD_DEBUG_LDAP, "ldap"); 1529148c5f43SAlan Wright 1530148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_ALL, _idmapdstate.debug[IDMAPD_DEBUG_ALL]); 1531148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_DISC, _idmapdstate.debug[IDMAPD_DEBUG_DISC]); 1532148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_DNS, _idmapdstate.debug[IDMAPD_DEBUG_DNS]); 1533148c5f43SAlan Wright adutils_set_debug(AD_DEBUG_LDAP, _idmapdstate.debug[IDMAPD_DEBUG_LDAP]); 1534e3f2c991SKeyur Desai } 1535e3f2c991SKeyur Desai 1536349d5d8fSnw /* 1537349d5d8fSnw * This is the half of idmap_cfg_load() that loads property values from 1538349d5d8fSnw * SMF (using the config/ property group of the idmap FMRI). 1539349d5d8fSnw * 1540349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1541479ac375Sdm * -3 -> hard smf config failures 1542349d5d8fSnw * reading from SMF. 1543349d5d8fSnw */ 1544b3700b07SGordon Ross static int 1545349d5d8fSnw idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, 1546e3f2c991SKeyur Desai int * const errors) 1547c5c4113dSnw { 1548e3c2d6aaSnw int rc; 1549e3f2c991SKeyur Desai char *s; 1550e3f2c991SKeyur Desai 1551e3f2c991SKeyur Desai *errors = 0; 1552c8e26105Sjp 1553c8e26105Sjp if (scf_pg_update(handles->config_pg) < 0) { 155471590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 155571590c90Snw scf_strerror(scf_error())); 1556349d5d8fSnw return (-2); 1557c5c4113dSnw } 1558c5c4113dSnw 1559148c5f43SAlan Wright if (scf_pg_update(handles->debug_pg) < 0) { 156071590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 156171590c90Snw scf_strerror(scf_error())); 1562349d5d8fSnw return (-2); 1563c5c4113dSnw } 1564c5c4113dSnw 1565148c5f43SAlan Wright check_smf_debug_mode(handles); 1566148c5f43SAlan Wright 1567148c5f43SAlan Wright rc = get_val_bool(handles, "unresolvable_sid_mapping", 1568148c5f43SAlan Wright &pgcfg->eph_map_unres_sids, B_TRUE); 1569479ac375Sdm if (rc != 0) 1570e3f2c991SKeyur Desai (*errors)++; 157171590c90Snw 15721ed6b69aSGordon Ross rc = get_val_bool(handles, "use_ads", 15731ed6b69aSGordon Ross &pgcfg->use_ads, B_TRUE); 15741ed6b69aSGordon Ross if (rc != 0) 15751ed6b69aSGordon Ross (*errors)++; 15761ed6b69aSGordon Ross 1577148c5f43SAlan Wright rc = get_val_bool(handles, "use_lsa", 1578148c5f43SAlan Wright &pgcfg->use_lsa, B_TRUE); 1579148c5f43SAlan Wright if (rc != 0) 1580148c5f43SAlan Wright (*errors)++; 1581148c5f43SAlan Wright 1582148c5f43SAlan Wright rc = get_val_bool(handles, "disable_cross_forest_trusts", 1583148c5f43SAlan Wright &pgcfg->disable_cross_forest_trusts, B_TRUE); 15844aa0a5e7Snw if (rc != 0) 1585e3f2c991SKeyur Desai (*errors)++; 1586e3f2c991SKeyur Desai 1587e3f2c991SKeyur Desai rc = get_val_astring(handles, "directory_based_mapping", &s); 1588e3f2c991SKeyur Desai if (rc != 0) 1589e3f2c991SKeyur Desai (*errors)++; 1590e3f2c991SKeyur Desai else if (s == NULL || strcasecmp(s, "none") == 0) 1591e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1592e3f2c991SKeyur Desai else if (strcasecmp(s, "name") == 0) 1593e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME; 1594e3f2c991SKeyur Desai else if (strcasecmp(s, "idmu") == 0) 1595e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU; 1596e3f2c991SKeyur Desai else { 1597e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1598e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 1599e3f2c991SKeyur Desai "config/directory_based_mapping: invalid value \"%s\" ignored", 1600e3f2c991SKeyur Desai s); 1601e3f2c991SKeyur Desai (*errors)++; 1602e3f2c991SKeyur Desai } 1603e3f2c991SKeyur Desai free(s); 16044aa0a5e7Snw 1605c8e26105Sjp rc = get_val_int(handles, "list_size_limit", 1606c8e26105Sjp &pgcfg->list_size_limit, SCF_TYPE_COUNT); 16074aa0a5e7Snw if (rc != 0) 1608e3f2c991SKeyur Desai (*errors)++; 1609c5c4113dSnw 1610*fea136a0SMatt Barden rc = get_val_int(handles, "max_threads", 1611*fea136a0SMatt Barden &pgcfg->max_threads, SCF_TYPE_COUNT); 1612*fea136a0SMatt Barden if (rc != 0) 1613*fea136a0SMatt Barden (*errors)++; 1614*fea136a0SMatt Barden if (pgcfg->max_threads == 0) 1615*fea136a0SMatt Barden pgcfg->max_threads = MAX_THREADS_DEFAULT; 1616*fea136a0SMatt Barden if (pgcfg->max_threads > UINT_MAX) 1617*fea136a0SMatt Barden pgcfg->max_threads = UINT_MAX; 1618*fea136a0SMatt Barden 161948cd229bSGordon Ross rc = get_val_int(handles, "id_cache_timeout", 162048cd229bSGordon Ross &pgcfg->id_cache_timeout, SCF_TYPE_COUNT); 162148cd229bSGordon Ross if (rc != 0) 162248cd229bSGordon Ross (*errors)++; 162348cd229bSGordon Ross if (pgcfg->id_cache_timeout == 0) 162448cd229bSGordon Ross pgcfg->id_cache_timeout = ID_CACHE_TMO_DEFAULT; 162548cd229bSGordon Ross 162648cd229bSGordon Ross rc = get_val_int(handles, "name_cache_timeout", 162748cd229bSGordon Ross &pgcfg->name_cache_timeout, SCF_TYPE_COUNT); 162848cd229bSGordon Ross if (rc != 0) 162948cd229bSGordon Ross (*errors)++; 163048cd229bSGordon Ross if (pgcfg->name_cache_timeout == 0) 163148cd229bSGordon Ross pgcfg->name_cache_timeout = NAME_CACHE_TMO_DEFAULT; 163248cd229bSGordon Ross 1633b3700b07SGordon Ross rc = get_val_int(handles, "rediscovery_interval", 1634b3700b07SGordon Ross &pgcfg->rediscovery_interval, SCF_TYPE_COUNT); 1635b3700b07SGordon Ross if (rc != 0) 1636b3700b07SGordon Ross (*errors)++; 1637b3700b07SGordon Ross if (pgcfg->rediscovery_interval == 0) 1638b3700b07SGordon Ross pgcfg->rediscovery_interval = REDISCOVERY_INTERVAL_DEFAULT; 1639b3700b07SGordon Ross 1640c8e26105Sjp rc = get_val_astring(handles, "domain_name", 1641c8e26105Sjp &pgcfg->domain_name); 1642e3c2d6aaSnw if (rc != 0) 1643e3f2c991SKeyur Desai (*errors)++; 16444d61c878SJulian Pullen else { 1645148c5f43SAlan Wright if (pgcfg->domain_name != NULL && 1646148c5f43SAlan Wright pgcfg->domain_name[0] == '\0') { 1647148c5f43SAlan Wright free(pgcfg->domain_name); 1648148c5f43SAlan Wright pgcfg->domain_name = NULL; 1649148c5f43SAlan Wright } 1650349d5d8fSnw (void) ad_disc_set_DomainName(handles->ad_ctx, 1651349d5d8fSnw pgcfg->domain_name); 16527a8a68f5SJulian Pullen pgcfg->domain_name_auto_disc = B_FALSE; 16534d61c878SJulian Pullen } 1654c8e26105Sjp 1655c8e26105Sjp rc = get_val_astring(handles, "default_domain", 1656c8e26105Sjp &pgcfg->default_domain); 1657c8e26105Sjp if (rc != 0) { 1658e3c2d6aaSnw /* 1659e3c2d6aaSnw * SCF failures fetching config/default_domain we treat 1660e3c2d6aaSnw * as fatal as they may leave ID mapping rules that 1661e3c2d6aaSnw * match unqualified winnames flapping in the wind. 1662e3c2d6aaSnw */ 1663349d5d8fSnw return (-2); 1664c8e26105Sjp } 1665c8e26105Sjp 1666e3f2c991SKeyur Desai if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) { 1667e3f2c991SKeyur Desai pgcfg->default_domain = strdup(pgcfg->domain_name); 1668c5c4113dSnw } 1669c5c4113dSnw 1670b3700b07SGordon Ross rc = get_val_astring(handles, "domain_guid", &s); 1671b3700b07SGordon Ross if (rc != 0) { 1672b3700b07SGordon Ross (*errors)++; 1673b3700b07SGordon Ross } else if (s == NULL || s[0] == '\0') { 1674b3700b07SGordon Ross /* OK, not set. */ 1675b3700b07SGordon Ross free(s); 1676b3700b07SGordon Ross } else { 1677b3700b07SGordon Ross uuid_t u; 1678b3700b07SGordon Ross 1679b3700b07SGordon Ross if (uuid_parse(s, u) != 0) { 1680b3700b07SGordon Ross idmapdlog(LOG_ERR, 1681b3700b07SGordon Ross "config/domain_guid: invalid value \"%s\" ignored", s); 1682b3700b07SGordon Ross free(s); 1683b3700b07SGordon Ross (*errors)++; 1684b3700b07SGordon Ross } else { 1685b3700b07SGordon Ross pgcfg->domain_guid = s; 1686b3700b07SGordon Ross pgcfg->domain_guid_auto_disc = B_FALSE; 1687b3700b07SGordon Ross (void) ad_disc_set_DomainGUID(handles->ad_ctx, u); 1688b3700b07SGordon Ross } 1689b3700b07SGordon Ross } 1690b3700b07SGordon Ross 169112b65585SGordon Ross rc = get_val_astring(handles, "machine_uuid", &pgcfg->machine_uuid); 169212b65585SGordon Ross if (rc != 0) 169312b65585SGordon Ross (*errors)++; 169412b65585SGordon Ross if (pgcfg->machine_uuid == NULL) { 169512b65585SGordon Ross /* If machine_uuid not configured, generate one */ 169612b65585SGordon Ross if (generate_machine_uuid(&pgcfg->machine_uuid) < 0) 169712b65585SGordon Ross return (-2); 169812b65585SGordon Ross rc = set_val_astring(handles, handles->config_pg, 169912b65585SGordon Ross "machine_uuid", pgcfg->machine_uuid); 170012b65585SGordon Ross if (rc != 0) 170112b65585SGordon Ross (*errors)++; 170212b65585SGordon Ross } 170312b65585SGordon Ross 1704c8e26105Sjp rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); 1705e3c2d6aaSnw if (rc != 0) 1706e3f2c991SKeyur Desai (*errors)++; 1707c8e26105Sjp if (pgcfg->machine_sid == NULL) { 170812b65585SGordon Ross /* 170912b65585SGordon Ross * If machine_sid not configured, generate one 171012b65585SGordon Ross * from the machine UUID. 171112b65585SGordon Ross */ 171212b65585SGordon Ross if (generate_machine_sid(&pgcfg->machine_sid, 171312b65585SGordon Ross pgcfg->machine_uuid) < 0) 1714349d5d8fSnw return (-2); 1715148c5f43SAlan Wright rc = set_val_astring(handles, handles->config_pg, 1716148c5f43SAlan Wright "machine_sid", pgcfg->machine_sid); 1717e3c2d6aaSnw if (rc != 0) 1718e3f2c991SKeyur Desai (*errors)++; 17198edda628Sbaban } 1720c5c4113dSnw 1721c8e26105Sjp rc = get_val_ds(handles, "domain_controller", 389, 1722c8e26105Sjp &pgcfg->domain_controller); 1723e3c2d6aaSnw if (rc != 0) 1724e3f2c991SKeyur Desai (*errors)++; 17254d61c878SJulian Pullen else { 1726349d5d8fSnw (void) ad_disc_set_DomainController(handles->ad_ctx, 1727e3c2d6aaSnw pgcfg->domain_controller); 17287a8a68f5SJulian Pullen pgcfg->domain_controller_auto_disc = B_FALSE; 17294d61c878SJulian Pullen } 1730c5c4113dSnw 1731b3700b07SGordon Ross rc = get_val_ds(handles, "preferred_dc", 389, 1732b3700b07SGordon Ross &pgcfg->preferred_dc); 1733b3700b07SGordon Ross if (rc != 0) 1734b3700b07SGordon Ross (*errors)++; 1735b3700b07SGordon Ross else { 1736b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(handles->ad_ctx, 1737b3700b07SGordon Ross pgcfg->preferred_dc); 1738b3700b07SGordon Ross pgcfg->preferred_dc_auto_disc = B_FALSE; 1739b3700b07SGordon Ross } 1740b3700b07SGordon Ross 1741c8e26105Sjp rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); 1742e3c2d6aaSnw if (rc != 0) 1743e3f2c991SKeyur Desai (*errors)++; 17444d61c878SJulian Pullen else { 1745349d5d8fSnw (void) ad_disc_set_ForestName(handles->ad_ctx, 1746349d5d8fSnw pgcfg->forest_name); 17477a8a68f5SJulian Pullen pgcfg->forest_name_auto_disc = B_FALSE; 17484d61c878SJulian Pullen } 1749c8e26105Sjp 1750c8e26105Sjp rc = get_val_astring(handles, "site_name", &pgcfg->site_name); 1751e3c2d6aaSnw if (rc != 0) 1752e3f2c991SKeyur Desai (*errors)++; 1753e3c2d6aaSnw else 1754349d5d8fSnw (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name); 1755c8e26105Sjp 1756c8e26105Sjp rc = get_val_ds(handles, "global_catalog", 3268, 1757c8e26105Sjp &pgcfg->global_catalog); 1758e3c2d6aaSnw if (rc != 0) 1759e3f2c991SKeyur Desai (*errors)++; 17604d61c878SJulian Pullen else { 1761349d5d8fSnw (void) ad_disc_set_GlobalCatalog(handles->ad_ctx, 1762349d5d8fSnw pgcfg->global_catalog); 17637a8a68f5SJulian Pullen pgcfg->global_catalog_auto_disc = B_FALSE; 17644d61c878SJulian Pullen } 1765c8e26105Sjp 1766e3f2c991SKeyur Desai /* Unless we're doing directory-based name mapping, we're done. */ 1767e3f2c991SKeyur Desai if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME) 1768e3f2c991SKeyur Desai return (0); 1769e8c27ec8Sbaban 1770349d5d8fSnw rc = get_val_astring(handles, "ad_unixuser_attr", 1771349d5d8fSnw &pgcfg->ad_unixuser_attr); 1772349d5d8fSnw if (rc != 0) 1773349d5d8fSnw return (-2); 1774479ac375Sdm if (pgcfg->ad_unixuser_attr != NULL && 1775479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixuser_attr)) { 1776479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a " 1777479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixuser_attr); 1778479ac375Sdm return (-3); 1779479ac375Sdm } 1780e8c27ec8Sbaban 1781349d5d8fSnw rc = get_val_astring(handles, "ad_unixgroup_attr", 1782349d5d8fSnw &pgcfg->ad_unixgroup_attr); 1783349d5d8fSnw if (rc != 0) 1784349d5d8fSnw return (-2); 1785479ac375Sdm if (pgcfg->ad_unixgroup_attr != NULL && 1786479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) { 1787479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a " 1788479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixgroup_attr); 1789479ac375Sdm return (-3); 1790479ac375Sdm } 1791e8c27ec8Sbaban 1792349d5d8fSnw rc = get_val_astring(handles, "nldap_winname_attr", 1793349d5d8fSnw &pgcfg->nldap_winname_attr); 1794349d5d8fSnw if (rc != 0) 1795349d5d8fSnw return (-2); 1796479ac375Sdm if (pgcfg->nldap_winname_attr != NULL && 1797479ac375Sdm !valid_ldap_attr(pgcfg->nldap_winname_attr)) { 1798479ac375Sdm idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a " 1799479ac375Sdm "valid LDAP attribute name", pgcfg->nldap_winname_attr); 1800349d5d8fSnw return (-3); 1801e8c27ec8Sbaban } 1802349d5d8fSnw if (pgcfg->ad_unixuser_attr == NULL && 1803479ac375Sdm pgcfg->ad_unixgroup_attr == NULL && 1804479ac375Sdm pgcfg->nldap_winname_attr == NULL) { 1805349d5d8fSnw idmapdlog(LOG_ERR, 1806e3f2c991SKeyur Desai "If config/directory_based_mapping property is set to " 1807e3f2c991SKeyur Desai "\"name\" then at least one of the following name mapping " 1808349d5d8fSnw "attributes must be specified. (config/ad_unixuser_attr OR " 1809479ac375Sdm "config/ad_unixgroup_attr OR config/nldap_winname_attr)"); 1810349d5d8fSnw return (-3); 1811349d5d8fSnw } 1812c8e26105Sjp 1813349d5d8fSnw return (rc); 1814349d5d8fSnw } 1815349d5d8fSnw 1816148c5f43SAlan Wright static 1817148c5f43SAlan Wright void 1818148c5f43SAlan Wright log_if_unable(const void *val, const char *what) 1819148c5f43SAlan Wright { 1820148c5f43SAlan Wright if (val == NULL) { 1821148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "unable to discover %s", what); 1822148c5f43SAlan Wright } 1823148c5f43SAlan Wright } 18244d61c878SJulian Pullen 1825349d5d8fSnw static 1826349d5d8fSnw void 1827148c5f43SAlan Wright discover_trusted_domains(idmap_pg_config_t *pgcfg, ad_disc_t ad_ctx) 1828349d5d8fSnw { 18294d61c878SJulian Pullen ad_disc_t trusted_ctx; 18304d61c878SJulian Pullen int i, j, k, l; 18314d61c878SJulian Pullen char *forestname; 18324d61c878SJulian Pullen int num_trusteddomains; 18337a8a68f5SJulian Pullen boolean_t new_forest; 18344d61c878SJulian Pullen char *trusteddomain; 1835b3700b07SGordon Ross ad_disc_ds_t *globalcatalog; 18364d61c878SJulian Pullen idmap_trustedforest_t *trustedforests; 18374d61c878SJulian Pullen ad_disc_domainsinforest_t *domainsinforest; 1838349d5d8fSnw 18394d61c878SJulian Pullen pgcfg->trusted_domains = 18404d61c878SJulian Pullen ad_disc_get_TrustedDomains(ad_ctx, NULL); 18414d61c878SJulian Pullen 18424d61c878SJulian Pullen if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL && 18434d61c878SJulian Pullen pgcfg->trusted_domains[0].domain[0] != '\0') { 18444d61c878SJulian Pullen /* 18454d61c878SJulian Pullen * We have trusted domains. We need to go through every 18464d61c878SJulian Pullen * one and find its forest. If it is a new forest we then need 18474d61c878SJulian Pullen * to find its Global Catalog and the domains in the forest 18484d61c878SJulian Pullen */ 18494d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) 18504d61c878SJulian Pullen continue; 18514d61c878SJulian Pullen num_trusteddomains = i; 18524d61c878SJulian Pullen 18534d61c878SJulian Pullen trustedforests = calloc(num_trusteddomains, 18544d61c878SJulian Pullen sizeof (idmap_trustedforest_t)); 18554d61c878SJulian Pullen j = 0; 18564d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) { 18574d61c878SJulian Pullen trusteddomain = pgcfg->trusted_domains[i].domain; 18584d61c878SJulian Pullen trusted_ctx = ad_disc_init(); 1859148c5f43SAlan Wright (void) ad_disc_set_DomainName(trusted_ctx, 18604d61c878SJulian Pullen trusteddomain); 18614d61c878SJulian Pullen forestname = 18624d61c878SJulian Pullen ad_disc_get_ForestName(trusted_ctx, NULL); 18634d61c878SJulian Pullen if (forestname == NULL) { 1864148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1865148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1866148c5f43SAlan Wright "unable to discover Forest Name" 1867148c5f43SAlan Wright " for the trusted domain %s", 1868148c5f43SAlan Wright trusteddomain); 1869148c5f43SAlan Wright } 18704d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 18714d61c878SJulian Pullen continue; 18724d61c878SJulian Pullen } 18734d61c878SJulian Pullen 18744d61c878SJulian Pullen if (strcasecmp(forestname, pgcfg->forest_name) == 0) { 18754d61c878SJulian Pullen /* 18764d61c878SJulian Pullen * Ignore the domain as it is part of 18774d61c878SJulian Pullen * the primary forest 18784d61c878SJulian Pullen */ 18794d61c878SJulian Pullen free(forestname); 18804d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 18814d61c878SJulian Pullen continue; 18824d61c878SJulian Pullen } 18834d61c878SJulian Pullen 18844d61c878SJulian Pullen /* Is this a new forest? */ 18857a8a68f5SJulian Pullen new_forest = B_TRUE; 18864d61c878SJulian Pullen for (k = 0; k < j; k++) { 18874d61c878SJulian Pullen if (strcasecmp(forestname, 18884d61c878SJulian Pullen trustedforests[k].forest_name) == 0) { 18897a8a68f5SJulian Pullen new_forest = B_FALSE; 18904d61c878SJulian Pullen domainsinforest = 18914d61c878SJulian Pullen trustedforests[k].domains_in_forest; 18924d61c878SJulian Pullen break; 18934d61c878SJulian Pullen } 18944d61c878SJulian Pullen } 18954d61c878SJulian Pullen if (!new_forest) { 18964d61c878SJulian Pullen /* Mark the domain as trusted */ 18974d61c878SJulian Pullen for (l = 0; 18984d61c878SJulian Pullen domainsinforest[l].domain[0] != '\0'; l++) { 18991fcced4cSJordan Brown if (domain_eq(trusteddomain, 19001fcced4cSJordan Brown domainsinforest[l].domain)) { 19014d61c878SJulian Pullen domainsinforest[l].trusted = 19024d61c878SJulian Pullen TRUE; 19034d61c878SJulian Pullen break; 19044d61c878SJulian Pullen } 19054d61c878SJulian Pullen } 19064d61c878SJulian Pullen free(forestname); 19074d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19084d61c878SJulian Pullen continue; 19094d61c878SJulian Pullen } 19104d61c878SJulian Pullen 19114d61c878SJulian Pullen /* 19124d61c878SJulian Pullen * Get the Global Catalog and the domains in 19134d61c878SJulian Pullen * this new forest. 19144d61c878SJulian Pullen */ 19154d61c878SJulian Pullen globalcatalog = 19164d61c878SJulian Pullen ad_disc_get_GlobalCatalog(trusted_ctx, 19174d61c878SJulian Pullen AD_DISC_PREFER_SITE, NULL); 19184d61c878SJulian Pullen if (globalcatalog == NULL) { 1919148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1920148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1921148c5f43SAlan Wright "unable to discover Global Catalog" 1922148c5f43SAlan Wright " for the trusted domain %s", 1923148c5f43SAlan Wright trusteddomain); 1924148c5f43SAlan Wright } 19254d61c878SJulian Pullen free(forestname); 19264d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19274d61c878SJulian Pullen continue; 19284d61c878SJulian Pullen } 19294d61c878SJulian Pullen domainsinforest = 1930b3700b07SGordon Ross ad_disc_get_DomainsInForest(trusted_ctx, NULL); 19314d61c878SJulian Pullen if (domainsinforest == NULL) { 1932148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 1933148c5f43SAlan Wright idmapdlog(LOG_DEBUG, 1934148c5f43SAlan Wright "unable to discover Domains in the" 1935148c5f43SAlan Wright " Forest for the trusted domain %s", 1936148c5f43SAlan Wright trusteddomain); 1937148c5f43SAlan Wright } 19384d61c878SJulian Pullen free(globalcatalog); 19394d61c878SJulian Pullen free(forestname); 19404d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19414d61c878SJulian Pullen continue; 19424d61c878SJulian Pullen } 19434d61c878SJulian Pullen 19444d61c878SJulian Pullen trustedforests[j].forest_name = forestname; 19454d61c878SJulian Pullen trustedforests[j].global_catalog = globalcatalog; 19464d61c878SJulian Pullen trustedforests[j].domains_in_forest = domainsinforest; 19474d61c878SJulian Pullen j++; 19484d61c878SJulian Pullen /* Mark the domain as trusted */ 19494d61c878SJulian Pullen for (l = 0; domainsinforest[l].domain[0] != '\0'; 19504d61c878SJulian Pullen l++) { 19511fcced4cSJordan Brown if (domain_eq(trusteddomain, 19521fcced4cSJordan Brown domainsinforest[l].domain)) { 19534d61c878SJulian Pullen domainsinforest[l].trusted = TRUE; 19544d61c878SJulian Pullen break; 19554d61c878SJulian Pullen } 19564d61c878SJulian Pullen } 19574d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 19584d61c878SJulian Pullen } 19594d61c878SJulian Pullen if (j > 0) { 19604d61c878SJulian Pullen pgcfg->num_trusted_forests = j; 19614d61c878SJulian Pullen pgcfg->trusted_forests = trustedforests; 19621fcced4cSJordan Brown } else { 19631fcced4cSJordan Brown free(trustedforests); 19644d61c878SJulian Pullen } 19654d61c878SJulian Pullen } 1966148c5f43SAlan Wright } 1967349d5d8fSnw 1968148c5f43SAlan Wright /* 1969148c5f43SAlan Wright * This is the half of idmap_cfg_load() that auto-discovers values of 1970148c5f43SAlan Wright * discoverable properties that weren't already set via SMF properties. 1971148c5f43SAlan Wright * 1972148c5f43SAlan Wright * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it 1973148c5f43SAlan Wright * needs to be careful not to overwrite any properties set in SMF. 1974148c5f43SAlan Wright */ 1975b3700b07SGordon Ross static void 1976b3700b07SGordon Ross idmap_cfg_discover1(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 1977148c5f43SAlan Wright { 1978148c5f43SAlan Wright ad_disc_t ad_ctx = handles->ad_ctx; 1979b3700b07SGordon Ross FILE *status_fp = NULL; 1980b3700b07SGordon Ross time_t t0, t1; 1981148c5f43SAlan Wright 1982b3700b07SGordon Ross t0 = time(NULL); 1983148c5f43SAlan Wright if (DBG(CONFIG, 1)) 1984b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Running domain discovery."); 1985148c5f43SAlan Wright 1986b3700b07SGordon Ross (void) unlink(IDMAP_CACHEDIR "/discovery.log"); 1987b3700b07SGordon Ross status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "w"); 1988b3700b07SGordon Ross if (status_fp) { 1989b3700b07SGordon Ross (void) fchmod(fileno(status_fp), 0644); 1990b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, status_fp); 1991b3700b07SGordon Ross } 1992148c5f43SAlan Wright 1993148c5f43SAlan Wright if (pgcfg->domain_name == NULL) { 1994148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "No domain name specified."); 1995b3700b07SGordon Ross if (status_fp) 1996b3700b07SGordon Ross (void) fprintf(status_fp, "(no domain name)\n"); 1997b3700b07SGordon Ross goto out; 1998b3700b07SGordon Ross } 1999148c5f43SAlan Wright 2000b3700b07SGordon Ross if (pgcfg->domain_controller == NULL) 2001b3700b07SGordon Ross pgcfg->domain_controller = 2002b3700b07SGordon Ross ad_disc_get_DomainController(ad_ctx, 2003b3700b07SGordon Ross AD_DISC_PREFER_SITE, 2004b3700b07SGordon Ross &pgcfg->domain_controller_auto_disc); 2005b3700b07SGordon Ross 2006b3700b07SGordon Ross if (pgcfg->domain_guid == NULL) { 2007b3700b07SGordon Ross char buf[UUID_PRINTABLE_STRING_LENGTH]; 2008b3700b07SGordon Ross uchar_t *u = ad_disc_get_DomainGUID(ad_ctx, 2009b3700b07SGordon Ross &pgcfg->domain_guid_auto_disc); 2010b3700b07SGordon Ross (void) memset(buf, 0, sizeof (buf)); 2011b3700b07SGordon Ross if (u != NULL) { 2012b3700b07SGordon Ross uuid_unparse(u, buf); 2013b3700b07SGordon Ross pgcfg->domain_guid = strdup(buf); 2014b3700b07SGordon Ross } 2015b3700b07SGordon Ross } 2016b3700b07SGordon Ross 2017b3700b07SGordon Ross if (pgcfg->forest_name == NULL) 2018b3700b07SGordon Ross pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx, 2019b3700b07SGordon Ross &pgcfg->forest_name_auto_disc); 2020b3700b07SGordon Ross 2021b3700b07SGordon Ross if (pgcfg->site_name == NULL) 2022b3700b07SGordon Ross pgcfg->site_name = ad_disc_get_SiteName(ad_ctx, 2023b3700b07SGordon Ross &pgcfg->site_name_auto_disc); 2024b3700b07SGordon Ross 2025b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2026b3700b07SGordon Ross log_if_unable(pgcfg->domain_name, "Domain Name"); 2027b3700b07SGordon Ross log_if_unable(pgcfg->domain_controller, 2028b3700b07SGordon Ross "Domain Controller"); 2029b3700b07SGordon Ross log_if_unable(pgcfg->domain_guid, "Domain GUID"); 2030b3700b07SGordon Ross log_if_unable(pgcfg->forest_name, "Forest Name"); 2031b3700b07SGordon Ross log_if_unable(pgcfg->site_name, "Site Name"); 2032b3700b07SGordon Ross } 2033b3700b07SGordon Ross 2034b3700b07SGordon Ross out: 2035b3700b07SGordon Ross if (status_fp) { 2036b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, NULL); 2037b3700b07SGordon Ross (void) fclose(status_fp); 2038b3700b07SGordon Ross status_fp = NULL; 2039b3700b07SGordon Ross } 2040b3700b07SGordon Ross 2041b3700b07SGordon Ross if (DBG(CONFIG, 1)) 2042b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Domain discovery done."); 2043b3700b07SGordon Ross 2044b3700b07SGordon Ross /* 2045b3700b07SGordon Ross * Log when this took more than 15 sec. 2046b3700b07SGordon Ross */ 2047b3700b07SGordon Ross t1 = time(NULL); 2048b3700b07SGordon Ross if (t1 > (t0 + 15)) { 2049b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Domain discovery took %d sec.", 2050b3700b07SGordon Ross (int)(t1 - t0)); 2051b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Check the DNS configuration."); 2052b3700b07SGordon Ross } 2053b3700b07SGordon Ross } 2054b3700b07SGordon Ross 2055b3700b07SGordon Ross /* 2056b3700b07SGordon Ross * This is the second part of discovery, which can take a while. 2057b3700b07SGordon Ross * We don't want to hold up parties who just want to know what 2058b3700b07SGordon Ross * domain controller we're using (like smbd), so this part runs 2059b3700b07SGordon Ross * after we've updated that info in the "live" config and told 2060b3700b07SGordon Ross * such consumers to go ahead. 2061b3700b07SGordon Ross * 2062b3700b07SGordon Ross * This is a lot like idmap_cfg_discover(), but used LDAP queries 2063b3700b07SGordon Ross * get the forest information from the global catalog servers. 2064b3700b07SGordon Ross * 2065b3700b07SGordon Ross * Note: the previous update_* calls have usually nuked any 2066b3700b07SGordon Ross * useful information from pgcfg before we get here, so we 2067b3700b07SGordon Ross * can only use it store discovery results, not to read. 2068b3700b07SGordon Ross */ 2069b3700b07SGordon Ross static void 2070b3700b07SGordon Ross idmap_cfg_discover2(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 2071b3700b07SGordon Ross { 2072b3700b07SGordon Ross ad_disc_t ad_ctx = handles->ad_ctx; 2073b3700b07SGordon Ross FILE *status_fp = NULL; 2074b3700b07SGordon Ross time_t t0, t1; 2075b3700b07SGordon Ross 2076b3700b07SGordon Ross t0 = time(NULL); 2077b3700b07SGordon Ross if (DBG(CONFIG, 1)) 2078b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Running forest discovery."); 2079b3700b07SGordon Ross 2080b3700b07SGordon Ross status_fp = fopen(IDMAP_CACHEDIR "/discovery.log", "a"); 2081b3700b07SGordon Ross if (status_fp) 2082b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, status_fp); 2083b3700b07SGordon Ross 2084b3700b07SGordon Ross if (pgcfg->global_catalog == NULL) 2085b3700b07SGordon Ross pgcfg->global_catalog = 2086b3700b07SGordon Ross ad_disc_get_GlobalCatalog(ad_ctx, 2087b3700b07SGordon Ross AD_DISC_PREFER_SITE, 2088b3700b07SGordon Ross &pgcfg->global_catalog_auto_disc); 2089b3700b07SGordon Ross 2090b3700b07SGordon Ross if (pgcfg->global_catalog != NULL) { 2091148c5f43SAlan Wright pgcfg->domains_in_forest = 2092148c5f43SAlan Wright ad_disc_get_DomainsInForest(ad_ctx, NULL); 2093148c5f43SAlan Wright 2094148c5f43SAlan Wright if (!pgcfg->disable_cross_forest_trusts) 2095148c5f43SAlan Wright discover_trusted_domains(pgcfg, ad_ctx); 2096b3700b07SGordon Ross } 2097148c5f43SAlan Wright 2098b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2099b3700b07SGordon Ross log_if_unable(pgcfg->global_catalog, "Global Catalog"); 2100b3700b07SGordon Ross log_if_unable(pgcfg->domains_in_forest, 2101b3700b07SGordon Ross "Domains in the Forest"); 2102b3700b07SGordon Ross /* Empty trusted domains list is OK. */ 2103148c5f43SAlan Wright } 2104c5866007SKeyur Desai 2105b3700b07SGordon Ross if (status_fp) { 2106b3700b07SGordon Ross ad_disc_set_StatusFP(ad_ctx, NULL); 2107b3700b07SGordon Ross (void) fclose(status_fp); 2108b3700b07SGordon Ross status_fp = NULL; 2109b3700b07SGordon Ross } 2110148c5f43SAlan Wright 2111148c5f43SAlan Wright if (DBG(CONFIG, 1)) 2112b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "Forest discovery done."); 2113b3700b07SGordon Ross 2114b3700b07SGordon Ross /* 2115b3700b07SGordon Ross * Log when this took more than 30 sec. 2116b3700b07SGordon Ross */ 2117b3700b07SGordon Ross t1 = time(NULL); 2118b3700b07SGordon Ross if (t1 > (t0 + 30)) { 2119b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Forest discovery took %d sec.", 2120b3700b07SGordon Ross (int)(t1 - t0)); 2121b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Check AD join status."); 2122b3700b07SGordon Ross } 2123349d5d8fSnw } 2124349d5d8fSnw 21254d61c878SJulian Pullen 2126349d5d8fSnw /* 2127349d5d8fSnw * idmap_cfg_load() is called at startup, and periodically via the 2128349d5d8fSnw * update thread when the auto-discovery TTLs expire, as well as part of 2129349d5d8fSnw * the refresh method, to update the current configuration. It always 2130349d5d8fSnw * reads from SMF, but you still have to refresh the service after 2131349d5d8fSnw * changing the config pg in order for the changes to take effect. 2132349d5d8fSnw * 2133148c5f43SAlan Wright * There is one flag: 2134349d5d8fSnw * 2135349d5d8fSnw * - CFG_DISCOVER 2136349d5d8fSnw * 2137349d5d8fSnw * If CFG_DISCOVER is set then idmap_cfg_load() calls 2138349d5d8fSnw * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property 2139349d5d8fSnw * values that weren't set in SMF. 2140349d5d8fSnw * 2141148c5f43SAlan Wright * idmap_cfg_load() will log (to LOG_NOTICE) whether the configuration 2142148c5f43SAlan Wright * changed. 2143349d5d8fSnw * 2144349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 2145349d5d8fSnw * reading from SMF. 2146349d5d8fSnw */ 2147349d5d8fSnw int 2148349d5d8fSnw idmap_cfg_load(idmap_cfg_t *cfg, int flags) 2149349d5d8fSnw { 2150b3700b07SGordon Ross const ad_disc_t ad_ctx = cfg->handles.ad_ctx; 2151349d5d8fSnw int rc = 0; 2152e3f2c991SKeyur Desai int errors; 2153349d5d8fSnw int changed = 0; 2154b3700b07SGordon Ross int dc_changed = 0; 21554d61c878SJulian Pullen int ad_reload_required = 0; 2156349d5d8fSnw idmap_pg_config_t new_pgcfg, *live_pgcfg; 2157349d5d8fSnw 2158148c5f43SAlan Wright if (DBG(CONFIG, 1)) 2159148c5f43SAlan Wright idmapdlog(LOG_DEBUG, "Loading configuration."); 2160148c5f43SAlan Wright 2161349d5d8fSnw live_pgcfg = &cfg->pgcfg; 2162349d5d8fSnw (void) memset(&new_pgcfg, 0, sizeof (new_pgcfg)); 2163349d5d8fSnw 2164148c5f43SAlan Wright (void) pthread_mutex_lock(&cfg->handles.mutex); 2165349d5d8fSnw 2166349d5d8fSnw if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1) 2167349d5d8fSnw goto err; 2168349d5d8fSnw 2169b3700b07SGordon Ross if (flags & CFG_DISCOVER) { 2170b3700b07SGordon Ross 2171b3700b07SGordon Ross ad_disc_refresh(ad_ctx); 2172b3700b07SGordon Ross 2173b3700b07SGordon Ross /* 2174b3700b07SGordon Ross * Unless we've been asked to forget the current DC, 2175b3700b07SGordon Ross * give preference (in order) to the preferred DC if 2176b3700b07SGordon Ross * configured, or the current DC. These preferences 2177b3700b07SGordon Ross * reduce undesirable DC changes. 2178b3700b07SGordon Ross */ 2179b3700b07SGordon Ross if (flags & CFG_FORGET_DC) { 2180b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, NULL); 2181b3700b07SGordon Ross } else if (new_pgcfg.preferred_dc != NULL) { 2182b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, 2183b3700b07SGordon Ross new_pgcfg.preferred_dc); 2184b3700b07SGordon Ross } else if (live_pgcfg->domain_controller != NULL) { 2185b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, 2186b3700b07SGordon Ross live_pgcfg->domain_controller); 2187b3700b07SGordon Ross } else { 2188b3700b07SGordon Ross (void) ad_disc_set_PreferredDC(ad_ctx, NULL); 2189b3700b07SGordon Ross } 2190b3700b07SGordon Ross 2191b3700b07SGordon Ross /* 2192b3700b07SGordon Ross * We want a way to tell adspriv_getdcname_1_svc() 2193b3700b07SGordon Ross * (and others) that discovery is running and therefore 2194b3700b07SGordon Ross * they may want to wait a bit or return an error... 2195b3700b07SGordon Ross */ 2196b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2197b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_RUNNING; 2198b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2199b3700b07SGordon Ross 2200b3700b07SGordon Ross idmap_cfg_discover1(&cfg->handles, &new_pgcfg); 2201b3700b07SGordon Ross 2202b3700b07SGordon Ross WRLOCK_CONFIG(); 2203b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2204b3700b07SGordon Ross _idmapdstate.addisc_st = 0; 2205b3700b07SGordon Ross (void) cond_broadcast(&_idmapdstate.addisc_cv); 2206b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2207b3700b07SGordon Ross } else { 2208b3700b07SGordon Ross WRLOCK_CONFIG(); 2209b3700b07SGordon Ross } 2210349d5d8fSnw 2211349d5d8fSnw /* Non-discoverable props updated here */ 221248cd229bSGordon Ross 221348cd229bSGordon Ross changed += update_uint64(&live_pgcfg->list_size_limit, 221448cd229bSGordon Ross &new_pgcfg.list_size_limit, "list_size_limit"); 221548cd229bSGordon Ross 2216*fea136a0SMatt Barden changed += update_uint64(&live_pgcfg->max_threads, 2217*fea136a0SMatt Barden &new_pgcfg.max_threads, "max_threads"); 2218*fea136a0SMatt Barden 221948cd229bSGordon Ross changed += update_uint64(&live_pgcfg->id_cache_timeout, 222048cd229bSGordon Ross &new_pgcfg.id_cache_timeout, "id_cache_timeout"); 222148cd229bSGordon Ross 222248cd229bSGordon Ross changed += update_uint64(&live_pgcfg->name_cache_timeout, 222348cd229bSGordon Ross &new_pgcfg.name_cache_timeout, "name_cache_timeout"); 222448cd229bSGordon Ross 2225b3700b07SGordon Ross changed += update_uint64(&live_pgcfg->rediscovery_interval, 2226b3700b07SGordon Ross &new_pgcfg.rediscovery_interval, "rediscovery_interval"); 2227b3700b07SGordon Ross 22284aa0a5e7Snw changed += update_string(&live_pgcfg->machine_sid, 2229349d5d8fSnw &new_pgcfg.machine_sid, "machine_sid"); 2230349d5d8fSnw 22314aa0a5e7Snw changed += update_bool(&live_pgcfg->eph_map_unres_sids, 22324aa0a5e7Snw &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); 22334aa0a5e7Snw 22341ed6b69aSGordon Ross changed += update_bool(&live_pgcfg->use_ads, 22351ed6b69aSGordon Ross &new_pgcfg.use_ads, "use_ads"); 22361ed6b69aSGordon Ross 2237148c5f43SAlan Wright changed += update_bool(&live_pgcfg->use_lsa, 2238148c5f43SAlan Wright &new_pgcfg.use_lsa, "use_lsa"); 2239148c5f43SAlan Wright 2240148c5f43SAlan Wright changed += update_bool(&live_pgcfg->disable_cross_forest_trusts, 2241148c5f43SAlan Wright &new_pgcfg.disable_cross_forest_trusts, 2242148c5f43SAlan Wright "disable_cross_forest_trusts"); 2243148c5f43SAlan Wright 2244e3f2c991SKeyur Desai changed += update_enum(&live_pgcfg->directory_based_mapping, 2245e3f2c991SKeyur Desai &new_pgcfg.directory_based_mapping, "directory_based_mapping", 2246e3f2c991SKeyur Desai directory_mapping_map); 2247349d5d8fSnw 22484aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixuser_attr, 2249349d5d8fSnw &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr"); 2250349d5d8fSnw 22514aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixgroup_attr, 2252349d5d8fSnw &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr"); 2253349d5d8fSnw 22544aa0a5e7Snw changed += update_string(&live_pgcfg->nldap_winname_attr, 2255349d5d8fSnw &new_pgcfg.nldap_winname_attr, "nldap_winname_attr"); 2256349d5d8fSnw 2257e3f2c991SKeyur Desai changed += update_string(&live_pgcfg->default_domain, 2258e3f2c991SKeyur Desai &new_pgcfg.default_domain, "default_domain"); 2259349d5d8fSnw 2260b3700b07SGordon Ross changed += update_dirs(&live_pgcfg->preferred_dc, 2261b3700b07SGordon Ross &new_pgcfg.preferred_dc, "preferred_dc"); 2262b3700b07SGordon Ross 2263b3700b07SGordon Ross /* Props that can be discovered or set in SMF updated here */ 2264b3700b07SGordon Ross 2265b3700b07SGordon Ross if (update_string(&live_pgcfg->domain_name, 2266b3700b07SGordon Ross &new_pgcfg.domain_name, "domain_name")) { 2267b3700b07SGordon Ross changed++; 2268b3700b07SGordon Ross ad_reload_required = TRUE; 2269b3700b07SGordon Ross idmapd_set_krb5_realm(live_pgcfg->domain_name); 2270b3700b07SGordon Ross } 22714d61c878SJulian Pullen live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc; 2272349d5d8fSnw 2273b3700b07SGordon Ross changed += update_string(&live_pgcfg->domain_guid, 2274b3700b07SGordon Ross &new_pgcfg.domain_guid, "domain_guid"); 2275b3700b07SGordon Ross live_pgcfg->domain_guid_auto_disc = new_pgcfg.domain_guid_auto_disc; 2276b3700b07SGordon Ross 2277b3700b07SGordon Ross dc_changed = update_dirs(&live_pgcfg->domain_controller, 2278349d5d8fSnw &new_pgcfg.domain_controller, "domain_controller"); 2279b3700b07SGordon Ross changed += dc_changed; 22804d61c878SJulian Pullen live_pgcfg->domain_controller_auto_disc = 22814d61c878SJulian Pullen new_pgcfg.domain_controller_auto_disc; 2282349d5d8fSnw 22834aa0a5e7Snw changed += update_string(&live_pgcfg->forest_name, 2284349d5d8fSnw &new_pgcfg.forest_name, "forest_name"); 22854d61c878SJulian Pullen live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc; 2286349d5d8fSnw 22874aa0a5e7Snw changed += update_string(&live_pgcfg->site_name, 2288349d5d8fSnw &new_pgcfg.site_name, "site_name"); 22894d61c878SJulian Pullen live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc; 2290349d5d8fSnw 2291b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2292b3700b07SGordon Ross if (changed) 2293b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Configuration changed"); 2294b3700b07SGordon Ross else 2295b3700b07SGordon Ross idmapdlog(LOG_NOTICE, "Configuration unchanged"); 2296b3700b07SGordon Ross } 2297b3700b07SGordon Ross 2298b3700b07SGordon Ross UNLOCK_CONFIG(); 2299b3700b07SGordon Ross 2300b3700b07SGordon Ross if (dc_changed != 0) { 2301b3700b07SGordon Ross notify_dc_changed(); 2302349d5d8fSnw } 2303b3700b07SGordon Ross 2304b3700b07SGordon Ross /* 2305b3700b07SGordon Ross * Discovery2 can take a while. 2306b3700b07SGordon Ross */ 2307b3700b07SGordon Ross if (flags & CFG_DISCOVER) { 2308b3700b07SGordon Ross if (live_pgcfg->domain_name != NULL && 2309b3700b07SGordon Ross live_pgcfg->forest_name != NULL) 2310b3700b07SGordon Ross idmap_cfg_discover2(&cfg->handles, &new_pgcfg); 2311b3700b07SGordon Ross ad_disc_done(ad_ctx); 2312b3700b07SGordon Ross } 2313b3700b07SGordon Ross 2314b3700b07SGordon Ross WRLOCK_CONFIG(); 2315b3700b07SGordon Ross 2316b3700b07SGordon Ross /* More props that can be discovered or set in SMF */ 2317b3700b07SGordon Ross 2318b3700b07SGordon Ross changed += update_dirs(&live_pgcfg->global_catalog, 2319b3700b07SGordon Ross &new_pgcfg.global_catalog, "global_catalog"); 23204d61c878SJulian Pullen live_pgcfg->global_catalog_auto_disc = 23214d61c878SJulian Pullen new_pgcfg.global_catalog_auto_disc; 23224d61c878SJulian Pullen 2323b3700b07SGordon Ross /* Props that are only discovered (never in SMF) */ 2324b3700b07SGordon Ross 23254d61c878SJulian Pullen if (update_domains_in_forest(&live_pgcfg->domains_in_forest, 23264d61c878SJulian Pullen &new_pgcfg.domains_in_forest, "domains_in_forest")) { 23274d61c878SJulian Pullen changed++; 23284d61c878SJulian Pullen ad_reload_required = TRUE; 23294d61c878SJulian Pullen } 23304d61c878SJulian Pullen 23314d61c878SJulian Pullen if (update_trusted_domains(&live_pgcfg->trusted_domains, 23324d61c878SJulian Pullen &new_pgcfg.trusted_domains, "trusted_domains")) { 23334d61c878SJulian Pullen changed++; 23344d61c878SJulian Pullen if (live_pgcfg->trusted_domains != NULL && 23354d61c878SJulian Pullen live_pgcfg->trusted_domains[0].domain[0] != '\0') 23364d61c878SJulian Pullen ad_reload_required = TRUE; 23374d61c878SJulian Pullen } 23384d61c878SJulian Pullen 23394d61c878SJulian Pullen if (update_trusted_forest(&live_pgcfg->trusted_forests, 23404d61c878SJulian Pullen &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests, 23414d61c878SJulian Pullen &new_pgcfg.num_trusted_forests, "trusted_forest")) { 23424d61c878SJulian Pullen changed++; 23434d61c878SJulian Pullen if (live_pgcfg->trusted_forests != NULL) 23444d61c878SJulian Pullen ad_reload_required = TRUE; 23454d61c878SJulian Pullen } 23464d61c878SJulian Pullen 2347148c5f43SAlan Wright if (DBG(CONFIG, 1)) { 2348148c5f43SAlan Wright if (changed) 2349148c5f43SAlan Wright idmapdlog(LOG_NOTICE, "Configuration changed"); 2350148c5f43SAlan Wright else 2351148c5f43SAlan Wright idmapdlog(LOG_NOTICE, "Configuration unchanged"); 2352c8e26105Sjp } 2353e3c2d6aaSnw 2354349d5d8fSnw UNLOCK_CONFIG(); 2355349d5d8fSnw 2356b3700b07SGordon Ross if (ad_reload_required) 2357b3700b07SGordon Ross reload_ad(); 2358b3700b07SGordon Ross 2359b3700b07SGordon Ross idmap_cfg_unload(&new_pgcfg); 2360b3700b07SGordon Ross 2361349d5d8fSnw err: 2362148c5f43SAlan Wright (void) pthread_mutex_unlock(&cfg->handles.mutex); 2363c5c4113dSnw 2364e8c27ec8Sbaban if (rc < -1) 2365e3c2d6aaSnw return (rc); 2366e3c2d6aaSnw 2367e3c2d6aaSnw return ((errors == 0) ? 0 : -1); 2368c5c4113dSnw } 2369c5c4113dSnw 2370651c0131Sbaban /* 2371651c0131Sbaban * Initialize 'cfg'. 2372651c0131Sbaban */ 2373c5c4113dSnw idmap_cfg_t * 23744edd44c5Sjp idmap_cfg_init() 23754edd44c5Sjp { 2376c8e26105Sjp idmap_cfg_handles_t *handles; 2377c5c4113dSnw 2378c5c4113dSnw /* First the smf repository handles: */ 2379c5c4113dSnw idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t)); 2380c5c4113dSnw if (!cfg) { 238171590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 2382c5c4113dSnw return (NULL); 2383c5c4113dSnw } 2384c8e26105Sjp handles = &cfg->handles; 2385c5c4113dSnw 2386c8e26105Sjp (void) pthread_mutex_init(&handles->mutex, NULL); 2387c8e26105Sjp 2388c8e26105Sjp if (!(handles->main = scf_handle_create(SCF_VERSION))) { 238971590c90Snw idmapdlog(LOG_ERR, "scf_handle_create() failed: %s", 239071590c90Snw scf_strerror(scf_error())); 2391c5c4113dSnw goto error; 2392c5c4113dSnw } 2393c5c4113dSnw 2394c8e26105Sjp if (scf_handle_bind(handles->main) < 0) { 239571590c90Snw idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s", 239671590c90Snw scf_strerror(scf_error())); 2397c5c4113dSnw goto error; 2398c5c4113dSnw } 2399c5c4113dSnw 2400c8e26105Sjp if (!(handles->service = scf_service_create(handles->main)) || 2401c8e26105Sjp !(handles->instance = scf_instance_create(handles->main)) || 2402c8e26105Sjp !(handles->config_pg = scf_pg_create(handles->main)) || 2403148c5f43SAlan Wright !(handles->debug_pg = scf_pg_create(handles->main))) { 240471590c90Snw idmapdlog(LOG_ERR, "scf handle creation failed: %s", 240571590c90Snw scf_strerror(scf_error())); 2406c5c4113dSnw goto error; 2407c5c4113dSnw } 2408c5c4113dSnw 2409c8e26105Sjp if (scf_handle_decode_fmri(handles->main, 24104edd44c5Sjp FMRI_BASE "/:properties/" CONFIG_PG, 24114edd44c5Sjp NULL, /* scope */ 24124edd44c5Sjp handles->service, /* service */ 24134edd44c5Sjp handles->instance, /* instance */ 24144edd44c5Sjp handles->config_pg, /* pg */ 24154edd44c5Sjp NULL, /* prop */ 24164edd44c5Sjp SCF_DECODE_FMRI_EXACT) < 0) { 241771590c90Snw idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s", 241871590c90Snw scf_strerror(scf_error())); 2419c5c4113dSnw goto error; 2420c5c4113dSnw } 2421c5c4113dSnw 2422c8e26105Sjp if (scf_service_get_pg(handles->service, 2423148c5f43SAlan Wright DEBUG_PG, handles->debug_pg) < 0) { 2424148c5f43SAlan Wright idmapdlog(LOG_ERR, "Property group \"%s\": %s", 2425148c5f43SAlan Wright DEBUG_PG, scf_strerror(scf_error())); 2426c5c4113dSnw goto error; 2427c5c4113dSnw } 2428c5c4113dSnw 2429148c5f43SAlan Wright check_smf_debug_mode(handles); 2430e3f2c991SKeyur Desai 2431c8e26105Sjp /* Initialize AD Auto Discovery context */ 2432c8e26105Sjp handles->ad_ctx = ad_disc_init(); 2433c8e26105Sjp if (handles->ad_ctx == NULL) 2434c8e26105Sjp goto error; 2435c8e26105Sjp 2436c5c4113dSnw return (cfg); 2437c5c4113dSnw 2438c5c4113dSnw error: 2439c5c4113dSnw (void) idmap_cfg_fini(cfg); 2440c5c4113dSnw return (NULL); 2441c5c4113dSnw } 2442c5c4113dSnw 2443c8e26105Sjp void 24444edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg) 24454edd44c5Sjp { 2446c8e26105Sjp 2447c8e26105Sjp if (pgcfg->default_domain) { 2448c8e26105Sjp free(pgcfg->default_domain); 2449c8e26105Sjp pgcfg->default_domain = NULL; 2450c8e26105Sjp } 2451c8e26105Sjp if (pgcfg->domain_name) { 2452c8e26105Sjp free(pgcfg->domain_name); 2453c8e26105Sjp pgcfg->domain_name = NULL; 2454c8e26105Sjp } 2455b3700b07SGordon Ross if (pgcfg->domain_guid) { 2456b3700b07SGordon Ross free(pgcfg->domain_guid); 2457b3700b07SGordon Ross pgcfg->domain_guid = NULL; 2458b3700b07SGordon Ross } 2459c8e26105Sjp if (pgcfg->machine_sid) { 2460c8e26105Sjp free(pgcfg->machine_sid); 2461c8e26105Sjp pgcfg->machine_sid = NULL; 2462c8e26105Sjp } 2463c8e26105Sjp if (pgcfg->domain_controller) { 2464c5c4113dSnw free(pgcfg->domain_controller); 2465c8e26105Sjp pgcfg->domain_controller = NULL; 2466c8e26105Sjp } 2467c8e26105Sjp if (pgcfg->forest_name) { 2468c8e26105Sjp free(pgcfg->forest_name); 2469c8e26105Sjp pgcfg->forest_name = NULL; 2470c8e26105Sjp } 2471c8e26105Sjp if (pgcfg->site_name) { 2472c8e26105Sjp free(pgcfg->site_name); 2473c8e26105Sjp pgcfg->site_name = NULL; 2474c8e26105Sjp } 2475c8e26105Sjp if (pgcfg->global_catalog) { 2476c8e26105Sjp free(pgcfg->global_catalog); 2477c8e26105Sjp pgcfg->global_catalog = NULL; 2478c8e26105Sjp } 24794d61c878SJulian Pullen if (pgcfg->trusted_domains) { 24804d61c878SJulian Pullen free(pgcfg->trusted_domains); 24814d61c878SJulian Pullen pgcfg->trusted_domains = NULL; 24824d61c878SJulian Pullen } 24834d61c878SJulian Pullen if (pgcfg->trusted_forests) 24844d61c878SJulian Pullen free_trusted_forests(&pgcfg->trusted_forests, 24854d61c878SJulian Pullen &pgcfg->num_trusted_forests); 24864d61c878SJulian Pullen 2487e8c27ec8Sbaban if (pgcfg->ad_unixuser_attr) { 2488e8c27ec8Sbaban free(pgcfg->ad_unixuser_attr); 2489e8c27ec8Sbaban pgcfg->ad_unixuser_attr = NULL; 2490e8c27ec8Sbaban } 2491e8c27ec8Sbaban if (pgcfg->ad_unixgroup_attr) { 2492e8c27ec8Sbaban free(pgcfg->ad_unixgroup_attr); 2493e8c27ec8Sbaban pgcfg->ad_unixgroup_attr = NULL; 2494e8c27ec8Sbaban } 2495e8c27ec8Sbaban if (pgcfg->nldap_winname_attr) { 2496e8c27ec8Sbaban free(pgcfg->nldap_winname_attr); 2497e8c27ec8Sbaban pgcfg->nldap_winname_attr = NULL; 2498e8c27ec8Sbaban } 2499c5c4113dSnw } 2500c5c4113dSnw 2501c5c4113dSnw int 2502c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg) 2503c5c4113dSnw { 2504c8e26105Sjp idmap_cfg_handles_t *handles = &cfg->handles; 2505c8e26105Sjp idmap_cfg_unload(&cfg->pgcfg); 2506c8e26105Sjp 2507c8e26105Sjp (void) pthread_mutex_destroy(&handles->mutex); 2508c8e26105Sjp scf_pg_destroy(handles->config_pg); 2509148c5f43SAlan Wright if (handles->debug_pg != NULL) 2510148c5f43SAlan Wright scf_pg_destroy(handles->debug_pg); 2511c8e26105Sjp scf_instance_destroy(handles->instance); 2512c8e26105Sjp scf_service_destroy(handles->service); 2513c8e26105Sjp scf_handle_destroy(handles->main); 2514e8c27ec8Sbaban if (handles->ad_ctx != NULL) 2515e8c27ec8Sbaban ad_disc_fini(handles->ad_ctx); 2516c5c4113dSnw free(cfg); 2517c5c4113dSnw 2518c5c4113dSnw return (0); 2519c5c4113dSnw } 25200dcc7149Snw 25210dcc7149Snw void 25220dcc7149Snw idmap_cfg_poke_updates(void) 25230dcc7149Snw { 2524b3700b07SGordon Ross int prev_st; 2525b3700b07SGordon Ross 2526b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2527b3700b07SGordon Ross idmapdlog(LOG_INFO, "idmap_cfg_poke_updates"); 2528b3700b07SGordon Ross } 2529b3700b07SGordon Ross 2530b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2531b3700b07SGordon Ross prev_st = _idmapdstate.addisc_st; 2532b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED; 2533b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2534b3700b07SGordon Ross 2535b3700b07SGordon Ross if (prev_st & ADDISC_ST_REQUESTED) { 2536b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "already poked"); 2537b3700b07SGordon Ross } else { 2538b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "port send poke"); 2539349d5d8fSnw (void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL); 2540b3700b07SGordon Ross } 2541b3700b07SGordon Ross } 2542b3700b07SGordon Ross 2543b3700b07SGordon Ross void 2544b3700b07SGordon Ross idmap_cfg_force_rediscovery(void) 2545b3700b07SGordon Ross { 2546b3700b07SGordon Ross int prev_st; 2547b3700b07SGordon Ross 2548b3700b07SGordon Ross if (DBG(CONFIG, 1)) { 2549b3700b07SGordon Ross idmapdlog(LOG_INFO, "idmap_cfg_force_rediscovery"); 2550b3700b07SGordon Ross } 2551b3700b07SGordon Ross 2552b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 2553b3700b07SGordon Ross prev_st = _idmapdstate.addisc_st; 2554b3700b07SGordon Ross _idmapdstate.addisc_st |= ADDISC_ST_REQUESTED; 2555b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 2556b3700b07SGordon Ross 2557b3700b07SGordon Ross if (prev_st & ADDISC_ST_REQUESTED) { 2558b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "already kicked"); 2559b3700b07SGordon Ross } else { 2560b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "port send kick"); 2561b3700b07SGordon Ross (void) port_send(idmapd_ev_port, KICK_AUTO_DISCOVERY, NULL); 2562b3700b07SGordon Ross } 25630dcc7149Snw } 25640dcc7149Snw 25650dcc7149Snw /*ARGSUSED*/ 25660dcc7149Snw void 2567349d5d8fSnw idmap_cfg_hup_handler(int sig) 2568349d5d8fSnw { 25690dcc7149Snw if (idmapd_ev_port >= 0) 25700dcc7149Snw (void) port_send(idmapd_ev_port, RECONFIGURE, NULL); 25710dcc7149Snw } 2572e3f2c991SKeyur Desai 2573148c5f43SAlan Wright /* 2574148c5f43SAlan Wright * Upgrade the debug flags. 2575148c5f43SAlan Wright * 2576148c5f43SAlan Wright * We're replacing a single debug flag with a fine-grained mechanism that 2577148c5f43SAlan Wright * is also capable of considerably more verbosity. We'll take a stab at 2578148c5f43SAlan Wright * producing roughly the same level of output. 2579148c5f43SAlan Wright */ 2580148c5f43SAlan Wright static 2581148c5f43SAlan Wright int 2582148c5f43SAlan Wright upgrade_debug(idmap_cfg_handles_t *handles) 2583148c5f43SAlan Wright { 2584148c5f43SAlan Wright boolean_t debug_present; 2585148c5f43SAlan Wright const char DEBUG_PROP[] = "debug"; 2586148c5f43SAlan Wright int rc; 2587148c5f43SAlan Wright 2588148c5f43SAlan Wright rc = prop_exists(handles, DEBUG_PROP, &debug_present); 2589148c5f43SAlan Wright 2590148c5f43SAlan Wright if (rc != 0) 2591148c5f43SAlan Wright return (rc); 2592148c5f43SAlan Wright 2593148c5f43SAlan Wright if (!debug_present) 2594148c5f43SAlan Wright return (0); 2595148c5f43SAlan Wright 2596148c5f43SAlan Wright idmapdlog(LOG_INFO, 2597148c5f43SAlan Wright "Upgrading old %s/%s setting to %s/* settings.", 2598148c5f43SAlan Wright CONFIG_PG, DEBUG_PROP, DEBUG_PG); 2599148c5f43SAlan Wright 2600148c5f43SAlan Wright rc = set_val_integer(handles, handles->debug_pg, "config", 1); 2601148c5f43SAlan Wright if (rc != 0) 2602148c5f43SAlan Wright return (rc); 2603148c5f43SAlan Wright rc = set_val_integer(handles, handles->debug_pg, "discovery", 1); 2604148c5f43SAlan Wright if (rc != 0) 2605148c5f43SAlan Wright return (rc); 2606148c5f43SAlan Wright 2607148c5f43SAlan Wright rc = del_val(handles, handles->config_pg, DEBUG_PROP); 2608148c5f43SAlan Wright if (rc != 0) 2609148c5f43SAlan Wright return (rc); 2610148c5f43SAlan Wright 2611148c5f43SAlan Wright return (0); 2612148c5f43SAlan Wright } 2613148c5f43SAlan Wright 2614e3f2c991SKeyur Desai /* 2615e3f2c991SKeyur Desai * Upgrade the DS mapping flags. 2616e3f2c991SKeyur Desai * 2617e3f2c991SKeyur Desai * If the old ds_name_mapping_enabled flag is present, then 2618e3f2c991SKeyur Desai * if the new directory_based_mapping value is present, then 2619e3f2c991SKeyur Desai * if the two are compatible, delete the old and note it 2620e3f2c991SKeyur Desai * else delete the old and warn 2621e3f2c991SKeyur Desai * else 2622e3f2c991SKeyur Desai * set the new based on the old, and note it 2623e3f2c991SKeyur Desai * delete the old 2624e3f2c991SKeyur Desai */ 2625e3f2c991SKeyur Desai static 2626e3f2c991SKeyur Desai int 2627e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles) 2628e3f2c991SKeyur Desai { 2629e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_present; 2630e3f2c991SKeyur Desai const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled"; 2631e3f2c991SKeyur Desai const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping"; 2632e3f2c991SKeyur Desai int rc; 2633e3f2c991SKeyur Desai 2634e3f2c991SKeyur Desai rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED, 2635e3f2c991SKeyur Desai &legacy_ds_name_mapping_present); 2636e3f2c991SKeyur Desai 2637e3f2c991SKeyur Desai if (rc != 0) 2638e3f2c991SKeyur Desai return (rc); 2639e3f2c991SKeyur Desai 2640e3f2c991SKeyur Desai if (!legacy_ds_name_mapping_present) 2641e3f2c991SKeyur Desai return (0); 2642e3f2c991SKeyur Desai 2643e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_enabled; 2644148c5f43SAlan Wright rc = get_val_bool(handles, DS_NAME_MAPPING_ENABLED, 2645148c5f43SAlan Wright &legacy_ds_name_mapping_enabled, B_FALSE); 2646e3f2c991SKeyur Desai if (rc != 0) 2647e3f2c991SKeyur Desai return (rc); 2648e3f2c991SKeyur Desai 2649e3f2c991SKeyur Desai char *legacy_mode; 2650e3f2c991SKeyur Desai char *legacy_bool_string; 2651e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled) { 2652e3f2c991SKeyur Desai legacy_mode = "name"; 2653e3f2c991SKeyur Desai legacy_bool_string = "true"; 2654e3f2c991SKeyur Desai } else { 2655e3f2c991SKeyur Desai legacy_mode = "none"; 2656e3f2c991SKeyur Desai legacy_bool_string = "false"; 2657e3f2c991SKeyur Desai } 2658e3f2c991SKeyur Desai 2659e3f2c991SKeyur Desai char *directory_based_mapping; 2660e3f2c991SKeyur Desai rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING, 2661e3f2c991SKeyur Desai &directory_based_mapping); 2662e3f2c991SKeyur Desai if (rc != 0) 2663e3f2c991SKeyur Desai return (rc); 2664e3f2c991SKeyur Desai 2665e3f2c991SKeyur Desai if (directory_based_mapping == NULL) { 2666e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 2667e3f2c991SKeyur Desai "Upgrading old %s=%s setting\n" 2668e3f2c991SKeyur Desai "to %s=%s.", 2669e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2670e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, legacy_mode); 2671148c5f43SAlan Wright rc = set_val_astring(handles, handles->config_pg, 2672148c5f43SAlan Wright DIRECTORY_BASED_MAPPING, legacy_mode); 2673e3f2c991SKeyur Desai if (rc != 0) 2674e3f2c991SKeyur Desai return (rc); 2675e3f2c991SKeyur Desai } else { 2676e3f2c991SKeyur Desai boolean_t new_name_mapping; 2677e3f2c991SKeyur Desai if (strcasecmp(directory_based_mapping, "name") == 0) 2678e3f2c991SKeyur Desai new_name_mapping = B_TRUE; 2679e3f2c991SKeyur Desai else 2680e3f2c991SKeyur Desai new_name_mapping = B_FALSE; 2681e3f2c991SKeyur Desai 2682e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled == new_name_mapping) { 2683e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 2684e3f2c991SKeyur Desai "Automatically removing old %s=%s setting\n" 2685e3f2c991SKeyur Desai "in favor of %s=%s.", 2686e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2687e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 2688e3f2c991SKeyur Desai } else { 2689e3f2c991SKeyur Desai idmapdlog(LOG_WARNING, 2690e3f2c991SKeyur Desai "Removing conflicting %s=%s setting\n" 2691e3f2c991SKeyur Desai "in favor of %s=%s.", 2692e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 2693e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 2694e3f2c991SKeyur Desai } 2695e3f2c991SKeyur Desai free(directory_based_mapping); 2696e3f2c991SKeyur Desai } 2697e3f2c991SKeyur Desai 2698148c5f43SAlan Wright rc = del_val(handles, handles->config_pg, DS_NAME_MAPPING_ENABLED); 2699e3f2c991SKeyur Desai if (rc != 0) 2700e3f2c991SKeyur Desai return (rc); 2701e3f2c991SKeyur Desai 2702e3f2c991SKeyur Desai return (0); 2703e3f2c991SKeyur Desai } 2704e3f2c991SKeyur Desai 2705e3f2c991SKeyur Desai /* 2706e3f2c991SKeyur Desai * Do whatever is necessary to upgrade idmap's configuration before 2707e3f2c991SKeyur Desai * we load it. 2708e3f2c991SKeyur Desai */ 2709e3f2c991SKeyur Desai int 2710e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg) 2711e3f2c991SKeyur Desai { 2712e3f2c991SKeyur Desai int rc; 2713e3f2c991SKeyur Desai 2714e3f2c991SKeyur Desai rc = upgrade_directory_mapping(&cfg->handles); 2715e3f2c991SKeyur Desai if (rc != 0) 2716e3f2c991SKeyur Desai return (rc); 2717e3f2c991SKeyur Desai 2718148c5f43SAlan Wright rc = upgrade_debug(&cfg->handles); 2719148c5f43SAlan Wright if (rc != 0) 2720148c5f43SAlan Wright return (rc); 2721148c5f43SAlan Wright 2722e3f2c991SKeyur Desai return (0); 2723e3f2c991SKeyur Desai } 2724b3700b07SGordon Ross 2725b3700b07SGordon Ross /* 2726b3700b07SGordon Ross * The LDAP code passes principal names lacking any 2727b3700b07SGordon Ross * realm information, which causes mech_krb5 to do 2728b3700b07SGordon Ross * awful things trying to figure out the realm. 2729b3700b07SGordon Ross * Avoid that by making sure it has a default, 2730b3700b07SGordon Ross * even when krb5.conf is not configured. 2731b3700b07SGordon Ross */ 2732b3700b07SGordon Ross static void 2733b3700b07SGordon Ross idmapd_set_krb5_realm(char *domain) 2734b3700b07SGordon Ross { 2735b3700b07SGordon Ross static char realm[MAXHOSTNAMELEN]; 2736b3700b07SGordon Ross size_t ilen, olen; 2737b3700b07SGordon Ross int err; 2738b3700b07SGordon Ross 2739b3700b07SGordon Ross if (domain == NULL) { 2740b3700b07SGordon Ross (void) unsetenv("KRB5_DEFAULT_REALM"); 2741b3700b07SGordon Ross return; 2742b3700b07SGordon Ross } 2743b3700b07SGordon Ross 2744b3700b07SGordon Ross /* Convert to upper case, in place. */ 2745b3700b07SGordon Ross (void) strlcpy(realm, domain, sizeof (realm)); 2746b3700b07SGordon Ross olen = ilen = strlen(realm); 2747b3700b07SGordon Ross (void) u8_textprep_str(realm, &ilen, realm, &olen, 2748b3700b07SGordon Ross U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err); 2749b3700b07SGordon Ross 2750b3700b07SGordon Ross (void) setenv("KRB5_DEFAULT_REALM", realm, 1); 2751b3700b07SGordon Ross } 2752