mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
Merge pull request #5626 from haydenroche5/load_system_root_certs
Add a function to load system CA certs into a WOLFSSL_CTX.
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
|
||||
@ -16152,15 +16226,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)
|
||||
{
|
||||
@ -59130,6 +59201,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
|
||||
|
||||
|
@ -1075,6 +1075,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