Blame SOURCES/0026-ssh-do-not-mix-different-certificate-lists.patch

0d441c
From f9b3c0d1009da8d8dbe273c38d6725100789e57b Mon Sep 17 00:00:00 2001
0d441c
From: Sumit Bose <sbose@redhat.com>
0d441c
Date: Wed, 8 Jan 2020 13:46:22 +0100
0d441c
Subject: [PATCH 26/27] ssh: do not mix different certificate lists
0d441c
MIME-Version: 1.0
0d441c
Content-Type: text/plain; charset=UTF-8
0d441c
Content-Transfer-Encoding: 8bit
0d441c
0d441c
There was a list of binary certificates and a list with base64 encoded
0d441c
ones which might be different depending on the active matching rules.
0d441c
Only the base64 one with the filtered results should be used.
0d441c
0d441c
Related to https://pagure.io/SSSD/sssd/issue/4121
0d441c
0d441c
Reviewed-by: Tomáš Halman <thalman@redhat.com>
0d441c
---
0d441c
 src/tests/cmocka/test_cert_utils.c    | 80 +++++++++++++++++++++++++++
0d441c
 src/util/cert.h                       |  3 +
0d441c
 src/util/cert/cert_common.c           | 20 +++++++
0d441c
 src/util/cert/cert_common_p11_child.c | 12 ++--
0d441c
 4 files changed, 108 insertions(+), 7 deletions(-)
0d441c
0d441c
diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c
0d441c
index 325e49f00..c2c9ca270 100644
0d441c
--- a/src/tests/cmocka/test_cert_utils.c
0d441c
+++ b/src/tests/cmocka/test_cert_utils.c
0d441c
@@ -711,6 +711,84 @@ void test_cert_to_ssh_2keys_with_certmap_send(void **state)
0d441c
     talloc_free(ev);
0d441c
 }
0d441c
 
0d441c
+void test_cert_to_ssh_2keys_with_certmap_2_done(struct tevent_req *req)
0d441c
+{
0d441c
+    int ret;
0d441c
+    struct test_state *ts = tevent_req_callback_data(req, struct test_state);
0d441c
+    struct ldb_val *keys;
0d441c
+    uint8_t *exp_key;
0d441c
+    size_t exp_key_size;
0d441c
+    size_t valid_keys;
0d441c
+
0d441c
+    assert_non_null(ts);
0d441c
+    ts->done = true;
0d441c
+
0d441c
+    ret = cert_to_ssh_key_recv(req, ts, &keys, &valid_keys);
0d441c
+    talloc_free(req);
0d441c
+    assert_int_equal(ret, 0);
0d441c
+    assert_non_null(keys[0].data);
0d441c
+    assert_int_equal(valid_keys, 1);
0d441c
+
0d441c
+    exp_key = sss_base64_decode(ts, SSSD_TEST_CERT_SSH_KEY_0002, &exp_key_size);
0d441c
+    assert_non_null(exp_key);
0d441c
+    assert_int_equal(keys[0].length, exp_key_size);
0d441c
+    assert_memory_equal(keys[0].data, exp_key, exp_key_size);
0d441c
+    talloc_free(exp_key);
0d441c
+
0d441c
+    talloc_free(keys);
0d441c
+    sss_certmap_free_ctx(ts->sss_certmap_ctx);
0d441c
+}
0d441c
+
0d441c
+void test_cert_to_ssh_2keys_with_certmap_2_send(void **state)
0d441c
+{
0d441c
+    int ret;
0d441c
+    struct tevent_context *ev;
0d441c
+    struct tevent_req *req;
0d441c
+    struct ldb_val val[2];
0d441c
+
0d441c
+    struct test_state *ts = talloc_get_type_abort(*state, struct test_state);
0d441c
+    assert_non_null(ts);
0d441c
+    ts->done = false;
0d441c
+
0d441c
+    ret = sss_certmap_init(ts, NULL, NULL, &ts->sss_certmap_ctx);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+
0d441c
+    ret = sss_certmap_add_rule(ts->sss_certmap_ctx, -1,
0d441c
+                               "<SUBJECT>CN=SSSD test cert 0002,.*", NULL,
0d441c
+                               NULL);
0d441c
+    assert_int_equal(ret, EOK);
0d441c
+
0d441c
+    val[0].data = sss_base64_decode(ts, SSSD_TEST_CERT_0001,
0d441c
+                                          &val[0].length);
0d441c
+    assert_non_null(val[0].data);
0d441c
+
0d441c
+    val[1].data = sss_base64_decode(ts, SSSD_TEST_CERT_0002,
0d441c
+                                          &val[1].length);
0d441c
+    assert_non_null(val[1].data);
0d441c
+
0d441c
+    ev = tevent_context_init(ts);
0d441c
+    assert_non_null(ev);
0d441c
+
0d441c
+    req = cert_to_ssh_key_send(ts, ev, -1, P11_CHILD_TIMEOUT,
0d441c
+#ifdef HAVE_NSS
0d441c
+                            "sql:" ABS_BUILD_DIR "/src/tests/test_CA/p11_nssdb",
0d441c
+#else
0d441c
+                            ABS_BUILD_DIR "/src/tests/test_CA/SSSD_test_CA.pem",
0d441c
+#endif
0d441c
+                            ts->sss_certmap_ctx, 2, &val[0], NULL);
0d441c
+    assert_non_null(req);
0d441c
+
0d441c
+    tevent_req_set_callback(req, test_cert_to_ssh_2keys_with_certmap_2_done, ts);
0d441c
+
0d441c
+    while (!ts->done) {
0d441c
+        tevent_loop_once(ev);
0d441c
+    }
0d441c
+
0d441c
+    talloc_free(val[0].data);
0d441c
+    talloc_free(val[1].data);
0d441c
+    talloc_free(ev);
0d441c
+}
0d441c
+
0d441c
 int main(int argc, const char *argv[])
0d441c
 {
0d441c
     poptContext pc;
0d441c
@@ -746,6 +824,8 @@ int main(int argc, const char *argv[])
0d441c
                                         setup, teardown),
0d441c
         cmocka_unit_test_setup_teardown(test_cert_to_ssh_2keys_with_certmap_send,
0d441c
                                         setup, teardown),
0d441c
+        cmocka_unit_test_setup_teardown(test_cert_to_ssh_2keys_with_certmap_2_send,
0d441c
+                                        setup, teardown),
0d441c
 #endif
0d441c
     };
0d441c
 
0d441c
diff --git a/src/util/cert.h b/src/util/cert.h
0d441c
index e0d44e3d6..d038a99f6 100644
0d441c
--- a/src/util/cert.h
0d441c
+++ b/src/util/cert.h
0d441c
@@ -52,6 +52,9 @@ errno_t get_ssh_key_from_cert(TALLOC_CTX *mem_ctx,
0d441c
                               uint8_t *der_blob, size_t der_size,
0d441c
                               uint8_t **key_blob, size_t *key_size);
0d441c
 
0d441c
+errno_t get_ssh_key_from_derb64(TALLOC_CTX *mem_ctx, const char *derb64,
0d441c
+                                uint8_t **key_blob, size_t *key_size);
0d441c
+
0d441c
 struct tevent_req *cert_to_ssh_key_send(TALLOC_CTX *mem_ctx,
0d441c
                                         struct tevent_context *ev,
0d441c
                                         int child_debug_fd, time_t timeout,
0d441c
diff --git a/src/util/cert/cert_common.c b/src/util/cert/cert_common.c
0d441c
index 766877089..511fddd4d 100644
0d441c
--- a/src/util/cert/cert_common.c
0d441c
+++ b/src/util/cert/cert_common.c
0d441c
@@ -206,3 +206,23 @@ done:
0d441c
 
0d441c
     return ret;
0d441c
 }
0d441c
+
0d441c
+errno_t get_ssh_key_from_derb64(TALLOC_CTX *mem_ctx, const char *derb64,
0d441c
+                                uint8_t **key_blob, size_t *key_size)
0d441c
+{
0d441c
+    int ret;
0d441c
+    uint8_t *der_blob;
0d441c
+    size_t der_size;
0d441c
+
0d441c
+    der_blob = sss_base64_decode(mem_ctx, derb64, &der_size);
0d441c
+    if (der_blob == NULL) {
0d441c
+        DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
0d441c
+        return EIO;
0d441c
+    }
0d441c
+
0d441c
+    ret = get_ssh_key_from_cert(mem_ctx, der_blob, der_size,
0d441c
+                                key_blob, key_size);
0d441c
+    talloc_free(der_blob);
0d441c
+
0d441c
+    return ret;
0d441c
+}
0d441c
diff --git a/src/util/cert/cert_common_p11_child.c b/src/util/cert/cert_common_p11_child.c
0d441c
index 80c10eff1..1846ff89a 100644
0d441c
--- a/src/util/cert/cert_common_p11_child.c
0d441c
+++ b/src/util/cert/cert_common_p11_child.c
0d441c
@@ -28,7 +28,6 @@ struct cert_to_ssh_key_state {
0d441c
     time_t timeout;
0d441c
     const char **extra_args;
0d441c
     const char **certs;
0d441c
-    struct ldb_val *bin_certs;
0d441c
     struct ldb_val *keys;
0d441c
     size_t cert_count;
0d441c
     size_t iter;
0d441c
@@ -74,7 +73,6 @@ struct tevent_req *cert_to_ssh_key_send(TALLOC_CTX *mem_ctx,
0d441c
     state->child_debug_fd = (child_debug_fd == -1) ? STDERR_FILENO
0d441c
                                                    : child_debug_fd;
0d441c
     state->timeout = timeout;
0d441c
-    state->bin_certs = bin_certs;
0d441c
     state->io = talloc(state, struct child_io_fds);
0d441c
     if (state->io == NULL) {
0d441c
         DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n");
0d441c
@@ -138,6 +136,7 @@ struct tevent_req *cert_to_ssh_key_send(TALLOC_CTX *mem_ctx,
0d441c
             ret = EINVAL;
0d441c
             goto done;
0d441c
         }
0d441c
+
0d441c
         state->cert_count++;
0d441c
     }
0d441c
 
0d441c
@@ -289,11 +288,10 @@ static void cert_to_ssh_key_done(int child_status,
0d441c
     if (valid) {
0d441c
         DEBUG(SSSDBG_TRACE_LIBS, "Certificate [%s] is valid.\n",
0d441c
                                   state->certs[state->iter]);
0d441c
-        ret = get_ssh_key_from_cert(state->keys,
0d441c
-                                    state->bin_certs[state->iter].data,
0d441c
-                                    state->bin_certs[state->iter].length,
0d441c
-                                    &state->keys[state->iter].data,
0d441c
-                                    &state->keys[state->iter].length);
0d441c
+        ret = get_ssh_key_from_derb64(state->keys,
0d441c
+                                      state->certs[state->iter],
0d441c
+                                      &state->keys[state->iter].data,
0d441c
+                                      &state->keys[state->iter].length);
0d441c
         if (ret == EOK) {
0d441c
             state->valid_keys++;
0d441c
         } else {
0d441c
-- 
0d441c
2.20.1
0d441c