[SSSD] [PATCHES] ID-Mapping enhancements for IPA

Sumit Bose sbose at redhat.com
Fri Jun 28 16:51:42 UTC 2013


Hi,

with the following patches the handling of ID ranges and ID mapping will
be unified over the LDAP based ID providers (LDAP, AD, IPA) and support
the the new IPA range type attribute is added.

Please see commit messages for more details.

bye,
Sumit
-------------- next part --------------
From d371920aa74fd73db26837492587c69045de1894 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Jun 2013 12:17:08 +0200
Subject: [PATCH 01/11] Add now options ldap_min_id and ldap_max_id

Currently the range for Posix IDs stored in an LDAP server is unbound.
This might lead to conflicts in a setup with AD and trusts when the
configured domain uses IDs from LDAP. With the two noe options this
conflict can be avoided.
---
 src/config/SSSDConfig/__init__.py.in     |    2 ++
 src/config/etc/sssd.api.d/sssd-ldap.conf |    2 ++
 src/man/sssd-ldap.5.xml                  |   21 +++++++++++++++++++++
 src/providers/ad/ad_opts.h               |    2 ++
 src/providers/ipa/ipa_opts.h             |    2 ++
 src/providers/ldap/ldap_opts.h           |    2 ++
 src/providers/ldap/sdap.h                |    2 ++
 7 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 4d7629e..1bc4f1b 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -309,6 +309,8 @@ option_strings = {
 
     'ldap_groups_use_matching_rule_in_chain' : _('Use LDAP_MATCHING_RULE_IN_CHAIN for group lookups'),
     'ldap_initgroups_use_matching_rule_in_chain' : _('Use LDAP_MATCHING_RULE_IN_CHAIN for initgroup lookups'),
+    'ldap_min_id' : _('Set lower boundary for allowed IDs from the LDAP server'),
+    'ldap_max_id' : _('Set upper boundary for allowed IDs from the LDAP server'),
 
     # [provider/ldap/auth]
     'ldap_pwd_policy' : _('Policy to evaluate the password expiration'),
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 870cf20..eb23966 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -117,6 +117,8 @@ 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
+ldap_min_id = int, None, false
+ldap_max_id = int, None, false
 
 [provider/ldap/auth]
 ldap_pwd_policy = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index fd29650..12e9152 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1434,6 +1434,27 @@
                 </varlistentry>
 
                 <varlistentry>
+                    <term>ldap_min_id, ldap_max_id (interger)</term>
+                    <listitem>
+                        <para>
+                            In contrast to the SID based ID mapping which is
+                            used if ldap_id_mapping is set to true the allowed
+                            ID range for ldap_user_uid_number and
+                            ldap_group_gid_number is unbound. In a setup with
+                            sub/trusted-domains this might lead to ID
+                            collisions. To avoid collisions ldap_min_id and
+                            ldap_max_id can be set to restrict the allowed
+                            range for the IDs which are read directly from the
+                            server. Sub-domains can then pick other ranges to
+                            map IDs.
+                        </para>
+                        <para>
+                            Default: not set (both options are set to 0)
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
                     <term>ldap_sasl_mech (string)</term>
                     <listitem>
                         <para>
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index ba03c23..2c60b76 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -124,6 +124,8 @@ struct dp_option ad_def_ldap_opts[] = {
     { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_disable_range_retrieval", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+    { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 6246f58..139008b 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -148,6 +148,8 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_disable_range_retrieval", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+    { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index 6857d4c..a6c821f 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -115,6 +115,8 @@ struct dp_option default_basic_opts[] = {
     { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_disable_range_retrieval", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+    { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 6f10efa..9fbe04b 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -219,6 +219,8 @@ enum sdap_basic_opt {
     SDAP_AD_MATCHING_RULE_INITGROUPS,
     SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS,
     SDAP_DISABLE_RANGE_RETRIEVAL,
+    SDAP_MIN_ID,
+    SDAP_MAX_ID,
 
     SDAP_OPTS_BASIC /* opts counter */
 };
-- 
1.7.7.6

-------------- next part --------------
From daabd6531e38afda80df8c7c68bc17204a9ae266 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Jun 2013 14:37:35 +0200
Subject: [PATCH 02/11] SDAP IDMAP: Add configured domain to idmap context

To allow libsss_idmap to manage all id-ranges the id-ranges of the
domains configured in sssd.conf which are currently unmanaged must be
added to libsss_idmap.
---
 src/providers/ldap/sdap_idmap.c |   70 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c
index a81bc98..46bc6e8 100644
--- a/src/providers/ldap/sdap_idmap.c
+++ b/src/providers/ldap/sdap_idmap.c
@@ -37,6 +37,64 @@ sdap_idmap_talloc_free(void *ptr, void *pvt)
     talloc_free(ptr);
 }
 
+static errno_t
+sdap_idmap_add_configured_external_range(struct sdap_idmap_ctx *idmap_ctx)
+{
+    int int_id;
+    struct sss_idmap_range range;
+    struct sdap_id_ctx *id_ctx;
+    enum idmap_error_code err;
+
+    if (idmap_ctx == NULL) {
+        return EINVAL;
+    }
+
+    id_ctx = idmap_ctx->id_ctx;
+
+    int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MIN_ID);
+    if (int_id < 0) {
+        DEBUG(SSSDBG_CONF_SETTINGS, ("ldap_min_id must be a greater 0.\n"));
+        return EINVAL;
+    }
+    range.min = int_id;
+
+    int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MAX_ID);
+    if (int_id < 0) {
+        DEBUG(SSSDBG_CONF_SETTINGS, ("ldap_min_id must be a greater 0.\n"));
+        return EINVAL;
+    }
+    range.max = int_id;
+
+    if ((range.min == 0 && range.max != 0)
+            || (range.min != 0 && range.max == 0)) {
+        DEBUG(SSSDBG_CONF_SETTINGS, ("Both ldap_min_id and ldap_max_id " \
+                                     "either must be 0 (not set) " \
+                                     "or positive integers.\n"));
+        return EINVAL;
+    }
+
+    if (range.min == 0 && range.max == 0) {
+        /* ldap_min_id and ldap_max_id not set, using min_id and max_id */
+        range.min = id_ctx->be->domain->id_min;
+        range.max = id_ctx->be->domain->id_max;
+        if (range.max == 0) {
+            range.max = UINT32_MAX;
+        }
+    }
+
+    err = sss_idmap_add_domain_ex(idmap_ctx->map, id_ctx->be->domain->name,
+                                  id_ctx->be->domain->domain_id, &range,
+                                  NULL, 0, true);
+    if (err != IDMAP_SUCCESS) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Could not add domain [%s] to the map: [%d]\n",
+               id_ctx->be->domain->name, err));
+        return EIO;
+    }
+
+    return EOK;
+}
+
 errno_t
 sdap_idmap_init(TALLOC_CTX *mem_ctx,
                 struct sdap_id_ctx *id_ctx,
@@ -120,6 +178,18 @@ sdap_idmap_init(TALLOC_CTX *mem_ctx,
         return EIO;
     }
 
+
+    /* Setup range for externally managed IDs, i.e. IDs are read from the
+     * ldap_user_uid_number and ldap_group_gid_number attributes. */
+    if (!dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_ID_MAPPING)) {
+        ret = sdap_idmap_add_configured_external_range(idmap_ctx);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  ("sdap_idmap_add_configured_external_range failed.\n"));
+            goto done;
+        }
+    }
+
     /* Read in any existing mappings from the cache */
     ret = sysdb_idmap_get_mappings(tmp_ctx, sysdb, id_ctx->be->domain, &res);
     if (ret != EOK && ret != ENOENT) {
-- 
1.7.7.6

-------------- next part --------------
From 8a3750e5f8bdc288918e0fd367190cf520ec688c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 13 Jun 2013 14:26:22 +0200
Subject: [PATCH 03/11] Allow different methods to find new domains for
 idmapping

Currently the range management code is in the generic LDAP provider and
can be used by the LDAP and AD provider. New ranges are allocated with
the help of a hash value of the domain SID.

If the IPA provider cannot find a range for a given domain it cannot
allocate a new range on its own but has to look up the idrange objects
on the FreeIPA server and use them accordingly. To allow the LDAP, AD
and IPA provider to use as much common code as possible a plugin
interface, similar to the one used to find the DNS site, to find a
missing range would be useful. The default plugin will be used by the
LDAP and the AD provider and the IPA provider will implement a plugin to
read the data from the server.

Fixes https://fedorahosted.org/sssd/ticket/1961
---
 src/providers/ldap/sdap_idmap.c |   23 ++++++++++++++++++++---
 src/providers/ldap/sdap_idmap.h |    4 ++++
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c
index 46bc6e8..e692853 100644
--- a/src/providers/ldap/sdap_idmap.c
+++ b/src/providers/ldap/sdap_idmap.c
@@ -95,6 +95,24 @@ sdap_idmap_add_configured_external_range(struct sdap_idmap_ctx *idmap_ctx)
     return EOK;
 }
 
+errno_t sdap_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
+                                   const char *dom_name,
+                                   const char *dom_sid_str)
+{
+    int ret;
+
+    ret = sdap_idmap_add_domain(idmap_ctx,
+                                dom_name, dom_sid_str,
+                                -1);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Could not add new domain [%s]\n", dom_name));
+        return ret;
+    }
+
+    return EOK;
+}
+
 errno_t
 sdap_idmap_init(TALLOC_CTX *mem_ctx,
                 struct sdap_id_ctx *id_ctx,
@@ -124,6 +142,7 @@ sdap_idmap_init(TALLOC_CTX *mem_ctx,
         goto done;
     }
     idmap_ctx->id_ctx = id_ctx;
+    idmap_ctx->find_new_domain = sdap_idmap_find_new_domain;
 
     idmap_lower = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
                                  SDAP_IDMAP_LOWER);
@@ -418,9 +437,7 @@ sdap_idmap_sid_to_unix(struct sdap_idmap_ctx *idmap_ctx,
             goto done;
         }
 
-        ret = sdap_idmap_add_domain(idmap_ctx,
-                                    dom_sid_str, dom_sid_str,
-                                    -1);
+        ret = idmap_ctx->find_new_domain(idmap_ctx, dom_sid_str, dom_sid_str);
         if (ret != EOK) {
             DEBUG(SSSDBG_MINOR_FAILURE,
                   ("Could not add new domain for sid [%s]\n", sid_str));
diff --git a/src/providers/ldap/sdap_idmap.h b/src/providers/ldap/sdap_idmap.h
index 2e2123f..45462c1 100644
--- a/src/providers/ldap/sdap_idmap.h
+++ b/src/providers/ldap/sdap_idmap.h
@@ -26,10 +26,14 @@
 #include "src/providers/ldap/sdap.h"
 #include "src/providers/ldap/ldap_common.h"
 
+typedef errno_t (find_new_domain_fn_t)(struct sdap_idmap_ctx *idmap_ctx,
+                                       const char *dom_name,
+                                       const char *dom_sid_str);
 struct sdap_idmap_ctx {
     struct sss_idmap_ctx *map;
 
     struct sdap_id_ctx *id_ctx;
+    find_new_domain_fn_t *find_new_domain;
 };
 
 errno_t sdap_idmap_init(TALLOC_CTX *mem_ctx,
-- 
1.7.7.6

-------------- next part --------------
From 33d7f169da079dac6077ea0708dc18773a4ba647 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 27 Jun 2013 12:48:49 +0200
Subject: [PATCH 04/11] Add sdap_idmap_domain_has_algorithmic_mapping()

This patch implements a wrapper for
sss_idmap_domain_has_algorithmic_mapping() for the sdap ID mapping.

Fixes https://fedorahosted.org/sssd/ticket/1960
---
 src/providers/ldap/sdap_idmap.c |   59 +++++++++++++++++++++++++++++++++++++++
 src/providers/ldap/sdap_idmap.h |    3 ++
 2 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c
index e692853..c4e2fb4 100644
--- a/src/providers/ldap/sdap_idmap.c
+++ b/src/providers/ldap/sdap_idmap.c
@@ -477,3 +477,62 @@ done:
     talloc_free(dom_sid_str);
     return ret;
 }
+
+bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
+                                               const char *dom_sid)
+{
+    enum idmap_error_code err;
+    bool has_algorithmic_mapping;
+    char *new_dom_sid;
+    int ret;
+    TALLOC_CTX *tmp_ctx = NULL;
+
+    err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid,
+                                                   &has_algorithmic_mapping);
+    if (err == IDMAP_SUCCESS) {
+        return has_algorithmic_mapping;
+    } else if (err != IDMAP_SID_UNKNOWN && err != IDMAP_NO_DOMAIN) {
+        return false;
+    }
+
+    /* This is the first time we've seen this domain
+     * Create a new domain for it. We'll use the dom-sid
+     * as the domain name for now, since we don't have
+     * any way to get the real name.
+     */
+
+    if (is_domain_sid(dom_sid)) {
+        new_dom_sid = discard_const(dom_sid);
+    } else {
+        tmp_ctx = talloc_new(NULL);
+        if (tmp_ctx == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+            return false;
+        }
+
+        ret = sdap_idmap_get_dom_sid_from_object(tmp_ctx, dom_sid,
+                                                 &new_dom_sid);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Could not parse domain SID from [%s]\n", dom_sid));
+            talloc_free(tmp_ctx);
+            return false;
+        }
+    }
+
+    ret = ctx->find_new_domain(ctx, new_dom_sid, new_dom_sid);
+    talloc_free(tmp_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Could not add new domain for sid [%s]\n", dom_sid));
+        return false;
+    }
+
+    err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid,
+                                                   &has_algorithmic_mapping);
+    if (err == IDMAP_SUCCESS) {
+        return has_algorithmic_mapping;
+    }
+
+    return false;
+}
diff --git a/src/providers/ldap/sdap_idmap.h b/src/providers/ldap/sdap_idmap.h
index 45462c1..c8bc4e2 100644
--- a/src/providers/ldap/sdap_idmap.h
+++ b/src/providers/ldap/sdap_idmap.h
@@ -56,4 +56,7 @@ sdap_idmap_sid_to_unix(struct sdap_idmap_ctx *idmap_ctx,
                        const char *sid_str,
                        id_t *id);
 
+bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
+                                               const char *dom_sid);
+
 #endif /* SDAP_IDMAP_H_ */
-- 
1.7.7.6

-------------- next part --------------
From 472175c51d2125aeb57c76fe1a4c4934f4fc8295 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Jun 2013 15:47:26 +0200
Subject: [PATCH 05/11] Replace SDAP_ID_MAPPING checks with
 sdap_idmap_domain_has_algorithmic_mapping

Currently the decision if external or algorithmic mapping should be used
in the LDAP or AD provider was based on the value of the ldap_id_mapping
config option. Since now all information about ID mapping is handled by
libsss_idmap the check for this options can be replace with a call which
checks the state via libss_idmap.

https://fedorahosted.org/sssd/ticket/1961
---
 src/providers/ldap/ldap_id.c               |   14 +++++++++++---
 src/providers/ldap/ldap_id_enum.c          |    9 +++++++--
 src/providers/ldap/sdap_async_groups.c     |    4 +++-
 src/providers/ldap/sdap_async_initgroups.c |   20 +++++++++++++-------
 src/providers/ldap/sdap_async_users.c      |    5 ++++-
 5 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index d76a81a..addb2f3 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -79,6 +79,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
     uid_t uid;
     enum idmap_error_code err;
     char *sid;
+    bool use_id_mapping;
 
     req = tevent_req_create(memctx, &state, struct users_get_state);
     if (!req) return NULL;
@@ -102,6 +103,9 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
     state->name = name;
     state->filter_type = filter_type;
 
+    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                          ctx->opts->idmap_ctx,
+                                                          sdom->dom->domain_id);
     switch (filter_type) {
     case BE_FILTER_NAME:
         attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
@@ -111,7 +115,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
         }
         break;
     case BE_FILTER_IDNUM:
-        if (dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING)) {
+        if (use_id_mapping) {
             /* If we're ID-mapping, we need to use the objectSID
              * in the search filter.
              */
@@ -416,7 +420,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
     gid_t gid;
     enum idmap_error_code err;
     char *sid;
-    bool use_id_mapping = dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING);
+    bool use_id_mapping;
     const char *member_filter[2];
 
     req = tevent_req_create(memctx, &state, struct groups_get_state);
@@ -441,6 +445,10 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
     state->name = name;
     state->filter_type = filter_type;
 
+    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                          ctx->opts->idmap_ctx,
+                                                          sdom->dom->domain_id);
+
     switch(filter_type) {
     case BE_FILTER_NAME:
         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
@@ -451,7 +459,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
         }
         break;
     case BE_FILTER_IDNUM:
-        if (dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING)) {
+        if (use_id_mapping) {
             /* If we're ID-mapping, we need to use the objectSID
              * in the search filter.
              */
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 719b130..06d6e87 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -30,6 +30,7 @@
 #include "db/sysdb.h"
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_idmap.h"
 
 extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx,
                                                struct tevent_context *ev,
@@ -498,7 +499,9 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
     state->ctx = ctx;
     state->op = op;
 
-    use_mapping = dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING);
+    use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                          ctx->opts->idmap_ctx,
+                                                          sdom->dom->domain_id);
 
     /* We always want to filter on objectclass and an available name */
     state->filter = talloc_asprintf(state,
@@ -663,7 +666,9 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
     state->ctx = ctx;
     state->op = op;
 
-    use_mapping = dp_opt_get_bool(ctx->opts->basic, SDAP_ID_MAPPING);
+    use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                          ctx->opts->idmap_ctx,
+                                                          sdom->dom->domain_id);
 
     /* We always want to filter on objectclass and an available name */
     state->filter = talloc_asprintf(state,
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index 04ce2f9..c3b5914 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -435,7 +435,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     char *usn_value = NULL;
     TALLOC_CTX *tmpctx = NULL;
     bool posix_group;
-    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
+    bool use_id_mapping;
     char *sid_str;
 
     tmpctx = talloc_new(NULL);
@@ -480,6 +480,8 @@ static int sdap_save_group(TALLOC_CTX *memctx,
         sid_str = NULL;
     }
 
+    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                               sid_str);
     if (use_id_mapping) {
         posix_group = true;
 
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 7678c7b..4c379fd 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -49,7 +49,7 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
     bool posix;
     time_t now;
     char *sid_str;
-    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
+    bool use_id_mapping;
 
     /* There are no groups in LDAP but we should add user to groups ?? */
     if (ldap_groups_count == 0) return EOK;
@@ -89,6 +89,9 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
         goto done;
     }
 
+    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                             domain->domain_id);
+
     ret = sysdb_transaction_start(sysdb);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -2522,6 +2525,8 @@ struct sdap_get_initgr_state {
 
     size_t user_base_iter;
     struct sdap_search_base **user_search_bases;
+
+    bool use_id_mapping;
 };
 
 static errno_t sdap_get_initgr_next_base(struct tevent_req *req);
@@ -2590,6 +2595,10 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
         return NULL;
     }
 
+    state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                                         state->opts->idmap_ctx,
+                                                         state->dom->domain_id);
+
     ret = sdap_get_initgr_next_base(req);
 
 done:
@@ -2649,8 +2658,6 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
     const char *orig_dn;
     const char *cname;
     bool in_transaction = false;
-    bool use_id_mapping =
-            dp_opt_get_bool(state->opts->basic, SDAP_ID_MAPPING);
 
     DEBUG(9, ("Receiving info for the user\n"));
 
@@ -2753,7 +2760,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
             return;
         }
 
-        if (use_id_mapping
+        if (state->use_id_mapping
                 && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
             /* Take advantage of AD's tokenGroups mechanism to look up all
              * parent groups in a single request.
@@ -2835,7 +2842,6 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
     char *dom_sid_str;
     char *group_sid_str;
     struct sdap_options *opts = state->opts;
-    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
 
     DEBUG(9, ("Initgroups done\n"));
 
@@ -2852,7 +2858,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
 
     case SDAP_SCHEMA_RFC2307BIS:
     case SDAP_SCHEMA_AD:
-        if (use_id_mapping
+        if (state->use_id_mapping
                 && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
             ret = sdap_get_ad_tokengroups_initgroups_recv(subreq);
         }
@@ -2886,7 +2892,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
      * the user may not be an explicit member of that group
      */
 
-    if (use_id_mapping) {
+    if (state->use_id_mapping) {
         DEBUG(SSSDBG_TRACE_LIBS,
               ("Mapping primary group to unix ID\n"));
 
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
index a368965..b3a5c3d 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -122,7 +122,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
     char *usn_value = NULL;
     char **missing = NULL;
     TALLOC_CTX *tmpctx = NULL;
-    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
+    bool use_id_mapping;
     char *sid_str;
     char *dom_sid_str = NULL;
 
@@ -216,6 +216,9 @@ int sdap_save_user(TALLOC_CTX *memctx,
     }
 
 
+    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                               sid_str);
+
     /* Retrieve or map the UID as appropriate */
     if (use_id_mapping) {
 
-- 
1.7.7.6

-------------- next part --------------
From 5a5dc95b29112750d58cdf2f750299466b32c897 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 Jun 2013 12:49:46 +0200
Subject: [PATCH 06/11] Add ipa_idmap_init()

Use the sdap_idmap context for the IPA provider as well.

https://fedorahosted.org/sssd/ticket/1961
---
 Makefile.am                    |    1 +
 src/providers/ipa/ipa_common.h |    3 +
 src/providers/ipa/ipa_idmap.c  |  271 ++++++++++++++++++++++++++++++++++++++++
 src/providers/ipa/ipa_init.c   |    2 +-
 4 files changed, 276 insertions(+), 1 deletions(-)
 create mode 100644 src/providers/ipa/ipa_idmap.c

diff --git a/Makefile.am b/Makefile.am
index 0cf6d92..e211b78 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1592,6 +1592,7 @@ libsss_ipa_la_SOURCES = \
     src/providers/ipa/ipa_selinux_maps.c \
     src/providers/ipa/ipa_selinux_common.c \
     src/providers/ipa/ipa_srv.c \
+    src/providers/ipa/ipa_idmap.c \
     src/util/user_info_msg.c \
     src/util/find_uid.c \
     src/util/sss_ldap.c \
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 01130c4..6dacdc5 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -183,4 +183,7 @@ int ipa_sudo_init(struct be_ctx *be_ctx,
                   struct bet_ops **ops,
                   void **pvt_data);
 
+errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx,
+                       struct sdap_id_ctx *id_ctx,
+                       struct sdap_idmap_ctx **_idmap_ctx);
 #endif /* _IPA_COMMON_H_ */
diff --git a/src/providers/ipa/ipa_idmap.c b/src/providers/ipa/ipa_idmap.c
new file mode 100644
index 0000000..a02724f
--- /dev/null
+++ b/src/providers/ipa/ipa_idmap.c
@@ -0,0 +1,271 @@
+/*
+    SSSD
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "util/util.h"
+#include "providers/ldap/sdap_idmap.h"
+
+#define IPA_RANGE_LOCAL "ipa-local"
+#define IPA_RANGE_AD_TRUST "ipa-ad-trust"
+#define IPA_RANGE_AD_TRUST_POSIX "ipa-ad-trust-posix"
+
+static void *
+ipa_idmap_talloc(size_t size, void *pvt)
+{
+    return talloc_size(pvt, size);
+}
+
+static void
+ipa_idmap_talloc_free(void *ptr, void *pvt)
+{
+    talloc_free(ptr);
+}
+
+errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
+                                  const char *dom_name,
+                                  const char *dom_sid_str)
+{
+    int ret;
+    size_t range_count;
+    struct range_info **range_list;
+    TALLOC_CTX *tmp_ctx;
+    size_t c;
+    enum idmap_error_code err;
+    struct range_info *r;
+    struct sss_idmap_range range;
+    uint32_t rid;
+    bool external_mapping;
+    char *name;
+    char *sid;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+        return ENOMEM;
+    }
+
+    ret = sysdb_get_ranges(tmp_ctx, idmap_ctx->id_ctx->be->domain->sysdb,
+                           &range_count, &range_list);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n"));
+        goto done;
+    }
+
+    for (c = 0; c < range_count; c++) {
+        r = range_list[c];
+
+        if (r->range_type == NULL) {
+            /* Older IPA servers might not have the range_type attribute, but
+             * only support local ranges and trusts with algorithmic mapping. */
+
+            if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) {
+                /* local IPA domain */
+                rid = 0;
+                external_mapping = true;
+                name = idmap_ctx->id_ctx->be->domain->name;
+                sid = NULL;
+            } else if (r->trusted_dom_sid != NULL
+                    && r->secondary_base_rid == 0) {
+                /* trusted domain */
+                rid = r->base_rid;
+                external_mapping = false;
+                name = r->trusted_dom_sid;
+                sid = r->trusted_dom_sid;
+            } else {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Cannot determine range type, " \
+                                             "skipping id ange [%s].\n",
+                                             r->name));
+                continue;
+            }
+        } else {
+            if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) {
+                rid = 0;
+                external_mapping = true;
+                name = idmap_ctx->id_ctx->be->domain->name;
+                sid = NULL;
+            } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) {
+                rid = 0;
+                external_mapping = true;
+                name = r->trusted_dom_sid;
+                sid = r->trusted_dom_sid;
+            } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) {
+                rid = r->base_rid;
+                external_mapping = false;
+                name = r->trusted_dom_sid;
+                sid = r->trusted_dom_sid;
+            } else {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Range type [%s] not supported, " \
+                                             "skipping id range [%s].\n",
+                                             r->range_type, r->name));
+                continue;
+            }
+        }
+
+        range.min = r->base_id;
+        range.max = r->base_id + r->id_range_size -1;
+        err = sss_idmap_add_domain_ex(idmap_ctx->map, name, sid, &range,
+                                      r->name, rid, external_mapping);
+        if (err != IDMAP_SUCCESS && err != IDMAP_COLLISION) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n",
+                                        r->name));
+            ret = EIO;
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
+errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx,
+                       struct sdap_id_ctx *id_ctx,
+                       struct sdap_idmap_ctx **_idmap_ctx)
+{
+    errno_t ret;
+    TALLOC_CTX *tmp_ctx;
+    enum idmap_error_code err;
+    size_t c;
+    struct sdap_idmap_ctx *idmap_ctx = NULL;
+    struct sysdb_ctx *sysdb = id_ctx->be->domain->sysdb;
+    size_t range_count;
+    struct range_info **range_list;
+    struct range_info *r;
+    struct sss_idmap_range range;
+    uint32_t rid;
+    bool external_mapping;
+    char *name;
+    char *sid;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) return ENOMEM;
+
+    idmap_ctx = talloc_zero(tmp_ctx, struct sdap_idmap_ctx);
+    if (!idmap_ctx) {
+        ret = ENOMEM;
+        goto done;
+    }
+    idmap_ctx->id_ctx = id_ctx;
+    idmap_ctx->find_new_domain = ipa_idmap_find_new_domain;
+
+    /* Initialize the map */
+    err = sss_idmap_init(ipa_idmap_talloc, idmap_ctx,
+                         ipa_idmap_talloc_free,
+                         &idmap_ctx->map);
+    if (err != IDMAP_SUCCESS) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Could not initialize the ID map: [%s]\n",
+               idmap_error_string(err)));
+        if (err == IDMAP_OUT_OF_MEMORY) {
+            ret = ENOMEM;
+        } else {
+            ret = EINVAL;
+        }
+        goto done;
+    }
+
+
+    /* Read in any existing mappings from the cache */
+    ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list);
+    if (ret != EOK && ret != ENOENT) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Could not read ranges from the cache: [%s]\n",
+               strerror(ret)));
+        goto done;
+    }
+
+    DEBUG(SSSDBG_CONF_SETTINGS,
+          ("Initializing [%d] domains for ID-mapping\n", range_count));
+
+    for (c = 0; c < range_count; c++) {
+
+        r = range_list[c];
+
+        if (r->range_type == NULL) {
+            /* Older IPA servers might not have the range_type attribute, but
+             * only support local ranges and trusts with algorithmic mapping. */
+
+            if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) {
+                /* local IPA domain */
+                rid = 0;
+                external_mapping = true;
+                sid = NULL;
+                name = id_ctx->be->domain->name;
+            } else if (r->trusted_dom_sid != NULL
+                    && r->secondary_base_rid == 0) {
+                /* trusted domain */
+                rid = r->base_rid;
+                external_mapping = false;
+                sid = r->trusted_dom_sid;
+                name = sid;
+            } else {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Cannot determine range type, " \
+                                             "skipping id ange [%s].\n",
+                                             r->name));
+                continue;
+            }
+        } else {
+            if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) {
+                rid = 0;
+                external_mapping = true;
+                sid = NULL;
+                name = id_ctx->be->domain->name;
+            } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) {
+                rid = 0;
+                external_mapping = true;
+                sid = r->trusted_dom_sid;
+                name = sid;
+            } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) {
+                rid = r->base_rid;
+                external_mapping = false;
+                sid = r->trusted_dom_sid;
+                name = sid;
+            } else {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Range type [%s] not supported, " \
+                                             "skipping id range [%s].\n",
+                                             r->range_type, r->name));
+                continue;
+            }
+        }
+
+        range.min = r->base_id;
+        range.max = r->base_id + r->id_range_size -1;
+        err = sss_idmap_add_domain_ex(idmap_ctx->map, name, sid, &range,
+                                      r->name, rid, external_mapping);
+        if (err != IDMAP_SUCCESS) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n",
+                                        r->name));
+            ret = EIO;
+            goto done;
+        }
+    }
+
+    *_idmap_ctx = talloc_steal(mem_ctx, idmap_ctx);
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 77a5143..7297fc9 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -188,7 +188,7 @@ int sssm_ipa_id_init(struct be_ctx *bectx,
 
 
     /* Set up the ID mapping object */
-    ret = sdap_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx);
+    ret = ipa_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx);
     if (ret != EOK) goto done;
 
     ret = sdap_id_setup_tasks(sdap_ctx);
-- 
1.7.7.6

-------------- next part --------------
From 7f6ee6afd7bca1c5359f662cfdbc1e20f1a3c5cb Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 Jun 2013 13:09:00 +0200
Subject: [PATCH 07/11] Add support for new ipaRangeType attribute

Recent versions of FreeIPA support a range type attribute to allow
different type of ranges for sub/trusted-domains. If the attribute is
available it will be used, if not the right value is determined with the
help of the other idrange attributes.

Fixes https://fedorahosted.org/sssd/ticket/1961
---
 src/db/sysdb.h                     |    2 ++
 src/db/sysdb_ranges.c              |   16 ++++++++++++++++
 src/providers/ipa/ipa_common.h     |    4 ++++
 src/providers/ipa/ipa_idmap.c      |    5 +----
 src/providers/ipa/ipa_subdomains.c |   33 +++++++++++++++++++++++++++++++--
 5 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 489188b..0b99dee 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -130,6 +130,7 @@
 #define SYSDB_BASE_RID "baseRID"
 #define SYSDB_SECONDARY_BASE_RID "secondaryBaseRID"
 #define SYSDB_DOMAIN_ID "domainID"
+#define SYSDB_ID_RANGE_TYPE "idRangeType"
 
 #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)"
 
@@ -245,6 +246,7 @@ struct range_info {
     uint32_t base_rid;
     uint32_t secondary_base_rid;
     char *trusted_dom_sid;
+    char *range_type;
 };
 
 
diff --git a/src/db/sysdb_ranges.c b/src/db/sysdb_ranges.c
index cc72033..5b444ea 100644
--- a/src/db/sysdb_ranges.c
+++ b/src/db/sysdb_ranges.c
@@ -53,6 +53,7 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                            SYSDB_BASE_RID,
                            SYSDB_SECONDARY_BASE_RID,
                            SYSDB_DOMAIN_ID,
+                           SYSDB_ID_RANGE_TYPE,
                            NULL};
     struct range_info **list;
     struct ldb_dn *basedn;
@@ -140,6 +141,17 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
             DEBUG(SSSDBG_MINOR_FAILURE, ("find_attr_as_uint32_t failed.\n"));
             goto done;
         }
+
+        tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_ID_RANGE_TYPE,
+                                              NULL);
+        if (tmp_str != NULL) {
+            list[c]->range_type = talloc_strdup(list, tmp_str);
+            if (list[c]->range_type == NULL) {
+                ret = ENOMEM;
+                goto done;
+            }
+        }
+
     }
     list[res->count] = NULL;
 
@@ -228,6 +240,10 @@ errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range)
                     (unsigned long)time(NULL));
     if (ret) goto done;
 
+    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_ID_RANGE_TYPE,
+                     range->range_type);
+    if (ret) goto done;
+
     ret = ldb_add(sysdb->ldb, msg);
     if (ret) goto done;
 
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 6dacdc5..8bf2d3e 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -142,6 +142,10 @@ struct ipa_options {
     struct ipa_auth_ctx *auth_ctx;
 };
 
+#define IPA_RANGE_LOCAL "ipa-local"
+#define IPA_RANGE_AD_TRUST "ipa-ad-trust"
+#define IPA_RANGE_AD_TRUST_POSIX "ipa-ad-trust-posix"
+
 /* options parsers */
 int ipa_get_options(TALLOC_CTX *memctx,
                     struct confdb_ctx *cdb,
diff --git a/src/providers/ipa/ipa_idmap.c b/src/providers/ipa/ipa_idmap.c
index a02724f..c108ca7 100644
--- a/src/providers/ipa/ipa_idmap.c
+++ b/src/providers/ipa/ipa_idmap.c
@@ -23,10 +23,7 @@
 
 #include "util/util.h"
 #include "providers/ldap/sdap_idmap.h"
-
-#define IPA_RANGE_LOCAL "ipa-local"
-#define IPA_RANGE_AD_TRUST "ipa-ad-trust"
-#define IPA_RANGE_AD_TRUST_POSIX "ipa-ad-trust-posix"
+#include "providers/ipa/ipa_common.h"
 
 static void *
 ipa_idmap_talloc(size_t size, void *pvt)
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 76ea709..120b955 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -35,6 +35,7 @@
 #define IPA_FLATNAME "ipaNTFlatName"
 #define IPA_SID "ipaNTSecurityIdentifier"
 #define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID"
+#define IPA_RANGE_TYPE "ipaRangeType"
 
 #define IPA_BASE_ID "ipaBaseID"
 #define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
@@ -60,7 +61,7 @@ enum ipa_subdomains_req_type {
 struct ipa_subdomains_req_params {
     const char *filter;
     tevent_req_fn cb;
-    const char *attrs[8];
+    const char *attrs[9];
 };
 
 struct ipa_subdomains_ctx {
@@ -188,6 +189,34 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
             DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n"));
             goto done;
         }
+
+        ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value);
+        if (ret == EOK) {
+            range_list[c]->range_type = talloc_strdup(range_list[c], value);
+            if (range_list[c]->range_type == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+        } else if (ret == ENOENT) {
+            /* Older IPA servers might not have the range_type attribute, but
+             * only support local ranges and trusts with algorithmic mapping. */
+            if (range_list[c]->trusted_dom_sid == NULL) {
+                range_list[c]->range_type = talloc_strdup(range_list[c],
+                                                          IPA_RANGE_LOCAL);
+            } else {
+                range_list[c]->range_type = talloc_strdup(range_list[c],
+                                                          IPA_RANGE_AD_TRUST);
+            }
+        } else {
+            DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n"));
+            goto done;
+        }
+        if (range_list[c]->range_type == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+            ret = ENOMEM;
+            goto done;
+        }
     }
     range_list[c] = NULL;
 
@@ -377,7 +406,7 @@ static struct ipa_subdomains_req_params subdomain_requests[] = {
       ipa_subdomains_handler_ranges_done,
       { OBJECTCLASS, IPA_CN,
         IPA_BASE_ID, IPA_BASE_RID, IPA_SECONDARY_BASE_RID,
-        IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID, NULL
+        IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID, IPA_RANGE_TYPE, NULL
       }
     }
 };
-- 
1.7.7.6

-------------- next part --------------
From 941d34270f0727a13f06d9fd37f7e5963c72c6bd Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 27 Jun 2013 17:07:36 +0200
Subject: [PATCH 08/11] Replace new_subdomain() with find_subdomain_by_name()

new_subdomain() will create a new domain object and should not be used
anymore in the priovder code directly. Instead a reference to the domain
from the common domain object should be used.
---
 src/providers/ad/ad_access.c          |    5 ++---
 src/providers/ipa/ipa_hbac_common.c   |    4 ++--
 src/providers/ipa/ipa_subdomains_id.c |    8 +++-----
 src/providers/krb5/krb5_utils.c       |    5 ++---
 src/providers/ldap/sdap_access.c      |    5 ++---
 5 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c
index 4e4dc88..746017d 100644
--- a/src/providers/ad/ad_access.c
+++ b/src/providers/ad/ad_access.c
@@ -44,10 +44,9 @@ ad_access_handler(struct be_req *breq)
 
     /* Handle subdomains */
     if (strcasecmp(pd->domain, be_ctx->domain->name) != 0) {
-        domain = new_subdomain(breq, be_ctx->domain,
-                               pd->domain, NULL, NULL, NULL);
+        domain = find_subdomain_by_name(be_ctx->domain, pd->domain, true);
         if (domain == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
+            DEBUG(SSSDBG_OP_FAILURE, ("find_subdomain_by_name failed.\n"));
             be_req_terminate(breq, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
             return;
         }
diff --git a/src/providers/ipa/ipa_hbac_common.c b/src/providers/ipa/ipa_hbac_common.c
index 2384ba6..0473a02 100644
--- a/src/providers/ipa/ipa_hbac_common.c
+++ b/src/providers/ipa/ipa_hbac_common.c
@@ -448,9 +448,9 @@ hbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
     /* Get user the user name and groups,
      * take care of subdomain users as well */
     if (strcasecmp(pd->domain, domain->name) != 0) {
-        user_dom = new_subdomain(tmp_ctx, domain, pd->domain, NULL, NULL, NULL);
+        user_dom = find_subdomain_by_name(domain, pd->domain, true);
         if (user_dom == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
+            DEBUG(SSSDBG_OP_FAILURE, ("find_subdomain_by_name failed.\n"));
             ret = ENOMEM;
             goto done;
         }
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 7fa09bd..dc82288 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -73,12 +73,10 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
         goto fail;
     }
 
-    state->domain = new_subdomain(state, state->ctx->be->domain, ar->domain,
-                        NULL,
-                        get_flat_name_from_subdomain_name(ctx->be,ar->domain),
-                        NULL);
+    state->domain = find_subdomain_by_name(state->ctx->be->domain,
+                                           ar->domain, true);
     if (state->domain == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
+        DEBUG(SSSDBG_OP_FAILURE, ("find_subdomain_by_name failed.\n"));
         ret = ENOMEM;
         goto fail;
     }
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index 1f7ed07..4811a73 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1216,10 +1216,9 @@ errno_t get_domain_or_subdomain(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx,
 
     if (domain_name != NULL &&
         strcasecmp(domain_name, be_ctx->domain->name) != 0) {
-        *dom = new_subdomain(mem_ctx, be_ctx->domain,
-                             domain_name, NULL, NULL, NULL);
+        *dom = find_subdomain_by_name(be_ctx->domain, domain_name, true);
         if (*dom == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
+            DEBUG(SSSDBG_OP_FAILURE, ("find_subdomain_by_name failed.\n"));
             return ENOMEM;
         }
     } else {
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index e745423..53df7b0 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -110,10 +110,9 @@ sdap_access_send(TALLOC_CTX *mem_ctx,
 
     /* Get original user DN, take care of subdomain users as well */
     if (strcasecmp(pd->domain, be_ctx->domain->name) != 0) {
-        user_dom = new_subdomain(state, be_ctx->domain, pd->domain,
-                                 NULL, NULL, NULL);
+        user_dom = find_subdomain_by_name(be_ctx->domain, pd->domain, true);
         if (user_dom == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
+            DEBUG(SSSDBG_OP_FAILURE, ("find_subdomain_by_name failed.\n"));
             ret = ENOMEM;
             goto done;
         }
-- 
1.7.7.6

-------------- next part --------------
From 2d649103f0475e3b4d702dca7ee0da5118204e83 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 28 Jun 2013 18:44:49 +0200
Subject: [PATCH 09/11] IPA: read ranges before subdomains

Since FreIPA will start to support external mapping for trusted domains
as well the range type for the domain must be know before the domain
object is created. The reason is that external mapping will not use
magic private groups (mpg) while algorithmic mapping will use them.
---
 src/providers/ipa/ipa_subdomains.c |   56 +++++++++++++++++------------------
 1 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 120b955..119f44a 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -427,7 +427,7 @@ static void ipa_subdomains_retrieve(struct ipa_subdomains_ctx *ctx, struct be_re
     req_ctx->be_req = be_req;
     req_ctx->sd_ctx = ctx;
     req_ctx->search_base_iter = 0;
-    req_ctx->search_bases = ctx->search_bases;
+    req_ctx->search_bases = ctx->ranges_search_bases;
     req_ctx->current_filter = NULL;
     req_ctx->reply_count = 0;
     req_ctx->reply = NULL;
@@ -485,7 +485,7 @@ static void ipa_subdomains_get_conn_done(struct tevent_req *req)
         goto fail;
     }
 
-    ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE);
+    ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_RANGES);
     if (ret != EOK && ret != EAGAIN) {
         goto fail;
     }
@@ -601,18 +601,26 @@ static void ipa_subdomains_handler_done(struct tevent_req *req)
         }
     }
 
-
-    ctx->search_base_iter = 0;
-    ctx->search_bases = ctx->sd_ctx->ranges_search_bases;
-    ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_RANGES);
-    if (ret == EAGAIN) {
-        return;
-    } else if (ret != EOK) {
+    ret = sysdb_master_domain_update(domain);
+    if (ret != EOK) {
         goto done;
     }
 
-    DEBUG(SSSDBG_OP_FAILURE, ("No search base for ranges available.\n"));
-    ret = EINVAL;
+    if (domain->flat_name == NULL ||
+        domain->domain_id == NULL ||
+        domain->realm == 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:
     be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
@@ -655,27 +663,17 @@ static void ipa_subdomains_handler_ranges_done(struct tevent_req *req)
         goto done;
     }
 
-
-    ret = sysdb_master_domain_update(domain);
-    if (ret != EOK) {
+    ctx->search_base_iter = 0;
+    ctx->search_bases = ctx->sd_ctx->search_bases;
+    ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE);
+    if (ret == EAGAIN) {
+        return;
+    } else if (ret != EOK) {
         goto done;
     }
 
-    if (domain->flat_name == NULL ||
-        domain->domain_id == NULL ||
-        domain->realm == 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;
-    }
+    DEBUG(SSSDBG_OP_FAILURE, ("No search base for ranges available.\n"));
+    ret = EINVAL;
 
 done:
     if (ret == EOK) {
-- 
1.7.7.6

-------------- next part --------------
From e7f577bcaab87f1787b17b17e05a64ac4409573e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 27 Jun 2013 21:49:26 +0200
Subject: [PATCH 10/11] Save mpg state for subdomains

The information of a subdomain will use magic private groups (mpg) or
not will be stored together with other information about the domain in
the cache.
---
 src/db/sysdb.h                     |    4 +++-
 src/db/sysdb_subdomains.c          |   33 ++++++++++++++++++++++++++++++---
 src/providers/ad/ad_subdomains.c   |    4 +++-
 src/providers/ipa/ipa_subdomains.c |   13 ++++++++++---
 src/tests/sysdb-tests.c            |   13 ++++++++-----
 5 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 0b99dee..7045edf 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -124,6 +124,7 @@
 #define SYSDB_SUBDOMAIN_REALM "realmName"
 #define SYSDB_SUBDOMAIN_FLAT "flatName"
 #define SYSDB_SUBDOMAIN_ID "domainID"
+#define SYSDB_SUBDOMAIN_MPG "mpg"
 
 #define SYSDB_BASE_ID "baseID"
 #define SYSDB_ID_RANGE_SIZE "idRangeSize"
@@ -366,7 +367,8 @@ errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name);
 
 errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                               const char *name, const char *realm,
-                              const char *flat_name, const char *domain_id);
+                              const char *flat_name, const char *domain_id,
+                              bool mpg);
 
 errno_t sysdb_update_subdomains(struct sss_domain_info *domain);
 
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 3e0d7b4..ef248ff 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -346,7 +346,8 @@ done:
 
 errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                               const char *name, const char *realm,
-                              const char *flat_name, const char *domain_id)
+                              const char *flat_name, const char *domain_id,
+                              bool mpg)
 {
     TALLOC_CTX *tmp_ctx;
     struct ldb_message *msg;
@@ -356,12 +357,15 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                            SYSDB_SUBDOMAIN_REALM,
                            SYSDB_SUBDOMAIN_FLAT,
                            SYSDB_SUBDOMAIN_ID,
+                           SYSDB_SUBDOMAIN_MPG,
                            NULL};
     const char *tmp_str;
+    bool tmp_bool;
     bool store = false;
     int realm_flags = 0;
     int flat_flags = 0;
     int id_flags = 0;
+    int mpg_flags = 0;
     int ret;
 
     tmp_ctx = talloc_new(NULL);
@@ -390,6 +394,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
         if (realm) realm_flags = LDB_FLAG_MOD_ADD;
         if (flat_name) flat_flags = LDB_FLAG_MOD_ADD;
         if (domain_id) id_flags = LDB_FLAG_MOD_ADD;
+        mpg_flags = LDB_FLAG_MOD_ADD;
     } else if (res->count != 1) {
         ret = EINVAL;
         goto done;
@@ -415,9 +420,16 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
                 id_flags = LDB_FLAG_MOD_REPLACE;
             }
         }
+
+        tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_MPG,
+                                             !mpg);
+        if (tmp_bool != mpg) {
+            mpg_flags = LDB_FLAG_MOD_REPLACE;
+        }
     }
 
-    if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0) {
+    if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0
+            && mpg_flags == 0) {
         ret = EOK;
         goto done;
     }
@@ -429,7 +441,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
     }
     msg->dn = dn;
 
-   if (store) {
+    if (store) {
         ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL);
         if (ret != LDB_SUCCESS) {
             ret = sysdb_error_to_errno(ret);
@@ -485,6 +497,21 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
         }
     }
 
+    if (mpg_flags) {
+        ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_MPG, mpg_flags, NULL);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_MPG,
+                                 mpg ? "TRUE" : "FALSE");
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+    }
+
     ret = ldb_modify(sysdb->ldb, msg);
     if (ret != LDB_SUCCESS) {
         DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add subdomain attributes to "
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 20aaa2d..724d073 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -220,7 +220,9 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx,
         goto done;
     }
 
-    ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str);
+    /* AD subdomains are currently all mpg */
+    ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
+                                true);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n"));
         goto done;
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 119f44a..a67526c 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -23,6 +23,7 @@
 */
 
 #include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_idmap.h"
 #include "providers/ipa/ipa_subdomains.h"
 #include "providers/ipa/ipa_common.h"
 #include <ctype.h>
@@ -232,6 +233,7 @@ done:
 }
 
 static errno_t ipa_subdom_store(struct sss_domain_info *domain,
+                                struct sdap_idmap_ctx *sdap_idmap_ctx,
                                 struct sysdb_attrs *attrs)
 {
     TALLOC_CTX *tmp_ctx;
@@ -240,6 +242,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *domain,
     const char *flat;
     const char *id;
     int ret;
+    bool mpg;
 
     tmp_ctx = talloc_new(domain);
     if (tmp_ctx == NULL) {
@@ -270,7 +273,9 @@ static errno_t ipa_subdom_store(struct sss_domain_info *domain,
         goto done;
     }
 
-    ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, id);
+    mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, id);
+
+    ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, id, mpg);
     if (ret) {
         DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n"));
         goto done;
@@ -323,7 +328,8 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
             }
         } else {
             /* ok let's try to update it */
-            ret = ipa_subdom_store(domain, reply[c]);
+            ret = ipa_subdom_store(domain, ctx->sdap_id_ctx->opts->idmap_ctx,
+                                   reply[c]);
             if (ret) {
                 /* Nothing we can do about the errorr. Let's at least try
                  * to reuse the existing domain
@@ -352,7 +358,8 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
         /* Nothing we can do about the errorr. Let's at least try
          * to reuse the existing domain.
          */
-        ret = ipa_subdom_store(domain, reply[c]);
+        ret = ipa_subdom_store(domain, ctx->sdap_id_ctx->opts->idmap_ctx,
+                               reply[c]);
         if (ret) {
             DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to parse subdom data, "
                   "will try to use cached subdomain\n"));
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index db2d903..1247117 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -4486,7 +4486,7 @@ START_TEST(test_sysdb_subdomain_create)
     fail_if(ret != EOK, "Could not set up the test");
 
     ret = sysdb_subdomain_store(test_ctx->sysdb,
-                                dom1[0], dom1[1], dom1[2], dom1[3]);
+                                dom1[0], dom1[1], dom1[2], dom1[3], false);
     fail_if(ret != EOK, "Could not set up the test (dom1)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4499,7 +4499,7 @@ START_TEST(test_sysdb_subdomain_create)
             dom1[0], test_ctx->domain->subdomains->name);
 
     ret = sysdb_subdomain_store(test_ctx->sysdb,
-                                dom2[0], dom2[1], dom2[2], dom2[3]);
+                                dom2[0], dom2[1], dom2[2], dom2[3], false);
     fail_if(ret != EOK, "Could not set up the test (dom2)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4543,7 +4543,8 @@ START_TEST(test_sysdb_subdomain_store_user)
                               testdom[0], testdom[1], testdom[2], testdom[3]);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                                testdom[0], testdom[1], testdom[2], testdom[3],
+                                false);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4600,7 +4601,8 @@ START_TEST(test_sysdb_subdomain_user_ops)
                               testdom[0], testdom[1], testdom[2], testdom[3]);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                                testdom[0], testdom[1], testdom[2], testdom[3],
+                                false);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4653,7 +4655,8 @@ START_TEST(test_sysdb_subdomain_group_ops)
                               testdom[0], testdom[1], testdom[2], testdom[3]);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                                testdom[0], testdom[1], testdom[2], testdom[3],
+                                false);
     fail_if(ret != EOK, "Could not set up the test (test subdom)");
 
     ret = sysdb_update_subdomains(test_ctx->domain);
-- 
1.7.7.6

-------------- next part --------------
From f4fda42758181c06c5a7ac85a954c996f138c593 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 28 Jun 2013 10:21:57 +0200
Subject: [PATCH 11/11] Read mpg state for subdomains from cache

The mpg flag will be read from the cache for subdomains and the domain
object will be created accordingly.
---
 src/db/sysdb_subdomains.c    |   24 +++++++++++++++++++-----
 src/tests/sysdb-tests.c      |    9 ++++++---
 src/util/domain_info_utils.c |    5 +++--
 src/util/util.h              |    3 ++-
 4 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index ef248ff..58df470 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -33,9 +33,15 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
                            SYSDB_SUBDOMAIN_REALM,
                            SYSDB_SUBDOMAIN_FLAT,
                            SYSDB_SUBDOMAIN_ID,
+                           SYSDB_SUBDOMAIN_MPG,
                            NULL};
     struct sss_domain_info *dom;
     struct ldb_dn *basedn;
+    const char *name;
+    const char *realm;
+    const char *flat;
+    const char *id;
+    bool mpg;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -68,10 +74,6 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
     }
 
     for (i = 0; i < res->count; i++) {
-        const char *name;
-        const char *realm;
-        const char *flat;
-        const char *id;
 
         name = ldb_msg_find_attr_as_string(res->msgs[i], "cn", NULL);
         if (name == NULL) {
@@ -91,6 +93,9 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
         id = ldb_msg_find_attr_as_string(res->msgs[i],
                                          SYSDB_SUBDOMAIN_ID, NULL);
 
+        mpg = ldb_msg_find_attr_as_bool(res->msgs[i],
+                                        SYSDB_SUBDOMAIN_MPG, false);
+
         /* explicitly use dom->next as we need to check 'disabled' domains */
         for (dom = domain->subdomains; dom; dom = dom->next) {
             if (strcasecmp(dom->name, name) == 0) {
@@ -129,12 +134,21 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
                         goto done;
                     }
                 }
+
+                if (dom->mpg != mpg) {
+                    DEBUG(SSSDBG_TRACE_INTERNAL,
+                          ("MPG state change from [%s] to [%s]!\n",
+                           dom->mpg ? "true" : "false",
+                           mpg ? "true" : "false"));
+                    dom->mpg = mpg;
+                }
+
                 break;
             }
         }
         /* If not found in loop it is a new subdomain */
         if (dom == NULL) {
-            dom = new_subdomain(domain, domain, name, realm, flat, id);
+            dom = new_subdomain(domain, domain, name, realm, flat, id, mpg);
             if (dom == NULL) {
                 ret = ENOMEM;
                 goto done;
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 1247117..308230f 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -4540,7 +4540,8 @@ START_TEST(test_sysdb_subdomain_store_user)
     fail_if(ret != EOK, "Could not set up the test");
 
     subdomain = new_subdomain(test_ctx, test_ctx->domain,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                              testdom[0], testdom[1], testdom[2], testdom[3],
+                              false);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
@@ -4598,7 +4599,8 @@ START_TEST(test_sysdb_subdomain_user_ops)
     fail_if(ret != EOK, "Could not set up the test");
 
     subdomain = new_subdomain(test_ctx, test_ctx->domain,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                              testdom[0], testdom[1], testdom[2], testdom[3],
+                              false);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
@@ -4652,7 +4654,8 @@ START_TEST(test_sysdb_subdomain_group_ops)
     fail_if(ret != EOK, "Could not set up the test");
 
     subdomain = new_subdomain(test_ctx, test_ctx->domain,
-                              testdom[0], testdom[1], testdom[2], testdom[3]);
+                              testdom[0], testdom[1], testdom[2], testdom[3],
+                              false);
     fail_unless(subdomain != NULL, "Failed to create new subdomin.");
     ret = sysdb_subdomain_store(test_ctx->sysdb,
                                 testdom[0], testdom[1], testdom[2], testdom[3],
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index ff7a739..6553927 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -75,7 +75,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
                                       const char *name,
                                       const char *realm,
                                       const char *flat_name,
-                                      const char *id)
+                                      const char *id,
+                                      bool mpg)
 {
     struct sss_domain_info *dom;
 
@@ -133,7 +134,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
 
     dom->enumerate = false;
     dom->fqnames = true;
-    dom->mpg = true;
+    dom->mpg = mpg;
     /* FIXME: get ranges from the server */
     dom->id_min = 0;
     dom->id_max = 0xffffffff;
diff --git a/src/util/util.h b/src/util/util.h
index f66f57b..5acc67b 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -562,7 +562,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
                                       const char *name,
                                       const char *realm,
                                       const char *flat_name,
-                                      const char *id);
+                                      const char *id,
+                                      bool mpg);
 
 errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
                          struct confdb_ctx *cdb,
-- 
1.7.7.6



More information about the sssd-devel mailing list