[SSSD] [PATCH] Look up trusted users directly with AD ID calls if IPA server mode is on

Jakub Hrozek jhrozek at redhat.com
Fri Jun 28 16:43:48 UTC 2013


Hi,

the attached patches implement
https://fedorahosted.org/sssd/ticket/1962. When a new option,
ipa_server_mode is set to True, then subdomain/trusted users are not
looked up using the extop plugin but AD ID context is initialized and
the users are looked up directly with AD code. This is in support of
legacy clients looking up trusted AD users and groups.
-------------- next part --------------
>From 1ba92ead20df70e51677b76b9bf26192288e1ec7 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 17 Jun 2013 09:32:07 +0200
Subject: [PATCH 1/8] IPA: Add a server mode option

https://fedorahosted.org/sssd/ticket/1993

SSSD needs to know that it is running on an IPA server and should not
look up trusted users and groups with the help of the extdom plugin
but do the lookups on its own. For this a new boolean configuration
option, is introduced which defaults to false but is set to true during
ipa-server-install or during updates of the FreeIPA server if it is not
already set.
---
 src/config/etc/sssd.api.d/sssd-ipa.conf |  1 +
 src/man/sssd-ipa.5.xml                  | 19 +++++++++++++++++++
 src/providers/ipa/ipa_common.h          |  1 +
 src/providers/ipa/ipa_opts.h            |  1 +
 4 files changed, 22 insertions(+)

diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 8a7e75f2a820e5fac604201586257342787d4a01..bc14fbe3d4153bd7a7ca4ffe0351edf0b8c02ee4 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -128,6 +128,7 @@ ldap_idmap_default_domain_sid = str, None, false
 ldap_groups_use_matching_rule_in_chain = bool, None, false
 ldap_initgroups_use_matching_rule_in_chain = bool, None, false
 ldap_rfc2307_fallback_to_local_users = bool, None, false
+ipa_server_mode = bool, None, false
 
 [provider/ipa/auth]
 krb5_ccachedir = str, None, false
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index a0c2c3460ac714cd849c176866723eaf90e9920a..2eebe70ffd40060f6aefe072da2b0717fc0d52c4 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -457,6 +457,7 @@
                         </para>
                     </listitem>
                 </varlistentry>
+
                 <varlistentry>
                     <term>ipa_hbac_support_srchost (boolean)</term>
                     <listitem>
@@ -475,6 +476,24 @@
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>ipa_server_mode (boolean)</term>
+                    <listitem>
+                        <para>
+                            This options should only be set by the IPA
+                            installer.
+                        </para>
+                        <para>
+                            The option denotes that the SSSD is running on
+                            IPA server and should perform lookups of users
+                            and groups from trusted domains differently.
+                        </para>
+                        <para>
+                            Default: false
+                        </para>
+                    </listitem>
+                </varlistentry>
+
                 <varlistentry condition="with_autofs">
                     <term>ipa_automount_location (string)</term>
                     <listitem>
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 6dacdc570a5718d5cb1b2076d1d70816f68e2956..b3e719ee7248445d4d64ed979c7f35188b892867 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -50,6 +50,7 @@ enum ipa_basic_opt {
     IPA_AUTOMOUNT_LOCATION,
     IPA_RANGES_SEARCH_BASE,
     IPA_ENABLE_DNS_SITES,
+    IPA_SERVER_MODE,
 
     IPA_OPTS_BASIC /* opts counter */
 };
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 139008b1a2df925f7ddfb3efc91fd23adf3cde2d..9babca73f4cf2e48ec7dff085870fa69429053df 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -48,6 +48,7 @@ struct dp_option ipa_basic_opts[] = {
     { "ipa_automount_location", DP_OPT_STRING, { "default" }, NULL_STRING },
     { "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 },
     DP_OPTION_TERMINATOR
 };
 
-- 
1.8.3.1

-------------- next part --------------
>From b2c5896a96ff058d249493a4e60571a9113446f3 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 19:06:14 +0300
Subject: [PATCH 2/8] LDAP: Add utility function sdap_copy_map

The AD subdomains will only use default options values. This patch
introduces a new utility function sdap_copy_map() that copies the
default options map.

Subtask of:
https://fedorahosted.org/sssd/ticket/1962
---
 src/providers/ldap/sdap.c | 28 ++++++++++++++++++++++++++++
 src/providers/ldap/sdap.h |  5 +++++
 2 files changed, 33 insertions(+)

diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 0492be05d78b78967989ecd783d92ce94315c551..c3db622fcf71c6e36d20dac4f06249e7dcd88cb6 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -28,6 +28,34 @@
 
 /* =Retrieve-Options====================================================== */
 
+int sdap_copy_map(TALLOC_CTX *memctx,
+                 struct sdap_attr_map *src_map,
+                 int num_entries,
+                 struct sdap_attr_map **_map)
+{
+    struct sdap_attr_map *map;
+    int i;
+
+    map = talloc_array(memctx, struct sdap_attr_map, num_entries);
+    if (!map) {
+        return ENOMEM;
+    }
+
+    for (i = 0; i < num_entries; i++) {
+        map[i].opt_name = src_map[i].opt_name;
+        map[i].def_name = src_map[i].def_name;
+        map[i].name = discard_const(src_map[i].def_name);
+        map[i].sys_name = src_map[i].sys_name;
+
+        DEBUG(SSSDBG_TRACE_FUNC, ("Option %s has%s value %s\n",
+              map[i].opt_name, map[i].name ? "" : " no",
+              map[i].name ? map[i].name : ""));
+    }
+
+    *_map = map;
+    return EOK;
+}
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 9fbe04b6a7071b82cc0170e7d8b371898b20a8a7..24d208a2e62dc088821d866e5b1411c94397e232 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -438,6 +438,11 @@ struct sdap_deref_attrs {
     struct sysdb_attrs *attrs;
 };
 
+int sdap_copy_map(TALLOC_CTX *memctx,
+                 struct sdap_attr_map *src_map,
+                 int num_entries,
+                 struct sdap_attr_map **_map);
+
 int sdap_get_map(TALLOC_CTX *memctx,
                  struct confdb_ctx *cdb,
                  const char *conf_path,
-- 
1.8.3.1

-------------- next part --------------
>From 65396f06ed1a9ea54d258be092b37ab6569b4256 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 17 Jun 2013 18:32:53 +0200
Subject: [PATCH 3/8] AD: decouple ad_id_ctx initialization

The IPA subdomain code will perform lookups on its own in the server
mode. For this, the AD provider must offer a way to initialize the
ad_id_ctx for external consumers.

Subtask of:
https://fedorahosted.org/sssd/ticket/1962
---
 src/providers/ad/ad_common.c | 350 +++++++++++++++++++++++++++++++++----------
 src/providers/ad/ad_common.h |   7 +
 src/providers/ad/ad_init.c   |  30 ++--
 3 files changed, 285 insertions(+), 102 deletions(-)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index b06691206f319bf2988f6b56c4d052e02aff423d..2f87bc63ea237e768e550deb7ffe3319d3cf6daf 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -29,6 +29,214 @@ struct ad_server_data {
     bool gc;
 };
 
+errno_t ad_set_search_bases(struct sdap_options *id_opts);
+static errno_t ad_set_ad_id_options(struct ad_options *ad_opts,
+                                    struct sdap_options *id_opts);
+
+static struct sdap_options *
+ad_create_default_sdap_options(TALLOC_CTX *mem_ctx)
+{
+    struct sdap_options *id_opts;
+    errno_t ret;
+
+    id_opts = talloc_zero(mem_ctx, struct sdap_options);
+    if (!id_opts) {
+        return NULL;
+    }
+
+    ret = dp_copy_options(id_opts,
+                          ad_def_ldap_opts,
+                          SDAP_OPTS_BASIC,
+                          &id_opts->basic);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* Get sdap option maps */
+
+    /* General Attribute Map */
+    ret = sdap_copy_map(id_opts,
+                       ad_2008r2_attr_map,
+                       SDAP_AT_GENERAL,
+                       &id_opts->gen_map);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* User map */
+    ret = sdap_copy_map(id_opts,
+                       ad_2008r2_user_map,
+                       SDAP_OPTS_USER,
+                       &id_opts->user_map);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* Group map */
+    ret = sdap_copy_map(id_opts,
+                       ad_2008r2_group_map,
+                       SDAP_OPTS_GROUP,
+                       &id_opts->group_map);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* Netgroup map */
+    ret = sdap_copy_map(id_opts,
+                       ad_netgroup_map,
+                       SDAP_OPTS_NETGROUP,
+                       &id_opts->netgroup_map);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* Services map */
+    ret = sdap_copy_map(id_opts,
+                       ad_service_map,
+                       SDAP_OPTS_SERVICES,
+                       &id_opts->service_map);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    return id_opts;
+
+fail:
+    talloc_free(id_opts);
+    return NULL;
+}
+
+struct ad_options *
+ad_create_default_options(TALLOC_CTX *mem_ctx,
+                          const char *realm,
+                          const char *hostname)
+{
+    struct ad_options *ad_options;
+    errno_t ret;
+
+    ad_options = talloc_zero(mem_ctx, struct ad_options);
+    if (ad_options == NULL) return NULL;
+
+    ret = dp_copy_options(ad_options,
+                          ad_basic_opts,
+                          AD_OPTS_BASIC,
+                          &ad_options->basic);
+    if (ret != EOK) {
+        talloc_free(ad_options);
+        return NULL;
+    }
+
+    ad_options->id = ad_create_default_sdap_options(ad_options);
+    if (ad_options->id == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD LDAP options\n"));
+        talloc_free(ad_options);
+        return NULL;
+    }
+
+    ret = dp_opt_set_string(ad_options->basic, AD_KRB5_REALM, realm);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n"));
+        talloc_free(ad_options);
+        return NULL;
+    }
+
+    ret = dp_opt_set_string(ad_options->basic, AD_HOSTNAME, hostname);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n"));
+        talloc_free(ad_options);
+        return NULL;
+    }
+
+    ret = ad_set_ad_id_options(ad_options, ad_options->id);
+    if (ret != EOK) {
+        talloc_free(ad_options);
+        return NULL;
+    }
+
+    return ad_options;
+}
+
+static errno_t
+ad_create_sdap_options(TALLOC_CTX *mem_ctx,
+                       struct confdb_ctx *cdb,
+                       const char *conf_path,
+                       struct sdap_options **_id_opts)
+{
+    struct sdap_options *id_opts;
+    errno_t ret;
+
+    id_opts = talloc_zero(mem_ctx, struct sdap_options);
+    if (!id_opts) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = dp_get_options(id_opts, cdb, conf_path,
+                         ad_def_ldap_opts,
+                         SDAP_OPTS_BASIC,
+                         &id_opts->basic);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* Get sdap option maps */
+
+    /* General Attribute Map */
+    ret = sdap_get_map(id_opts,
+                       cdb, conf_path,
+                       ad_2008r2_attr_map,
+                       SDAP_AT_GENERAL,
+                       &id_opts->gen_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* User map */
+    ret = sdap_get_map(id_opts,
+                       cdb, conf_path,
+                       ad_2008r2_user_map,
+                       SDAP_OPTS_USER,
+                       &id_opts->user_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* Group map */
+    ret = sdap_get_map(id_opts,
+                       cdb, conf_path,
+                       ad_2008r2_group_map,
+                       SDAP_OPTS_GROUP,
+                       &id_opts->group_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* Netgroup map */
+    ret = sdap_get_map(id_opts,
+                       cdb, conf_path,
+                       ad_netgroup_map,
+                       SDAP_OPTS_NETGROUP,
+                       &id_opts->netgroup_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* Services map */
+    ret = sdap_get_map(id_opts,
+                       cdb, conf_path,
+                       ad_service_map,
+                       SDAP_OPTS_SERVICES,
+                       &id_opts->service_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    ret = EOK;
+    *_id_opts = id_opts;
+done:
+    return ret;
+}
+
 errno_t
 ad_get_common_options(TALLOC_CTX *mem_ctx,
                       struct confdb_ctx *cdb,
@@ -576,49 +784,14 @@ done:
     return;
 }
 
-errno_t
-ad_set_search_bases(struct sdap_options *id_opts);
-
-errno_t
-ad_get_id_options(struct ad_options *ad_opts,
-                   struct confdb_ctx *cdb,
-                   const char *conf_path,
-                   struct sdap_options **_opts)
+static errno_t
+ad_set_ad_id_options(struct ad_options *ad_opts,
+                     struct sdap_options *id_opts)
 {
     errno_t ret;
-    TALLOC_CTX *tmp_ctx;
-    struct sdap_options *id_opts;
     char *krb5_realm;
     char *keytab_path;
 
-    tmp_ctx = talloc_new(NULL);
-    if (!tmp_ctx) return ENOMEM;
-
-    id_opts = talloc_zero(tmp_ctx, struct sdap_options);
-    if (!id_opts) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    ret = sdap_domain_add(id_opts,
-                          ad_opts->id_ctx->sdap_id_ctx->be->domain,
-                          NULL);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    ret = dp_get_options(id_opts, cdb, conf_path,
-                         ad_def_ldap_opts,
-                         SDAP_OPTS_BASIC,
-                         &id_opts->basic);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    /* Set up search bases if they were assigned explicitly */
-    ret = ad_set_search_bases(id_opts);
-    if (ret != EOK) goto done;
-
     /* We only support Kerberos password policy with AD, so
      * force that on.
      */
@@ -671,64 +844,49 @@ ad_get_id_options(struct ad_options *ad_opts,
     /* fix schema to AD  */
     id_opts->schema_type = SDAP_SCHEMA_AD;
 
-    /* Get sdap option maps */
+    ad_opts->id = id_opts;
+    ret = EOK;
+done:
+    return ret;
+}
 
-    /* General Attribute Map */
-    ret = sdap_get_map(id_opts,
-                       cdb, conf_path,
-                       ad_2008r2_attr_map,
-                       SDAP_AT_GENERAL,
-                       &id_opts->gen_map);
-    if (ret != EOK) {
-        goto done;
-    }
+errno_t
+ad_get_id_options(struct ad_options *ad_opts,
+                  struct confdb_ctx *cdb,
+                  const char *conf_path,
+                  struct sdap_options **_opts)
+{
+    struct sdap_options *id_opts;
+    errno_t ret;
 
-    /* User map */
-    ret = sdap_get_map(id_opts,
-                       cdb, conf_path,
-                       ad_2008r2_user_map,
-                       SDAP_OPTS_USER,
-                       &id_opts->user_map);
+    ret = ad_create_sdap_options(ad_opts, cdb, conf_path, &id_opts);
     if (ret != EOK) {
-        goto done;
+        return ENOMEM;
     }
 
-    /* Group map */
-    ret = sdap_get_map(id_opts,
-                       cdb, conf_path,
-                       ad_2008r2_group_map,
-                       SDAP_OPTS_GROUP,
-                       &id_opts->group_map);
+    ret = ad_set_ad_id_options(ad_opts, id_opts);
     if (ret != EOK) {
-        goto done;
+        talloc_free(id_opts);
+        return ret;
     }
 
-    /* Netgroup map */
-    ret = sdap_get_map(id_opts,
-                       cdb, conf_path,
-                       ad_netgroup_map,
-                       SDAP_OPTS_NETGROUP,
-                       &id_opts->netgroup_map);
+    ret = sdap_domain_add(id_opts,
+                          ad_opts->id_ctx->sdap_id_ctx->be->domain,
+                          NULL);
     if (ret != EOK) {
-        goto done;
+        talloc_free(id_opts);
+        return ret;
     }
 
-    /* Services map */
-    ret = sdap_get_map(id_opts,
-                       cdb, conf_path,
-                       ad_service_map,
-                       SDAP_OPTS_SERVICES,
-                       &id_opts->service_map);
+    /* Set up search bases if they were assigned explicitly */
+    ret = ad_set_search_bases(id_opts);
     if (ret != EOK) {
-        goto done;
+        talloc_free(id_opts);
+        return ret;
     }
 
-    ad_opts->id = talloc_steal(ad_opts, id_opts);
     *_opts = id_opts;
-    ret = EOK;
-done:
-    talloc_free(tmp_ctx);
-    return ret;
+    return EOK;
 }
 
 errno_t
@@ -898,3 +1056,33 @@ errno_t ad_get_dyndns_options(struct be_ctx *be_ctx,
 
     return EOK;
 }
+
+
+struct ad_id_ctx *
+ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx)
+{
+    struct sdap_id_ctx *sdap_ctx;
+    struct ad_id_ctx *ad_ctx;
+
+    ad_ctx = talloc_zero(ad_opts, struct ad_id_ctx);
+    if (ad_ctx == NULL) {
+        return NULL;
+    }
+    ad_ctx->ad_options = ad_opts;
+
+    sdap_ctx = sdap_id_ctx_new(ad_ctx, bectx, ad_opts->service->sdap);
+    if (sdap_ctx == NULL) {
+        talloc_free(ad_ctx);
+        return NULL;
+    }
+    ad_ctx->sdap_id_ctx = sdap_ctx;
+    ad_ctx->ldap_ctx = sdap_ctx->conn;
+
+    ad_ctx->gc_ctx = sdap_id_ctx_conn_add(sdap_ctx, ad_opts->service->gc);
+    if (ad_ctx->gc_ctx == NULL) {
+        talloc_free(ad_ctx);
+        return NULL;
+    }
+
+    return ad_ctx;
+}
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 500f49c783d488e217955fad2472177fbf733de5..11075423c15854a236e0acabbdcce4551b6097b2 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -82,6 +82,10 @@ ad_get_common_options(TALLOC_CTX *mem_ctx,
                       struct sss_domain_info *dom,
                       struct ad_options **_opts);
 
+struct ad_options *ad_create_default_options(TALLOC_CTX *mem_ctx,
+                                             const char *realm,
+                                             const char *hostname);
+
 errno_t
 ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
                  const char *primary_servers,
@@ -104,6 +108,9 @@ errno_t
 ad_get_dyndns_options(struct be_ctx *be_ctx,
                       struct ad_options *ad_opts);
 
+struct ad_id_ctx *
+ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx);
+
 /* AD dynamic DNS updates */
 errno_t ad_dyndns_init(struct be_ctx *be_ctx,
                        struct ad_options *ctx);
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 5c6b6f5c84afc3597ff2a65e91e20d2fb7e69f9a..5efe05e6424784484ebbad0a950849fc128bc81d 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -109,7 +109,6 @@ sssm_ad_id_init(struct be_ctx *bectx,
 {
     errno_t ret;
     struct ad_id_ctx *ad_ctx;
-    struct sdap_id_ctx *sdap_ctx;
     const char *hostname;
     const char *ad_domain;
     struct ad_srv_plugin_ctx *srv_ctx;
@@ -128,26 +127,14 @@ sssm_ad_id_init(struct be_ctx *bectx,
         return EOK;
     }
 
-    ad_ctx = talloc_zero(ad_options, struct ad_id_ctx);
+
+    ad_ctx = ad_id_ctx_init(ad_options, bectx);
     if (ad_ctx == NULL) {
         return ENOMEM;
     }
-    ad_ctx->ad_options = ad_options;
     ad_options->id_ctx = ad_ctx;
 
-    sdap_ctx = sdap_id_ctx_new(ad_options, bectx, ad_options->service->sdap);
-    if (sdap_ctx == NULL) {
-        return ENOMEM;
-    }
-    ad_ctx->sdap_id_ctx = sdap_ctx;
-    ad_ctx->ldap_ctx = sdap_ctx->conn;
-
-    ad_ctx->gc_ctx = sdap_id_ctx_conn_add(sdap_ctx, ad_options->service->gc);
-    if (ad_ctx->gc_ctx == NULL) {
-        return ENOMEM;
-    }
-
-    ret = ad_dyndns_init(sdap_ctx->be, ad_options);
+    ret = ad_dyndns_init(ad_ctx->sdap_id_ctx->be, ad_options);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE,
              ("Failure setting up automatic DNS update\n"));
@@ -165,22 +152,23 @@ sssm_ad_id_init(struct be_ctx *bectx,
     /* Set up various SDAP options */
     ret = ad_get_id_options(ad_options, bectx->cdb,
                             bectx->conf_path,
-                            &sdap_ctx->opts);
+                            &ad_ctx->sdap_id_ctx->opts);
     if (ret != EOK) {
         goto done;
     }
 
-    ret = sdap_id_setup_tasks(sdap_ctx);
+    ret = sdap_id_setup_tasks(ad_ctx->sdap_id_ctx);
     if (ret != EOK) {
         goto done;
     }
 
     /* Set up the ID mapping object */
-    ret = sdap_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx);
+    ret = sdap_idmap_init(ad_ctx->sdap_id_ctx, ad_ctx->sdap_id_ctx,
+                          &ad_ctx->sdap_id_ctx->opts->idmap_ctx);
     if (ret != EOK) goto done;
 
 
-    ret = setup_tls_config(sdap_ctx->opts->basic);
+    ret = setup_tls_config(ad_ctx->sdap_id_ctx->opts->basic);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               ("setup_tls_config failed [%s]\n", strerror(ret)));
@@ -217,7 +205,7 @@ sssm_ad_id_init(struct be_ctx *bectx,
     ret = be_refresh_add_cb(bectx->refresh_ctx, BE_REFRESH_TYPE_NETGROUPS,
                             sdap_refresh_netgroups_send,
                             sdap_refresh_netgroups_recv,
-                            sdap_ctx);
+                            ad_ctx->sdap_id_ctx);
     if (ret != EOK && ret != EEXIST) {
         DEBUG(SSSDBG_MINOR_FAILURE, ("Periodical refresh of netgroups "
               "will not work [%d]: %s\n", ret, strerror(ret)));
-- 
1.8.3.1

-------------- next part --------------
>From bb1d3fd1edde588cf70f3a1ab8d9be9fe6c49201 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 10:49:05 +0200
Subject: [PATCH 4/8] AD: initialize failover with custom realm, domain and
 failover service

This is needed so we can initialize failover using IPA realm and
on-the-fly discovered DNS domain. The subdomains discovered on-thefly
will use the subdomain name for realm, domain and failover service to
avoid conflicts.

Subtaks of:
https://fedorahosted.org/sssd/ticket/1962
---
 src/providers/ad/ad_common.c | 58 ++++++++++++++++++++++++--------------------
 src/providers/ad/ad_common.h |  5 +++-
 src/providers/ad/ad_init.c   |  6 ++++-
 3 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 2f87bc63ea237e768e550deb7ffe3319d3cf6daf..700ac033f42ac700b4e255a74350d774a3340358 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -356,14 +356,15 @@ static errno_t
 _ad_servers_init(TALLOC_CTX *mem_ctx,
                  struct ad_service *service,
                  struct be_ctx *bectx,
+                 const char *fo_service,
+                 const char *fo_gc_service,
                  const char *servers,
-                 struct ad_options *options,
+                 const char *ad_domain,
                  bool primary)
 {
     size_t i;
     errno_t ret = 0;
     char **list;
-    char *ad_domain;
     struct ad_server_data *sdata;
     TALLOC_CTX *tmp_ctx;
 
@@ -377,8 +378,6 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ad_domain = dp_opt_get_string(options->basic, AD_DOMAIN);
-
     /* Add each of these servers to the failover service */
     for (i = 0; list[i]; i++) {
         if (be_fo_is_srv_identifier(list[i])) {
@@ -397,7 +396,7 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
             }
             sdata->gc = true;
 
-            ret = be_fo_add_srv_server(bectx, AD_GC_SERVICE_NAME, "gc",
+            ret = be_fo_add_srv_server(bectx, fo_gc_service, "gc",
                                        ad_domain, BE_FO_PROTO_TCP,
                                        false, sdata);
             if (ret != EOK) {
@@ -414,7 +413,7 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
             }
             sdata->gc = false;
 
-            ret = be_fo_add_srv_server(bectx, AD_SERVICE_NAME, "ldap",
+            ret = be_fo_add_srv_server(bectx, fo_service, "ldap",
                                        ad_domain, BE_FO_PROTO_TCP,
                                        false, sdata);
             if (ret != EOK) {
@@ -442,7 +441,7 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
         }
         sdata->gc = true;
 
-        ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, sdata, primary);
+        ret = be_fo_add_server(bectx, fo_service, list[i], 0, sdata, primary);
         if (ret && ret != EEXIST) {
             DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
             goto done;
@@ -455,7 +454,7 @@ _ad_servers_init(TALLOC_CTX *mem_ctx,
         }
         sdata->gc = false;
 
-        ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, sdata, primary);
+        ret = be_fo_add_server(bectx, fo_service, list[i], 0, sdata, primary);
         if (ret && ret != EEXIST) {
             DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
             goto done;
@@ -471,17 +470,21 @@ done:
 static inline errno_t
 ad_primary_servers_init(TALLOC_CTX *mem_ctx, struct ad_service *service,
                         struct be_ctx *bectx, const char *servers,
-                        struct ad_options *options)
+                        const char *fo_service, const char *fo_gc_service,
+                        const char *ad_domain)
 {
-    return _ad_servers_init(mem_ctx, service, bectx, servers, options, true);
+    return _ad_servers_init(mem_ctx, service, bectx, fo_service,
+                            fo_gc_service, servers, ad_domain, true);
 }
 
 static inline errno_t
 ad_backup_servers_init(TALLOC_CTX *mem_ctx, struct ad_service *service,
                         struct be_ctx *bectx, const char *servers,
-                        struct ad_options *options)
+                        const char *fo_service, const char *fo_gc_service,
+                        const char *ad_domain)
 {
-    return _ad_servers_init(mem_ctx, service, bectx, servers, options, false);
+    return _ad_servers_init(mem_ctx, service, bectx, fo_service,
+                            fo_gc_service, servers, ad_domain, false);
 }
 
 static int ad_user_data_cmp(void *ud1, void *ud2)
@@ -522,13 +525,15 @@ errno_t
 ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
                  const char *primary_servers,
                  const char *backup_servers,
-                 struct ad_options *options,
+                 const char *krb5_realm,
+                 const char *ad_service,
+                 const char *ad_gc_service,
+                 const char *ad_domain,
                  struct ad_service **_service)
 {
     errno_t ret;
     TALLOC_CTX *tmp_ctx;
     struct ad_service *service;
-    char *realm;
 
     tmp_ctx = talloc_new(mem_ctx);
     if (!tmp_ctx) return ENOMEM;
@@ -546,8 +551,8 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
         goto done;
     }
 
-    service->sdap->name = talloc_strdup(service->sdap, AD_SERVICE_NAME);
-    service->gc->name = talloc_strdup(service->gc, AD_GC_SERVICE_NAME);
+    service->sdap->name = talloc_strdup(service->sdap, ad_service);
+    service->gc->name = talloc_strdup(service->gc, ad_gc_service);
     if (!service->sdap->name || !service->gc->name) {
         ret = ENOMEM;
         goto done;
@@ -559,20 +564,20 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
         goto done;
     }
 
-    ret = be_fo_add_service(bectx, AD_SERVICE_NAME, ad_user_data_cmp);
+    ret = be_fo_add_service(bectx, ad_service, ad_user_data_cmp);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to create failover service!\n"));
         goto done;
     }
 
-    ret = be_fo_add_service(bectx, AD_GC_SERVICE_NAME, ad_user_data_cmp);
+    ret = be_fo_add_service(bectx, ad_gc_service, ad_user_data_cmp);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to create GC failover service!\n"));
         goto done;
     }
 
     service->krb5_service->name = talloc_strdup(service->krb5_service,
-                                                AD_SERVICE_NAME);
+                                                ad_service);
     if (!service->krb5_service->name) {
         ret = ENOMEM;
         goto done;
@@ -580,14 +585,13 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
     service->sdap->kinit_service_name = service->krb5_service->name;
     service->gc->kinit_service_name = service->krb5_service->name;
 
-    realm = dp_opt_get_string(options->basic, AD_KRB5_REALM);
-    if (!realm) {
+    if (!krb5_realm) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("No Kerberos realm set\n"));
         ret = EINVAL;
         goto done;
     }
     service->krb5_service->realm =
-        talloc_strdup(service->krb5_service, realm);
+        talloc_strdup(service->krb5_service, krb5_realm);
     if (!service->krb5_service->realm) {
         ret = ENOMEM;
         goto done;
@@ -600,14 +604,16 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
     }
 
     ret = ad_primary_servers_init(mem_ctx, service, bectx,
-                                  primary_servers, options);
+                                  primary_servers, ad_service,
+                                  ad_gc_service, ad_domain);
     if (ret != EOK) {
         goto done;
     }
 
     if (backup_servers) {
         ret = ad_backup_servers_init(mem_ctx, service, bectx,
-                                     backup_servers, options);
+                                     backup_servers, ad_service,
+                                     ad_gc_service, ad_domain);
         if (ret != EOK) {
             goto done;
         }
@@ -619,7 +625,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
         return ret;
     }
 
-    ret = be_fo_service_add_callback(mem_ctx, bectx, AD_SERVICE_NAME,
+    ret = be_fo_service_add_callback(mem_ctx, bectx, ad_service,
                                      ad_resolve_callback, service);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
@@ -627,7 +633,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
         goto done;
     }
 
-    ret = be_fo_service_add_callback(mem_ctx, bectx, AD_GC_SERVICE_NAME,
+    ret = be_fo_service_add_callback(mem_ctx, bectx, ad_gc_service,
                                      ad_resolve_callback, service);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 11075423c15854a236e0acabbdcce4551b6097b2..98aeb2165273b5dbfafd3b8757180d74b4504c98 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -90,7 +90,10 @@ errno_t
 ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
                  const char *primary_servers,
                  const char *backup_servers,
-                 struct ad_options *options,
+                 const char *krb5_realm,
+                 const char *ad_service,
+                 const char *ad_gc_service,
+                 const char *ad_domain,
                  struct ad_service **_service);
 
 errno_t
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 5efe05e6424784484ebbad0a950849fc128bc81d..c5d3fac235dd2473ce98c425adfc9aef0e7b9219 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -71,6 +71,7 @@ common_ad_init(struct be_ctx *bectx)
     errno_t ret;
     char *ad_servers = NULL;
     char *ad_backup_servers = NULL;
+    char *ad_realm;
 
     /* Get AD-specific options */
     ret = ad_get_common_options(bectx, bectx->cdb,
@@ -86,9 +87,12 @@ common_ad_init(struct be_ctx *bectx)
 
     ad_servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
     ad_backup_servers = dp_opt_get_string(ad_options->basic, AD_BACKUP_SERVER);
+    ad_realm = dp_opt_get_string(ad_options->basic, AD_KRB5_REALM);
 
     /* Set up the failover service */
-    ret = ad_failover_init(ad_options, bectx, ad_servers, ad_backup_servers, ad_options,
+    ret = ad_failover_init(ad_options, bectx, ad_servers, ad_backup_servers, ad_realm,
+                           AD_SERVICE_NAME, AD_GC_SERVICE_NAME,
+                           dp_opt_get_string(ad_options->basic, AD_DOMAIN),
                            &ad_options->service);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
-- 
1.8.3.1

-------------- next part --------------
>From 441df97eff4b69d292e105a04d142df8bb8c0a32 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 10:50:44 +0200
Subject: [PATCH 5/8] IPA: Initialize server mode ctx if server mode is on

This patch introduces a new structure that holds information about a
subdomain and its ad_id_ctx. This structure will be used only in server
mode to make it possible to search subdomains with a particular
ad_id_ctx.

Subtask of:
https://fedorahosted.org/sssd/ticket/1962
---
 Makefile.am                        |  7 +++++++
 src/providers/ipa/ipa_common.h     |  5 +++++
 src/providers/ipa/ipa_init.c       |  6 ++++++
 src/providers/ipa/ipa_subdomains.c | 33 +++++++++++++++++++++++++++++++++
 src/providers/ipa/ipa_subdomains.h | 18 ++++++++++++++++++
 5 files changed, 69 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index e211b789fdce9a081f22518e8c4e36f708d4f78d..0447d15002fcc3b817f7bb286f120e9af1e51138 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1593,6 +1593,11 @@ libsss_ipa_la_SOURCES = \
     src/providers/ipa/ipa_selinux_common.c \
     src/providers/ipa/ipa_srv.c \
     src/providers/ipa/ipa_idmap.c \
+    src/providers/ad/ad_common.c \
+    src/providers/ad/ad_common.h \
+    src/providers/ad/ad_dyndns.c \
+    src/providers/ad/ad_id.c \
+    src/providers/ad/ad_srv.c \
     src/util/user_info_msg.c \
     src/util/find_uid.c \
     src/util/sss_ldap.c \
@@ -1601,10 +1606,12 @@ libsss_ipa_la_CFLAGS = \
     $(AM_CFLAGS) \
     $(LDAP_CFLAGS) \
     $(DHASH_CFLAGS) \
+    $(NDR_NBT_CFLAGS)
     $(KRB5_CFLAGS)
 libsss_ipa_la_LIBADD = \
     $(OPENLDAP_LIBS) \
     $(DHASH_LIBS) \
+    $(NDR_NBT_LIBS) \
     $(KEYUTILS_LIBS) \
     $(KRB5_LIBS) \
     libsss_ldap_common.la \
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index b3e719ee7248445d4d64ed979c7f35188b892867..78ea23c93bbbac7de90482c23c7b2ca1a8557a19 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -112,9 +112,14 @@ struct ipa_auth_ctx {
     struct dp_option *ipa_options;
 };
 
+/* In server mode, each subdomain corresponds to an AD context */
+
 struct ipa_id_ctx {
     struct sdap_id_ctx *sdap_id_ctx;
     struct ipa_options *ipa_options;
+
+    /* Only used with server mode */
+    struct ipa_server_mode_ctx *server_mode;
 };
 
 struct ipa_options {
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 7297fc936c948e548b7ee8989f76c215fafe41e1..fe13b18722d7a2506ea52850e17a4cf20073bc56 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -528,6 +528,12 @@ int sssm_ipa_subdomains_init(struct be_ctx *bectx,
         return ret;
     }
 
+    ret = ipa_ad_subdom_init(bectx, id_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("ipa_ad_subdom_init failed.\n"));
+        return ret;
+    }
+
     return EOK;
 }
 
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index d8157c999ef710d99fdf66e812b1e2d930e7636b..9e1b8c31aea99b12185c90bf8dd7fda59f69db9f 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -910,3 +910,36 @@ int ipa_subdom_init(struct be_ctx *be_ctx,
 
     return EOK;
 }
+
+int ipa_ad_subdom_init(struct be_ctx *be_ctx,
+                       struct ipa_id_ctx *id_ctx)
+{
+    char *realm;
+    char *hostname;
+
+    if (dp_opt_get_bool(id_ctx->ipa_options->basic,
+                        IPA_SERVER_MODE) == false) {
+        return EOK;
+    }
+
+    realm = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_KRB5_REALM);
+    if (realm == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("No Kerberos realm for IPA?\n"));
+        return EINVAL;
+    }
+
+    hostname = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_HOSTNAME);
+    if (hostname == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("No host name for IPA?\n"));
+        return EINVAL;
+    }
+
+    id_ctx->server_mode = talloc(id_ctx, struct ipa_server_mode_ctx);
+    if (id_ctx->server_mode == NULL) {
+        return ENOMEM;
+    }
+    id_ctx->server_mode->realm = realm;
+    id_ctx->server_mode->hostname = hostname;
+
+    return EOK;
+}
diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h
index c9ab82a25df2dee06dfb8cc0da754ff3a359d0e6..315ce9e06c5159406782d00ffacef58b503c7118 100644
--- a/src/providers/ipa/ipa_subdomains.h
+++ b/src/providers/ipa/ipa_subdomains.h
@@ -38,6 +38,24 @@ int ipa_subdom_init(struct be_ctx *be_ctx,
                     struct bet_ops **ops,
                     void **pvt_data);
 
+/* The following are used in server mode only */
+struct ipa_ad_server_ctx {
+    struct sss_domain_info *dom;
+    struct ad_id_ctx *ad_id_ctx;
+
+    struct ipa_ad_server_ctx *next, *prev;
+};
+
+struct ipa_server_mode_ctx {
+    const char *realm;
+    const char *hostname;
+
+    struct ipa_ad_server_ctx *trusts;
+};
+
+int ipa_ad_subdom_init(struct be_ctx *be_ctx,
+                       struct ipa_id_ctx *id_ctx);
+
 enum req_input_type {
     REQ_INP_NAME,
     REQ_INP_ID,
-- 
1.8.3.1

-------------- next part --------------
>From c16d9637f13b350a1c5fc0947a402325cc920a60 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 13:00:41 +0200
Subject: [PATCH 6/8] AD: Move storing sdap_domain for subdomain to generic
 LDAP code

Makes creating the sdap_domain structure for a subdomain reusable
outside AD subdomain code where it was created initially.

Subtask of:
    https://fedorahosted.org/sssd/ticket/1962
---
 src/providers/ad/ad_subdomains.c | 66 +-----------------------------------
 src/providers/ldap/ldap_common.c | 73 ++++++++++++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_common.h |  4 +++
 3 files changed, 78 insertions(+), 65 deletions(-)

diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 724d0736bf89913d49d19183a9c8f370bc80feb1..be4781cc5bc01152ffa1fbedf0ad5352f72939ae 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -89,71 +89,7 @@ static errno_t
 ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
                       struct sss_domain_info *parent)
 {
-    struct sss_domain_info *dom;
-    struct sdap_domain *sdom, *sditer;
-    char *basedn;
-    errno_t ret;
-
-    for (dom = get_next_domain(parent, true);
-         dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
-         dom = get_next_domain(dom, false)) {
-
-        DLIST_FOR_EACH(sditer, ctx->sdom) {
-            if (sditer->dom == dom) {
-                break;
-            }
-        }
-
-        if (sditer == NULL) {
-            /* New sdap domain */
-            DEBUG(SSSDBG_TRACE_FUNC, ("subdomain %s is a new one, will "
-                  "create a new sdap domain object\n", dom->name));
-
-            ret = sdap_domain_add(ctx->sdap_id_ctx->opts, dom, &sdom);
-            if (ret != EOK) {
-                DEBUG(SSSDBG_OP_FAILURE,
-                    ("Cannot add new sdap domain for domain %s [%d]: %s\n",
-                    parent->name, ret, strerror(ret)));
-                return ret;
-            }
-            sditer = sdom;
-        }
-
-        /* Convert the domain name into search base */
-        ret = domain_to_basedn(sditer, sditer->dom->name, &basedn);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                ("Cannot convert domain name [%s] to base DN [%d]: %s\n",
-                dom->name, ret, strerror(ret)));
-            talloc_free(basedn);
-            return ret;
-        }
-
-        /* Update search bases */
-        talloc_zfree(sdom->search_bases);
-        sdom->search_bases = talloc_array(sdom, struct sdap_search_base *, 2);
-        if (sdom->search_bases == NULL) {
-            return ret;
-        }
-        sdom->search_bases[1] = NULL;
-
-        ret = sdap_create_search_base(sdom, basedn, LDAP_SCOPE_SUBTREE, NULL,
-                                      &sdom->search_bases[0]);
-        talloc_free(basedn);
-        if (ret) {
-            DEBUG(SSSDBG_OP_FAILURE, ("Cannot create new sdap search base\n"));
-            return ret;
-        }
-
-        sdom->user_search_bases = sdom->search_bases;
-        sdom->group_search_bases = sdom->search_bases;
-        sdom->netgroup_search_bases = sdom->search_bases;
-        sdom->sudo_search_bases = sdom->search_bases;
-        sdom->service_search_bases = sdom->search_bases;
-        sdom->autofs_search_bases = sdom->search_bases;
-    }
-
-    return EOK;
+    return sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
 }
 
 static errno_t
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 96edd3362caf717ff68ab4eb52d031fc745a7b6e..9aa98173c865d0b032f02bd6a0ec80b93682af6d 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -94,6 +94,79 @@ sdap_domain_add(struct sdap_options *opts,
     return EOK;
 }
 
+errno_t
+sdap_domain_subdom_add(struct sdap_id_ctx *sdap_id_ctx,
+                       struct sdap_domain *sdom_list,
+                       struct sss_domain_info *parent)
+{
+    struct sss_domain_info *dom;
+    struct sdap_domain *sdom, *sditer;
+    char *basedn;
+    errno_t ret;
+
+    for (dom = get_next_domain(parent, true);
+         dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
+         dom = get_next_domain(dom, false)) {
+
+        DLIST_FOR_EACH(sditer, sdom_list) {
+            if (sditer->dom == dom) {
+                break;
+            }
+        }
+
+        if (sditer == NULL) {
+            /* New sdap domain */
+            DEBUG(SSSDBG_TRACE_FUNC, ("subdomain %s is a new one, will "
+                  "create a new sdap domain object\n", dom->name));
+
+            ret = sdap_domain_add(sdap_id_ctx->opts, dom, &sdom);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                    ("Cannot add new sdap domain for domain %s [%d]: %s\n",
+                    parent->name, ret, strerror(ret)));
+                return ret;
+            }
+        } else {
+            sdom = sditer;
+        }
+
+        /* Convert the domain name into search base */
+        ret = domain_to_basedn(sdom, sdom->dom->name, &basedn);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                ("Cannot convert domain name [%s] to base DN [%d]: %s\n",
+                dom->name, ret, strerror(ret)));
+            talloc_free(basedn);
+            return ret;
+        }
+
+        /* Update search bases */
+        talloc_zfree(sdom->search_bases);
+        sdom->search_bases = talloc_array(sdom, struct sdap_search_base *, 2);
+        if (sdom->search_bases == NULL) {
+            return ret;
+        }
+        sdom->search_bases[1] = NULL;
+
+        ret = sdap_create_search_base(sdom, basedn, LDAP_SCOPE_SUBTREE, NULL,
+                                      &sdom->search_bases[0]);
+        talloc_free(basedn);
+        if (ret) {
+            DEBUG(SSSDBG_OP_FAILURE, ("Cannot create new sdap search base\n"));
+            return ret;
+        }
+
+        sdom->user_search_bases = sdom->search_bases;
+        sdom->group_search_bases = sdom->search_bases;
+        sdom->netgroup_search_bases = sdom->search_bases;
+        sdom->sudo_search_bases = sdom->search_bases;
+        sdom->service_search_bases = sdom->search_bases;
+        sdom->autofs_search_bases = sdom->search_bases;
+    }
+
+    return EOK;
+}
+
 void
 sdap_domain_remove(struct sdap_options *opts,
                    struct sss_domain_info *dom)
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 7a708301152dcbf72c90b11353ebae43a21f51de..db2466ad832d7867d9244a835cde1adab39d347d 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -240,6 +240,10 @@ errno_t msgs2attrs_array(TALLOC_CTX *mem_ctx, size_t count,
 errno_t sdap_domain_add(struct sdap_options *opts,
                         struct sss_domain_info *dom,
                         struct sdap_domain **_sdom);
+errno_t
+sdap_domain_subdom_add(struct sdap_id_ctx *sdap_id_ctx,
+                       struct sdap_domain *sdom_list,
+                       struct sss_domain_info *parent);
 
 void
 sdap_domain_remove(struct sdap_options *opts,
-- 
1.8.3.1

-------------- next part --------------
>From bdf82045d08e82bc2887feb2ad58aa533008d995 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 13:20:50 +0200
Subject: [PATCH 7/8] IPA: Create and remove AD id_ctx for subdomains
 discovered in server mode

When IPA server mode is on, then this patch will create an ad_id_ctx for
each subdomain discovered in IPA provider. The ID context is needed to
perform direct lookups using the AD provider.

Subtask of:
https://fedorahosted.org/sssd/ticket/1962
---
 src/providers/ipa/ipa_subdomains.c | 182 +++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 9e1b8c31aea99b12185c90bf8dd7fda59f69db9f..8d7e9626043a41c9402e28a11a388190f6cbc392 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -67,6 +67,7 @@ struct ipa_subdomains_req_params {
 
 struct ipa_subdomains_ctx {
     struct be_ctx *be_ctx;
+    struct ipa_id_ctx *id_ctx;
     struct sdap_id_ctx *sdap_id_ctx;
     struct sdap_search_base **search_bases;
     struct sdap_search_base **master_search_bases;
@@ -92,6 +93,175 @@ struct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx)
     return subdom_ctx->be_ctx;
 }
 
+static errno_t
+ipa_ad_ctx_new(struct be_ctx *be_ctx,
+               struct ipa_id_ctx *id_ctx,
+               struct sss_domain_info *subdom,
+               struct ad_id_ctx **_ad_id_ctx)
+{
+    struct ad_options *ad_options;
+    struct ad_id_ctx *ad_id_ctx;
+    const char *gc_service_name;
+    errno_t ret;
+
+    ad_options = ad_create_default_options(id_ctx, id_ctx->server_mode->realm,
+                                           id_ctx->server_mode->hostname);
+    if (ad_options == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD options\n"));
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+
+    ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, subdom->name);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    ret = dp_opt_set_string(ad_options->basic, AD_KRB5_REALM,
+                            id_ctx->server_mode->realm);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD realm\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
+    if (gc_service_name == NULL) {
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+
+    /* Set KRB5 realm to same as the one of IPA when IPA
+     * is able to attach PAC. For testing, use hardcoded. */
+    ret = ad_failover_init(ad_options, be_ctx, NULL, NULL,
+                           id_ctx->server_mode->realm,
+                           subdom->name, gc_service_name,
+                           subdom->name, &ad_options->service);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD failover\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
+    if (ad_id_ctx == NULL) {
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+    ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
+    ad_options->id_ctx = ad_id_ctx;
+
+    ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
+                                 ad_id_ctx->sdap_id_ctx->opts->sdom,
+                                 subdom->parent);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize sdap domain\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    /* Set up the ID mapping object */
+    ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
+        id_ctx->sdap_id_ctx->opts->idmap_ctx;
+
+    *_ad_id_ctx = ad_id_ctx;
+    return EOK;
+}
+
+static errno_t
+ipa_server_trust_add(struct be_ctx *be_ctx,
+                     struct ipa_id_ctx *id_ctx,
+                     struct sss_domain_info *subdom)
+{
+    struct ipa_ad_server_ctx *trust_ctx;
+    struct ad_id_ctx *ad_id_ctx;
+    errno_t ret;
+
+    ret = ipa_ad_ctx_new(be_ctx, id_ctx, subdom, &ad_id_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Cannot create ad_id_ctx for subdomain %s\n", subdom->name));
+        return ret;
+    }
+
+    trust_ctx = talloc(id_ctx->server_mode, struct ipa_ad_server_ctx);
+    if (trust_ctx == NULL) {
+        return ENOMEM;
+    }
+    trust_ctx->dom = subdom;
+    trust_ctx->ad_id_ctx = ad_id_ctx;
+
+    DLIST_ADD(id_ctx->server_mode->trusts, trust_ctx);
+    return EOK;
+}
+
+static errno_t
+ipa_ad_subdom_refresh(struct be_ctx *be_ctx,
+                      struct ipa_id_ctx *id_ctx,
+                      struct sss_domain_info *parent)
+{
+    struct sss_domain_info *dom;
+    struct ipa_ad_server_ctx *trust_iter;
+    errno_t ret;
+
+    if (dp_opt_get_bool(id_ctx->ipa_options->basic,
+                        IPA_SERVER_MODE) == false) {
+        return EOK;
+    }
+
+    for (dom = get_next_domain(parent, true);
+         dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
+         dom = get_next_domain(dom, false)) {
+
+        /* Check if we already have an ID context for this subdomain */
+        DLIST_FOR_EACH(trust_iter, id_ctx->server_mode->trusts) {
+            if (trust_iter->dom == dom) {
+                break;
+            }
+        }
+
+        /* Newly detected trust */
+        if (trust_iter == NULL) {
+            ret = ipa_server_trust_add(be_ctx, id_ctx, dom);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      ("Cannot create ad_id_ctx for subdomain %s\n",
+                       dom->name));
+                continue;
+            }
+        }
+    }
+
+    return EOK;
+}
+
+static void
+ipa_ad_subdom_remove(struct ipa_subdomains_ctx *ctx,
+                     struct sss_domain_info *subdom)
+{
+    struct ipa_ad_server_ctx *iter;
+
+    if (dp_opt_get_bool(ctx->id_ctx->ipa_options->basic,
+                        IPA_SERVER_MODE) == false) {
+        return;
+    }
+
+    DLIST_FOR_EACH(iter, ctx->id_ctx->server_mode->trusts) {
+        if (iter->dom == subdom) break;
+    }
+
+    if (iter == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("No IPA-AD context for subdomain %s\n",
+              subdom->name));
+        return;
+    }
+
+    sdap_domain_remove(iter->ad_id_ctx->sdap_id_ctx->opts, subdom);
+    DLIST_REMOVE(ctx->id_ctx->server_mode->trusts, iter);
+}
+
 const char *get_flat_name_from_subdomain_name(struct be_ctx *be_ctx,
                                               const char *name)
 {
@@ -311,6 +481,9 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
             if (ret != EOK) {
                 goto done;
             }
+
+            /* Remove the AD ID ctx from the list of LDAP domains */
+            ipa_ad_subdom_remove(ctx, dom);
         } else {
             /* ok let's try to update it */
             ret = ipa_subdom_store(domain, ctx->sdap_id_ctx->opts->idmap_ctx,
@@ -585,6 +758,13 @@ static void ipa_subdomains_handler_done(struct tevent_req *req)
             goto done;
         }
 
+        ret = ipa_ad_subdom_refresh(ctx->sd_ctx->be_ctx, ctx->sd_ctx->id_ctx,
+                                    domain);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n"));
+            goto done;
+        }
+
         ret = sss_write_domain_mappings(domain);
         if (ret != EOK) {
             DEBUG(SSSDBG_MINOR_FAILURE,
@@ -889,6 +1069,7 @@ int ipa_subdom_init(struct be_ctx *be_ctx,
     }
 
     ctx->be_ctx = be_ctx;
+    ctx->id_ctx = id_ctx;
     ctx->sdap_id_ctx = id_ctx->sdap_id_ctx;
     ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases;
     ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases;
@@ -940,6 +1121,7 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx,
     }
     id_ctx->server_mode->realm = realm;
     id_ctx->server_mode->hostname = hostname;
+    id_ctx->server_mode->trusts = NULL;
 
     return EOK;
 }
-- 
1.8.3.1

-------------- next part --------------
>From 5c45910c3674446e3ef9a0b7fd20f82bf0654dce Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 19 Jun 2013 10:51:19 +0200
Subject: [PATCH 8/8] IPA: Look up AD users directly if IPA server mode is on

https://fedorahosted.org/sssd/ticket/1962

If the ipa_server_mode is selected IPA subdomain user and group lookups
are not done with the help of the extdom plugin but directly against AD
using the AD ID code.
---
 src/providers/ad/ad_id.c              |   4 +-
 src/providers/ad/ad_id.h              |  11 +++
 src/providers/ipa/ipa_common.h        |   1 +
 src/providers/ipa/ipa_id.c            |  23 +++++--
 src/providers/ipa/ipa_id.h            |   9 +++
 src/providers/ipa/ipa_subdomains_id.c | 126 ++++++++++++++++++++++++++++++++++
 6 files changed, 168 insertions(+), 6 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 9c4abc8c9be5f19ff36d30321dccd66a2d10519d..48ad842590d0a8904744cd5518ac511205416f28 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -38,7 +38,7 @@ struct ad_handle_acct_info_state {
 static errno_t ad_handle_acct_info_step(struct tevent_req *req);
 static void ad_handle_acct_info_done(struct tevent_req *subreq);
 
-static struct tevent_req *
+struct tevent_req *
 ad_handle_acct_info_send(TALLOC_CTX *mem_ctx,
                          struct be_req *breq,
                          struct be_acct_req *ar,
@@ -152,7 +152,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
     /* Another lookup in progress */
 }
 
-static errno_t
+errno_t
 ad_handle_acct_info_recv(struct tevent_req *req,
                          int *_dp_error, const char **_err)
 {
diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h
index 47fc3b33b21d1a89c96c8497b22b9a42f047471b..1fd6b599a8c42ccf9b68cec6b450a01c5ad80796 100644
--- a/src/providers/ad/ad_id.h
+++ b/src/providers/ad/ad_id.h
@@ -26,6 +26,17 @@
 void
 ad_account_info_handler(struct be_req *breq);
 
+struct tevent_req *
+ad_handle_acct_info_send(TALLOC_CTX *mem_ctx,
+                         struct be_req *breq,
+                         struct be_acct_req *ar,
+                         struct sdap_id_ctx *ctx,
+                         struct sdap_domain *sdom,
+                         struct sdap_id_conn_ctx **conn);
+errno_t
+ad_handle_acct_info_recv(struct tevent_req *req,
+                         int *_dp_error, const char **_err);
+
 void
 ad_check_online(struct be_req *be_req);
 #endif /* AD_ID_H_ */
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 78ea23c93bbbac7de90482c23c7b2ca1a8557a19..9ed7c232708eaf88c535336be374780421f00a83 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -26,6 +26,7 @@
 #include "confdb/confdb.h"
 #include "providers/ldap/ldap_common.h"
 #include "providers/krb5/krb5_common.h"
+#include "providers/ad/ad_common.h"
 
 struct ipa_service {
     struct sdap_service *sdap;
diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index b11abaa7dbdfdae119d9ec18e1d53538b5382259..6e0964400bf32a138b1ede5edd610f022db41311 100644
--- a/src/providers/ipa/ipa_id.c
+++ b/src/providers/ipa/ipa_id.c
@@ -83,9 +83,15 @@ void ipa_account_info_handler(struct be_req *breq)
     ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);
 
     if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
-        /* if domain names do not match, this is a subdomain case */
-        req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar);
-
+        /* if domain names do not match, this is a subdomain case
+         * subdomain lookups are handled differently on the server
+         * and the client
+         */
+        if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) {
+            req = ipa_get_ad_acct_send(breq, be_ctx->ev, ipa_ctx, breq, ar);
+        } else {
+            req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar);
+        }
     } else if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
         /* netgroups are handled by a separate request function */
         if (ar->filter_type != BE_FILTER_NAME) {
@@ -110,15 +116,24 @@ void ipa_account_info_handler(struct be_req *breq)
 static void ipa_account_info_done(struct tevent_req *req)
 {
     struct be_req *breq = tevent_req_callback_data(req, struct be_req);
+    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
+    struct ipa_id_ctx *ipa_ctx;
     struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq),
                                              struct be_acct_req);
     const char *error_text;
     int ret, dp_error;
 
+    ipa_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
+                              struct ipa_id_ctx);
+
     if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
         ret = ipa_id_get_netgroup_recv(req, &dp_error);
     } else {
-        ret = ipa_get_subdom_acct_recv(req, &dp_error);
+        if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) {
+            ret = ipa_get_ad_acct_recv(req, &dp_error);
+        } else {
+            ret = ipa_get_subdom_acct_recv(req, &dp_error);
+        }
     }
     talloc_zfree(req);
 
diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 7fa25e9270737cc27a961b73828bbc13c75d0cca..6c72f6d0481872bdfecfd07bd06995bd040ee4a7 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -64,4 +64,13 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
                                             struct sdap_id_ctx *ctx,
                                             struct be_acct_req *ar);
 int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out);
+
+struct tevent_req *ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+                                        struct tevent_context *ev,
+                                        struct ipa_id_ctx *ipa_ctx,
+                                        struct be_req *be_req,
+                                        struct be_acct_req *ar);
+
+errno_t ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out);
+
 #endif
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index dc822888f2cbb243547341fb537d672d59af7077..6bf97bec0df465ba206181ec59789c0567443432 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -30,6 +30,7 @@
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async.h"
 #include "providers/ipa/ipa_id.h"
+#include "providers/ad/ad_id.h"
 #include "providers/ipa/ipa_subdomains.h"
 
 struct ipa_get_subdom_acct {
@@ -246,3 +247,128 @@ int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out)
     return EOK;
 }
 
+/* IPA lookup for server mode. Directly to AD. */
+struct ipa_get_ad_acct_state {
+    int dp_error;
+};
+
+static void ipa_get_ad_acct_done(struct tevent_req *subreq);
+static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
+                                           struct sss_domain_info *dom);
+
+struct tevent_req *
+ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+                     struct tevent_context *ev,
+                     struct ipa_id_ctx *ipa_ctx,
+                     struct be_req *be_req,
+                     struct be_acct_req *ar)
+{
+    errno_t ret;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct ipa_get_ad_acct_state *state;
+    struct sss_domain_info *dom;
+    struct sdap_domain *sdom;
+    struct sdap_id_conn_ctx **clist;
+    struct sdap_id_ctx *sdap_id_ctx;;
+    struct ad_id_ctx *ad_id_ctx;
+
+    req = tevent_req_create(mem_ctx, &state, struct ipa_get_ad_acct_state);
+    if (req == NULL) return NULL;
+
+    /* This can only be a subdomain request, verify subdomain */
+    dom = find_subdomain_by_name(ipa_ctx->sdap_id_ctx->be->domain,
+                                 ar->domain, true);
+    if (dom == NULL) {
+        ret = EINVAL;
+        goto fail;
+    }
+
+    /* Let's see if this subdomain has a ad_id_ctx */
+    ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, dom);
+    if (ad_id_ctx == NULL) {
+        ret = EINVAL;
+        goto fail;
+    }
+    sdap_id_ctx = ad_id_ctx->sdap_id_ctx;
+
+    /* Currently only LDAP port for AD is used because POSIX
+     * attributes are not replicated to GC by default
+     */
+    clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2);
+    if (clist == NULL) {
+        ret = ENOMEM;
+        goto fail;
+    }
+    clist[0] = ad_id_ctx->ldap_ctx;
+    clist[1] = NULL;
+
+    /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */
+    sdom = sdap_domain_get(sdap_id_ctx->opts, dom);
+    if (sdom == NULL) {
+        ret = EIO;
+        goto fail;
+    }
+
+    subreq = ad_handle_acct_info_send(req, be_req, ar, sdap_id_ctx,
+                                      sdom, clist);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto fail;
+    }
+    tevent_req_set_callback(subreq, ipa_get_ad_acct_done, req);
+    return req;
+
+fail:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static struct ad_id_ctx *
+ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
+                  struct sss_domain_info *dom)
+{
+    struct ipa_ad_server_ctx *iter;
+
+    DLIST_FOR_EACH(iter, ipa_ctx->server_mode->trusts) {
+        if (iter->dom == dom) break;
+    }
+
+    return iter->ad_id_ctx;
+}
+
+static void
+ipa_get_ad_acct_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    struct ipa_get_ad_acct_state *state = tevent_req_data(req,
+                                                struct ipa_get_ad_acct_state);
+    errno_t ret;
+
+    ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("AD lookup failed: %d\n", ret));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t
+ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
+{
+    struct ipa_get_ad_acct_state *state = tevent_req_data(req,
+                                                struct ipa_get_ad_acct_state);
+
+    if (dp_error_out) {
+        *dp_error_out = state->dp_error;
+    }
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    return EOK;
+}
-- 
1.8.3.1



More information about the sssd-devel mailing list