URL: https://github.com/SSSD/sssd/pull/5407
Author: ikerexxe
 Title: #5407: kcm: check socket path loaded from configuration
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5407/head:pr5407
git checkout pr5407
From 318ad7e7d8fba67d4b84fd410ed01ff7991e37ae Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedr...@redhat.com>
Date: Tue, 17 Nov 2020 12:17:28 +0100
Subject: [PATCH 1/3] confdb: log message when falling back to default

Log message when string attribute is not found in database and value
falls back to default. Moreover, implement unit-test for
confdb_get_string() method.

Resolves: https://github.com/SSSD/sssd/issues/5406
---
 src/confdb/confdb.c                   |  3 +
 src/tests/cmocka/confdb/test_confdb.c | 91 +++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index d2fc018fd0..7254d8c5ae 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -411,6 +411,9 @@ int confdb_get_string(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
             return EOK;
         }
 
+        DEBUG(SSSDBG_CONF_SETTINGS,
+              "Unable to get [%s] from [%s], falling back to default [%s]\n",
+              attribute, section, defstr);
         /* Copy the default string */
         restr = talloc_strdup(ctx, defstr);
     }
diff --git a/src/tests/cmocka/confdb/test_confdb.c b/src/tests/cmocka/confdb/test_confdb.c
index daff41e5cc..7851945878 100644
--- a/src/tests/cmocka/confdb/test_confdb.c
+++ b/src/tests/cmocka/confdb/test_confdb.c
@@ -251,6 +251,88 @@ static void test_confdb_get_enabled_domain_list(void **state)
 }
 
 
+static void test_confdb_get_string_value_present(void **state)
+{
+    /*
+     * Given config_file_version exists in the configuration database
+     * And a default value is defined
+     * When config_file_version is requested
+     * Then config_file_version value is returned
+     */
+    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
+    TALLOC_CTX* tmp_ctx = talloc_new(NULL);
+    char *confdb_value;
+    int ret = EOK;
+
+    ret = confdb_get_string(test_ctx->confdb,
+                            tmp_ctx,
+                            "config/sssd",
+                            "config_file_version",
+                            NULL,
+                            &confdb_value);
+
+    assert_int_equal(EOK, ret);
+    assert_string_equal("2", confdb_value);
+
+    TALLOC_FREE(tmp_ctx);
+}
+
+
+static void test_confdb_get_string_value_not_present_fallback_default(void **state)
+{
+    /*
+     * Given non_existing_value doesn't exist in the configuration database
+     * And a default value is defined
+     * When non_existing_value is requested
+     * Then default value is returned
+     */
+    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
+    TALLOC_CTX* tmp_ctx = talloc_new(NULL);
+    char *confdb_value;
+    const char *default_value = "3";
+    int ret = EOK;
+
+    ret = confdb_get_string(test_ctx->confdb,
+                            tmp_ctx,
+                            "config/sssd",
+                            "non_existing_value",
+                            default_value,
+                            &confdb_value);
+
+    assert_int_equal(EOK, ret);
+    assert_string_equal(default_value, confdb_value);
+
+    TALLOC_FREE(tmp_ctx);
+}
+
+
+static void test_confdb_get_string_value_and_default_not_present(void **state)
+{
+    /*
+     * Given non_existing_value doesn't exist in the configuration database
+     * And a default value isn't defined
+     * When non_existing_value is requested
+     * Then NULL is returned
+     */
+    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
+    TALLOC_CTX* tmp_ctx = talloc_new(NULL);
+    char *confdb_value;
+    int ret = EOK;
+
+    ret = confdb_get_string(test_ctx->confdb,
+                            tmp_ctx,
+                            "config/sssd",
+                            "non_existing_value",
+                            NULL,
+                            &confdb_value);
+
+    assert_int_equal(EOK, ret);
+    assert_null(confdb_value);
+
+    TALLOC_FREE(tmp_ctx);
+}
+
+
 int main(int argc, const char *argv[])
 {
     poptContext pc;
@@ -272,6 +354,15 @@ int main(int argc, const char *argv[])
         cmocka_unit_test_setup_teardown(test_confdb_get_enabled_domain_list,
                                         confdb_test_setup,
                                         confdb_test_teardown),
+        cmocka_unit_test_setup_teardown(test_confdb_get_string_value_present,
+                                        confdb_test_setup,
+                                        confdb_test_teardown),
+        cmocka_unit_test_setup_teardown(test_confdb_get_string_value_not_present_fallback_default,
+                                        confdb_test_setup,
+                                        confdb_test_teardown),
+        cmocka_unit_test_setup_teardown(test_confdb_get_string_value_and_default_not_present,
+                                        confdb_test_setup,
+                                        confdb_test_teardown),
     };
 
     /* Set debug level to invalid value so we can decide if -d 0 was used. */

From 483c4e40e6bc52e326e745ffcba5964ec4e3189d Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedr...@redhat.com>
Date: Tue, 17 Nov 2020 12:27:57 +0100
Subject: [PATCH 2/3] util: extract substring from string

Implement a method to extract a substring from the start of a string
until the last match of a given character. Besides, implement unit-tests
to check that it works as expected.
---
 src/tests/cmocka/test_string_utils.c | 47 ++++++++++++++++++++++++++++
 src/tests/cmocka/test_utils.c        |  1 +
 src/tests/cmocka/test_utils.h        |  1 +
 src/util/string_utils.c              | 19 +++++++++++
 src/util/util.h                      | 18 +++++++++++
 5 files changed, 86 insertions(+)

diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c
index 57e6f2617b..7f884ef281 100644
--- a/src/tests/cmocka/test_string_utils.c
+++ b/src/tests/cmocka/test_string_utils.c
@@ -269,3 +269,50 @@ void test_concatenate_string_array(void **state)
     assert_true(check_leaks_pop(mem_ctx) == true);
     talloc_free(mem_ctx);
 }
+
+void test_extract_string_last_char_match(void **state)
+{
+    TALLOC_CTX *mem_ctx;
+    const char char_to_match = '/';
+    const char *simple_correct_string = "/tmp/abc";
+    const char *complex_correct_string = "/tmp/abc/def/ghi/jk";
+    const char *current_string = "./";
+    const char *root_string = "/";
+    const char *wrong_string = "blablablablablablablabla";
+    const char *substring;
+
+    mem_ctx = talloc_new(NULL);
+    assert_non_null(mem_ctx);
+    check_leaks_push(mem_ctx);
+
+    substring = extract_string_last_char_match(mem_ctx,
+                                                 simple_correct_string,
+                                                 char_to_match);
+    assert_string_equal("/tmp", substring);
+    talloc_free(substring);
+
+    substring = extract_string_last_char_match(mem_ctx,
+                                                 complex_correct_string,
+                                                 char_to_match);
+    assert_string_equal("/tmp/abc/def/ghi", substring);
+    talloc_free(substring);
+
+    substring = extract_string_last_char_match(mem_ctx,
+                                                 current_string,
+                                                 char_to_match);
+    assert_string_equal(".", substring);
+    talloc_free(substring);
+
+    substring = extract_string_last_char_match(mem_ctx,
+                                                 root_string,
+                                                 char_to_match);
+    assert_null(substring);
+
+    substring = extract_string_last_char_match(mem_ctx,
+                                                 wrong_string,
+                                                 char_to_match);
+    assert_null(substring);
+
+    assert_true(check_leaks_pop(mem_ctx) == true);
+    talloc_free(mem_ctx);
+}
\ No newline at end of file
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 945f5cb44a..2a17c62625 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -2075,6 +2075,7 @@ int main(int argc, const char *argv[])
         cmocka_unit_test(test_guid_blob_to_string_buf),
         cmocka_unit_test(test_get_last_x_chars),
         cmocka_unit_test(test_concatenate_string_array),
+        cmocka_unit_test(test_extract_string_last_char_match),
         cmocka_unit_test_setup_teardown(test_add_strings_lists,
                                         setup_leak_tests,
                                         teardown_leak_tests),
diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h
index 44b9479f96..c766cd976a 100644
--- a/src/tests/cmocka/test_utils.h
+++ b/src/tests/cmocka/test_utils.h
@@ -32,6 +32,7 @@ void test_reverse_replace_whitespaces(void **state);
 void test_guid_blob_to_string_buf(void **state);
 void test_get_last_x_chars(void **state);
 void test_concatenate_string_array(void **state);
+void test_extract_string_last_char_match(void **state);
 
 /* from src/tests/cmocka/test_sss_ptr_hash.c */
 void test_sss_ptr_hash_with_free_cb(void **state);
diff --git a/src/util/string_utils.c b/src/util/string_utils.c
index 1215ec96a5..847e507df1 100644
--- a/src/util/string_utils.c
+++ b/src/util/string_utils.c
@@ -146,3 +146,22 @@ char **concatenate_string_array(TALLOC_CTX *mem_ctx,
 
     return string_array;
 }
+
+const char *extract_string_last_char_match(TALLOC_CTX *mem_ctx,
+                                             const char *string,
+                                             const char character) {
+    char *substring = NULL;
+    int pos;
+
+    for (pos = strlen(string); pos > 0; pos--) {
+        if(string[pos] == '/') {
+            break;
+        }
+    }
+
+    if (pos > 0) {
+        substring = talloc_strndup(mem_ctx, string, pos);
+    }
+
+    return substring;
+}
\ No newline at end of file
diff --git a/src/util/util.h b/src/util/util.h
index fbcac5cd09..42f89c7109 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -691,6 +691,24 @@ char **concatenate_string_array(TALLOC_CTX *mem_ctx,
                                 char **arr1, size_t len1,
                                 char **arr2, size_t len2);
 
+/**
+ * @brief Extract a substring until the last match of a character
+ *
+ * Extract a substring from the start of a string until the last match of a
+ * given character.
+ *
+ * @param[in] mem_ctx      Talloc memory context for the new list.
+ * @param[in] string       String to extract from.
+ * @param[in] character    Character to find.
+ *
+ * @return                 If the character is found then return substring from
+ *                         the start until the last match of the character. If
+ *                         it isn't found, then return NULL.
+ */
+const char *extract_string_last_char_match(TALLOC_CTX *mem_ctx,
+                                             const char *string,
+                                             const char character);
+
 /* from become_user.c */
 errno_t become_user(uid_t uid, gid_t gid);
 struct sss_creds;

From c34a235c0e73cad4e16020144d63936c8920d5f4 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedr...@redhat.com>
Date: Tue, 17 Nov 2020 12:48:26 +0100
Subject: [PATCH 3/3] kcm: check socket path loaded from configuration

Check the existence of the socket path loaded from configuration. If it
doesn't contain a valid path, then log it and fail.

Besides, implement an integration test that checks if sssd_kcm fails
when kcm socket is defined in an invalid location.

Resolves: https://github.com/SSSD/sssd/issues/5406
---
 src/responder/kcm/kcm.c    | 28 ++++++++++++++++++++
 src/tests/intg/test_kcm.py | 52 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c
index f1fc958be2..f6c1a8d450 100644
--- a/src/responder/kcm/kcm.c
+++ b/src/responder/kcm/kcm.c
@@ -87,6 +87,14 @@ static int kcm_get_config(struct kcm_ctx *kctx)
 {
     int ret;
     char *sock_name;
+    const char *sock_path;
+    struct stat stat_info;
+    TALLOC_CTX *tmp_ctx = NULL;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
 
     ret = confdb_get_int(kctx->rctx->cdb,
                          CONFDB_KCM_CONF_ENTRY,
@@ -128,6 +136,25 @@ static int kcm_get_config(struct kcm_ctx *kctx)
                ret, strerror(ret));
         goto done;
     }
+
+    sock_path = extract_string_last_char_match(tmp_ctx, sock_name, '/');
+    if (sock_path != NULL) {
+        ret = stat (sock_path, &stat_info);
+
+        if (ret != 0) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Folder defined in KCM [%s = %s] doesn't exist\n",
+                  CONFDB_KCM_SOCKET, sock_name);
+            ret = ENOENT;
+            goto done;
+        }
+    } else {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "KCM [%s = %s] doesn't contain a valid path\n",
+              CONFDB_KCM_SOCKET, sock_name);
+        ret = ENOENT;
+        goto done;
+    }
     kctx->rctx->sock_name = sock_name;
 
     ret = kcm_get_ccdb_be(kctx);
@@ -156,6 +183,7 @@ static int kcm_get_config(struct kcm_ctx *kctx)
     }
     ret = EOK;
 done:
+    talloc_free(tmp_ctx);
     return ret;
 }
 
diff --git a/src/tests/intg/test_kcm.py b/src/tests/intg/test_kcm.py
index 3a43491b96..0ec7f8007b 100644
--- a/src/tests/intg/test_kcm.py
+++ b/src/tests/intg/test_kcm.py
@@ -585,3 +585,55 @@ def test_kcm_secrets_quota(setup_for_kcm_sec,
     princ = "%s%d" % ("kcmtest", MAX_SECRETS)
     out, _, _ = testenv.k5util.kinit(princ, princ)
     assert out != 0
+
+
+@pytest.fixture
+def setup_kcm_non_existing_socket_path(request, kdc_instance):
+    """
+    Just set up the local provider for tests and enable the KCM
+    responder
+    """
+    sec_resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_secrets")
+    if not os.access(sec_resp_path, os.X_OK):
+        # It would be cleaner to use pytest.mark.skipif on the package level
+        # but upstream insists on supporting RHEL-6.
+        pytest.skip("No Secrets responder, skipping")
+
+    kcm_path = os.path.join("/non_existing", "kcm.socket")
+    sssd_conf = create_sssd_conf(kcm_path, "secrets")
+
+    kcm_socket_include = unindent("""
+    [libdefaults]
+    default_ccache_name = KCM:
+    kcm_socket = {kcm_path}
+    """).format(**locals())
+    kdc_instance.add_config({'kcm_socket': kcm_socket_include})
+
+    create_conf_fixture(request, sssd_conf)
+
+
+@pytest.mark.skipif(sys.version_info < (3,3), reason="requires python3.3")
+def test_kcm_non_existing_socket_path(setup_kcm_non_existing_socket_path):
+    '''
+    Given kcm socket is defined in an invalid location
+    When sssd_kcm is launched
+    Then sssd_kcm logs failure and fails
+    '''
+    if subprocess.call(['sssd', "--genconf"]) != 0:
+        raise Exception("failed to regenerate confdb")
+
+    resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_kcm")
+    if not os.access(resp_path, os.X_OK):
+        # It would be cleaner to use pytest.mark.skipif on the package level
+        # but upstream insists on supporting RHEL-6..
+        pytest.skip("No KCM responder, skipping")
+
+    try:
+        subprocess.check_output([resp_path, "--uid=0", "--gid=0"],
+                                stderr=subprocess.STDOUT, timeout=10)
+    except subprocess.CalledProcessError as e:
+        assert e.returncode != 0
+    except subprocess.TimeoutExpired as e:
+        # If sssd_kcm time outs it means that the process continues
+        # its execution and this shouldn't happen
+        assert "", "Time out, shouldn't arrive to this point"
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org

Reply via email to