Changes with Apache 2.0.40
+ *) SECURITY: [CAN-2002-0661] Close a very significant security hole that
+ applies only to the Win32, OS2 and Netware platforms. Unix was not
+ affected, Cygwin may be affected. Certain URIs will bypass security
+ and allow users to invoke or access any file depending on the system
+ configuration. Without upgrading, a single .conf change will close
+ the vulnerability. Add the following directive in the global server
+ httpd.conf context before any other Alias or Redirect directives;
+ RedirectMatch 400 "\\\.\."
+ Reported by Auriemma Luigi <bugtest@sitoverde.com>.
+ [Brad Nicholes]
+
+ *) SECURITY: Close a path-revealing exposure in multiview type
+ map negotiation (such as the default error documents) where the
+ module would report the full path of the typemapped .var file when
+ multiple documents or no documents could be served based on the mime
+ negotiation. Reported by Auriemma Luigi <bugtest@sitoverde.com>.
+ [CAN-2002-0654] [William Rowe]
+
+ *) SECURITY: Close a path-revealing exposure in cgi/cgid when we
+ fail to invoke a script. The modules would report "couldn't create
+ child process /path-to-script/script.pl" revealing the full path
+ of the script. Reported by Jim Race <jrace@qualys.com>.
+ [CAN-2002-0654] [Bill Stoddard]
+
*) Set aside the apr-iconv and apr_xlate() features for the Win32
build of 2.0.40 so development can be completed. A patch, from
<http://www.apache.org/dist/httpd/patches/apply_to_2.0.40/>
break;
}
mime_info.bytes = len;
- mime_info.file_name = rr->filename;
+ mime_info.file_name = apr_filename_of_pathname(rr->filename);
}
}
else {
clean_var_rec(&mime_info);
- if (!(filp = strrchr(r->filename, '/'))) {
- return DECLINED; /* Weird... */
+ if (r->proxyreq || !r->filename
+ || !ap_os_is_path_absolute(neg->pool, r->filename)) {
+ return DECLINED;
}
- /* XXX this should be more general, and quit using 'specials' */
- if (strncmp(r->filename, "proxy:", 6) == 0) {
+ /* Only absolute paths here */
+ if (!(filp = strrchr(r->filename, '/'))) {
return DECLINED;
}
-
++filp;
prefix_len = strlen(filp);
* non-neighboring variant. We can have a non-neighboring
* variant when processing a type map.
*/
- if (ap_strchr_c(variant->file_name, '/'))
+ if (ap_strchr(variant->file_name, '/'))
+ neg->is_transparent = 0;
+
+ /* We can't be transparent, because of the behavior
+ * of variant typemap bodies.
+ */
+ if (variant->body) {
neg->is_transparent = 0;
+ }
}
}
apr_bucket *e;
ap_allow_standard_methods(r, REPLACE_ALLOW, M_GET, M_OPTIONS, M_POST, -1);
- if ((res = ap_discard_request_body(r)) != OK) {
- return res;
- }
/*if (r->method_number == M_OPTIONS) {
* return ap_send_http_options(r);
*}
return res;
}
+ if ((res = ap_discard_request_body(r)) != OK) {
+ return res;
+ }
bb = apr_brigade_create(r->pool, c->bucket_alloc);
e = apr_bucket_file_create(map, best->body,
(apr_size_t)best->bytes, r->pool,
*/
#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
+/* Win32/NetWare/OS2 need to check for both forward and back slashes
+ * in ap_getparents() and ap_escape_url.
+ */
+#ifdef CASE_BLIND_FILESYSTEM
+#define IS_SLASH(s) ((s == '/') || (s == '\\'))
+#else
+#define IS_SLASH(s) (s == '/')
+#endif
+
+
/*
* Examine a field value (such as a media-/content-type) string and return
* it sans any parameters; e.g., strip off any ';charset=foo' and the like.
}
l = w = first_dot = next - name;
while (name[l] != '\0') {
- if (name[l] == '.' && name[l + 1] == '/' && (l == 0 || name[l - 1] == '/'))
+ if (name[l] == '.' && IS_SLASH(name[l + 1]) && (l == 0 || IS_SLASH(name[l - 1])))
l += 2;
else
name[w++] = name[l++];
/* b) remove trailing . path, segment */
if (w == 1 && name[0] == '.')
w--;
- else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
+ else if (w > 1 && name[w - 1] == '.' && IS_SLASH(name[w - 2]))
w--;
name[w] = '\0';
l = first_dot;
while (name[l] != '\0') {
- if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' &&
- (l == 0 || name[l - 1] == '/')) {
+ if (name[l] == '.' && name[l + 1] == '.' && IS_SLASH(name[l + 2]) &&
+ (l == 0 || IS_SLASH(name[l - 1]))) {
register int m = l + 3, n;
l = l - 2;
if (l >= 0) {
- while (l >= 0 && name[l] != '/')
+ while (l >= 0 && !IS_SLASH(name[l]))
l--;
l++;
}
/* d) remove trailing xx/.. segment. */
if (l == 2 && name[0] == '.' && name[1] == '.')
name[0] = '\0';
- else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') {
+ else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && IS_SLASH(name[l - 3])) {
l = l - 4;
if (l >= 0) {
- while (l >= 0 && name[l] != '/')
+ while (l >= 0 && !IS_SLASH(name[l]))
l--;
l++;
}
else {
*x = x2c(y + 1);
y += 2;
- if (*x == '/' || *x == '\0')
+ if (IS_SLASH(*x) || *x == '\0')
badpath = 1;
}
}