[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-httpd-dev
Subject:    [PATCH 62186] POST request getting logged as GET request
From:       Micha Lenk <micha () lenk ! info>
Date:       2018-03-29 19:09:59
Message-ID: 5a3d8774-4362-cd4d-6d6c-0534291f8726 () lenk ! info
[Download RAW message or body]

Hi Apache httpd committers,

I think I've found a bug which triggers under following conditions:

* Apache is configured to serve a local customized error page, e.g.
   using something like "ErrorDocument 404 /var/www/errors/404.html"

* Apache is configured to log the original request's method, e.g.
   using something like (please note, the "%<m" is the part that
   matters):
   CustomLog logs/mylog "%h %l %u %t \"%r\" %>s %b method=\"%<m\""

* HTTP request is a POST request (request body content doesn't matter)

* the request destination path results in a 404 Not Found error

If all these conditions are met, the request will get logged to
logs/mylog with a line ending with 'method="GET"', even though this was
a POST request.

For easier reproduction of this case, I've created a patch that extends
the Apache httpd test suite to cover this case. Please see the attached
file bz62186_httpd-test.patch.

An explanation of this behavior can be found in the code of ap_die_r(),
which explicitly sets r->method to "GET" and r->method_number to M_GET
before it is calling ap_internal_redirect(custom_response, r) to serve
the configured error document.

I've tried to fix this issue by taking a backup of the original
request's method and restoring it as soon as ap_internal_redirect()
returns (see attached patch bz62186_httpd_bugfix.patch). So far the
tests I've done are successful, i.e. the request is now correctly logged
as POST request.

I've filed this issue some days ago as
https://bz.apache.org/bugzilla/show_bug.cgi?id=62186 , but so far it
didn't get any comments yet. Could anybody please take a look?


Kind regards,
Micha


["bz62186_httpd-test.patch" (text/x-patch)]

--- t/apache/errordoc_method_logging.t	(nonexistent)
+++ t/apache/errordoc_method_logging.t	(working copy)
@@ -0,0 +1,34 @@ 
+use strict;
+use warnings FATAL => 'all';
+
+use Data::Dumper;
+use Apache::Test;
+use Apache::TestRequest;
+use Apache::TestUtil qw/t_cmp
+                        t_start_file_watch
+                        t_finish_file_watch/;
+
+Apache::TestRequest::module('error_document');
+
+plan tests => 3, need_lwp;
+
+{
+    t_start_file_watch 'method_log';
+
+    my $response = POST '/method_logging', content => 'does not matter';
+    chomp(my $content = $response->content);
+
+    ok t_cmp($response->code,
+             404,
+             'POST /method_logging, code');
+
+    ok t_cmp($content,
+             'Error 404 Test',
+             'POST /method/logging, content');
+
+    my @loglines = t_finish_file_watch 'method_log';
+    chomp @loglines;
+    ok t_cmp($loglines[0],
+             qr/"POST \/method_logging HTTP\/1.1" .* method="POST"/,
+             'POST /method/logging, log');
+}
--- t/conf/extra.conf.in	(revision 1826815)
+++ t/conf/extra.conf.in	(working copy)
@@ -742,7 +742,11 @@ 
 ## 
 <VirtualHost _default_:error_document>
     ErrorDocument 404 "per-server 404
-                                                                                     \
 +    <IfModule mod_log_config.c>
+        CustomLog logs/method_log "%h %l %u %t \"%r\" %>s %b method=\"%<m\""
+        CustomLog logs/access_log "%h %l %u %t \"%r\" %>s %b"
+    </IfModule>
+
     <Location /redefine>
         ErrorDocument 404 "per-dir 404
     </Location>
@@ -760,6 +764,10 @@ 
         ErrorDocument 404 default
     </Location>
 
+    <Location /method_logging>
+        ErrorDocument 404 /apache/errordoc/404.html
+    </Location>
+
     <Directory @DocumentRoot@/apache>
          ErrorDocument 404 "testing merge
     </Directory>
--- t/htdocs/apache/errordoc/404.html	(nonexistent)
+++ t/htdocs/apache/errordoc/404.html	(working copy)
@@ -0,0 +1, @@ 
+Error 404 Test


["bz62186_httpd_bugfix.patch" (text/x-patch)]

--- modules/http/http_request.c	(revision 1826989)
+++ modules/http/http_request.c	(working copy)
@@ -187,7 +187,8 @@ 
             apr_table_setn(r->headers_out, "Location", custom_response);
         }
         else if (custom_response[0] == '/') {
-            const char *error_notes;
+            const char *error_notes, *original_method;
+            int original_method_number;
             r->no_local_copy = 1;       /* Do NOT send HTTP_NOT_MODIFIED for
                                          * error documents! */
             /*
@@ -205,9 +206,13 @@ 
                                              "error-notes")) != NULL) {
                 apr_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
             }
+            original_method = r->method;
+            original_method_number = r->method_number;
             r->method = "GET";
             r->method_number = M_GET;
             ap_internal_redirect(custom_response, r);
+            r->method = original_method;
+            r->method_number = original_method_number;
             return;
         }
         else {



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic