@@ -923,44 +923,86 @@ static int HandleChrootDir(WOLFSSHD_CONFIG* conf, const char* value)
923923}
924924
925925
926- /* returns WS_SUCCESS on success, helps with adding a restricted case to the
927- * config */
928- static int AddRestrictedCase (WOLFSSHD_CONFIG * config , const char * mtch ,
929- const char * value , char * * out )
926+ /* Parse the value of a Match directive into the user and group applies-to
927+ * fields of 'config'. The value is a whitespace separated sequence of
928+ * keyword/name pairs, e.g. "User alice Group admins". The token immediately
929+ * following a "User" or "Group" keyword is taken literally as the name and is
930+ * never re-examined as a keyword, so a principal named like the opposite
931+ * keyword (e.g. "Match User Group") is handled by position rather than by a
932+ * substring search. A recognized keyword with no following name (e.g. a bare
933+ * "Match User") is a configuration error so the admin's intent is not silently
934+ * dropped. Unrecognized tokens are ignored to stay lenient toward Match
935+ * criteria that are not yet supported. Returns WS_SUCCESS on success. */
936+ static int ParseMatchCriteria (WOLFSSHD_CONFIG * config , const char * value )
930937{
931938 int ret = WS_SUCCESS ;
932- char * pt ;
939+ const char * pt ;
933940
934- pt = ( char * ) XSTRSTR ( value , mtch );
935- if ( pt != NULL ) {
936- int sz , i ;
941+ if ( config == NULL || value == NULL ) {
942+ ret = WS_BAD_ARGUMENT ;
943+ }
937944
938- pt += (int )XSTRLEN (mtch );
939- sz = (int )XSTRLEN (pt );
945+ pt = value ;
946+ while (ret == WS_SUCCESS && pt != NULL && * pt != '\0' ) {
947+ const char * tok ;
948+ int tokSz ;
949+ char * * out = NULL ;
940950
941- /* remove spaces between 'mtch' and the user name */
942- for ( i = 0 ; i < sz ; i ++ ) {
943- if ( pt [ i ] != ' ' ) break ;
951+ /* skip separators preceding the keyword token */
952+ while ( WISSPACE (( unsigned char ) * pt ) ) {
953+ pt ++ ;
944954 }
945- if (i == sz ) {
946- wolfSSH_Log (WS_LOG_ERROR ,
947- "[SSHD] No valid input found with Match" );
948- ret = WS_FATAL_ERROR ;
955+ if (* pt == '\0' ) {
956+ break ;
949957 }
950958
951- if (ret == WS_SUCCESS ) {
952- pt += i ;
953- sz -= i ;
959+ /* read the keyword token */
960+ tok = pt ;
961+ while (* pt != '\0' && !WISSPACE ((unsigned char )* pt )) {
962+ pt ++ ;
963+ }
964+ tokSz = (int )(pt - tok );
965+
966+ /* map the keyword to its applies-to field; ignore anything else */
967+ if (tokSz == (int )XSTRLEN ("User" ) &&
968+ WSTRNCMP (tok , "User" , tokSz ) == 0 ) {
969+ out = & config -> usrAppliesTo ;
970+ }
971+ else if (tokSz == (int )XSTRLEN ("Group" ) &&
972+ WSTRNCMP (tok , "Group" , tokSz ) == 0 ) {
973+ out = & config -> groupAppliesTo ;
974+ }
975+
976+ if (out != NULL ) {
977+ /* skip separators between the keyword and its name */
978+ while (WISSPACE ((unsigned char )* pt )) {
979+ pt ++ ;
980+ }
954981
955- /* get the actual size of the user name */
956- for (i = 0 ; i < sz ; i ++ ) {
957- if (pt [i ] == ' ' || pt [i ] == '\r' || pt [i ] == '\n' ) break ;
982+ /* the next token is the name, taken literally */
983+ tok = pt ;
984+ while (* pt != '\0' && !WISSPACE ((unsigned char )* pt )) {
985+ pt ++ ;
958986 }
959- sz = i ;
987+ tokSz = ( int )( pt - tok ) ;
960988
961- ret = CreateString (out , pt , sz , config -> heap );
989+ if (tokSz == 0 ) {
990+ wolfSSH_Log (WS_LOG_ERROR ,
991+ "[SSHD] Match %s directive is missing a name" ,
992+ (out == & config -> usrAppliesTo ) ? "User" : "Group" );
993+ ret = WS_FATAL_ERROR ;
994+ }
995+
996+ if (ret == WS_SUCCESS ) {
997+ /* a repeated keyword replaces the earlier value */
998+ if (* out != NULL ) {
999+ FreeString (out , config -> heap );
1000+ }
1001+ ret = CreateString (out , tok , tokSz , config -> heap );
1002+ }
9621003 }
9631004 }
1005+
9641006 return ret ;
9651007}
9661008
@@ -1052,16 +1094,9 @@ static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
10521094 }
10531095 }
10541096
1055- /* users the settings apply to */
1097+ /* parse the User/Group criteria the settings apply to */
10561098 if (ret == WS_SUCCESS ) {
1057- ret = AddRestrictedCase (newConf , "User" , value ,
1058- & newConf -> usrAppliesTo );
1059- }
1060-
1061- /* groups the settings apply to */
1062- if (ret == WS_SUCCESS ) {
1063- ret = AddRestrictedCase (newConf , "Group" , value ,
1064- & newConf -> groupAppliesTo );
1099+ ret = ParseMatchCriteria (newConf , value );
10651100 }
10661101
10671102 /* @TODO handle , separated user/group list */
@@ -1077,6 +1112,10 @@ static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
10771112 (* conf )-> next = newConf ;
10781113 (* conf ) = newConf ;
10791114 }
1115+ else {
1116+ /* newConf was allocated but not linked into the list; free it */
1117+ wolfSSHD_ConfigFree (newConf );
1118+ }
10801119
10811120 (void )valueSz ;
10821121 return ret ;
0 commit comments