summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config/SSSDConfig/__init__.py.in1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ipa.conf1
-rw-r--r--src/db/sysdb.h7
-rw-r--r--src/db/sysdb_subdomains.c166
-rw-r--r--src/man/sssd-ipa.5.xml19
-rw-r--r--src/providers/ipa/ipa_common.c26
-rw-r--r--src/providers/ipa/ipa_common.h2
-rw-r--r--src/providers/ipa/ipa_init.c4
-rw-r--r--src/providers/ipa/ipa_opts.h1
-rw-r--r--src/providers/ipa/ipa_subdomains.c147
-rw-r--r--src/providers/ipa/ipa_subdomains.h1
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, &current_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;
};