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

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