-
Notifications
You must be signed in to change notification settings - Fork 103
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
Prohibit DELETE method in default configuration #2058 #2078
base: master
Are you sure you want to change the base?
Conversation
fw/http_limits.c
Outdated
} | ||
__FRANG_FSM_MOVE(Frang_Req_Hdr_UriLen); | ||
} | ||
T_FSM_STATE(Frang_Req_Hdr_Method) { |
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.
Invalid tabulation.
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.
Sorry, I have changed my editor's behavior.
fw/http_limits.c
Outdated
|
||
if (!f_cfg->http_methods_mask) { | ||
/* If we have a default value, we set all bits to 1 except DELETE */ | ||
f_cfg->http_methods_mask = ~(1 << TFW_HTTP_METH_DELETE); |
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.
I think we should also prohibit PUT method here
You should also fix tests, where DELETE method is used by adding appropriate DELETE method to frang config |
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.
Definitely need more work and it seems the issue isn't so straightforward as I thought, so we need a good discussion on this.
Also please make pull requests from our repo, not your own - this way we can just switch between branches during review instead of cloning repos of each developers.
Finally, please don't forget to update wiki about allowed methods by default. Probably it also makes sense to describe in the wiki how DELETE behaves with the cache.
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.
LGTM with just a small coding style cleanup
fw/vhost.c
Outdated
|
||
#define TFW_FRANG_HTTP_METHODS_MASK_DEFAULT ((1 << TFW_HTTP_METH_GET) | \ | ||
(1 << TFW_HTTP_METH_HEAD) | \ | ||
(1 << TFW_HTTP_METH_POST)) | ||
|
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.
#define TFW_FRANG_HTTP_METHODS_MASK_DEFAULT ((1 << TFW_HTTP_METH_GET) | \ | |
(1 << TFW_HTTP_METH_HEAD) | \ | |
(1 << TFW_HTTP_METH_POST)) | |
#define TFW_FRANG_HTTP_METHODS_MASK_DEFAULT ((1 << TFW_HTTP_METH_GET) | \ | |
(1 << TFW_HTTP_METH_HEAD) | \ | |
(1 << TFW_HTTP_METH_POST)) | |
We almost never use 2 empty lines in C/C++ code and we use alignments (tabs plus spaces)
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.
I would like to suggest another solution. In TfwCfgSpec
we can specify default values for each directive.
Example:
{
.name = "http_methods",
.deflt = "get post head",
.handler = tfw_cfgop_frang_http_methods,
.allow_reconfig = true,
},
Field deflt
it's just value, same as in config, that will be parsed and assigned to directive. Please, change TfwCfgSpec
for each context.
Also, I believe, we don't need to remove already made changes, we will treat empty value, as defualt. Or we can remove these changes, and treat empty value of this directive as error - this looks more clear for me. Up to you.
@@ -3220,7 +3237,7 @@ static TfwCfgSpec tfw_vhost_internal_specs[] = { | |||
.handler = tfw_cfg_handle_children, | |||
.cleanup = tfw_cfgop_frang_cleanup, | |||
.dest = tfw_vhost_frang_specs, | |||
.allow_none = true, | |||
.allow_none = false, |
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.
Why do we set allow_none
to false for frang_limits
?
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.
If we leave allow_none as true, the default configuration won't be read in spec_finish_handling(TfwCfgSpec specs[]).
It was the reason why I wrote my previous version.
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.
This seems wrong. Are you sure? There are plenty of places in the code with both .allow_none = true
and .deflt
set to some value.
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, guys, I was wrong.
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.
I tested it more careful and found that with .allow_none = true, in this position, it stops using default configuration when vhost is configured in tempesta_fw.cfg.
Looks like I hastened to agree with you. And we need to use .allow_none = false or change behavior of spec_finish_handling(TfwCfgSpec specs[]) or change somthing else.
fw/vhost.c
Outdated
return -EINVAL; | ||
} | ||
|
||
T_ERR_NL("frang: http_methods should contain at least one " |
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.
Looks like dead code and we never reach this place. If we have ce->dflt_value == false
it means value was specified in config and now we know that this value is empty. Therefore, we will always return in if (!ce->dflt_value)
. Is there a case when ce->dflt_value == true
but ce->val_n == false
?
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.
This situation is possible when we have " http_methods ;" in config
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.
In my understanding when we have " http_methods ;" then we have ce->dflt_value == false
and ce->val_n == false
in other cases we will have ce->val_n > 0
. For example: http_methods ""; or http_methods " "; will have ce->val_n > 0
and will disallowed in TFW_CFG_ENTRY_FOR_EACH_VAL
. I can't find another value for http_methods where ce->val_n == 0
except " http_methods ;". Do you know such value for http_methods?
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, when we have
.name = "http_methods",
.deflt = "",
in the code
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.
Now we doesn't, and I believe we must not maintain this. If you warring about this, it would be better to write a comment in appropriate place.
Please remove todo from |
@@ -1142,14 +1140,13 @@ frang_http_req_process(FrangAcc *ra, TfwConn *conn, TfwFsmData *data, | |||
|
|||
/* Ensure that HTTP request method is one of those defined by a user. */ | |||
T_FSM_STATE(Frang_Req_Hdr_Method) { | |||
if (f_cfg->http_methods_mask) { |
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.
I removed checking f_cfg->http_methods_mask because this checking breaks new logic.
configuration part. And everything was prohibited except GET, HEAD and POST.
and the request was dropped by frang after that.
Please implement a workaround for #2119 with a TODO comment |
Fixed reading default value of http_strict_host_checking. Chenged frang inheritance for locatians in default vhost.
I manage to do it in normal way. |
A want to ask you to check following(and others similar conditions) part in
In this case we don't freed split skb as well. To check it just use redirects.
|
fw/tls.c
Outdated
@@ -1128,6 +1128,11 @@ tfw_tls_start(void) | |||
return 0; | |||
} | |||
|
|||
bool tfw_tls_get_allow_any_sni_reconfig(void) |
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.
bool tfw_tls_get_allow_any_sni_reconfig(void) | |
bool | |
tfw_tls_get_allow_any_sni_reconfig(void) |
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.
In general looks good, but could you add a little bit description to the last commit.
Chenged frang inheritance for locatians in default vhost
Why it's changed, how it's changed. Also looks like you fixed live-reconfig logic for frang, describe it also in the commit message.
fw/http.c
Outdated
"parsed request has been filtered out", | ||
HTTP2_ECODE_PROTO); | ||
if (skb) { |
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.
Seems we can remove this unnecessary condition if (skb)
then just assign skb
and return r
instead of T_DROP
.
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.
We should not change return code here, because it is used to determine how Tempesta close connection.
We should also fix this memory leak in all other places in this function.
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.
Code reworked. I tried to make it universal, but if you think it is not the best way, I will rework it for special cases only.
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.
Change fixing memory leak
etc/tempesta_fw.conf
Outdated
# http_uri_len 0; | ||
# http_body_len 1073741824; | ||
# http_hdr_len 0; | ||
# http_header_cnt 0; |
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.
50 is default value for this setting. Please also check all other settings. concurrent_tcp_connections - 1000 is default settings
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.
Fixed
fw/vhost.c
Outdated
@@ -2141,7 +2197,7 @@ tfw_cfgop_frang_strict_host_checking(TfwCfgSpec *cs, TfwCfgEntry *ce) | |||
int r; | |||
FrangVhostCfg *cfg = tfw_cfgop_frang_get_cfg(); | |||
|
|||
if (ce->dflt_value && cfg->http_strict_host_checking) | |||
if (ce->dflt_value && !cfg->http_strict_host_checking) |
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.
We need to discuss this place. If I understand it correctly we have the same problem for http_body_len
also and may be some other settings.
frang_limits {
http_body_len 0;
}
frang_limits {
}
The second one frang_limits has default http_body_len == 1073741824, should we override previosly set http_body_len
or not?
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.
I returned the old behavior, only explicit parameters should be overridden.
fw/vhost.c
Outdated
@@ -1903,6 +1911,11 @@ __tfw_cfgop_frang_http_methods(TfwCfgSpec *cs, TfwCfgEntry *ce, | |||
methods_mask |= (1UL << method_id); | |||
} | |||
|
|||
if (!ce->val_n && !ce->dflt_value) { |
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.
You don't need to check !ce->dflt_value here, because if it is dflt_value vam_n is always 3 (get post head). This check is better to do before TFW_CFG_ENTRY_FOR_EACH_VAL
loop
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.
TFW_CFG_CHECK_VAL_N(>, 0, cs, ce);
TFW_CFG_CHECK_NO_ATTRS(cs, ce);
is right way. Tempesta interpret get=hhhsdsd as attribute and silently ignore such invalid configuration
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.
Reworked.
fw/vhost.c
Outdated
.allow_reconfig = true, | ||
}, | ||
{ | ||
.name = "http_body_len", | ||
.deflt = "1073741824", /* 1 Gb. */ | ||
.handler = tfw_cfgop_frang_body_len, | ||
.handler = tfw_cfgop_frang_glob_set_long, |
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.
It is incorrect to use tfw_cfgop_frang_glob_set_long
here. If we have global frang limits like below:
frang_limits {
http_body_len 0;
}
frang_limits {
}
We should not override http_body_len 0;
in the second config as i understand the idea in all other places.
I thinkn that using tfw_cfgop_frang_glob_set_int
for tfw_frang_glob_reconfig.http_hdr_cnt is also incorrect. Same as for concurrent_tcp_connections
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.
I returned the old behavior, only explicit parameters should be overridden.
fw/vhost.c
Outdated
.allow_reconfig = true, | ||
}, | ||
{ | ||
.name = "http_strict_host_checking", | ||
.deflt = "true", | ||
.handler = tfw_cfgop_frang_strict_host_checking, | ||
.handler = tfw_cfgop_frang_glob_set_bool, |
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.
We can't use tfw_cfgop_frang_glob_set_bool here because default value is true.
frang_limits {
http_strict_host_checking false;
}
frang_limits {
}
We have http_strict_host_checking true, but should have false
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.
Please add tests for all this changes! We need to cover all this cases because I found a lot of mistakes here. you should check several frang_limits on one level and how it is work.
if (tfw_frang_cfg_inherit(loc->frang_cfg, vhost->loc_dflt->frang_cfg)) | ||
return NULL; | ||
if (strncasecmp(vhost->name.data, TFW_VH_DFT_NAME, vhost->name.len)) { | ||
if (tfw_frang_cfg_inherit(loc->frang_cfg, |
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.
Please look at this function tfw_frang_cfg_inherit
we have BUG in it.
if (!curr->http_ct_vals)
we only set r = -ENOMEM and do not return. Then we memcpy(curr->http_ct_vals, from->http_ct_vals, sz);
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.
Add else to avoid using curr->http_ct_vals after error.
* Do not perform any SNI<=>authority validation if | ||
* tls_match_any_server_name is set. | ||
*/ | ||
if (tfw_tls_allow_any_sni) |
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.
Why do you delete this check? Previously when tls_match_any_server_name is true, we return T_OK. Why this behavior is changed?
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.
When tfw_tls_allow_any_sni
is true, it means connection with empty sni or sni not listed in our vhost is "routed" to default vhost. In other words tfw_tls_allow_any_sni
is the way to enable default vhost and it's not related to other vhosts. But when we have this check here and we want to check SNI vs authority for some vhosts and don't check for other we can't do this, because tfw_tls_allow_any_sni
will override it.
Now I would prefer to introduce new knob only for domain fronting, that must be disabled by default. It will depends on tfw_tls_allow_any_sni
also, but in the future we will remove default
vhost and tfw_tls_allow_any_sni
and will check SNI only when vhost is found by http tables.
fw/vhost.c
Outdated
static int | ||
tfw_cfgop_frang_glob_rsp_code_block(TfwCfgSpec *cs, TfwCfgEntry *ce) | ||
{ | ||
FrangVhostCfg *cfg = &tfw_frang_vhost_reconfig; |
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.
Why we can't use tfw_cfgop_frang_rsp_code_block
. The only difference that here we directly set FrangVhostCfg *cfg = &tfw_frang_vhost_reconfig; instead of FrangVhostCfg *cfg = tfw_cfgop_frang_get_cfg(); ?
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.
It was attempt to solve strange location inheritance for default vhost. I returned it back now because my code had changed overriding.
fw/vhost.c
Outdated
kfree(cfg->http_resp_code_block); | ||
cfg->http_resp_code_block = NULL; | ||
} | ||
return __tfw_cfgop_frang_rsp_code_block(cs, ce, cfg); |
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.
Can you also check __tfw_cfgop_frang_rsp_code_block
. I see that we return -EINVAL after memory allocation without
freeing previously allocated cb = kzalloc(sizeof(FrangHttpRespCodeBlock), GFP_KERNEL); Is there memory leak or we will free it later?
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.
It assigns to conf->http_resp_code_block and will be freed by __tfw_frang_clean() in case of error.
Only GET, HEAD and POST are allowed by default. Global frang initialization happens before reading config file. Global frang was copied before initialization to prevent using old config during live-reconfiguration. Fixed memory leak when skb was split in tfw_http_req_process(). Fixed bug in tfw_frang_cfg_inherit(). tls_match_any_server_name is now permited only globaly. Now tls_match_any_server_name and http_strict_host_checking are used independandly. Changed inheritance for locations of default vhost. Added print frang configuration.
My first attempt, I am not sure that it is the best solution, but it seems to work.