@@ -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