-
-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: allow selectors on *_NAMES
collections
#1143
base: main
Are you sure you want to change the base?
Changes from 11 commits
a5b714e
73a2508
dd38d5f
0e4f805
8d4e521
21e6aaa
e84a320
f26a5ea
c6a4048
77f4159
280af44
8dbefad
5ead3ff
279c462
5c8a2e2
e1d83b2
1a8f57c
f8e778f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,7 +80,7 @@ | |
c.Map.Reset() | ||
} | ||
|
||
func (c *NamedCollection) Names(rv variables.RuleVariable) collection.Collection { | ||
func (c *NamedCollection) Names(rv variables.RuleVariable) collection.Keyed { | ||
return &NamedCollectionNames{ | ||
variable: rv, | ||
collection: c, | ||
|
@@ -101,11 +101,41 @@ | |
} | ||
|
||
func (c *NamedCollectionNames) FindRegex(key *regexp.Regexp) []types.MatchData { | ||
panic("selection operator not supported") | ||
var res []types.MatchData | ||
|
||
for k, data := range c.collection.Map.data { | ||
if key.MatchString(k) { | ||
blotus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for _, d := range data { | ||
res = append(res, &corazarules.MatchData{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if MatchData is mutable, if so we probably want to reuse the pointer? |
||
Variable_: c.variable, | ||
Key_: d.key, | ||
Value_: d.key, | ||
}) | ||
} | ||
} | ||
} | ||
return res | ||
} | ||
|
||
func (c *NamedCollectionNames) FindString(key string) []types.MatchData { | ||
panic("selection operator not supported") | ||
var res []types.MatchData | ||
|
||
for k, data := range c.collection.Map.data { | ||
if k == key { | ||
blotus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for _, d := range data { | ||
res = append(res, &corazarules.MatchData{ | ||
Variable_: c.variable, | ||
Key_: d.key, | ||
Value_: d.key, | ||
}) | ||
} | ||
} | ||
} | ||
return res | ||
} | ||
|
||
func (c *NamedCollectionNames) Get(key string) []string { | ||
return c.collection.Map.Get(key) | ||
} | ||
|
||
func (c *NamedCollectionNames) FindAll() []types.MatchData { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -571,13 +571,15 @@ | |
if m, ok := col.(collection.Keyed); ok { | ||
matches = m.FindRegex(rv.KeyRx) | ||
} else { | ||
panic("attempted to use regex with non-selectable collection: " + rv.Variable.Name()) | ||
// This should probably never happen, selectability is checked at parsing time | ||
tx.debugLogger.Error().Str("collection", rv.Variable.Name()).Msg("attempted to use regex with non-selectable collection") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed time ago that panic is ok, as this is a low level issue and coraza should not run here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I agree with this: coraza is designed as a library, and in my point of view, this means that explicit panics must be avoided at all costs (with very little exceptions, if you can call panic, you can return an error), and not doing anything is almost always better than bringing down a production website. If a function call can lead to a panic, it should be made very clear to the caller (either with an explicit function name ( For this specific case, it can only (AFAIK) be triggered by a configuration error, so this means it should be detected when parsing the configuration (and is now thanks to this PR), so the panic has become redundant. |
||
} | ||
case rv.KeyStr != "": | ||
if m, ok := col.(collection.Keyed); ok { | ||
matches = m.FindString(rv.KeyStr) | ||
} else { | ||
panic("attempted to use string with non-selectable collection: " + rv.Variable.Name()) | ||
// This should probably never happen, selectability is checked at parsing time | ||
tx.debugLogger.Error().Str("collection", rv.Variable.Name()).Msg("attempted to use string with non-selectable collection") | ||
} | ||
default: | ||
matches = col.FindAll() | ||
|
@@ -1570,11 +1572,11 @@ | |
args *collections.ConcatKeyed | ||
argsCombinedSize *collections.SizeCollection | ||
argsGet *collections.NamedCollection | ||
argsGetNames collection.Collection | ||
argsNames *collections.ConcatCollection | ||
argsGetNames collection.Keyed | ||
argsNames *collections.ConcatKeyed | ||
argsPath *collections.NamedCollection | ||
argsPost *collections.NamedCollection | ||
argsPostNames collection.Collection | ||
argsPostNames collection.Keyed | ||
duration *collections.Single | ||
env *collections.Map | ||
files *collections.Map | ||
|
@@ -1590,7 +1592,7 @@ | |
matchedVar *collections.Single | ||
matchedVarName *collections.Single | ||
matchedVars *collections.NamedCollection | ||
matchedVarsNames collection.Collection | ||
matchedVarsNames collection.Keyed | ||
multipartDataAfter *collections.Single | ||
multipartFilename *collections.Map | ||
multipartName *collections.Map | ||
|
@@ -1610,10 +1612,10 @@ | |
requestBody *collections.Single | ||
requestBodyLength *collections.Single | ||
requestCookies *collections.NamedCollection | ||
requestCookiesNames collection.Collection | ||
requestCookiesNames collection.Keyed | ||
requestFilename *collections.Single | ||
requestHeaders *collections.NamedCollection | ||
requestHeadersNames collection.Collection | ||
requestHeadersNames collection.Keyed | ||
requestLine *collections.Single | ||
requestMethod *collections.Single | ||
requestProtocol *collections.Single | ||
|
@@ -1624,7 +1626,7 @@ | |
responseContentLength *collections.Single | ||
responseContentType *collections.Single | ||
responseHeaders *collections.NamedCollection | ||
responseHeadersNames collection.Collection | ||
responseHeadersNames collection.Keyed | ||
responseProtocol *collections.Single | ||
responseStatus *collections.Single | ||
responseXML *collections.Map | ||
|
@@ -1738,7 +1740,7 @@ | |
v.argsPost, | ||
v.argsPath, | ||
) | ||
v.argsNames = collections.NewConcatCollection( | ||
v.argsNames = collections.NewConcatKeyed( | ||
variables.ArgsNames, | ||
v.argsGetNames, | ||
v.argsPostNames, | ||
|
@@ -1964,7 +1966,7 @@ | |
return v.multipartName | ||
} | ||
|
||
func (v *TransactionVariables) MatchedVarsNames() collection.Collection { | ||
func (v *TransactionVariables) MatchedVarsNames() collection.Keyed { | ||
return v.matchedVarsNames | ||
} | ||
|
||
|
@@ -1988,19 +1990,19 @@ | |
return v.filesTmpContent | ||
} | ||
|
||
func (v *TransactionVariables) ResponseHeadersNames() collection.Collection { | ||
func (v *TransactionVariables) ResponseHeadersNames() collection.Keyed { | ||
return v.responseHeadersNames | ||
} | ||
|
||
func (v *TransactionVariables) ResponseArgs() collection.Map { | ||
return v.responseArgs | ||
} | ||
|
||
func (v *TransactionVariables) RequestHeadersNames() collection.Collection { | ||
func (v *TransactionVariables) RequestHeadersNames() collection.Keyed { | ||
return v.requestHeadersNames | ||
} | ||
|
||
func (v *TransactionVariables) RequestCookiesNames() collection.Collection { | ||
func (v *TransactionVariables) RequestCookiesNames() collection.Keyed { | ||
return v.requestCookiesNames | ||
} | ||
|
||
|
@@ -2020,15 +2022,15 @@ | |
return v.resBodyProcessor | ||
} | ||
|
||
func (v *TransactionVariables) ArgsNames() collection.Collection { | ||
func (v *TransactionVariables) ArgsNames() collection.Keyed { | ||
return v.argsNames | ||
} | ||
|
||
func (v *TransactionVariables) ArgsGetNames() collection.Collection { | ||
func (v *TransactionVariables) ArgsGetNames() collection.Keyed { | ||
return v.argsGetNames | ||
} | ||
|
||
func (v *TransactionVariables) ArgsPostNames() collection.Collection { | ||
func (v *TransactionVariables) ArgsPostNames() collection.Keyed { | ||
return v.argsPostNames | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any chance
data
is empty? if so I would handle the empty case before this allocation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there are probably situations where
data
can be empty (I haven't tested, but I'd expect a collection likeXML
to have an emptydata
on a non-XML request )AFAIK, declaring a slice like this does not perform any actual allocation (other than the header of the slice, which will be all zero), and the actual allocation will be performed the first time we append to it, but I can add a check on
data
if you are worried about it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, from what I see, this check is not performed in the existing code (here for example)