Commit 67dd13f3 authored by Jim Jagielski's avatar Jim Jagielski
Browse files

Backport the CSS security fixes to Apache 2.0a. Or is that forward

port? My sense of direction is all confused.

PR:
Obtained from:
Submitted by:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84751 13f79535-47bb-0310-9956-ffa450edef68
parent 30a82f66
Loading
Loading
Loading
Loading
+9 −0
Changes for include/http_core.h: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -245,6 +245,15 @@ typedef struct {
     */
    unsigned d_is_fnmatch : 1;

    /* should we force a charset on any outgoing parameterless content-type?
     * if so, which charset?
     */
#define ADD_DEFAULT_CHARSET_OFF   (0)
#define ADD_DEFAULT_CHARSET_ON    (1)
#define ADD_DEFAULT_CHARSET_UNSET (2)
    unsigned add_default_charset : 2;
    char *add_default_charset_name;

    unsigned long limit_req_body;  /* limit on bytes in request msg body */

    /* logging options */
+26 −1
Changes for modules/filters/mod_include.c: 26 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -943,6 +943,9 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
{
    char tag[MAX_STRING_LEN];
    char *tag_val;
    enum {E_NONE, E_URL, E_ENTITY} encode;

    encode = E_ENTITY;

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
@@ -952,8 +955,16 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
            const char *val = ap_table_get(r->subprocess_env, tag_val);

            if (val) {
		if (encode == E_NONE) {
		    ap_rputs(val, r);
		}
		else if (encode == E_URL) {
		    ap_rputs(ap_escape_uri(r->pool, val), r);
		}
		else if (encode == E_ENTITY) {
		    ap_rputs(ap_escape_html(r->pool, val), r);
		}
            }
            else {
                ap_rputs("(none)", r);
            }
@@ -961,6 +972,19 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
        else if (!strcmp(tag, "done")) {
            return 0;
        }
	else if (!strcmp(tag, "encoding")) {
	    if (!strcasecmp(tag_val, "none")) encode = E_NONE;
	    else if (!strcasecmp(tag_val, "url")) encode = E_URL;
	    else if (!strcasecmp(tag_val, "entity")) encode = E_ENTITY;
	    else {
		ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
			    "unknown value \"%s\" to parameter \"encoding\" of "
			    "tag echo in %s",
			    tag_val, r->filename);
		ap_rputs(error, r);
	    }
	}

        else {
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                        "unknown parameter \"%s\" to tag echo in %s",
@@ -2138,7 +2162,8 @@ static int handle_printenv(ap_file_t *in, request_rec *r, const char *error)
    }
    else if (!strcmp(tag, "done")) {
        for (i = 0; i < arr->nelts; ++i) {
            ap_rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL);
            ap_rvputs(r, ap_escape_html(r->pool, elts[i].key), "=", 
		ap_escape_html(r->pool, elts[i].val), "\n", NULL);
        }
        return 0;
    }
+1 −1
Changes for modules/generators/mod_autoindex.c: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -690,7 +690,7 @@ struct ent {

static char *find_item(request_rec *r, ap_array_header_t *list, int path_only)
{
    const char *content_type = r->content_type;
    const char *content_type = ap_field_noparam(r->pool, r->content_type);
    const char *content_encoding = r->content_encoding;
    char *path = r->filename;

+34 −0
Changes for modules/http/http_core.c: 34 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -146,6 +146,9 @@ static void *create_core_dir_config(ap_context_t *a, char *dir)

    conf->server_signature = srv_sig_unset;

    conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
    conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;

    return (void *)conf;
}

@@ -257,6 +260,14 @@ static void *merge_core_dir_configs(ap_context_t *a, void *basev, void *newv)
	conf->server_signature = new->server_signature;
    }

    if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
	conf->add_default_charset = new->add_default_charset;
    }

    if (new->add_default_charset_name) {
	conf->add_default_charset_name = new->add_default_charset_name;
    }

    return (void*)conf;
}

@@ -1000,6 +1011,27 @@ static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, char *arg)
}
#endif /*GPROF*/

static const char *set_add_default_charset(cmd_parms *cmd, 
	core_dir_config *d, char *arg)
{
    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    if (err != NULL) {
        return err;
    }
    if (!strcasecmp(arg, "Off")) {
       d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
    }
    else if (!strcasecmp(arg, "On")) {
       d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
       d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
    }
    else {
       d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
       d->add_default_charset_name = arg;
    }
    return NULL;
}

static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
{
    void *sconf = cmd->server->module_config;
@@ -2294,6 +2326,8 @@ static const command_rec core_cmds[] = {
{ "GprofDir", set_gprof_dir, NULL, RSRC_CONF, TAKE1,
  "Directory to plop gmon.out files" },
#endif
{ "AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO, 
  TAKE1, "The name of the default charset to add to any Content-Type without one or 'Off' to disable" },

/* Old resource config file commands */
  
+43 −8
Changes for modules/http/http_protocol.c: 43 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -90,6 +90,43 @@ HOOK_STRUCT(
  } while (0)


/*
 * Builds the content-type that should be sent to the client from the
 * content-type specified.  The following rules are followed:
 *    - if type is NULL, type is set to ap_default_type(r)
 *    - if charset adding is disabled, stop processing and return type.
 *    - then, if there are no parameters on type, add the default charset
 *    - return type
 */
static const char *make_content_type(request_rec *r, const char *type) {
    char *needcset[] = {
	"text/plain",
	"text/html",
	NULL };
    char **pcset;
    core_dir_config *conf = (core_dir_config *)ap_get_module_config(
	r->per_dir_config, &core_module);
    if (!type) type = ap_default_type(r);
    if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) return type;

    if (ap_strcasestr(type, "charset=") != NULL) {
	/* already has parameter, do nothing */
	/* XXX we don't check the validity */
	;
    } else {
    	/* see if it makes sense to add the charset. At present,
	 * we only add it if the Content-type is one of needcset[]
	 */
	for (pcset = needcset; *pcset ; pcset++)
	    if (ap_strcasestr(type, *pcset) != NULL) {
		type = ap_pstrcat(r->pool, type, "; charset=", 
		    conf->add_default_charset_name, NULL);
		break;
	    }
    }
    return type;
}

static int parse_byterange(char *range, long clength, long *start, long *end)
{
    char *dash = strchr(range, '-');
@@ -240,7 +277,7 @@ static int internal_byterange(int realreq, long *tlength, request_rec *r,
                                  length);

    if (r->byterange > 1) {
        const char *ct = r->content_type ? r->content_type : ap_default_type(r);
        const char *ct = make_content_type(r, r->content_type);
        char ts[MAX_STRING_LEN];

        ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
@@ -897,7 +934,7 @@ static void get_mime_headers(request_rec *r)
            r->status = HTTP_BAD_REQUEST;
            ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
                "Size of a request header field exceeds server limit.<P>\n"
                "<PRE>\n", field, "</PRE>\n", NULL));
                "<PRE>\n", ap_escape_html(r->pool, field), "</PRE>\n", NULL));
            return;
        }
        copy = ap_palloc(r->pool, len + 1);
@@ -907,7 +944,7 @@ static void get_mime_headers(request_rec *r)
            r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
            ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
                "Request header field is missing colon separator.<P>\n"
                "<PRE>\n", copy, "</PRE>\n", NULL));
                "<PRE>\n", ap_escape_html(r->pool, copy), "</PRE>\n", NULL));
            return;
        }

@@ -1604,10 +1641,8 @@ API_EXPORT(void) ap_send_http_header(request_rec *r)
        ap_table_setn(r->headers_out, "Content-Type",
                  ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
                          "byteranges; boundary=", r->boundary, NULL));
    else if (r->content_type)
        ap_table_setn(r->headers_out, "Content-Type", r->content_type);
    else
        ap_table_setn(r->headers_out, "Content-Type", ap_default_type(r));
    else ap_table_setn(r->headers_out, "Content-Type", make_content_type(r, 
	r->content_type));

    if (r->content_encoding)
        ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
@@ -2493,7 +2528,7 @@ API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error)
        r->content_languages = NULL;
        r->content_encoding = NULL;
        r->clength = 0;
        r->content_type = "text/html";
        r->content_type = "text/html; charset=iso-8859-1";

        if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
            ap_table_setn(r->headers_out, "Allow", make_allow(r));
Loading