From 6dcb100f89d0ef081771d533fed342412ac7a13f Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 6 Mar 2019 23:34:19 +0100 Subject: X509_LOOKUP_store: new X509_LOOKUP_METHOD that works by OSSL_STORE URI This is a wrapper around OSSL_STORE. This also adds necessary support functions: - X509_STORE_load_file - X509_STORE_load_path - X509_STORE_load_store - SSL_add_store_cert_subjects_to_stack - SSL_CTX_set_default_verify_store - SSL_CTX_load_verify_file - SSL_CTX_load_verify_dir - SSL_CTX_load_verify_store and deprecates X509_STORE_load_locations and SSL_CTX_load_verify_locations, as they aren't extensible. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/8442) --- ssl/ssl_cert.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ssl/ssl_conf.c | 54 +++++++++++++++++++++++++++++++++++++----- ssl/ssl_lib.c | 56 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 173 insertions(+), 11 deletions(-) (limited to 'ssl') diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index e3ad6a55ee..28fbdf8e65 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -15,6 +15,7 @@ #include "internal/o_dir.h" #include #include +#include #include #include #include @@ -782,6 +783,79 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, return ret; } +/** + * Add a container of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +static int add_uris_recursive(STACK_OF(X509_NAME) *stack, + const char *uri, int depth) +{ + int ok = 1; + OSSL_STORE_CTX *ctx = NULL; + X509 *x = NULL; + X509_NAME *xn = NULL; + + if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL) + goto err; + + while (!OSSL_STORE_eof(ctx) && !OSSL_STORE_error(ctx)) { + OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); + int infotype = info == 0 ? 0 : OSSL_STORE_INFO_get_type(info); + + if (info == NULL) + continue; + + if (infotype == OSSL_STORE_INFO_NAME) { + /* + * This is an entry in the "directory" represented by the current + * uri. if |depth| allows, dive into it. + */ + if (depth == 0) + ok = add_uris_recursive(stack, uri, depth - 1); + } else if (infotype == OSSL_STORE_INFO_CERT) { + if ((x = OSSL_STORE_INFO_get0_CERT(info)) == NULL + || (xn = X509_get_subject_name(x)) == NULL + || (xn = X509_NAME_dup(xn)) == NULL) + goto err; + if (sk_X509_NAME_find(stack, xn) >= 0) { + /* Duplicate. */ + X509_NAME_free(xn); + } else if (!sk_X509_NAME_push(stack, xn)) { + X509_NAME_free(xn); + goto err; + } + } + + OSSL_STORE_INFO_free(info); + } + + ERR_clear_error(); + goto done; + + err: + ok = 0; + done: + OSSL_STORE_close(ctx); + + return ok; +} + +int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *store) +{ + int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b) + = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp); + int ret = add_uris_recursive(stack, store, 1); + + (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); + return ret; +} + /* Build a certificate chain for current certificate */ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags) { diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 40db39b2e1..cccda866eb 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -455,10 +455,12 @@ static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) } static int do_store(SSL_CONF_CTX *cctx, - const char *CAfile, const char *CApath, int verify_store) + const char *CAfile, const char *CApath, const char *CAstore, + int verify_store) { CERT *cert; X509_STORE **st; + if (cctx->ctx) cert = cctx->ctx->cert; else if (cctx->ssl) @@ -471,27 +473,44 @@ static int do_store(SSL_CONF_CTX *cctx, if (*st == NULL) return 0; } - return X509_STORE_load_locations(*st, CAfile, CApath) > 0; + + if (CAfile != NULL && !X509_STORE_load_file(*st, CAfile)) + return 0; + if (CApath != NULL && !X509_STORE_load_path(*st, CApath)) + return 0; + if (CAstore != NULL && !X509_STORE_load_store(*st, CAstore)) + return 0; + return 1; } static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value) { - return do_store(cctx, NULL, value, 0); + return do_store(cctx, NULL, value, NULL, 0); } static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value) { - return do_store(cctx, value, NULL, 0); + return do_store(cctx, value, NULL, NULL, 0); +} + +static int cmd_ChainCAStore(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, NULL, NULL, value, 0); } static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value) { - return do_store(cctx, NULL, value, 1); + return do_store(cctx, NULL, value, NULL, 1); } static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value) { - return do_store(cctx, value, NULL, 1); + return do_store(cctx, value, NULL, NULL, 1); +} + +static int cmd_VerifyCAStore(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, NULL, NULL, value, 1); } static int cmd_RequestCAFile(SSL_CONF_CTX *cctx, const char *value) @@ -522,6 +541,20 @@ static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value) return cmd_RequestCAPath(cctx, value); } +static int cmd_RequestCAStore(SSL_CONF_CTX *cctx, const char *value) +{ + if (cctx->canames == NULL) + cctx->canames = sk_X509_NAME_new_null(); + if (cctx->canames == NULL) + return 0; + return SSL_add_store_cert_subjects_to_stack(cctx->canames, value); +} + +static int cmd_ClientCAStore(SSL_CONF_CTX *cctx, const char *value) +{ + return cmd_RequestCAStore(cctx, value); +} + #ifndef OPENSSL_NO_DH static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) { @@ -651,10 +684,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_TYPE_DIR), SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(ChainCAStore, "chainCAstore", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_STORE), SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_DIR), SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(VerifyCAStore, "verifyCAstore", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_STORE), SSL_CONF_CMD(RequestCAFile, "requestCAFile", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_FILE), SSL_CONF_CMD(ClientCAFile, NULL, @@ -665,6 +702,11 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_CMD(ClientCAPath, NULL, SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_TYPE_DIR), + SSL_CONF_CMD(RequestCAStore, "requestCAStore", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_STORE), + SSL_CONF_CMD(ClientCAStore, NULL, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_STORE), #ifndef OPENSSL_NO_DH SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 61c90218e3..2c901ff176 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -4181,10 +4181,13 @@ int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx) lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir()); if (lookup == NULL) return 0; + + /* We ignore errors, in case the directory doesn't exist */ + ERR_set_mark(); + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); - /* Clear any errors if the default directory does not exist */ - ERR_clear_error(); + ERR_pop_to_mark(); return 1; } @@ -4197,19 +4200,62 @@ int SSL_CTX_set_default_verify_file(SSL_CTX *ctx) if (lookup == NULL) return 0; + /* We ignore errors, in case the directory doesn't exist */ + ERR_set_mark(); + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); - /* Clear any errors if the default file does not exist */ - ERR_clear_error(); + ERR_pop_to_mark(); return 1; } +int SSL_CTX_set_default_verify_store(SSL_CTX *ctx) +{ + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_store()); + if (lookup == NULL) + return 0; + + /* We ignore errors, in case the directory doesn't exist */ + ERR_set_mark(); + + X509_LOOKUP_add_store(lookup, NULL); + + ERR_pop_to_mark(); + + return 1; +} + +int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile) +{ + return X509_STORE_load_file(ctx->cert_store, CAfile); +} + +int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath) +{ + return X509_STORE_load_path(ctx->cert_store, CApath); +} + +int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore) +{ + return X509_STORE_load_store(ctx->cert_store, CAstore); +} + +#if OPENSSL_API_LEVEL < 3 int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) { - return X509_STORE_load_locations(ctx->cert_store, CAfile, CApath); + if (CAfile == NULL && CApath == NULL) + return 0; + if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile)) + return 0; + if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath)) + return 0; + return 1; } +#endif void SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val)) -- cgit v1.2.3