From a38dc696383d3b0a25896a8a6298fe9b56c2d8ed Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Tue, 15 May 2012 06:33:13 -0400
Subject: [PATCH 1/2] IPA subdomains - ask for information about master domain

The query is performed only if there is missing information in the
cache. That means this should be done only once after restart when cache
doesn't exist. All subsequent requests for subdomains won't include the
request for master domain.

https://fedorahosted.org/sssd/ticket/1351
---
 src/db/sysdb.h                     |    7 ++
 src/db/sysdb_subdomains.c          |  166 ++++++++++++++++++++++++++++++++++++
 src/providers/ipa/ipa_common.c     |   48 ++++++++++
 src/providers/ipa/ipa_common.h     |    2 +
 src/providers/ipa/ipa_init.c       |    4 +-
 src/providers/ipa/ipa_opts.h       |    1 +
 src/providers/ipa/ipa_subdomains.c |  149 +++++++++++++++++++++++++++++---
 src/providers/ipa/ipa_subdomains.h |    1 +
 8 files changed, 361 insertions(+), 17 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index a0d176ec7f9c04b467caf7b2c38ffc6fb263497b..c28b71b2705ef93352ca69a50d1c300b9c1dfc60 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -338,6 +338,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 bac846ef7df380bd129f34b2c50a057e7f4617cd..523a23a5b8e0c2d9db2d08233861b7d9b3923897 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/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 262a9bccc1c9f113202a60f5ba551018d3d07f7f..fb1a91e58be5c33748baa283ac517848d91eace2 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,51 @@ 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;
+    if (NULL == dp_opt_get_string(ipa_opts->basic,
+                                  IPA_SUBDOMAINS_SEARCH_BASE)) {
+        value = talloc_asprintf(tmpctx, "cn=trusts,%s", basedn);
+        if (value == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = dp_opt_set_string(ipa_opts->basic, IPA_SUBDOMAINS_SEARCH_BASE, value);
+        if (ret != EOK) {
+            goto done;
+        }
+
+        DEBUG(SSSDBG_CONF_SETTINGS, ("Option %s set to %s\n",
+                  ipa_opts->basic[IPA_SUBDOMAINS_SEARCH_BASE].opt_name,
+                  dp_opt_get_string(ipa_opts->basic,
+                                    IPA_SUBDOMAINS_SEARCH_BASE)));
+    }
+    ret = ipa_parse_search_base(ipa_opts, ipa_opts->basic,
+                                IPA_SUBDOMAINS_SEARCH_BASE,
+                                &ipa_opts->subdomains_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 9232260eb8790e6d1c87818d7c36d78c60974f20..0a18ec1b1da1ec7cd2862a40a48df2c3fc1e7007 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 90acb1082ec47f4b10c8b04c15a7fc1eaba92fe3..b58058a8e50af289683e12127b71a5b2a2494ea7 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 f688f765c988fa79d2ae97fcdfbeee0bd3fa523b..770406cfebe67ba5104163986a29f4a1a9f34869 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 da9785f2c2aac3e9bddf6c2fc49e9aae63303591..93540e84ef50930cd7f8a9c7c6ca490bd3d0565c 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,101 @@ 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;
+    struct sysdb_ctx *sysdb;
+
+    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;
+        }
+
+        sysdb = (be_req->sysdb)?be_req->sysdb:be_req->be_ctx->sysdb;
+        ret = sysdb_master_domain_add_info(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 be62b15251df55eab957ba6d5bb0baebd9ba1ad2..76406f1221eb015474dedfb1175872c36ecb95bf 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;
 };
 
 
-- 
1.7.7.6

