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