Skip to content

Commit 67bd2bc

Browse files
wolfsshd: fix Match User/Group directive misparse
1 parent 36e2765 commit 67bd2bc

2 files changed

Lines changed: 402 additions & 34 deletions

File tree

apps/wolfsshd/configuration.c

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -871,44 +871,86 @@ static int HandleChrootDir(WOLFSSHD_CONFIG* conf, const char* value)
871871
}
872872

873873

874-
/* returns WS_SUCCESS on success, helps with adding a restricted case to the
875-
* config */
876-
static int AddRestrictedCase(WOLFSSHD_CONFIG* config, const char* mtch,
877-
const char* value, char** out)
874+
/* Parse the value of a Match directive into the user and group applies-to
875+
* fields of 'config'. The value is a whitespace separated sequence of
876+
* keyword/name pairs, e.g. "User alice Group admins". The token immediately
877+
* following a "User" or "Group" keyword is taken literally as the name and is
878+
* never re-examined as a keyword, so a principal named like the opposite
879+
* keyword (e.g. "Match User Group") is handled by position rather than by a
880+
* substring search. A recognized keyword with no following name (e.g. a bare
881+
* "Match User") is a configuration error so the admin's intent is not silently
882+
* dropped. Unrecognized tokens are ignored to stay lenient toward Match
883+
* criteria that are not yet supported. Returns WS_SUCCESS on success. */
884+
static int ParseMatchCriteria(WOLFSSHD_CONFIG* config, const char* value)
878885
{
879886
int ret = WS_SUCCESS;
880-
char* pt;
887+
const char* pt;
881888

882-
pt = (char*)XSTRSTR(value, mtch);
883-
if (pt != NULL) {
884-
int sz, i;
889+
if (config == NULL || value == NULL) {
890+
ret = WS_BAD_ARGUMENT;
891+
}
885892

886-
pt += (int)XSTRLEN(mtch);
887-
sz = (int)XSTRLEN(pt);
893+
pt = value;
894+
while (ret == WS_SUCCESS && pt != NULL && *pt != '\0') {
895+
const char* tok;
896+
int tokSz;
897+
char** out = NULL;
888898

889-
/* remove spaces between 'mtch' and the user name */
890-
for (i = 0; i < sz; i++) {
891-
if (pt[i] != ' ') break;
899+
/* skip separators preceding the keyword token */
900+
while (WISSPACE((unsigned char)*pt)) {
901+
pt++;
892902
}
893-
if (i == sz) {
894-
wolfSSH_Log(WS_LOG_ERROR,
895-
"[SSHD] No valid input found with Match");
896-
ret = WS_FATAL_ERROR;
903+
if (*pt == '\0') {
904+
break;
897905
}
898906

899-
if (ret == WS_SUCCESS) {
900-
pt += i;
901-
sz -= i;
907+
/* read the keyword token */
908+
tok = pt;
909+
while (*pt != '\0' && !WISSPACE((unsigned char)*pt)) {
910+
pt++;
911+
}
912+
tokSz = (int)(pt - tok);
913+
914+
/* map the keyword to its applies-to field; ignore anything else */
915+
if (tokSz == (int)XSTRLEN("User") &&
916+
WSTRNCMP(tok, "User", tokSz) == 0) {
917+
out = &config->usrAppliesTo;
918+
}
919+
else if (tokSz == (int)XSTRLEN("Group") &&
920+
WSTRNCMP(tok, "Group", tokSz) == 0) {
921+
out = &config->groupAppliesTo;
922+
}
923+
924+
if (out != NULL) {
925+
/* skip separators between the keyword and its name */
926+
while (WISSPACE((unsigned char)*pt)) {
927+
pt++;
928+
}
902929

903-
/* get the actual size of the user name */
904-
for (i = 0; i < sz; i++) {
905-
if (pt[i] == ' ' || pt[i] == '\r' || pt[i] == '\n') break;
930+
/* the next token is the name, taken literally */
931+
tok = pt;
932+
while (*pt != '\0' && !WISSPACE((unsigned char)*pt)) {
933+
pt++;
906934
}
907-
sz = i;
935+
tokSz = (int)(pt - tok);
908936

909-
ret = CreateString(out, pt, sz, config->heap);
937+
if (tokSz == 0) {
938+
wolfSSH_Log(WS_LOG_ERROR,
939+
"[SSHD] Match %s directive is missing a name",
940+
(out == &config->usrAppliesTo) ? "User" : "Group");
941+
ret = WS_FATAL_ERROR;
942+
}
943+
944+
if (ret == WS_SUCCESS) {
945+
/* a repeated keyword replaces the earlier value */
946+
if (*out != NULL) {
947+
FreeString(out, config->heap);
948+
}
949+
ret = CreateString(out, tok, tokSz, config->heap);
950+
}
910951
}
911952
}
953+
912954
return ret;
913955
}
914956

@@ -932,16 +974,9 @@ static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
932974
}
933975
}
934976

935-
/* users the settings apply to */
977+
/* parse the User/Group criteria the settings apply to */
936978
if (ret == WS_SUCCESS) {
937-
ret = AddRestrictedCase(newConf, "User", value,
938-
&newConf->usrAppliesTo);
939-
}
940-
941-
/* groups the settings apply to */
942-
if (ret == WS_SUCCESS) {
943-
ret = AddRestrictedCase(newConf, "Group", value,
944-
&newConf->groupAppliesTo);
979+
ret = ParseMatchCriteria(newConf, value);
945980
}
946981

947982
/* @TODO handle , separated user/group list */
@@ -951,6 +986,10 @@ static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
951986
(*conf)->next = newConf;
952987
(*conf) = newConf;
953988
}
989+
else {
990+
/* newConf was allocated but not linked into the list; free it */
991+
wolfSSHD_ConfigFree(newConf);
992+
}
954993

955994
(void)valueSz;
956995
return ret;

0 commit comments

Comments
 (0)