]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
SECURITY [CAN-2003-0020]: escape arbitrary data before writing into the
authorAndré Malo <nd@apache.org>
Sun, 14 Dec 2003 17:32:04 +0000 (17:32 +0000)
committerAndré Malo <nd@apache.org>
Sun, 14 Dec 2003 17:32:04 +0000 (17:32 +0000)
errorlog.

Reviewed by: Mark J Cox, Erik Abele, Jeff Trawick

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@102059 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
include/ap_mmn.h
include/httpd.h
server/log.c
server/util.c

diff --git a/CHANGES b/CHANGES
index 649c3cb700bb1875ca8d248799ba75ae7f4f1585..d61afdfb9ec47be6ddb4e544183214c1a8b42958 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
 Changes with Apache 2.0.49
 
+  *) SECURITY [CAN-2003-0020]: Escape arbitrary data before writing
+     into the errorlog.  [André Malo]
+
   *) mod_autoindex / core: Don't fail to show filenames containing
      special characters like '%'. PR 13598.  [André Malo]
  
diff --git a/STATUS b/STATUS
index c9c930f35a41a27fe68499da02578af83131f71e..b0f65f5c22b5161f98a38466c995cf68469b6b7e 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 APACHE 2.0 STATUS:                                              -*-text-*-
-Last modified at [$Date: 2003/12/14 16:21:43 $]
+Last modified at [$Date: 2003/12/14 17:32:03 $]
 
 Release:
 
@@ -62,14 +62,6 @@ Contributors looking for a mission:
 
 RELEASE SHOWSTOPPERS:
 
-    * core: Escape arbitrary data before writing into the errorlog
-      [CAN-2003-0020]  (2.0 + 1.3)
-        include/ap_mmn.h: r1.61
-        include/httpd.h: r1.203
-        server/log.c: r1.136
-        server/util.c: r1.143
-      +1: nd, erikabele, trawick
-
 PATCHES TO BACKPORT FROM 2.1
   [ please place file names and revisions from HEAD here, so it is easy to
     identify exactly what the proposed changes are! ]
index 97f8ad12bdf07211bf0d0bf5aae257c37e0ce2ba..d07d428ae94c0b3756b13ad20d504c2ae8fa2228 100644 (file)
  * 20020903.2 (2.0.46-dev) add ap_escape_logitem
  * 20020903.3 (2.0.46-dev) allow_encoded_slashes added to core_dir_config
  * 20020903.4 (2.0.47-dev) add ap_is_recursion_limit_exceeded()
+ * 20020903.5 (2.0.49-dev) add ap_escape_errorlog_item()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20020903
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 4                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 5                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index e5b8b5b2a44087fadbc4d947a239619866d7e520..4d50a5e5d19d50a794292b00c02d6a748cd4122b 100644 (file)
@@ -1371,11 +1371,21 @@ AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s);
 /**
  * Escape a string for logging
  * @param p The pool to allocate from
- * @param s The string to escape
+ * @param str The string to escape
  * @return The escaped string
  */
 AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str);
 
+/**
+ * Escape a string for logging into the error log (without a pool)
+ * @param dest The buffer to write to
+ * @param source The string to escape
+ * @param buflen The buffer size for the escaped string (including \0)
+ * @return The len of the escaped string (always < maxlen)
+ */
+AP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
+                                               apr_size_t buflen);
+
 /**
  * Construct a full hostname
  * @param p The pool to allocate from
index 41dbb5b1aa24b7d1be43220a0c28f8d0598cca46..19842d3fe93c6dbe4f35174cc8e87d8728cc6b7f 100644 (file)
@@ -401,7 +401,7 @@ static void log_error_core(const char *file, int line, int level,
                            const request_rec *r, apr_pool_t *pool,
                            const char *fmt, va_list args)
 {
-    char errstr[MAX_STRING_LEN];
+    char errstr[MAX_STRING_LEN], scratch[MAX_STRING_LEN];
     apr_size_t len, errstrlen;
     apr_file_t *logf = NULL;
     const char *referer;
@@ -536,12 +536,17 @@ static void log_error_core(const char *file, int line, int level,
             errstr[len] = '\0';
         }
     }
+
     errstrlen = len;
-    len += apr_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
+    if (apr_vsnprintf(scratch, MAX_STRING_LEN - len, fmt, args)) {
+        len += ap_escape_errorlog_item(errstr + len, scratch,
+                                       MAX_STRING_LEN - len);
+    }
 
-    if (r && (referer = apr_table_get(r->headers_in, "Referer"))) {
+    if (   r && (referer = apr_table_get(r->headers_in, "Referer"))
+        && ap_escape_errorlog_item(scratch, referer, MAX_STRING_LEN - len)) {
         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
-                            ", referer: %s", referer);
+                            ", referer: %s", scratch);
     }
 
     /* NULL if we are logging to syslog */
index 251eacd6a7774f3bfc2f1edf5ce773af08292654..c1623679f89d3d487f950cec91426d3531110465 100644 (file)
@@ -1837,6 +1837,70 @@ AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str)
     return ret;
 }
 
+AP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
+                                               apr_size_t buflen)
+{
+    unsigned char *d, *ep;
+    const unsigned char *s;
+
+    if (!source || !buflen) { /* be safe */
+        return 0;
+    }
+
+    d = (unsigned char *)dest;
+    s = (const unsigned char *)source;
+    ep = d + buflen - 1;
+
+    for (; d < ep && *s; ++s) {
+
+        if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
+            *d++ = '\\';
+            if (d >= ep) {
+                --d;
+                break;
+            }
+
+            switch(*s) {
+            case '\b':
+                *d++ = 'b';
+                break;
+            case '\n':
+                *d++ = 'n';
+                break;
+            case '\r':
+                *d++ = 'r';
+                break;
+            case '\t':
+                *d++ = 't';
+                break;
+            case '\v':
+                *d++ = 'v';
+                break;
+            case '\\':
+                *d++ = *s;
+                break;
+            case '"': /* no need for this in error log */
+                d[-1] = *s;
+                break;
+            default:
+                if (d >= ep - 2) {
+                    ep = --d; /* break the for loop as well */
+                    break;
+                }
+                c2x(*s, d);
+                *d = 'x';
+                d += 3;
+            }
+        }
+        else {
+            *d++ = *s;
+        }
+    }
+    *d = '\0';
+
+    return (d - (unsigned char *)dest);
+}
+
 AP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
 {
     apr_finfo_t finfo;