diff --git a/NEWS b/NEWS index 9dc2d1d..24f34ef 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Pound -- history of user-visible changes. 2024-03-29 +Pound -- history of user-visible changes. 2024-03-30 See the end of file for copying conditions. Pound is a continuation of the software originally developed by @@ -46,6 +46,11 @@ Err400 - Err503 statements used in previous versions. These statements are still supported for backward compatibility, although their use is discouraged. +* New statement: MaxURI + +This statement sets the maximum allowed length of the request URI. +It can be used in ListenHTTP and ListenHTTPS sections. + * Bugfixes ** Don't try to access the include directory, unless needed by configuration. diff --git a/doc/pound.8 b/doc/pound.8 index f3e355a..89466a3 100644 --- a/doc/pound.8 +++ b/doc/pound.8 @@ -14,7 +14,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with pound. If not, see . -.TH POUND 8 "March 28, 2024" "pound" "System Manager's Manual" +.TH POUND 8 "March 30, 2024" "pound" "System Manager's Manual" .SH NAME pound \- HTTP/HTTPS reverse-proxy and load-balancer .SH SYNOPSIS @@ -889,6 +889,10 @@ Maximum allowed size of incoming request. All requests will be limited to these many bytes. If a request contains more data than allowed, an error 413 is returned. Default: unlimited. .TP +\fBMaxURI\fR \fIn\fR +Maximum allowed length of an URI. If the URI of a request is longer than +\fIn\fR bytes, an error 414 is returned. Default: unlimited. +.TP \fBRewriteLocation\fR 0|1|2 If set to 1, force .B pound diff --git a/doc/pound.texi b/doc/pound.texi index 2b2d8a8..ad65c88 100644 --- a/doc/pound.texi +++ b/doc/pound.texi @@ -2503,6 +2503,14 @@ A request bigger than that will be responded with status By default, there is no limit on the request size. @end deffn +@deffn {ListenHTTP directive} MaxURI @var{n} +Limits the maximum allowed length of incoming request URI. +A request with an URI longer than that will be responded with status +414. + +By default, there is no limit on the URI length. +@end deffn + @deffn {ListenHTTP directive} CheckURL "@var{pattern}" Define a pattern that must be matched by each request sent to this listener. A request that does not match will be returned a 501 diff --git a/src/config.c b/src/config.c index d89cf25..92384f2 100644 --- a/src/config.c +++ b/src/config.c @@ -4028,8 +4028,8 @@ static PARSER_TABLE http_parsetab[] = { { "Client", assign_timeout, NULL, offsetof (LISTENER, to) }, { "CheckURL", listener_parse_checkurl }, { "ErrorFile", parse_errorfile, NULL, offsetof (LISTENER, http_err) }, - { "MaxRequest", assign_CONTENT_LENGTH, NULL, offsetof (LISTENER, max_req) }, - + { "MaxRequest", assign_CONTENT_LENGTH, NULL, offsetof (LISTENER, max_req_size) }, + { "MaxURI", assign_unsigned, NULL, offsetof (LISTENER, max_uri_length) }, { "Rewrite", parse_rewrite, NULL, offsetof (LISTENER, rewrite) }, { "SetHeader", SETFN_SVC_NAME (set_header), NULL, offsetof (LISTENER, rewrite) }, { "DeleteHeader", SETFN_SVC_NAME (delete_header), NULL, offsetof (LISTENER, rewrite) }, @@ -4681,7 +4681,8 @@ static PARSER_TABLE https_parsetab[] = { { "Client", assign_timeout, NULL, offsetof (LISTENER, to) }, { "CheckURL", listener_parse_checkurl }, { "ErrorFile", parse_errorfile, NULL, offsetof (LISTENER, http_err) }, - { "MaxRequest", assign_CONTENT_LENGTH, NULL, offsetof (LISTENER, max_req) }, + { "MaxRequest", assign_CONTENT_LENGTH, NULL, offsetof (LISTENER, max_req_size) }, + { "MaxURI", assign_unsigned, NULL, offsetof (LISTENER, max_uri_length) }, { "Rewrite", parse_rewrite, NULL, offsetof (LISTENER, rewrite) }, { "SetHeader", SETFN_SVC_NAME (set_header), NULL, offsetof (LISTENER, rewrite) }, diff --git a/src/http.c b/src/http.c index 84a0976..5aa9f9e 100644 --- a/src/http.c +++ b/src/http.c @@ -4095,7 +4095,7 @@ send_to_backend (POUND_HTTP *phttp, int chunked, CONTENT_LENGTH content_length) */ int rc = copy_chunks (phttp->cl, phttp->be, NULL, phttp->backend->be_type != BE_BACKEND, - phttp->lstn->max_req); + phttp->lstn->max_req_size); if (rc != HTTP_STATUS_OK) { log_error (phttp, rc, errno, "error sending chunks"); @@ -4603,11 +4603,36 @@ do_http (POUND_HTTP *phttp) } } + if (phttp->lstn->max_uri_length > 0) + { + int rc; + char const *url; + rc = http_request_get_url (&phttp->request, &url); + if (rc == RETRIEVE_OK) + { + size_t urlen; + if ((urlen = strlen (url)) > phttp->lstn->max_uri_length) + { + log_error (phttp, HTTP_STATUS_URI_TOO_LONG, 0, + "URI too long: %zu bytes", + urlen); + http_err_reply (phttp, HTTP_STATUS_URI_TOO_LONG); + return; + } + } + else + { + log_error (phttp, HTTP_STATUS_INTERNAL_SERVER_ERROR, 0, + "can't get URL from the request (shouldn't happen)"); + goto err; + } + } + /* * possibly limited request size */ - if (phttp->lstn->max_req > 0 && content_length > 0 - && content_length > phttp->lstn->max_req) + if (phttp->lstn->max_req_size > 0 && content_length > 0 + && content_length > phttp->lstn->max_req_size) { log_error (phttp, HTTP_STATUS_PAYLOAD_TOO_LARGE, 0, "request too large: %"PRICLEN" bytes", diff --git a/src/pound.h b/src/pound.h index 32e0e1f..c9aa71b 100644 --- a/src/pound.h +++ b/src/pound.h @@ -734,7 +734,8 @@ typedef struct _listener unsigned to; /* client time-out */ regex_t *url_pat; /* pattern to match the request URL against */ char *http_err[HTTP_STATUS_MAX]; /* error messages */ - CONTENT_LENGTH max_req; /* max. request size */ + CONTENT_LENGTH max_req_size; /* max. request size */ + unsigned max_uri_length; /* max. URI length */ int rewr_loc; /* rewrite location response */ int rewr_dest; /* rewrite destination header */ int disabled; /* true if the listener is disabled */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 0129a34..9bdb7e4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -95,6 +95,7 @@ TESTSUITE_AT = \ logsup.at\ lstset.at\ maxrequest.at\ + maxuri.at\ multival.at\ nb.at\ not.at\ diff --git a/tests/maxuri.at b/tests/maxuri.at new file mode 100644 index 0000000..3ef075d --- /dev/null +++ b/tests/maxuri.at @@ -0,0 +1,37 @@ +# This file is part of pound testsuite. -*- autotest -*- +# Copyright (C) 2022-2024 Sergey Poznyakoff +# +# Pound is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Pound is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pound. If not, see . +AT_SETUP([MaxURI]) +AT_KEYWORDS([maxuri]) + +PT_CHECK([ListenHTTP + MaxURI 8 + Service + Backend + Address + Port + End + End +End +], +[GET /echo/file + +end + +414 +end +]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 3f98880..28f05f6 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -58,6 +58,7 @@ m4_include([xhttp.at]) m4_include([checkurl.at]) m4_include([errfile.at]) m4_include([maxrequest.at]) +m4_include([maxuri.at]) m4_include([rewriteloc.at]) m4_include([nb.at]) m4_include([chunked.at])