Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for loading user CA certs from a configurable Windows cert store. #688

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 185 additions & 1 deletion apps/wolfsshd/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ struct WOLFSSHD_CONFIG {
char* authKeysFile;
char* forceCmd;
char* pidFile;
char* winUserStores;
char* winUserDwFlags;
char* winUserPvPara;
WOLFSSHD_CONFIG* next; /* next config in list */
long loginTimer;
word16 port;
Expand All @@ -89,6 +92,8 @@ struct WOLFSSHD_CONFIG {
byte permitRootLogin:1;
byte permitEmptyPasswords:1;
byte authKeysFileSet:1; /* if not set then no explicit authorized keys */
byte useSystemCA:1;
byte useUserCAStore:1;
};

int CountWhitespace(const char* in, int inSz, byte inv);
Expand Down Expand Up @@ -312,6 +317,9 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
FreeString(&current->hostKeyFile, heap);
FreeString(&current->hostCertFile, heap);
FreeString(&current->pidFile, heap);
FreeString(&current->winUserStores, heap);
FreeString(&current->winUserDwFlags, heap);
FreeString(&current->winUserPvPara, heap);

WFREE(current, heap, DYNTYPE_SSHD);
current = next;
Expand Down Expand Up @@ -350,9 +358,14 @@ enum {
OPT_TRUSTED_USER_CA_KEYS = 21,
OPT_PIDFILE = 22,
OPT_BANNER = 23,
OPT_TRUSTED_SYSTEM_CA_KEYS = 24,
OPT_TRUSTED_USER_CA_STORE = 25,
OPT_WIN_USER_STORES = 26,
OPT_WIN_USER_DW_FLAGS = 27,
OPT_WIN_USER_PV_PARA = 28
};
enum {
NUM_OPTIONS = 24
NUM_OPTIONS = 29
};

static const CONFIG_OPTION options[NUM_OPTIONS] = {
Expand Down Expand Up @@ -380,6 +393,11 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
{OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"},
{OPT_PIDFILE, "PidFile"},
{OPT_BANNER, "Banner"},
{OPT_TRUSTED_SYSTEM_CA_KEYS, "wolfSSH_TrustedSystemCAKeys"},
{OPT_TRUSTED_USER_CA_STORE, "wolfSSH_TrustedUserCaStore"},
{OPT_WIN_USER_STORES, "wolfSSH_WinUserStores"},
{OPT_WIN_USER_DW_FLAGS, "wolfSSH_WinUserDwFlags"},
{OPT_WIN_USER_PV_PARA, "wolfSSH_WinUserPvPara"},
};

/* returns WS_SUCCESS on success */
Expand Down Expand Up @@ -1021,12 +1039,27 @@ 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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows specific stuff should have a guard around it.

ret = wolfSSHD_ConfigSetSystemCA(*conf, value);
break;
case OPT_PIDFILE:
ret = SetFileString(&(*conf)->pidFile, value, (*conf)->heap);
break;
case OPT_BANNER:
ret = SetFileString(&(*conf)->banner, value, (*conf)->heap);
break;
case OPT_TRUSTED_USER_CA_STORE:
ret = wolfSSHD_ConfigSetUserCAStore(*conf, value);
break;
case OPT_WIN_USER_STORES:
ret = wolfSSHD_ConfigSetWinUserStores(*conf, value);
break;
case OPT_WIN_USER_DW_FLAGS:
ret = wolfSSHD_ConfigSetWinUserDwFlags(*conf, value);
break;
case OPT_WIN_USER_PV_PARA:
ret = wolfSSHD_ConfigSetWinUserPvPara(*conf, value);
break;
default:
break;
}
Expand Down Expand Up @@ -1309,6 +1342,157 @@ 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;
}

/* getter function for if using user CA store
* return 1 if true and 0 if false */
int wolfSSHD_ConfigGetUserCAStore(const WOLFSSHD_CONFIG* conf)
{
if (conf != NULL) {
return conf->useUserCAStore;
}
return 0;
}


/* setter function for if using user CA store
* 'yes' if true and 'no' if false
* returns WS_SUCCESS on success */
int wolfSSHD_ConfigSetUserCAStore(WOLFSSHD_CONFIG* conf, const char* value)
{
int ret = WS_SUCCESS;

if (conf != NULL) {
if (WSTRCMP(value, "yes") == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User CA store enabled. Note this "
"is currently only supported on Windows.");
conf->useUserCAStore = 1;
}
else if (WSTRCMP(value, "no") == 0) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User CA store disabled");
conf->useUserCAStore = 0;
}
else {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] User CA store unexpected flag");
ret = WS_FATAL_ERROR;
}
}

return ret;
}

char* wolfSSHD_ConfigGetWinUserStores(WOLFSSHD_CONFIG* conf) {
if (conf != NULL) {
if (conf->winUserStores == NULL) {
/* If no value was specified, default to CERT_STORE_PROV_SYSTEM */
CreateString(&conf->winUserStores, "CERT_STORE_PROV_SYSTEM",
(int)WSTRLEN("CERT_STORE_PROV_SYSTEM"), conf->heap);
}

return conf->winUserStores;
}

return NULL;
}

int wolfSSHD_ConfigSetWinUserStores(WOLFSSHD_CONFIG* conf, const char* value) {
int ret = WS_SUCCESS;

if (conf == NULL) {
ret = WS_BAD_ARGUMENT;
}

ret = CreateString(&conf->winUserStores, value, (int)WSTRLEN(value), conf->heap);

return ret;
}

char* wolfSSHD_ConfigGetWinUserDwFlags(WOLFSSHD_CONFIG* conf) {
if (conf != NULL) {
if (conf->winUserDwFlags == NULL) {
/* If no value was specified, default to CERT_SYSTEM_STORE_CURRENT_USER */
CreateString(&conf->winUserDwFlags, "CERT_SYSTEM_STORE_CURRENT_USER",
(int)WSTRLEN("CERT_SYSTEM_STORE_CURRENT_USER"), conf->heap);
}

return conf->winUserDwFlags;
}

return NULL;
}

int wolfSSHD_ConfigSetWinUserDwFlags(WOLFSSHD_CONFIG* conf, const char* value) {
int ret = WS_SUCCESS;

if (conf == NULL) {
ret = WS_BAD_ARGUMENT;
}

ret = CreateString(&conf->winUserDwFlags, value, (int)WSTRLEN(value), conf->heap);

return ret;
}

char* wolfSSHD_ConfigGetWinUserPvPara(WOLFSSHD_CONFIG* conf) {
if (conf != NULL) {
if (conf->winUserPvPara == NULL) {
/* If no value was specified, default to MY */
CreateString(&conf->winUserPvPara, "MY", (int)WSTRLEN("MY"), conf->heap);
}

return conf->winUserPvPara;
}

return NULL;
}

int wolfSSHD_ConfigSetWinUserPvPara(WOLFSSHD_CONFIG* conf, const char* value) {
int ret = WS_SUCCESS;

if (conf == NULL) {
ret = WS_BAD_ARGUMENT;
}

ret = CreateString(&conf->winUserPvPara, value, (int)WSTRLEN(value), conf->heap);

return ret;
}

char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf)
{
char* ret = NULL;
Expand Down
10 changes: 10 additions & 0 deletions apps/wolfsshd/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ char* wolfSSHD_ConfigGetHostCertFile(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetUserCAKeysFile(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_ConfigSetUserCAStore(WOLFSSHD_CONFIG* conf, const char* value);
int wolfSSHD_ConfigGetUserCAStore(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetWinUserStores(WOLFSSHD_CONFIG* conf);
int wolfSSHD_ConfigSetWinUserStores(WOLFSSHD_CONFIG* conf, const char* value);
char* wolfSSHD_ConfigGetWinUserDwFlags(WOLFSSHD_CONFIG* conf);
int wolfSSHD_ConfigSetWinUserDwFlags(WOLFSSHD_CONFIG* conf, const char* value);
char* wolfSSHD_ConfigGetWinUserPvPara(WOLFSSHD_CONFIG* conf);
int wolfSSHD_ConfigSetWinUserPvPara(WOLFSSHD_CONFIG* conf, const char* value);
int wolfSSHD_ConfigSetUserCAKeysFile(WOLFSSHD_CONFIG* conf, const char* file);
word16 wolfSSHD_ConfigGetPort(const WOLFSSHD_CONFIG* conf);
char* wolfSSHD_ConfigGetAuthKeysFile(const WOLFSSHD_CONFIG* conf);
Expand Down
50 changes: 50 additions & 0 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,56 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
#endif /* WOLFSSH_OSSH_CERTS || WOLFSSH_CERTS */

#ifdef WOLFSSH_CERTS
/* check if loading in system and/or user CA certs */
#ifdef WOLFSSL_SYS_CA_CERTS
if (ret == WS_SUCCESS && (wolfSSHD_ConfigGetSystemCA(conf)
|| wolfSSHD_ConfigGetUserCAStore(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 (wolfSSHD_ConfigGetSystemCA(conf)) {
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 (wolfSSHD_ConfigGetUserCAStore(conf)) {
if (wolfSSL_CTX_load_windows_user_CA_certs(sslCtx,
wolfSSHD_ConfigGetWinUserStores(conf),
wolfSSHD_ConfigGetWinUserDwFlags(conf),
wolfSSHD_ConfigGetWinUserPvPara(conf)) != WOLFSSL_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Issue loading user 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);
}
}
#endif

/* load in CA certs from file set */
if (ret == WS_SUCCESS) {
char* caCert = wolfSSHD_ConfigGetUserCAKeysFile(conf);
if (caCert != NULL) {
Expand Down
2 changes: 0 additions & 2 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -2855,8 +2855,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
#endif /* NO_WOLFSSH_SERVER */


void wolfSSL_Debugging_ON(void);

int wolfSSH_Echoserver(int argc, char** argv)
{
func_args args;
Expand Down
21 changes: 20 additions & 1 deletion src/certman.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#endif


#include <wolfssl/ssl.h>
#include <wolfssl/ocsp.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/error-ssl.h>
Expand Down Expand Up @@ -84,6 +83,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;
Expand Down
4 changes: 4 additions & 0 deletions wolfssh/certman.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <wolfssh/settings.h>
#include <wolfssh/port.h>
#include <wolfssl/ssl.h> /* included for WOLFSSL_CERT_MANAGER struct */

#ifdef __cplusplus
extern "C" {
Expand All @@ -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);

Expand Down
5 changes: 4 additions & 1 deletion wolfssh/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,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,
Expand Down Expand Up @@ -1186,7 +1187,9 @@ static int Base16_Decode(const byte* in, word32 inLen,
*outLen = outIdx;
return 0;
}

#else
#include <wolfssl/wolfcrypt/coding.h>
#endif /* !WOLFSSL_BASE16 */

static void FreeBins(byte* b1, byte* b2, byte* b3, byte* b4)
{
Expand Down
Loading