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*4edd44c5Sjp * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23c5c4113dSnw * Use is subject to license terms. 24c5c4113dSnw */ 25c5c4113dSnw 26c5c4113dSnw #pragma ident "%Z%%M% %I% %E% SMI" 27c5c4113dSnw 28c5c4113dSnw /* 29c5c4113dSnw * Config routines common to idmap(1M) and idmapd(1M) 30c5c4113dSnw */ 31c5c4113dSnw 32c5c4113dSnw #include <stdlib.h> 33c5c4113dSnw #include <strings.h> 34c5c4113dSnw #include <libintl.h> 35c5c4113dSnw #include <ctype.h> 36c5c4113dSnw #include <errno.h> 37651c0131Sbaban #include "idmapd.h" 38c5c4113dSnw #include <stdio.h> 39c5c4113dSnw #include <stdarg.h> 408edda628Sbaban #include <uuid/uuid.h> 41c8e26105Sjp #include <pthread.h> 42c8e26105Sjp #include <port.h> 43c8e26105Sjp #include "addisc.h" 44c5c4113dSnw 458edda628Sbaban #define MACHINE_SID_LEN (9 + UUID_LEN/4 * 11) 46c5c4113dSnw #define FMRI_BASE "svc:/system/idmap" 47c5c4113dSnw #define CONFIG_PG "config" 48c5c4113dSnw #define GENERAL_PG "general" 49c5c4113dSnw /* initial length of the array for policy options/attributes: */ 50c5c4113dSnw #define DEF_ARRAY_LENGTH 16 51c5c4113dSnw 52c8e26105Sjp /*LINTLIBRARY*/ 53c8e26105Sjp 54c8e26105Sjp 55651c0131Sbaban static const char *me = "idmapd"; 56c5c4113dSnw 57c8e26105Sjp 58c8e26105Sjp static pthread_t update_thread_handle = 0; 59c8e26105Sjp 60c8e26105Sjp int hup_ev_port = -1; 61c8e26105Sjp extern int hupped; 62c8e26105Sjp 638edda628Sbaban static int 64*4edd44c5Sjp generate_machine_sid(char **machine_sid) 65*4edd44c5Sjp { 668edda628Sbaban char *p; 678edda628Sbaban uuid_t uu; 688edda628Sbaban int i, j, len, rlen; 698edda628Sbaban uint32_t rid; 708edda628Sbaban 718edda628Sbaban /* 728edda628Sbaban * Generate and split 128-bit UUID into four 32-bit RIDs 738edda628Sbaban * The machine_sid will be of the form S-1-5-N1-N2-N3-N4 748edda628Sbaban * We depart from Windows here, which instead of 128 758edda628Sbaban * bits worth of random numbers uses 96 bits. 768edda628Sbaban */ 778edda628Sbaban 788edda628Sbaban *machine_sid = calloc(1, MACHINE_SID_LEN); 798edda628Sbaban if (*machine_sid == NULL) { 808edda628Sbaban idmapdlog(LOG_ERR, "%s: Out of memory", me); 818edda628Sbaban return (-1); 828edda628Sbaban } 838edda628Sbaban (void) strcpy(*machine_sid, "S-1-5-21"); 848edda628Sbaban p = *machine_sid + strlen("S-1-5-21"); 858edda628Sbaban len = MACHINE_SID_LEN - strlen("S-1-5-21"); 868edda628Sbaban 878edda628Sbaban uuid_clear(uu); 888edda628Sbaban uuid_generate_random(uu); 898edda628Sbaban 908edda628Sbaban for (i = 0; i < UUID_LEN/4; i++) { 918edda628Sbaban j = i * 4; 928edda628Sbaban rid = (uu[j] << 24) | (uu[j + 1] << 16) | 93*4edd44c5Sjp (uu[j + 2] << 8) | (uu[j + 3]); 948edda628Sbaban rlen = snprintf(p, len, "-%u", rid); 958edda628Sbaban p += rlen; 968edda628Sbaban len -= rlen; 978edda628Sbaban } 988edda628Sbaban 998edda628Sbaban return (0); 1008edda628Sbaban } 1018edda628Sbaban 102c5c4113dSnw /* Check if in the case of failure the original value of *val is preserved */ 103c5c4113dSnw static int 104c8e26105Sjp get_val_int(idmap_cfg_handles_t *handles, char *name, 105c8e26105Sjp void *val, scf_type_t type) 106c5c4113dSnw { 107c5c4113dSnw int rc = 0; 108c5c4113dSnw 109c8e26105Sjp scf_property_t *scf_prop = scf_property_create(handles->main); 110c8e26105Sjp scf_value_t *value = scf_value_create(handles->main); 111c5c4113dSnw 112c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 113c5c4113dSnw /* this is OK: the property is just undefined */ 114c5c4113dSnw goto destruction; 115c5c4113dSnw 116c5c4113dSnw 117c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) 118c5c4113dSnw /* It is still OK when a property doesn't have any value */ 119c5c4113dSnw goto destruction; 120c5c4113dSnw 121c5c4113dSnw switch (type) { 122c5c4113dSnw case SCF_TYPE_BOOLEAN: 123c5c4113dSnw rc = scf_value_get_boolean(value, val); 124c5c4113dSnw break; 125c5c4113dSnw case SCF_TYPE_COUNT: 126c5c4113dSnw rc = scf_value_get_count(value, val); 127c5c4113dSnw break; 128c5c4113dSnw case SCF_TYPE_INTEGER: 129c5c4113dSnw rc = scf_value_get_integer(value, val); 130c5c4113dSnw break; 131c5c4113dSnw default: 132651c0131Sbaban idmapdlog(LOG_ERR, "%s: Invalid scf integer type (%d)", 133651c0131Sbaban me, type); 134c5c4113dSnw rc = -1; 135c5c4113dSnw break; 136c5c4113dSnw } 137c5c4113dSnw 138c5c4113dSnw 139c5c4113dSnw destruction: 140c5c4113dSnw scf_value_destroy(value); 141c5c4113dSnw scf_property_destroy(scf_prop); 142c5c4113dSnw 143c5c4113dSnw return (rc); 144c5c4113dSnw } 145c5c4113dSnw 146c5c4113dSnw static char * 147*4edd44c5Sjp scf_value2string(scf_value_t *value) 148*4edd44c5Sjp { 149c5c4113dSnw int rc = -1; 150c5c4113dSnw char buf_size = 127; 151c5c4113dSnw int length; 152c5c4113dSnw char *buf = NULL; 153c5c4113dSnw buf = (char *) malloc(sizeof (char) * buf_size); 154c5c4113dSnw 155c5c4113dSnw for (;;) { 156c5c4113dSnw length = scf_value_get_astring(value, buf, buf_size); 157c5c4113dSnw if (length < 0) { 158c5c4113dSnw rc = -1; 159c5c4113dSnw goto destruction; 160c5c4113dSnw } 161c5c4113dSnw 162c5c4113dSnw if (length == buf_size - 1) { 163c5c4113dSnw buf_size *= 2; 164c5c4113dSnw buf = (char *)realloc(buf, buf_size * sizeof (char)); 165c5c4113dSnw if (!buf) { 166651c0131Sbaban idmapdlog(LOG_ERR, "%s: Out of memory", me); 167c5c4113dSnw rc = -1; 168c5c4113dSnw goto destruction; 169c5c4113dSnw } 170c5c4113dSnw } else { 171c5c4113dSnw rc = 0; 172*4edd44c5Sjp break; 173*4edd44c5Sjp } 174c5c4113dSnw } 175c5c4113dSnw 176c5c4113dSnw destruction: 177c5c4113dSnw if (rc < 0) { 178c5c4113dSnw if (buf) 179c5c4113dSnw free(buf); 180c5c4113dSnw buf = NULL; 181c5c4113dSnw } 182c5c4113dSnw 183c5c4113dSnw return (buf); 184c5c4113dSnw } 185c5c4113dSnw 186c8e26105Sjp static int 187c8e26105Sjp get_val_ds(idmap_cfg_handles_t *handles, const char *name, int defport, 188c8e26105Sjp ad_disc_ds_t **val) 189c8e26105Sjp { 190c8e26105Sjp ad_disc_ds_t *servers = NULL; 191c8e26105Sjp scf_property_t *scf_prop; 192c8e26105Sjp scf_value_t *value; 193c8e26105Sjp scf_iter_t *iter; 194c8e26105Sjp char *host, *portstr; 195e3c2d6aaSnw int len, i; 196c8e26105Sjp int count = 0; 197e3c2d6aaSnw int rc = -1; 198c8e26105Sjp 199c8e26105Sjp *val = NULL; 200c8e26105Sjp 201c8e26105Sjp restart: 202c8e26105Sjp scf_prop = scf_property_create(handles->main); 203c8e26105Sjp value = scf_value_create(handles->main); 204c8e26105Sjp iter = scf_iter_create(handles->main); 205c8e26105Sjp 206e3c2d6aaSnw if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) { 207c8e26105Sjp /* this is OK: the property is just undefined */ 208e3c2d6aaSnw rc = 0; 209c8e26105Sjp goto destruction; 210e3c2d6aaSnw } 211c8e26105Sjp 212c8e26105Sjp if (scf_iter_property_values(iter, scf_prop) < 0) { 213c8e26105Sjp idmapdlog(LOG_ERR, 214c8e26105Sjp "%s: scf_iter_property_values(%s) failed: %s", 215c8e26105Sjp me, name, scf_strerror(scf_error())); 216c8e26105Sjp goto destruction; 217c8e26105Sjp } 218c8e26105Sjp 219c8e26105Sjp /* Workaround scf bugs -- can't reset an iteration */ 220c8e26105Sjp if (count == 0) { 221c8e26105Sjp while (scf_iter_next_value(iter, value) > 0) 222c8e26105Sjp count++; 223c8e26105Sjp 224e3c2d6aaSnw if (count == 0) { 225c8e26105Sjp /* no values */ 226e3c2d6aaSnw rc = 0; 227c8e26105Sjp goto destruction; 228e3c2d6aaSnw } 229c8e26105Sjp 230c8e26105Sjp scf_value_destroy(value); 231c8e26105Sjp scf_iter_destroy(iter); 232c8e26105Sjp scf_property_destroy(scf_prop); 233c8e26105Sjp goto restart; 234c8e26105Sjp } 235c8e26105Sjp 236c8e26105Sjp if ((servers = calloc(count + 1, sizeof (*servers))) == NULL) { 237c8e26105Sjp idmapdlog(LOG_ERR, "%s: Out of memory", me); 238c8e26105Sjp goto destruction; 239c8e26105Sjp } 240c8e26105Sjp 241e3c2d6aaSnw i = 0; 242e3c2d6aaSnw while (i < count && scf_iter_next_value(iter, value) > 0) { 243e3c2d6aaSnw servers[i].priority = 0; 244e3c2d6aaSnw servers[i].weight = 100; 245e3c2d6aaSnw servers[i].port = defport; 246c8e26105Sjp if ((host = scf_value2string(value)) == NULL) { 247c8e26105Sjp goto destruction; 248c8e26105Sjp } 249c8e26105Sjp if ((portstr = strchr(host, ':')) != NULL) { 250c8e26105Sjp *portstr++ = '\0'; 251e3c2d6aaSnw servers[i].port = strtol(portstr, 252c8e26105Sjp (char **)NULL, 10); 253e3c2d6aaSnw if (servers[i].port == 0) 254e3c2d6aaSnw servers[i].port = defport; 255c8e26105Sjp } 256e3c2d6aaSnw len = strlcpy(servers[i].host, host, 257c8e26105Sjp sizeof (servers->host)); 258c8e26105Sjp 259c8e26105Sjp free(host); 260c8e26105Sjp 261c8e26105Sjp /* Ignore this server if the hostname is too long */ 262c8e26105Sjp if (len < sizeof (servers->host)) 263e3c2d6aaSnw i++; 264c8e26105Sjp } 265c8e26105Sjp 266c8e26105Sjp *val = servers; 267c8e26105Sjp 268e3c2d6aaSnw rc = 0; 269e3c2d6aaSnw 270c8e26105Sjp destruction: 271c8e26105Sjp scf_value_destroy(value); 272c8e26105Sjp scf_iter_destroy(iter); 273c8e26105Sjp scf_property_destroy(scf_prop); 274c8e26105Sjp 275c8e26105Sjp if (rc < 0) { 276c8e26105Sjp if (servers) 277c8e26105Sjp free(servers); 278c8e26105Sjp *val = NULL; 279c8e26105Sjp } 280c8e26105Sjp 281c8e26105Sjp return (rc); 282c8e26105Sjp } 283c8e26105Sjp 284c5c4113dSnw 285c5c4113dSnw static int 286c8e26105Sjp get_val_astring(idmap_cfg_handles_t *handles, char *name, char **val) 287c5c4113dSnw { 288c5c4113dSnw int rc = 0; 289c5c4113dSnw 290c8e26105Sjp scf_property_t *scf_prop = scf_property_create(handles->main); 291c8e26105Sjp scf_value_t *value = scf_value_create(handles->main); 292c5c4113dSnw 293c8e26105Sjp *val = NULL; 294c5c4113dSnw 295c8e26105Sjp if (scf_pg_get_property(handles->config_pg, name, scf_prop) < 0) 296c5c4113dSnw /* this is OK: the property is just undefined */ 297c5c4113dSnw goto destruction; 298c5c4113dSnw 299c8e26105Sjp if (scf_property_get_value(scf_prop, value) < 0) { 300651c0131Sbaban idmapdlog(LOG_ERR, 301651c0131Sbaban "%s: scf_property_get_value(%s) failed: %s", 302651c0131Sbaban me, name, scf_strerror(scf_error())); 303c5c4113dSnw rc = -1; 304c5c4113dSnw goto destruction; 305c5c4113dSnw } 306c5c4113dSnw 307c8e26105Sjp if (!(*val = scf_value2string(value))) 308c5c4113dSnw rc = -1; 309c5c4113dSnw 310c5c4113dSnw destruction: 311c5c4113dSnw scf_value_destroy(value); 312c5c4113dSnw scf_property_destroy(scf_prop); 313c5c4113dSnw 314c5c4113dSnw if (rc < 0) { 315c5c4113dSnw if (*val) 316c5c4113dSnw free(*val); 317c5c4113dSnw *val = NULL; 318c5c4113dSnw } 319c5c4113dSnw 320c5c4113dSnw return (rc); 321c5c4113dSnw } 322c5c4113dSnw 323c8e26105Sjp 3248edda628Sbaban static int 325c8e26105Sjp set_val_astring(idmap_cfg_handles_t *handles, char *name, const char *val) 3268edda628Sbaban { 327e3c2d6aaSnw int rc = -1; 328e3c2d6aaSnw int ret = -2; 329e3c2d6aaSnw int i; 3308edda628Sbaban scf_property_t *scf_prop = NULL; 3318edda628Sbaban scf_value_t *value = NULL; 3328edda628Sbaban scf_transaction_t *tx = NULL; 3338edda628Sbaban scf_transaction_entry_t *ent = NULL; 3348edda628Sbaban 335c8e26105Sjp if ((scf_prop = scf_property_create(handles->main)) == NULL || 336c8e26105Sjp (value = scf_value_create(handles->main)) == NULL || 337c8e26105Sjp (tx = scf_transaction_create(handles->main)) == NULL || 338c8e26105Sjp (ent = scf_entry_create(handles->main)) == NULL) { 3398edda628Sbaban idmapdlog(LOG_ERR, "%s: Unable to set property %s: %s", 3408edda628Sbaban me, name, scf_strerror(scf_error())); 3418edda628Sbaban goto destruction; 3428edda628Sbaban } 3438edda628Sbaban 344e3c2d6aaSnw for (i = 0; i < MAX_TRIES && (ret == -2 || ret == 0); i++) { 345c8e26105Sjp if (scf_transaction_start(tx, handles->config_pg) == -1) { 3468edda628Sbaban idmapdlog(LOG_ERR, 3478edda628Sbaban "%s: scf_transaction_start(%s) failed: %s", 3488edda628Sbaban me, name, scf_strerror(scf_error())); 3498edda628Sbaban goto destruction; 3508edda628Sbaban } 3518edda628Sbaban 352e3c2d6aaSnw if (scf_transaction_property_new(tx, ent, name, 353e3c2d6aaSnw SCF_TYPE_ASTRING) < 0) { 3548edda628Sbaban idmapdlog(LOG_ERR, 3558edda628Sbaban "%s: scf_transaction_property_new() failed: %s", 3568edda628Sbaban me, scf_strerror(scf_error())); 3578edda628Sbaban goto destruction; 3588edda628Sbaban } 3598edda628Sbaban 3608edda628Sbaban if (scf_value_set_astring(value, val) == -1) { 3618edda628Sbaban idmapdlog(LOG_ERR, 3628edda628Sbaban "%s: scf_value_set_astring() failed: %s", 3638edda628Sbaban me, scf_strerror(scf_error())); 3648edda628Sbaban goto destruction; 3658edda628Sbaban } 3668edda628Sbaban 3678edda628Sbaban if (scf_entry_add_value(ent, value) == -1) { 3688edda628Sbaban idmapdlog(LOG_ERR, 3698edda628Sbaban "%s: scf_entry_add_value() failed: %s", 3708edda628Sbaban me, scf_strerror(scf_error())); 3718edda628Sbaban goto destruction; 3728edda628Sbaban } 3738edda628Sbaban 374e3c2d6aaSnw if ((ret = scf_transaction_commit(tx)) == 1) 375e3c2d6aaSnw break; 376e3c2d6aaSnw 377e3c2d6aaSnw if (ret == 0 && i < MAX_TRIES - 1) { 3788edda628Sbaban /* 3798edda628Sbaban * Property group set in scf_transaction_start() 3808edda628Sbaban * is not the most recent. Update pg, reset tx and 3818edda628Sbaban * retry tx. 3828edda628Sbaban */ 3838edda628Sbaban idmapdlog(LOG_WARNING, 3848edda628Sbaban "%s: scf_transaction_commit(%s) failed - Retry: %s", 3858edda628Sbaban me, name, scf_strerror(scf_error())); 386c8e26105Sjp if (scf_pg_update(handles->config_pg) == -1) { 3878edda628Sbaban idmapdlog(LOG_ERR, 3888edda628Sbaban "%s: scf_pg_update() failed: %s", 3898edda628Sbaban me, scf_strerror(scf_error())); 3908edda628Sbaban goto destruction; 3918edda628Sbaban } 3928edda628Sbaban scf_transaction_reset(tx); 3938edda628Sbaban } 3948edda628Sbaban } 3958edda628Sbaban 396e3c2d6aaSnw 397e3c2d6aaSnw if (ret == 1) 398e3c2d6aaSnw rc = 0; 399e3c2d6aaSnw else if (ret != -2) 4008edda628Sbaban idmapdlog(LOG_ERR, 4018edda628Sbaban "%s: scf_transaction_commit(%s) failed: %s", 4028edda628Sbaban me, name, scf_strerror(scf_error())); 4038edda628Sbaban 4048edda628Sbaban destruction: 4058edda628Sbaban scf_value_destroy(value); 4068edda628Sbaban scf_entry_destroy(ent); 4078edda628Sbaban scf_transaction_destroy(tx); 4088edda628Sbaban scf_property_destroy(scf_prop); 4098edda628Sbaban return (rc); 4108edda628Sbaban } 4118edda628Sbaban 412c8e26105Sjp static int 413c8e26105Sjp update_value(char **value, char **new, char *name) 414c8e26105Sjp { 415c8e26105Sjp if (*new == NULL) 416c8e26105Sjp return (FALSE); 417c8e26105Sjp 418c8e26105Sjp if (*value != NULL && strcmp(*new, *value) == 0) { 419c8e26105Sjp free(*new); 420c8e26105Sjp *new = NULL; 421c8e26105Sjp return (FALSE); 422c8e26105Sjp } 423c8e26105Sjp 424c8e26105Sjp idmapdlog(LOG_INFO, "%s: change %s=%s", me, name, CHECK_NULL(*new)); 425c8e26105Sjp if (*value != NULL) 426c8e26105Sjp free(*value); 427c8e26105Sjp *value = *new; 428c8e26105Sjp *new = NULL; 429c8e26105Sjp return (TRUE); 430c8e26105Sjp } 431c8e26105Sjp 432c8e26105Sjp static int 433c8e26105Sjp update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new, char *name) 434c8e26105Sjp { 435c8e26105Sjp int i; 436c8e26105Sjp 437c8e26105Sjp if (*new == NULL) 438c8e26105Sjp return (FALSE); 439c8e26105Sjp 440c8e26105Sjp if (*value != NULL && ad_disc_compare_ds(*value, *new) == 0) { 441c8e26105Sjp free(*new); 442c8e26105Sjp *new = NULL; 443c8e26105Sjp return (FALSE); 444c8e26105Sjp } 445c8e26105Sjp 446c8e26105Sjp if (*value) 447c8e26105Sjp free(*value); 448c8e26105Sjp 449c8e26105Sjp for (i = 0; (*new)[i].host[0] != '\0'; i++) 450c8e26105Sjp idmapdlog(LOG_INFO, "%s: change %s=%s port=%d", me, name, 451c8e26105Sjp (*new)[i].host, (*new)[i].port); 452c8e26105Sjp *value = *new; 453c8e26105Sjp *new = NULL; 454c8e26105Sjp return (TRUE); 455c8e26105Sjp } 456c8e26105Sjp 457c8e26105Sjp 458c8e26105Sjp #define SUBNET_CHECK_TIME (2 * 60) 459c8e26105Sjp #define MAX_CHECK_TIME (10 * 60) 460c8e26105Sjp 461c8e26105Sjp /* 462c8e26105Sjp * Returns 1 if SIGHUP has been received (see hup_handler elsewhere), 0 463c8e26105Sjp * otherwise. Uses an event port and a user-defined event. 464c8e26105Sjp * 465c8e26105Sjp * Note that port_get() does not update its timeout argument when EINTR, 466c8e26105Sjp * unlike nanosleep(). We probably don't care very much here because 467c8e26105Sjp * the only signals we expect are ones that will lead to idmapd dying or 468c8e26105Sjp * SIGHUP, and we intend for the latter to cause this function to 469c8e26105Sjp * return. But if we did care then we could always use a timer event 470c8e26105Sjp * (see timer_create(3RT)) and associate it with the same event port, 471c8e26105Sjp * then we could get accurate waiting regardless of EINTRs. 472c8e26105Sjp */ 473c8e26105Sjp static 474c8e26105Sjp int 475c8e26105Sjp wait_for_ttl(struct timespec *timeout) 476c8e26105Sjp { 477c8e26105Sjp port_event_t pe; 478c8e26105Sjp int retries = 1; 479c8e26105Sjp 480c8e26105Sjp /* 481c8e26105Sjp * If event port creation failed earlier and fails now then we 482c8e26105Sjp * simply don't learn about SIGHUPs in a timely fashion. No big 483c8e26105Sjp * deal 484c8e26105Sjp */ 485c8e26105Sjp if (hup_ev_port == -1 && (hup_ev_port = port_create()) < 0) { 486c8e26105Sjp (void) nanosleep(timeout, NULL); 487c8e26105Sjp return (0); 488c8e26105Sjp } 489c8e26105Sjp 490c8e26105Sjp retry: 491c8e26105Sjp if (port_get(hup_ev_port, &pe, timeout) != 0) { 492c8e26105Sjp switch (errno) { 493c8e26105Sjp case EBADF: 494c8e26105Sjp case EBADFD: 495c8e26105Sjp hup_ev_port = -1; 496c8e26105Sjp (void) nanosleep(timeout, NULL); 497c8e26105Sjp break; 498c8e26105Sjp case EINVAL: 499c8e26105Sjp /* 500c8e26105Sjp * Shouldn't happen, except, perhaps, near the 501c8e26105Sjp * end of time 502c8e26105Sjp */ 503c8e26105Sjp timeout->tv_nsec = 0; 504c8e26105Sjp timeout->tv_sec = MAX_CHECK_TIME; 505c8e26105Sjp if (retries-- > 0) 506c8e26105Sjp goto retry; 507c8e26105Sjp /* NOTREACHED */ 508c8e26105Sjp break; 509c8e26105Sjp case EINTR: 510c8e26105Sjp if (!hupped) 511c8e26105Sjp goto retry; 512c8e26105Sjp break; 513c8e26105Sjp case ETIME: 514c8e26105Sjp /* Timeout */ 515c8e26105Sjp break; 516c8e26105Sjp default: 517c8e26105Sjp /* EFAULT */ 518c8e26105Sjp (void) nanosleep(timeout, NULL); 519c8e26105Sjp break; 520c8e26105Sjp } 521c8e26105Sjp } 522c8e26105Sjp 523c8e26105Sjp /* 524c8e26105Sjp * We only have one event that we care about, a user event, so 525c8e26105Sjp * there's nothing to check or clean up about pe. 526c8e26105Sjp * 527c8e26105Sjp * If we get here it's either because we had a SIGHUP and a user 528c8e26105Sjp * event was sent to our port, or because the port_get() timed 529c8e26105Sjp * out (or even both!). 530c8e26105Sjp */ 531c8e26105Sjp 532c8e26105Sjp if (hupped) { 533e3c2d6aaSnw int rc; 534e3c2d6aaSnw 535c8e26105Sjp hupped = 0; 536e3c2d6aaSnw /* 537e3c2d6aaSnw * Blow away the ccache, we might have re-joined the 538e3c2d6aaSnw * domain or joined a new one 539e3c2d6aaSnw */ 540e3c2d6aaSnw (void) unlink(IDMAP_CACHEDIR "/ccache"); 541e3c2d6aaSnw /* HUP is the refresh method, so re-read SMF config */ 542c8e26105Sjp (void) idmapdlog(LOG_INFO, "idmapd: SMF refresh"); 543c8e26105Sjp WRLOCK_CONFIG(); 544c8e26105Sjp (void) idmap_cfg_unload(&_idmapdstate.cfg->pgcfg); 545e3c2d6aaSnw rc = idmap_cfg_load(&_idmapdstate.cfg->handles, 546e3c2d6aaSnw &_idmapdstate.cfg->pgcfg, 1); 547e8c27ec8Sbaban if (rc < -1) 548e3c2d6aaSnw (void) idmapdlog(LOG_ERR, 549e3c2d6aaSnw "idmapd: Various errors re-loading configuration " 550e3c2d6aaSnw "will cause AD lookups to fail"); 551e8c27ec8Sbaban else if (rc == -1) 552e3c2d6aaSnw (void) idmapdlog(LOG_WARNING, 553e3c2d6aaSnw "idmapd: Various errors re-loading configuration " 554e3c2d6aaSnw "may cause AD lookups to fail"); 555c8e26105Sjp UNLOCK_CONFIG(); 556c8e26105Sjp return (1); 557c8e26105Sjp } 558c8e26105Sjp 559c8e26105Sjp return (0); 560c8e26105Sjp } 561c8e26105Sjp 562c8e26105Sjp void * 563c8e26105Sjp idmap_cfg_update_thread(void *arg) 564c8e26105Sjp { 565c8e26105Sjp 566c8e26105Sjp idmap_pg_config_t new_cfg; 567e3c2d6aaSnw int ttl, changed; 568c8e26105Sjp idmap_cfg_handles_t *handles = &_idmapdstate.cfg->handles; 569c8e26105Sjp idmap_pg_config_t *live_cfg = &_idmapdstate.cfg->pgcfg; 570c8e26105Sjp ad_disc_t ad_ctx = handles->ad_ctx; 571c8e26105Sjp struct timespec delay; 572e3c2d6aaSnw int first = 1; 573c8e26105Sjp 574c8e26105Sjp (void) memset(&new_cfg, 0, sizeof (new_cfg)); 575c8e26105Sjp 576c8e26105Sjp for (;;) { 577c8e26105Sjp changed = FALSE; 578e3c2d6aaSnw 579e3c2d6aaSnw if (first) { 580e3c2d6aaSnw ttl = 1; 581e3c2d6aaSnw first = 0; 582e3c2d6aaSnw } else { 583e3c2d6aaSnw ttl = ad_disc_get_TTL(ad_ctx); 584e3c2d6aaSnw } 585e3c2d6aaSnw 586c8e26105Sjp if (ttl > MAX_CHECK_TIME) 587c8e26105Sjp ttl = MAX_CHECK_TIME; 588c8e26105Sjp while (ttl > 0 || ttl == -1) { 589c8e26105Sjp if (ttl == -1) { 590c8e26105Sjp wait_for_ttl(NULL); 591c8e26105Sjp } else if (ttl > SUBNET_CHECK_TIME) { 592c8e26105Sjp /* 593c8e26105Sjp * We really ought to just monitor 594c8e26105Sjp * network interfaces with a PF_ROUTE 595c8e26105Sjp * socket... This crude method of 596c8e26105Sjp * discovering subnet changes will do 597c8e26105Sjp * for now. Though might even not want 598c8e26105Sjp * to bother: subnet changes leading to 599c8e26105Sjp * sitename changes ought never happen, 600c8e26105Sjp * and requiring a refresh when they do 601c8e26105Sjp * should be no problem (SMF/NWAM ought 602c8e26105Sjp * to be able to refresh us). 603c8e26105Sjp */ 604c8e26105Sjp delay.tv_sec = SUBNET_CHECK_TIME; 605c8e26105Sjp delay.tv_nsec = 0; 606c8e26105Sjp if (wait_for_ttl(&delay)) { 607c8e26105Sjp /* Got SIGHUP, re-discover */ 608c8e26105Sjp ttl = 0; 609c8e26105Sjp changed = TRUE; 610c8e26105Sjp break; 611c8e26105Sjp } 612c8e26105Sjp ttl -= SUBNET_CHECK_TIME; 613c8e26105Sjp if (ad_disc_SubnetChanged(ad_ctx)) 614c8e26105Sjp break; 615c8e26105Sjp } else { 616c8e26105Sjp delay.tv_sec = ttl; 617c8e26105Sjp delay.tv_nsec = 0; 618c8e26105Sjp if (wait_for_ttl(&delay)) 619c8e26105Sjp changed = TRUE; 620c8e26105Sjp ttl = 0; 621c8e26105Sjp } 622c8e26105Sjp } 623c8e26105Sjp 624c8e26105Sjp /* 625c8e26105Sjp * Load configuration data into a private copy. 626c8e26105Sjp * 627c8e26105Sjp * The fixed values (i.e., from SMF) have already been 628c8e26105Sjp * set in AD auto discovery, so if all values have been 629c8e26105Sjp * set in SMF and they haven't been changed or the 630c8e26105Sjp * service been refreshed then the rest of this loop's 631c8e26105Sjp * body is one big no-op. 632c8e26105Sjp */ 633c8e26105Sjp pthread_mutex_lock(&handles->mutex); 634c8e26105Sjp 635c8e26105Sjp new_cfg.default_domain = ad_disc_get_DomainName(ad_ctx); 636c8e26105Sjp if (new_cfg.default_domain == NULL) { 637c8e26105Sjp idmapdlog(LOG_INFO, 638c8e26105Sjp "%s: unable to discover Default Domain", me); 639c8e26105Sjp } 640c8e26105Sjp 641c8e26105Sjp new_cfg.domain_name = ad_disc_get_DomainName(ad_ctx); 642c8e26105Sjp if (new_cfg.domain_name == NULL) { 643c8e26105Sjp idmapdlog(LOG_INFO, 644c8e26105Sjp "%s: unable to discover Domain Name", me); 645c8e26105Sjp } 646c8e26105Sjp 647c8e26105Sjp new_cfg.domain_controller = 648c8e26105Sjp ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE); 649c8e26105Sjp if (new_cfg.domain_controller == NULL) { 650c8e26105Sjp idmapdlog(LOG_INFO, 651c8e26105Sjp "%s: unable to discover Domain Controller", me); 652c8e26105Sjp } 653c8e26105Sjp 654c8e26105Sjp new_cfg.forest_name = ad_disc_get_ForestName(ad_ctx); 655c8e26105Sjp if (new_cfg.forest_name == NULL) { 656c8e26105Sjp idmapdlog(LOG_INFO, 657c8e26105Sjp "%s: unable to discover Forest Name", me); 658c8e26105Sjp } 659c8e26105Sjp 660c8e26105Sjp new_cfg.site_name = ad_disc_get_SiteName(ad_ctx); 661c8e26105Sjp if (new_cfg.site_name == NULL) { 662c8e26105Sjp idmapdlog(LOG_INFO, 663c8e26105Sjp "%s: unable to discover Site Name", me); 664c8e26105Sjp } 665c8e26105Sjp 666c8e26105Sjp new_cfg.global_catalog = 667c8e26105Sjp ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE); 668c8e26105Sjp if (new_cfg.global_catalog == NULL) { 669c8e26105Sjp idmapdlog(LOG_INFO, 670c8e26105Sjp "%s: unable to discover Global Catalog", me); 671c8e26105Sjp } 672c8e26105Sjp 673c8e26105Sjp pthread_mutex_unlock(&handles->mutex); 674c8e26105Sjp 675c8e26105Sjp if (new_cfg.default_domain == NULL && 676c8e26105Sjp new_cfg.domain_name == NULL && 677c8e26105Sjp new_cfg.domain_controller == NULL && 678c8e26105Sjp new_cfg.forest_name == NULL && 679c8e26105Sjp new_cfg.global_catalog == NULL) { 680c8e26105Sjp idmapdlog(LOG_NOTICE, "%s: Could not auto-discover AD " 681c8e26105Sjp "domain and forest names nor domain controllers " 682c8e26105Sjp "and global catalog servers", me); 683c8e26105Sjp idmap_cfg_unload(&new_cfg); 684c8e26105Sjp continue; 685c8e26105Sjp } 686c8e26105Sjp 687c8e26105Sjp /* 688c8e26105Sjp * Update the live configuration 689c8e26105Sjp */ 690c8e26105Sjp WRLOCK_CONFIG(); 691c8e26105Sjp 692c8e26105Sjp if (live_cfg->list_size_limit != new_cfg.list_size_limit) { 693c8e26105Sjp idmapdlog(LOG_INFO, "%s: change list_size=%d", me, 694c8e26105Sjp new_cfg.list_size_limit); 695c8e26105Sjp live_cfg->list_size_limit = new_cfg.list_size_limit; 696c8e26105Sjp } 697c8e26105Sjp 698c8e26105Sjp /* 699c8e26105Sjp * If default_domain came from SMF then we must not 700c8e26105Sjp * auto-discover it. 701c8e26105Sjp */ 702c8e26105Sjp if (live_cfg->dflt_dom_set_in_smf == FALSE && 703c8e26105Sjp update_value(&live_cfg->default_domain, 704c8e26105Sjp &new_cfg.default_domain, "default_domain") == TRUE) 705c8e26105Sjp changed = TRUE; 706c8e26105Sjp 707c8e26105Sjp (void) update_value(&live_cfg->domain_name, 708c8e26105Sjp &new_cfg.domain_name, "domain_name"); 709c8e26105Sjp 710c8e26105Sjp (void) update_dirs(&live_cfg->domain_controller, 711c8e26105Sjp &new_cfg.domain_controller, "domain_controller"); 712c8e26105Sjp 713c8e26105Sjp (void) update_value(&live_cfg->forest_name, 714c8e26105Sjp &new_cfg.forest_name, "forest_name"); 715c8e26105Sjp 716c8e26105Sjp (void) update_value(&live_cfg->site_name, 717c8e26105Sjp &new_cfg.site_name, "site_name"); 718c8e26105Sjp 719c8e26105Sjp if (update_dirs(&live_cfg->global_catalog, 720c8e26105Sjp &new_cfg.global_catalog, "global_catalog") == TRUE) 721c8e26105Sjp changed = TRUE; 722c8e26105Sjp UNLOCK_CONFIG(); 723c8e26105Sjp 724c8e26105Sjp idmap_cfg_unload(&new_cfg); 725c8e26105Sjp 726c8e26105Sjp 727c8e26105Sjp /* 728c8e26105Sjp * Re-create the ad_t/ad_host_t objects if 729c8e26105Sjp * either the default domain or the global 730c8e26105Sjp * catalog server list changed. 731c8e26105Sjp */ 732c8e26105Sjp 733c8e26105Sjp if (changed) { 734c8e26105Sjp RDLOCK_CONFIG(); 735c8e26105Sjp (void) reload_ad(); 736c8e26105Sjp UNLOCK_CONFIG(); 737c8e26105Sjp print_idmapdstate(); 738c8e26105Sjp } 739c8e26105Sjp } 740c8e26105Sjp /*NOTREACHED*/ 741c8e26105Sjp return (NULL); 742c8e26105Sjp } 743c8e26105Sjp 744c8e26105Sjp 745c8e26105Sjp int 746c8e26105Sjp idmap_cfg_start_updates(idmap_cfg_t *cfg) 747c8e26105Sjp { 748c8e26105Sjp /* Don't check for failure -- see wait_for_ttl() */ 749c8e26105Sjp hup_ev_port = port_create(); 750c8e26105Sjp 751c8e26105Sjp errno = pthread_create(&update_thread_handle, NULL, 752c8e26105Sjp idmap_cfg_update_thread, NULL); 753c8e26105Sjp if (errno == 0) 754c8e26105Sjp return (0); 755c8e26105Sjp else 756c8e26105Sjp return (-1); 757c8e26105Sjp } 758c8e26105Sjp 759c8e26105Sjp 760c5c4113dSnw int 761e3c2d6aaSnw idmap_cfg_load(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, 762e3c2d6aaSnw int discover) 763c5c4113dSnw { 764e3c2d6aaSnw int rc; 765e3c2d6aaSnw int errors = 0; 766e8c27ec8Sbaban uint8_t bool_val; 767c8e26105Sjp char *str = NULL; 768c8e26105Sjp ad_disc_t ad_ctx = handles->ad_ctx; 769c5c4113dSnw 770c8e26105Sjp pgcfg->list_size_limit = 0; 771c8e26105Sjp pgcfg->default_domain = NULL; 772c8e26105Sjp pgcfg->domain_name = NULL; 773c8e26105Sjp pgcfg->machine_sid = NULL; 774c8e26105Sjp pgcfg->domain_controller = NULL; 775c8e26105Sjp pgcfg->forest_name = NULL; 776c8e26105Sjp pgcfg->site_name = NULL; 777c8e26105Sjp pgcfg->global_catalog = NULL; 778e8c27ec8Sbaban pgcfg->ad_unixuser_attr = NULL; 779e8c27ec8Sbaban pgcfg->ad_unixgroup_attr = NULL; 780e8c27ec8Sbaban pgcfg->nldap_winname_attr = NULL; 781e8c27ec8Sbaban pgcfg->ds_name_mapping_enabled = FALSE; 782c5c4113dSnw 783c8e26105Sjp pthread_mutex_lock(&handles->mutex); 784c8e26105Sjp 785c8e26105Sjp ad_disc_refresh(handles->ad_ctx); 786c8e26105Sjp 787c8e26105Sjp if (scf_pg_update(handles->config_pg) < 0) { 788651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s", 789651c0131Sbaban me, scf_strerror(scf_error())); 790e3c2d6aaSnw rc = -2; 791c8e26105Sjp goto exit; 792c5c4113dSnw } 793c5c4113dSnw 794c8e26105Sjp if (scf_pg_update(handles->general_pg) < 0) { 795651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s", 796651c0131Sbaban me, scf_strerror(scf_error())); 797e3c2d6aaSnw rc = -2; 798c8e26105Sjp goto exit; 799c5c4113dSnw } 800c5c4113dSnw 801c8e26105Sjp rc = get_val_int(handles, "list_size_limit", 802c8e26105Sjp &pgcfg->list_size_limit, SCF_TYPE_COUNT); 803c8e26105Sjp if (rc != 0) { 804e3c2d6aaSnw pgcfg->list_size_limit = 0; 805e3c2d6aaSnw errors++; 806c8e26105Sjp } 807c5c4113dSnw 808c8e26105Sjp rc = get_val_astring(handles, "domain_name", 809c8e26105Sjp &pgcfg->domain_name); 810e3c2d6aaSnw if (rc != 0) 811e3c2d6aaSnw errors++; 812e3c2d6aaSnw else 813e3c2d6aaSnw (void) ad_disc_set_DomainName(ad_ctx, pgcfg->domain_name); 814c8e26105Sjp 815c8e26105Sjp rc = get_val_astring(handles, "default_domain", 816c8e26105Sjp &pgcfg->default_domain); 817c8e26105Sjp if (rc != 0) { 818e3c2d6aaSnw /* 819e3c2d6aaSnw * SCF failures fetching config/default_domain we treat 820e3c2d6aaSnw * as fatal as they may leave ID mapping rules that 821e3c2d6aaSnw * match unqualified winnames flapping in the wind. 822e3c2d6aaSnw */ 823e3c2d6aaSnw rc = -2; 824c8e26105Sjp goto exit; 825c8e26105Sjp } 826c8e26105Sjp 827c8e26105Sjp rc = get_val_astring(handles, "mapping_domain", &str); 828e3c2d6aaSnw if (rc != 0) 829e3c2d6aaSnw errors++; 830c5c4113dSnw 831c5c4113dSnw /* 832c8e26105Sjp * We treat default_domain as having been specified in SMF IFF 833c8e26105Sjp * either (the config/default_domain property was set) or (the 834c8e26105Sjp * old, obsolete, never documented config/mapping_domain 835c8e26105Sjp * property was set and the new config/domain_name property was 836c8e26105Sjp * not set). 837c5c4113dSnw */ 838c8e26105Sjp pgcfg->dflt_dom_set_in_smf = TRUE; 839c8e26105Sjp if (pgcfg->default_domain == NULL) { 840c8e26105Sjp 841c8e26105Sjp pgcfg->dflt_dom_set_in_smf = FALSE; 842c8e26105Sjp 843c8e26105Sjp if (pgcfg->domain_name != NULL) { 844c8e26105Sjp pgcfg->default_domain = strdup(pgcfg->domain_name); 845c8e26105Sjp if (str != NULL) { 846c8e26105Sjp idmapdlog(LOG_WARNING, 847c8e26105Sjp "%s: Ignoring obsolete, undocumented " 848c8e26105Sjp "config/mapping_domain property", me); 849c8e26105Sjp } 850c8e26105Sjp } else if (str != NULL) { 851c8e26105Sjp pgcfg->default_domain = strdup(str); 852c8e26105Sjp pgcfg->dflt_dom_set_in_smf = TRUE; 853c8e26105Sjp idmapdlog(LOG_WARNING, 854c8e26105Sjp "%s: The config/mapping_domain property is " 855c8e26105Sjp "obsolete; support for it will be removed, " 856c8e26105Sjp "please use config/default_domain instead", 857c8e26105Sjp me); 858c5c4113dSnw } 859c5c4113dSnw } 860c5c4113dSnw 861c8e26105Sjp if (str != NULL) 862c8e26105Sjp free(str); 863c8e26105Sjp 864c8e26105Sjp rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); 865e3c2d6aaSnw if (rc != 0) 866e3c2d6aaSnw errors++; 867c8e26105Sjp if (pgcfg->machine_sid == NULL) { 8688edda628Sbaban /* If machine_sid not configured, generate one */ 869c8e26105Sjp if (generate_machine_sid(&pgcfg->machine_sid) < 0) { 870e3c2d6aaSnw rc = -2; 871c8e26105Sjp goto exit; 872c8e26105Sjp } 873c8e26105Sjp rc = set_val_astring(handles, "machine_sid", 874c8e26105Sjp pgcfg->machine_sid); 875e3c2d6aaSnw if (rc != 0) 876e3c2d6aaSnw errors++; 8778edda628Sbaban } 878c5c4113dSnw 879c8e26105Sjp str = NULL; 880c8e26105Sjp rc = get_val_ds(handles, "domain_controller", 389, 881c8e26105Sjp &pgcfg->domain_controller); 882e3c2d6aaSnw if (rc != 0) 883e3c2d6aaSnw errors++; 884e3c2d6aaSnw else 885e3c2d6aaSnw (void) ad_disc_set_DomainController(ad_ctx, 886e3c2d6aaSnw pgcfg->domain_controller); 887c5c4113dSnw 888c8e26105Sjp rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); 889e3c2d6aaSnw if (rc != 0) 890e3c2d6aaSnw errors++; 891e3c2d6aaSnw else 892e3c2d6aaSnw (void) ad_disc_set_ForestName(ad_ctx, pgcfg->forest_name); 893c8e26105Sjp 894c8e26105Sjp rc = get_val_astring(handles, "site_name", &pgcfg->site_name); 895e3c2d6aaSnw if (rc != 0) 896e3c2d6aaSnw errors++; 897e3c2d6aaSnw else 898e3c2d6aaSnw (void) ad_disc_set_SiteName(ad_ctx, pgcfg->site_name); 899c8e26105Sjp 900c8e26105Sjp str = NULL; 901c8e26105Sjp rc = get_val_ds(handles, "global_catalog", 3268, 902c8e26105Sjp &pgcfg->global_catalog); 903e3c2d6aaSnw if (rc != 0) 904e3c2d6aaSnw errors++; 905e3c2d6aaSnw else 906e3c2d6aaSnw (void) ad_disc_set_GlobalCatalog(ad_ctx, pgcfg->global_catalog); 907c8e26105Sjp 908e8c27ec8Sbaban /* 909e8c27ec8Sbaban * Read directory-based name mappings related SMF properties 910e8c27ec8Sbaban */ 911e8c27ec8Sbaban bool_val = 0; 912e8c27ec8Sbaban rc = get_val_int(handles, "ds_name_mapping_enabled", 913e8c27ec8Sbaban &bool_val, SCF_TYPE_BOOLEAN); 914e8c27ec8Sbaban if (rc != 0) { 915e8c27ec8Sbaban rc = -2; 916e8c27ec8Sbaban goto exit; 917e8c27ec8Sbaban } else if (bool_val) { 918e8c27ec8Sbaban pgcfg->ds_name_mapping_enabled = TRUE; 919e8c27ec8Sbaban rc = get_val_astring(handles, "ad_unixuser_attr", 920e8c27ec8Sbaban &pgcfg->ad_unixuser_attr); 921e8c27ec8Sbaban if (rc != 0) { 922e8c27ec8Sbaban rc = -2; 923e8c27ec8Sbaban goto exit; 924e8c27ec8Sbaban } 925e8c27ec8Sbaban 926e8c27ec8Sbaban rc = get_val_astring(handles, "ad_unixgroup_attr", 927e8c27ec8Sbaban &pgcfg->ad_unixgroup_attr); 928e8c27ec8Sbaban if (rc != 0) { 929e8c27ec8Sbaban rc = -2; 930e8c27ec8Sbaban goto exit; 931e8c27ec8Sbaban } 932e8c27ec8Sbaban 933e8c27ec8Sbaban rc = get_val_astring(handles, "nldap_winname_attr", 934e8c27ec8Sbaban &pgcfg->nldap_winname_attr); 935e8c27ec8Sbaban if (rc != 0) { 936e8c27ec8Sbaban rc = -2; 937e8c27ec8Sbaban goto exit; 938e8c27ec8Sbaban } 939e8c27ec8Sbaban 940e8c27ec8Sbaban if (pgcfg->nldap_winname_attr != NULL) { 941e8c27ec8Sbaban idmapdlog(LOG_ERR, 942e8c27ec8Sbaban "%s: native LDAP based name mapping not supported " 943e8c27ec8Sbaban "at this time. Please unset " 944e8c27ec8Sbaban "config/nldap_winname_attr and restart idmapd.", 945e8c27ec8Sbaban me); 946e8c27ec8Sbaban rc = -3; 947e8c27ec8Sbaban goto exit; 948e8c27ec8Sbaban } 949e8c27ec8Sbaban 950e8c27ec8Sbaban if (pgcfg->ad_unixuser_attr == NULL && 951e8c27ec8Sbaban pgcfg->ad_unixgroup_attr == NULL) { 952e8c27ec8Sbaban idmapdlog(LOG_ERR, 953e8c27ec8Sbaban "%s: If config/ds_name_mapping_enabled property " 954e8c27ec8Sbaban "is set to true then atleast one of the following " 955e8c27ec8Sbaban "name mapping attributes must be specified. " 956e8c27ec8Sbaban "(config/ad_unixuser_attr OR " 957e8c27ec8Sbaban "config/ad_unixgroup_attr)", me); 958e8c27ec8Sbaban rc = -3; 959e8c27ec8Sbaban goto exit; 960e8c27ec8Sbaban } 961e8c27ec8Sbaban } 962e8c27ec8Sbaban 963c8e26105Sjp 964e3c2d6aaSnw if (!discover) 965e3c2d6aaSnw goto exit; 966e3c2d6aaSnw 967c8e26105Sjp /* 968c8e26105Sjp * Auto Discover the rest 969c8e26105Sjp */ 970c8e26105Sjp if (pgcfg->default_domain == NULL) { 971c8e26105Sjp pgcfg->default_domain = ad_disc_get_DomainName(ad_ctx); 972c8e26105Sjp if (pgcfg->default_domain == NULL) { 973c8e26105Sjp idmapdlog(LOG_INFO, 974c8e26105Sjp "%s: unable to discover Default Domain", me); 975c8e26105Sjp } 976c8e26105Sjp } 977c8e26105Sjp 978c8e26105Sjp if (pgcfg->domain_name == NULL) { 979c8e26105Sjp pgcfg->domain_name = ad_disc_get_DomainName(ad_ctx); 980c8e26105Sjp if (pgcfg->domain_name == NULL) { 981c8e26105Sjp idmapdlog(LOG_INFO, 982c8e26105Sjp "%s: unable to discover Domain Name", me); 983c8e26105Sjp } 984c8e26105Sjp } 985c8e26105Sjp 986c8e26105Sjp if (pgcfg->domain_controller == NULL) { 987c8e26105Sjp pgcfg->domain_controller = 988c8e26105Sjp ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE); 989c8e26105Sjp if (pgcfg->domain_controller == NULL) { 990c8e26105Sjp idmapdlog(LOG_INFO, 991c8e26105Sjp "%s: unable to discover Domain Controller", me); 992c8e26105Sjp } 993c8e26105Sjp } 994c8e26105Sjp 995c8e26105Sjp if (pgcfg->forest_name == NULL) { 996c8e26105Sjp pgcfg->forest_name = ad_disc_get_ForestName(ad_ctx); 997c8e26105Sjp if (pgcfg->forest_name == NULL) { 998c8e26105Sjp idmapdlog(LOG_INFO, 999c8e26105Sjp "%s: unable to discover Forest Name", me); 1000c8e26105Sjp } 1001c8e26105Sjp } 1002c8e26105Sjp 1003c8e26105Sjp if (pgcfg->site_name == NULL) { 1004c8e26105Sjp pgcfg->site_name = ad_disc_get_SiteName(ad_ctx); 1005c8e26105Sjp if (pgcfg->site_name == NULL) { 1006c8e26105Sjp idmapdlog(LOG_INFO, 1007c8e26105Sjp "%s: unable to discover Site Name", me); 1008c8e26105Sjp } 1009c8e26105Sjp } 1010c8e26105Sjp 1011c8e26105Sjp if (pgcfg->global_catalog == NULL) { 1012c8e26105Sjp pgcfg->global_catalog = 1013c8e26105Sjp ad_disc_get_GlobalCatalog(ad_ctx, AD_DISC_PREFER_SITE); 1014c8e26105Sjp if (pgcfg->global_catalog == NULL) { 1015c8e26105Sjp idmapdlog(LOG_INFO, 1016c8e26105Sjp "%s: unable to discover Global Catalog", me); 1017c8e26105Sjp } 1018c8e26105Sjp } 1019e3c2d6aaSnw 1020c8e26105Sjp exit: 1021c8e26105Sjp pthread_mutex_unlock(&handles->mutex); 1022c5c4113dSnw 1023e8c27ec8Sbaban if (rc < -1) 1024e3c2d6aaSnw return (rc); 1025e3c2d6aaSnw 1026e3c2d6aaSnw return ((errors == 0) ? 0 : -1); 1027c5c4113dSnw } 1028c5c4113dSnw 1029651c0131Sbaban /* 1030651c0131Sbaban * Initialize 'cfg'. 1031651c0131Sbaban */ 1032c5c4113dSnw idmap_cfg_t * 1033*4edd44c5Sjp idmap_cfg_init() 1034*4edd44c5Sjp { 1035c8e26105Sjp idmap_cfg_handles_t *handles; 1036c5c4113dSnw 1037c5c4113dSnw /* First the smf repository handles: */ 1038c5c4113dSnw idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t)); 1039c5c4113dSnw if (!cfg) { 1040651c0131Sbaban idmapdlog(LOG_ERR, "%s: Out of memory", me); 1041c5c4113dSnw return (NULL); 1042c5c4113dSnw } 1043c8e26105Sjp handles = &cfg->handles; 1044c5c4113dSnw 1045c8e26105Sjp (void) pthread_mutex_init(&handles->mutex, NULL); 1046c8e26105Sjp 1047c8e26105Sjp if (!(handles->main = scf_handle_create(SCF_VERSION))) { 1048651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_handle_create() failed: %s", 1049651c0131Sbaban me, scf_strerror(scf_error())); 1050c5c4113dSnw goto error; 1051c5c4113dSnw } 1052c5c4113dSnw 1053c8e26105Sjp if (scf_handle_bind(handles->main) < 0) { 1054651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_handle_bind() failed: %s", 1055651c0131Sbaban me, scf_strerror(scf_error())); 1056c5c4113dSnw goto error; 1057c5c4113dSnw } 1058c5c4113dSnw 1059c8e26105Sjp if (!(handles->service = scf_service_create(handles->main)) || 1060c8e26105Sjp !(handles->instance = scf_instance_create(handles->main)) || 1061c8e26105Sjp !(handles->config_pg = scf_pg_create(handles->main)) || 1062c8e26105Sjp !(handles->general_pg = scf_pg_create(handles->main))) { 1063651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf handle creation failed: %s", 1064651c0131Sbaban me, scf_strerror(scf_error())); 1065c5c4113dSnw goto error; 1066c5c4113dSnw } 1067c5c4113dSnw 1068c8e26105Sjp if (scf_handle_decode_fmri(handles->main, 1069*4edd44c5Sjp FMRI_BASE "/:properties/" CONFIG_PG, 1070*4edd44c5Sjp NULL, /* scope */ 1071*4edd44c5Sjp handles->service, /* service */ 1072*4edd44c5Sjp handles->instance, /* instance */ 1073*4edd44c5Sjp handles->config_pg, /* pg */ 1074*4edd44c5Sjp NULL, /* prop */ 1075*4edd44c5Sjp SCF_DECODE_FMRI_EXACT) < 0) { 1076651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_handle_decode_fmri() failed: %s", 1077651c0131Sbaban me, scf_strerror(scf_error())); 1078c5c4113dSnw goto error; 1079c5c4113dSnw } 1080c5c4113dSnw 1081c8e26105Sjp if (scf_service_get_pg(handles->service, 1082*4edd44c5Sjp GENERAL_PG, handles->general_pg) < 0) { 1083651c0131Sbaban idmapdlog(LOG_ERR, "%s: scf_service_get_pg() failed: %s", 1084651c0131Sbaban me, scf_strerror(scf_error())); 1085c5c4113dSnw goto error; 1086c5c4113dSnw } 1087c5c4113dSnw 1088c8e26105Sjp /* Initialize AD Auto Discovery context */ 1089c8e26105Sjp handles->ad_ctx = ad_disc_init(); 1090c8e26105Sjp if (handles->ad_ctx == NULL) 1091c8e26105Sjp goto error; 1092c8e26105Sjp 1093c5c4113dSnw return (cfg); 1094c5c4113dSnw 1095c5c4113dSnw error: 1096c5c4113dSnw (void) idmap_cfg_fini(cfg); 1097c5c4113dSnw return (NULL); 1098c5c4113dSnw } 1099c5c4113dSnw 1100c8e26105Sjp void 1101*4edd44c5Sjp idmap_cfg_unload(idmap_pg_config_t *pgcfg) 1102*4edd44c5Sjp { 1103c8e26105Sjp 1104c8e26105Sjp if (pgcfg->default_domain) { 1105c8e26105Sjp free(pgcfg->default_domain); 1106c8e26105Sjp pgcfg->default_domain = NULL; 1107c8e26105Sjp } 1108c8e26105Sjp if (pgcfg->domain_name) { 1109c8e26105Sjp free(pgcfg->domain_name); 1110c8e26105Sjp pgcfg->domain_name = NULL; 1111c8e26105Sjp } 1112c8e26105Sjp if (pgcfg->machine_sid) { 1113c8e26105Sjp free(pgcfg->machine_sid); 1114c8e26105Sjp pgcfg->machine_sid = NULL; 1115c8e26105Sjp } 1116c8e26105Sjp if (pgcfg->domain_controller) { 1117c5c4113dSnw free(pgcfg->domain_controller); 1118c8e26105Sjp pgcfg->domain_controller = NULL; 1119c8e26105Sjp } 1120c8e26105Sjp if (pgcfg->forest_name) { 1121c8e26105Sjp free(pgcfg->forest_name); 1122c8e26105Sjp pgcfg->forest_name = NULL; 1123c8e26105Sjp } 1124c8e26105Sjp if (pgcfg->site_name) { 1125c8e26105Sjp free(pgcfg->site_name); 1126c8e26105Sjp pgcfg->site_name = NULL; 1127c8e26105Sjp } 1128c8e26105Sjp if (pgcfg->global_catalog) { 1129c8e26105Sjp free(pgcfg->global_catalog); 1130c8e26105Sjp pgcfg->global_catalog = NULL; 1131c8e26105Sjp } 1132e8c27ec8Sbaban if (pgcfg->ad_unixuser_attr) { 1133e8c27ec8Sbaban free(pgcfg->ad_unixuser_attr); 1134e8c27ec8Sbaban pgcfg->ad_unixuser_attr = NULL; 1135e8c27ec8Sbaban } 1136e8c27ec8Sbaban if (pgcfg->ad_unixgroup_attr) { 1137e8c27ec8Sbaban free(pgcfg->ad_unixgroup_attr); 1138e8c27ec8Sbaban pgcfg->ad_unixgroup_attr = NULL; 1139e8c27ec8Sbaban } 1140e8c27ec8Sbaban if (pgcfg->nldap_winname_attr) { 1141e8c27ec8Sbaban free(pgcfg->nldap_winname_attr); 1142e8c27ec8Sbaban pgcfg->nldap_winname_attr = NULL; 1143e8c27ec8Sbaban } 1144c5c4113dSnw } 1145c5c4113dSnw 1146c5c4113dSnw int 1147c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg) 1148c5c4113dSnw { 1149c8e26105Sjp idmap_cfg_handles_t *handles = &cfg->handles; 1150c8e26105Sjp idmap_cfg_unload(&cfg->pgcfg); 1151c8e26105Sjp 1152c8e26105Sjp (void) pthread_mutex_destroy(&handles->mutex); 1153c8e26105Sjp scf_pg_destroy(handles->config_pg); 1154c8e26105Sjp scf_pg_destroy(handles->general_pg); 1155c8e26105Sjp scf_instance_destroy(handles->instance); 1156c8e26105Sjp scf_service_destroy(handles->service); 1157c8e26105Sjp scf_handle_destroy(handles->main); 1158e8c27ec8Sbaban if (handles->ad_ctx != NULL) 1159e8c27ec8Sbaban ad_disc_fini(handles->ad_ctx); 1160c5c4113dSnw free(cfg); 1161c5c4113dSnw 1162c5c4113dSnw return (0); 1163c5c4113dSnw } 1164