diff options
Diffstat (limited to 'usr/src/cmd/idmap/idmapd/idmap_config.c')
| -rw-r--r-- | usr/src/cmd/idmap/idmapd/idmap_config.c | 438 |
1 files changed, 313 insertions, 125 deletions
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.c b/usr/src/cmd/idmap/idmapd/idmap_config.c index 493802af5b..e11d0f8d47 100644 --- a/usr/src/cmd/idmap/idmapd/idmap_config.c +++ b/usr/src/cmd/idmap/idmapd/idmap_config.c @@ -58,6 +58,13 @@ static pthread_t update_thread_handle = 0; static int idmapd_ev_port = -1; static int rt_sock = -1; +struct enum_lookup_map directory_mapping_map[] = { + { DIRECTORY_MAPPING_NONE, "none" }, + { DIRECTORY_MAPPING_NAME, "name" }, + { DIRECTORY_MAPPING_IDMU, "idmu" }, + { 0, NULL }, +}; + static int generate_machine_sid(char **machine_sid) { @@ -71,7 +78,7 @@ generate_machine_sid(char **machine_sid) * machine_sid will be of the form S-1-5-21-N1-N2-N3 (that's * four RIDs altogether). * - * Technically we could use upto 14 random RIDs here, but it + * Technically we could use up to 14 random RIDs here, but it * turns out that with some versions of Windows using SIDs with * more than five RIDs in security descriptors causes problems. */ @@ -107,7 +114,7 @@ generate_machine_sid(char **machine_sid) /* In the case of error, exists is set to FALSE anyway */ static int -prop_exists(idmap_cfg_handles_t *handles, char *name, boolean_t *exists) +prop_exists(idmap_cfg_handles_t *handles, const char *name, boolean_t *exists) { scf_property_t *scf_prop; @@ -140,17 +147,18 @@ prop_exists(idmap_cfg_handles_t *handles, char *name, boolean_t *exists) /* Check if in the case of failure the original value of *val is preserved */ static int -get_val_int(idmap_cfg_handles_t *handles, char *name, +get_val_int(idmap_cfg_handles_t *handles, const char *name, void *val, scf_type_t type) { int rc = 0; scf_property_t *scf_prop; scf_value_t *value; + uint8_t b; switch (type) { case SCF_TYPE_BOOLEAN: - *(uint8_t *)val = 0; + *(boolean_t *)val = B_FALSE; break; case SCF_TYPE_COUNT: *(uint64_t *)val = 0; @@ -189,7 +197,8 @@ get_val_int(idmap_cfg_handles_t *handles, char *name, switch (type) { case SCF_TYPE_BOOLEAN: - rc = scf_value_get_boolean(value, val); + rc = scf_value_get_boolean(value, &b); + *(boolean_t *)val = b; break; case SCF_TYPE_COUNT: rc = scf_value_get_count(value, val); @@ -197,8 +206,15 @@ get_val_int(idmap_cfg_handles_t *handles, char *name, case SCF_TYPE_INTEGER: rc = scf_value_get_integer(value, val); break; + default: + abort(); /* tested above */ + /* NOTREACHED */ } + if (rc != 0) { + idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", + name, scf_strerror(scf_error())); + } destruction: scf_value_destroy(value); @@ -208,43 +224,25 @@ destruction: } static char * -scf_value2string(scf_value_t *value) +scf_value2string(const char *name, scf_value_t *value) { - int rc = -1; - char buf_size = 127; - int length; - char *buf = NULL; - buf = (char *) malloc(sizeof (char) * buf_size); + static size_t max_val = 0; - for (;;) { - length = scf_value_get_astring(value, buf, buf_size); - if (length < 0) { - rc = -1; - goto destruction; - } + if (max_val == 0) + max_val = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); - if (length == buf_size - 1) { - buf_size *= 2; - buf = (char *)realloc(buf, buf_size * sizeof (char)); - if (!buf) { - idmapdlog(LOG_ERR, "Out of memory"); - rc = -1; - goto destruction; - } - } else { - rc = 0; - break; - } + char buf[max_val + 1]; + if (scf_value_get_astring(value, buf, max_val + 1) < 0) { + idmapdlog(LOG_ERR, "Can not retrieve config/%s: %s", + name, scf_strerror(scf_error())); + return (NULL); } -destruction: - if (rc < 0) { - if (buf) - free(buf); - buf = NULL; - } + char *s = strdup(buf); + if (s == NULL) + idmapdlog(LOG_ERR, "Out of memory"); - return (buf); + return (s); } static int @@ -327,7 +325,7 @@ restart: servers[i].priority = 0; servers[i].weight = 100; servers[i].port = defport; - if ((host = scf_value2string(value)) == NULL) { + if ((host = scf_value2string(name, value)) == NULL) { goto destruction; } if ((portstr = strchr(host, ':')) != NULL) { @@ -367,7 +365,7 @@ destruction: static int -get_val_astring(idmap_cfg_handles_t *handles, char *name, char **val) +get_val_astring(idmap_cfg_handles_t *handles, const char *name, char **val) { int rc = 0; @@ -402,7 +400,8 @@ get_val_astring(idmap_cfg_handles_t *handles, char *name, char **val) goto destruction; } - if (!(*val = scf_value2string(value))) + *val = scf_value2string(name, value); + if (*val == NULL) rc = -1; destruction: @@ -420,7 +419,77 @@ destruction: static int -set_val_astring(idmap_cfg_handles_t *handles, char *name, const char *val) +del_val(idmap_cfg_handles_t *handles, const char *name) +{ + int rc = -1; + int ret; + scf_transaction_t *tx = NULL; + scf_transaction_entry_t *ent = NULL; + + if ((tx = scf_transaction_create(handles->main)) == NULL) { + idmapdlog(LOG_ERR, + "scf_transaction_create() failed: %s", + scf_strerror(scf_error())); + goto destruction; + } + if ((ent = scf_entry_create(handles->main)) == NULL) { + idmapdlog(LOG_ERR, + "scf_entry_create() failed: %s", + scf_strerror(scf_error())); + goto destruction; + } + + do { + if (scf_pg_update(handles->config_pg) == -1) { + idmapdlog(LOG_ERR, + "scf_pg_update(%s) failed: %s", + name, scf_strerror(scf_error())); + goto destruction; + } + if (scf_transaction_start(tx, handles->config_pg) != 0) { + idmapdlog(LOG_ERR, + "scf_transaction_start(%s) failed: %s", + name, scf_strerror(scf_error())); + goto destruction; + } + + if (scf_transaction_property_delete(tx, ent, name) != 0) { + /* Don't complain if it already doesn't exist. */ + if (scf_error() != SCF_ERROR_NOT_FOUND) { + idmapdlog(LOG_ERR, + "scf_transaction_property_delete() failed:" + " %s", + scf_strerror(scf_error())); + } + goto destruction; + } + + ret = scf_transaction_commit(tx); + + if (ret == 0) + scf_transaction_reset(tx); + } while (ret == 0); + + if (ret == -1) { + idmapdlog(LOG_ERR, + "scf_transaction_commit(%s) failed: %s", + name, scf_strerror(scf_error())); + goto destruction; + } + + rc = 0; + +destruction: + if (ent != NULL) + scf_entry_destroy(ent); + if (tx != NULL) + scf_transaction_destroy(tx); + return (rc); +} + + +static int +set_val_astring(idmap_cfg_handles_t *handles, const char *name, const char *val) { int rc = -1; int ret = -2; @@ -549,6 +618,18 @@ update_string(char **value, char **new, char *name) return (1); } +static int +update_enum(int *value, int *new, char *name, struct enum_lookup_map *map) +{ + if (*value == *new) + return (0); + + idmapdlog(LOG_INFO, "change %s=%s", name, enum_lookup(*new, map)); + + *value = *new; + + return (1); +} /* * This function updates a directory service structure. @@ -801,6 +882,16 @@ not_equal: return (1); } +const char * +enum_lookup(int value, struct enum_lookup_map *map) +{ + for (; map->string != NULL; map++) { + if (value == map->value) { + return (map->string); + } + } + return ("(invalid)"); +} #define MAX_CHECK_TIME (20 * 60) @@ -1030,6 +1121,32 @@ valid_ldap_attr(const char *attr) { return (1); } +static +int +check_smf_debug_mode(idmap_cfg_handles_t *handles) +{ + boolean_t new_debug_mode; + int rc; + + rc = prop_exists(handles, "debug", &new_debug_mode); + if (rc != 0) + return (rc); + + if (_idmapdstate.debug_mode != new_debug_mode) { + if (!_idmapdstate.debug_mode) { + _idmapdstate.debug_mode = new_debug_mode; + idmap_log_stderr(LOG_DEBUG); + idmapdlog(LOG_DEBUG, "debug mode enabled"); + } else { + idmapdlog(LOG_DEBUG, "debug mode disabled"); + idmap_log_stderr(-1); + _idmapdstate.debug_mode = new_debug_mode; + } + } + + return (0); +} + /* * This is the half of idmap_cfg_load() that loads property values from * SMF (using the config/ property group of the idmap FMRI). @@ -1041,12 +1158,12 @@ valid_ldap_attr(const char *attr) { static int idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, - int *errors) + int * const errors) { int rc; - uint8_t bool_val; - char *str = NULL; - boolean_t new_debug_mode; + char *s; + + *errors = 0; if (scf_pg_update(handles->config_pg) < 0) { idmapdlog(LOG_ERR, "scf_pg_update() failed: %s", @@ -1060,37 +1177,42 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, return (-2); } - - rc = prop_exists(handles, "debug", &new_debug_mode); + rc = check_smf_debug_mode(handles); if (rc != 0) - errors++; - - if (_idmapdstate.debug_mode != new_debug_mode) { - if (!_idmapdstate.debug_mode) { - _idmapdstate.debug_mode = new_debug_mode; - idmap_log_stderr(LOG_DEBUG); - idmapdlog(LOG_DEBUG, "debug mode enabled"); - } else { - idmapdlog(LOG_DEBUG, "debug mode disabled"); - idmap_log_stderr(-1); - _idmapdstate.debug_mode = new_debug_mode; - } - } + (*errors)++; rc = get_val_int(handles, "unresolvable_sid_mapping", &pgcfg->eph_map_unres_sids, SCF_TYPE_BOOLEAN); if (rc != 0) - errors++; + (*errors)++; + + rc = get_val_astring(handles, "directory_based_mapping", &s); + if (rc != 0) + (*errors)++; + else if (s == NULL || strcasecmp(s, "none") == 0) + pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; + else if (strcasecmp(s, "name") == 0) + pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NAME; + else if (strcasecmp(s, "idmu") == 0) + pgcfg->directory_based_mapping = DIRECTORY_MAPPING_IDMU; + else { + pgcfg->directory_based_mapping = DIRECTORY_MAPPING_NONE; + idmapdlog(LOG_ERR, + "config/directory_based_mapping: invalid value \"%s\" ignored", + s); + (*errors)++; + } + free(s); rc = get_val_int(handles, "list_size_limit", &pgcfg->list_size_limit, SCF_TYPE_COUNT); if (rc != 0) - errors++; + (*errors)++; rc = get_val_astring(handles, "domain_name", &pgcfg->domain_name); if (rc != 0) - errors++; + (*errors)++; else { (void) ad_disc_set_DomainName(handles->ad_ctx, pgcfg->domain_name); @@ -1108,45 +1230,13 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, return (-2); } - rc = get_val_astring(handles, "mapping_domain", &str); - if (rc != 0) - errors++; - - /* - * We treat default_domain as having been specified in SMF IFF - * either (the config/default_domain property was set) or (the - * old, obsolete, never documented config/mapping_domain - * property was set and the new config/domain_name property was - * not set). - */ - pgcfg->dflt_dom_set_in_smf = B_TRUE; - if (pgcfg->default_domain == NULL) { - - pgcfg->dflt_dom_set_in_smf = B_FALSE; - - if (pgcfg->domain_name != NULL) { - pgcfg->default_domain = strdup(pgcfg->domain_name); - if (str != NULL) { - idmapdlog(LOG_WARNING, - "Ignoring obsolete, undocumented " - "config/mapping_domain property"); - } - } else if (str != NULL) { - pgcfg->default_domain = strdup(str); - pgcfg->dflt_dom_set_in_smf = B_TRUE; - idmapdlog(LOG_WARNING, - "The config/mapping_domain property is " - "obsolete; support for it will be removed, " - "please use config/default_domain instead"); - } + if (pgcfg->default_domain == NULL && pgcfg->domain_name != NULL) { + pgcfg->default_domain = strdup(pgcfg->domain_name); } - if (str != NULL) - free(str); - rc = get_val_astring(handles, "machine_sid", &pgcfg->machine_sid); if (rc != 0) - errors++; + (*errors)++; if (pgcfg->machine_sid == NULL) { /* If machine_sid not configured, generate one */ if (generate_machine_sid(&pgcfg->machine_sid) < 0) @@ -1154,14 +1244,13 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, rc = set_val_astring(handles, "machine_sid", pgcfg->machine_sid); if (rc != 0) - errors++; + (*errors)++; } - str = NULL; rc = get_val_ds(handles, "domain_controller", 389, &pgcfg->domain_controller); if (rc != 0) - errors++; + (*errors)++; else { (void) ad_disc_set_DomainController(handles->ad_ctx, pgcfg->domain_controller); @@ -1170,7 +1259,7 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, rc = get_val_astring(handles, "forest_name", &pgcfg->forest_name); if (rc != 0) - errors++; + (*errors)++; else { (void) ad_disc_set_ForestName(handles->ad_ctx, pgcfg->forest_name); @@ -1179,33 +1268,24 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, rc = get_val_astring(handles, "site_name", &pgcfg->site_name); if (rc != 0) - errors++; + (*errors)++; else (void) ad_disc_set_SiteName(handles->ad_ctx, pgcfg->site_name); - str = NULL; rc = get_val_ds(handles, "global_catalog", 3268, &pgcfg->global_catalog); if (rc != 0) - errors++; + (*errors)++; else { (void) ad_disc_set_GlobalCatalog(handles->ad_ctx, pgcfg->global_catalog); pgcfg->global_catalog_auto_disc = B_FALSE; } - /* - * Read directory-based name mappings related SMF properties - */ - rc = get_val_int(handles, "ds_name_mapping_enabled", - &bool_val, SCF_TYPE_BOOLEAN); - if (rc != 0) - return (-2); - - if (!bool_val) - return (rc); + /* Unless we're doing directory-based name mapping, we're done. */ + if (pgcfg->directory_based_mapping != DIRECTORY_MAPPING_NAME) + return (0); - pgcfg->ds_name_mapping_enabled = B_TRUE; rc = get_val_astring(handles, "ad_unixuser_attr", &pgcfg->ad_unixuser_attr); if (rc != 0) @@ -1242,8 +1322,8 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, pgcfg->ad_unixgroup_attr == NULL && pgcfg->nldap_winname_attr == NULL) { idmapdlog(LOG_ERR, - "If config/ds_name_mapping_enabled property is set to " - "true then atleast one of the following name mapping " + "If config/directory_based_mapping property is set to " + "\"name\" then at least one of the following name mapping " "attributes must be specified. (config/ad_unixuser_attr OR " "config/ad_unixgroup_attr OR config/nldap_winname_attr)"); return (-3); @@ -1474,7 +1554,7 @@ int idmap_cfg_load(idmap_cfg_t *cfg, int flags) { int rc = 0; - int errors = 0; + int errors; int changed = 0; int ad_reload_required = 0; idmap_pg_config_t new_pgcfg, *live_pgcfg; @@ -1504,10 +1584,9 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags) changed += update_bool(&live_pgcfg->eph_map_unres_sids, &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); - changed += live_pgcfg->ds_name_mapping_enabled != - new_pgcfg.ds_name_mapping_enabled; - live_pgcfg->ds_name_mapping_enabled = - new_pgcfg.ds_name_mapping_enabled; + changed += update_enum(&live_pgcfg->directory_based_mapping, + &new_pgcfg.directory_based_mapping, "directory_based_mapping", + directory_mapping_map); changed += update_string(&live_pgcfg->ad_unixuser_attr, &new_pgcfg.ad_unixuser_attr, "ad_unixuser_attr"); @@ -1519,9 +1598,8 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags) &new_pgcfg.nldap_winname_attr, "nldap_winname_attr"); /* Props that can be discovered and set in SMF updated here */ - if (!live_pgcfg->dflt_dom_set_in_smf) - changed += update_string(&live_pgcfg->default_domain, - &new_pgcfg.default_domain, "default_domain"); + changed += update_string(&live_pgcfg->default_domain, + &new_pgcfg.default_domain, "default_domain"); changed += update_string(&live_pgcfg->domain_name, &new_pgcfg.domain_name, "domain_name"); @@ -1657,6 +1735,9 @@ idmap_cfg_init() goto error; } + if (check_smf_debug_mode(handles) != 0) + goto error; + /* Initialize AD Auto Discovery context */ handles->ad_ctx = ad_disc_init(); if (handles->ad_ctx == NULL) @@ -1756,3 +1837,110 @@ idmap_cfg_hup_handler(int sig) if (idmapd_ev_port >= 0) (void) port_send(idmapd_ev_port, RECONFIGURE, NULL); } + +/* + * Upgrade the DS mapping flags. + * + * If the old ds_name_mapping_enabled flag is present, then + * if the new directory_based_mapping value is present, then + * if the two are compatible, delete the old and note it + * else delete the old and warn + * else + * set the new based on the old, and note it + * delete the old + */ +static +int +upgrade_directory_mapping(idmap_cfg_handles_t *handles) +{ + boolean_t legacy_ds_name_mapping_present; + const char DS_NAME_MAPPING_ENABLED[] = "ds_name_mapping_enabled"; + const char DIRECTORY_BASED_MAPPING[] = "directory_based_mapping"; + int rc; + + rc = prop_exists(handles, DS_NAME_MAPPING_ENABLED, + &legacy_ds_name_mapping_present); + + if (rc != 0) + return (rc); + + if (!legacy_ds_name_mapping_present) + return (0); + + boolean_t legacy_ds_name_mapping_enabled; + rc = get_val_int(handles, DS_NAME_MAPPING_ENABLED, + &legacy_ds_name_mapping_enabled, SCF_TYPE_BOOLEAN); + if (rc != 0) + return (rc); + + char *legacy_mode; + char *legacy_bool_string; + if (legacy_ds_name_mapping_enabled) { + legacy_mode = "name"; + legacy_bool_string = "true"; + } else { + legacy_mode = "none"; + legacy_bool_string = "false"; + } + + char *directory_based_mapping; + rc = get_val_astring(handles, DIRECTORY_BASED_MAPPING, + &directory_based_mapping); + if (rc != 0) + return (rc); + + if (directory_based_mapping == NULL) { + idmapdlog(LOG_INFO, + "Upgrading old %s=%s setting\n" + "to %s=%s.", + DS_NAME_MAPPING_ENABLED, legacy_bool_string, + DIRECTORY_BASED_MAPPING, legacy_mode); + rc = set_val_astring(handles, DIRECTORY_BASED_MAPPING, + legacy_mode); + if (rc != 0) + return (rc); + } else { + boolean_t new_name_mapping; + if (strcasecmp(directory_based_mapping, "name") == 0) + new_name_mapping = B_TRUE; + else + new_name_mapping = B_FALSE; + + if (legacy_ds_name_mapping_enabled == new_name_mapping) { + idmapdlog(LOG_INFO, + "Automatically removing old %s=%s setting\n" + "in favor of %s=%s.", + DS_NAME_MAPPING_ENABLED, legacy_bool_string, + DIRECTORY_BASED_MAPPING, directory_based_mapping); + } else { + idmapdlog(LOG_WARNING, + "Removing conflicting %s=%s setting\n" + "in favor of %s=%s.", + DS_NAME_MAPPING_ENABLED, legacy_bool_string, + DIRECTORY_BASED_MAPPING, directory_based_mapping); + } + free(directory_based_mapping); + } + + rc = del_val(handles, DS_NAME_MAPPING_ENABLED); + if (rc != 0) + return (rc); + + return (0); +} + +/* + * Do whatever is necessary to upgrade idmap's configuration before + * we load it. + */ +int +idmap_cfg_upgrade(idmap_cfg_t *cfg) +{ + int rc; + + rc = upgrade_directory_mapping(&cfg->handles); + if (rc != 0) + return (rc); + + return (0); +} |
