Skip to content

Commit 6c4188b

Browse files
add Windows cert store use with signing and add example arguments
1 parent 6f7b777 commit 6c4188b

11 files changed

Lines changed: 1485 additions & 136 deletions

File tree

apps/wolfsshd/configuration.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ struct WOLFSSHD_CONFIG {
7474
char* hostKeyFile;
7575
char* hostCertFile;
7676
char* userCAKeysFile;
77+
#ifdef USE_WINDOWS_API
78+
#ifdef WOLFSSH_CERTS
79+
char* hostKeyStore;
80+
char* hostKeyStoreSubject;
81+
char* hostKeyStoreFlags;
82+
#endif /* WOLFSSH_CERTS */
83+
#endif /* USE_WINDOWS_API */
7784
char* hostKeyAlgos;
7885
char* kekAlgos;
7986
char* listenAddress;
@@ -316,6 +323,13 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
316323
FreeString(&current->authKeysFile, heap);
317324
FreeString(&current->hostKeyFile, heap);
318325
FreeString(&current->hostCertFile, heap);
326+
#ifdef USE_WINDOWS_API
327+
#ifdef WOLFSSH_CERTS
328+
FreeString(&current->hostKeyStore, heap);
329+
FreeString(&current->hostKeyStoreSubject, heap);
330+
FreeString(&current->hostKeyStoreFlags, heap);
331+
#endif /* WOLFSSH_CERTS */
332+
#endif /* USE_WINDOWS_API */
319333
FreeString(&current->pidFile, heap);
320334
FreeString(&current->winUserStores, heap);
321335
FreeString(&current->winUserDwFlags, heap);
@@ -346,6 +360,13 @@ enum {
346360
OPT_PROTOCOL = 9,
347361
OPT_LOGIN_GRACE_TIME = 10,
348362
OPT_HOST_KEY = 11,
363+
#ifdef USE_WINDOWS_API
364+
#ifdef WOLFSSH_CERTS
365+
OPT_HOST_KEY_STORE = 50,
366+
OPT_HOST_KEY_STORE_SUBJECT = 51,
367+
OPT_HOST_KEY_STORE_FLAGS = 52,
368+
#endif /* WOLFSSH_CERTS */
369+
#endif /* USE_WINDOWS_API */
349370
OPT_PASSWORD_AUTH = 12,
350371
OPT_PORT = 13,
351372
OPT_PERMIT_ROOT = 14,
@@ -366,6 +387,11 @@ enum {
366387
};
367388
enum {
368389
NUM_OPTIONS = 29
390+
#ifdef USE_WINDOWS_API
391+
#ifdef WOLFSSH_CERTS
392+
+ 3
393+
#endif /* WOLFSSH_CERTS */
394+
#endif /* USE_WINDOWS_API */
369395
};
370396

371397
static const CONFIG_OPTION options[NUM_OPTIONS] = {
@@ -380,6 +406,17 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
380406
{OPT_ACCEPT_ENV, "AcceptEnv"},
381407
{OPT_PROTOCOL, "Protocol"},
382408
{OPT_LOGIN_GRACE_TIME, "LoginGraceTime"},
409+
/* The config parser uses strncmp with the option-name length, so longer
410+
* option names that share a common prefix MUST appear before the shorter
411+
* one. HostKeyStoreSubject/HostKeyStoreFlags before HostKeyStore,
412+
* and all HostKeyStore* before HostKey. */
413+
#ifdef USE_WINDOWS_API
414+
#ifdef WOLFSSH_CERTS
415+
{OPT_HOST_KEY_STORE_SUBJECT, "HostKeyStoreSubject"},
416+
{OPT_HOST_KEY_STORE_FLAGS, "HostKeyStoreFlags"},
417+
{OPT_HOST_KEY_STORE, "HostKeyStore"},
418+
#endif /* WOLFSSH_CERTS */
419+
#endif /* USE_WINDOWS_API */
383420
{OPT_HOST_KEY, "HostKey"},
384421
{OPT_PASSWORD_AUTH, "PasswordAuthentication"},
385422
{OPT_PORT, "Port"},
@@ -397,7 +434,7 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
397434
{OPT_TRUSTED_USER_CA_STORE, "wolfSSH_TrustedUserCaStore"},
398435
{OPT_WIN_USER_STORES, "wolfSSH_WinUserStores"},
399436
{OPT_WIN_USER_DW_FLAGS, "wolfSSH_WinUserDwFlags"},
400-
{OPT_WIN_USER_PV_PARA, "wolfSSH_WinUserPvPara"},
437+
{OPT_WIN_USER_PV_PARA, "wolfSSH_WinUserPvPara"}
401438
};
402439

403440
/* returns WS_SUCCESS on success */
@@ -1060,6 +1097,27 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
10601097
case OPT_WIN_USER_PV_PARA:
10611098
ret = wolfSSHD_ConfigSetWinUserPvPara(*conf, value);
10621099
break;
1100+
#ifdef USE_WINDOWS_API
1101+
#ifdef WOLFSSH_CERTS
1102+
case OPT_HOST_KEY_STORE:
1103+
wolfSSH_Log(WS_LOG_INFO,
1104+
"[SSHD] Parsed HostKeyStore = '%s'", value);
1105+
ret = SetFileString(&(*conf)->hostKeyStore, value, (*conf)->heap);
1106+
break;
1107+
case OPT_HOST_KEY_STORE_SUBJECT:
1108+
wolfSSH_Log(WS_LOG_INFO,
1109+
"[SSHD] Parsed HostKeyStoreSubject = '%s'", value);
1110+
ret = SetFileString(&(*conf)->hostKeyStoreSubject, value,
1111+
(*conf)->heap);
1112+
break;
1113+
case OPT_HOST_KEY_STORE_FLAGS:
1114+
wolfSSH_Log(WS_LOG_INFO,
1115+
"[SSHD] Parsed HostKeyStoreFlags = '%s'", value);
1116+
ret = SetFileString(&(*conf)->hostKeyStoreFlags, value,
1117+
(*conf)->heap);
1118+
break;
1119+
#endif /* WOLFSSH_CERTS */
1120+
#endif /* USE_WINDOWS_API */
10631121
default:
10641122
break;
10651123
}
@@ -1526,6 +1584,45 @@ int SetFileString(char** dst, const char* src, void* heap)
15261584
return ret;
15271585
}
15281586

1587+
#ifdef USE_WINDOWS_API
1588+
#ifdef WOLFSSH_CERTS
1589+
char* wolfSSHD_ConfigGetHostKeyStore(const WOLFSSHD_CONFIG* conf)
1590+
{
1591+
char* ret = NULL;
1592+
1593+
if (conf != NULL) {
1594+
ret = conf->hostKeyStore;
1595+
}
1596+
1597+
return ret;
1598+
}
1599+
1600+
1601+
char* wolfSSHD_ConfigGetHostKeyStoreSubject(const WOLFSSHD_CONFIG* conf)
1602+
{
1603+
char* ret = NULL;
1604+
1605+
if (conf != NULL) {
1606+
ret = conf->hostKeyStoreSubject;
1607+
}
1608+
1609+
return ret;
1610+
}
1611+
1612+
1613+
char* wolfSSHD_ConfigGetHostKeyStoreFlags(const WOLFSSHD_CONFIG* conf)
1614+
{
1615+
char* ret = NULL;
1616+
1617+
if (conf != NULL) {
1618+
ret = conf->hostKeyStoreFlags;
1619+
}
1620+
1621+
return ret;
1622+
}
1623+
#endif /* WOLFSSH_CERTS */
1624+
#endif /* USE_WINDOWS_API */
1625+
15291626
int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file)
15301627
{
15311628
int ret = WS_SUCCESS;

apps/wolfsshd/configuration.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ char* wolfSSHD_ConfigGetHostCertFile(const WOLFSSHD_CONFIG* conf);
4242
char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf);
4343
int wolfSSHD_ConfigSetHostKeyFile(WOLFSSHD_CONFIG* conf, const char* file);
4444
int wolfSSHD_ConfigSetHostCertFile(WOLFSSHD_CONFIG* conf, const char* file);
45+
#ifdef USE_WINDOWS_API
46+
#ifdef WOLFSSH_CERTS
47+
char* wolfSSHD_ConfigGetHostKeyStore(const WOLFSSHD_CONFIG* conf);
48+
char* wolfSSHD_ConfigGetHostKeyStoreSubject(const WOLFSSHD_CONFIG* conf);
49+
char* wolfSSHD_ConfigGetHostKeyStoreFlags(const WOLFSSHD_CONFIG* conf);
50+
#endif /* WOLFSSH_CERTS */
51+
#endif /* USE_WINDOWS_API */
4552
int wolfSSHD_ConfigSetSystemCA(WOLFSSHD_CONFIG* conf, const char* value);
4653
int wolfSSHD_ConfigGetSystemCA(const WOLFSSHD_CONFIG* conf);
4754
int wolfSSHD_ConfigSetUserCAStore(WOLFSSHD_CONFIG* conf, const char* value);

apps/wolfsshd/wolfsshd.c

Lines changed: 115 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@
3838
#include <wolfssl/wolfcrypt/logging.h>
3939
#include <wolfssl/wolfcrypt/asn_public.h>
4040

41+
#ifdef USE_WINDOWS_API
42+
#ifdef WOLFSSH_CERTS
43+
#include <windows.h>
44+
#include <wincrypt.h>
45+
#include <ncrypt.h>
46+
#ifndef CERT_SYSTEM_STORE_CURRENT_USER
47+
#define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000
48+
#endif
49+
#ifndef CERT_SYSTEM_STORE_LOCAL_MACHINE
50+
#define CERT_SYSTEM_STORE_LOCAL_MACHINE 0x00020000
51+
#endif
52+
#endif /* WOLFSSH_CERTS */
53+
#endif /* USE_WINDOWS_API */
54+
4155
#define WOLFSSH_TEST_SERVER
4256
#include <wolfssh/test.h>
4357

@@ -340,14 +354,80 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
340354

341355
/* Load in host private key */
342356
if (ret == WS_SUCCESS) {
357+
#ifdef USE_WINDOWS_API
358+
#ifdef WOLFSSH_CERTS
359+
char* hostKeyStore = wolfSSHD_ConfigGetHostKeyStore(conf);
360+
char* hostKeyStoreSubject = wolfSSHD_ConfigGetHostKeyStoreSubject(conf);
361+
char* hostKeyStoreFlags = wolfSSHD_ConfigGetHostKeyStoreFlags(conf);
343362

344-
char* hostKey = wolfSSHD_ConfigGetHostKeyFile(conf);
363+
wolfSSH_Log(WS_LOG_INFO,
364+
"[SSHD] Cert store code compiled in. "
365+
"hostKeyStore=%s, hostKeyStoreSubject=%s, hostKeyStoreFlags=%s",
366+
hostKeyStore ? hostKeyStore : "(null)",
367+
hostKeyStoreSubject ? hostKeyStoreSubject : "(null)",
368+
hostKeyStoreFlags ? hostKeyStoreFlags : "(null)");
369+
370+
if (hostKeyStore != NULL && hostKeyStoreSubject != NULL) {
371+
/* Use cert store host key */
372+
wchar_t* wStoreName = NULL;
373+
wchar_t* wSubjectName = NULL;
374+
DWORD dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
375+
int storeNameLen, subjectNameLen;
376+
377+
/* Parse flags if provided */
378+
if (hostKeyStoreFlags != NULL) {
379+
if (WSTRCMP(hostKeyStoreFlags, "CURRENT_USER") == 0) {
380+
dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
381+
} else if (WSTRCMP(hostKeyStoreFlags, "LOCAL_MACHINE") == 0) {
382+
dwFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
383+
} else {
384+
dwFlags = (DWORD)atoi(hostKeyStoreFlags);
385+
}
386+
}
387+
388+
/* Convert to wide strings */
389+
storeNameLen = MultiByteToWideChar(CP_UTF8, 0, hostKeyStore, -1, NULL, 0);
390+
subjectNameLen = MultiByteToWideChar(CP_UTF8, 0, hostKeyStoreSubject, -1, NULL, 0);
391+
392+
wStoreName = (wchar_t*)WMALLOC(storeNameLen * sizeof(wchar_t), heap, DYNTYPE_SSHD);
393+
wSubjectName = (wchar_t*)WMALLOC(subjectNameLen * sizeof(wchar_t), heap, DYNTYPE_SSHD);
394+
395+
if (wStoreName == NULL || wSubjectName == NULL) {
396+
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Memory allocation failed for cert store strings");
397+
ret = WS_MEMORY_E;
398+
} else {
399+
MultiByteToWideChar(CP_UTF8, 0, hostKeyStore, -1, wStoreName, storeNameLen);
400+
MultiByteToWideChar(CP_UTF8, 0, hostKeyStoreSubject, -1, wSubjectName, subjectNameLen);
401+
402+
ret = wolfSSH_CTX_UsePrivateKey_fromStore(*ctx, wStoreName, dwFlags, wSubjectName);
403+
if (ret != WS_SUCCESS) {
404+
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to load host key from certificate store");
405+
}
406+
407+
WFREE(wStoreName, heap, DYNTYPE_SSHD);
408+
WFREE(wSubjectName, heap, DYNTYPE_SSHD);
409+
}
410+
} else
411+
#else
412+
wolfSSH_Log(WS_LOG_INFO,
413+
"[SSHD] WOLFSSH_CERTS not defined - cert store support disabled");
414+
#endif /* WOLFSSH_CERTS */
415+
#else
416+
wolfSSH_Log(WS_LOG_INFO,
417+
"[SSHD] USE_WINDOWS_API not defined - cert store support disabled");
418+
#endif /* USE_WINDOWS_API */
419+
{
420+
char* hostKey = wolfSSHD_ConfigGetHostKeyFile(conf);
345421

346-
if (hostKey == NULL) {
347-
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No host private key set");
348-
ret = WS_BAD_ARGUMENT;
349-
}
350-
else {
422+
wolfSSH_Log(WS_LOG_INFO,
423+
"[SSHD] File-based host key path entered. hostKey=%s",
424+
hostKey ? hostKey : "(null)");
425+
426+
if (hostKey == NULL) {
427+
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No host private key set");
428+
ret = WS_BAD_ARGUMENT;
429+
}
430+
else {
351431
byte* data;
352432
word32 dataSz = 0;
353433

@@ -384,6 +464,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
384464
wc_FreeDer(&der);
385465
}
386466
}
467+
}
387468
}
388469

389470
#if defined(WOLFSSH_OSSH_CERTS) || defined(WOLFSSH_CERTS)
@@ -440,7 +521,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
440521
WOLFSSL_CTX* sslCtx;
441522

442523
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Using system CAs");
443-
sslCtx = wolfSSL_CTX_new(wolfSSLv23_method());
524+
sslCtx = wolfSSL_CTX_new(wolfSSLv23_server_method());
444525
if (sslCtx == NULL) {
445526
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Unable to create temporary CTX");
446527
ret = WS_FATAL_ERROR;
@@ -457,13 +538,19 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
457538

458539
if (ret == WS_SUCCESS) {
459540
if (wolfSSHD_ConfigGetUserCAStore(conf)) {
541+
#if defined(_WIN32)
460542
if (wolfSSL_CTX_load_windows_user_CA_certs(sslCtx,
461-
wolfSSHD_ConfigGetWinUserStores(conf),
462-
wolfSSHD_ConfigGetWinUserDwFlags(conf),
463-
wolfSSHD_ConfigGetWinUserPvPara(conf)) != WOLFSSL_SUCCESS) {
543+
wolfSSHD_ConfigGetWinUserStores(conf),
544+
wolfSSHD_ConfigGetWinUserDwFlags(conf),
545+
wolfSSHD_ConfigGetWinUserPvPara(conf)) != WOLFSSL_SUCCESS) {
464546
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Issue loading user CAs");
465547
ret = WS_FATAL_ERROR;
466548
}
549+
#else
550+
wolfSSH_Log(WS_LOG_INFO,
551+
"[SSHD] User CA store is only supported on Windows");
552+
ret = WS_BAD_ARGUMENT;
553+
#endif /* _WIN32 */
467554
}
468555
}
469556

@@ -2451,6 +2538,24 @@ static int StartSSHD(int argc, char** argv)
24512538
}
24522539
}
24532540

2541+
if (logFile == NULL) {
2542+
logFile = stderr;
2543+
}
2544+
#ifdef _WIN32
2545+
/* The early -D detection (wide-string comparison of cmdArgs before
2546+
* conversion) may have set ServiceDebugCb even when -D was supplied.
2547+
* Now that mygetopt has been processed, restore the file-based
2548+
* callback in any case where output should go to logFile:
2549+
* - isDaemon==0 → running interactively, logs to logFile (stderr)
2550+
* - isDaemon==1 but -E was used → logs to the specified file
2551+
* This must happen BEFORE config/SetupCTX so their log messages are
2552+
* captured in the file (or stderr) rather than lost to
2553+
* OutputDebugString. */
2554+
if (!isDaemon || logFile != stderr) {
2555+
wolfSSH_SetLoggingCb(wolfSSHDLoggingCb);
2556+
}
2557+
#endif
2558+
24542559
if (ret == WS_SUCCESS) {
24552560
ret = wolfSSHD_ConfigLoad(conf, configFile);
24562561
if (ret != WS_SUCCESS) {
@@ -2482,10 +2587,6 @@ static int StartSSHD(int argc, char** argv)
24822587
}
24832588
}
24842589

2485-
if (logFile == NULL) {
2486-
logFile = stderr;
2487-
}
2488-
24892590
/* run as a daemon or service */
24902591
#ifndef WIN32
24912592
if (ret == WS_SUCCESS && isDaemon) {

0 commit comments

Comments
 (0)