Do we want this for the 2.2 release?

On Thu, Jan 5, 2017 at 7:31 AM,  <yla...@apache.org> wrote:
> Author: ylavic
> Date: Thu Jan  5 12:31:48 2017
> New Revision: 1777460
>
> URL: http://svn.apache.org/viewvc?rev=1777460&view=rev
> Log:
> http: allow folding in check_headers(), still compliant with RFC 7230 (3.2.4).
>
> Modified:
>     httpd/httpd/trunk/modules/http/http_filters.c
>
> Modified: httpd/httpd/trunk/modules/http/http_filters.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/http_filters.c?rev=1777460&r1=1777459&r2=1777460&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/http/http_filters.c (original)
> +++ httpd/httpd/trunk/modules/http/http_filters.c Thu Jan  5 12:31:48 2017
> @@ -631,14 +631,16 @@ apr_status_t ap_http_filter(ap_filter_t
>
>  struct check_header_ctx {
>      request_rec *r;
> -    int strict;
> +    unsigned int strict:1,
> +                 unfold:1;
>  };
>
>  /* check a single header, to be used with apr_table_do() */
> -static int check_header(void *arg, const char *name, const char *val)
> +static int check_header(struct check_header_ctx *ctx,
> +                        const char *name, const char **val)
>  {
> -    struct check_header_ctx *ctx = arg;
> -    const char *test;
> +    const char *pos, *end;
> +    char *dst = NULL;
>
>      if (name[0] == '\0') {
>          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02428)
> @@ -647,12 +649,12 @@ static int check_header(void *arg, const
>      }
>
>      if (ctx->strict) {
> -        test = ap_scan_http_token(name);
> +        end = ap_scan_http_token(name);
>      }
>      else {
> -        test = ap_scan_vchar_obstext(name);
> +        end = ap_scan_vchar_obstext(name);
>      }
> -    if (*test) {
> +    if (*end) {
>          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02429)
>                        "Response header name '%s' contains invalid "
>                        "characters, aborting request",
> @@ -660,13 +662,54 @@ static int check_header(void *arg, const
>          return 0;
>      }
>
> -    test = ap_scan_http_field_content(val);
> -    if (*test) {
> -        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02430)
> -                      "Response header '%s' value of '%s' contains invalid "
> -                      "characters, aborting request",
> -                      name, val);
> -        return 0;
> +    for (pos = *val; *pos; pos = end) {
> +        end = ap_scan_http_field_content(pos);
> +        if (*end) {
> +            if (end[0] != CR || end[1] != LF || (end[2] != ' ' &&
> +                                                 end[2] != '\t')) {
> +                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, 
> APLOGNO(02430)
> +                              "Response header '%s' value of '%s' contains "
> +                              "invalid characters, aborting request",
> +                              name, pos);
> +                return 0;
> +            }
> +            if (!ctx->unfold) {
> +                end += 3;
> +            }
> +            else if (!dst) {
> +                *val = dst = apr_palloc(ctx->r->pool, strlen(*val) + 1);
> +            }
> +        }
> +        if (dst) {
> +            memcpy(dst, pos, end - pos);
> +            dst += end - pos;
> +            if (*end) {
> +                /* skip folding and replace with a single space */
> +                end += 3 + strspn(end + 3, "\t ");
> +                *dst++ = ' ';
> +            }
> +        }
> +    }
> +    if (dst) {
> +        *dst = '\0';
> +    }
> +    return 1;
> +}
> +
> +static int check_headers_table(apr_table_t *t, struct check_header_ctx *ctx)
> +{
> +    const apr_array_header_t *headers = apr_table_elts(t);
> +    apr_table_entry_t *header;
> +    int i;
> +
> +    for (i = 0; i < headers->nelts; ++i) {
> +        header = &APR_ARRAY_IDX(headers, i, apr_table_entry_t);
> +        if (!header->key) {
> +            continue;
> +        }
> +        if (!check_header(ctx, header->key, (const char **)&header->val)) {
> +            return 0;
> +        }
>      }
>      return 1;
>  }
> @@ -683,8 +726,10 @@ static APR_INLINE int check_headers(requ
>
>      ctx.r = r;
>      ctx.strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
> -    return apr_table_do(check_header, &ctx, r->headers_out, NULL) &&
> -           apr_table_do(check_header, &ctx, r->err_headers_out, NULL);
> +    ctx.unfold = (!r->content_type || strncmp(r->content_type,
> +                                              "message/http", 12));
> +    return check_headers_table(r->headers_out, &ctx) &&
> +           check_headers_table(r->err_headers_out, &ctx);
>  }
>
>  static int check_headers_recursion(request_rec *r)
>
>



-- 
Eric Covener
cove...@gmail.com

Reply via email to