From 37e75d4aa022cf4e07e8841868aa0c9efeb2e8e3 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 12 Sep 2023 14:15:23 -0700 Subject: [PATCH] add TrustedSystemCAKeys sshd option for system CA load --- apps/wolfsshd/configuration.c | 46 ++++++++++++++++++++++++++++++++++- apps/wolfsshd/configuration.h | 2 ++ apps/wolfsshd/wolfsshd.c | 33 +++++++++++++++++++++++++ src/certman.c | 21 +++++++++++++++- wolfssh/certman.h | 4 +++ wolfssh/test.h | 3 +-- 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/apps/wolfsshd/configuration.c b/apps/wolfsshd/configuration.c index a06e6a6f..ad54379a 100644 --- a/apps/wolfsshd/configuration.c +++ b/apps/wolfsshd/configuration.c @@ -109,6 +109,7 @@ struct WOLFSSHD_CONFIG { byte permitEmptyPasswords:1; byte authKeysFileSet:1; /* if not set then no explicit authorized keys */ byte strictModes:1; /* enforce file permission/ownership checks */ + byte useSystemCA:1; }; /* Maximum depth of nested Include directives. Bounds the recursion @@ -434,9 +435,10 @@ enum { OPT_PUBKEY_AUTH = 24, OPT_STRICT_MODES = 25, OPT_AUTHORIZED_UPN_DOMAINS = 26, + OPT_TRUSTED_SYSTEM_CA_KEYS = 27, }; enum { - NUM_OPTIONS = 27 + NUM_OPTIONS = 28 }; /* bit in WOLFSSHD_CONFIG.setMask recording that option 'o' was set on a node. @@ -474,6 +476,7 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = { {OPT_FORCE_CMD, "ForceCommand"}, {OPT_HOST_CERT, "HostCertificate"}, {OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"}, + {OPT_TRUSTED_SYSTEM_CA_KEYS, "TrustedSystemCAKeys"}, {OPT_PIDFILE, "PidFile"}, {OPT_BANNER, "Banner"}, {OPT_STRICT_MODES, "StrictModes"}, @@ -1342,6 +1345,9 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt, /* TODO: Add logic to check if file exists? */ ret = wolfSSHD_ConfigSetUserCAKeysFile(*conf, value); break; + case OPT_TRUSTED_SYSTEM_CA_KEYS: + ret = wolfSSHD_ConfigSetSystemCA(*conf, value); + break; case OPT_PIDFILE: ret = SetFileString(&(*conf)->pidFile, value, (*conf)->heap); break; @@ -1818,6 +1824,44 @@ char* wolfSSHD_ConfigGetHostCertFile(const WOLFSSHD_CONFIG* conf) return ret; } + +/* getter function for if using system CAs + * return 1 if true and 0 if false */ +int wolfSSHD_ConfigGetSystemCA(const WOLFSSHD_CONFIG* conf) +{ + if (conf != NULL) { + return conf->useSystemCA; + } + return 0; +} + + +/* setter function for if using system CAs + * 'yes' if true and 'no' if false + * returns WS_SUCCESS on success */ +int wolfSSHD_ConfigSetSystemCA(WOLFSSHD_CONFIG* conf, const char* value) +{ + int ret = WS_SUCCESS; + + if (conf != NULL) { + if (WSTRCMP(value, "yes") == 0) { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] System CAs enabled"); + conf->useSystemCA = 1; + } + else if (WSTRCMP(value, "no") == 0) { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] System CAs disabled"); + conf->useSystemCA = 0; + } + else { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] System CAs unexpected flag"); + ret = WS_FATAL_ERROR; + } + } + + return ret; +} + + char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf) { char* ret = NULL; diff --git a/apps/wolfsshd/configuration.h b/apps/wolfsshd/configuration.h index 5608f5e3..5dc9b0b1 100644 --- a/apps/wolfsshd/configuration.h +++ b/apps/wolfsshd/configuration.h @@ -64,6 +64,8 @@ char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetAuthorizedUPNDomains(const WOLFSSHD_CONFIG* conf); int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file); int wolfSSHD_ConfigSetHostCertFile(WOLFSSHD_CONFIG* conf, const char* file); +int wolfSSHD_ConfigSetSystemCA(WOLFSSHD_CONFIG* conf, const char* value); +int wolfSSHD_ConfigGetSystemCA(const WOLFSSHD_CONFIG* conf); int wolfSSHD_ConfigSetUserCAKeysFile(WOLFSSHD_CONFIG* conf, const char* file); word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf); char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf); diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 6ab96326..549ef6bb 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -570,6 +570,39 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx, #endif /* WOLFSSH_OSSH_CERTS || WOLFSSH_CERTS */ #ifdef WOLFSSH_CERTS + /* check if loading in system CA certs */ + if (ret == WS_SUCCESS && wolfSSHD_ConfigGetSystemCA(conf)) { + WOLFSSL_CTX* sslCtx; + + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using system CAs"); + sslCtx = wolfSSL_CTX_new(wolfSSLv23_method()); + if (sslCtx == NULL) { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Unable to create temporary CTX"); + ret = WS_FATAL_ERROR; + } + + if (ret == WS_SUCCESS) { + if (wolfSSL_CTX_load_system_CA_certs(sslCtx) != WOLFSSL_SUCCESS) { + wolfSSH_Log(WS_LOG_INFO, "[SSHD] Issue loading system CAs"); + ret = WS_FATAL_ERROR; + } + } + + if (ret == WS_SUCCESS) { + if (wolfSSH_SetCertManager(*ctx, + wolfSSL_CTX_GetCertManager(sslCtx)) != WS_SUCCESS) { + wolfSSH_Log(WS_LOG_INFO, + "[SSHD] Issue copying over system CAs"); + ret = WS_FATAL_ERROR; + } + } + + if (sslCtx != NULL) { + wolfSSL_CTX_free(sslCtx); + } + } + + /* load in CA certs from file set */ if (ret == WS_SUCCESS) { char* caCert = wolfSSHD_ConfigGetUserCAKeysFile(conf); if (caCert != NULL) { diff --git a/src/certman.c b/src/certman.c index d68e813b..a75b71db 100644 --- a/src/certman.c +++ b/src/certman.c @@ -36,7 +36,6 @@ #endif -#include #include #include #include @@ -85,6 +84,26 @@ struct WOLFSSH_CERTMAN { }; +/* used to import an external cert manager, frees and replaces existing manager + * returns WS_SUCCESS on success + */ +int wolfSSH_SetCertManager(WOLFSSH_CTX* ctx, WOLFSSL_CERT_MANAGER* cm) +{ + if (ctx == NULL || cm == NULL) { + return WS_BAD_ARGUMENT; + } + + /* free up existing cm if present */ + if (ctx->certMan != NULL && ctx->certMan->cm != NULL) { + wolfSSL_CertManagerFree(ctx->certMan->cm); + } + wolfSSL_CertManager_up_ref(cm); + ctx->certMan->cm = cm; + + return WS_SUCCESS; +} + + static WOLFSSH_CERTMAN* _CertMan_init(WOLFSSH_CERTMAN* cm, void* heap) { WOLFSSH_CERTMAN* ret = NULL; diff --git a/wolfssh/certman.h b/wolfssh/certman.h index f8073555..854b15e8 100644 --- a/wolfssh/certman.h +++ b/wolfssh/certman.h @@ -30,6 +30,7 @@ #include #include +#include /* included for WOLFSSL_CERT_MANAGER struct */ #ifdef __cplusplus extern "C" { @@ -40,6 +41,9 @@ struct WOLFSSH_CERTMAN; typedef struct WOLFSSH_CERTMAN WOLFSSH_CERTMAN; +WOLFSSH_API +int wolfSSH_SetCertManager(WOLFSSH_CTX* ctx, WOLFSSL_CERT_MANAGER* cm); + WOLFSSH_API WOLFSSH_CERTMAN* wolfSSH_CERTMAN_new(void* heap); diff --git a/wolfssh/test.h b/wolfssh/test.h index a03f4368..ebeefc52 100644 --- a/wolfssh/test.h +++ b/wolfssh/test.h @@ -1167,6 +1167,7 @@ static INLINE void build_addr_ipv6(struct sockaddr_in6* addr, const char* peer, #define BAD 0xFF +#ifndef WOLFSSL_BASE16 static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -1236,10 +1237,8 @@ static int Base16_Decode(const byte* in, word32 inLen, *outLen = outIdx; return 0; } - #endif /* !WOLFSSL_BASE16 */ - static void FreeBins(byte* b1, byte* b2, byte* b3, byte* b4) { if (b1 != NULL) free(b1);