Hi,

this patch fixes some issues in the IPA provider if the name of a
trusted domain contains upper-case characters.

bye,
Sumit
From 8cf7c2f5b1905cc0b6e61b5ef943585e235b8831 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 22 Jan 2015 17:03:00 +0100
Subject: [PATCH] IPA: properly handle mixed-case trusted domains

In the SSSD cache domain names are handled case-sensitive. As a result
fully-qualified names in RDN contain the domain part in the original
spelling. When IPA client lookup up group-memberships on the IPA server
via the extdom plugin the names returned are all lower case. To make
sure new DNs are generated correctly the domain part must adjusted.

Related to https://fedorahosted.org/sssd/ticket/2159
---
 src/providers/ipa/ipa_s2n_exop.c | 16 +++++++--
 src/tests/cmocka/test_utils.c    | 44 ++++++++++++++++++++++++
 src/util/domain_info_utils.c     | 73 ++++++++++++++++++++++++++++++++++++++++
 src/util/util.h                  |  3 ++
 4 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 
a9c2f1ae3955bc3d2707bbcd186609a8d76b6169..997d0dce8d3225f83bbce506d349e4a8705e1e95
 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -1749,6 +1749,7 @@ static errno_t ipa_s2n_save_objects(struct 
sss_domain_info *dom,
     bool in_transaction = false;
     int tret;
     struct sysdb_attrs *gid_override_attrs = NULL;
+    char ** exop_grouplist;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -2000,8 +2001,19 @@ static errno_t ipa_s2n_save_objects(struct 
sss_domain_info *dom,
                     goto done;
                 }
 
-                ret = diff_string_lists(tmp_ctx, attrs->groups, 
sysdb_grouplist,
-                                        &add_groups, &del_groups, NULL);
+                /* names returned by extdom exop will be all lower case, since
+                 * we handle domain names case sensitve in the cache we have
+                 * to make sure we use the right case. */
+                ret = fix_domain_in_name_list(tmp_ctx, dom, attrs->groups,
+                                              &exop_grouplist);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE, "fix_domain_name failed.\n");
+                    goto done;
+                }
+
+                ret = diff_string_lists(tmp_ctx, exop_grouplist,
+                                        sysdb_grouplist, &add_groups,
+                                        &del_groups, NULL);
                 if (ret != EOK) {
                     DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n");
                     goto done;
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 
f028c84b0fbe525a5af1e937e33dce484713bcb1..e04a1af3d90a3318c829e95eb1ac50be5b83e4d2
 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -1030,6 +1030,48 @@ void test_sss_write_krb5_conf_snippet(void **state)
     free(path);
 }
 
+
+void test_fix_domain_in_name_list(void **state)
+{
+    struct name_init_test_ctx *test_ctx;
+
+    int ret;
+    struct sss_domain_info *sd;
+    struct sss_domain_info *dom;
+    const char *in[] = { "a...@test.case.dom", "d...@test.case.dom", NULL};
+    char **out = NULL;
+
+    test_ctx = talloc_get_type(*state, struct name_init_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = confdb_get_domains(test_ctx->confdb, &dom);
+    assert_int_equal(ret, EOK);
+
+    ret = sss_names_init(dom, test_ctx->confdb, NULL, &dom->names);
+    assert_int_equal(ret, EOK);
+
+    sd = talloc_zero(test_ctx, struct sss_domain_info);
+    assert_non_null(sd);
+    sd->name = talloc_strdup(sd, "TesT.CasE.DoM");
+    assert_non_null(sd->name);
+    sd->names = dom->names;
+    DLIST_ADD(dom->subdomains, sd);
+    sd->parent = dom;
+
+    ret = fix_domain_in_name_list(test_ctx, dom, discard_const(in), &out);
+    assert_int_equal(ret, EOK);
+    assert_non_null(out);
+    assert_non_null(out[0]);
+    assert_string_equal(out[0], "a...@test.case.dom");
+    assert_non_null(out[1]);
+    assert_string_equal(out[1], "d...@test.case.dom");
+    assert_null(out[2]);
+
+    talloc_free(out);
+    talloc_free(sd);
+    talloc_free(dom);
+}
+
 int main(int argc, const char *argv[])
 {
     poptContext pc;
@@ -1078,6 +1120,8 @@ int main(int argc, const char *argv[])
                                  setup_add_strings_lists,
                                  teardown_add_strings_lists),
         unit_test(test_sss_write_krb5_conf_snippet),
+        unit_test_setup_teardown(test_fix_domain_in_name_list,
+                                 confdb_test_setup, confdb_test_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 
e04b905768078c503168f27327f974c0f19a6775..39870491ff290255f659df726041b670318c4095
 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -777,3 +777,76 @@ done:
 
     return ret;
 }
+
+errno_t fix_domain_in_name_list(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *dom,
+                                char **in, char ***_out)
+{
+    int ret;
+    size_t c;
+    TALLOC_CTX *tmp_ctx;
+    char **out;
+    struct sss_domain_info *head;
+    struct sss_domain_info *out_domain;
+    char *in_name;
+    char *in_domain;
+
+    head = get_domains_head(dom);
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    /* count elements */
+    for (c = 0; in[c] != NULL; c++);
+
+    out = talloc_zero_array(tmp_ctx, char *, c + 1);
+    if (out == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (c = 0; in[c] != NULL; c++) {
+        ret = sss_parse_name(tmp_ctx, head->names, in[c], &in_domain,
+                              &in_name);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sss_parse_name failed for [%s].\n",
+                                      in[c]);
+            goto done;
+        }
+
+        if (in_domain == NULL) {
+            out[c] = talloc_strdup(out, in_name);
+        } else {
+            out_domain = find_domain_by_name(head, in_domain, true);
+            if (out_domain == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "Cannot find domain with name [%s].\n", in_domain);
+                ret = EINVAL;
+                goto done;
+            }
+
+            out[c] = sss_tc_fqname(out, head->names, out_domain, in_name);
+        }
+
+        if (out[c] == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "%s failed.\n",
+                  in_domain == NULL ? "talloc_strdup" : "sss_tc_fqname");
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    *_out = talloc_steal(mem_ctx, out);
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
diff --git a/src/util/util.h b/src/util/util.h
index 
60dbf9381c5fe26e7d42d51c6f9c7df6e3ebc4be..4ee9bad113299d8fb3eabebec508c2ab4c80d4e9
 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -601,6 +601,9 @@ errno_t get_dom_names(TALLOC_CTX *mem_ctx,
                       char ***_dom_names,
                       int *_dom_names_count);
 
+errno_t fix_domain_in_name_list(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *dom,
+                                char **in, char ***_out);
 /* from util_lock.c */
 errno_t sss_br_lock_file(int fd, size_t start, size_t len,
                          int num_tries, useconds_t wait);
-- 
2.1.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to