diff options
-rw-r--r-- | src/config/SSSDConfig/__init__.py.in | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-ipa.conf | 1 | ||||
-rw-r--r-- | src/db/sysdb.h | 7 | ||||
-rw-r--r-- | src/db/sysdb_subdomains.c | 166 | ||||
-rw-r--r-- | src/man/sssd-ipa.5.xml | 19 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.c | 26 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.h | 2 | ||||
-rw-r--r-- | src/providers/ipa/ipa_init.c | 4 | ||||
-rw-r--r-- | src/providers/ipa/ipa_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ipa/ipa_subdomains.c | 147 | ||||
-rw-r--r-- | src/providers/ipa/ipa_subdomains.h | 1 |
11 files changed, 358 insertions, 17 deletions
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 6d5a25c19..1f59bd9cb 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -128,6 +128,7 @@ option_strings = { 'ipa_hbac_treat_deny_as' : _("If DENY rules are present, either DENY_ALL or IGNORE"), 'ipa_hbac_support_srchost' : _("If set to false, host argument given by PAM will be ignored"), 'ipa_automount_location' : _("The automounter location this IPA client is using"), + 'ipa_master_domain_search_base': _("Search base for object containing info about IPA domain"), # [provider/krb5] 'krb5_kdcip' : _('Kerberos server address'), diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf index 20eb71f4c..6094a47d4 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -7,6 +7,7 @@ ipa_dyndns_iface = str, None, false ipa_hbac_search_base = str, None, false ipa_host_search_base = str, None, false ipa_subdomains_search_base = str, None, false +ipa_master_domain_search_base = str, None, false ldap_uri = str, None, false ldap_search_base = str, None, false ldap_schema = str, None, false diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 85dde2c49..5867b19c1 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -340,6 +340,13 @@ errno_t sysdb_get_subdomain_context(TALLOC_CTX *mem_ctx, struct sss_domain_info *subdomain, struct sysdb_ctx **subdomain_ctx); +errno_t sysdb_master_domain_get_info(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + struct subdomain_info **info); + +errno_t sysdb_master_domain_add_info(struct sysdb_ctx *sysdb, + struct subdomain_info *domain_info); + errno_t sysdb_search_domuser_by_name(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c index bac846ef7..523a23a5b 100644 --- a/src/db/sysdb_subdomains.c +++ b/src/db/sysdb_subdomains.c @@ -112,6 +112,172 @@ done: return ret; } +errno_t sysdb_master_domain_get_info(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + struct subdomain_info **_info) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *tmp_str; + struct ldb_dn *basedn; + struct subdomain_info *info; + struct ldb_result *res; + const char *attrs[] = {"cn", + SYSDB_SUBDOMAIN_FLAT, + SYSDB_SUBDOMAIN_ID, + NULL}; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + info = talloc_zero(tmp_ctx, struct subdomain_info); + if (info == NULL) { + ret = ENOMEM; + goto done; + } + + basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, + sysdb->domain->name); + if (basedn == NULL) { + ret = EIO; + goto done; + } + ret = ldb_search(sysdb->ldb, tmp_ctx, &res, basedn, LDB_SCOPE_BASE, attrs, + NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + if (res->count != 1) { + DEBUG(SSSDBG_OP_FAILURE, ("Base search returned [%d] results, " + "expected 1.\n")); + ret = EINVAL; + goto done; + } + + tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FLAT, + NULL); + if (tmp_str != NULL) { + info->flat_name = talloc_strdup(info, tmp_str); + if (info->flat_name == NULL) { + ret = ENOMEM; + goto done; + } + } + + tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_ID, + NULL); + if (tmp_str != NULL) { + info->flat_name = talloc_strdup(info, tmp_str); + if (info->flat_name == NULL) { + ret = ENOMEM; + goto done; + } + } + + *_info = talloc_steal(mem_ctx, info); +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t sysdb_master_domain_add_info(struct sysdb_ctx *sysdb, + struct subdomain_info *domain_info) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; + int ret; + bool do_update = false; + struct subdomain_info *current_info; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sysdb_master_domain_get_info(tmp_ctx, sysdb, ¤t_info); + if (ret != EOK) { + goto done; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, + sysdb->domain->name); + if (msg->dn == NULL) { + ret = EIO; + goto done; + } + + if (domain_info->flat_name != NULL && + (current_info->flat_name == NULL || + strcmp(current_info->flat_name, domain_info->flat_name) != 0) ) { + ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT, LDB_FLAG_MOD_REPLACE, + NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_fmt(msg, SYSDB_SUBDOMAIN_FLAT, "%s", + domain_info->flat_name); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret);; + goto done; + } + + do_update = true; + } + + if (domain_info->id != NULL && + (current_info->flat_name == NULL || + strcmp(current_info->flat_name, domain_info->id) != 0) ) { + ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID, LDB_FLAG_MOD_REPLACE, + NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_fmt(msg, SYSDB_SUBDOMAIN_ID, "%s", + domain_info->id); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret);; + goto done; + } + + do_update = true; + } + + if (do_update == false) { + ret = EOK; + goto done; + } + + ret = ldb_modify(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add subdomain attributes to " + "[%s]: [%d][%s]!\n", + domain_info->name, ret, + ldb_errstring(sysdb->ldb))); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} static errno_t sysdb_add_subdomain_attributes(struct sysdb_ctx *sysdb, struct subdomain_info *domain_info) { diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml index 9b8a140ce..a0a57fb54 100644 --- a/src/man/sssd-ipa.5.xml +++ b/src/man/sssd-ipa.5.xml @@ -215,6 +215,25 @@ </varlistentry> <varlistentry> + <term>ipa_master_domain_search_base (string)</term> + <listitem> + <para> + Optional. Use the given string as search base for + master domain object. + </para> + <para> + See <quote>ldap_search_base</quote> for + information about configuring multiple search + bases. + </para> + <para> + Default: the value of + <emphasis>cn=ad,cn=etc,%basedn</emphasis> + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>krb5_validate (boolean)</term> <listitem> <para> diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 262a9bccc..09fbeadc0 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -146,6 +146,9 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx, case IPA_SUBDOMAINS_SEARCH_BASE: class_name = "IPA_SUBDOMAINS"; break; + case IPA_MASTER_DOMAIN_SEARCH_BASE: + class_name = "IPA_MASTER_DOMAIN"; + break; default: DEBUG(SSSDBG_CONF_SETTINGS, ("Unknown search base type: [%d]\n", class)); @@ -513,6 +516,29 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, &ipa_opts->subdomains_search_bases); if (ret != EOK) goto done; + if (NULL == dp_opt_get_string(ipa_opts->basic, + IPA_MASTER_DOMAIN_SEARCH_BASE)) { + value = talloc_asprintf(tmpctx, "cn=ad,cn=etc,%s", basedn); + if (value == NULL) { + ret = ENOMEM; + goto done; + } + + ret = dp_opt_set_string(ipa_opts->basic, IPA_MASTER_DOMAIN_SEARCH_BASE, value); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_CONF_SETTINGS, ("Option %s set to %s\n", + ipa_opts->basic[IPA_MASTER_DOMAIN_SEARCH_BASE].opt_name, + dp_opt_get_string(ipa_opts->basic, + IPA_MASTER_DOMAIN_SEARCH_BASE))); + } + ret = ipa_parse_search_base(ipa_opts, ipa_opts->basic, + IPA_MASTER_DOMAIN_SEARCH_BASE, + &ipa_opts->master_domain_search_bases); + if (ret != EOK) goto done; + ret = sdap_get_map(ipa_opts->id, cdb, conf_path, ipa_attr_map, SDAP_AT_GENERAL, diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 9232260eb..0a18ec1b1 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -42,6 +42,7 @@ enum ipa_basic_opt { IPA_HOST_SEARCH_BASE, IPA_SELINUX_SEARCH_BASE, IPA_SUBDOMAINS_SEARCH_BASE, + IPA_MASTER_DOMAIN_SEARCH_BASE, IPA_KRB5_REALM, IPA_HBAC_REFRESH, IPA_HBAC_DENY_METHOD, @@ -125,6 +126,7 @@ struct ipa_options { struct sdap_search_base **hbac_search_bases; struct sdap_search_base **selinux_search_bases; struct sdap_search_base **subdomains_search_bases; + struct sdap_search_base **master_domain_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 90acb1082..b58058a8e 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -522,7 +522,7 @@ int sssm_ipa_autofs_init(struct be_ctx *bectx, int sssm_ipa_subdomains_init(struct be_ctx *bectx, struct bet_ops **ops, - void **pvt_data) + void **pvt_data) { int ret; struct ipa_subdomains_ctx *subdomains_ctx; @@ -541,7 +541,7 @@ int sssm_ipa_subdomains_init(struct be_ctx *bectx, } subdomains_ctx->sdap_id_ctx = id_ctx->sdap_id_ctx; subdomains_ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases; - + subdomains_ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases; *ops = &ipa_subdomains_ops; *pvt_data = subdomains_ctx; diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index f688f765c..770406cfe 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -39,6 +39,7 @@ struct dp_option ipa_basic_opts[] = { { "ipa_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_selinux_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_subdomains_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ipa_master_domain_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING}, { "ipa_hbac_refresh", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER }, { "ipa_hbac_treat_deny_as", DP_OPT_STRING, { "DENY_ALL" }, NULL_STRING }, diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index da9785f2c..185b3c523 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -27,10 +27,24 @@ #include "providers/ipa/ipa_common.h" #define SUBDOMAINS_FILTER "objectclass=ipaNTTrustedDomain" +#define MASTER_DOMAIN_FILTER "objectclass=ipaNTDomainAttrs" + #define IPA_CN "cn" #define IPA_FLATNAME "ipaNTFlatName" #define IPA_SID "ipaNTTrustedDomainSID" +enum ipa_subdomains_req_type { + IPA_SUBDOMAINS_MASTER, + IPA_SUBDOMAINS_SLAVE, + + IPA_SUBDOMAINS_MAX /* Counter */ +}; + +struct ipa_subdomains_req_params { + const char *filter; + tevent_req_fn cb; +}; + static void ipa_subdomains_reply(struct be_req *be_req, int dp_err, int result) { be_req->fn(be_req, dp_err, result, NULL); @@ -131,8 +145,16 @@ struct ipa_subdomains_req_ctx { }; static void ipa_subdomains_get_conn_done(struct tevent_req *req); -static errno_t ipa_subdomains_handler_next(struct ipa_subdomains_req_ctx *ctx); +static errno_t +ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, + enum ipa_subdomains_req_type type); static void ipa_subdomains_handler_done(struct tevent_req *req); +static void ipa_subdomains_handler_master_done(struct tevent_req *req); + +static struct ipa_subdomains_req_params subdomain_requests[] = { + { MASTER_DOMAIN_FILTER, ipa_subdomains_handler_master_done }, + { SUBDOMAINS_FILTER, ipa_subdomains_handler_done } +}; void ipa_subdomains_handler(struct be_req *be_req) { @@ -208,7 +230,7 @@ static void ipa_subdomains_get_conn_done(struct tevent_req *req) goto fail; } - ret = ipa_subdomains_handler_next(ctx); + ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE); if (ret != EOK && ret != EAGAIN) { goto fail; } @@ -221,23 +243,31 @@ fail: ipa_subdomains_reply(be_req, dp_error, ret); } -static errno_t ipa_subdomains_handler_next(struct ipa_subdomains_req_ctx *ctx) +static errno_t +ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, + enum ipa_subdomains_req_type type) { struct tevent_req *req; struct sdap_search_base *base; - const char *attrs[] = {"cn", - "ipaNTFlatName", - "ipaNTTrustedDomainSID", + struct ipa_subdomains_req_params *params; + const char *attrs[] = {IPA_CN, + IPA_FLATNAME, + IPA_SID, NULL}; + if (type >= IPA_SUBDOMAINS_MAX) { + return EINVAL; + } + + params = &subdomain_requests[type]; + base = ctx->search_bases[ctx->search_base_iter]; if (base == NULL) { return EOK; } talloc_free(ctx->current_filter); - ctx->current_filter = sdap_get_id_specific_filter(ctx, SUBDOMAINS_FILTER, - base->filter); + ctx->current_filter = sdap_get_id_specific_filter(ctx, params->filter, base->filter); if (ctx->current_filter == NULL) { return ENOMEM; } @@ -255,7 +285,7 @@ static errno_t ipa_subdomains_handler_next(struct ipa_subdomains_req_ctx *ctx) return ENOMEM; } - tevent_req_set_callback(req, ipa_subdomains_handler_done, ctx); + tevent_req_set_callback(req, params->cb, ctx); return EAGAIN; } @@ -263,13 +293,15 @@ static errno_t ipa_subdomains_handler_next(struct ipa_subdomains_req_ctx *ctx) static void ipa_subdomains_handler_done(struct tevent_req *req) { int ret; - struct be_req *be_req; size_t reply_count; struct sysdb_attrs **reply = NULL; struct ipa_subdomains_req_ctx *ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx); + struct be_req *be_req = ctx->be_req; + struct sysdb_ctx *sysdb; + struct subdomain_info *domain_info; - be_req = ctx->be_req; + sysdb = (be_req->sysdb)?be_req->sysdb:be_req->be_ctx->sysdb; ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply); talloc_zfree(req); @@ -291,7 +323,7 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) } ctx->search_base_iter++; - ret = ipa_subdomains_handler_next(ctx); + ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE); if (ret == EAGAIN) { return; } else if (ret != EOK) { @@ -304,14 +336,99 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) goto done; } - ret = sysdb_update_subdomains(ctx->sd_ctx->sdap_id_ctx->be->sysdb, - ctx->sd_data->domain_list); + ret = sysdb_update_subdomains(sysdb, ctx->sd_data->domain_list); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_subdomains failed.\n")); goto done; } - ret = EOK; + ret = sysdb_master_domain_get_info(ctx, sysdb, &domain_info); + if (ret != EOK) { + goto done; + } + + if (domain_info->flat_name == NULL || + domain_info->id == NULL || + domain_info->name == NULL) { + + ctx->search_base_iter = 0; + ctx->search_bases = ctx->sd_ctx->master_search_bases; + ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + } else { + ret = EOK; + } + +done: + talloc_free(ctx); + ipa_subdomains_reply(be_req, (ret == EOK ? DP_ERR_OK : DP_ERR_FATAL), ret); +} + +static void ipa_subdomains_handler_master_done(struct tevent_req *req) +{ + errno_t ret; + size_t reply_count; + struct sysdb_attrs **reply = NULL; + struct ipa_subdomains_req_ctx *ctx = tevent_req_callback_data(req, + struct ipa_subdomains_req_ctx); + struct be_req *be_req = ctx->be_req; + struct subdomain_info *domain_info; + const char *tmp_str; + + ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply); + talloc_zfree(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n")); + goto done; + } + + if (reply_count) { + domain_info = talloc_zero(ctx, struct subdomain_info); + if (domain_info == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_get_string(reply[0], IPA_FLATNAME, &tmp_str); + if (ret != EOK) goto done; + domain_info->flat_name = talloc_strdup(domain_info, tmp_str); + if (domain_info->flat_name == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_get_string(reply[0], IPA_SID, &tmp_str); + if (ret != EOK) { + goto done; + } + domain_info->id = talloc_strdup(domain_info, tmp_str); + if (domain_info->flat_name == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_master_domain_add_info(be_req->be_ctx->sysdb, domain_info); + goto done; + } else { + ctx->search_base_iter++; + ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + + /* Right now we know there has been an error + * and we don't have the master domain record + */ + DEBUG(SSSDBG_CRIT_FAILURE, ("Master domain record not found!\n")); + ret = EIO; + goto done; + } done: talloc_free(ctx); diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h index be62b1525..76406f122 100644 --- a/src/providers/ipa/ipa_subdomains.h +++ b/src/providers/ipa/ipa_subdomains.h @@ -31,6 +31,7 @@ struct ipa_subdomains_ctx { struct sdap_id_ctx *sdap_id_ctx; struct sdap_search_base **search_bases; + struct sdap_search_base **master_search_bases; }; |