Commit f7d51859 authored by Nick Kew's avatar Nick Kew
Browse files

Relax checks on HTTP Response status line from a backend.

PR#44995 - Rainer Jung


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@693108 13f79535-47bb-0310-9956-ffa450edef68
parent 716b1526
Loading
Loading
Loading
Loading
+4 −0
Changes for CHANGES: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2,6 +2,10 @@
Changes with Apache 2.3.0
[ When backported to 2.2.x, remove entry from this file ]

  *) Be tolerant in what you accept - accept slightly broken
     status lines from a backend provide they include a valid status code.
     PR 44995 [Rainer Jung <rainer.jung kippdata.de>

  *) New module mod_sed: filter Request/Response bodies through sed
     [Basant Kumar Kukreja <basant.kukreja sun.com>]

+13 −4
Changes for modules/http/http_filters.c: 13 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -802,13 +802,22 @@ static void validate_status_line(request_rec *r)
{
    char *end;

    if (r->status_line
        && (strlen(r->status_line) <= 4
    if (r->status_line) {
        int len = strlen(r->status_line);
        if (len < 3
            || apr_strtoi64(r->status_line, &end, 10) != r->status
            || *end != ' '
            || (end - 3) != r->status_line)) {
            || (end - 3) != r->status_line
            || (len >= 4 && ! apr_isspace(r->status_line[3]))) {
            r->status_line = NULL;
        }
        /* Since we passed the above check, we know that length three
         * is equivalent to only a 3 digit numeric http status.
         * RFC2616 mandates a trailing space, let's add it.
         */
        else if (len == 3) {
            r->status_line = apr_pstrcat(r->pool, r->status_line, " ");
        }
    }
}

/*
+20 −8
Changes for modules/http/http_protocol.c: 20 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -1232,17 +1232,29 @@ AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
        const char *h1;

        /* Accept a status_line set by a module, but only if it begins
         * with the 3 digit status code
         * with the correct 3 digit status code
         */
        if (r->status_line != NULL
            && strlen(r->status_line) > 4       /* long enough */
            && apr_isdigit(r->status_line[0])
            && apr_isdigit(r->status_line[1])
            && apr_isdigit(r->status_line[2])
            && apr_isspace(r->status_line[3])
            && apr_isalnum(r->status_line[4])) {
        if (r->status_line) {
            char *end;
            int len = strlen(r->status_line);
            if (len >= 3
                && apr_strtoi64(r->status_line, &end, 10) == r->status
                && (end - 3) == r->status_line
                && (len < 4 || apr_isspace(r->status_line[3]))
                && (len < 5 || apr_isalnum(r->status_line[4]))) {
                /* Since we passed the above check, we know that length three
                 * is equivalent to only a 3 digit numeric http status.
                 * RFC2616 mandates a trailing space, let's add it.
                 * If we have an empty reason phrase, we also add "Unknown Reason".
                 */
                if (len == 3) {
                    r->status_line = apr_pstrcat(r->pool, r->status_line, " Unknown Reason");
                } else if (len == 4) {
                    r->status_line = apr_pstrcat(r->pool, r->status_line, "Unknown Reason");
                }
                title = r->status_line;
            }
        }

        /* folks decided they didn't want the error code in the H1 text */
        h1 = &title[4];