Skip to content

Commit e0765a8

Browse files
wolfsshd: mark AuthorizedKeysFile as explicitly set in public setter
1 parent 52f6db9 commit e0765a8

2 files changed

Lines changed: 71 additions & 6 deletions

File tree

apps/wolfsshd/configuration.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,6 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
11551155

11561156
switch (opt) {
11571157
case OPT_AUTH_KEYS_FILE:
1158-
(*conf)->authKeysFileSet = 1;
11591158
ret = wolfSSHD_ConfigSetAuthKeysFile(*conf, value);
11601159
break;
11611160
case OPT_PRIV_SEP:
@@ -1475,21 +1474,29 @@ int wolfSSHD_ConfigGetAuthKeysFileSet(const WOLFSSHD_CONFIG* conf)
14751474
int wolfSSHD_ConfigSetAuthKeysFile(WOLFSSHD_CONFIG* conf, const char* file)
14761475
{
14771476
int ret = WS_SUCCESS;
1477+
char* newFile = NULL;
14781478

14791479
if (conf == NULL) {
14801480
ret = WS_BAD_ARGUMENT;
14811481
}
14821482

1483+
/* allocate the replacement string first so a failure leaves the existing
1484+
* authKeysFile and authKeysFileSet untouched rather than half updated */
1485+
if (ret == WS_SUCCESS && file != NULL) {
1486+
ret = CreateString(&newFile, file, (int)WSTRLEN(file), conf->heap);
1487+
}
1488+
14831489
if (ret == WS_SUCCESS) {
14841490
if (conf->authKeysFile != NULL) {
14851491
FreeString(&conf->authKeysFile, conf->heap);
14861492
conf->authKeysFile = NULL;
14871493
}
14881494

1489-
if (file != NULL) {
1490-
ret = CreateString(&conf->authKeysFile, file,
1491-
(int)WSTRLEN(file), conf->heap);
1492-
}
1495+
/* swap in the new file and keep authKeysFileSet consistent with it:
1496+
* set when a file is explicitly configured so certificate public-key
1497+
* logins are still checked against it, cleared when removed */
1498+
conf->authKeysFile = newFile;
1499+
conf->authKeysFileSet = (file != NULL) ? 1 : 0;
14931500
}
14941501

14951502
return ret;

apps/wolfsshd/test/test_configuration.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ static int test_ConfigCopy(void)
314314
ret = wolfSSHD_ConfigSetHostCertFile(head, "/etc/ssh/host_cert.pub");
315315
if (ret == WS_SUCCESS)
316316
ret = wolfSSHD_ConfigSetUserCAKeysFile(head, "/etc/ssh/ca.pub");
317-
/* AuthorizedKeysFile must go through PCL so authKeysFileSet flag is set */
317+
/* AuthorizedKeysFile via PCL to also exercise the config-parse path; the
318+
* authKeysFileSet flag is set either way and must survive the copy */
318319
if (ret == WS_SUCCESS) ret = PCL("AuthorizedKeysFile .ssh/authorized_keys");
319320

320321
/* scalar fields */
@@ -996,6 +997,62 @@ static int test_IncludeRecursionBound(void)
996997
return ret;
997998
}
998999

1000+
/* The public wolfSSHD_ConfigSetAuthKeysFile setter must mark the authorized
1001+
* keys file as explicitly configured, otherwise certificate public-key logins
1002+
* skip the authorized-keys check and rely on CA validation alone. */
1003+
static int test_ConfigSetAuthKeysFile(void)
1004+
{
1005+
int ret = WS_SUCCESS;
1006+
WOLFSSHD_CONFIG* conf;
1007+
1008+
conf = wolfSSHD_ConfigNew(NULL);
1009+
if (conf == NULL)
1010+
ret = WS_MEMORY_E;
1011+
1012+
/* fresh config has no explicit authorized keys file */
1013+
if (ret == WS_SUCCESS) {
1014+
if (wolfSSHD_ConfigGetAuthKeysFileSet(conf) != 0)
1015+
ret = WS_FATAL_ERROR;
1016+
}
1017+
1018+
/* configuring a file through the public setter must set the flag */
1019+
if (ret == WS_SUCCESS)
1020+
ret = wolfSSHD_ConfigSetAuthKeysFile(conf, ".ssh/authorized_keys");
1021+
if (ret == WS_SUCCESS) {
1022+
if (wolfSSHD_ConfigGetAuthKeysFileSet(conf) == 0)
1023+
ret = WS_FATAL_ERROR;
1024+
}
1025+
1026+
/* a failed update must leave the existing configuration intact: an
1027+
* all-whitespace file makes CreateString fail, and both the previously
1028+
* configured file and the flag must be untouched, not half cleared */
1029+
if (ret == WS_SUCCESS) {
1030+
if (wolfSSHD_ConfigSetAuthKeysFile(conf, " ") == WS_SUCCESS)
1031+
ret = WS_FATAL_ERROR; /* the bad value should have been rejected */
1032+
}
1033+
if (ret == WS_SUCCESS) {
1034+
if (wolfSSHD_ConfigGetAuthKeysFile(conf) == NULL ||
1035+
XSTRCMP(wolfSSHD_ConfigGetAuthKeysFile(conf),
1036+
".ssh/authorized_keys") != 0)
1037+
ret = WS_FATAL_ERROR;
1038+
}
1039+
if (ret == WS_SUCCESS) {
1040+
if (wolfSSHD_ConfigGetAuthKeysFileSet(conf) == 0)
1041+
ret = WS_FATAL_ERROR;
1042+
}
1043+
1044+
/* removing the file must clear the flag again */
1045+
if (ret == WS_SUCCESS)
1046+
ret = wolfSSHD_ConfigSetAuthKeysFile(conf, NULL);
1047+
if (ret == WS_SUCCESS) {
1048+
if (wolfSSHD_ConfigGetAuthKeysFileSet(conf) != 0)
1049+
ret = WS_FATAL_ERROR;
1050+
}
1051+
1052+
wolfSSHD_ConfigFree(conf);
1053+
return ret;
1054+
}
1055+
9991056
/* Verifies ConfigFree releases all string fields - most useful under ASan. */
10001057
static int test_ConfigFree(void)
10011058
{
@@ -1438,6 +1495,7 @@ const TEST_CASE testCases[] = {
14381495
TEST_DECL(test_CAKeysFileDiffers),
14391496
TEST_DECL(test_IncludeRecursionBound),
14401497
TEST_DECL(test_GetUserAuthTypes),
1498+
TEST_DECL(test_ConfigSetAuthKeysFile),
14411499
TEST_DECL(test_ConfigFree),
14421500
#ifdef WOLFSSL_BASE64_ENCODE
14431501
TEST_DECL(test_CheckAuthKeysLine),

0 commit comments

Comments
 (0)