Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 8:38 PM Ruediger Pluem  wrote:
>
> On 6/8/20 6:06 PM, Yann Ylavic wrote:
> > On Mon, Jun 8, 2020 at 5:43 PM Julian Reschke  wrote:
> >>
> >> On 08.06.2020 16:59, Yann Ylavic wrote:
> >>> On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
> 
>  I came across the question if we should not reject HTTP protocols >= 2.0 
>  in the request line when we parse it
>  in ap_parse_request_line.
> >>>
> >>> Why not >= 1.2 ?
> >>
> >> In *theory*, there could a future HTTP/1.2 version that shares the wire
> >> format with 1.0 and 1.1.
>
> Exactly this was my reason for not >= 1.2 as this case is IMHO already 
> handled in a compliant way by the current code.
> https://tools.ietf.org/html/rfc7230#section-2.6 states:
>
> The interpretation of a header field does not change between minor
>versions of the same major HTTP version, though the default behavior
>of a recipient in the absence of such a field can change.  Unless
>specified otherwise, header fields defined in HTTP/1.1 are defined
>for all versions of HTTP/1.x.  In particular, the Host and Connection
>header fields ought to be implemented by all HTTP/1.x implementations
>whether or not they advertise conformance with HTTP/1.1.
>
>New header fields can be introduced without changing the protocol
>version if their defined semantics allow them to be safely ignored by
>recipients that do not recognize them.  Header field extensibility is
>discussed in Section 3.2.1.
>
>
> I interpret this that if we handle a potential HTTP 1.2 request as if
>
> - headers already known in HTTP 1.1 are handled in the same way as if the 
> request was HTTP 1.1
> - headers unknown in HTTP 1.2 and added and in HTTP 1.2 are ignored
>
> we are on the safe side if we sent back a HTTP 1.1 response.
>
> Furthermore I get from https://tools.ietf.org/html/rfc7231#section-6.6.6 that
> 505 indicates that we reject the processing of the major version which would 
> be wrong in the HTTP 1.2 case
> as we will process HTTP 1.0 and HTTP 1.1.

Fair enough ;)

Regards;
Yann.


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 10:12 PM Ruediger Pluem  wrote:
>
> On 6/8/20 10:05 PM, Yann Ylavic wrote:
> > On Mon, Jun 8, 2020 at 9:30 PM Ruediger Pluem  wrote:
> >>
> >> On 6/8/20 4:59 PM, Yann Ylavic wrote:
> >>> On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
> 
>  I came across the question if we should not reject HTTP protocols >= 2.0 
>  in the request line when we parse it
>  in ap_parse_request_line.
> >>>
> >>> Why not >= 1.2 ?
> >>>
>  A possible patch could look like the following (which rejects such 
>  requests with a HTTP_VERSION_NOT_SUPPORTED status code):
> >>>
> >>> Looks good.
> >>>
> >>>
> >>> In the same category, could we reject invalid URI paths earlier
> >>> (request-target per RFC-7230 5.3)?
> >>> Today it fails in ap_core_translate(), but possibly the below would be 
> >>> better:
> >>
> >> I think we could, but I am not sure if we have ap_parse_uri callers in 
> >> other parts of the code that do not pass absolute URI's
> >
> > This patch works with absolute URIs too since apr_parse_uri will split
> > it in r->parsed_uri and we consider r->parsed_uri.path only.
>
> I guess I was not precise enough with my concern. I meant that I haven't 
> checked if there are callers which pass in relative URI's.

Oh no, actually _I_ missed the "do _not_ pass" :)

I don't think ap_parse_uri() should accept an URI-path which is not
HTTP compliant (i.e. does not start with '/'), that's where we
initialize the request_rec after all.. So yes apr_uri_parse() accepts
that and sets a relative path in r->parsed_uri.path, but
ap_parse_uri() if for HTTP parsing IMHO.

Regards;
Yann.


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Ruediger Pluem



On 6/8/20 10:05 PM, Yann Ylavic wrote:
> On Mon, Jun 8, 2020 at 9:30 PM Ruediger Pluem  wrote:
>>
>> On 6/8/20 4:59 PM, Yann Ylavic wrote:
>>> On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:

 I came across the question if we should not reject HTTP protocols >= 2.0 
 in the request line when we parse it
 in ap_parse_request_line.
>>>
>>> Why not >= 1.2 ?
>>>
 A possible patch could look like the following (which rejects such 
 requests with a HTTP_VERSION_NOT_SUPPORTED status code):
>>>
>>> Looks good.
>>>
>>>
>>> In the same category, could we reject invalid URI paths earlier
>>> (request-target per RFC-7230 5.3)?
>>> Today it fails in ap_core_translate(), but possibly the below would be 
>>> better:
>>
>> I think we could, but I am not sure if we have ap_parse_uri callers in other 
>> parts of the code that do not pass absolute URI's
> 
> This patch works with absolute URIs too since apr_parse_uri will split
> it in r->parsed_uri and we consider r->parsed_uri.path only.

I guess I was not precise enough with my concern. I meant that I haven't 
checked if there are callers which pass in relative URI's.

> 
>>
>>>
>>> Index: server/protocol.c
>>> ===
>>> --- server/protocol.c(revision 1878328)
>>> +++ server/protocol.c(working copy)
>>> @@ -627,6 +627,14 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r,
>>>  }
>>>  else {
>>>  status = apr_uri_parse(r->pool, uri, >parsed_uri);
>>> +if (status == APR_SUCCESS
>>> +&& (r->parsed_uri.path != NULL)
>>> +&& (r->parsed_uri.path[0] != '/')
>>> +&& (r->method_number != M_OPTIONS
>>> +|| strcmp(r->parsed_uri.path, "*") != 0)) {
>>> +/* Invalid request-target per rfc7230#section-5.3 */
>>> +status = APR_EINVAL;
>>> +}
>>>  }
>>>
>>>  if (status == APR_SUCCESS) {
>>
>> Don't we miss in  server/protocol.c:
>>
>> @@ -906,6 +911,12 @@
>>
>>  ap_parse_uri(r, uri);
>>
>> +if (strict && deferred_error == rrl_none
>> +&& r->status == HTTP_BAD_REQUEST) {
>> +deferred_error = rrl_invaliduri
>> +}
> 
> Somehow r->status != HTTP_OK is caught below all the deferred_error
> cases (which we want to report in priority?), and then jumps to the
> rrl_failed label.

Fair enough :-) I missed this one.

Regards

Rüdiger



Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 10:05 PM Yann Ylavic  wrote:
>
> On Mon, Jun 8, 2020 at 9:30 PM Ruediger Pluem  wrote:
> >
> > I think we could, but I am not sure if we have ap_parse_uri callers in 
> > other parts of the code that do not pass absolute URI's
>
> This patch works with absolute URIs too since apr_parse_uri will split
> it in r->parsed_uri and we consider r->parsed_uri.path only.

But to be complete on that side, and handle the proxy case of the
asterisk-form (section 5.3.4 [1]), I think we also need this hunk:

Index: server/protocol.c
===
--- server/protocol.c(revision 1878328)
+++ server/protocol.c(working copy)
@@ -640,8 +648,15 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r,
 }

 r->args = r->parsed_uri.query;
-r->uri = r->parsed_uri.path ? r->parsed_uri.path
- : apr_pstrdup(r->pool, "/");
+if (r->parsed_uri.path) {
+r->uri = r->parsed_uri.path;
+}
+else if (r->method_number == M_OPTIONS) {
+r->uri = apr_pstrdup(r->pool, "*");
+}
+else {
+r->uri = apr_pstrdup(r->pool, "/");
+}

 #if defined(OS2) || defined(WIN32)
 /* Handle path translations for OS/2 and plug security hole.
--

[1] https://tools.ietf.org/html/rfc7230#section-5.3.4


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 9:30 PM Ruediger Pluem  wrote:
>
> On 6/8/20 4:59 PM, Yann Ylavic wrote:
> > On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
> >>
> >> I came across the question if we should not reject HTTP protocols >= 2.0 
> >> in the request line when we parse it
> >> in ap_parse_request_line.
> >
> > Why not >= 1.2 ?
> >
> >> A possible patch could look like the following (which rejects such 
> >> requests with a HTTP_VERSION_NOT_SUPPORTED status code):
> >
> > Looks good.
> >
> >
> > In the same category, could we reject invalid URI paths earlier
> > (request-target per RFC-7230 5.3)?
> > Today it fails in ap_core_translate(), but possibly the below would be 
> > better:
>
> I think we could, but I am not sure if we have ap_parse_uri callers in other 
> parts of the code that do not pass absolute URI's

This patch works with absolute URIs too since apr_parse_uri will split
it in r->parsed_uri and we consider r->parsed_uri.path only.

>
> >
> > Index: server/protocol.c
> > ===
> > --- server/protocol.c(revision 1878328)
> > +++ server/protocol.c(working copy)
> > @@ -627,6 +627,14 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r,
> >  }
> >  else {
> >  status = apr_uri_parse(r->pool, uri, >parsed_uri);
> > +if (status == APR_SUCCESS
> > +&& (r->parsed_uri.path != NULL)
> > +&& (r->parsed_uri.path[0] != '/')
> > +&& (r->method_number != M_OPTIONS
> > +|| strcmp(r->parsed_uri.path, "*") != 0)) {
> > +/* Invalid request-target per rfc7230#section-5.3 */
> > +status = APR_EINVAL;
> > +}
> >  }
> >
> >  if (status == APR_SUCCESS) {
>
> Don't we miss in  server/protocol.c:
>
> @@ -906,6 +911,12 @@
>
>  ap_parse_uri(r, uri);
>
> +if (strict && deferred_error == rrl_none
> +&& r->status == HTTP_BAD_REQUEST) {
> +deferred_error = rrl_invaliduri
> +}

Somehow r->status != HTTP_OK is caught below all the deferred_error
cases (which we want to report in priority?), and then jumps to the
rrl_failed label.


Regards;
Yann.


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Ruediger Pluem



On 6/8/20 4:59 PM, Yann Ylavic wrote:
> On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
>>
>> I came across the question if we should not reject HTTP protocols >= 2.0 in 
>> the request line when we parse it
>> in ap_parse_request_line.
> 
> Why not >= 1.2 ?
> 
>> A possible patch could look like the following (which rejects such requests 
>> with a HTTP_VERSION_NOT_SUPPORTED status code):
> 
> Looks good.
> 
> 
> In the same category, could we reject invalid URI paths earlier
> (request-target per RFC-7230 5.3)?
> Today it fails in ap_core_translate(), but possibly the below would be better:

I think we could, but I am not sure if we have ap_parse_uri callers in other 
parts of the code that do not pass absolute URI's

> 
> Index: server/protocol.c
> ===
> --- server/protocol.c(revision 1878328)
> +++ server/protocol.c(working copy)
> @@ -627,6 +627,14 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r,
>  }
>  else {
>  status = apr_uri_parse(r->pool, uri, >parsed_uri);
> +if (status == APR_SUCCESS
> +&& (r->parsed_uri.path != NULL)
> +&& (r->parsed_uri.path[0] != '/')
> +&& (r->method_number != M_OPTIONS
> +|| strcmp(r->parsed_uri.path, "*") != 0)) {
> +/* Invalid request-target per rfc7230#section-5.3 */
> +status = APR_EINVAL;
> +}
>  }
> 
>  if (status == APR_SUCCESS) {

Don't we miss in  server/protocol.c:

@@ -906,6 +911,12 @@

 ap_parse_uri(r, uri);

+if (strict && deferred_error == rrl_none
+&& r->status == HTTP_BAD_REQUEST) {
+deferred_error = rrl_invaliduri
+}
+
+

Plus adding rrl_invaliduri to the enum and handling later on?

Regards

Rüdiger




Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Ruediger Pluem



On 6/8/20 6:06 PM, Yann Ylavic wrote:
> On Mon, Jun 8, 2020 at 5:43 PM Julian Reschke  wrote:
>>
>> On 08.06.2020 16:59, Yann Ylavic wrote:
>>> On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:

 I came across the question if we should not reject HTTP protocols >= 2.0 
 in the request line when we parse it
 in ap_parse_request_line.
>>>
>>> Why not >= 1.2 ?
>>
>> In *theory*, there could a future HTTP/1.2 version that shares the wire
>> format with 1.0 and 1.1.

Exactly this was my reason for not >= 1.2 as this case is IMHO already handled 
in a compliant way by the current code.
https://tools.ietf.org/html/rfc7230#section-2.6 states:

The interpretation of a header field does not change between minor
   versions of the same major HTTP version, though the default behavior
   of a recipient in the absence of such a field can change.  Unless
   specified otherwise, header fields defined in HTTP/1.1 are defined
   for all versions of HTTP/1.x.  In particular, the Host and Connection
   header fields ought to be implemented by all HTTP/1.x implementations
   whether or not they advertise conformance with HTTP/1.1.

   New header fields can be introduced without changing the protocol
   version if their defined semantics allow them to be safely ignored by
   recipients that do not recognize them.  Header field extensibility is
   discussed in Section 3.2.1.


I interpret this that if we handle a potential HTTP 1.2 request as if

- headers already known in HTTP 1.1 are handled in the same way as if the 
request was HTTP 1.1
- headers unknown in HTTP 1.2 and added and in HTTP 1.2 are ignored

we are on the safe side if we sent back a HTTP 1.1 response.

Furthermore I get from https://tools.ietf.org/html/rfc7231#section-6.6.6 that
505 indicates that we reject the processing of the major version which would be 
wrong in the HTTP 1.2 case
as we will process HTTP 1.0 and HTTP 1.1.

Regards

Rüdiger


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 5:43 PM Julian Reschke  wrote:
>
> On 08.06.2020 16:59, Yann Ylavic wrote:
> > On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
> >>
> >> I came across the question if we should not reject HTTP protocols >= 2.0 
> >> in the request line when we parse it
> >> in ap_parse_request_line.
> >
> > Why not >= 1.2 ?
>
> In *theory*, there could a future HTTP/1.2 version that shares the wire
> format with 1.0 and 1.1.

Sure, but we have quite some time to adapt the check then :)


Regards;
Yann.


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Julian Reschke

On 08.06.2020 16:59, Yann Ylavic wrote:

On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:


I came across the question if we should not reject HTTP protocols >= 2.0 in the 
request line when we parse it
in ap_parse_request_line.


Why not >= 1.2 ?


In *theory*, there could a future HTTP/1.2 version that shares the wire
format with 1.0 and 1.1.


...


Best regards, Julian


Re: Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Yann Ylavic
On Mon, Jun 8, 2020 at 9:56 AM Ruediger Pluem  wrote:
>
> I came across the question if we should not reject HTTP protocols >= 2.0 in 
> the request line when we parse it
> in ap_parse_request_line.

Why not >= 1.2 ?

> A possible patch could look like the following (which rejects such requests 
> with a HTTP_VERSION_NOT_SUPPORTED status code):

Looks good.


In the same category, could we reject invalid URI paths earlier
(request-target per RFC-7230 5.3)?
Today it fails in ap_core_translate(), but possibly the below would be better:

Index: server/protocol.c
===
--- server/protocol.c(revision 1878328)
+++ server/protocol.c(working copy)
@@ -627,6 +627,14 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r,
 }
 else {
 status = apr_uri_parse(r->pool, uri, >parsed_uri);
+if (status == APR_SUCCESS
+&& (r->parsed_uri.path != NULL)
+&& (r->parsed_uri.path[0] != '/')
+&& (r->method_number != M_OPTIONS
+|| strcmp(r->parsed_uri.path, "*") != 0)) {
+/* Invalid request-target per rfc7230#section-5.3 */
+status = APR_EINVAL;
+}
 }

 if (status == APR_SUCCESS) {
--

Regards;
Yann.


Re: RFC: Documenting changes in the CHANGES file

2020-06-08 Thread Nick Kew



> On 1 Jun 2020, at 13:33, Graham Leggett  wrote:
> 
> On 29 May 2020, at 21:30, Ruediger Pluem  wrote:
> 
>>  changes-fragments/
>>2.4.41/
>>2.4.42/
>>2.4.43/
>>2.4.44/

And a current/ as symlink?

> I’m keen for a simpler version of this that doesn't create additional steps 
> for people.

Not sure that's simpler, though it too has potential.  Delete-after-append 
seems tidier
than keeping forever-fragments.

I wonder if this could be hooked into SVN?  Something like an @CHANGES tag in
a svn commit message?

-- 
Nick Kew

Re: RFC: Documenting changes in the CHANGES file

2020-06-08 Thread Ruediger Pluem



On 6/2/20 2:17 PM, Stefan Eissing wrote:
> 
>> Am 02.06.2020 um 14:11 schrieb Daniel Ruggeri :
>>
>> On 6/1/2020 6:23 AM, Yann Ylavic wrote:
>>> On Fri, May 29, 2020 at 9:30 PM Ruediger Pluem 
>>>  wrote:
>>>
 Reviewing our backport process I noticed that in many cases a clean merge 
 via svn merge fails due to conflicts in CHANGES. While
 these are easy to solve it puts IMHO unnecessary extra work on the 
 backport process, both for reviewing and for actually doing the
 backport. How about if we change the way we document changes the following 
 way:

 1. We create a changes-fragments directory (name to be determined) at the 
 top level.
 2. For each release we create a subdirectory such that we end up with the 
 following structure:

changes-fragments/
  2.4.41/
  2.4.42/
  2.4.43/
  2.4.44/

 3. Each directory contains the changes for each release and each change 
 entry is a single file.
 4. We have a script that builds our current CHANGES file from the content 
 in changes-fragments directories with the help of
a template or at least some sort of header / footer that is static.
 5. This script can be called either manually and we commit the resulting 
 CHANGES file as we like just like the x-forms commits
for documentation plus this script is called by the release scripts 
 from Daniel as part of the preparation of rolling a
release.

>>> +1 from me, I don't volonteer for the scripts though :)
>>>
>>> Regards;
>>> Yann.
>>>
>> Hi, Yann;
>>
>> I'm open to whatever... and don't mind writing or tweaking scripts once we 
>> decide on an approach :-)
>>
>> While we are discussing ideas in this neighborhood, one thing to keep in 
>> mind is that during release of security fixes, sometimes there are items 
>> added to CHANGES and sometimes CHANGES is modified to add CVE information. 
>> There have been minor bumps in the road where these patches don't always 
>> apply cleanly. So, if possible, it would be great to consider. There may be 
>> nothing to do, though, since that happens way after backport.
>>
> 
> 
> +1 from me as well. CHANGES is annoying atm, any automation appreciated.
> 

Thanks for all the feedback. I try to work out something more detailed aka 
patch that we can discuss then.

Regards

Rüdiger




Reject HTTP protocols >= 2.0 in ap_parse_request_line?

2020-06-08 Thread Ruediger Pluem
I came across the question if we should not reject HTTP protocols >= 2.0 in the 
request line when we parse it
in ap_parse_request_line.
This does not affect mod_http2 if loaded as HTTP/2.0 connections itself are not 
parsed via ap_parse_request_line
and sending a

GET /something HTTP/2.0

as request line is not a valid way to start a HTTP 2.0 connection and I doubt 
that it will be for future major versions.
A possible patch could look like the following (which rejects such requests 
with a HTTP_VERSION_NOT_SUPPORTED status code):

Index: server/protocol.c
===
--- server/protocol.c   (revision 1878470)
+++ server/protocol.c   (working copy)
@@ -748,7 +748,7 @@ AP_DECLARE(int) ap_parse_request_line(request_rec
 enum {
 rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace,
 rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext,
-rrl_badmethod09, rrl_reject09
+rrl_badmethod09, rrl_reject09, rrl_versionnotsupported
 } deferred_error = rrl_none;
 apr_size_t len = 0;
 char *uri, *ll;
@@ -897,6 +897,11 @@ rrl_done:
 r->proto_num = HTTP_VERSION(0, 9);
 }

+if (strict && deferred_error == rrl_none
+&& r->proto_num >= HTTP_VERSION(2, 0)) {
+deferred_error = rrl_versionnotsupported;
+}
+
 /* Determine the method_number and parse the uri prior to invoking error
  * handling, such that these fields are available for substitution
  */
@@ -918,6 +923,7 @@ rrl_done:
  * we can safely resume any deferred error reporting
  */
 if (deferred_error != rrl_none) {
+r->status = HTTP_BAD_REQUEST;
 if (deferred_error == rrl_badmethod)
 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03445)
   "HTTP Request Line; Invalid method token: '%.*s'",
@@ -954,7 +960,13 @@ rrl_done:
   "HTTP Request Line; Unrecognized protocol '%.*s' "
   "(perhaps whitespace was injected?)",
   field_name_len(r->protocol), r->protocol);
-r->status = HTTP_BAD_REQUEST;
+else if (deferred_error == rrl_versionnotsupported) {
+ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO()
+  "HTTP Request Line; Protocol '%.*s' >= HTTP/2.0 not"
+  " supported", field_name_len(r->protocol),
+  r->protocol);
+r->status = HTTP_VERSION_NOT_SUPPORTED;
+}
 goto rrl_failed;
 }



Regards

Rüdiger