use wolfSSH_ prefix on wolfSSH specific config's HostKeyStore, HostKeyStoreSubject, HostKeyStoreFlags

pull/1242/head
JacobBarthelmeh 2026-09-02 14:40:24 -06:00 committed by John Safranek
parent ed9bf644d0
commit 0be0fae009
6 changed files with 69 additions and 73 deletions

View File

@ -480,7 +480,7 @@ jobs:
Set-Acl $keyFile $acl
Write-Host "Granted SYSTEM FullControl on private key: $keyFile"
# Export the CN (without "CN=") for HostKeyStoreSubject
# Export the CN (without "CN=") for wolfSSH_HostKeyStoreSubject
$subject = $serverCert.Subject
if ($subject -match "^CN=(.+)$") { $subject = $matches[1] }
Add-Content -Path $env:GITHUB_ENV -Value "SERVER_CERT_SUBJECT=$subject"
@ -654,12 +654,12 @@ jobs:
if ("${{ matrix.server_key_source }}" -eq "store") {
# The certificate is part of the store entry. HostKey and
# HostCertificate alongside HostKeyStore are rejected at startup.
# HostCertificate alongside wolfSSH_HostKeyStore are rejected at startup.
$configContent += @"
HostKeyStore My
HostKeyStoreSubject $env:SERVER_CERT_SUBJECT
HostKeyStoreFlags LOCAL_MACHINE
wolfSSH_HostKeyStore My
wolfSSH_HostKeyStoreSubject $env:SERVER_CERT_SUBJECT
wolfSSH_HostKeyStoreFlags LOCAL_MACHINE
"@
} else {
$keyPath = (Resolve-Path "keys\server-key.pem").Path
@ -1171,34 +1171,34 @@ jobs:
"wolfSSH_WinUserPvPara wolfSSHLeafOnlyCA",
"wolfSSH_WinUserDwFlags LOCAL_MACHINE") `
"No usable CA certificates found in store"
Test-SshdRejects "HostKeyStore without HostKeyStoreSubject" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "HostKeyStore My",
"HostKeyStoreFlags LOCAL_MACHINE")) `
"HostKeyStoreSubject is missing"
Test-SshdRejects "HostKeyStore without HostKeyStoreFlags" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "HostKeyStore My",
"HostKeyStoreSubject wolfSSH-Test-Server")) `
"HostKeyStoreFlags is missing"
Test-SshdRejects "HostKeyStoreSubject/Flags without HostKeyStore" `
Test-SshdRejects "wolfSSH_HostKeyStore without wolfSSH_HostKeyStoreSubject" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "wolfSSH_HostKeyStore My",
"wolfSSH_HostKeyStoreFlags LOCAL_MACHINE")) `
"wolfSSH_HostKeyStoreSubject is missing"
Test-SshdRejects "wolfSSH_HostKeyStore without wolfSSH_HostKeyStoreFlags" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "wolfSSH_HostKeyStore My",
"wolfSSH_HostKeyStoreSubject wolfSSH-Test-Server")) `
"wolfSSH_HostKeyStoreFlags is missing"
Test-SshdRejects "wolfSSH_HostKeyStoreSubject/Flags without wolfSSH_HostKeyStore" `
($base[0..0] + @("TrustedUserCAKeys $caPem",
"HostKeyStoreSubject wolfSSH-Test-Server",
"HostKeyStoreFlags LOCAL_MACHINE")) `
"HostKeyStore is missing"
Test-SshdRejects "HostKeyStore conflicts with HostKey" `
($base + @("HostKeyStore My",
"HostKeyStoreSubject wolfSSH-Test-Server",
"HostKeyStoreFlags LOCAL_MACHINE")) `
"wolfSSH_HostKeyStoreSubject wolfSSH-Test-Server",
"wolfSSH_HostKeyStoreFlags LOCAL_MACHINE")) `
"wolfSSH_HostKeyStore is missing"
Test-SshdRejects "wolfSSH_HostKeyStore conflicts with HostKey" `
($base + @("wolfSSH_HostKeyStore My",
"wolfSSH_HostKeyStoreSubject wolfSSH-Test-Server",
"wolfSSH_HostKeyStoreFlags LOCAL_MACHINE")) `
"HostKey conflicts"
Test-SshdRejects "HostKeyStore conflicts with HostCertificate" `
Test-SshdRejects "wolfSSH_HostKeyStore conflicts with HostCertificate" `
($base[0..0] + @("TrustedUserCAKeys $caPem",
"HostCertificate $hostCert", "HostKeyStore My",
"HostKeyStoreSubject wolfSSH-Test-Server",
"HostKeyStoreFlags LOCAL_MACHINE")) `
"HostCertificate $hostCert", "wolfSSH_HostKeyStore My",
"wolfSSH_HostKeyStoreSubject wolfSSH-Test-Server",
"wolfSSH_HostKeyStoreFlags LOCAL_MACHINE")) `
"HostCertificate conflicts"
Test-SshdRejects "-h conflicts with HostKeyStore" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "HostKeyStore My",
"HostKeyStoreSubject wolfSSH-Test-Server",
"HostKeyStoreFlags LOCAL_MACHINE")) `
Test-SshdRejects "-h conflicts with wolfSSH_HostKeyStore" `
($base[0..0] + @("TrustedUserCAKeys $caPem", "wolfSSH_HostKeyStore My",
"wolfSSH_HostKeyStoreSubject wolfSSH-Test-Server",
"wolfSSH_HostKeyStoreFlags LOCAL_MACHINE")) `
"-h host key file conflicts" @("-h", $hostKey)
# This build has no WOLFSSL_SYS_CA_CERTS, so the system CA directive
# must fail closed rather than run without the configured anchors.

View File

@ -569,8 +569,8 @@ search so file arguments resolve against the current directory.
wolfSSHd gains these configuration directives, all global only (they are
rejected inside a `Match` block):
* `HostKeyStore <store>`, `HostKeyStoreSubject <CN>`, and
`HostKeyStoreFlags <location>` select the host key from a certificate
* `wolfSSH_HostKeyStore <store>`, `wolfSSH_HostKeyStoreSubject <CN>`, and
`wolfSSH_HostKeyStoreFlags <location>` select the host key from a certificate
store. All three must be set together, and they conflict with `HostKey`,
`HostCertificate`, and the `-h` command line option.
* `wolfSSH_TrustedUserCAStore yes|no` loads the client-certificate trust

View File

@ -534,16 +534,6 @@ static const CONFIG_OPTION options[] = {
{OPT_ACCEPT_ENV, "AcceptEnv"},
{OPT_PROTOCOL, "Protocol"},
{OPT_LOGIN_GRACE_TIME, "LoginGraceTime"},
/* The parser requires a whitespace delimiter after the option name, which
* is the primary defence against a shorter name prefix-matching a longer
* one. As belt-and-braces, longer option names that share a common prefix
* MUST still appear before the shorter one:
* HostKeyStoreSubject/HostKeyStoreFlags before HostKeyStore, and all
* HostKeyStore* before HostKey. Kept unconditional so "HostKeyStore"
* never matches "HostKey" on non-store builds. */
{OPT_HOST_KEY_STORE_SUBJECT, "HostKeyStoreSubject"},
{OPT_HOST_KEY_STORE_FLAGS, "HostKeyStoreFlags"},
{OPT_HOST_KEY_STORE, "HostKeyStore"},
{OPT_HOST_KEY, "HostKey"},
{OPT_PASSWORD_AUTH, "PasswordAuthentication"},
{OPT_PUBKEY_AUTH, "PubkeyAuthentication"},
@ -564,6 +554,9 @@ static const CONFIG_OPTION options[] = {
{OPT_WIN_USER_STORES, "wolfSSH_WinUserStores"},
{OPT_WIN_USER_DW_FLAGS, "wolfSSH_WinUserDwFlags"},
{OPT_WIN_USER_PV_PARA, "wolfSSH_WinUserPvPara"},
{OPT_HOST_KEY_STORE_SUBJECT, "wolfSSH_HostKeyStoreSubject"},
{OPT_HOST_KEY_STORE_FLAGS, "wolfSSH_HostKeyStoreFlags"},
{OPT_HOST_KEY_STORE, "wolfSSH_HostKeyStore"},
{OPT_AUTHORIZED_UPN_DOMAINS, "AuthorizedUPNDomains"},
};
#define NUM_OPTIONS ((int)(sizeof(options) / sizeof(*options)))
@ -1570,13 +1563,13 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
break;
#ifdef WOLFSSHD_WIN_STORE_CONFIG
case OPT_HOST_KEY_STORE:
ret = CheckNotInMatch(*conf, "HostKeyStore");
ret = CheckNotInMatch(*conf, "wolfSSH_HostKeyStore");
if (ret == WS_SUCCESS)
ret = SetFileString(&(*conf)->hostKeyStore, value,
(*conf)->heap);
break;
case OPT_HOST_KEY_STORE_SUBJECT:
ret = CheckNotInMatch(*conf, "HostKeyStoreSubject");
ret = CheckNotInMatch(*conf, "wolfSSH_HostKeyStoreSubject");
/* use the full line remainder so a CN containing spaces is
* kept instead of being cut at the first token */
if (ret == WS_SUCCESS)
@ -1584,7 +1577,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
fullSz, (*conf)->heap);
break;
case OPT_HOST_KEY_STORE_FLAGS:
ret = CheckNotInMatch(*conf, "HostKeyStoreFlags");
ret = CheckNotInMatch(*conf, "wolfSSH_HostKeyStoreFlags");
if (ret == WS_SUCCESS)
ret = SetFileString(&(*conf)->hostKeyStoreFlags, value,
(*conf)->heap);
@ -1595,13 +1588,13 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
case OPT_HOST_KEY_STORE_FLAGS:
#ifdef WOLFSSH_IGNORE_UNKNOWN_CONFIG
wolfSSH_Log(WS_LOG_WARN,
"[SSHD] Ignoring HostKeyStore* option: requires a "
"[SSHD] Ignoring wolfSSH_HostKeyStore* option: requires a "
"WOLFSSH_WINDOWS_CERT_STORE build");
ignored = 1;
ret = WS_SUCCESS;
#else
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostKeyStore* options require a "
"[SSHD] wolfSSH_HostKeyStore* options require a "
"WOLFSSH_WINDOWS_CERT_STORE build");
ret = WS_NOT_COMPILED;
#endif

View File

@ -300,7 +300,8 @@ static int test_ParseConfigLine(void)
#ifndef WOLFSSH_IGNORE_UNKNOWN_CONFIG
{"Unknown extension of Port", "PortFoo 22", 1},
{"Unknown extension of HostKey", "HostKeyFoo /tmp/x", 1},
{"Unknown extension of HostKeyStore", "HostKeyStoreX MY", 1},
{"Unknown extension of wolfSSH_HostKeyStore",
"wolfSSH_HostKeyStoreX MY", 1},
{"Unknown extension of TrustedUserCAStore",
"wolfSSH_TrustedUserCAStoreX yes", 1},
#endif
@ -454,9 +455,10 @@ static int test_ConfigCopy(void)
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_TrustedUserCAStore yes");
#ifdef WOLFSSHD_WIN_STORE_CONFIG
if (ret == WS_SUCCESS) ret = PCL("HostKeyStore MY");
if (ret == WS_SUCCESS) ret = PCL("HostKeyStoreSubject wolfSSH Host");
if (ret == WS_SUCCESS) ret = PCL("HostKeyStoreFlags 0x1000");
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_HostKeyStore MY");
if (ret == WS_SUCCESS)
ret = PCL("wolfSSH_HostKeyStoreSubject wolfSSH Host");
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_HostKeyStoreFlags 0x1000");
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_WinUserStores MY,Root");
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_WinUserDwFlags 0x1");
if (ret == WS_SUCCESS) ret = PCL("wolfSSH_WinUserPvPara subjectName");
@ -5142,8 +5144,7 @@ static int test_PermitRootLoginModes(void)
}
/* The config parser matches option names with WSTRNCMP over the options table
* in order, so no entry may be a strict prefix of a later one (e.g. "HostKey"
* must come after the "HostKeyStore*" names). */
* in order, so no entry may be a strict prefix of a later one. */
static int test_ConfigOptionPrefixOrder(void)
{
int ret = WS_SUCCESS;
@ -5193,9 +5194,9 @@ static int test_ConfigGlobalOnlyOptionsInMatch(void)
{ "HostCertificate /etc/ssh/host_cert.pem", WS_BAD_ARGUMENT },
#endif
#ifdef WOLFSSHD_WIN_STORE_CONFIG
{ "HostKeyStore MY", WS_BAD_ARGUMENT },
{ "HostKeyStoreSubject wolfSSH Host", WS_BAD_ARGUMENT },
{ "HostKeyStoreFlags 0x1000", WS_BAD_ARGUMENT },
{ "wolfSSH_HostKeyStore MY", WS_BAD_ARGUMENT },
{ "wolfSSH_HostKeyStoreSubject wolfSSH Host", WS_BAD_ARGUMENT },
{ "wolfSSH_HostKeyStoreFlags 0x1000", WS_BAD_ARGUMENT },
{ "wolfSSH_WinUserStores CERT_STORE_PROV_SYSTEM", WS_BAD_ARGUMENT },
{ "wolfSSH_WinUserDwFlags LOCAL_MACHINE", WS_BAD_ARGUMENT },
{ "wolfSSH_WinUserPvPara SSH_UserCA", WS_BAD_ARGUMENT },

View File

@ -902,7 +902,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
if (hostKeyStore != NULL && hostKeyStoreSubject == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostKeyStore set but HostKeyStoreSubject is missing");
"[SSHD] wolfSSH_HostKeyStore set but "
"wolfSSH_HostKeyStoreSubject is missing");
ret = WS_BAD_ARGUMENT;
}
/* The location is mandatory for the same reason wolfSSH_WinUserDwFlags
@ -911,7 +912,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
* anything running as that account install a host key. */
else if (hostKeyStore != NULL && hostKeyStoreFlags == NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostKeyStore set but HostKeyStoreFlags is missing.");
"[SSHD] wolfSSH_HostKeyStore set but "
"wolfSSH_HostKeyStoreFlags is missing.");
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Set the store location explicitly, normally "
"LOCAL_MACHINE.");
@ -920,8 +922,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
else if (hostKeyStore == NULL &&
(hostKeyStoreSubject != NULL || hostKeyStoreFlags != NULL)) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostKeyStoreSubject/HostKeyStoreFlags set but "
"HostKeyStore is missing");
"[SSHD] wolfSSH_HostKeyStoreSubject/wolfSSH_HostKeyStoreFlags "
"set but wolfSSH_HostKeyStore is missing");
ret = WS_BAD_ARGUMENT;
}
/* The store branch below wins over the file path, so a HostKey line
@ -930,8 +932,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
else if (hostKeyStore != NULL &&
wolfSSHD_ConfigGetHostKeyFile(conf) != NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostKey conflicts with the configured HostKeyStore. "
"Use one or the other.");
"[SSHD] HostKey conflicts with the configured "
"wolfSSH_HostKeyStore. Use one or the other.");
ret = WS_BAD_ARGUMENT;
}
/* A store host key carries its own certificate. A HostCertificate
@ -941,7 +943,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
wolfSSHD_ConfigGetHostCertFile(conf) != NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] HostCertificate conflicts with the configured "
"HostKeyStore, which supplies its own certificate.");
"wolfSSH_HostKeyStore, which supplies its own certificate.");
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Use one or the other.");
ret = WS_BAD_ARGUMENT;
}
@ -964,8 +966,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
}
if (ret == WS_SUCCESS && !IsElevationProtectedHive(dwFlags)) {
wolfSSH_Log(WS_LOG_WARN,
"[SSHD] HostKeyStoreFlags selects a store hive that its "
"own account can write to without elevation.");
"[SSHD] wolfSSH_HostKeyStoreFlags selects a store hive "
"that its own account can write to without elevation.");
wolfSSH_Log(WS_LOG_WARN,
"[SSHD] LOCAL_MACHINE is the safer location for the host "
"key.");
@ -1269,8 +1271,8 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
/* Load user CA certs (trust anchors used to verify client X.509 certs)
* directly from a Windows certificate store into the cert manager. */
#if defined(WOLFSSH_CERTS) && defined(WOLFSSH_WINDOWS_CERT_STORE)
/* Mirror the HostKeyStore* validation: the wolfSSH_WinUser* group only
* has an effect through LoadUserCACertsFromStore(), so accepting it
/* Mirror the wolfSSH_HostKeyStore* validation: the wolfSSH_WinUser* group
* only has an effect through LoadUserCACertsFromStore(), so accepting it
* without the store enabled would start the daemon with no client CA
* trust anchors and no indication why logins fail. */
if (ret == WS_SUCCESS && !wolfSSHD_ConfigGetUserCAStore(conf) &&
@ -1490,7 +1492,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
* also needs certificate support. Fail startup rather than silently
* ignore a configured realm policy, unless the build opts into
* WOLFSSH_IGNORE_UNKNOWN_CONFIG, which downgrades not-compiled-in
* directives to a warning the same way the HostKeyStore* and
* directives to a warning the same way the wolfSSH_HostKeyStore* and
* wolfSSH_WinUser* handlers do. Check every config node since the
* directive may sit in a Match block. */
#if !defined(WOLFSSL_FPKI) || !defined(WOLFSSH_CERTS)
@ -4226,7 +4228,7 @@ static int StartSSHD(int argc, char** argv)
if (wolfSSHD_ConfigGetHostKeyStore(conf) != NULL) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] -h host key file conflicts with the configured "
"HostKeyStore. Use one or the other.");
"wolfSSH_HostKeyStore. Use one or the other.");
ret = WS_BAD_ARGUMENT;
}
#endif

View File

@ -757,7 +757,7 @@ int wolfSSH_CertStoreLocationValid(word32 dwFlags)
/* The one name-to-value table for CERT_SYSTEM_STORE_* locations, shared by
* wolfSSH_ParseCertStoreSpec() and wolfsshd's HostKeyStoreFlags and
* wolfSSH_ParseCertStoreSpec() and wolfsshd's wolfSSH_HostKeyStoreFlags and
* wolfSSH_WinUserDwFlags parsing so the accepted spellings cannot drift. */
static const struct {
const char* shortName;
@ -905,10 +905,10 @@ int wolfSSH_ParseCertStoreSpec(const char* spec,
WFREE(specCopy, heap, DYNTYPE_TEMP);
return WS_BAD_ARGUMENT;
}
/* Accept the same spellings as wolfsshd's HostKeyStoreFlags and
* wolfSSH_WinUserDwFlags so one name works everywhere; the
* shared parser also handles the numeric location forms and
* rejects control flags. */
/* Accept the same spellings as wolfsshd's
* wolfSSH_HostKeyStoreFlags and wolfSSH_WinUserDwFlags so one
* name works everywhere; the shared parser also handles the
* numeric location forms and rejects control flags. */
if (wolfSSH_CertStoreLocationFromName(flagsStr, &flags)
!= WS_SUCCESS) {
WLOG(WS_LOG_CERTMAN, "Malformed cert store flags value "