You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@locus.apache.org on 2000/03/13 21:27:33 UTC

cvs commit: apache-2.0/src/modules/standard mod_actions.c mod_autoindex.c mod_expires.c mod_include.c mod_log_config.c mod_speling.c

jim         00/03/13 12:27:31

  Modified:    src/include http_core.h
               src/main http_core.c http_log.c http_protocol.c util.c
               src/modules/proxy proxy_util.c
               src/modules/standard mod_actions.c mod_autoindex.c
                        mod_expires.c mod_include.c mod_log_config.c
                        mod_speling.c
  Log:
  Backport the CSS security fixes to Apache 2.0a. Or is that forward
  port? My sense of direction is all confused.
  
  Revision  Changes    Path
  1.7       +9 -0      apache-2.0/src/include/http_core.h
  
  Index: http_core.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/http_core.h,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- http_core.h	2000/03/10 00:05:51	1.6
  +++ http_core.h	2000/03/13 20:27:16	1.7
  @@ -245,6 +245,15 @@
        */
       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 */
  
  
  
  1.36      +34 -0     apache-2.0/src/main/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- http_core.c	2000/03/10 00:06:53	1.35
  +++ http_core.c	2000/03/13 20:27:18	1.36
  @@ -146,6 +146,9 @@
   
       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 @@
   	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 @@
   }
   #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 @@
   { "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 */
     
  
  
  
  1.35      +2 -1      apache-2.0/src/main/http_log.c
  
  Index: http_log.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_log.c,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- http_log.c	2000/03/10 00:06:53	1.34
  +++ http_log.c	2000/03/13 20:27:19	1.35
  @@ -469,7 +469,8 @@
       if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
   	&& (ap_table_get(r->notes, "error-notes") == NULL)) {
   	ap_table_setn(r->notes, "error-notes",
  -		      ap_pvsprintf(r->pool, fmt, args));
  +		      ap_escape_html(r->pool, ap_pvsprintf(r->pool, fmt, 
  +		      args)));
       }
       va_end(args);
   }
  
  
  
  1.56      +43 -8     apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.55
  retrieving revision 1.56
  diff -u -r1.55 -r1.56
  --- http_protocol.c	2000/03/10 00:06:53	1.55
  +++ http_protocol.c	2000/03/13 20:27:20	1.56
  @@ -90,6 +90,43 @@
     } 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 @@
                                     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 @@
               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 @@
               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 @@
           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 @@
           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));
  
  
  
  1.33      +34 -0     apache-2.0/src/main/util.c
  
  Index: util.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/util.c,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- util.c	2000/03/10 00:06:55	1.32
  +++ util.c	2000/03/13 20:27:21	1.33
  @@ -104,6 +104,8 @@
   {
       const char *semi;
   
  +    if (intype == NULL) return NULL;
  +
       semi = strchr(intype, ';');
       if (semi == NULL) {
   	return ap_pstrdup(p, intype);
  @@ -275,6 +277,38 @@
       ap_unblock_alarms();
   }
   
  +/*
  + * Similar to standard strstr() but we ignore case in this version.
  + * Based on the strstr() implementation further below.
  + */
  +API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2)
  +{
  +    char *p1, *p2;
  +    if (*s2 == '\0') {
  +	/* an empty s2 */
  +        return((char *)s1);
  +    }
  +    while(1) {
  +	for ( ; (*s1 != '\0') && (ap_tolower(*s1) != ap_tolower(*s2)); s1++);
  +	if (*s1 == '\0') return(NULL);
  +	/* found first character of s2, see if the rest matches */
  +        p1 = (char *)s1;
  +        p2 = (char *)s2;
  +        while (ap_tolower(*++p1) == ap_tolower(*++p2)) {
  +            if (*p1 == '\0') {
  +                /* both strings ended together */
  +                return((char *)s1);
  +            }
  +        }
  +        if (*p2 == '\0') {
  +            /* second string ended, a match */
  +            break;
  +        }
  +	/* didn't find a match here, try starting at next character in s1 */
  +        s1++;
  +    }
  +    return((char *)s1);
  +}
   /* 
    * Apache stub function for the regex libraries regexec() to make sure the
    * whole regex(3) API is available through the Apache (exported) namespace.
  
  
  
  1.8       +8 -4      apache-2.0/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- proxy_util.c	2000/03/10 00:07:08	1.7
  +++ proxy_util.c	2000/03/13 20:27:25	1.8
  @@ -822,11 +822,15 @@
       ap_table_setn(r->notes, "error-notes",
   		  ap_pstrcat(r->pool, 
   			     "The proxy server could not handle the request "
  -			     "<EM><A HREF=\"", r->uri, "\">",
  -			     r->method, "&nbsp;", r->uri, "</A></EM>.<P>\n"
  -			     "Reason: <STRONG>", message, "</STRONG>", NULL));
  +			     "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
  +			     "\">", ap_escape_html(r->pool, r->method),
  +			     "&nbsp;", 
  +			     ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
  +			     "Reason: <STRONG>",
  +			     ap_escape_html(r->pool, message), 
  +			     "</STRONG>", NULL));
   
  -    /* Allow the "error-notes" string to be printed by ap_send_error_response() */
  +    /* Allow "error-notes" string to be printed by ap_send_error_response() */
       ap_table_setn(r->notes, "verbose-error-to", ap_pstrdup(r->pool, "*"));
   
       r->status_line = ap_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
  
  
  
  1.8       +2 -1      apache-2.0/src/modules/standard/mod_actions.c
  
  Index: mod_actions.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_actions.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- mod_actions.c	2000/03/10 00:07:09	1.7
  +++ mod_actions.c	2000/03/13 20:27:26	1.8
  @@ -159,7 +159,8 @@
   {
       action_dir_config *conf = (action_dir_config *)
           ap_get_module_config(r->per_dir_config, &action_module);
  -    const char *t, *action = r->handler ? r->handler : r->content_type;
  +    const char *t, *action = r->handler ? r->handler : 
  +	ap_field_noparam(r->pool, r->content_type);
       const char *script;
       int i;
   
  
  
  
  1.25      +1 -1      apache-2.0/src/modules/standard/mod_autoindex.c
  
  Index: mod_autoindex.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_autoindex.c,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- mod_autoindex.c	2000/03/10 00:07:11	1.24
  +++ mod_autoindex.c	2000/03/13 20:27:27	1.25
  @@ -690,7 +690,7 @@
   
   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;
   
  
  
  
  1.11      +2 -1      apache-2.0/src/modules/standard/mod_expires.c
  
  Index: mod_expires.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_expires.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- mod_expires.c	2000/03/10 00:07:11	1.10
  +++ mod_expires.c	2000/03/13 20:27:27	1.11
  @@ -441,7 +441,8 @@
       if (r->content_type == NULL)
           code = NULL;
       else
  -        code = (char *) ap_table_get(conf->expiresbytype, r->content_type);
  +        code = (char *) ap_table_get(conf->expiresbytype, 
  +		ap_field_noparam(r->pool, r->content_type));
   
       if (code == NULL) {
           /* no expires defined for that type, is there a default? */
  
  
  
  1.22      +27 -2     apache-2.0/src/modules/standard/mod_include.c
  
  Index: mod_include.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_include.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- mod_include.c	2000/03/10 00:07:11	1.21
  +++ mod_include.c	2000/03/13 20:27:27	1.22
  @@ -943,7 +943,10 @@
   {
       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))) {
               return 1;
  @@ -952,7 +955,15 @@
               const char *val = ap_table_get(r->subprocess_env, tag_val);
   
               if (val) {
  -                ap_rputs(val, r);
  +		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 @@
           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 @@
       }
       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.17      +1 -1      apache-2.0/src/modules/standard/mod_log_config.c
  
  Index: mod_log_config.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_log_config.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- mod_log_config.c	2000/03/10 00:07:12	1.16
  +++ mod_log_config.c	2000/03/13 20:27:28	1.17
  @@ -364,7 +364,7 @@
   {
       const char *cp = ap_table_get(r->headers_out, a);
       if (!strcasecmp(a, "Content-type") && r->content_type) {
  -        cp = r->content_type;
  +        cp = ap_field_noparam(r->pool, r->content_type);
       }
       if (cp) {
           return cp;
  
  
  
  1.10      +5 -5      apache-2.0/src/modules/standard/mod_speling.c
  
  Index: mod_speling.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_speling.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- mod_speling.c	2000/03/10 00:07:12	1.9
  +++ mod_speling.c	2000/03/13 20:27:29	1.10
  @@ -467,7 +467,7 @@
   
   	    *(const char **)ap_push_array(t) =
   			  "The document name you requested (<code>";
  -	    *(const char **)ap_push_array(t) = r->uri;
  +	    *(const char **)ap_push_array(t) = ap_escape_html(sub_pool, r->uri);
   	    *(const char **)ap_push_array(t) =
   			   "</code>) could not be found on this server.\n"
   			   "However, we found documents with names similar "
  @@ -486,15 +486,15 @@
   				      ? r->parsed_uri.query : "",
   				  NULL);
   		*(const char **)ap_push_array(v) = "\"";
  -		*(const char **)ap_push_array(v) = vuri;
  +		*(const char **)ap_push_array(v) = ap_escape_uri(sub_pool, vuri);
   		*(const char **)ap_push_array(v) = "\";\"";
   		*(const char **)ap_push_array(v) = reason;
   		*(const char **)ap_push_array(v) = "\"";
   
   		*(const char **)ap_push_array(t) = "<li><a href=\"";
  -		*(const char **)ap_push_array(t) = vuri;
  +		*(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, vuri);
   		*(const char **)ap_push_array(t) = "\">";
  -		*(const char **)ap_push_array(t) = vuri;
  +		*(const char **)ap_push_array(t) = ap_escape_html(sub_pool, vuri);
   		*(const char **)ap_push_array(t) = "</a> (";
   		*(const char **)ap_push_array(t) = reason;
   		*(const char **)ap_push_array(t) = ")\n";
  @@ -521,7 +521,7 @@
                   *(const char **)ap_push_array(t) =
   			       "Please consider informing the owner of the "
   			       "<a href=\"";
  -                *(const char **)ap_push_array(t) = ref;
  +		*(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, ref);
                   *(const char **)ap_push_array(t) = "\">referring page</a> "
   			       "about the broken link.\n";
   	    }