From f9b3c0d1009da8d8dbe273c38d6725100789e57b Mon Sep 17 00:00:00 2001 From: Sumit Bose 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 --- 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, + "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