summaryrefslogtreecommitdiffstats
path: root/server/util_script.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/util_script.c')
-rw-r--r--server/util_script.c131
1 files changed, 89 insertions, 42 deletions
diff --git a/server/util_script.c b/server/util_script.c
index 599ba58..1fa4276 100644
--- a/server/util_script.c
+++ b/server/util_script.c
@@ -45,7 +45,7 @@
/*
* Various utility functions which are common to a whole lot of
* script-type extensions mechanisms, and might as well be gathered
- * in one place (if only to avoid creating inter-module dependancies
+ * in one place (if only to avoid creating inter-module dependencies
* where there don't have to be).
*/
@@ -92,9 +92,21 @@ static void add_unless_null(apr_table_t *table, const char *name, const char *va
}
}
-static void env2env(apr_table_t *table, const char *name)
+/* Sets variable @name in table @dest from r->subprocess_env if
+ * available, else from the environment, else from @fallback if
+ * non-NULL. */
+static void env2env(apr_table_t *dest, request_rec *r,
+ const char *name, const char *fallback)
{
- add_unless_null(table, name, getenv(name));
+ const char *val;
+
+ val = apr_table_get(r->subprocess_env, name);
+ if (!val)
+ val = apr_pstrdup(r->pool, getenv(name));
+ if (!val)
+ val = apr_pstrdup(r->pool, fallback);
+ if (val)
+ apr_table_addn(dest, name, val);
}
AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
@@ -180,10 +192,10 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r)
* for no particular reason.
*/
- if (!strcasecmp(hdrs[i].key, "Content-type")) {
+ if (!ap_cstr_casecmp(hdrs[i].key, "Content-type")) {
apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
}
- else if (!strcasecmp(hdrs[i].key, "Content-length")) {
+ else if (!ap_cstr_casecmp(hdrs[i].key, "Content-length")) {
apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
}
/* HTTP_PROXY collides with a popular envvar used to configure
@@ -200,8 +212,8 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r)
* in the environment with "ps -e". But, if you must...
*/
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
- else if (!strcasecmp(hdrs[i].key, "Authorization")
- || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
+ else if (!ap_cstr_casecmp(hdrs[i].key, "Authorization")
+ || !ap_cstr_casecmp(hdrs[i].key, "Proxy-Authorization")) {
if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) {
add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
}
@@ -211,37 +223,29 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r)
add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val);
}
- env_temp = apr_table_get(r->subprocess_env, "PATH");
- if (env_temp == NULL) {
- env_temp = getenv("PATH");
- }
- if (env_temp == NULL) {
- env_temp = DEFAULT_PATH;
- }
- apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp));
-
+ env2env(e, r, "PATH", DEFAULT_PATH);
#if defined(WIN32)
- env2env(e, "SystemRoot");
- env2env(e, "COMSPEC");
- env2env(e, "PATHEXT");
- env2env(e, "WINDIR");
+ env2env(e, r, "SystemRoot", NULL);
+ env2env(e, r, "COMSPEC", NULL);
+ env2env(e, r, "PATHEXT", NULL);
+ env2env(e, r, "WINDIR", NULL);
#elif defined(OS2)
- env2env(e, "COMSPEC");
- env2env(e, "ETC");
- env2env(e, "DPATH");
- env2env(e, "PERLLIB_PREFIX");
+ env2env(e, r, "COMSPEC", NULL);
+ env2env(e, r, "ETC", NULL);
+ env2env(e, r, "DPATH", NULL);
+ env2env(e, r, "PERLLIB_PREFIX", NULL);
#elif defined(BEOS)
- env2env(e, "LIBRARY_PATH");
+ env2env(e, r, "LIBRARY_PATH", NULL);
#elif defined(DARWIN)
- env2env(e, "DYLD_LIBRARY_PATH");
+ env2env(e, r, "DYLD_LIBRARY_PATH", NULL);
#elif defined(_AIX)
- env2env(e, "LIBPATH");
+ env2env(e, r, "LIBPATH", NULL);
#elif defined(__HPUX__)
/* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */
- env2env(e, "SHLIB_PATH");
- env2env(e, "LD_LIBRARY_PATH");
+ env2env(e, r, "SHLIB_PATH", NULL);
+ env2env(e, r, "LD_LIBRARY_PATH", NULL);
#else /* Some Unix */
- env2env(e, "LD_LIBRARY_PATH");
+ env2env(e, r, "LD_LIBRARY_PATH", NULL);
#endif
apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
@@ -620,7 +624,7 @@ AP_DECLARE(int) ap_scan_script_header_err_core_ex(request_rec *r, char *buffer,
++l;
}
- if (!strcasecmp(w, "Content-type")) {
+ if (!ap_cstr_casecmp(w, "Content-type")) {
char *tmp;
/* Nuke trailing whitespace */
@@ -638,7 +642,7 @@ AP_DECLARE(int) ap_scan_script_header_err_core_ex(request_rec *r, char *buffer,
* If the script returned a specific status, that's what
* we'll use - otherwise we assume 200 OK.
*/
- else if (!strcasecmp(w, "Status")) {
+ else if (!ap_cstr_casecmp(w, "Status")) {
r->status = cgi_status = atoi(l);
if (!ap_is_HTTP_VALID_RESPONSE(cgi_status))
/* Intentional no APLOGNO */
@@ -652,30 +656,73 @@ AP_DECLARE(int) ap_scan_script_header_err_core_ex(request_rec *r, char *buffer,
apr_filepath_name_get(r->filename), l);
r->status_line = apr_pstrdup(r->pool, l);
}
- else if (!strcasecmp(w, "Location")) {
+ else if (!ap_cstr_casecmp(w, "Location")) {
apr_table_set(r->headers_out, w, l);
}
- else if (!strcasecmp(w, "Content-Length")) {
+ else if (!ap_cstr_casecmp(w, "Content-Length")) {
apr_table_set(r->headers_out, w, l);
}
- else if (!strcasecmp(w, "Content-Range")) {
+ else if (!ap_cstr_casecmp(w, "Content-Range")) {
apr_table_set(r->headers_out, w, l);
}
- else if (!strcasecmp(w, "Transfer-Encoding")) {
+ else if (!ap_cstr_casecmp(w, "Transfer-Encoding")) {
apr_table_set(r->headers_out, w, l);
}
- else if (!strcasecmp(w, "ETag")) {
+ else if (!ap_cstr_casecmp(w, "ETag")) {
apr_table_set(r->headers_out, w, l);
}
/*
* If the script gave us a Last-Modified header, we can't just
- * pass it on blindly because of restrictions on future values.
+ * pass it on blindly because of restrictions on future or invalid values.
*/
- else if (!strcasecmp(w, "Last-Modified")) {
- ap_update_mtime(r, apr_date_parse_http(l));
- ap_set_last_modified(r);
+ else if (!ap_cstr_casecmp(w, "Last-Modified")) {
+ apr_time_t parsed_date = apr_date_parse_http(l);
+ if (parsed_date != APR_DATE_BAD) {
+ ap_update_mtime(r, parsed_date);
+ ap_set_last_modified(r);
+ if (APLOGrtrace1(r)) {
+ apr_time_t last_modified_date = apr_date_parse_http(apr_table_get(r->headers_out,
+ "Last-Modified"));
+ /*
+ * A Last-Modified header value coming from a (F)CGI source
+ * is considered HTTP input so we assume the GMT timezone.
+ * The following logs should inform the admin about violations
+ * and related actions taken by httpd.
+ * The apr_date_parse_rfc function is 'timezone aware'
+ * and it will be used to generate a more informative set of logs
+ * (we don't use it as a replacement of apr_date_parse_http
+ * for the aforementioned reason).
+ */
+ apr_time_t parsed_date_tz_aware = apr_date_parse_rfc(l);
+
+ /*
+ * The parsed Last-Modified header datestring has been replaced by httpd.
+ */
+ if (parsed_date > last_modified_date) {
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_TRACE1, 0, r,
+ "The Last-Modified header value %s (%s) "
+ "has been replaced with '%s'", l,
+ parsed_date != parsed_date_tz_aware ? "not in GMT"
+ : "in the future",
+ apr_table_get(r->headers_out, "Last-Modified"));
+ /*
+ * Last-Modified header datestring not in GMT and not considered in the future
+ * by httpd (like now() + 1 hour in the PST timezone). No action is taken but
+ * the admin is warned about the violation.
+ */
+ } else if (parsed_date != parsed_date_tz_aware) {
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_TRACE1, 0, r,
+ "The Last-Modified header value is not set "
+ "within the GMT timezone (as required)");
+ }
+ }
+ }
+ else {
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_INFO, 0, r, APLOGNO(10247)
+ "Ignored invalid header value: Last-Modified: '%s'", l);
+ }
}
- else if (!strcasecmp(w, "Set-Cookie")) {
+ else if (!ap_cstr_casecmp(w, "Set-Cookie")) {
apr_table_add(cookie_table, w, l);
}
else {