sssd/SOURCES/0026-ssh-do-not-mix-differe...

210 lines
7.4 KiB
Diff

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