URL: https://github.com/SSSD/sssd/pull/496
Author: sumit-bose
 Title: #496: sysdb: sanitize search filter input - backport sssd-1-13
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/496/head:pr496
git checkout pr496
From 3849861953424249c0f093b5a53fb906c67b3864 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Tue, 15 Nov 2016 15:15:35 +0100
Subject: [PATCH 1/6] cache_req: add object by id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This request returns either user or group object.

Resolves:
https://fedorahosted.org/sssd/ticket/3151

Reviewed-by: Lukáš Slebodník <lsleb...@redhat.com>
(cherry picked from commit 3be2628d8aba6aeb99ac1484da990f1fad8169ec)
Only sysdb changes were cherry picked from previous commit
(cherry picked from commit f84055ee1c4ad60219e5d9b2ea5cc4dd6e1112eb)
---
 src/db/sysdb.h     | 14 +++++++++++
 src/db/sysdb_ops.c | 74 +++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 8f844cde4..f6f7a78d3 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -198,6 +198,8 @@
 
 #define SYSDB_SID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_SID_STR"=%s))"
 #define SYSDB_UUID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_UUID"=%s))"
+#define SYSDB_NAME_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_NAME"=%s))"
+#define SYSDB_ID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))(|("SYSDB_UIDNUM"=%u)("SYSDB_GIDNUM"=%u)))"
 #define SYSDB_USER_CERT_FILTER "(&("SYSDB_UC")%s)"
 
 #define SYSDB_HAS_ENUMERATED "has_enumerated"
@@ -1172,6 +1174,18 @@ errno_t sysdb_idmap_get_mappings(TALLOC_CTX *mem_ctx,
                                  struct sss_domain_info *domain,
                                  struct ldb_result **_result);
 
+errno_t sysdb_search_object_by_id(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  uint32_t id,
+                                  const char **attrs,
+                                  struct ldb_result **res);
+
+errno_t sysdb_search_object_by_name(TALLOC_CTX *mem_ctx,
+                                    struct sss_domain_info *domain,
+                                    const char *name,
+                                    const char **attrs,
+                                    struct ldb_result **res);
+
 errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
                                    struct sss_domain_info *domain,
                                    const char *sid_str,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 96db53f83..32a62a2ce 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3662,12 +3662,11 @@ errno_t sysdb_remove_attrs(struct sss_domain_info *domain,
     return ret;
 }
 
-static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
-                                   struct sss_domain_info *domain,
-                                   const char *filter_tmpl,
-                                   const char *str,
-                                   const char **attrs,
-                                   struct ldb_result **_res)
+static errno_t sysdb_search_object_attr(TALLOC_CTX *mem_ctx,
+                                        struct sss_domain_info *domain,
+                                        const char *filter,
+                                        const char **attrs,
+                                        struct ldb_result **_res)
 {
     TALLOC_CTX *tmp_ctx;
     const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM,
@@ -3691,9 +3690,9 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
-                     basedn, LDB_SCOPE_SUBTREE, attrs?attrs:def_attrs,
-                     filter_tmpl, str);
+    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, basedn,
+                     LDB_SCOPE_SUBTREE, attrs ? attrs : def_attrs,
+                     "%s", filter);
     if (ret != EOK) {
         ret = sysdb_error_to_errno(ret);
         DEBUG(SSSDBG_OP_FAILURE, "ldb_search failed.\n");
@@ -3701,9 +3700,9 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
     }
 
     if (res->count > 1) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Search for [%s]  with filter [%s] " \
-                                   "returned more than one object.\n",
-                                   str, filter_tmpl);
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Search with filter [%s] returned more than one object.\n",
+              filter);
         ret = EINVAL;
         goto done;
     } else if (res->count == 0) {
@@ -3724,6 +3723,57 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
     return ret;
 }
 
+static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
+                                               struct sss_domain_info *domain,
+                                               const char *filter_tmpl,
+                                               const char *str,
+                                               const char **attrs,
+                                               struct ldb_result **_res)
+{
+    char *filter;
+    errno_t ret;
+
+    filter = talloc_asprintf(NULL, filter_tmpl, str);
+    if (filter == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, _res);
+
+    talloc_free(filter);
+    return ret;
+}
+
+errno_t sysdb_search_object_by_id(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  uint32_t id,
+                                  const char **attrs,
+                                  struct ldb_result **res)
+{
+    char *filter;
+    errno_t ret;
+
+    filter = talloc_asprintf(NULL, SYSDB_ID_FILTER, id, id);
+    if (filter == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, res);
+
+    talloc_free(filter);
+    return ret;
+}
+
+errno_t sysdb_search_object_by_name(TALLOC_CTX *mem_ctx,
+                                    struct sss_domain_info *domain,
+                                    const char *name,
+                                    const char **attrs,
+                                    struct ldb_result **res)
+{
+    return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_NAME_FILTER,
+                                           name, attrs, res);
+}
+
 errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
                                    struct sss_domain_info *domain,
                                    const char *sid_str,

From 902e2bf3d8e871954a030159d3d51fc3fc797c48 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Sat, 21 Jan 2017 21:03:54 +0100
Subject: [PATCH 2/6] sysdb: Search also aliases in sysdb_search_object_by_name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

sysdb_search_object_by_name did not work well case insensitive domain.

Resolves:
https://fedorahosted.org/sssd/ticket/3284

Reviewed-by: Pavel Březina <pbrez...@redhat.com>
(cherry picked from commit 8a4a2b87f51462ac22bf6db93927484841f098c6)
(cherry picked from commit 64ef6ab9a432d6fdd231d5f96887ecabeb2fc39e)
---
 src/db/sysdb.h     |  2 +-
 src/db/sysdb_ops.c | 31 +++++++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index f6f7a78d3..803338888 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -198,7 +198,7 @@
 
 #define SYSDB_SID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_SID_STR"=%s))"
 #define SYSDB_UUID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_UUID"=%s))"
-#define SYSDB_NAME_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_NAME"=%s))"
+#define SYSDB_NAME_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
 #define SYSDB_ID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))(|("SYSDB_UIDNUM"=%u)("SYSDB_GIDNUM"=%u)))"
 #define SYSDB_USER_CERT_FILTER "(&("SYSDB_UC")%s)"
 
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 32a62a2ce..3df02b163 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3770,8 +3770,35 @@ errno_t sysdb_search_object_by_name(TALLOC_CTX *mem_ctx,
                                     const char **attrs,
                                     struct ldb_result **res)
 {
-    return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_NAME_FILTER,
-                                           name, attrs, res);
+    TALLOC_CTX *tmp_ctx;
+    char *filter;
+    char *sanitized_name;
+    char *sanitized_alias_name;
+    errno_t ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain, &sanitized_name,
+                                      &sanitized_alias_name);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    filter = talloc_asprintf(tmp_ctx, SYSDB_NAME_FILTER, sanitized_alias_name,
+                             sanitized_name);
+    if (filter == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, res);
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
 }
 
 errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,

From 6cbade6867c88773389e397cd47cc25e18163960 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Mon, 23 Jan 2017 07:36:14 +0100
Subject: [PATCH 3/6] sysdb-tests: Add test for sysdb_search_object_by_name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reviewed-by: Pavel Březina <pbrez...@redhat.com>
(cherry picked from commit daf3714bd3f772934025894c534aa902f0b8f98f)
(cherry picked from commit 4814454b846cbe9682e0bbcfcf9e0fe98b5181f3)
+ create equivalent of test_data_new_group for 1.13 due to sysdb
  refactoring in newer branches
---
 src/tests/sysdb-tests.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 33e0f4873..d4d823a25 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -258,6 +258,26 @@ static struct test_data *test_data_new_user(struct sysdb_test_ctx *test_ctx,
     return data;
 }
 
+static struct test_data *test_data_new_group(struct sysdb_test_ctx *test_ctx,
+                                             gid_t gid)
+{
+    struct test_data *data;
+
+    data = test_data_new(test_ctx);
+    if (data == NULL) {
+        return NULL;
+    }
+
+    data->gid = gid;
+    data->groupname = talloc_asprintf(data, "testgroup%d", gid);
+    if (data->groupname == NULL) {
+        talloc_free(data);
+        return NULL;
+    }
+
+    return data;
+}
+
 static int test_add_user(struct test_data *data)
 {
     char *homedir;
@@ -5387,6 +5407,119 @@ START_TEST(test_sysdb_search_object_by_uuid)
 }
 END_TEST
 
+START_TEST(test_sysdb_search_object_by_name)
+{
+    errno_t ret;
+    struct sysdb_test_ctx *test_ctx;
+    struct ldb_result *res;
+    struct test_data *data;
+    const char *user_name = "John Doe";
+    const char *group_name = "Domain Users";
+    const char *lc_group_name = "domain users";
+    const char *returned_name;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Could not set up the test");
+
+    /* test for missing entry */
+    ret = sysdb_search_object_by_name(test_ctx, test_ctx->domain,
+                                      "nonexisting_name", NULL, &res);
+    fail_unless(ret == ENOENT, "sysdb_search_object_by_name failed with "
+                               "[%d][%s].", ret, strerror(ret));
+
+    /* test user search */
+    data = test_data_new_user(test_ctx, 23456);
+    fail_if(data == NULL);
+
+    data->username = user_name;
+
+    ret = test_add_user(data);
+    fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_name(test_ctx, test_ctx->domain,
+                                      user_name, NULL, &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_name failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, ""),
+    fail_unless(strcmp(returned_name, data->username) == 0,
+                "Unexpected object found, expected [%s], got [%s].",
+                user_name, returned_name);
+    talloc_free(res);
+
+    ret = test_remove_user(data);
+    fail_unless(ret == EOK,
+                "test_remove_user failed with [%d][%s].", ret, strerror(ret));
+
+    /* test group search */
+    data = test_data_new_group(test_ctx, 23456);
+    fail_if(data == NULL);
+
+    data->groupname = group_name;
+
+    ret = test_add_group(data);
+    fail_unless(ret == EOK, "sysdb_add_group failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_name(test_ctx, test_ctx->domain,
+                                      group_name, NULL, &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_name failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, ""),
+    fail_unless(strcmp(returned_name, data->groupname) == 0,
+                "Unexpected object found, expected [%s], got [%s].",
+                group_name, returned_name);
+    talloc_free(res);
+
+    ret = test_remove_group(data);
+    fail_unless(ret == EOK,
+                "test_remove_group failed with [%d][%s].", ret, strerror(ret));
+
+    /* test case insensitive search */
+    data = test_data_new_group(test_ctx, 23456);
+    fail_if(data == NULL);
+
+    data->groupname = group_name;
+    test_ctx->domain->case_sensitive = false;
+
+    data->attrs = sysdb_new_attrs(test_ctx);
+    fail_if(data->attrs == NULL);
+
+    ret = sysdb_attrs_add_lc_name_alias(data->attrs, group_name);
+    fail_unless(ret == EOK);
+
+    ret = test_add_group(data);
+    fail_unless(ret == EOK, "sysdb_add_group failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_name(test_ctx, test_ctx->domain,
+                                      lc_group_name, NULL, &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_name failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, ""),
+    fail_unless(strcmp(returned_name, data->groupname) == 0,
+                "Unexpected object found, expected [%s], got [%s].",
+                group_name, returned_name);
+
+    talloc_free(res);
+
+    talloc_free(test_ctx);
+}
+END_TEST
+
 /* For simple searches the content of the certificate does not matter */
 #define TEST_USER_CERT_DERB64 "gJznJT7L0aETU5CMk+n+1Q=="
 START_TEST(test_sysdb_search_user_by_cert)
@@ -6627,6 +6760,9 @@ Suite *create_sysdb_suite(void)
     /* Test UUID string searches */
     tcase_add_test(tc_sysdb, test_sysdb_search_object_by_uuid);
 
+    /* Test object by name */
+    tcase_add_test(tc_sysdb, test_sysdb_search_object_by_name);
+
     /* Test user by certificate searches */
     tcase_add_test(tc_sysdb, test_sysdb_search_user_by_cert);
 

From 69fe5514b2133d098bc0c1f00bb2671bff4abe8d Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Sat, 21 Jan 2017 19:07:45 +0100
Subject: [PATCH 4/6] SYSDB: Update filter for get object by id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Resolves:
https://fedorahosted.org/sssd/ticket/3283

Reviewed-by: Pavel Březina <pbrez...@redhat.com>
(cherry picked from commit 2a2014d706478561e6f7dc938751bc224a93fee5)
(cherry picked from commit 353853d479225ba7a625658e58a3af989de909a5)
---
 src/db/sysdb.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 803338888..967218490 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -199,7 +199,7 @@
 #define SYSDB_SID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_SID_STR"=%s))"
 #define SYSDB_UUID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_UUID"=%s))"
 #define SYSDB_NAME_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
-#define SYSDB_ID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))(|("SYSDB_UIDNUM"=%u)("SYSDB_GIDNUM"=%u)))"
+#define SYSDB_ID_FILTER "(|(&("SYSDB_UC")("SYSDB_UIDNUM"=%u))(&("SYSDB_GC")("SYSDB_GIDNUM"=%u)))"
 #define SYSDB_USER_CERT_FILTER "(&("SYSDB_UC")%s)"
 
 #define SYSDB_HAS_ENUMERATED "has_enumerated"

From 968e2be3fbf567b9c5562ba03c5ef1b31d242c29 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Mon, 23 Jan 2017 08:05:26 +0100
Subject: [PATCH 5/6] sysdb-tests: Add test for sysdb_search_object_by_id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reviewed-by: Pavel Březina <pbrez...@redhat.com>
(cherry picked from commit 1266980705981445961864ee2eb0ea21aea4287d)
(cherry picked from commit e358dd7b4992da4c4aa7b7f769bd597222715127)
---
 src/tests/sysdb-tests.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index d4d823a25..23c0ed518 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -5359,6 +5359,127 @@ START_TEST(test_sysdb_search_sid_str)
 }
 END_TEST
 
+START_TEST(test_sysdb_search_object_by_id)
+{
+    errno_t ret;
+    struct sysdb_test_ctx *test_ctx;
+    struct ldb_result *res;
+    struct test_data *data;
+    const uint32_t id = 23456;
+    uint32_t returned_id;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Could not set up the test");
+
+    /* test for missing entry */
+    ret = sysdb_search_object_by_id(test_ctx, test_ctx->domain, 111, NULL,
+                                    &res);
+    fail_unless(ret == ENOENT, "sysdb_search_object_by_name failed with "
+                               "[%d][%s].", ret, strerror(ret));
+
+    /* test user search */
+    data = test_data_new_user(test_ctx, id);
+    fail_if(data == NULL);
+
+    ret = test_add_user(data);
+    fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_id(test_ctx, test_ctx->domain, id, NULL,
+                                    &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_id failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_id = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_UIDNUM, 0);
+    fail_unless(id == returned_id,
+                "Unexpected object found, expected UID [%"PRIu32"], "
+                "got [%"PRIu32"].", id, returned_id);
+    talloc_free(res);
+
+    ret = test_remove_user(data);
+    fail_unless(ret == EOK,
+                "test_remove_user failed with [%d][%s].", ret, strerror(ret));
+
+    /* test group search */
+    data = test_data_new_group(test_ctx, id);
+    fail_if(data == NULL);
+
+    ret = test_add_group(data);
+    fail_unless(ret == EOK, "sysdb_add_group failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_id(test_ctx, test_ctx->domain, id, NULL,
+                                    &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_id failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_id = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
+    fail_unless(id == returned_id,
+                "Unexpected object found, expected GID [%"PRIu32"], "
+                "got [%"PRIu32"].", id, returned_id);
+    talloc_free(res);
+
+    ret = test_remove_group(data);
+    fail_unless(ret == EOK,
+                "test_remove_group failed with [%d][%s].", ret, strerror(ret));
+
+    /* test for bad search filter bug #3283 */
+    data = test_data_new_group(test_ctx, id);
+    fail_if(data == NULL);
+
+    ret = test_add_group(data);
+    fail_unless(ret == EOK, "sysdb_add_group failed with [%d][%s].",
+                ret, strerror(ret));
+
+    test_ctx->domain->mpg = false;
+    ret = sysdb_add_user(test_ctx->domain, "user1", 4001, id,
+                         "User 1", "/home/user1", "/bin/bash",
+                         NULL, NULL, 0, 0);
+    fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_add_user(test_ctx->domain, "user2", 4002, id,
+                         "User 2", "/home/user2", "/bin/bash",
+                         NULL, NULL, 0, 0);
+    fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].",
+                ret, strerror(ret));
+
+    ret = sysdb_search_object_by_id(test_ctx, test_ctx->domain, id, NULL,
+                                    &res);
+    fail_unless(ret == EOK,
+                "sysdb_search_object_by_id failed with [%d][%s].",
+                ret, strerror(ret));
+    fail_unless(res->count == 1, "Unexpected number of results, "
+                                 "expected [%u], get [%u].", 1, res->count);
+
+    returned_id = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
+    fail_unless(id == returned_id,
+                "Unexpected object found, expected GID [%"PRIu32"], "
+                "got [%"PRIu32"].", id, returned_id);
+    talloc_free(res);
+
+    data->uid = 4001;
+    ret = test_remove_user_by_uid(data);
+    fail_unless(ret == EOK);
+
+    data->uid = 4002;
+    ret = test_remove_user_by_uid(data);
+    fail_unless(ret == EOK);
+
+    ret = test_remove_group(data);
+    fail_unless(ret == EOK);
+
+    talloc_free(test_ctx);
+}
+END_TEST
+
 START_TEST(test_sysdb_search_object_by_uuid)
 {
     errno_t ret;
@@ -6757,6 +6878,9 @@ Suite *create_sysdb_suite(void)
     /* Test SID string searches */
     tcase_add_test(tc_sysdb, test_sysdb_search_sid_str);
 
+    /* Test object by ID searches */
+    tcase_add_test(tc_sysdb, test_sysdb_search_object_by_id);
+
     /* Test UUID string searches */
     tcase_add_test(tc_sysdb, test_sysdb_search_object_by_uuid);
 

From efd07fe87cc7ed50fff741135ed96e7d02652c80 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 5 Oct 2017 11:07:38 +0200
Subject: [PATCH 6/6] sysdb: sanitize search filter input
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch sanitizes the input for sysdb searches by UPN/email, SID and
UUID.

This security issue was assigned CVE-2017-12173

Resolves:
https://pagure.io/SSSD/sssd/issue/3549

Reviewed-by: Lukáš Slebodník <lsleb...@redhat.com>
Reviewed-by: Jakub Hrozek <jhro...@redhat.com>
(cherry picked from commit 1f2662c8f97c9c0fa250055d4b6750abfc6d0835)
(cherry picked from commit e45e50e4523e36f310d7ff0b052500c024c434bf)
---
 src/db/sysdb_ops.c      | 43 +++++++++++++++++++++++++++++++++++--------
 src/tests/sysdb-tests.c |  7 +++++++
 2 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 3df02b163..7680cfe7e 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -494,6 +494,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
     int ret;
     const char *def_attrs[] = { SYSDB_NAME, SYSDB_UPN, SYSDB_CANONICAL_UPN,
                                 NULL };
+    char *sanitized;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -501,6 +502,12 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    ret = sss_filter_sanitize(tmp_ctx, upn, &sanitized);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize failed.\n");
+        goto done;
+    }
+
     base_dn = sysdb_base_dn(domain->sysdb, tmp_ctx);
     if (base_dn == NULL) {
         ret = ENOMEM;
@@ -509,7 +516,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
 
     ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
                      base_dn, LDB_SCOPE_SUBTREE, attrs ? attrs : def_attrs,
-                     SYSDB_PWUPN_FILTER, upn, upn);
+                     SYSDB_PWUPN_FILTER, sanitized, sanitized);
     if (ret != EOK) {
         ret = sysdb_error_to_errno(ret);
         goto done;
@@ -3730,16 +3737,30 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
                                                const char **attrs,
                                                struct ldb_result **_res)
 {
-    char *filter;
+    char *filter = NULL;
     errno_t ret;
+    char *sanitized = NULL;
+
+    if (str == NULL) {
+        return EINVAL;
+    }
+
+    ret = sss_filter_sanitize(NULL, str, &sanitized);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize failed.\n");
+        goto done;
+    }
 
-    filter = talloc_asprintf(NULL, filter_tmpl, str);
+    filter = talloc_asprintf(NULL, filter_tmpl, sanitized);
     if (filter == NULL) {
-        return ENOMEM;
+        ret = ENOMEM;
+        goto done;
     }
 
     ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, _res);
 
+done:
+    talloc_free(sanitized);
     talloc_free(filter);
     return ret;
 }
@@ -3828,7 +3849,8 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx,
                                     struct ldb_result **res)
 {
     int ret;
-    char *user_filter;
+    char *user_filter = NULL;
+    char *filter = NULL;
 
     ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_CERT,
                                          &user_filter);
@@ -3837,10 +3859,15 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx,
         return ret;
     }
 
-    ret = sysdb_search_object_by_str_attr(mem_ctx, domain,
-                                          SYSDB_USER_CERT_FILTER,
-                                          user_filter, attrs, res);
+    filter = talloc_asprintf(NULL, SYSDB_USER_CERT_FILTER, user_filter);
     talloc_free(user_filter);
+    if (filter == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, res);
+
+    talloc_free(filter);
 
     return ret;
 }
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 23c0ed518..8eab46747 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -6266,6 +6266,13 @@ START_TEST(test_upn_basic)
     fail_unless(strcmp(str, UPN_PRINC) == 0,
                 "Expected [%s], got [%s].", UPN_PRINC, str);
 
+    /* check if input is sanitized */
+    ret = sysdb_search_user_by_upn(test_ctx, test_ctx->domain,
+                                   "a...@def.ghi)(name="UPN_USER_NAME")(abc=xyz",
+                                   NULL, &msg);
+    fail_unless(ret == ENOENT,
+                "sysdb_search_user_by_upn failed with un-sanitized input.");
+
     talloc_free(test_ctx);
 }
 END_TEST
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to