mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-29 18:27:29 +02:00
Add a function to load system CA certs into a WOLFSSL_CTX.
This new function, wolfSSL_CTX_load_system_CA_certs, currently only supports Linux-based OS's. It searches through conventional CA directories and once it finds one, attempts to load CA certs from it. After the first directory is found, we don't check the others. This commit also adds a function wolfSSL_get_system_CA_dirs, which returns a pointer to an array of directories where wolfSSL_CTX_load_system_CA_certs will look for CA certs. This is used in a unit test, where we only want to expect success if one of these directories actually exists on the test system. Finally, this commit adds support for SSL_CTX_set_default_verify_paths to the compatibility layer. It doesn't model the exact behavior of its OpenSSL counterpart; it's mostly a wrapper around wolfSSL_CTX_load_system_CA_certs, manipulating the return value of that function to conform to OpenSSL's conventions.
This commit is contained in:
@ -1231,6 +1231,69 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
|
||||
int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
|
||||
const char* path, unsigned int flags);
|
||||
|
||||
/*!
|
||||
\ingroup CertsKeys
|
||||
|
||||
\brief This function returns a pointer to an array of strings representing
|
||||
directories wolfSSL will search for system CA certs when
|
||||
wolfSSL_CTX_load_system_CA_certs is called.
|
||||
|
||||
\return Valid pointer on success.
|
||||
\return NULL pointer on failure.
|
||||
|
||||
\param num pointer to a word32 that will be populated with the length of the
|
||||
array of strings.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
WOLFSSL_CTX* ctx;
|
||||
const char** dirs;
|
||||
word32 numDirs;
|
||||
|
||||
dirs = wolfSSL_get_system_CA_dirs(&numDirs);
|
||||
for (int i = 0; i < numDirs; ++i) {
|
||||
printf("Potential system CA dir: %s\n", dirs[i]);
|
||||
}
|
||||
...
|
||||
\endcode
|
||||
|
||||
\sa wolfSSL_CTX_load_system_CA_certs
|
||||
\sa wolfSSL_CTX_load_verify_locations
|
||||
\sa wolfSSL_CTX_load_verify_locations_ex
|
||||
*/
|
||||
const char** wolfSSL_get_system_CA_dirs(word32* num);
|
||||
|
||||
/*!
|
||||
\ingroup CertsKeys
|
||||
|
||||
\brief This function attempts to load CA certificates into a WOLFSSL_CTX
|
||||
from conventional CA cert directories, which is OS-dependent.
|
||||
|
||||
\return WOLFSSL_SUCCESS on success.
|
||||
\return WOLFSSL_BAD_PATH if no system CA certs were loaded.
|
||||
\return WOLFSSL_NOT_IMPLEMENTED if the function isn't supported for the
|
||||
target OS.
|
||||
|
||||
\param ctx pointer to the SSL context, created with wolfSSL_CTX_new().
|
||||
|
||||
_Example_
|
||||
\code
|
||||
int ret = 0;
|
||||
WOLFSSL_CTX* ctx;
|
||||
...
|
||||
ret = wolfSSL_CTX_load_system_CA_certs(ctx,);
|
||||
if (ret != WOLFSSL_SUCCESS) {
|
||||
// error loading system CA certs
|
||||
}
|
||||
...
|
||||
\endcode
|
||||
|
||||
\sa wolfSSL_get_system_CA_dirs
|
||||
\sa wolfSSL_CTX_load_verify_locations
|
||||
\sa wolfSSL_CTX_load_verify_locations_ex
|
||||
*/
|
||||
int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx);
|
||||
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
|
113
src/ssl.c
113
src/ssl.c
@ -8041,6 +8041,80 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
|
||||
return WS_RETURN_CODE(ret,WOLFSSL_FAILURE);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Potential system CA certs directories on Linux distros. */
|
||||
static const char* systemCaDirs[] = {
|
||||
"/etc/ssl/certs", /* Debian, Ubuntu, Gentoo, others */
|
||||
"/etc/pki/ca-trust/source/anchors", /* Fedora, RHEL */
|
||||
"/etc/pki/tls/certs" /* Older RHEL */
|
||||
};
|
||||
|
||||
const char** wolfSSL_get_system_CA_dirs(word32* num)
|
||||
{
|
||||
const char** ret;
|
||||
|
||||
if (num == NULL) {
|
||||
ret = NULL;
|
||||
}
|
||||
else {
|
||||
ret = systemCaDirs;
|
||||
*num = sizeof(systemCaDirs)/sizeof(*systemCaDirs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
int ret;
|
||||
#ifndef _WIN32
|
||||
word32 i;
|
||||
byte loaded = 0;
|
||||
#endif
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_CTX_load_system_CA_certs");
|
||||
|
||||
#ifdef _WIN32
|
||||
(void)ctx;
|
||||
ret = WOLFSSL_NOT_IMPLEMENTED;
|
||||
#else
|
||||
if (ctx != NULL) {
|
||||
for (i = 0; i < sizeof(systemCaDirs)/sizeof(*systemCaDirs); ++i) {
|
||||
WOLFSSL_MSG_EX("Attempting to load system CA certs from %s.",
|
||||
systemCaDirs[i]);
|
||||
/*
|
||||
* We want to keep trying to load more CAs even if one cert in
|
||||
* the directory is bad and can't be used (e.g. if one is expired),
|
||||
* so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR.
|
||||
*/
|
||||
if (wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, systemCaDirs[i],
|
||||
WOLFSSL_LOAD_FLAG_IGNORE_ERR) != WOLFSSL_SUCCESS) {
|
||||
WOLFSSL_MSG_EX("Failed to load CA certs from %s, trying "
|
||||
"next possible location.", systemCaDirs[i]);
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG_EX("Loaded CA certs from %s.",
|
||||
systemCaDirs[i]);
|
||||
loaded = 1;
|
||||
/* Stop searching after we've loaded one directory. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loaded) {
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
}
|
||||
else {
|
||||
ret = WOLFSSL_BAD_PATH;
|
||||
}
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||
/* Used to specify a peer cert to match when connecting
|
||||
@ -15961,15 +16035,42 @@ cleanup:
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
|
||||
#ifndef NO_WOLFSSL_STUB
|
||||
#ifndef NO_FILESYSTEM
|
||||
/*
|
||||
* This is an OpenSSL compatibility layer function, but it doesn't mirror
|
||||
* the exact functionality of its OpenSSL counterpart. We don't support the
|
||||
* notion of an "OpenSSL directory," nor do we support the environment
|
||||
* variables SSL_CERT_DIR or SSL_CERT_FILE. This function is simply a
|
||||
* wrapper around our native wolfSSL_CTX_load_system_CA_certs function. This
|
||||
* function does conform to OpenSSL's return value conventions, though.
|
||||
*/
|
||||
int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
/* TODO:, not needed in goahead */
|
||||
(void)ctx;
|
||||
WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
|
||||
return SSL_NOT_IMPLEMENTED;
|
||||
int ret;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths");
|
||||
|
||||
ret = wolfSSL_CTX_load_system_CA_certs(ctx);
|
||||
if (ret == WOLFSSL_BAD_PATH) {
|
||||
/*
|
||||
* OpenSSL doesn't treat the lack of a system CA cert directory as a
|
||||
* failure. We do the same here.
|
||||
*/
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
}
|
||||
else if (ret != WOLFSSL_SUCCESS) {
|
||||
/*
|
||||
* All other failure types map to WOLFSSL_FAILURE (0), same as
|
||||
* OpenSSL.
|
||||
*/
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
#if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
|
||||
&& !defined(WC_NO_RNG)
|
||||
|
72
tests/api.c
72
tests/api.c
@ -1346,6 +1346,77 @@ static int test_wolfSSL_CTX_load_verify_locations(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_wolfSSL_CTX_load_system_CA_certs(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_WOLFSSL_CLIENT)
|
||||
WOLFSSL_CTX* ctx;
|
||||
|
||||
ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
if (ctx == NULL) {
|
||||
ret = -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
#ifdef _WIN32
|
||||
if (wolfSSL_CTX_load_system_CA_certs(ctx) != WOLFSSL_NOT_IMPLEMENTED) {
|
||||
ret = -1;
|
||||
}
|
||||
#ifdef OPENSSL_EXTRA
|
||||
if (wolfSSL_CTX_set_default_verify_paths(ctx) != WOLFSSL_FAILURE) {
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
#else
|
||||
word32 numDirs;
|
||||
const char** caDirs = wolfSSL_get_system_CA_dirs(&numDirs);
|
||||
|
||||
if (caDirs == NULL || numDirs == 0) {
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
ReadDirCtx dirCtx;
|
||||
byte dirValid = 0;
|
||||
word32 i;
|
||||
|
||||
for (i = 0; i < numDirs; ++i) {
|
||||
if (wc_ReadDirFirst(&dirCtx, caDirs[i], NULL) == 0) {
|
||||
/* Directory isn't empty. */
|
||||
dirValid = 1;
|
||||
wc_ReadDirClose(&dirCtx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the directory isn't empty, we should be able to load CA
|
||||
* certs from it.
|
||||
*/
|
||||
if (dirValid && wolfSSL_CTX_load_system_CA_certs(ctx) !=
|
||||
WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
}
|
||||
#ifdef OPENSSL_EXTRA
|
||||
/*
|
||||
* Even if we don't have a valid directory to load system CA
|
||||
* certs from, the OpenSSL compat layer function should return
|
||||
* success.
|
||||
*/
|
||||
if (wolfSSL_CTX_set_default_verify_paths(ctx)
|
||||
!= WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
wolfSSL_CTX_free(ctx);
|
||||
#endif /* !NO_FILESYSTEM && !NO_CERTS && !NO_WOLFSSL_CLIENT */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
|
||||
static int test_cm_load_ca_buffer(const byte* cert_buf, size_t cert_sz, int file_type)
|
||||
{
|
||||
@ -58611,6 +58682,7 @@ TEST_CASE testCases[] = {
|
||||
TEST_DECL(test_wolfSSL_CTX_use_certificate_buffer),
|
||||
TEST_DECL(test_wolfSSL_CTX_use_PrivateKey_file),
|
||||
TEST_DECL(test_wolfSSL_CTX_load_verify_locations),
|
||||
TEST_DECL(test_wolfSSL_CTX_load_system_CA_certs),
|
||||
TEST_DECL(test_wolfSSL_CertManagerCheckOCSPResponse),
|
||||
TEST_DECL(test_wolfSSL_CheckOCSPResponse),
|
||||
TEST_DECL(test_wolfSSL_CertManagerLoadCABuffer),
|
||||
|
@ -267,6 +267,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
|
||||
#else
|
||||
#define SSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations
|
||||
#endif
|
||||
#define SSL_CTX_set_default_verify_paths wolfSSL_CTX_set_default_verify_paths
|
||||
#define SSL_CTX_use_certificate_chain_file wolfSSL_CTX_use_certificate_chain_file
|
||||
#define SSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file
|
||||
|
||||
|
@ -1070,6 +1070,13 @@ WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(
|
||||
WOLFSSL_CTX* ctx, const char* file, const char* path, word32 flags);
|
||||
WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations(
|
||||
WOLFSSL_CTX* ctx, const char* file, const char* path);
|
||||
#ifndef _WIN32
|
||||
WOLFSSL_API const char** wolfSSL_get_system_CA_dirs(word32* num);
|
||||
#endif /* !_WIN32 */
|
||||
WOLFSSL_API int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx);
|
||||
#ifdef OPENSSL_EXTRA
|
||||
WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx);
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||
WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(
|
||||
WOLFSSL_CTX* ctx, const char* file, int type);
|
||||
|
Reference in New Issue
Block a user