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 /* 22*c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23c5c4113dSnw */ 24c5c4113dSnw 25c5c4113dSnw 26c5c4113dSnw /* 27c5c4113dSnw * Config routines common to idmap(1M) and idmapd(1M) 28c5c4113dSnw */ 29c5c4113dSnw 30c5c4113dSnw #include <stdlib.h> 31c5c4113dSnw #include <strings.h> 32c5c4113dSnw #include <libintl.h> 33c5c4113dSnw #include <ctype.h> 34c5c4113dSnw #include <errno.h> 35651c0131Sbaban #include "idmapd.h" 36c5c4113dSnw #include <stdio.h> 37c5c4113dSnw #include <stdarg.h> 388edda628Sbaban #include <uuid/uuid.h> 39c8e26105Sjp #include <pthread.h> 40c8e26105Sjp #include <port.h> 410dcc7149Snw #include <net/route.h> 424d61c878SJulian Pullen #include <sys/u8_textprep.h> 43c8e26105Sjp #include "addisc.h" 44c5c4113dSnw 454aa0a5e7Snw #define MACHINE_SID_LEN (9 + 3 * 11) 460dcc7149Snw #define FMRI_BASE "svc:/system/idmap" 470dcc7149Snw #define CONFIG_PG "config" 480dcc7149Snw #define GENERAL_PG "general" 490dcc7149Snw #define RECONFIGURE 1 500dcc7149Snw #define POKE_AUTO_DISCOVERY 2 51c5c4113dSnw 52*c5866007SKeyur Desai enum event_type { 53*c5866007SKeyur Desai EVENT_NOTHING, /* Woke up for no good reason */ 54*c5866007SKeyur Desai EVENT_TIMEOUT, /* Timeout expired */ 55*c5866007SKeyur Desai EVENT_ROUTING, /* An interesting routing event happened */ 56*c5866007SKeyur Desai EVENT_DEGRADE, /* An error occurred in the mainline */ 57*c5866007SKeyur Desai EVENT_REFRESH, /* SMF refresh */ 58*c5866007SKeyur Desai }; 59*c5866007SKeyur Desai 60c8e26105Sjp /*LINTLIBRARY*/ 61c8e26105Sjp 62c8e26105Sjp 63c8e26105Sjp static pthread_t update_thread_handle = 0; 64c8e26105Sjp 650dcc7149Snw static int idmapd_ev_port = -1; 660dcc7149Snw static int rt_sock = -1; 67c8e26105Sjp 68e3f2c991SKeyur Desai struct enum_lookup_map directory_mapping_map[] = { 69e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NONE, "none" }, 70e3f2c991SKeyur Desai { DIRECTORY_MAPPING_NAME, "name" }, 71e3f2c991SKeyur Desai { DIRECTORY_MAPPING_IDMU, "idmu" }, 72e3f2c991SKeyur Desai { 0, NULL }, 73e3f2c991SKeyur Desai }; 74e3f2c991SKeyur Desai 758edda628Sbaban static int 764edd44c5Sjp generate_machine_sid(char **machine_sid) 774edd44c5Sjp { 788edda628Sbaban char *p; 798edda628Sbaban uuid_t uu; 808edda628Sbaban int i, j, len, rlen; 818edda628Sbaban uint32_t rid; 828edda628Sbaban 838edda628Sbaban /* 844aa0a5e7Snw * Generate and split 128-bit UUID into three 32-bit RIDs The 854aa0a5e7Snw * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's 864aa0a5e7Snw * four RIDs altogether). 874aa0a5e7Snw * 88e3f2c991SKeyur Desai * Technically we could use up to 14 random RIDs here, but it 894aa0a5e7Snw * turns out that with some versions of Windows using SIDs with 904aa0a5e7Snw * more than five RIDs in security descriptors causes problems. 918edda628Sbaban */ 928edda628Sbaban 938edda628Sbaban *machine_sid = calloc(1, MACHINE_SID_LEN); 948edda628Sbaban if (*machine_sid == NULL) { 9571590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 968edda628Sbaban return (-1); 978edda628Sbaban } 988edda628Sbaban (void) strcpy(*machine_sid, "S-1-5-21"); 998edda628Sbaban p = *machine_sid + strlen("S-1-5-21"); 1008edda628Sbaban len = MACHINE_SID_LEN - strlen("S-1-5-21"); 1018edda628Sbaban 1028edda628Sbaban uuid_clear(uu); 1038edda628Sbaban uuid_generate_random(uu); 1048edda628Sbaban 1054aa0a5e7Snw #if UUID_LEN != 16 1064aa0a5e7Snw #error UUID size is not 16! 1074aa0a5e7Snw #endif 1084aa0a5e7Snw 1094aa0a5e7Snw for (i = 0; i < 3; i++) { 1108edda628Sbaban j = i * 4; 1118edda628Sbaban rid = (uu[j] << 24) | (uu[j + 1] << 16) | 1124edd44c5Sjp (uu[j + 2] << 8) | (uu[j + 3]); 1138edda628Sbaban rlen = snprintf(p, len, "-%u", rid); 1148edda628Sbaban p += rlen; 1158edda628Sbaban len -= rlen; 1168edda628Sbaban } 1178edda628Sbaban 1188edda628Sbaban return (0); 1198edda628Sbaban } 1208edda628Sbaban 121479ac375Sdm 122479ac375Sdm /* In the case of error, exists is set to FALSE anyway */ 123479ac375Sdm static int 124e3f2c991SKeyur Desai prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists) 12571590c90Snw { 12671590c90Snw 127479ac375Sdm scf_property_t *scf_prop; 128479ac375Sdm scf_value_t *value; 129479ac375Sdm 1307a8a68f5SJulian Pullen *exists = B_FALSE; 131479ac375Sdm 132479ac375Sdm scf_prop = scf_property_create(handles->main); 133479ac375Sdm if (scf_prop == NULL) { 134479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 135479ac375Sdm scf_strerror(scf_error())); 136479ac375Sdm return (-1); 137479ac375Sdm } 138479ac375Sdm value = scf_value_create(handles->main); 139479ac375Sdm if (value == NULL) { 140479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 141479ac375Sdm scf_strerror(scf_error())); 142479ac375Sdm scf_property_destroy(scf_prop); 143479ac375Sdm return (-1); 144479ac375Sdm } 14571590c90Snw 14671590c90Snw if (scf_pg_get_property(handles->config_pg, name, scf_prop) == 0) 1477a8a68f5SJulian Pullen *exists = B_TRUE; 14871590c90Snw 14971590c90Snw scf_value_destroy(value); 15071590c90Snw scf_property_destroy(scf_prop); 15171590c90Snw 152479ac375Sdm return (0); 15371590c90Snw } 15471590c90Snw 155c5c4113dSnw /* Check if in the case of failure the original value of *val is preserved */ 156c5c4113dSnw static int 157e3f2c991SKeyur Desai get_val_int(idmap_cfg_handles_t *handles, const char *name, 158c8e26105Sjp void *val, scf_type_t type) 159c5c4113dSnw { 160c5c4113dSnw int rc = 0; 161c5c4113dSnw 162479ac375Sdm scf_property_t *scf_prop; 163479ac375Sdm scf_value_t *value; 164e3f2c991SKeyur Desai uint8_t b; 165479ac375Sdm 1664aa0a5e7Snw switch (type) { 1674aa0a5e7Snw case SCF_TYPE_BOOLEAN: 168e3f2c991SKeyur Desai *(boolean_t *)val = B_FALSE; 1694aa0a5e7Snw break; 1704aa0a5e7Snw case SCF_TYPE_COUNT: 1714aa0a5e7Snw *(uint64_t *)val = 0; 1724aa0a5e7Snw break; 1734aa0a5e7Snw case SCF_TYPE_INTEGER: 1744aa0a5e7Snw *(int64_t *)val = 0; 1754aa0a5e7Snw break; 1764aa0a5e7Snw default: 1774aa0a5e7Snw idmapdlog(LOG_ERR, "Invalid scf integer type (%d)", 1784aa0a5e7Snw type); 1794aa0a5e7Snw abort(); 1804aa0a5e7Snw } 1814aa0a5e7Snw 182479ac375Sdm scf_prop = scf_property_create(handles->main); 183479ac375Sdm if (scf_prop == NULL) { 184479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 185479ac375Sdm scf_strerror(scf_error())); 186479ac375Sdm return (-1); 187479ac375Sdm } 188479ac375Sdm value = scf_value_create(handles->main); 189479ac375Sdm if (value == NULL) { 190479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 191479ac375Sdm scf_strerror(scf_error())); 192479ac375Sdm scf_property_destroy(scf_prop); 193479ac375Sdm return (-1); 194479ac375Sdm } 195c5c4113dSnw 196c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 197c5c4113dSnw /* this is OK: the property is just undefined */ 198c5c4113dSnw goto destruction; 199c5c4113dSnw 200c5c4113dSnw 201c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) 202c5c4113dSnw /* It is still OK when a property doesn't have any value */ 203c5c4113dSnw goto destruction; 204c5c4113dSnw 205c5c4113dSnw switch (type) { 206c5c4113dSnw case SCF_TYPE_BOOLEAN: 207e3f2c991SKeyur Desai rc = scf_value_get_boolean(value, &b); 208e3f2c991SKeyur Desai *(boolean_t *)val = b; 209c5c4113dSnw break; 210c5c4113dSnw case SCF_TYPE_COUNT: 211c5c4113dSnw rc = scf_value_get_count(value, val); 212c5c4113dSnw break; 213c5c4113dSnw case SCF_TYPE_INTEGER: 214c5c4113dSnw rc = scf_value_get_integer(value, val); 215c5c4113dSnw break; 216e3f2c991SKeyur Desai default: 217e3f2c991SKeyur Desai abort(); /* tested above */ 218e3f2c991SKeyur Desai /* NOTREACHED */ 219c5c4113dSnw } 220c5c4113dSnw 221e3f2c991SKeyur Desai if (rc != 0) { 222e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 223e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 224e3f2c991SKeyur Desai } 225c5c4113dSnw 226c5c4113dSnw destruction: 227c5c4113dSnw scf_value_destroy(value); 228c5c4113dSnw scf_property_destroy(scf_prop); 229c5c4113dSnw 230c5c4113dSnw return (rc); 231c5c4113dSnw } 232c5c4113dSnw 233c5c4113dSnw static char * 234e3f2c991SKeyur Desai scf_value2string(const char *name, scf_value_t *value) 2354edd44c5Sjp { 236e3f2c991SKeyur Desai static size_t max_val = 0; 237c5c4113dSnw 238e3f2c991SKeyur Desai if (max_val == 0) 239e3f2c991SKeyur Desai max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 240c5c4113dSnw 241e3f2c991SKeyur Desai char buf[max_val + 1]; 242e3f2c991SKeyur Desai if (scf_value_get_astring(value, buf, max_val + 1) < 0) { 243e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", 244e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 245e3f2c991SKeyur Desai return (NULL); 246c5c4113dSnw } 247c5c4113dSnw 248e3f2c991SKeyur Desai char *s = strdup(buf); 249e3f2c991SKeyur Desai if (s == NULL) 250e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "Out of memory"); 251c5c4113dSnw 252e3f2c991SKeyur Desai return (s); 253c5c4113dSnw } 254c5c4113dSnw 255c8e26105Sjp static int 256c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport, 257479ac375Sdm idmap_ad_disc_ds_t **val) 258c8e26105Sjp { 259479ac375Sdm idmap_ad_disc_ds_t *servers = NULL; 260c8e26105Sjp scf_property_t *scf_prop; 261c8e26105Sjp scf_value_t *value; 262c8e26105Sjp scf_iter_t *iter; 263c8e26105Sjp char *host, *portstr; 264e3c2d6aaSnw int len, i; 265c8e26105Sjp int count = 0; 266e3c2d6aaSnw int rc = -1; 267c8e26105Sjp 268c8e26105Sjp *val = NULL; 269c8e26105Sjp 270c8e26105Sjp restart: 271c8e26105Sjp scf_prop = scf_property_create(handles->main); 272479ac375Sdm if (scf_prop == NULL) { 273479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 274479ac375Sdm scf_strerror(scf_error())); 275479ac375Sdm return (-1); 276479ac375Sdm } 277479ac375Sdm 278c8e26105Sjp value = scf_value_create(handles->main); 279479ac375Sdm if (value == NULL) { 280479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 281479ac375Sdm scf_strerror(scf_error())); 282479ac375Sdm scf_property_destroy(scf_prop); 283479ac375Sdm return (-1); 284479ac375Sdm } 285479ac375Sdm 286c8e26105Sjp iter = scf_iter_create(handles->main); 287479ac375Sdm if (iter == NULL) { 288479ac375Sdm idmapdlog(LOG_ERR, "scf_iter_create() failed: %s", 289479ac375Sdm scf_strerror(scf_error())); 290479ac375Sdm scf_value_destroy(value); 291479ac375Sdm scf_property_destroy(scf_prop); 292479ac375Sdm return (-1); 293479ac375Sdm } 294c8e26105Sjp 295e3c2d6aaSnw if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) { 296c8e26105Sjp /* this is OK: the property is just undefined */ 297e3c2d6aaSnw rc = 0; 298c8e26105Sjp goto destruction; 299e3c2d6aaSnw } 300c8e26105Sjp 301c8e26105Sjp if (scf_iter_property_values(iter, scf_prop) < 0) { 302c8e26105Sjp idmapdlog(LOG_ERR, 30371590c90Snw "scf_iter_property_values(%s) failed: %s", 30471590c90Snw name, scf_strerror(scf_error())); 305c8e26105Sjp goto destruction; 306c8e26105Sjp } 307c8e26105Sjp 308c8e26105Sjp /* Workaround scf bugs -- can't reset an iteration */ 309c8e26105Sjp if (count == 0) { 310c8e26105Sjp while (scf_iter_next_value(iter, value) > 0) 311c8e26105Sjp count++; 312c8e26105Sjp 313e3c2d6aaSnw if (count == 0) { 314c8e26105Sjp /* no values */ 315e3c2d6aaSnw rc = 0; 316c8e26105Sjp goto destruction; 317e3c2d6aaSnw } 318c8e26105Sjp 319c8e26105Sjp scf_value_destroy(value); 320c8e26105Sjp scf_iter_destroy(iter); 321c8e26105Sjp scf_property_destroy(scf_prop); 322c8e26105Sjp goto restart; 323c8e26105Sjp } 324c8e26105Sjp 325c8e26105Sjp if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) { 32671590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 327c8e26105Sjp goto destruction; 328c8e26105Sjp } 329c8e26105Sjp 330e3c2d6aaSnw i = 0; 331e3c2d6aaSnw while (i < count && scf_iter_next_value(iter, value) > 0) { 332e3c2d6aaSnw servers[i].priority = 0; 333e3c2d6aaSnw servers[i].weight = 100; 334e3c2d6aaSnw servers[i].port = defport; 335e3f2c991SKeyur Desai if ((host = scf_value2string(name, value)) == NULL) { 336c8e26105Sjp goto destruction; 337c8e26105Sjp } 338c8e26105Sjp if ((portstr = strchr(host, ':')) != NULL) { 339c8e26105Sjp *portstr++ = '\0'; 340e3c2d6aaSnw servers[i].port = strtol(portstr, 341c8e26105Sjp (char **)NULL, 10); 342e3c2d6aaSnw if (servers[i].port == 0) 343e3c2d6aaSnw servers[i].port = defport; 344c8e26105Sjp } 345e3c2d6aaSnw len = strlcpy(servers[i].host, host, 346c8e26105Sjp sizeof (servers->host)); 347c8e26105Sjp 348c8e26105Sjp free(host); 349c8e26105Sjp 350c8e26105Sjp /* Ignore this server if the hostname is too long */ 351c8e26105Sjp if (len < sizeof (servers->host)) 352e3c2d6aaSnw i++; 353c8e26105Sjp } 354c8e26105Sjp 355c8e26105Sjp *val = servers; 356c8e26105Sjp 357e3c2d6aaSnw rc = 0; 358e3c2d6aaSnw 359c8e26105Sjp destruction: 360c8e26105Sjp scf_value_destroy(value); 361c8e26105Sjp scf_iter_destroy(iter); 362c8e26105Sjp scf_property_destroy(scf_prop); 363c8e26105Sjp 364c8e26105Sjp if (rc < 0) { 365c8e26105Sjp if (servers) 366c8e26105Sjp free(servers); 367c8e26105Sjp *val = NULL; 368c8e26105Sjp } 369c8e26105Sjp 370c8e26105Sjp return (rc); 371c8e26105Sjp } 372c8e26105Sjp 373c5c4113dSnw 374c5c4113dSnw static int 375e3f2c991SKeyur Desai get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val) 376c5c4113dSnw { 377c5c4113dSnw int rc = 0; 378c5c4113dSnw 379479ac375Sdm scf_property_t *scf_prop; 380479ac375Sdm scf_value_t *value; 381479ac375Sdm 382479ac375Sdm scf_prop = scf_property_create(handles->main); 383479ac375Sdm if (scf_prop == NULL) { 384479ac375Sdm idmapdlog(LOG_ERR, "scf_property_create() failed: %s", 385479ac375Sdm scf_strerror(scf_error())); 386479ac375Sdm return (-1); 387479ac375Sdm } 388479ac375Sdm value = scf_value_create(handles->main); 389479ac375Sdm if (value == NULL) { 390479ac375Sdm idmapdlog(LOG_ERR, "scf_value_create() failed: %s", 391479ac375Sdm scf_strerror(scf_error())); 392479ac375Sdm scf_property_destroy(scf_prop); 393479ac375Sdm return (-1); 394479ac375Sdm } 395c5c4113dSnw 396c8e26105Sjp *val = NULL; 397c5c4113dSnw 398c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 399c5c4113dSnw /* this is OK: the property is just undefined */ 400c5c4113dSnw goto destruction; 401c5c4113dSnw 402c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) { 403651c0131Sbaban idmapdlog(LOG_ERR, 40471590c90Snw "scf_property_get_value(%s) failed: %s", 40571590c90Snw name, scf_strerror(scf_error())); 406c5c4113dSnw rc = -1; 407c5c4113dSnw goto destruction; 408c5c4113dSnw } 409c5c4113dSnw 410e3f2c991SKeyur Desai *val = scf_value2string(name, value); 411e3f2c991SKeyur Desai if (*val == NULL) 412c5c4113dSnw rc = -1; 413c5c4113dSnw 414c5c4113dSnw destruction: 415c5c4113dSnw scf_value_destroy(value); 416c5c4113dSnw scf_property_destroy(scf_prop); 417c5c4113dSnw 418c5c4113dSnw if (rc < 0) { 419c5c4113dSnw if (*val) 420c5c4113dSnw free(*val); 421c5c4113dSnw *val = NULL; 422c5c4113dSnw } 423c5c4113dSnw 424c5c4113dSnw return (rc); 425c5c4113dSnw } 426c5c4113dSnw 427c8e26105Sjp 4288edda628Sbaban static int 429e3f2c991SKeyur Desai del_val(idmap_cfg_handles_t *handles, const char *name) 430e3f2c991SKeyur Desai { 431e3f2c991SKeyur Desai int rc = -1; 432e3f2c991SKeyur Desai int ret; 433e3f2c991SKeyur Desai scf_transaction_t *tx = NULL; 434e3f2c991SKeyur Desai scf_transaction_entry_t *ent = NULL; 435e3f2c991SKeyur Desai 436e3f2c991SKeyur Desai if ((tx = scf_transaction_create(handles->main)) == NULL) { 437e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 438e3f2c991SKeyur Desai "scf_transaction_create() failed: %s", 439e3f2c991SKeyur Desai scf_strerror(scf_error())); 440e3f2c991SKeyur Desai goto destruction; 441e3f2c991SKeyur Desai } 442e3f2c991SKeyur Desai if ((ent = scf_entry_create(handles->main)) == NULL) { 443e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 444e3f2c991SKeyur Desai "scf_entry_create() failed: %s", 445e3f2c991SKeyur Desai scf_strerror(scf_error())); 446e3f2c991SKeyur Desai goto destruction; 447e3f2c991SKeyur Desai } 448e3f2c991SKeyur Desai 449e3f2c991SKeyur Desai do { 450e3f2c991SKeyur Desai if (scf_pg_update(handles->config_pg) == -1) { 451e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 452e3f2c991SKeyur Desai "scf_pg_update(%s) failed: %s", 453e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 454e3f2c991SKeyur Desai goto destruction; 455e3f2c991SKeyur Desai } 456e3f2c991SKeyur Desai if (scf_transaction_start(tx, handles->config_pg) != 0) { 457e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 458e3f2c991SKeyur Desai "scf_transaction_start(%s) failed: %s", 459e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 460e3f2c991SKeyur Desai goto destruction; 461e3f2c991SKeyur Desai } 462e3f2c991SKeyur Desai 463e3f2c991SKeyur Desai if (scf_transaction_property_delete(tx, ent, name) != 0) { 464e3f2c991SKeyur Desai /* Don't complain if it already doesn't exist. */ 465e3f2c991SKeyur Desai if (scf_error() != SCF_ERROR_NOT_FOUND) { 466e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 467e3f2c991SKeyur Desai "scf_transaction_property_delete() failed:" 468e3f2c991SKeyur Desai " %s", 469e3f2c991SKeyur Desai scf_strerror(scf_error())); 470e3f2c991SKeyur Desai } 471e3f2c991SKeyur Desai goto destruction; 472e3f2c991SKeyur Desai } 473e3f2c991SKeyur Desai 474e3f2c991SKeyur Desai ret = scf_transaction_commit(tx); 475e3f2c991SKeyur Desai 476e3f2c991SKeyur Desai if (ret == 0) 477e3f2c991SKeyur Desai scf_transaction_reset(tx); 478e3f2c991SKeyur Desai } while (ret == 0); 479e3f2c991SKeyur Desai 480e3f2c991SKeyur Desai if (ret == -1) { 481e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 482e3f2c991SKeyur Desai "scf_transaction_commit(%s) failed: %s", 483e3f2c991SKeyur Desai name, scf_strerror(scf_error())); 484e3f2c991SKeyur Desai goto destruction; 485e3f2c991SKeyur Desai } 486e3f2c991SKeyur Desai 487e3f2c991SKeyur Desai rc = 0; 488e3f2c991SKeyur Desai 489e3f2c991SKeyur Desai destruction: 490e3f2c991SKeyur Desai if (ent != NULL) 491e3f2c991SKeyur Desai scf_entry_destroy(ent); 492e3f2c991SKeyur Desai if (tx != NULL) 493e3f2c991SKeyur Desai scf_transaction_destroy(tx); 494e3f2c991SKeyur Desai return (rc); 495e3f2c991SKeyur Desai } 496e3f2c991SKeyur Desai 497e3f2c991SKeyur Desai 498e3f2c991SKeyur Desai static int 499e3f2c991SKeyur Desai set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val) 5008edda628Sbaban { 501e3c2d6aaSnw int rc = -1; 502e3c2d6aaSnw int ret = -2; 503e3c2d6aaSnw int i; 5048edda628Sbaban scf_property_t *scf_prop = NULL; 5058edda628Sbaban scf_value_t *value = NULL; 5068edda628Sbaban scf_transaction_t *tx = NULL; 5078edda628Sbaban scf_transaction_entry_t *ent = NULL; 5088edda628Sbaban 509c8e26105Sjp if ((scf_prop = scf_property_create(handles->main)) == NULL || 510c8e26105Sjp (value = scf_value_create(handles->main)) == NULL || 511c8e26105Sjp (tx = scf_transaction_create(handles->main)) == NULL || 512c8e26105Sjp (ent = scf_entry_create(handles->main)) == NULL) { 51371590c90Snw idmapdlog(LOG_ERR, "Unable to set property %s", 51471590c90Snw name, scf_strerror(scf_error())); 5158edda628Sbaban goto destruction; 5168edda628Sbaban } 5178edda628Sbaban 518e3c2d6aaSnw for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) { 519c8e26105Sjp if (scf_transaction_start(tx, handles->config_pg) == -1) { 5208edda628Sbaban idmapdlog(LOG_ERR, 52171590c90Snw "scf_transaction_start(%s) failed: %s", 52271590c90Snw name, scf_strerror(scf_error())); 5238edda628Sbaban goto destruction; 5248edda628Sbaban } 5258edda628Sbaban 526e3c2d6aaSnw if (scf_transaction_property_new(tx, ent, name, 527e3c2d6aaSnw SCF_TYPE_ASTRING) < 0) { 5288edda628Sbaban idmapdlog(LOG_ERR, 52971590c90Snw "scf_transaction_property_new() failed: %s", 53071590c90Snw scf_strerror(scf_error())); 5318edda628Sbaban goto destruction; 5328edda628Sbaban } 5338edda628Sbaban 5348edda628Sbaban if (scf_value_set_astring(value, val) == -1) { 5358edda628Sbaban idmapdlog(LOG_ERR, 53671590c90Snw "scf_value_set_astring() failed: %s", 53771590c90Snw scf_strerror(scf_error())); 5388edda628Sbaban goto destruction; 5398edda628Sbaban } 5408edda628Sbaban 5418edda628Sbaban if (scf_entry_add_value(ent, value) == -1) { 5428edda628Sbaban idmapdlog(LOG_ERR, 54371590c90Snw "scf_entry_add_value() failed: %s", 54471590c90Snw scf_strerror(scf_error())); 5458edda628Sbaban goto destruction; 5468edda628Sbaban } 5478edda628Sbaban 548e3c2d6aaSnw if ((ret = scf_transaction_commit(tx)) == 1) 549e3c2d6aaSnw break; 550e3c2d6aaSnw 551e3c2d6aaSnw if (ret == 0 && i < MAX_TRIES - 1) { 5528edda628Sbaban /* 5538edda628Sbaban * Property group set in scf_transaction_start() 5548edda628Sbaban * is not the most recent. Update pg, reset tx and 5558edda628Sbaban * retry tx. 5568edda628Sbaban */ 5578edda628Sbaban idmapdlog(LOG_WARNING, 55871590c90Snw "scf_transaction_commit(%s) failed - Retry: %s", 55971590c90Snw name, scf_strerror(scf_error())); 560c8e26105Sjp if (scf_pg_update(handles->config_pg) == -1) { 5618edda628Sbaban idmapdlog(LOG_ERR, 56271590c90Snw "scf_pg_update() failed: %s", 56371590c90Snw scf_strerror(scf_error())); 5648edda628Sbaban goto destruction; 5658edda628Sbaban } 5668edda628Sbaban scf_transaction_reset(tx); 5678edda628Sbaban } 5688edda628Sbaban } 5698edda628Sbaban 570e3c2d6aaSnw 571e3c2d6aaSnw if (ret == 1) 572e3c2d6aaSnw rc = 0; 573e3c2d6aaSnw else if (ret != -2) 5748edda628Sbaban idmapdlog(LOG_ERR, 57571590c90Snw "scf_transaction_commit(%s) failed: %s", 57671590c90Snw name, scf_strerror(scf_error())); 5778edda628Sbaban 5788edda628Sbaban destruction: 5798edda628Sbaban scf_value_destroy(value); 5808edda628Sbaban scf_entry_destroy(ent); 5818edda628Sbaban scf_transaction_destroy(tx); 5828edda628Sbaban scf_property_destroy(scf_prop); 5838edda628Sbaban return (rc); 5848edda628Sbaban } 5858edda628Sbaban 5864d61c878SJulian Pullen 5874d61c878SJulian Pullen 5884d61c878SJulian Pullen /* 5894d61c878SJulian Pullen * This function updates a boolean value. 5904d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 5914d61c878SJulian Pullen */ 592c8e26105Sjp static int 5937a8a68f5SJulian Pullen update_bool(boolean_t *value, boolean_t *new, char *name) 5944aa0a5e7Snw { 5954aa0a5e7Snw if (*value == *new) 5964aa0a5e7Snw return (0); 5974aa0a5e7Snw 5984aa0a5e7Snw idmapdlog(LOG_INFO, "change %s=%s", name, *new ? "true" : "false"); 5994aa0a5e7Snw *value = *new; 6004aa0a5e7Snw return (1); 6014aa0a5e7Snw } 6024aa0a5e7Snw 6034d61c878SJulian Pullen 6044d61c878SJulian Pullen /* 6054d61c878SJulian Pullen * This function updates a string value. 6064d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 6074d61c878SJulian Pullen */ 6084aa0a5e7Snw static int 6094aa0a5e7Snw update_string(char **value, char **new, char *name) 610c8e26105Sjp { 611c8e26105Sjp if (*new == NULL) 612349d5d8fSnw return (0); 613c8e26105Sjp 614c8e26105Sjp if (*value != NULL && strcmp(*new, *value) == 0) { 615c8e26105Sjp free(*new); 616c8e26105Sjp *new = NULL; 617349d5d8fSnw return (0); 618c8e26105Sjp } 619c8e26105Sjp 62071590c90Snw idmapdlog(LOG_INFO, "change %s=%s", name, CHECK_NULL(*new)); 621c8e26105Sjp if (*value != NULL) 622c8e26105Sjp free(*value); 623c8e26105Sjp *value = *new; 624c8e26105Sjp *new = NULL; 625349d5d8fSnw return (1); 626c8e26105Sjp } 627c8e26105Sjp 628e3f2c991SKeyur Desai static int 629e3f2c991SKeyur Desai update_enum(int *value, int *new, char *name, struct enum_lookup_map *map) 630e3f2c991SKeyur Desai { 631e3f2c991SKeyur Desai if (*value == *new) 632e3f2c991SKeyur Desai return (0); 633e3f2c991SKeyur Desai 634e3f2c991SKeyur Desai idmapdlog(LOG_INFO, "change %s=%s", name, enum_lookup(*new, map)); 635e3f2c991SKeyur Desai 636e3f2c991SKeyur Desai *value = *new; 637e3f2c991SKeyur Desai 638e3f2c991SKeyur Desai return (1); 639e3f2c991SKeyur Desai } 6404d61c878SJulian Pullen 6414d61c878SJulian Pullen /* 6424d61c878SJulian Pullen * This function updates a directory service structure. 6434d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 6444d61c878SJulian Pullen */ 645c8e26105Sjp static int 646479ac375Sdm update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new, char *name) 647c8e26105Sjp { 648c8e26105Sjp int i; 649c8e26105Sjp 6500dcc7149Snw if (*value == *new) 6510dcc7149Snw /* Nothing to do */ 652349d5d8fSnw return (0); 653c8e26105Sjp 6540dcc7149Snw if (*value != NULL && *new != NULL && 6550dcc7149Snw ad_disc_compare_ds(*value, *new) == 0) { 656c8e26105Sjp free(*new); 657c8e26105Sjp *new = NULL; 658349d5d8fSnw return (0); 659c8e26105Sjp } 660c8e26105Sjp 6614d61c878SJulian Pullen if (*value != NULL) 662c8e26105Sjp free(*value); 663c8e26105Sjp 664c8e26105Sjp *value = *new; 665c8e26105Sjp *new = NULL; 6660dcc7149Snw 6670dcc7149Snw if (*value == NULL) { 6680dcc7149Snw /* We're unsetting this DS property */ 66971590c90Snw idmapdlog(LOG_INFO, "change %s=<none>", name); 670349d5d8fSnw return (1); 6710dcc7149Snw } 6720dcc7149Snw 6730dcc7149Snw /* List all the new DSs */ 6740dcc7149Snw for (i = 0; (*value)[i].host[0] != '\0'; i++) 67571590c90Snw idmapdlog(LOG_INFO, "change %s=%s port=%d", name, 6760dcc7149Snw (*value)[i].host, (*value)[i].port); 677349d5d8fSnw return (1); 678c8e26105Sjp } 679c8e26105Sjp 6804d61c878SJulian Pullen /* 6814d61c878SJulian Pullen * This function updates a trusted domains structure. 6824d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 6834d61c878SJulian Pullen */ 6844d61c878SJulian Pullen static int 6854d61c878SJulian Pullen update_trusted_domains(ad_disc_trusteddomains_t **value, 6864d61c878SJulian Pullen ad_disc_trusteddomains_t **new, char *name) 6874d61c878SJulian Pullen { 6884d61c878SJulian Pullen int i; 6894d61c878SJulian Pullen 6904d61c878SJulian Pullen if (*value == *new) 6914d61c878SJulian Pullen /* Nothing to do */ 6924d61c878SJulian Pullen return (0); 6934d61c878SJulian Pullen 6944d61c878SJulian Pullen if (*value != NULL && *new != NULL && 6954d61c878SJulian Pullen ad_disc_compare_trusteddomains(*value, *new) == 0) { 6964d61c878SJulian Pullen free(*new); 6974d61c878SJulian Pullen *new = NULL; 6984d61c878SJulian Pullen return (0); 6994d61c878SJulian Pullen } 7004d61c878SJulian Pullen 7014d61c878SJulian Pullen if (*value != NULL) 7024d61c878SJulian Pullen free(*value); 7034d61c878SJulian Pullen 7044d61c878SJulian Pullen *value = *new; 7054d61c878SJulian Pullen *new = NULL; 7064d61c878SJulian Pullen 7074d61c878SJulian Pullen if (*value == NULL) { 7084d61c878SJulian Pullen /* We're unsetting this DS property */ 7094d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=<none>", name); 7104d61c878SJulian Pullen return (1); 7114d61c878SJulian Pullen } 7124d61c878SJulian Pullen 7134d61c878SJulian Pullen /* List all the new domains */ 7144d61c878SJulian Pullen for (i = 0; (*value)[i].domain[0] != '\0'; i++) 7154d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=%s direction=%s", name, 7164d61c878SJulian Pullen (*value)[i].domain, 7174d61c878SJulian Pullen (*value)[i].direction == 3 ? "bi-directional" : "inbound"); 7184d61c878SJulian Pullen return (1); 7194d61c878SJulian Pullen } 7204d61c878SJulian Pullen 7214d61c878SJulian Pullen 7224d61c878SJulian Pullen /* 7234d61c878SJulian Pullen * This function updates a domains in a forest structure. 7244d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 7254d61c878SJulian Pullen */ 7264d61c878SJulian Pullen static int 7274d61c878SJulian Pullen update_domains_in_forest(ad_disc_domainsinforest_t **value, 7284d61c878SJulian Pullen ad_disc_domainsinforest_t **new, char *name) 7294d61c878SJulian Pullen { 7304d61c878SJulian Pullen int i; 7314d61c878SJulian Pullen 7324d61c878SJulian Pullen if (*value == *new) 7334d61c878SJulian Pullen /* Nothing to do */ 7344d61c878SJulian Pullen return (0); 7354d61c878SJulian Pullen 7364d61c878SJulian Pullen if (*value != NULL && *new != NULL && 7374d61c878SJulian Pullen ad_disc_compare_domainsinforest(*value, *new) == 0) { 7384d61c878SJulian Pullen free(*new); 7394d61c878SJulian Pullen *new = NULL; 7404d61c878SJulian Pullen return (0); 7414d61c878SJulian Pullen } 7424d61c878SJulian Pullen 7434d61c878SJulian Pullen if (*value != NULL) 7444d61c878SJulian Pullen free(*value); 7454d61c878SJulian Pullen 7464d61c878SJulian Pullen *value = *new; 7474d61c878SJulian Pullen *new = NULL; 7484d61c878SJulian Pullen 7494d61c878SJulian Pullen if (*value == NULL) { 7504d61c878SJulian Pullen /* We're unsetting this DS property */ 7514d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=<none>", name); 7524d61c878SJulian Pullen return (1); 7534d61c878SJulian Pullen } 7544d61c878SJulian Pullen 7554d61c878SJulian Pullen /* List all the new domains */ 7564d61c878SJulian Pullen for (i = 0; (*value)[i].domain[0] != '\0'; i++) 7574d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=%s", name, 7584d61c878SJulian Pullen (*value)[i].domain); 7594d61c878SJulian Pullen return (1); 7604d61c878SJulian Pullen } 7614d61c878SJulian Pullen 7624d61c878SJulian Pullen 7634d61c878SJulian Pullen static void 7644d61c878SJulian Pullen free_trusted_forests(idmap_trustedforest_t **value, int *num_values) 7654d61c878SJulian Pullen { 7664d61c878SJulian Pullen int i; 7674d61c878SJulian Pullen 7684d61c878SJulian Pullen for (i = 0; i < *num_values; i++) { 7694d61c878SJulian Pullen free((*value)[i].forest_name); 7704d61c878SJulian Pullen free((*value)[i].global_catalog); 7714d61c878SJulian Pullen free((*value)[i].domains_in_forest); 7724d61c878SJulian Pullen } 7734d61c878SJulian Pullen free(*value); 7744d61c878SJulian Pullen *value = NULL; 7754d61c878SJulian Pullen *num_values = 0; 7764d61c878SJulian Pullen } 7774d61c878SJulian Pullen 7784d61c878SJulian Pullen 7794d61c878SJulian Pullen static int 7804d61c878SJulian Pullen compare_trusteddomainsinforest(ad_disc_domainsinforest_t *df1, 7814d61c878SJulian Pullen ad_disc_domainsinforest_t *df2) 7824d61c878SJulian Pullen { 7837a8a68f5SJulian Pullen int i, j; 7847a8a68f5SJulian Pullen int num_df1 = 0; 7857a8a68f5SJulian Pullen int num_df2 = 0; 7867a8a68f5SJulian Pullen boolean_t match; 7874d61c878SJulian Pullen 7884d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) 7894d61c878SJulian Pullen if (df1[i].trusted) 7904d61c878SJulian Pullen num_df1++; 7914d61c878SJulian Pullen 7924d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) 7934d61c878SJulian Pullen if (df2[j].trusted) 7944d61c878SJulian Pullen num_df2++; 7954d61c878SJulian Pullen 7964d61c878SJulian Pullen if (num_df1 != num_df2) 7974d61c878SJulian Pullen return (1); 7984d61c878SJulian Pullen 7994d61c878SJulian Pullen for (i = 0; df1[i].domain[0] != '\0'; i++) { 8004d61c878SJulian Pullen if (df1[i].trusted) { 8017a8a68f5SJulian Pullen match = B_FALSE; 8024d61c878SJulian Pullen for (j = 0; df2[j].domain[0] != '\0'; j++) { 8034d61c878SJulian Pullen if (df2[j].trusted && 8041fcced4cSJordan Brown domain_eq(df1[i].domain, df2[j].domain) && 8051fcced4cSJordan Brown strcmp(df1[i].sid, df2[j].sid) == 0) { 8067a8a68f5SJulian Pullen match = B_TRUE; 8074d61c878SJulian Pullen break; 8084d61c878SJulian Pullen } 8094d61c878SJulian Pullen } 8104d61c878SJulian Pullen if (!match) 8114d61c878SJulian Pullen return (1); 8124d61c878SJulian Pullen } 8134d61c878SJulian Pullen } 8144d61c878SJulian Pullen return (0); 8154d61c878SJulian Pullen } 8164d61c878SJulian Pullen 8174d61c878SJulian Pullen 8184d61c878SJulian Pullen 8194d61c878SJulian Pullen /* 8204d61c878SJulian Pullen * This function updates trusted forest structure. 8214d61c878SJulian Pullen * If nothing has changed it returns 0 else 1 8224d61c878SJulian Pullen */ 8234d61c878SJulian Pullen static int 8244d61c878SJulian Pullen update_trusted_forest(idmap_trustedforest_t **value, int *num_value, 8254d61c878SJulian Pullen idmap_trustedforest_t **new, int *num_new, char *name) 8264d61c878SJulian Pullen { 8274d61c878SJulian Pullen int i, j; 8287a8a68f5SJulian Pullen boolean_t match; 8294d61c878SJulian Pullen 8304d61c878SJulian Pullen if (*value == *new) 8314d61c878SJulian Pullen /* Nothing to do */ 8324d61c878SJulian Pullen return (0); 8334d61c878SJulian Pullen 8344d61c878SJulian Pullen if (*value != NULL && *new != NULL) { 8354d61c878SJulian Pullen if (*num_value != *num_new) 8364d61c878SJulian Pullen goto not_equal; 8374d61c878SJulian Pullen for (i = 0; i < *num_value; i++) { 8387a8a68f5SJulian Pullen match = B_FALSE; 8394d61c878SJulian Pullen for (j = 0; j < *num_new; j++) { 8404d61c878SJulian Pullen if (strcmp((*value)[i].forest_name, 8414d61c878SJulian Pullen (*new)[j].forest_name) == 0 && 8424d61c878SJulian Pullen ad_disc_compare_ds( 8434d61c878SJulian Pullen (*value)[i].global_catalog, 8441fcced4cSJordan Brown (*new)[j].global_catalog) == 0 && 8454d61c878SJulian Pullen compare_trusteddomainsinforest( 8464d61c878SJulian Pullen (*value)[i].domains_in_forest, 8471fcced4cSJordan Brown (*new)[j].domains_in_forest) == 0) { 8487a8a68f5SJulian Pullen match = B_TRUE; 8494d61c878SJulian Pullen break; 8504d61c878SJulian Pullen } 8514d61c878SJulian Pullen } 8524d61c878SJulian Pullen if (!match) 8534d61c878SJulian Pullen goto not_equal; 8544d61c878SJulian Pullen } 8554d61c878SJulian Pullen free_trusted_forests(new, num_new); 8564d61c878SJulian Pullen return (0); 8574d61c878SJulian Pullen } 8584d61c878SJulian Pullen not_equal: 8594d61c878SJulian Pullen if (*value != NULL) 8604d61c878SJulian Pullen free_trusted_forests(value, num_value); 8614d61c878SJulian Pullen *value = *new; 8624d61c878SJulian Pullen *num_value = *num_new; 8634d61c878SJulian Pullen *new = NULL; 8644d61c878SJulian Pullen *num_new = 0; 8654d61c878SJulian Pullen 8664d61c878SJulian Pullen if (*value == NULL) { 8674d61c878SJulian Pullen /* We're unsetting this DS property */ 8684d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=<none>", name); 8694d61c878SJulian Pullen return (1); 8704d61c878SJulian Pullen } 8714d61c878SJulian Pullen 8724d61c878SJulian Pullen /* List all the trusted forests */ 8734d61c878SJulian Pullen for (i = 0; i < *num_value; i++) { 8744d61c878SJulian Pullen for (j = 0; (*value)[i].domains_in_forest[j].domain[0] != '\0'; 8754d61c878SJulian Pullen j++) { 8764d61c878SJulian Pullen /* List trusted Domains in the forest. */ 8774d61c878SJulian Pullen if ((*value)[i].domains_in_forest[j].trusted) 8784d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=%s domain=%s", 8794d61c878SJulian Pullen name, (*value)[i].forest_name, 8804d61c878SJulian Pullen (*value)[i].domains_in_forest[j].domain); 8814d61c878SJulian Pullen } 8824d61c878SJulian Pullen /* List the hosts */ 8834d61c878SJulian Pullen for (j = 0; (*value)[i].global_catalog[j].host[0] != '\0'; j++) 8844d61c878SJulian Pullen idmapdlog(LOG_INFO, "change %s=%s host=%s port=%d", 8854d61c878SJulian Pullen name, (*value)[i].forest_name, 8864d61c878SJulian Pullen (*value)[i].global_catalog[j].host, 8874d61c878SJulian Pullen (*value)[i].global_catalog[j].port); 8884d61c878SJulian Pullen } 8894d61c878SJulian Pullen return (1); 8904d61c878SJulian Pullen } 8914d61c878SJulian Pullen 892e3f2c991SKeyur Desai const char * 893e3f2c991SKeyur Desai enum_lookup(int value, struct enum_lookup_map *map) 894e3f2c991SKeyur Desai { 895e3f2c991SKeyur Desai for (; map->string != NULL; map++) { 896e3f2c991SKeyur Desai if (value == map->value) { 897e3f2c991SKeyur Desai return (map->string); 898e3f2c991SKeyur Desai } 899e3f2c991SKeyur Desai } 900e3f2c991SKeyur Desai return ("(invalid)"); 901e3f2c991SKeyur Desai } 902c8e26105Sjp 903c8e26105Sjp /* 9040dcc7149Snw * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the 9050dcc7149Snw * interfaces. 906c8e26105Sjp * 9070dcc7149Snw * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON. 908c8e26105Sjp */ 909c8e26105Sjp static 910*c5866007SKeyur Desai boolean_t 9110dcc7149Snw pfroute_event_is_interesting(int rt_sock) 912c8e26105Sjp { 9130dcc7149Snw int nbytes; 9140dcc7149Snw int64_t msg[2048 / 8]; 9150dcc7149Snw struct rt_msghdr *rtm; 916*c5866007SKeyur Desai boolean_t is_interesting = B_FALSE; 917c8e26105Sjp 9180dcc7149Snw for (;;) { 9190dcc7149Snw if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0) 9200dcc7149Snw break; 9210dcc7149Snw rtm = (struct rt_msghdr *)msg; 9220dcc7149Snw if (rtm->rtm_version != RTM_VERSION) 9230dcc7149Snw continue; 9240dcc7149Snw if (nbytes < rtm->rtm_msglen) 9250dcc7149Snw continue; 9260dcc7149Snw switch (rtm->rtm_type) { 9270dcc7149Snw case RTM_NEWADDR: 9280dcc7149Snw case RTM_DELADDR: 9290dcc7149Snw case RTM_IFINFO: 930*c5866007SKeyur Desai is_interesting = B_TRUE; 9310dcc7149Snw break; 9320dcc7149Snw default: 9330dcc7149Snw break; 9340dcc7149Snw } 935c8e26105Sjp } 9360dcc7149Snw return (is_interesting); 9370dcc7149Snw } 9380dcc7149Snw 9390dcc7149Snw /* 940*c5866007SKeyur Desai * Wait for an event, and report what kind of event occurred. 9410dcc7149Snw * 942*c5866007SKeyur Desai * Note that there are cases where we are awoken but don't care about 943*c5866007SKeyur Desai * the lower-level event. We can't just loop here because we can't 944*c5866007SKeyur Desai * readily calculate how long to sleep the next time. We return 945*c5866007SKeyur Desai * EVENT_NOTHING and let the caller loop. 9460dcc7149Snw */ 9470dcc7149Snw static 948*c5866007SKeyur Desai enum event_type 949*c5866007SKeyur Desai wait_for_event(struct timespec *timeoutp) 9500dcc7149Snw { 9510dcc7149Snw port_event_t pe; 952c8e26105Sjp 9530dcc7149Snw memset(&pe, 0, sizeof (pe)); 954349d5d8fSnw if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) { 955c8e26105Sjp switch (errno) { 956c8e26105Sjp case EINTR: 957*c5866007SKeyur Desai return (EVENT_NOTHING); 958c8e26105Sjp case ETIME: 959c8e26105Sjp /* Timeout */ 960*c5866007SKeyur Desai return (EVENT_TIMEOUT); 961c8e26105Sjp default: 9620dcc7149Snw /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */ 9630dcc7149Snw idmapdlog(LOG_ERR, "Event port failed: %s", 9640dcc7149Snw strerror(errno)); 9650dcc7149Snw exit(1); 9660dcc7149Snw /* NOTREACHED */ 967c8e26105Sjp } 968c8e26105Sjp } 969c8e26105Sjp 9700dcc7149Snw 971*c5866007SKeyur Desai switch (pe.portev_source) { 972*c5866007SKeyur Desai case 0: 9730dcc7149Snw /* 974*c5866007SKeyur Desai * This isn't documented, but seems to be what you get if 975*c5866007SKeyur Desai * the timeout is zero seconds and there are no events 976*c5866007SKeyur Desai * pending. 9770dcc7149Snw */ 978*c5866007SKeyur Desai return (EVENT_TIMEOUT); 979c8e26105Sjp 980*c5866007SKeyur Desai case PORT_SOURCE_USER: 981*c5866007SKeyur Desai if (pe.portev_events == POKE_AUTO_DISCOVERY) 982*c5866007SKeyur Desai return (EVENT_DEGRADE); 983*c5866007SKeyur Desai if (pe.portev_events == RECONFIGURE) 984*c5866007SKeyur Desai return (EVENT_REFRESH); 985*c5866007SKeyur Desai break; 986e3c2d6aaSnw 987*c5866007SKeyur Desai case PORT_SOURCE_FD: 988*c5866007SKeyur Desai if (pe.portev_object == rt_sock) { 989*c5866007SKeyur Desai /* 990*c5866007SKeyur Desai * PF_ROUTE socket read event: 991*c5866007SKeyur Desai * re-associate fd 992*c5866007SKeyur Desai * handle event 993*c5866007SKeyur Desai */ 994*c5866007SKeyur Desai if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 995*c5866007SKeyur Desai rt_sock, POLLIN, NULL) != 0) { 996*c5866007SKeyur Desai idmapdlog(LOG_ERR, "Failed to re-associate the " 997*c5866007SKeyur Desai "routing socket with the event port: %s", 998*c5866007SKeyur Desai strerror(errno)); 999*c5866007SKeyur Desai abort(); 1000*c5866007SKeyur Desai } 1001*c5866007SKeyur Desai /* 1002*c5866007SKeyur Desai * The network configuration may still be in flux. 1003*c5866007SKeyur Desai * No matter, the resolver will re-transmit and 1004*c5866007SKeyur Desai * timeout if need be. 1005*c5866007SKeyur Desai */ 1006*c5866007SKeyur Desai if (pfroute_event_is_interesting(rt_sock)) { 1007*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, 1008*c5866007SKeyur Desai "Interesting routing event"); 1009*c5866007SKeyur Desai return (EVENT_ROUTING); 1010*c5866007SKeyur Desai } else { 1011*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, 1012*c5866007SKeyur Desai "Boring routing event"); 1013*c5866007SKeyur Desai return (EVENT_NOTHING); 1014*c5866007SKeyur Desai } 1015349d5d8fSnw } 1016*c5866007SKeyur Desai /* Event on an FD other than the routing FD? Ignore it. */ 1017*c5866007SKeyur Desai break; 1018c8e26105Sjp } 1019c8e26105Sjp 1020*c5866007SKeyur Desai return (EVENT_NOTHING); 1021c8e26105Sjp } 1022c8e26105Sjp 1023c8e26105Sjp void * 1024c8e26105Sjp idmap_cfg_update_thread(void *arg) 1025c8e26105Sjp { 1026c8e26105Sjp 1027*c5866007SKeyur Desai const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx; 10280dcc7149Snw 1029*c5866007SKeyur Desai for (;;) { 1030*c5866007SKeyur Desai struct timespec timeout; 1031*c5866007SKeyur Desai struct timespec *timeoutp; 1032*c5866007SKeyur Desai int rc; 1033*c5866007SKeyur Desai int ttl; 10340dcc7149Snw 10350dcc7149Snw (void) ad_disc_SubnetChanged(ad_ctx); 1036c8e26105Sjp 1037*c5866007SKeyur Desai rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER); 1038*c5866007SKeyur Desai if (rc < -1) { 10397a8a68f5SJulian Pullen idmapdlog(LOG_ERR, "Fatal errors while reading " 1040349d5d8fSnw "SMF properties"); 1041349d5d8fSnw exit(1); 1042*c5866007SKeyur Desai } else if (rc == -1) { 1043*c5866007SKeyur Desai idmapdlog(LOG_WARNING, 1044*c5866007SKeyur Desai "Errors re-loading configuration may cause AD " 1045*c5866007SKeyur Desai "lookups to fail"); 1046349d5d8fSnw } 1047c8e26105Sjp 1048*c5866007SKeyur Desai /* 1049*c5866007SKeyur Desai * Wait for an interesting event. Note that we might get 1050*c5866007SKeyur Desai * boring events between interesting events. If so, we loop. 1051*c5866007SKeyur Desai */ 1052*c5866007SKeyur Desai for (;;) { 1053*c5866007SKeyur Desai ttl = ad_disc_get_TTL(ad_ctx); 1054*c5866007SKeyur Desai 1055*c5866007SKeyur Desai if (ttl < 0) { 1056*c5866007SKeyur Desai timeoutp = NULL; 1057*c5866007SKeyur Desai } else { 1058*c5866007SKeyur Desai timeoutp = &timeout; 1059*c5866007SKeyur Desai timeout.tv_sec = ttl; 1060*c5866007SKeyur Desai timeout.tv_nsec = 0; 1061*c5866007SKeyur Desai } 1062*c5866007SKeyur Desai 1063*c5866007SKeyur Desai switch (wait_for_event(timeoutp)) { 1064*c5866007SKeyur Desai case EVENT_NOTHING: 1065*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, "Boring event."); 1066*c5866007SKeyur Desai continue; 1067*c5866007SKeyur Desai case EVENT_REFRESH: 1068*c5866007SKeyur Desai idmapdlog(LOG_INFO, "SMF refresh"); 1069*c5866007SKeyur Desai /* 1070*c5866007SKeyur Desai * Blow away the ccache, we might have 1071*c5866007SKeyur Desai * re-joined the domain or joined a new one 1072*c5866007SKeyur Desai */ 1073*c5866007SKeyur Desai (void) unlink(IDMAP_CACHEDIR "/ccache"); 1074*c5866007SKeyur Desai break; 1075*c5866007SKeyur Desai case EVENT_DEGRADE: 1076*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, 1077*c5866007SKeyur Desai "Service degraded"); 1078*c5866007SKeyur Desai break; 1079*c5866007SKeyur Desai case EVENT_TIMEOUT: 1080*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, "TTL expired"); 1081*c5866007SKeyur Desai break; 1082*c5866007SKeyur Desai case EVENT_ROUTING: 1083*c5866007SKeyur Desai /* Already logged to DEBUG */ 1084*c5866007SKeyur Desai break; 1085*c5866007SKeyur Desai } 1086*c5866007SKeyur Desai /* An interesting event! */ 1087*c5866007SKeyur Desai break; 1088*c5866007SKeyur Desai } 1089c8e26105Sjp } 1090*c5866007SKeyur Desai /* 1091*c5866007SKeyur Desai * Lint isn't happy with the concept of a function declared to 1092*c5866007SKeyur Desai * return something, that doesn't return. Of course, merely adding 1093*c5866007SKeyur Desai * the return isn't enough, because it's never reached... 1094*c5866007SKeyur Desai */ 1095c8e26105Sjp /*NOTREACHED*/ 1096c8e26105Sjp return (NULL); 1097c8e26105Sjp } 1098c8e26105Sjp 1099c8e26105Sjp int 11000dcc7149Snw idmap_cfg_start_updates(void) 1101c8e26105Sjp { 11020dcc7149Snw if ((idmapd_ev_port = port_create()) < 0) { 110371590c90Snw idmapdlog(LOG_ERR, "Failed to create event port: %s", 110471590c90Snw strerror(errno)); 1105c8e26105Sjp return (-1); 11060dcc7149Snw } 11070dcc7149Snw 11080dcc7149Snw if ((rt_sock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 110971590c90Snw idmapdlog(LOG_ERR, "Failed to open routing socket: %s", 111071590c90Snw strerror(errno)); 11110dcc7149Snw (void) close(idmapd_ev_port); 11120dcc7149Snw return (-1); 11130dcc7149Snw } 11140dcc7149Snw 11150dcc7149Snw if (fcntl(rt_sock, F_SETFL, O_NDELAY|O_NONBLOCK) < 0) { 111671590c90Snw idmapdlog(LOG_ERR, "Failed to set routing socket flags: %s", 111771590c90Snw strerror(errno)); 11180dcc7149Snw (void) close(rt_sock); 11190dcc7149Snw (void) close(idmapd_ev_port); 11200dcc7149Snw return (-1); 11210dcc7149Snw } 11220dcc7149Snw 11230dcc7149Snw if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, 11240dcc7149Snw rt_sock, POLLIN, NULL) != 0) { 112571590c90Snw idmapdlog(LOG_ERR, "Failed to associate the routing " 112671590c90Snw "socket with the event port: %s", strerror(errno)); 11270dcc7149Snw (void) close(rt_sock); 11280dcc7149Snw (void) close(idmapd_ev_port); 11290dcc7149Snw return (-1); 11300dcc7149Snw } 11310dcc7149Snw 11320dcc7149Snw if ((errno = pthread_create(&update_thread_handle, NULL, 11330dcc7149Snw idmap_cfg_update_thread, NULL)) != 0) { 113471590c90Snw idmapdlog(LOG_ERR, "Failed to start update thread: %s", 113571590c90Snw strerror(errno)); 11360dcc7149Snw (void) port_dissociate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock); 11370dcc7149Snw (void) close(rt_sock); 11380dcc7149Snw (void) close(idmapd_ev_port); 11390dcc7149Snw return (-1); 11400dcc7149Snw } 11410dcc7149Snw 11420dcc7149Snw return (0); 1143c8e26105Sjp } 1144c8e26105Sjp 1145479ac375Sdm /* 1146479ac375Sdm * Reject attribute names with invalid characters. 1147479ac375Sdm */ 1148479ac375Sdm static 1149479ac375Sdm int 1150479ac375Sdm valid_ldap_attr(const char *attr) { 1151479ac375Sdm for (; *attr; attr++) { 1152479ac375Sdm if (!isalnum(*attr) && *attr != '-' && 1153479ac375Sdm *attr != '_' && *attr != '.' && *attr != ';') 1154479ac375Sdm return (0); 1155479ac375Sdm } 1156479ac375Sdm return (1); 1157479ac375Sdm } 1158479ac375Sdm 1159e3f2c991SKeyur Desai static 1160e3f2c991SKeyur Desai int 1161e3f2c991SKeyur Desai check_smf_debug_mode(idmap_cfg_handles_t *handles) 1162e3f2c991SKeyur Desai { 1163e3f2c991SKeyur Desai boolean_t new_debug_mode; 1164e3f2c991SKeyur Desai int rc; 1165e3f2c991SKeyur Desai 1166e3f2c991SKeyur Desai rc = prop_exists(handles, "debug", &new_debug_mode); 1167e3f2c991SKeyur Desai if (rc != 0) 1168e3f2c991SKeyur Desai return (rc); 1169e3f2c991SKeyur Desai 1170e3f2c991SKeyur Desai if (_idmapdstate.debug_mode != new_debug_mode) { 1171e3f2c991SKeyur Desai if (!_idmapdstate.debug_mode) { 1172e3f2c991SKeyur Desai _idmapdstate.debug_mode = new_debug_mode; 1173e3f2c991SKeyur Desai idmap_log_stderr(LOG_DEBUG); 1174e3f2c991SKeyur Desai idmapdlog(LOG_DEBUG, "debug mode enabled"); 1175e3f2c991SKeyur Desai } else { 1176e3f2c991SKeyur Desai idmapdlog(LOG_DEBUG, "debug mode disabled"); 1177e3f2c991SKeyur Desai idmap_log_stderr(-1); 1178e3f2c991SKeyur Desai _idmapdstate.debug_mode = new_debug_mode; 1179e3f2c991SKeyur Desai } 1180e3f2c991SKeyur Desai } 1181e3f2c991SKeyur Desai 1182e3f2c991SKeyur Desai return (0); 1183e3f2c991SKeyur Desai } 1184e3f2c991SKeyur Desai 1185349d5d8fSnw /* 1186349d5d8fSnw * This is the half of idmap_cfg_load() that loads property values from 1187349d5d8fSnw * SMF (using the config/ property group of the idmap FMRI). 1188349d5d8fSnw * 1189349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1190479ac375Sdm * -3 -> hard smf config failures 1191349d5d8fSnw * reading from SMF. 1192349d5d8fSnw */ 1193349d5d8fSnw static 1194c5c4113dSnw int 1195349d5d8fSnw idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, 1196e3f2c991SKeyur Desai int * const errors) 1197c5c4113dSnw { 1198e3c2d6aaSnw int rc; 1199e3f2c991SKeyur Desai char *s; 1200e3f2c991SKeyur Desai 1201e3f2c991SKeyur Desai *errors = 0; 1202c8e26105Sjp 1203c8e26105Sjp if (scf_pg_update(handles->config_pg) < 0) { 120471590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 120571590c90Snw scf_strerror(scf_error())); 1206349d5d8fSnw return (-2); 1207c5c4113dSnw } 1208c5c4113dSnw 1209c8e26105Sjp if (scf_pg_update(handles->general_pg) < 0) { 121071590c90Snw idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", 121171590c90Snw scf_strerror(scf_error())); 1212349d5d8fSnw return (-2); 1213c5c4113dSnw } 1214c5c4113dSnw 1215e3f2c991SKeyur Desai rc = check_smf_debug_mode(handles); 1216479ac375Sdm if (rc != 0) 1217e3f2c991SKeyur Desai (*errors)++; 121871590c90Snw 12194aa0a5e7Snw rc = get_val_int(handles, "unresolvable_sid_mapping", 12204aa0a5e7Snw &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN); 12214aa0a5e7Snw if (rc != 0) 1222e3f2c991SKeyur Desai (*errors)++; 1223e3f2c991SKeyur Desai 1224e3f2c991SKeyur Desai rc = get_val_astring(handles, "directory_based_mapping", &s); 1225e3f2c991SKeyur Desai if (rc != 0) 1226e3f2c991SKeyur Desai (*errors)++; 1227e3f2c991SKeyur Desai else if (s == NULL || strcasecmp(s, "none") == 0) 1228e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1229e3f2c991SKeyur Desai else if (strcasecmp(s, "name") == 0) 1230e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME; 1231e3f2c991SKeyur Desai else if (strcasecmp(s, "idmu") == 0) 1232e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU; 1233e3f2c991SKeyur Desai else { 1234e3f2c991SKeyur Desai pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; 1235e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 1236e3f2c991SKeyur Desai "config/directory_based_mapping: invalid value \"%s\" ignored", 1237e3f2c991SKeyur Desai s); 1238e3f2c991SKeyur Desai (*errors)++; 1239e3f2c991SKeyur Desai } 1240e3f2c991SKeyur Desai free(s); 12414aa0a5e7Snw 1242c8e26105Sjp rc = get_val_int(handles, "list_size_limit", 1243c8e26105Sjp &pgcfg->list_size_limit, SCF_TYPE_COUNT); 12444aa0a5e7Snw if (rc != 0) 1245e3f2c991SKeyur Desai (*errors)++; 1246c5c4113dSnw 1247c8e26105Sjp rc = get_val_astring(handles, "domain_name", 1248c8e26105Sjp &pgcfg->domain_name); 1249e3c2d6aaSnw if (rc != 0) 1250e3f2c991SKeyur Desai (*errors)++; 12514d61c878SJulian Pullen else { 1252349d5d8fSnw (void) ad_disc_set_DomainName(handles->ad_ctx, 1253349d5d8fSnw pgcfg->domain_name); 12547a8a68f5SJulian Pullen pgcfg->domain_name_auto_disc = B_FALSE; 12554d61c878SJulian Pullen } 1256c8e26105Sjp 1257c8e26105Sjp rc = get_val_astring(handles, "default_domain", 1258c8e26105Sjp &pgcfg->default_domain); 1259c8e26105Sjp if (rc != 0) { 1260e3c2d6aaSnw /* 1261e3c2d6aaSnw * SCF failures fetching config/default_domain we treat 1262e3c2d6aaSnw * as fatal as they may leave ID mapping rules that 1263e3c2d6aaSnw * match unqualified winnames flapping in the wind. 1264e3c2d6aaSnw */ 1265349d5d8fSnw return (-2); 1266c8e26105Sjp } 1267c8e26105Sjp 1268e3f2c991SKeyur Desai if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) { 1269e3f2c991SKeyur Desai pgcfg->default_domain = strdup(pgcfg->domain_name); 1270c5c4113dSnw } 1271c5c4113dSnw 1272c8e26105Sjp rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); 1273e3c2d6aaSnw if (rc != 0) 1274e3f2c991SKeyur Desai (*errors)++; 1275c8e26105Sjp if (pgcfg->machine_sid == NULL) { 12768edda628Sbaban /* If machine_sid not configured, generate one */ 1277349d5d8fSnw if (generate_machine_sid(&pgcfg->machine_sid) < 0) 1278349d5d8fSnw return (-2); 1279c8e26105Sjp rc = set_val_astring(handles, "machine_sid", 1280c8e26105Sjp pgcfg->machine_sid); 1281e3c2d6aaSnw if (rc != 0) 1282e3f2c991SKeyur Desai (*errors)++; 12838edda628Sbaban } 1284c5c4113dSnw 1285c8e26105Sjp rc = get_val_ds(handles, "domain_controller", 389, 1286c8e26105Sjp &pgcfg->domain_controller); 1287e3c2d6aaSnw if (rc != 0) 1288e3f2c991SKeyur Desai (*errors)++; 12894d61c878SJulian Pullen else { 1290349d5d8fSnw (void) ad_disc_set_DomainController(handles->ad_ctx, 1291e3c2d6aaSnw pgcfg->domain_controller); 12927a8a68f5SJulian Pullen pgcfg->domain_controller_auto_disc = B_FALSE; 12934d61c878SJulian Pullen } 1294c5c4113dSnw 1295c8e26105Sjp rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); 1296e3c2d6aaSnw if (rc != 0) 1297e3f2c991SKeyur Desai (*errors)++; 12984d61c878SJulian Pullen else { 1299349d5d8fSnw (void) ad_disc_set_ForestName(handles->ad_ctx, 1300349d5d8fSnw pgcfg->forest_name); 13017a8a68f5SJulian Pullen pgcfg->forest_name_auto_disc = B_FALSE; 13024d61c878SJulian Pullen } 1303c8e26105Sjp 1304c8e26105Sjp rc = get_val_astring(handles, "site_name", &pgcfg->site_name); 1305e3c2d6aaSnw if (rc != 0) 1306e3f2c991SKeyur Desai (*errors)++; 1307e3c2d6aaSnw else 1308349d5d8fSnw (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name); 1309c8e26105Sjp 1310c8e26105Sjp rc = get_val_ds(handles, "global_catalog", 3268, 1311c8e26105Sjp &pgcfg->global_catalog); 1312e3c2d6aaSnw if (rc != 0) 1313e3f2c991SKeyur Desai (*errors)++; 13144d61c878SJulian Pullen else { 1315349d5d8fSnw (void) ad_disc_set_GlobalCatalog(handles->ad_ctx, 1316349d5d8fSnw pgcfg->global_catalog); 13177a8a68f5SJulian Pullen pgcfg->global_catalog_auto_disc = B_FALSE; 13184d61c878SJulian Pullen } 1319c8e26105Sjp 1320e3f2c991SKeyur Desai /* Unless we're doing directory-based name mapping, we're done. */ 1321e3f2c991SKeyur Desai if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME) 1322e3f2c991SKeyur Desai return (0); 1323e8c27ec8Sbaban 1324349d5d8fSnw rc = get_val_astring(handles, "ad_unixuser_attr", 1325349d5d8fSnw &pgcfg->ad_unixuser_attr); 1326349d5d8fSnw if (rc != 0) 1327349d5d8fSnw return (-2); 1328479ac375Sdm if (pgcfg->ad_unixuser_attr != NULL && 1329479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixuser_attr)) { 1330479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixuser_attr=%s is not a " 1331479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixuser_attr); 1332479ac375Sdm return (-3); 1333479ac375Sdm } 1334e8c27ec8Sbaban 1335349d5d8fSnw rc = get_val_astring(handles, "ad_unixgroup_attr", 1336349d5d8fSnw &pgcfg->ad_unixgroup_attr); 1337349d5d8fSnw if (rc != 0) 1338349d5d8fSnw return (-2); 1339479ac375Sdm if (pgcfg->ad_unixgroup_attr != NULL && 1340479ac375Sdm !valid_ldap_attr(pgcfg->ad_unixgroup_attr)) { 1341479ac375Sdm idmapdlog(LOG_ERR, "config/ad_unixgroup_attr=%s is not a " 1342479ac375Sdm "valid LDAP attribute name", pgcfg->ad_unixgroup_attr); 1343479ac375Sdm return (-3); 1344479ac375Sdm } 1345e8c27ec8Sbaban 1346349d5d8fSnw rc = get_val_astring(handles, "nldap_winname_attr", 1347349d5d8fSnw &pgcfg->nldap_winname_attr); 1348349d5d8fSnw if (rc != 0) 1349349d5d8fSnw return (-2); 1350479ac375Sdm if (pgcfg->nldap_winname_attr != NULL && 1351479ac375Sdm !valid_ldap_attr(pgcfg->nldap_winname_attr)) { 1352479ac375Sdm idmapdlog(LOG_ERR, "config/nldap_winname_attr=%s is not a " 1353479ac375Sdm "valid LDAP attribute name", pgcfg->nldap_winname_attr); 1354349d5d8fSnw return (-3); 1355e8c27ec8Sbaban } 1356349d5d8fSnw if (pgcfg->ad_unixuser_attr == NULL && 1357479ac375Sdm pgcfg->ad_unixgroup_attr == NULL && 1358479ac375Sdm pgcfg->nldap_winname_attr == NULL) { 1359349d5d8fSnw idmapdlog(LOG_ERR, 1360e3f2c991SKeyur Desai "If config/directory_based_mapping property is set to " 1361e3f2c991SKeyur Desai "\"name\" then at least one of the following name mapping " 1362349d5d8fSnw "attributes must be specified. (config/ad_unixuser_attr OR " 1363479ac375Sdm "config/ad_unixgroup_attr OR config/nldap_winname_attr)"); 1364349d5d8fSnw return (-3); 1365349d5d8fSnw } 1366c8e26105Sjp 1367349d5d8fSnw return (rc); 1368e3c2d6aaSnw 1369349d5d8fSnw } 1370349d5d8fSnw 13714d61c878SJulian Pullen 1372349d5d8fSnw /* 1373349d5d8fSnw * This is the half of idmap_cfg_load() that auto-discovers values of 1374349d5d8fSnw * discoverable properties that weren't already set via SMF properties. 1375349d5d8fSnw * 1376349d5d8fSnw * idmap_cfg_discover() is called *after* idmap_cfg_load_smf(), so it 1377349d5d8fSnw * needs to be careful not to overwrite any properties set in SMF. 1378349d5d8fSnw */ 1379349d5d8fSnw static 1380349d5d8fSnw void 1381349d5d8fSnw idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) 1382349d5d8fSnw { 1383349d5d8fSnw ad_disc_t ad_ctx = handles->ad_ctx; 13844d61c878SJulian Pullen ad_disc_t trusted_ctx; 13854d61c878SJulian Pullen int i, j, k, l; 13864d61c878SJulian Pullen char *forestname; 13874d61c878SJulian Pullen int num_trusteddomains; 13887a8a68f5SJulian Pullen boolean_t new_forest; 13894d61c878SJulian Pullen char *trusteddomain; 13904d61c878SJulian Pullen idmap_ad_disc_ds_t *globalcatalog; 13914d61c878SJulian Pullen idmap_trustedforest_t *trustedforests; 13924d61c878SJulian Pullen ad_disc_domainsinforest_t *domainsinforest; 1393349d5d8fSnw 1394*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, "Running discovery."); 1395*c5866007SKeyur Desai 1396349d5d8fSnw ad_disc_refresh(ad_ctx); 1397349d5d8fSnw 1398349d5d8fSnw if (pgcfg->default_domain == NULL) 13994d61c878SJulian Pullen pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx, 14004d61c878SJulian Pullen NULL); 1401c8e26105Sjp 1402349d5d8fSnw if (pgcfg->domain_name == NULL) 14034d61c878SJulian Pullen pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx, 14044d61c878SJulian Pullen &pgcfg->domain_name_auto_disc); 1405c8e26105Sjp 1406349d5d8fSnw if (pgcfg->domain_controller == NULL) 1407c8e26105Sjp pgcfg->domain_controller = 14084d61c878SJulian Pullen ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE, 14094d61c878SJulian Pullen &pgcfg->domain_controller_auto_disc); 1410c8e26105Sjp 1411349d5d8fSnw if (pgcfg->forest_name == NULL) 14124d61c878SJulian Pullen pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx, 14134d61c878SJulian Pullen &pgcfg->forest_name_auto_disc); 1414c8e26105Sjp 1415349d5d8fSnw if (pgcfg->site_name == NULL) 14164d61c878SJulian Pullen pgcfg->site_name = ad_disc_get_SiteName(ad_ctx, 14174d61c878SJulian Pullen &pgcfg->site_name_auto_disc); 1418c8e26105Sjp 1419349d5d8fSnw if (pgcfg->global_catalog == NULL) 1420c8e26105Sjp pgcfg->global_catalog = 14214d61c878SJulian Pullen ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE, 14224d61c878SJulian Pullen &pgcfg->global_catalog_auto_disc); 14234d61c878SJulian Pullen 14244d61c878SJulian Pullen pgcfg->domains_in_forest = 14254d61c878SJulian Pullen ad_disc_get_DomainsInForest(ad_ctx, NULL); 14264d61c878SJulian Pullen 14274d61c878SJulian Pullen pgcfg->trusted_domains = 14284d61c878SJulian Pullen ad_disc_get_TrustedDomains(ad_ctx, NULL); 14294d61c878SJulian Pullen 14304d61c878SJulian Pullen if (pgcfg->forest_name != NULL && pgcfg->trusted_domains != NULL && 14314d61c878SJulian Pullen pgcfg->trusted_domains[0].domain[0] != '\0') { 14324d61c878SJulian Pullen /* 14334d61c878SJulian Pullen * We have trusted domains. We need to go through every 14344d61c878SJulian Pullen * one and find its forest. If it is a new forest we then need 14354d61c878SJulian Pullen * to find its Global Catalog and the domains in the forest 14364d61c878SJulian Pullen */ 14374d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) 14384d61c878SJulian Pullen continue; 14394d61c878SJulian Pullen num_trusteddomains = i; 14404d61c878SJulian Pullen 14414d61c878SJulian Pullen trustedforests = calloc(num_trusteddomains, 14424d61c878SJulian Pullen sizeof (idmap_trustedforest_t)); 14434d61c878SJulian Pullen j = 0; 14444d61c878SJulian Pullen for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++) { 14454d61c878SJulian Pullen trusteddomain = pgcfg->trusted_domains[i].domain; 14464d61c878SJulian Pullen trusted_ctx = ad_disc_init(); 14474d61c878SJulian Pullen ad_disc_set_DomainName(trusted_ctx, 14484d61c878SJulian Pullen trusteddomain); 14494d61c878SJulian Pullen forestname = 14504d61c878SJulian Pullen ad_disc_get_ForestName(trusted_ctx, NULL); 14514d61c878SJulian Pullen if (forestname == NULL) { 14524d61c878SJulian Pullen idmapdlog(LOG_DEBUG, "unable to discover " 14534d61c878SJulian Pullen "Forest Name for the trusted domain %s", 14544d61c878SJulian Pullen trusteddomain); 14554d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 14564d61c878SJulian Pullen continue; 14574d61c878SJulian Pullen } 14584d61c878SJulian Pullen 14594d61c878SJulian Pullen if (strcasecmp(forestname, pgcfg->forest_name) == 0) { 14604d61c878SJulian Pullen /* 14614d61c878SJulian Pullen * Ignore the domain as it is part of 14624d61c878SJulian Pullen * the primary forest 14634d61c878SJulian Pullen */ 14644d61c878SJulian Pullen free(forestname); 14654d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 14664d61c878SJulian Pullen continue; 14674d61c878SJulian Pullen } 14684d61c878SJulian Pullen 14694d61c878SJulian Pullen /* Is this a new forest? */ 14707a8a68f5SJulian Pullen new_forest = B_TRUE; 14714d61c878SJulian Pullen for (k = 0; k < j; k++) { 14724d61c878SJulian Pullen if (strcasecmp(forestname, 14734d61c878SJulian Pullen trustedforests[k].forest_name) == 0) { 14747a8a68f5SJulian Pullen new_forest = B_FALSE; 14754d61c878SJulian Pullen domainsinforest = 14764d61c878SJulian Pullen trustedforests[k].domains_in_forest; 14774d61c878SJulian Pullen break; 14784d61c878SJulian Pullen } 14794d61c878SJulian Pullen } 14804d61c878SJulian Pullen if (!new_forest) { 14814d61c878SJulian Pullen /* Mark the domain as trusted */ 14824d61c878SJulian Pullen for (l = 0; 14834d61c878SJulian Pullen domainsinforest[l].domain[0] != '\0'; l++) { 14841fcced4cSJordan Brown if (domain_eq(trusteddomain, 14851fcced4cSJordan Brown domainsinforest[l].domain)) { 14864d61c878SJulian Pullen domainsinforest[l].trusted = 14874d61c878SJulian Pullen TRUE; 14884d61c878SJulian Pullen break; 14894d61c878SJulian Pullen } 14904d61c878SJulian Pullen } 14914d61c878SJulian Pullen free(forestname); 14924d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 14934d61c878SJulian Pullen continue; 14944d61c878SJulian Pullen } 14954d61c878SJulian Pullen 14964d61c878SJulian Pullen /* 14974d61c878SJulian Pullen * Get the Global Catalog and the domains in 14984d61c878SJulian Pullen * this new forest. 14994d61c878SJulian Pullen */ 15004d61c878SJulian Pullen globalcatalog = 15014d61c878SJulian Pullen ad_disc_get_GlobalCatalog(trusted_ctx, 15024d61c878SJulian Pullen AD_DISC_PREFER_SITE, NULL); 15034d61c878SJulian Pullen if (globalcatalog == NULL) { 15044d61c878SJulian Pullen idmapdlog(LOG_DEBUG, 15054d61c878SJulian Pullen "unable to discover Global " 15064d61c878SJulian Pullen "Catalog for the trusted domain %s", 15074d61c878SJulian Pullen trusteddomain); 15084d61c878SJulian Pullen free(forestname); 15094d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 15104d61c878SJulian Pullen continue; 15114d61c878SJulian Pullen } 15124d61c878SJulian Pullen domainsinforest = 15134d61c878SJulian Pullen ad_disc_get_DomainsInForest(trusted_ctx, 15144d61c878SJulian Pullen NULL); 15154d61c878SJulian Pullen if (domainsinforest == NULL) { 15164d61c878SJulian Pullen idmapdlog(LOG_DEBUG, 15174d61c878SJulian Pullen "unable to discover Domains in the Forest " 15184d61c878SJulian Pullen "for the trusted domain %s", 15194d61c878SJulian Pullen trusteddomain); 15204d61c878SJulian Pullen free(globalcatalog); 15214d61c878SJulian Pullen free(forestname); 15224d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 15234d61c878SJulian Pullen continue; 15244d61c878SJulian Pullen } 15254d61c878SJulian Pullen 15264d61c878SJulian Pullen trustedforests[j].forest_name = forestname; 15274d61c878SJulian Pullen trustedforests[j].global_catalog = globalcatalog; 15284d61c878SJulian Pullen trustedforests[j].domains_in_forest = domainsinforest; 15294d61c878SJulian Pullen j++; 15304d61c878SJulian Pullen /* Mark the domain as trusted */ 15314d61c878SJulian Pullen for (l = 0; domainsinforest[l].domain[0] != '\0'; 15324d61c878SJulian Pullen l++) { 15331fcced4cSJordan Brown if (domain_eq(trusteddomain, 15341fcced4cSJordan Brown domainsinforest[l].domain)) { 15354d61c878SJulian Pullen domainsinforest[l].trusted = TRUE; 15364d61c878SJulian Pullen break; 15374d61c878SJulian Pullen } 15384d61c878SJulian Pullen } 15394d61c878SJulian Pullen ad_disc_fini(trusted_ctx); 15404d61c878SJulian Pullen } 15414d61c878SJulian Pullen if (j > 0) { 15424d61c878SJulian Pullen pgcfg->num_trusted_forests = j; 15434d61c878SJulian Pullen pgcfg->trusted_forests = trustedforests; 15441fcced4cSJordan Brown } else { 15451fcced4cSJordan Brown free(trustedforests); 15464d61c878SJulian Pullen } 15474d61c878SJulian Pullen } 1548349d5d8fSnw 1549349d5d8fSnw if (pgcfg->domain_name == NULL) 1550349d5d8fSnw idmapdlog(LOG_DEBUG, "unable to discover Domain Name"); 1551349d5d8fSnw if (pgcfg->domain_controller == NULL) 1552349d5d8fSnw idmapdlog(LOG_DEBUG, "unable to discover Domain Controller"); 1553349d5d8fSnw if (pgcfg->forest_name == NULL) 1554349d5d8fSnw idmapdlog(LOG_DEBUG, "unable to discover Forest Name"); 1555349d5d8fSnw if (pgcfg->site_name == NULL) 1556349d5d8fSnw idmapdlog(LOG_DEBUG, "unable to discover Site Name"); 1557349d5d8fSnw if (pgcfg->global_catalog == NULL) 1558349d5d8fSnw idmapdlog(LOG_DEBUG, "unable to discover Global Catalog"); 15594d61c878SJulian Pullen if (pgcfg->domains_in_forest == NULL) 15604d61c878SJulian Pullen idmapdlog(LOG_DEBUG, 15614d61c878SJulian Pullen "unable to discover Domains in the Forest"); 15624d61c878SJulian Pullen if (pgcfg->trusted_domains == NULL) 15634d61c878SJulian Pullen idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains"); 1564*c5866007SKeyur Desai 1565*c5866007SKeyur Desai ad_disc_done(ad_ctx); 1566*c5866007SKeyur Desai idmapdlog(LOG_DEBUG, "Discovery done."); 1567349d5d8fSnw } 1568349d5d8fSnw 15694d61c878SJulian Pullen 1570349d5d8fSnw /* 1571349d5d8fSnw * idmap_cfg_load() is called at startup, and periodically via the 1572349d5d8fSnw * update thread when the auto-discovery TTLs expire, as well as part of 1573349d5d8fSnw * the refresh method, to update the current configuration. It always 1574349d5d8fSnw * reads from SMF, but you still have to refresh the service after 1575349d5d8fSnw * changing the config pg in order for the changes to take effect. 1576349d5d8fSnw * 1577349d5d8fSnw * There are two flags: 1578349d5d8fSnw * 1579349d5d8fSnw * - CFG_DISCOVER 1580349d5d8fSnw * - CFG_LOG 1581349d5d8fSnw * 1582349d5d8fSnw * If CFG_DISCOVER is set then idmap_cfg_load() calls 1583349d5d8fSnw * idmap_cfg_discover() to discover, via DNS and LDAP lookups, property 1584349d5d8fSnw * values that weren't set in SMF. 1585349d5d8fSnw * 1586349d5d8fSnw * If CFG_LOG is set then idmap_cfg_load() will log (to LOG_NOTICE) 1587349d5d8fSnw * whether the configuration changed. This should be used only from the 1588349d5d8fSnw * refresh method. 1589349d5d8fSnw * 1590349d5d8fSnw * Return values: 0 -> success, -1 -> failure, -2 -> hard failures 1591349d5d8fSnw * reading from SMF. 1592349d5d8fSnw */ 1593349d5d8fSnw int 1594349d5d8fSnw idmap_cfg_load(idmap_cfg_t *cfg, int flags) 1595349d5d8fSnw { 1596349d5d8fSnw int rc = 0; 1597e3f2c991SKeyur Desai int errors; 1598349d5d8fSnw int changed = 0; 15994d61c878SJulian Pullen int ad_reload_required = 0; 1600349d5d8fSnw idmap_pg_config_t new_pgcfg, *live_pgcfg; 1601349d5d8fSnw 1602349d5d8fSnw live_pgcfg = &cfg->pgcfg; 1603349d5d8fSnw (void) memset(&new_pgcfg, 0, sizeof (new_pgcfg)); 1604349d5d8fSnw 1605349d5d8fSnw pthread_mutex_lock(&cfg->handles.mutex); 1606349d5d8fSnw 1607349d5d8fSnw if ((rc = idmap_cfg_load_smf(&cfg->handles, &new_pgcfg, &errors)) < -1) 1608349d5d8fSnw goto err; 1609349d5d8fSnw 1610349d5d8fSnw if (flags & CFG_DISCOVER) 1611349d5d8fSnw idmap_cfg_discover(&cfg->handles, &new_pgcfg); 1612349d5d8fSnw 1613349d5d8fSnw WRLOCK_CONFIG(); 1614349d5d8fSnw if (live_pgcfg->list_size_limit != new_pgcfg.list_size_limit) { 1615349d5d8fSnw idmapdlog(LOG_INFO, "change list_size=%d", 1616349d5d8fSnw new_pgcfg.list_size_limit); 1617349d5d8fSnw live_pgcfg->list_size_limit = new_pgcfg.list_size_limit; 1618349d5d8fSnw } 1619349d5d8fSnw 1620349d5d8fSnw /* Non-discoverable props updated here */ 16214aa0a5e7Snw changed += update_string(&live_pgcfg->machine_sid, 1622349d5d8fSnw &new_pgcfg.machine_sid, "machine_sid"); 1623349d5d8fSnw 16244aa0a5e7Snw changed += update_bool(&live_pgcfg->eph_map_unres_sids, 16254aa0a5e7Snw &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); 16264aa0a5e7Snw 1627e3f2c991SKeyur Desai changed += update_enum(&live_pgcfg->directory_based_mapping, 1628e3f2c991SKeyur Desai &new_pgcfg.directory_based_mapping, "directory_based_mapping", 1629e3f2c991SKeyur Desai directory_mapping_map); 1630349d5d8fSnw 16314aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixuser_attr, 1632349d5d8fSnw &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr"); 1633349d5d8fSnw 16344aa0a5e7Snw changed += update_string(&live_pgcfg->ad_unixgroup_attr, 1635349d5d8fSnw &new_pgcfg.ad_unixgroup_attr, "ad_unixgroup_attr"); 1636349d5d8fSnw 16374aa0a5e7Snw changed += update_string(&live_pgcfg->nldap_winname_attr, 1638349d5d8fSnw &new_pgcfg.nldap_winname_attr, "nldap_winname_attr"); 1639349d5d8fSnw 1640349d5d8fSnw /* Props that can be discovered and set in SMF updated here */ 1641e3f2c991SKeyur Desai changed += update_string(&live_pgcfg->default_domain, 1642e3f2c991SKeyur Desai &new_pgcfg.default_domain, "default_domain"); 1643349d5d8fSnw 16444aa0a5e7Snw changed += update_string(&live_pgcfg->domain_name, 1645349d5d8fSnw &new_pgcfg.domain_name, "domain_name"); 16464d61c878SJulian Pullen live_pgcfg->domain_name_auto_disc = new_pgcfg.domain_name_auto_disc; 1647349d5d8fSnw 1648349d5d8fSnw changed += update_dirs(&live_pgcfg->domain_controller, 1649349d5d8fSnw &new_pgcfg.domain_controller, "domain_controller"); 16504d61c878SJulian Pullen live_pgcfg->domain_controller_auto_disc = 16514d61c878SJulian Pullen new_pgcfg.domain_controller_auto_disc; 1652349d5d8fSnw 16534aa0a5e7Snw changed += update_string(&live_pgcfg->forest_name, 1654349d5d8fSnw &new_pgcfg.forest_name, "forest_name"); 16554d61c878SJulian Pullen live_pgcfg->forest_name_auto_disc = new_pgcfg.forest_name_auto_disc; 1656349d5d8fSnw 16574aa0a5e7Snw changed += update_string(&live_pgcfg->site_name, 1658349d5d8fSnw &new_pgcfg.site_name, "site_name"); 16594d61c878SJulian Pullen live_pgcfg->site_name_auto_disc = new_pgcfg.site_name_auto_disc; 1660349d5d8fSnw 1661349d5d8fSnw if (update_dirs(&live_pgcfg->global_catalog, 1662349d5d8fSnw &new_pgcfg.global_catalog, "global_catalog")) { 1663349d5d8fSnw changed++; 1664349d5d8fSnw if (live_pgcfg->global_catalog != NULL && 1665349d5d8fSnw live_pgcfg->global_catalog[0].host[0] != '\0') 16664d61c878SJulian Pullen ad_reload_required = TRUE; 1667349d5d8fSnw } 16684d61c878SJulian Pullen live_pgcfg->global_catalog_auto_disc = 16694d61c878SJulian Pullen new_pgcfg.global_catalog_auto_disc; 16704d61c878SJulian Pullen 16714d61c878SJulian Pullen if (update_domains_in_forest(&live_pgcfg->domains_in_forest, 16724d61c878SJulian Pullen &new_pgcfg.domains_in_forest, "domains_in_forest")) { 16734d61c878SJulian Pullen changed++; 16744d61c878SJulian Pullen ad_reload_required = TRUE; 16754d61c878SJulian Pullen } 16764d61c878SJulian Pullen 16774d61c878SJulian Pullen if (update_trusted_domains(&live_pgcfg->trusted_domains, 16784d61c878SJulian Pullen &new_pgcfg.trusted_domains, "trusted_domains")) { 16794d61c878SJulian Pullen changed++; 16804d61c878SJulian Pullen if (live_pgcfg->trusted_domains != NULL && 16814d61c878SJulian Pullen live_pgcfg->trusted_domains[0].domain[0] != '\0') 16824d61c878SJulian Pullen ad_reload_required = TRUE; 16834d61c878SJulian Pullen } 16844d61c878SJulian Pullen 16854d61c878SJulian Pullen if (update_trusted_forest(&live_pgcfg->trusted_forests, 16864d61c878SJulian Pullen &live_pgcfg->num_trusted_forests, &new_pgcfg.trusted_forests, 16874d61c878SJulian Pullen &new_pgcfg.num_trusted_forests, "trusted_forest")) { 16884d61c878SJulian Pullen changed++; 16894d61c878SJulian Pullen if (live_pgcfg->trusted_forests != NULL) 16904d61c878SJulian Pullen ad_reload_required = TRUE; 16914d61c878SJulian Pullen } 16924d61c878SJulian Pullen 16934d61c878SJulian Pullen if (ad_reload_required) 16944d61c878SJulian Pullen reload_ad(); 1695349d5d8fSnw 1696349d5d8fSnw idmap_cfg_unload(&new_pgcfg); 1697349d5d8fSnw 1698349d5d8fSnw if (flags & CFG_LOG) { 1699349d5d8fSnw /* 1700349d5d8fSnw * If the config changes as a result of a refresh of the 1701349d5d8fSnw * service, then logging about it can provide useful 1702349d5d8fSnw * feedback to the sysadmin. 1703349d5d8fSnw */ 1704349d5d8fSnw idmapdlog(LOG_NOTICE, "Configuration %schanged", 1705349d5d8fSnw changed ? "" : "un"); 1706c8e26105Sjp } 1707e3c2d6aaSnw 1708349d5d8fSnw UNLOCK_CONFIG(); 1709349d5d8fSnw 1710349d5d8fSnw err: 1711349d5d8fSnw pthread_mutex_unlock(&cfg->handles.mutex); 1712c5c4113dSnw 1713e8c27ec8Sbaban if (rc < -1) 1714e3c2d6aaSnw return (rc); 1715e3c2d6aaSnw 1716e3c2d6aaSnw return ((errors == 0) ? 0 : -1); 1717c5c4113dSnw } 1718c5c4113dSnw 1719651c0131Sbaban /* 1720651c0131Sbaban * Initialize 'cfg'. 1721651c0131Sbaban */ 1722c5c4113dSnw idmap_cfg_t * 17234edd44c5Sjp idmap_cfg_init() 17244edd44c5Sjp { 1725c8e26105Sjp idmap_cfg_handles_t *handles; 1726c5c4113dSnw 1727c5c4113dSnw /* First the smf repository handles: */ 1728c5c4113dSnw idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t)); 1729c5c4113dSnw if (!cfg) { 173071590c90Snw idmapdlog(LOG_ERR, "Out of memory"); 1731c5c4113dSnw return (NULL); 1732c5c4113dSnw } 1733c8e26105Sjp handles = &cfg->handles; 1734c5c4113dSnw 1735c8e26105Sjp (void) pthread_mutex_init(&handles->mutex, NULL); 1736c8e26105Sjp 1737c8e26105Sjp if (!(handles->main = scf_handle_create(SCF_VERSION))) { 173871590c90Snw idmapdlog(LOG_ERR, "scf_handle_create() failed: %s", 173971590c90Snw scf_strerror(scf_error())); 1740c5c4113dSnw goto error; 1741c5c4113dSnw } 1742c5c4113dSnw 1743c8e26105Sjp if (scf_handle_bind(handles->main) < 0) { 174471590c90Snw idmapdlog(LOG_ERR, "scf_handle_bind() failed: %s", 174571590c90Snw scf_strerror(scf_error())); 1746c5c4113dSnw goto error; 1747c5c4113dSnw } 1748c5c4113dSnw 1749c8e26105Sjp if (!(handles->service = scf_service_create(handles->main)) || 1750c8e26105Sjp !(handles->instance = scf_instance_create(handles->main)) || 1751c8e26105Sjp !(handles->config_pg = scf_pg_create(handles->main)) || 1752c8e26105Sjp !(handles->general_pg = scf_pg_create(handles->main))) { 175371590c90Snw idmapdlog(LOG_ERR, "scf handle creation failed: %s", 175471590c90Snw scf_strerror(scf_error())); 1755c5c4113dSnw goto error; 1756c5c4113dSnw } 1757c5c4113dSnw 1758c8e26105Sjp if (scf_handle_decode_fmri(handles->main, 17594edd44c5Sjp FMRI_BASE "/:properties/" CONFIG_PG, 17604edd44c5Sjp NULL, /* scope */ 17614edd44c5Sjp handles->service, /* service */ 17624edd44c5Sjp handles->instance, /* instance */ 17634edd44c5Sjp handles->config_pg, /* pg */ 17644edd44c5Sjp NULL, /* prop */ 17654edd44c5Sjp SCF_DECODE_FMRI_EXACT) < 0) { 176671590c90Snw idmapdlog(LOG_ERR, "scf_handle_decode_fmri() failed: %s", 176771590c90Snw scf_strerror(scf_error())); 1768c5c4113dSnw goto error; 1769c5c4113dSnw } 1770c5c4113dSnw 1771c8e26105Sjp if (scf_service_get_pg(handles->service, 17724edd44c5Sjp GENERAL_PG, handles->general_pg) < 0) { 177371590c90Snw idmapdlog(LOG_ERR, "scf_service_get_pg() failed: %s", 177471590c90Snw scf_strerror(scf_error())); 1775c5c4113dSnw goto error; 1776c5c4113dSnw } 1777c5c4113dSnw 1778e3f2c991SKeyur Desai if (check_smf_debug_mode(handles) != 0) 1779e3f2c991SKeyur Desai goto error; 1780e3f2c991SKeyur Desai 1781c8e26105Sjp /* Initialize AD Auto Discovery context */ 1782c8e26105Sjp handles->ad_ctx = ad_disc_init(); 1783c8e26105Sjp if (handles->ad_ctx == NULL) 1784c8e26105Sjp goto error; 1785c8e26105Sjp 1786c5c4113dSnw return (cfg); 1787c5c4113dSnw 1788c5c4113dSnw error: 1789c5c4113dSnw (void) idmap_cfg_fini(cfg); 1790c5c4113dSnw return (NULL); 1791c5c4113dSnw } 1792c5c4113dSnw 1793c8e26105Sjp void 17944edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg) 17954edd44c5Sjp { 1796c8e26105Sjp 1797c8e26105Sjp if (pgcfg->default_domain) { 1798c8e26105Sjp free(pgcfg->default_domain); 1799c8e26105Sjp pgcfg->default_domain = NULL; 1800c8e26105Sjp } 1801c8e26105Sjp if (pgcfg->domain_name) { 1802c8e26105Sjp free(pgcfg->domain_name); 1803c8e26105Sjp pgcfg->domain_name = NULL; 1804c8e26105Sjp } 1805c8e26105Sjp if (pgcfg->machine_sid) { 1806c8e26105Sjp free(pgcfg->machine_sid); 1807c8e26105Sjp pgcfg->machine_sid = NULL; 1808c8e26105Sjp } 1809c8e26105Sjp if (pgcfg->domain_controller) { 1810c5c4113dSnw free(pgcfg->domain_controller); 1811c8e26105Sjp pgcfg->domain_controller = NULL; 1812c8e26105Sjp } 1813c8e26105Sjp if (pgcfg->forest_name) { 1814c8e26105Sjp free(pgcfg->forest_name); 1815c8e26105Sjp pgcfg->forest_name = NULL; 1816c8e26105Sjp } 1817c8e26105Sjp if (pgcfg->site_name) { 1818c8e26105Sjp free(pgcfg->site_name); 1819c8e26105Sjp pgcfg->site_name = NULL; 1820c8e26105Sjp } 1821c8e26105Sjp if (pgcfg->global_catalog) { 1822c8e26105Sjp free(pgcfg->global_catalog); 1823c8e26105Sjp pgcfg->global_catalog = NULL; 1824c8e26105Sjp } 18254d61c878SJulian Pullen if (pgcfg->trusted_domains) { 18264d61c878SJulian Pullen free(pgcfg->trusted_domains); 18274d61c878SJulian Pullen pgcfg->trusted_domains = NULL; 18284d61c878SJulian Pullen } 18294d61c878SJulian Pullen if (pgcfg->trusted_forests) 18304d61c878SJulian Pullen free_trusted_forests(&pgcfg->trusted_forests, 18314d61c878SJulian Pullen &pgcfg->num_trusted_forests); 18324d61c878SJulian Pullen 1833e8c27ec8Sbaban if (pgcfg->ad_unixuser_attr) { 1834e8c27ec8Sbaban free(pgcfg->ad_unixuser_attr); 1835e8c27ec8Sbaban pgcfg->ad_unixuser_attr = NULL; 1836e8c27ec8Sbaban } 1837e8c27ec8Sbaban if (pgcfg->ad_unixgroup_attr) { 1838e8c27ec8Sbaban free(pgcfg->ad_unixgroup_attr); 1839e8c27ec8Sbaban pgcfg->ad_unixgroup_attr = NULL; 1840e8c27ec8Sbaban } 1841e8c27ec8Sbaban if (pgcfg->nldap_winname_attr) { 1842e8c27ec8Sbaban free(pgcfg->nldap_winname_attr); 1843e8c27ec8Sbaban pgcfg->nldap_winname_attr = NULL; 1844e8c27ec8Sbaban } 1845c5c4113dSnw } 1846c5c4113dSnw 1847c5c4113dSnw int 1848c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg) 1849c5c4113dSnw { 1850c8e26105Sjp idmap_cfg_handles_t *handles = &cfg->handles; 1851c8e26105Sjp idmap_cfg_unload(&cfg->pgcfg); 1852c8e26105Sjp 1853c8e26105Sjp (void) pthread_mutex_destroy(&handles->mutex); 1854c8e26105Sjp scf_pg_destroy(handles->config_pg); 1855c8e26105Sjp scf_pg_destroy(handles->general_pg); 1856c8e26105Sjp scf_instance_destroy(handles->instance); 1857c8e26105Sjp scf_service_destroy(handles->service); 1858c8e26105Sjp scf_handle_destroy(handles->main); 1859e8c27ec8Sbaban if (handles->ad_ctx != NULL) 1860e8c27ec8Sbaban ad_disc_fini(handles->ad_ctx); 1861c5c4113dSnw free(cfg); 1862c5c4113dSnw 1863c5c4113dSnw return (0); 1864c5c4113dSnw } 18650dcc7149Snw 18660dcc7149Snw void 18670dcc7149Snw idmap_cfg_poke_updates(void) 18680dcc7149Snw { 1869349d5d8fSnw if (idmapd_ev_port != -1) 1870349d5d8fSnw (void) port_send(idmapd_ev_port, POKE_AUTO_DISCOVERY, NULL); 18710dcc7149Snw } 18720dcc7149Snw 18730dcc7149Snw /*ARGSUSED*/ 18740dcc7149Snw void 1875349d5d8fSnw idmap_cfg_hup_handler(int sig) 1876349d5d8fSnw { 18770dcc7149Snw if (idmapd_ev_port >= 0) 18780dcc7149Snw (void) port_send(idmapd_ev_port, RECONFIGURE, NULL); 18790dcc7149Snw } 1880e3f2c991SKeyur Desai 1881e3f2c991SKeyur Desai /* 1882e3f2c991SKeyur Desai * Upgrade the DS mapping flags. 1883e3f2c991SKeyur Desai * 1884e3f2c991SKeyur Desai * If the old ds_name_mapping_enabled flag is present, then 1885e3f2c991SKeyur Desai * if the new directory_based_mapping value is present, then 1886e3f2c991SKeyur Desai * if the two are compatible, delete the old and note it 1887e3f2c991SKeyur Desai * else delete the old and warn 1888e3f2c991SKeyur Desai * else 1889e3f2c991SKeyur Desai * set the new based on the old, and note it 1890e3f2c991SKeyur Desai * delete the old 1891e3f2c991SKeyur Desai */ 1892e3f2c991SKeyur Desai static 1893e3f2c991SKeyur Desai int 1894e3f2c991SKeyur Desai upgrade_directory_mapping(idmap_cfg_handles_t *handles) 1895e3f2c991SKeyur Desai { 1896e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_present; 1897e3f2c991SKeyur Desai const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled"; 1898e3f2c991SKeyur Desai const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping"; 1899e3f2c991SKeyur Desai int rc; 1900e3f2c991SKeyur Desai 1901e3f2c991SKeyur Desai rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED, 1902e3f2c991SKeyur Desai &legacy_ds_name_mapping_present); 1903e3f2c991SKeyur Desai 1904e3f2c991SKeyur Desai if (rc != 0) 1905e3f2c991SKeyur Desai return (rc); 1906e3f2c991SKeyur Desai 1907e3f2c991SKeyur Desai if (!legacy_ds_name_mapping_present) 1908e3f2c991SKeyur Desai return (0); 1909e3f2c991SKeyur Desai 1910e3f2c991SKeyur Desai boolean_t legacy_ds_name_mapping_enabled; 1911e3f2c991SKeyur Desai rc = get_val_int(handles, DS_NAME_MAPPING_ENABLED, 1912e3f2c991SKeyur Desai &legacy_ds_name_mapping_enabled, SCF_TYPE_BOOLEAN); 1913e3f2c991SKeyur Desai if (rc != 0) 1914e3f2c991SKeyur Desai return (rc); 1915e3f2c991SKeyur Desai 1916e3f2c991SKeyur Desai char *legacy_mode; 1917e3f2c991SKeyur Desai char *legacy_bool_string; 1918e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled) { 1919e3f2c991SKeyur Desai legacy_mode = "name"; 1920e3f2c991SKeyur Desai legacy_bool_string = "true"; 1921e3f2c991SKeyur Desai } else { 1922e3f2c991SKeyur Desai legacy_mode = "none"; 1923e3f2c991SKeyur Desai legacy_bool_string = "false"; 1924e3f2c991SKeyur Desai } 1925e3f2c991SKeyur Desai 1926e3f2c991SKeyur Desai char *directory_based_mapping; 1927e3f2c991SKeyur Desai rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING, 1928e3f2c991SKeyur Desai &directory_based_mapping); 1929e3f2c991SKeyur Desai if (rc != 0) 1930e3f2c991SKeyur Desai return (rc); 1931e3f2c991SKeyur Desai 1932e3f2c991SKeyur Desai if (directory_based_mapping == NULL) { 1933e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 1934e3f2c991SKeyur Desai "Upgrading old %s=%s setting\n" 1935e3f2c991SKeyur Desai "to %s=%s.", 1936e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 1937e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, legacy_mode); 1938e3f2c991SKeyur Desai rc = set_val_astring(handles, DIRECTORY_BASED_MAPPING, 1939e3f2c991SKeyur Desai legacy_mode); 1940e3f2c991SKeyur Desai if (rc != 0) 1941e3f2c991SKeyur Desai return (rc); 1942e3f2c991SKeyur Desai } else { 1943e3f2c991SKeyur Desai boolean_t new_name_mapping; 1944e3f2c991SKeyur Desai if (strcasecmp(directory_based_mapping, "name") == 0) 1945e3f2c991SKeyur Desai new_name_mapping = B_TRUE; 1946e3f2c991SKeyur Desai else 1947e3f2c991SKeyur Desai new_name_mapping = B_FALSE; 1948e3f2c991SKeyur Desai 1949e3f2c991SKeyur Desai if (legacy_ds_name_mapping_enabled == new_name_mapping) { 1950e3f2c991SKeyur Desai idmapdlog(LOG_INFO, 1951e3f2c991SKeyur Desai "Automatically removing old %s=%s setting\n" 1952e3f2c991SKeyur Desai "in favor of %s=%s.", 1953e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 1954e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 1955e3f2c991SKeyur Desai } else { 1956e3f2c991SKeyur Desai idmapdlog(LOG_WARNING, 1957e3f2c991SKeyur Desai "Removing conflicting %s=%s setting\n" 1958e3f2c991SKeyur Desai "in favor of %s=%s.", 1959e3f2c991SKeyur Desai DS_NAME_MAPPING_ENABLED, legacy_bool_string, 1960e3f2c991SKeyur Desai DIRECTORY_BASED_MAPPING, directory_based_mapping); 1961e3f2c991SKeyur Desai } 1962e3f2c991SKeyur Desai free(directory_based_mapping); 1963e3f2c991SKeyur Desai } 1964e3f2c991SKeyur Desai 1965e3f2c991SKeyur Desai rc = del_val(handles, DS_NAME_MAPPING_ENABLED); 1966e3f2c991SKeyur Desai if (rc != 0) 1967e3f2c991SKeyur Desai return (rc); 1968e3f2c991SKeyur Desai 1969e3f2c991SKeyur Desai return (0); 1970e3f2c991SKeyur Desai } 1971e3f2c991SKeyur Desai 1972e3f2c991SKeyur Desai /* 1973e3f2c991SKeyur Desai * Do whatever is necessary to upgrade idmap's configuration before 1974e3f2c991SKeyur Desai * we load it. 1975e3f2c991SKeyur Desai */ 1976e3f2c991SKeyur Desai int 1977e3f2c991SKeyur Desai idmap_cfg_upgrade(idmap_cfg_t *cfg) 1978e3f2c991SKeyur Desai { 1979e3f2c991SKeyur Desai int rc; 1980e3f2c991SKeyur Desai 1981e3f2c991SKeyur Desai rc = upgrade_directory_mapping(&cfg->handles); 1982e3f2c991SKeyur Desai if (rc != 0) 1983e3f2c991SKeyur Desai return (rc); 1984e3f2c991SKeyur Desai 1985e3f2c991SKeyur Desai return (0); 1986e3f2c991SKeyur Desai } 1987