@@ -147,11 +147,14 @@ public function launch($mustExit = true)
147147 return true ;
148148 }
149149
150- // Determine if the current request is whitelisted or not (role based) .
150+ // Determine if the current request is whitelisted or not.
151151 $ isWhitelisted = !$ this ->mustUsePluginCall && $ this ->extension ->canBypass ();
152152
153- // Merge the rules together. First iterate through the whitelist rules.
153+ // Merge the rules together. First iterate through the whitelist rules because
154+ // we want to whitelist the request if there's a whitelist rule match.
154155 $ rules = array_merge ($ this ->whitelistRules , $ this ->firewallRules );
156+
157+ // Iterate through all the firewall rules.
155158 foreach ($ rules as $ rule ) {
156159 // Should never happen.
157160 if (!isset ($ rule ['rules ' ]) || empty ($ rule ['rules ' ])) {
@@ -230,36 +233,44 @@ public function executeFirewall($rules)
230233 }
231234
232235 // Extract the value of the paramater that we want.
233- $ value = $ this ->request ->getParameterValue ($ rule ['parameter ' ]);
234- if (is_null ($ value ) && $ rule ['parameter ' ] !== false && $ rule ['parameter ' ] != 'rules ' ) {
236+ $ values = $ this ->request ->getParameterValues ($ rule ['parameter ' ]);
237+ if (is_null ($ values ) && $ rule ['parameter ' ] !== false && $ rule ['parameter ' ] != 'rules ' ) {
235238 continue ;
236239 }
237240
238- // Apply mutations, if any.
239- if (isset ($ rule ['mutations ' ]) && is_array ($ rule ['mutations ' ])) {
240- $ value = $ this ->request ->applyMutation ($ rule ['mutations ' ], $ value );
241- if (is_null ($ value )) {
242- continue ;
243- }
241+ // For special parameter values we just set the array to a single null value.
242+ if ($ rule ['parameter ' ] === false || $ rule ['parameter ' ] == 'rules ' ) {
243+ $ values = [null ];
244244 }
245245
246- // Perform the matching .
247- if ( isset ( $ rule [ ' match ' ]) && is_array ( $ rule [ ' match ' ]) || isset ( $ rule [ ' rules ' ]) ) {
248-
249- // Do we have to process child-rules?
250- if ( isset ( $ rule ['rules ' ])) {
251- $ match = $ this -> executeFirewall ( $ rule [ ' rules ' ]);
252- } else {
253- $ match = $ this -> matchParameterValue ( $ rule [ ' match ' ], $ value );
246+ // For all field matches, we want to execute the rule against it .
247+ foreach ( $ values as $ value ) {
248+ // Apply mutations, if any.
249+ if ( isset ( $ rule [ ' mutations ' ]) && is_array ( $ rule [ ' mutations ' ])) {
250+ $ value = $ this -> request -> applyMutation ( $ rule ['mutations ' ], $ value );
251+ if ( is_null ( $ value )) {
252+ continue ;
253+ }
254254 }
255255
256- // Is the rule a match?
257- if ($ match ) {
258- // In case there are multiple rules, they may require chained AND conditions.
259- if ($ inclusiveCount <= 1 || !isset ($ rule ['inclusive ' ]) || $ rule ['inclusive ' ] !== true ) {
260- return true ;
256+ // Perform the matching.
257+ if (isset ($ rule ['match ' ]) && is_array ($ rule ['match ' ]) || isset ($ rule ['rules ' ])) {
258+
259+ // Do we have to process child-rules?
260+ if (isset ($ rule ['rules ' ])) {
261+ $ match = $ this ->executeFirewall ($ rule ['rules ' ]);
261262 } else {
262- $ inclusiveHits ++;
263+ $ match = $ this ->matchParameterValue ($ rule ['match ' ], $ value );
264+ }
265+
266+ // Is the rule a match?
267+ if ($ match ) {
268+ // In case there are multiple rules, they may require chained AND conditions.
269+ if ($ inclusiveCount <= 1 || !isset ($ rule ['inclusive ' ]) || $ rule ['inclusive ' ] !== true ) {
270+ return true ;
271+ } else {
272+ $ inclusiveHits ++;
273+ }
263274 }
264275 }
265276 }
@@ -387,8 +398,13 @@ public function matchParameterValue($match, $value)
387398
388399 // If a specific parameter key matches a sub-match condition.
389400 if ($ matchType == 'array_key_value ' && isset ($ match ['key ' ], $ match ['match ' ])) {
390- $ value = $ this ->request ->getParameterValue ($ match ['key ' ], $ value );
391- return $ this ->matchParameterValue ($ match ['match ' ], $ value );
401+ $ values = $ this ->request ->getParameterValues ($ match ['key ' ], $ value );
402+ foreach ($ values as $ value ) {
403+ if ($ this ->matchParameterValue ($ match ['match ' ], $ value )) {
404+ return true ;
405+ }
406+ }
407+ return false ;
392408 }
393409
394410 // If the user provided value does not match the current hostname.
0 commit comments