diff options
author | (no author) <(no author)@unknown> | 2003-05-28 04:50:15 +0000 |
---|---|---|
committer | (no author) <(no author)@unknown> | 2003-05-28 04:50:15 +0000 |
commit | 13d25cd681ca3c80ab0ea1bbcfb4d8727736b78e (patch) | |
tree | e04b44346cd921b021ba69d3a70d726b529fed92 | |
parent | 3fe01f3dd7085a5867efedf5d178d9d6829e12a1 (diff) | |
download | httpd-2.0.46.tar.gz |
This commit was manufactured by cvs2svn to create tag2.0.46
'APACHE_2_0_46'.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/tags/2.0.46@100062 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 12 | ||||
-rw-r--r-- | docs/manual/content-negotiation.html.en | 14 | ||||
-rw-r--r-- | docs/manual/content-negotiation.xml | 14 | ||||
-rw-r--r-- | docs/manual/env.html.en | 12 | ||||
-rw-r--r-- | docs/manual/env.xml | 12 | ||||
-rw-r--r-- | modules/mappers/mod_negotiation.c | 148 | ||||
-rw-r--r-- | modules/metadata/mod_expires.c | 195 |
7 files changed, 106 insertions, 301 deletions
@@ -1,5 +1,17 @@ Changes with Apache 2.0.46 + *) SECURITY [CAN-2003-0245]: Fixed a bug that could be triggered + remotely through mod_dav and possibly other mechanisms, causing + an Apache child process to crash. The crash was first reported + by David Endler <DEndler@iDefense.com> and was researched and + fixed by Joe Orton <jorton@redhat.com>. Details will be released + on 30 May 2003. + + *) SECURITY [CAN-2003-0189]: Fixed a denial-of-service vulnerability + affecting basic authentication on Unix platforms related to + thread-safety in apr_password_validate(). The problem was reported + by John Hughes <john.hughes@entegrity.com>. + *) Fix for mod_dav. Call the 'can_be_activity' callback, if provided, when a MKACTIVITY request comes in. [Ben Collins-Sussman <sussman@collab.net>] diff --git a/docs/manual/content-negotiation.html.en b/docs/manual/content-negotiation.html.en index 937af9647f..9baa734680 100644 --- a/docs/manual/content-negotiation.html.en +++ b/docs/manual/content-negotiation.html.en @@ -480,20 +480,6 @@ Negotiation</a></li> specification and to work effectively with properly configured clients.</p> - <p>In order to support advanced techniques (such as Cookies or - special URL-paths) to determine the user's preferred language, - since Apache 2.0.46 <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> recognizes - the <a href="env.html">environment variable</a> - <code>prefer-language</code>. If it exists and contains an - appropriate language tag, <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> will - try to select a matching variant. If there's no such variant, - the normal negotiation process applies.</p> - - <div class="example"><h3>Example</h3><p><code> - SetEnvIf Cookie "language=en" prefer-language=en - SetEnvIf Cookie "language=fr" prefer-language=fr - </code></p></div> - </div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div> <div class="section"> <h2><a name="extensions" id="extensions">Extensions to Transparent Content diff --git a/docs/manual/content-negotiation.xml b/docs/manual/content-negotiation.xml index 0618696e02..ee7562b89d 100644 --- a/docs/manual/content-negotiation.xml +++ b/docs/manual/content-negotiation.xml @@ -465,20 +465,6 @@ This is necessary to maintain compliance with the HTTP/1.1 specification and to work effectively with properly configured clients.</p> - - <p>In order to support advanced techniques (such as Cookies or - special URL-paths) to determine the user's preferred language, - since Apache 2.0.46 <module>mod_negotiation</module> recognizes - the <a href="env.html">environment variable</a> - <code>prefer-language</code>. If it exists and contains an - appropriate language tag, <module>mod_negotiation</module> will - try to select a matching variant. If there's no such variant, - the normal negotiation process applies.</p> - - <example><title>Example</title> - SetEnvIf Cookie "language=en" prefer-language=en - SetEnvIf Cookie "language=fr" prefer-language=fr - </example> </section> </section> diff --git a/docs/manual/env.html.en b/docs/manual/env.html.en index 95ae3c8ea3..6c37c2c454 100644 --- a/docs/manual/env.html.en +++ b/docs/manual/env.html.en @@ -268,18 +268,6 @@ <p>This disables <code class="directive"><a href="./mod/core.html#keepalive">KeepAlive</a></code> when set.</p> - - <h3><a name="prefer-language" id="prefer-language">prefer-language</a></h3> - - <p>This influences <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code>'s behaviour. If - it contains a language tag (such as <code>en</code>, <code>ja</code> - or <code>x-klingon</code>), <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> tries - to deliver a variant with that language. If there's no such variant, - the normal <a href="content-negotiation.html">negotiation</a> process - applies.</p> - - - <h3><a name="redirect-carefully" id="redirect-carefully">redirect-carefully</a></h3> diff --git a/docs/manual/env.xml b/docs/manual/env.xml index 58ae9cfd7a..ded93dd7da 100644 --- a/docs/manual/env.xml +++ b/docs/manual/env.xml @@ -294,18 +294,6 @@ <p>This disables <directive module="core">KeepAlive</directive> when set.</p> </section> - - <section id="prefer-language"><title>prefer-language</title> - - <p>This influences <module>mod_negotiation</module>'s behaviour. If - it contains a language tag (such as <code>en</code>, <code>ja</code> - or <code>x-klingon</code>), <module>mod_negotiation</module> tries - to deliver a variant with that language. If there's no such variant, - the normal <a href="content-negotiation.html">negotiation</a> process - applies.</p> - - </section> - <section id="redirect-carefully"> <title>redirect-carefully</title> diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index b486d6ee78..8f2670ca93 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -2202,134 +2202,74 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, return 1; } -/* figure out, whether a variant is in a specific language - * it returns also false, if the variant has no language. - */ -static int variant_has_language(var_rec *variant, const char *lang) -{ - int j, max; - - /* fast exit */ - if ( !lang - || !variant->content_languages - || !(max = variant->content_languages->nelts)) { - return 0; - } - - for (j = 0; j < max; ++j) { - if (!strcmp(lang, - ((char **) (variant->content_languages->elts))[j])) { - return 1; - } - } - - return 0; -} - static int best_match(negotiation_state *neg, var_rec **pbest) { int j; - var_rec *best; + var_rec *best = NULL; float bestq = 0.0f; enum algorithm_results algorithm_result; var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; - const char *preferred_language = apr_table_get(neg->r->subprocess_env, - "prefer-language"); - set_default_lang_quality(neg); /* - * Find the 'best' variant - * We run the loop possibly twice: if "prefer-language" - * environment variable is set but we did not find an appropriate - * best variant. In that case forget the preferred language and - * negotiate over all variants. + * Find the 'best' variant */ - do { - best = NULL; - - for (j = 0; j < neg->avail_vars->nelts; ++j) { - var_rec *variant = &avail_recs[j]; + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; - /* if a language is preferred, but the current variant - * is not in that language, then drop it for now - */ - if ( preferred_language - && !variant_has_language(variant, preferred_language)) { - continue; - } + /* Find all the relevant 'quality' values from the + * Accept... headers, and store in the variant. This also + * prepares for sending an Alternates header etc so we need to + * do it even if we do not actually plan to find a best + * variant. + */ + set_accept_quality(neg, variant); + set_language_quality(neg, variant); + set_encoding_quality(neg, variant); + set_charset_quality(neg, variant); - /* Find all the relevant 'quality' values from the - * Accept... headers, and store in the variant. This also - * prepares for sending an Alternates header etc so we need to - * do it even if we do not actually plan to find a best - * variant. - */ - set_accept_quality(neg, variant); - /* accept the preferred language, even when it's not listed within - * the Accept-Language header - */ - if (preferred_language) { - variant->lang_quality = 1.0f; - variant->definite = 1; - } - else { - set_language_quality(neg, variant); - } - set_encoding_quality(neg, variant); - set_charset_quality(neg, variant); + /* Only do variant selection if we may actually choose a + * variant for the client + */ + if (neg->may_choose) { - /* Only do variant selection if we may actually choose a - * variant for the client + /* Now find out if this variant is better than the current + * best, either using the RVSA/1.0 algorithm, or Apache's + * internal server-driven algorithm. Presumably other + * server-driven algorithms are possible, and could be + * implemented here. */ - if (neg->may_choose) { - /* Now find out if this variant is better than the current - * best, either using the RVSA/1.0 algorithm, or Apache's - * internal server-driven algorithm. Presumably other - * server-driven algorithms are possible, and could be - * implemented here. - */ - - if (neg->use_rvsa) { - if (is_variant_better_rvsa(neg, variant, best, &bestq)) { - best = variant; - } + if (neg->use_rvsa) { + if (is_variant_better_rvsa(neg, variant, best, &bestq)) { + best = variant; } - else { - if (is_variant_better(neg, variant, best, &bestq)) { - best = variant; - } + } + else { + if (is_variant_better(neg, variant, best, &bestq)) { + best = variant; } } } + } - /* We now either have a best variant, or no best variant */ - - if (neg->use_rvsa) { - /* calculate result for RVSA/1.0 algorithm: - * only a choice response if the best variant has q>0 - * and is definite - */ - algorithm_result = (best && best->definite) && (bestq > 0) ? - alg_choice : alg_list; - } - else { - /* calculate result for Apache negotiation algorithm */ - algorithm_result = bestq > 0 ? alg_choice : alg_list; - } - - /* run the loop again, if the "prefer-language" got no clear result */ - if (preferred_language && (!best || algorithm_result != alg_choice)) { - preferred_language = NULL; - continue; - } + /* We now either have a best variant, or no best variant */ - break; - } while (1); + if (neg->use_rvsa) { + /* calculate result for RVSA/1.0 algorithm: + * only a choice response if the best variant has q>0 + * and is definite + */ + algorithm_result = (best && best->definite) && (bestq > 0) ? + alg_choice : alg_list; + } + else { + /* calculate result for Apache negotiation algorithm */ + algorithm_result = bestq > 0 ? alg_choice : alg_list; + } /* Returning a choice response with a non-neighboring variant is a * protocol security error in TCN (see rfc2295). We do *not* diff --git a/modules/metadata/mod_expires.c b/modules/metadata/mod_expires.c index 64fdb0cf14..e35e5544e4 100644 --- a/modules/metadata/mod_expires.c +++ b/modules/metadata/mod_expires.c @@ -212,11 +212,6 @@ typedef struct { apr_table_t *expiresbytype; } expires_dir_config; -typedef struct { - int defaulted; - apr_table_t *expfields; -} expires_interphase_t; - /* from mod_dir, why is this alias used? */ #define DIR_CMD_PERMS OR_INDEXES @@ -421,23 +416,59 @@ static void *merge_expires_dir_configs(apr_pool_t *p, void *basev, void *addv) return new; } -/* - * Handle the setting of the expiration response header fields according - * to our criteria. - */ - -static int set_expiration_fields(request_rec *r, const char *code, - apr_table_t *t) +static int add_expires(request_rec *r) { + expires_dir_config *conf; + char *code; apr_time_t base; apr_time_t additional; apr_time_t expires; int additional_sec; char *timestr; - expires_interphase_t *notes; - notes = (expires_interphase_t *) ap_get_module_config(r->request_config, - &expires_module); + if (ap_is_HTTP_ERROR(r->status)) /* Don't add Expires headers to errors */ + return DECLINED; + + if (r->main != NULL) /* Say no to subrequests */ + return DECLINED; + + conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module); + if (conf == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "internal error: %s", r->filename); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (conf->active != ACTIVE_ON) + return DECLINED; + + /* we perhaps could use the default_type(r) in its place but that + * may be 2nd guesing the desired configuration... calling table_get + * with a NULL key will SEGV us + * + * I still don't know *why* r->content_type would ever be NULL, this + * is possibly a result of fixups being called in many different + * places. Fixups is probably the wrong place to be doing all this + * work... Bah. + * + * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault. + */ + if (r->content_type == NULL) + code = NULL; + else + code = (char *) apr_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? */ + code = conf->expiresdefault; + + if (code[0] == '\0') + return OK; + } + + /* we have our code */ + switch (code[0]) { case 'M': if (r->finfo.filetype == 0) { @@ -468,143 +499,17 @@ static int set_expiration_fields(request_rec *r, const char *code, } expires = base + additional; - apr_table_mergen(t, "Cache-Control", - apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT, - apr_time_sec(expires - r->request_time))); + apr_table_mergen(r->headers_out, "Cache-Control", + apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT, + apr_time_sec(expires - r->request_time))); timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(timestr, expires); - apr_table_setn(t, "Expires", timestr); + apr_table_setn(r->headers_out, "Expires", timestr); return OK; } -/* - * Output filter to set the Expires response header field - * according to the content-type of the response -- if it hasn't - * already been set. - */ -static apr_status_t expires_by_type_filter(ap_filter_t *f, - apr_bucket_brigade *b) -{ - request_rec *r; - expires_dir_config *conf; - expires_interphase_t *notes; - const char *bytype_expiry; - apr_table_t *t; - - r = f->r; - conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, - &expires_module); - notes = (expires_interphase_t *) ap_get_module_config(r->request_config, - &expires_module); - - /* - * If this filter is getting called, it *should* mean that - * the fixup-phase handler ran and set things up for us. - * Check to see which output header table we should use; - * mod_cgi loads script fields into r->err_headers_out, - * for instance. - */ - bytype_expiry = apr_table_get(r->err_headers_out, "Expires"); - if (bytype_expiry != NULL) { - t = r->err_headers_out; - } - else { - bytype_expiry = apr_table_get(r->headers_out, "Expires"); - t = r->headers_out; - } - if (bytype_expiry == NULL) { - /* - * No expiration has been set, so we can apply any managed by - * this module. Check for one for this content type. - */ - bytype_expiry = apr_table_get(conf->expiresbytype, - ap_field_noparam(r->pool, - r->content_type)); - if (bytype_expiry != NULL) { - set_expiration_fields(r, bytype_expiry, t); - } - else if ((notes != NULL) && notes->defaulted) { - /* - * None for this type, but there was a default defined -- - * so use it. - */ - t = apr_table_overlay(r->pool, notes->expfields, t); - } - } - ap_remove_output_filter(f); - return ap_pass_brigade(f->next, b); -} - -static int add_expires(request_rec *r) -{ - expires_dir_config *conf; - expires_interphase_t *notes; - apr_table_t *rfields; - char *code; - - if (ap_is_HTTP_ERROR(r->status)) {/* Don't add Expires headers to errors */ - return DECLINED; - } - - if (r->main != NULL) { /* Say no to subrequests */ - return DECLINED; - } - - conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, - &expires_module); - if (conf == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "internal error: %s", r->filename); - return HTTP_INTERNAL_SERVER_ERROR; - } - - if (conf->active != ACTIVE_ON) { - return DECLINED; - } - - notes = apr_palloc(r->pool, sizeof(expires_interphase_t)); - notes->defaulted = 0; - notes->expfields = apr_table_make(r->pool, 4); - ap_set_module_config(r->request_config, &expires_module, notes); - - /* - * If there are any ExpiresByType directives for this scope, - * add the output filter and defer all setting to it. We - * do make a note of any ExpiresDefault value for its use. - */ - if (! apr_is_empty_table(conf->expiresbytype)) { - ap_add_output_filter("MOD_EXPIRES", NULL, r, r->connection); - rfields = notes->expfields; - } - else { - rfields = r->headers_out; - } - /* - * Apply the default expiration if there is one; the filter will - * narrow it down later if possible. - */ - code = conf->expiresdefault; - - if (code[0] == '\0') { - return OK; - } - else { - /* - * Note that we're setting it from the default, so that - * the output filter (if it runs) knows it can override the - * value. This allows the by-type filter to be able to - * tell the difference between a value set by, say, a - * CGI script and the one we set by default. - */ - notes->defaulted = 1; - } - return set_expiration_fields(r, code, rfields); -} - static void register_hooks(apr_pool_t *p) { - ap_register_output_filter("MOD_EXPIRES", expires_by_type_filter, NULL, - AP_FTYPE_CONTENT_SET); ap_hook_fixups(add_expires,NULL,NULL,APR_HOOK_MIDDLE); } |