Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > c3f48b97eea7ea342086686527f89d24 > files > 10

apache-1.3.29-1.4.100mdk.src.rpm

Security Fix (CAN-2003-0020):
Apache does not filter terminal escape sequences from its error logs,
which could make it easier for attackers to insert those sequences
into terminal emulators containing vulnerabilities related to escape
sequences.

Index: src/include/httpd.h
--- src/include/httpd.h.orig	2003-10-24 18:11:40.000000000 +0200
+++ src/include/httpd.h	2004-05-12 10:04:43.000000000 +0200
@@ -1028,6 +1028,8 @@
 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: src/main/http_log.c
--- src/main/http_log.c.orig	2003-02-03 18:13:21.000000000 +0100
+++ src/main/http_log.c	2004-05-12 10:04:43.000000000 +0200
@@ -314,6 +314,9 @@
 			   const char *fmt, va_list args)
 {
     char errstr[MAX_STRING_LEN];
+#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
+    char scratch[MAX_STRING_LEN];
+#endif
     size_t len;
     int save_errno = errno;
     FILE *logf;
@@ -445,7 +448,14 @@
     }
 #endif
 
+#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
+    if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) {
+        len += ap_escape_errorlog_item(errstr + len, scratch,
+                                       sizeof(errstr) - len);
+    }
+#else
     len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args);
+#endif
 
     /* NULL if we are logging to syslog */
     if (logf) {
Index: src/main/util.c
--- src/main/util.c.orig	2003-02-03 18:13:23.000000000 +0100
+++ src/main/util.c	2004-05-12 10:04:43.000000000 +0200
@@ -1520,6 +1520,69 @@
     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)
 {