diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 27aad6a6ce18949b037f0a8e8f09eacd38bf0c29..abbf232133fabdde228df897fc3e5acf932befea 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1828,6 +1828,7 @@ X509_F_COMMON_VERIFY_SM2:165:common_verify_sm2 X509_F_DANE_I2D:107:dane_i2d X509_F_DIR_CTRL:102:dir_ctrl X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject +X509_F_CACHE_OBJECTS:163:cache_objects X509_F_I2D_X509_AUX:151:i2d_X509_AUX X509_F_LOOKUP_CERTS_SK:152:lookup_certs_sk X509_F_NETSCAPE_SPKI_B64_DECODE:129:NETSCAPE_SPKI_b64_decode diff --git a/crypto/x509/build.info b/crypto/x509/build.info index bee9f80961f1353be9b30419c7477dfc5b9c89bc..ca7bb2a03f7415e370e3fe7fe7d3add7f5f0b935 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -5,7 +5,7 @@ SOURCE[../../libcrypto]=\ x509_set.c x509cset.c x509rset.c x509_err.c \ x509name.c x509_v3.c x509_ext.c x509_att.c \ x509type.c x509_meth.c x509_lu.c x_all.c x509_txt.c \ - x509_trs.c by_file.c by_dir.c x509_vpm.c \ + x509_trs.c by_file.c by_dir.c by_store.c x509_vpm.c \ x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \ x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c \ v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_lib.c \ diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c new file mode 100644 index 0000000000000000000000000000000000000000..b2264d71238ebea1fc8c70303734f20bacb7cf87 --- /dev/null +++ b/crypto/x509/by_store.c @@ -0,0 +1,227 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "crypto/x509.h" +#include "x509_local.h" + +/* Generic object loader, given expected type and criterion */ +static int cache_objects(X509_LOOKUP *lctx, const char *uri, + const OSSL_STORE_SEARCH *criterion, + int depth) +{ + int ok = 0; + OSSL_STORE_CTX *ctx = NULL; + X509_STORE *xstore = X509_LOOKUP_get_store(lctx); + + if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL) + return 0; + + /* + * We try to set the criterion, but don't care if it was valid or not. + * For a OSSL_STORE, it merely serves as an optimization, the expectation + * being that if the criterion couldn't be used, we will get *everything* + * from the container that the URI represents rather than the subset that + * the criterion indicates, so the biggest harm is that we cache more + * objects certs and CRLs than we may expect, but that's ok. + * + * Specifically for OpenSSL's own file: scheme, the only workable + * criterion is the BY_NAME one, which it can only apply on directories, + * but it's possible that the URI is a single file rather than a directory, + * and in that case, the BY_NAME criterion is pointless. + * + * We could very simply not apply any criterion at all here, and just let + * the code that selects certs and CRLs from the cached objects do its job, + * but it's a nice optimization when it can be applied (such as on an + * actual directory with a thousand CA certs). + */ + if (criterion != NULL) + OSSL_STORE_find(ctx, criterion); + + for (;;) { + OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); + int infotype; + + /* NULL means error or "end of file". Either way, we break. */ + if (info == NULL) + break; + + infotype = OSSL_STORE_INFO_get_type(info); + ok = 0; + + 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 = cache_objects(lctx, OSSL_STORE_INFO_get0_NAME(info), + criterion, depth - 1); + } else { + /* + * We know that X509_STORE_add_{cert|crl} increments the object's + * refcount, so we can safely use OSSL_STORE_INFO_get0_{cert,crl} + * to get them. + */ + switch (infotype) { + case OSSL_STORE_INFO_CERT: + ok = X509_STORE_add_cert(xstore, + OSSL_STORE_INFO_get0_CERT(info)); + break; + case OSSL_STORE_INFO_CRL: + ok = X509_STORE_add_crl(xstore, + OSSL_STORE_INFO_get0_CRL(info)); + break; + } + } + + OSSL_STORE_INFO_free(info); + if (!ok) + break; + } + OSSL_STORE_close(ctx); + + return ok; +} + + +/* Because OPENSSL_free is a macro and for C type match */ +static void free_uri(OPENSSL_STRING data) +{ + OPENSSL_free(data); +} + +static void by_store_free(X509_LOOKUP *ctx) +{ + STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx); + sk_OPENSSL_STRING_pop_free(uris, free_uri); +} + +static int by_store_ctrl(X509_LOOKUP *ctx, int cmd, + const char *argp, long argl, + char **retp) +{ + switch (cmd) { + case X509_L_ADD_STORE: + /* If no URI is given, use the default cert dir as default URI */ + if (argp == NULL) + argp = ossl_safe_getenv(X509_get_default_cert_dir_env()); + if (argp == NULL) + argp = X509_get_default_cert_dir(); + + { + STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx); + + if (uris == NULL) { + uris = sk_OPENSSL_STRING_new_null(); + X509_LOOKUP_set_method_data(ctx, uris); + } + return sk_OPENSSL_STRING_push(uris, OPENSSL_strdup(argp)) > 0; + } + case X509_L_LOAD_STORE: + /* This is a shortcut for quick loading of specific containers */ + return cache_objects(ctx, argp, NULL, 0); + } + + return 0; +} + +static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const OSSL_STORE_SEARCH *criterion, X509_OBJECT *ret) +{ + STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx); + int i; + int ok = 0; + + for (i = 0; i < sk_OPENSSL_STRING_num(uris); i++) { + ok = cache_objects(ctx, sk_OPENSSL_STRING_value(uris, i), criterion, + 1 /* depth */); + + if (ok) + break; + } + return ok; +} + +static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) +{ + OSSL_STORE_SEARCH *criterion = OSSL_STORE_SEARCH_by_name(name); + int ok = by_store(ctx, type, criterion, ret); + STACK_OF(X509_OBJECT) *store_objects = + X509_STORE_get0_objects(X509_LOOKUP_get_store(ctx)); + X509_OBJECT *tmp = NULL; + + OSSL_STORE_SEARCH_free(criterion); + + if (ok) + tmp = X509_OBJECT_retrieve_by_subject(store_objects, type, name); + + ok = 0; + if (tmp != NULL) { + /* + * This could also be done like this: + * + * if (tmp != NULL) { + * *ret = *tmp; + * ok = 1; + * } + * + * However, we want to exercise the documented API to the max, so + * we do it the hard way. + * + * To be noted is that X509_OBJECT_set1_* increment the refcount, + * but so does X509_STORE_CTX_get_by_subject upon return of this + * function, so we must ensure the the refcount is decremented + * before we return, or we will get a refcount leak. We cannot do + * this with X509_OBJECT_free(), though, as that will free a bit + * too much. + */ + switch (type) { + case X509_LU_X509: + ok = X509_OBJECT_set1_X509(ret, tmp->data.x509); + if (ok) + X509_free(tmp->data.x509); + break; + case X509_LU_CRL: + ok = X509_OBJECT_set1_X509_CRL(ret, tmp->data.crl); + if (ok) + X509_CRL_free(tmp->data.crl); + break; + case X509_LU_NONE: + break; + } + } + return ok; +} + +/* + * We lack the implementations for get_by_issuer_serial, get_by_fingerprint + * and get_by_alias. There's simply not enough support in the X509_LOOKUP + * or X509_STORE APIs. + */ + +static X509_LOOKUP_METHOD x509_store_lookup = { + "Load certs from STORE URIs", + NULL, /* new_item */ + by_store_free, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + by_store_ctrl, /* ctrl */ + by_store_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +X509_LOOKUP_METHOD *X509_LOOKUP_store(void) +{ + return &x509_store_lookup; +} diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c index 70d57f5274a9bdb9264869a6a21c9202036c4425..5beb7034a726cdaf72f89bb53e3b81c1422b6a08 100644 --- a/crypto/x509/x509_d2.c +++ b/crypto/x509/x509_d2.c @@ -26,32 +26,64 @@ int X509_STORE_set_default_paths(X509_STORE *ctx) return 0; X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store()); + if (lookup == NULL) + return 0; + X509_LOOKUP_add_store(lookup, NULL); + /* clear any errors */ ERR_clear_error(); return 1; } -int X509_STORE_load_locations(X509_STORE *ctx, const char *file, - const char *path) +int X509_STORE_load_file(X509_STORE *ctx, const char *file) +{ + X509_LOOKUP *lookup; + + if (file == NULL + || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file())) == NULL + || X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) == 0) + return 0; + + return 1; +} + +int X509_STORE_load_path(X509_STORE *ctx, const char *path) { X509_LOOKUP *lookup; - if (file != NULL) { - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); - if (lookup == NULL) - return 0; - if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) - return 0; - } - if (path != NULL) { - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - return 0; - if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) - return 0; - } - if ((path == NULL) && (file == NULL)) + if (path == NULL + || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir())) == NULL + || X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) == 0) + return 0; + + return 1; +} + +int X509_STORE_load_store(X509_STORE *ctx, const char *uri) +{ + X509_LOOKUP *lookup; + + if (uri == NULL + || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store())) == NULL + || X509_LOOKUP_add_store(lookup, uri) == 0) + return 0; + + return 1; +} + +/* Deprecated */ +#if OPENSSL_API_LEVEL < 3 +int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *path) +{ + if (file == NULL && path == NULL) + return 0; + if (file != NULL && !X509_STORE_load_file(ctx, file)) + return 0; + if (path != NULL && !X509_STORE_load_path(ctx, path)) return 0; return 1; } +#endif diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 35477d9cb773b9f4c6b7045955d79bd36ac59387..dbf1b48f14cde864cf9cf5793f497d7cc23a2f97 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -598,6 +598,7 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg); # define SSL_CONF_TYPE_FILE 0x2 # define SSL_CONF_TYPE_DIR 0x3 # define SSL_CONF_TYPE_NONE 0x4 +# define SSL_CONF_TYPE_STORE 0x5 /* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */ # define SSL_COOKIE_LENGTH 4096 @@ -1626,6 +1627,8 @@ __owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, const char *file); int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, const char *dir); +int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *uri); # if !OPENSSL_API_1_1_0 # define SSL_load_error_strings() \ @@ -2013,8 +2016,13 @@ __owur int SSL_client_version(const SSL *s); __owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); __owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx); __owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx); -__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath); +__owur int SSL_CTX_set_default_verify_store(SSL_CTX *ctx); +__owur int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile); +__owur int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath); +__owur int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore); +DEPRECATEDIN_3(__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, + const char *CAfile, + const char *CApath)) # define SSL_get0_session SSL_get_session/* just peek at pointer */ __owur SSL_SESSION *SSL_get_session(const SSL *ssl); __owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h index e16ad1d7c07a024da749260edbaf95521c935384..8b5f3f6dd6de05be3bce4f56455d695d31b0c890 100644 --- a/include/openssl/x509_vfy.h +++ b/include/openssl/x509_vfy.h @@ -95,6 +95,8 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); # define X509_L_FILE_LOAD 1 # define X509_L_ADD_DIR 2 +# define X509_L_ADD_STORE 3 +# define X509_L_LOAD_STORE 4 # define X509_LOOKUP_load_file(x,name,type) \ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) @@ -102,6 +104,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); # define X509_LOOKUP_add_dir(x,name,type) \ X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) +# define X509_LOOKUP_add_store(x,name) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_STORE,(name),0,NULL) + +# define X509_LOOKUP_load_store(x,name) \ + X509_LOOKUP_ctrl((x),X509_L_LOAD_STORE,(name),0,NULL) + # define X509_V_OK 0 # define X509_V_ERR_UNSPECIFIED 1 # define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 @@ -383,6 +391,7 @@ X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx); X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); X509_LOOKUP_METHOD *X509_LOOKUP_file(void); +X509_LOOKUP_METHOD *X509_LOOKUP_store(void); typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); @@ -488,8 +497,11 @@ void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx); X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx); int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); -int X509_STORE_load_locations(X509_STORE *ctx, - const char *file, const char *dir); +int X509_STORE_load_file(X509_STORE *ctx, const char *file); +int X509_STORE_load_path(X509_STORE *ctx, const char *path); +int X509_STORE_load_store(X509_STORE *ctx, const char *store); +DEPRECATEDIN_3(int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *dir)) int X509_STORE_set_default_paths(X509_STORE *ctx); #define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \ diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index e3ad6a55ee017b9bf3a8b8bba6cb87aaecb09f17..28fbdf8e659070898bea43cd9577f0f571e35868 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 40db39b2e1c51bb1372179a94dd93f262f216be4..cccda866eb8416278b8d6c59475ccf514b4b3e84 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 61c90218e38851308dd7d18abfd0b1e6aa5e85e1..2c901ff176d466510db092fedf956d9e981c4777 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)) diff --git a/util/libcrypto.num b/util/libcrypto.num index 41ab92ac0447fa38e33a5f1508cc0c4c7aca6fe7..8a88b6e8bd3af8da20c76677e8517d09435d5a20 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -2122,7 +2122,7 @@ X509_EXTENSION_create_by_NID 2168 3_0_0 EXIST::FUNCTION: i2d_RSAPrivateKey 2169 3_0_0 EXIST::FUNCTION:RSA d2i_CERTIFICATEPOLICIES 2170 3_0_0 EXIST::FUNCTION: CMAC_CTX_get0_cipher_ctx 2171 3_0_0 EXIST::FUNCTION:CMAC -X509_STORE_load_locations 2172 3_0_0 EXIST::FUNCTION: +X509_STORE_load_locations 2172 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 OBJ_find_sigid_algs 2173 3_0_0 EXIST::FUNCTION: TS_RESP_CTX_set_accuracy 2174 3_0_0 EXIST::FUNCTION:TS NETSCAPE_SPKI_get_pubkey 2175 3_0_0 EXIST::FUNCTION: @@ -4853,3 +4853,7 @@ EVP_SIGNATURE_number 4969 3_0_0 EXIST::FUNCTION: OSSL_CMP_CTX_snprint_PKIStatus 4970 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_HDR_get0_transactionID 4971 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_HDR_get0_recipNonce 4972 3_0_0 EXIST::FUNCTION:CMP +X509_LOOKUP_store 4973 3_0_0 EXIST::FUNCTION: +X509_STORE_load_file 4974 3_0_0 EXIST::FUNCTION: +X509_STORE_load_path 4975 3_0_0 EXIST::FUNCTION: +X509_STORE_load_store 4976 3_0_0 EXIST::FUNCTION: diff --git a/util/libssl.num b/util/libssl.num index 25e12ab36af35c73a0ade099a592aa5feb9af2cf..c643acbb24793d4722b0e3776a3bb80c9a3aa0ae 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -354,7 +354,7 @@ SSL_set_session_id_context 354 3_0_0 EXIST::FUNCTION: SSL_new 355 3_0_0 EXIST::FUNCTION: TLSv1_1_method 356 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_1_METHOD SSL_CTX_get_cert_store 357 3_0_0 EXIST::FUNCTION: -SSL_CTX_load_verify_locations 358 3_0_0 EXIST::FUNCTION: +SSL_CTX_load_verify_locations 358 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 SSL_SESSION_print_fp 359 3_0_0 EXIST::FUNCTION:STDIO SSL_get0_dane_tlsa 360 3_0_0 EXIST::FUNCTION: SSL_CTX_set_generate_session_id 361 3_0_0 EXIST::FUNCTION: @@ -506,3 +506,8 @@ SSL_get_async_status 506 3_0_0 EXIST::FUNCTION: SSL_sendfile 507 3_0_0 EXIST::FUNCTION: OSSL_default_cipher_list 508 3_0_0 EXIST::FUNCTION: OSSL_default_ciphersuites 509 3_0_0 EXIST::FUNCTION: +SSL_add_store_cert_subjects_to_stack 510 3_0_0 EXIST::FUNCTION: +SSL_CTX_set_default_verify_store 511 3_0_0 EXIST::FUNCTION: +SSL_CTX_load_verify_file 512 3_0_0 EXIST::FUNCTION: +SSL_CTX_load_verify_dir 513 3_0_0 EXIST::FUNCTION: +SSL_CTX_load_verify_store 514 3_0_0 EXIST::FUNCTION: