]> 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 18:16:50 +0000 (18:16 +0000)
committerAndré Malo <nd@apache.org>
Sun, 14 Dec 2003 18:16:50 +0000 (18:16 +0000)
  errorlog.

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

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

src/CHANGES
src/include/ap_mmn.h
src/include/httpd.h
src/main/http_log.c
src/main/util.c

index c10ca8c60b51fb76730f5d24fb23cb42ad35eff1..461337f7241d8b510922575b945419f8f9f94a17 100644 (file)
@@ -1,5 +1,8 @@
 Changes with Apache 1.3.30
 
+  *) SECURITY [CAN-2003-0020]: Escape arbitrary data before writing
+     into the errorlog.  [André Malo]
+
   *) '%X' is now accepted as an alias for '%c' in the
      LogFormat directive. This allows you to configure logging
      to still log the connection status even with mod_ssl
index 19185fbcccb86559599430fa2aac65f1a38f42fc..70cb1c7818342e7923693731bf1c1eb8415cc5ee 100644 (file)
  *                        ap_note_cleanups_for_file_ex(),
  *                        ap_popenf_ex() and ap_psocket_ex().
  * 19990320.15          - ap_is_recursion_limit_exceeded()
+ * 19990320.16          - ap_escape_errorlog_item()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 19990320
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 15                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 16                    /* 0...n */
 
 /* Useful for testing for features. */
 #define AP_MODULE_MAGIC_AT_LEAST(major,minor)          \
index 5d6a985bf5eb0af8fee919c715ffcda0511291a1..1be4eeafa972cc8ad6fae8aab05cdf628d6fe516 100644 (file)
@@ -1028,6 +1028,8 @@ API_EXPORT(char *) ap_escape_html(pool *p, const char *s);
 API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname,
                                    unsigned port, const request_rec *r);
 API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str);
+API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source,
+                                           size_t buflen);
 API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s);
 
 API_EXPORT(int) ap_count_dirs(const char *path);
index 9906c2006a4e09c25dbaedd33f2d35390a0c23d1..6b20424b7fc31152d9d63c7cb473795aeef89e51 100644 (file)
@@ -313,7 +313,7 @@ static void log_error_core(const char *file, int line, int level,
                           const server_rec *s, const request_rec *r,
                           const char *fmt, va_list args)
 {
-    char errstr[MAX_STRING_LEN];
+    char errstr[MAX_STRING_LEN], scratch[MAX_STRING_LEN];
     size_t len;
     int save_errno = errno;
     FILE *logf;
@@ -445,7 +445,10 @@ static void log_error_core(const char *file, int line, int level,
     }
 #endif
 
-    len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args);
+    if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) {
+        len += ap_escape_errorlog_item(errstr + len, scratch,
+                                       sizeof(errstr) - len);
+    }
 
     /* NULL if we are logging to syslog */
     if (logf) {
index 9ef1f348413b66d6eb0de38dd70fa548190555ff..5c0df87b5409128bacb3cf8aa0268d74a0009aa7 100644 (file)
@@ -1520,6 +1520,69 @@ API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str)
     return ret;
 }
 
+API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source,
+                                           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);
+}
 
 API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *str)
 {