@@ -91,8 +91,16 @@ struct WOLFSSHD_CONFIG {
9191 byte authKeysFileSet :1 ; /* if not set then no explicit authorized keys */
9292};
9393
94- int CountWhitespace (const char * in , int inSz , byte inv );
95- int SetFileString (char * * dst , const char * src , void * heap );
94+ /* Maximum depth of nested Include directives. Bounds the recursion
95+ * through wolfSSHD_ConfigLoad -> ParseConfigLine -> HandleConfigOption
96+ * -> HandleInclude -> wolfSSHD_ConfigLoad. */
97+ #ifndef WOLFSSHD_MAX_INCLUDE_DEPTH
98+ #define WOLFSSHD_MAX_INCLUDE_DEPTH 16
99+ #endif
100+ static int ConfigLoad (WOLFSSHD_CONFIG * conf , const char * filename , int depth );
101+
102+ static int CountWhitespace (const char * in , int inSz , byte inv );
103+ static int SetFileString (char * * dst , const char * src , void * heap );
96104
97105/* convert a string into seconds, handles if 'm' for minutes follows the string
98106 * number, i.e. 2m
@@ -616,7 +624,8 @@ static int HandlePort(WOLFSSHD_CONFIG* conf, const char* value)
616624 return ret ;
617625}
618626
619- static int HandleInclude (WOLFSSHD_CONFIG * conf , const char * value )
627+ /* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
628+ static int HandleInclude (WOLFSSHD_CONFIG * conf , const char * value , int depth )
620629{
621630 const char * ptr ;
622631 const char * ptr2 ;
@@ -802,7 +811,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
802811 WSNPRINTF (filepath , PATH_MAX , "%s/%s" , path ,
803812 fileNames [i ]);
804813 }
805- ret = wolfSSHD_ConfigLoad (conf , filepath );
814+ ret = ConfigLoad (conf , filepath , depth );
806815 if (ret != WS_SUCCESS ) {
807816 break ;
808817 }
@@ -834,7 +843,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
834843#endif
835844 }
836845 else {
837- ret = wolfSSHD_ConfigLoad (conf , value );
846+ ret = ConfigLoad (conf , value , depth );
838847 }
839848 }
840849 return ret ;
@@ -974,8 +983,9 @@ static int HandleForcedCommand(WOLFSSHD_CONFIG* conf, const char* value,
974983}
975984
976985/* returns WS_SUCCESS on success */
986+ /* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
977987static int HandleConfigOption (WOLFSSHD_CONFIG * * conf , int opt ,
978- const char * value , const char * full , int fullSz )
988+ const char * value , const char * full , int fullSz , int depth )
979989{
980990 int ret = WS_BAD_ARGUMENT ;
981991
@@ -1043,7 +1053,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
10431053 ret = WS_SUCCESS ;
10441054 break ;
10451055 case OPT_INCLUDE :
1046- ret = HandleInclude (* conf , value );
1056+ ret = HandleInclude (* conf , value , depth );
10471057 break ;
10481058 case OPT_CHROOT_DIR :
10491059 ret = HandleChrootDir (* conf , value );
@@ -1074,7 +1084,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
10741084
10751085/* helper function to count white spaces, returns the number of white spaces on
10761086 * success */
1077- int CountWhitespace (const char * in , int inSz , byte inv )
1087+ static int CountWhitespace (const char * in , int inSz , byte inv )
10781088{
10791089 int i = 0 ;
10801090
@@ -1100,8 +1110,9 @@ int CountWhitespace(const char* in, int inSz, byte inv)
11001110 * Fails if any option is found that is unknown/unsupported
11011111 * Match command will create new configs for specific matching cases
11021112 */
1113+ /* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
11031114WOLFSSHD_STATIC int ParseConfigLine (WOLFSSHD_CONFIG * * conf , const char * l ,
1104- int lSz )
1115+ int lSz , int depth )
11051116{
11061117 int ret = WS_BAD_ARGUMENT ;
11071118 int sz = 0 ;
@@ -1132,7 +1143,8 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
11321143 else {
11331144 WMEMCPY (tmp , l + idx , sz );
11341145 tmp [sz ] = 0 ;
1135- ret = HandleConfigOption (conf , found -> tag , tmp , l + idx , lSz - idx );
1146+ ret = HandleConfigOption (conf ,
1147+ found -> tag , tmp , l + idx , lSz - idx , depth );
11361148 }
11371149 }
11381150 else {
@@ -1153,6 +1165,13 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
11531165 * returns WS_SUCCESS on success
11541166 */
11551167int wolfSSHD_ConfigLoad (WOLFSSHD_CONFIG * conf , const char * filename )
1168+ {
1169+ return ConfigLoad (conf , filename , 0 );
1170+ }
1171+
1172+
1173+ /* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
1174+ static int ConfigLoad (WOLFSSHD_CONFIG * conf , const char * filename , int depth )
11561175{
11571176 WFILE * f ;
11581177 WOLFSSHD_CONFIG * currentConfig ;
@@ -1163,12 +1182,20 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
11631182 if (conf == NULL || filename == NULL )
11641183 return BAD_FUNC_ARG ;
11651184
1185+ if (depth >= WOLFSSHD_MAX_INCLUDE_DEPTH ) {
1186+ wolfSSH_Log (WS_LOG_ERROR ,
1187+ "[SSHD] Include depth (%d) exceeded loading %s" ,
1188+ WOLFSSHD_MAX_INCLUDE_DEPTH , filename );
1189+ return WS_BAD_ARGUMENT ;
1190+ }
1191+
11661192 if (WFOPEN (NULL , & f , filename , "rb" ) != 0 ) {
11671193 wolfSSH_Log (WS_LOG_ERROR , "Unable to open SSHD config file %s" ,
11681194 filename );
11691195 return BAD_FUNC_ARG ;
11701196 }
11711197 wolfSSH_Log (WS_LOG_INFO , "[SSHD] parsing config file %s" , filename );
1198+ depth ++ ;
11721199
11731200 currentConfig = conf ;
11741201 while ((current = XFGETS (buf , MAX_LINE_SIZE , f )) != NULL ) {
@@ -1189,7 +1216,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
11891216 continue ; /* commented out line */
11901217 }
11911218
1192- ret = ParseConfigLine (& currentConfig , current , currentSz );
1219+ ret = ParseConfigLine (& currentConfig , current , currentSz , depth );
11931220 if (ret != WS_SUCCESS ) {
11941221 fprintf (stderr , "Unable to parse config line : %s\n" , current );
11951222 break ;
@@ -1356,7 +1383,7 @@ char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf)
13561383 return ret ;
13571384}
13581385
1359- int SetFileString (char * * dst , const char * src , void * heap )
1386+ static int SetFileString (char * * dst , const char * src , void * heap )
13601387{
13611388 int ret = WS_SUCCESS ;
13621389
0 commit comments