From a2525ccdcd232330109ad196f64a034ce88f56f4 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 16 Sep 2014 15:26:24 +0200 Subject: IPA: add view support --- src/db/sysdb.h | 4 + src/providers/ipa/ipa_common.c | 44 ++++++++++ src/providers/ipa/ipa_common.h | 27 ++++++ src/providers/ipa/ipa_init.c | 6 ++ src/providers/ipa/ipa_opts.h | 23 +++++ src/providers/ipa/ipa_subdomains.c | 166 ++++++++++++++++++++++++++++++++++--- 6 files changed, 260 insertions(+), 10 deletions(-) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index fca2aec2a..9c4e04ad8 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -142,6 +142,10 @@ #define SYSDB_VIEW_CLASS "view" #define SYSDB_VIEW_NAME "viewName" +#define SYSDB_OVERRIDE_CLASS "overrride" +#define SYSDB_OVERRIDE_ANCHOR_UUID "overrideAnchorUUID" +#define SYSDB_OVERRIDE_USER_CLASS "userOverride" +#define SYSDB_OVERRIDE_GROUP_CLASS "groupOverride" #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index f594de27a..2940a42cc 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -149,6 +149,9 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx, case IPA_RANGES_SEARCH_BASE: class_name = "IPA_RANGES"; break; + case IPA_VIEWS_SEARCH_BASE: + class_name = "IPA_VIEWS"; + break; default: DEBUG(SSSDBG_CONF_SETTINGS, "Unknown search base type: [%d]\n", class); @@ -530,6 +533,29 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, &ipa_opts->ranges_search_bases); if (ret != EOK) goto done; + if (NULL == dp_opt_get_string(ipa_opts->basic, + IPA_VIEWS_SEARCH_BASE)) { + value = talloc_asprintf(tmpctx, "cn=views,cn=accounts,%s", basedn); + if (value == NULL) { + ret = ENOMEM; + goto done; + } + + ret = dp_opt_set_string(ipa_opts->basic, IPA_VIEWS_SEARCH_BASE, value); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n", + ipa_opts->basic[IPA_VIEWS_SEARCH_BASE].opt_name, + dp_opt_get_string(ipa_opts->basic, + IPA_VIEWS_SEARCH_BASE)); + } + ret = ipa_parse_search_base(ipa_opts, ipa_opts->basic, + IPA_VIEWS_SEARCH_BASE, + &ipa_opts->views_search_bases); + if (ret != EOK) goto done; + ret = sdap_get_map(ipa_opts->id, cdb, conf_path, ipa_attr_map, SDAP_AT_GENERAL, @@ -611,6 +637,24 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, goto done; } + ret = sdap_get_map(ipa_opts->id, + cdb, conf_path, + ipa_view_map, + IPA_OPTS_VIEW, + &ipa_opts->view_map); + if (ret != EOK) { + goto done; + } + + ret = sdap_get_map(ipa_opts->id, + cdb, conf_path, + ipa_override_map, + IPA_OPTS_OVERRIDE, + &ipa_opts->override_map); + if (ret != EOK) { + goto done; + } + ret = EOK; *_opts = ipa_opts->id; diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 0b8a17c53..2207604b7 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -53,6 +53,7 @@ enum ipa_basic_opt { IPA_RANGES_SEARCH_BASE, IPA_ENABLE_DNS_SITES, IPA_SERVER_MODE, + IPA_VIEWS_SEARCH_BASE, IPA_OPTS_BASIC /* opts counter */ }; @@ -107,6 +108,28 @@ enum ipa_selinux_usermap_attrs { IPA_OPTS_SELINUX_USERMAP /* attrs counter */ }; +enum ipa_view_attrs { + IPA_OC_VIEW = 0, + IPA_AT_VIEW_NAME, + + IPA_OPTS_VIEW +}; + +enum ipa_override_attrs { + IPA_OC_OVERRIDE = 0, + IPA_AT_OVERRIDE_ANCHOR_UUID, + IPA_AT_OVERRIDE_USER_NAME, + IPA_AT_OVERRIDE_UID_NUMBER, + IPA_AT_OVERRIDE_USER_GID_NUMBER, + IPA_AT_OVERRIDE_GECOS, + IPA_AT_OVERRIDE_HOMEDIR, + IPA_AT_OVERRIDE_SHELL, + IPA_AT_OVERRIDE_GROUP, + IPA_AT_OVERRIDE_GROUP_GID_NUMBER, + + IPA_OPTS_OVERRIDE +}; + struct ipa_auth_ctx { struct krb5_ctx *krb5_auth_ctx; struct sdap_id_ctx *sdap_id_ctx; @@ -120,6 +143,7 @@ struct ipa_id_ctx { struct sdap_id_ctx *sdap_id_ctx; struct ipa_options *ipa_options; + char *view_name; /* Only used with server mode */ struct ipa_server_mode_ctx *server_mode; }; @@ -130,6 +154,8 @@ struct ipa_options { struct sdap_attr_map *host_map; struct sdap_attr_map *hostgroup_map; struct sdap_attr_map *selinuxuser_map; + struct sdap_attr_map *view_map; + struct sdap_attr_map *override_map; struct sdap_search_base **host_search_bases; struct sdap_search_base **hbac_search_bases; @@ -137,6 +163,7 @@ struct ipa_options { struct sdap_search_base **subdomains_search_bases; struct sdap_search_base **master_domain_search_bases; struct sdap_search_base **ranges_search_bases; + struct sdap_search_base **views_search_bases; struct ipa_service *service; /* id provider */ diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index c1a9cc71d..51d8b1e3d 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -244,6 +244,12 @@ int sssm_ipa_id_init(struct be_ctx *bectx, server_mode = dp_opt_get_bool(ipa_options->basic, IPA_SERVER_MODE); if (server_mode == true) { + ipa_ctx->view_name = talloc_strdup(ipa_ctx, "default"); + if (ipa_ctx->view_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); if (srv_in_server_list(ipa_servers) == true || dp_opt_get_bool(ipa_options->basic, diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 30cb96b3d..4785e0164 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -50,6 +50,7 @@ struct dp_option ipa_basic_opts[] = { { "ipa_ranges_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_enable_dns_sites", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "ipa_server_mode", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ipa_views_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, DP_OPTION_TERMINATOR }; @@ -263,6 +264,28 @@ struct sdap_attr_map ipa_selinux_user_map[] = { SDAP_ATTR_MAP_TERMINATOR }; +struct sdap_attr_map ipa_view_map[] = { + { "ipa_view_class", "nsContainer", SYSDB_VIEW_CLASS, NULL}, + { "ipa_view_name", "cn", SYSDB_VIEW_NAME, NULL}, + SDAP_ATTR_MAP_TERMINATOR +}; + +struct sdap_attr_map ipa_override_map[] = { + { "ipa_overide_object_class", "ipaOverrideAnchor", SYSDB_OVERRIDE_CLASS, NULL}, + { "ipa_anchor_uuid", "ipaAnchorUUID", SYSDB_OVERRIDE_ANCHOR_UUID, NULL}, + { "ipa_user_override_object_class", "ipaUserOverride", SYSDB_OVERRIDE_USER_CLASS, NULL}, + { "ipa_group_override_object_class", "ipaGroupOverride", SYSDB_OVERRIDE_GROUP_CLASS, NULL}, + { "ldap_user_name", "uid", SYSDB_NAME, NULL }, + { "ldap_user_uid_number", "uidNumber", SYSDB_UIDNUM, NULL }, + { "ldap_user_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, + { "ldap_user_gecos", "gecos", SYSDB_GECOS, NULL }, + { "ldap_user_home_directory", "homeDirectory", SYSDB_HOMEDIR, NULL }, + { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL }, + { "ldap_group_name", "cn", SYSDB_NAME, NULL }, + { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, + SDAP_ATTR_MAP_TERMINATOR +}; + struct dp_option ipa_def_krb5_opts[] = { { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 524504846..1fe4c4d8d 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -44,6 +44,9 @@ #define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID" #define OBJECTCLASS "objectClass" +#define IPA_ASSIGNED_ID_VIEW "ipaAssignedIDView" +#define DEFAULT_VIEW "default" + /* do not refresh more often than every 5 seconds for now */ #define IPA_SUBDOMAIN_REFRESH_LIMIT 5 @@ -70,6 +73,7 @@ struct ipa_subdomains_ctx { struct sdap_search_base **search_bases; struct sdap_search_base **master_search_bases; struct sdap_search_base **ranges_search_bases; + struct sdap_search_base **host_search_bases; time_t last_refreshed; struct tevent_timer *timer_event; @@ -943,6 +947,111 @@ ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, return EAGAIN; } +static void ipa_get_view_name_done(struct tevent_req *req); +static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx); + +static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx) +{ + struct tevent_req *req; + struct sdap_search_base *base; + const char *attrs[] = {IPA_CN, OBJECTCLASS, NULL}; + struct sdap_attr_map_info *maps; + + maps = talloc_zero(ctx, struct sdap_attr_map_info); + if (maps == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + return ENOMEM; + } + maps->map = ctx->sd_ctx->id_ctx->ipa_options->view_map; + maps->num_attrs = IPA_OPTS_VIEW; + + base = ctx->search_bases[ctx->search_base_iter]; + if (base == NULL) { + return EOK; + } + + req = sdap_deref_search_with_filter_send(ctx, ctx->sd_ctx->be_ctx->ev, + ctx->sd_ctx->sdap_id_ctx->opts, + sdap_id_op_handle(ctx->sdap_op), + base->basedn, + ctx->current_filter, IPA_ASSIGNED_ID_VIEW, attrs, + 1, maps, + dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic, + SDAP_SEARCH_TIMEOUT)); + + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n"); + return ENOMEM; + } + + tevent_req_set_callback(req, ipa_get_view_name_done, ctx); + + return EAGAIN; +} + +static void ipa_get_view_name_done(struct tevent_req *req) +{ + int ret; + struct ipa_subdomains_req_ctx *ctx; + size_t reply_count; + struct sdap_deref_attrs **reply = NULL; + const char *view_name; + int dp_error = DP_ERR_FATAL; + + ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx); + + ret = sdap_deref_search_recv(req, ctx, &reply_count, &reply); + talloc_zfree(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_view_name request failed.\n"); + goto done; + } + + if (reply_count == 0) { + ctx->search_base_iter++; + ret = ipa_get_view_name(ctx); + if (ret == EAGAIN) { + return; + } else if (ret == EOK) { + DEBUG(SSSDBG_TRACE_ALL, "No view found, using default"); + view_name = DEFAULT_VIEW; + } else { + goto done; + } + } else if (reply_count > 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "get_view_name request returned more than one object.\n"); + ret = EINVAL; + goto done; + } + + ret = sysdb_attrs_get_string(reply[0]->attrs, SYSDB_VIEW_NAME, &view_name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, "Found view name [%s].\n", view_name); + + ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain, view_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add/update view name to sysdb.\n"); + } + + ret = ipa_check_master(ctx); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + +done: + if (ret == EOK) { + dp_error = DP_ERR_OK; + } + be_req_terminate(ctx->be_req, dp_error, ret, NULL); +} + static void ipa_subdomains_handler_done(struct tevent_req *req) { int ret; @@ -1005,9 +1114,51 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) } } + ctx->search_base_iter = 0; + ctx->search_bases = ctx->sd_ctx->host_search_bases; + talloc_zfree(ctx->current_filter); + ctx->current_filter = talloc_asprintf(ctx, "(&(objectClass=%s)(%s=%s))", + ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_OC_HOST].name, + ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_AT_HOST_FQDN].name, + dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic, + IPA_HOSTNAME)); + if (ctx->current_filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = ipa_get_view_name(ctx); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + + ret = ipa_check_master(ctx); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + +done: + if (ret == EOK) { + dp_error = DP_ERR_OK; + } + be_req_terminate(ctx->be_req, dp_error, ret, NULL); +} + +static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx) +{ + int ret; + struct sss_domain_info *domain; + + domain = ctx->sd_ctx->be_ctx->domain; + ret = sysdb_master_domain_update(domain); if (ret != EOK) { - goto done; + return ret; } if (domain->flat_name == NULL || @@ -1018,19 +1169,13 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) ctx->search_bases = ctx->sd_ctx->master_search_bases; ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER); if (ret == EAGAIN) { - return; + return EAGAIN; } else if (ret != EOK) { - goto done; + return ret; } - } else { - ret = EOK; } -done: - if (ret == EOK) { - dp_error = DP_ERR_OK; - } - be_req_terminate(ctx->be_req, dp_error, ret, NULL); + return EOK; } @@ -1328,6 +1473,7 @@ int ipa_subdom_init(struct be_ctx *be_ctx, ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases; ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases; ctx->ranges_search_bases = id_ctx->ipa_options->ranges_search_bases; + ctx->host_search_bases = id_ctx->ipa_options->host_search_bases; ctx->configured_explicit = configured_explicit; ctx->disabled_until = 0; *ops = &ipa_subdomains_ops; -- cgit