You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dirk-Willem van Gulik <di...@webweaving.org> on 2003/12/18 15:13:41 UTC

Escaping of outside chars

We've just been looking at a case of an (admittently) doggy resolver
library which led through non-ASCII chars (as part of some i18n efford)
and hence allowed for alien chars to end up in the log files. Which
royally screwed the operator.

The patch below goes a bit further than the current escaping added
recently - and adds a %t to the ap_snprintf(). Specically around some
resover returns.

Posting here as it may be of use for some people. I am too far removed
from day to day httpd dev to even consider committing this.

Have fun,

Dw


Index: src/ApacheCore.def
===================================================================
RCS file: /home/cvs/apache-1.3/src/ApacheCore.def,v
retrieving revision 1.35
diff -u -r1.35 ApacheCore.def
--- src/ApacheCore.def	18 Jun 2002 04:19:46 -0000	1.35
+++ src/ApacheCore.def	18 Dec 2003 14:05:51 -0000
@@ -447,3 +447,4 @@
         ap_getline @439
         ap_get_chunk_size @440
         ap_escape_logitem @441
+        ap_escape_snbuff @442
Index: src/ap/ap_snprintf.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/ap/ap_snprintf.c,v
retrieving revision 1.54
diff -u -r1.54 ap_snprintf.c
--- src/ap/ap_snprintf.c	3 Feb 2003 17:13:17 -0000	1.54
+++ src/ap/ap_snprintf.c	18 Dec 2003 14:05:51 -0000
@@ -118,6 +118,10 @@
  */
 #define NUM_BUF_SIZE		512

+/* Max size for escaped string (%t) argument.
+ */
+#define STR_BUF_SIZE		(MAX_STRING_LEN)
+
 /*
  * cvt.c - IEEE floating point formatting routines for FreeBSD
  * from GNU libc-4.6.27.  Modified to be thread safe.
@@ -714,6 +718,7 @@
 	    /*
 	     * Default variable settings
 	     */
+	    char strbuff[ STR_BUF_SIZE ];
 	    adjust = RIGHT;
 	    alternate_form = print_sign = print_blank = NO;
 	    pad_char = ' ';
@@ -915,9 +920,14 @@


 	    case 's':
+	    case 't':
 		s = va_arg(ap, char *);
 		if (s != NULL) {
-		    s_len = strlen(s);
+		    if (*fmt == 't') {
+			s_len = ap_escape_snbuff(strbuff,sizeof(strbuff),s);
+			s = strbuff;
+		    } else
+		    	s_len = strlen(s);
 		    if (adjust_precision && precision < s_len)
 			s_len = precision;
 		}
Index: src/include/httpd.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v
retrieving revision 1.374
diff -u -r1.374 httpd.h
@@ -1028,6 +1029,7 @@
 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(int)    ap_escape_snbuff(char *buff, int size, 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);
Index: src/main/http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.327
diff -u -r1.327 http_core.c
@@ -3669,7 +3671,7 @@
     }
     if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
 	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-		     "Invalid URI in request %s", r->the_request);
+		     "Invalid URI in request %t", r->the_request);
 	return BAD_REQUEST;
     }

@@ -4003,7 +4005,7 @@

     if (r->method_number == M_INVALID) {
 	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-		    "Invalid method in request %s",
+		    "Invalid method in request %t",
 		    ap_escape_logitem(r->pool, r->the_request));
 	return NOT_IMPLEMENTED;
     }
@@ -4016,7 +4018,7 @@

     if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
 	ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
-		      "File does not exist: %s",r->path_info ?
+		      "File does not exist: %t",r->path_info ?
 		      ap_pstrcat(r->pool, r->filename, r->path_info, NULL)
 		      : r->filename);
 	return HTTP_NOT_FOUND;
Index: src/main/http_log.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_log.c,v
retrieving revision 1.97
diff -u -r1.97 http_log.c
--- src/main/http_log.c	14 Dec 2003 18:16:50 -0000	1.97
+++ src/main/http_log.c	18 Dec 2003 14:05:54 -0000
@@ -549,13 +549,13 @@

 API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s)
 {
-    ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err);
+    ap_log_error(APLOG_MARK, APLOG_ERR, s, "%t", err);
 }

 API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
 			      const char *msg, server_rec *s)
 {
-    ap_log_error(file, 0, APLOG_ERR, s, "%s", msg);
+    ap_log_error(file, 0, APLOG_ERR, s, "%t", msg);
 }

 API_EXPORT_NONSTD(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
@@ -570,7 +570,7 @@
 API_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r)
 {
     ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
-		"access to %s failed for %s, reason: %s",
+		"access to %t failed for %t, reason: %t",
 		file,
 		ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
 		reason);
Index: src/main/http_main.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v
retrieving revision 1.605
diff -u -r1.605 http_main.c
--- src/main/http_main.c	19 Oct 2003 18:00:35 -0000	1.605
+++ src/main/http_main.c	18 Dec 2003 14:05:58 -0000
@@ -1541,7 +1541,7 @@
 	dirconf = current_conn->server->lookup_defaults;
     if (!current_conn->keptalive) {
 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
-		     current_conn->server, "[client %s] %s timed out",
+		     current_conn->server, "[client %t] %s timed out",
 		     current_conn->remote_ip,
 		     timeout_name ? timeout_name : "request");
     }
Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.330
diff -u -r1.330 http_protocol.c
--- src/main/http_protocol.c	3 Feb 2003 17:13:22 -0000	1.330
+++ src/main/http_protocol.c	18 Dec 2003 14:05:59 -0000
@@ -1252,7 +1252,7 @@
              * comes through...
              */
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-                          "client sent invalid HTTP/0.9 request: HEAD %s",
+                          "client sent invalid HTTP/0.9 request: HEAD %t",
                           r->uri);
             r->header_only = 0;
             r->status = HTTP_BAD_REQUEST;
@@ -1287,7 +1287,7 @@
         r->status = HTTP_BAD_REQUEST;
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                       "client sent HTTP/1.1 request without hostname "
-                      "(see RFC2616 section 14.23): %s", r->uri);
+                      "(see RFC2616 section 14.23): %t", r->uri);
     }
     if (r->status != HTTP_OK) {
         ap_send_error_response(r, 0);
@@ -1316,7 +1316,7 @@
             r->status = HTTP_EXPECTATION_FAILED;
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r,
                           "client sent an unrecognized expectation value of "
-                          "Expect: %s", expect);
+                          "Expect: %t", expect);
             ap_send_error_response(r, 0);
             (void) ap_discard_request_body(r);
             ap_log_transaction(r);
@@ -1411,7 +1411,7 @@

     if (!ap_auth_name(r)) {
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
-		    r, "need AuthName: %s", r->uri);
+		    r, "need AuthName: %t", r->uri);
         return SERVER_ERROR;
     }

@@ -1423,7 +1423,7 @@
     if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
         /* Client tried to authenticate using wrong auth scheme */
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-                    "client used wrong authentication scheme: %s", r->uri);
+                    "client used wrong authentication scheme: %t", r->uri);
         ap_note_basic_auth_failure(r);
         return AUTH_REQUIRED;
     }
@@ -2006,12 +2006,12 @@
     if (tenc) {
         if (strcasecmp(tenc, "chunked")) {
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-                        "Unknown Transfer-Encoding %s", tenc);
+                        "Unknown Transfer-Encoding %t", tenc);
             return HTTP_NOT_IMPLEMENTED;
         }
         if (r->read_body == REQUEST_CHUNKED_ERROR) {
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-                        "chunked Transfer-Encoding forbidden: %s", r->uri);
+                        "chunked Transfer-Encoding forbidden: %t", r->uri);
             return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
         }

@@ -2049,7 +2049,7 @@
     if ((r->read_body == REQUEST_NO_BODY) &&
         (r->read_chunked || (r->remaining > 0))) {
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-                    "%s with body is not allowed for %s", r->method, r->uri);
+                    "%t with body is not allowed for %t", r->method, r->uri);
         return HTTP_REQUEST_ENTITY_TOO_LARGE;
     }

@@ -2057,7 +2057,7 @@
     if (max_body && ((unsigned long)r->remaining > max_body)
                  && (r->remaining >= 0)) {
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-          "Request content-length of %s is larger than the configured "
+          "Request content-length of %t is larger than the configured "
           "limit of %lu", lenp, max_body);
         return HTTP_REQUEST_ENTITY_TOO_LARGE;
     }
Index: src/main/http_request.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_request.c,v
retrieving revision 1.171
diff -u -r1.171 http_request.c
--- src/main/http_request.c	18 Oct 2003 14:15:58 -0000	1.171
+++ src/main/http_request.c	18 Dec 2003 14:06:00 -0000
@@ -296,7 +296,7 @@
             else
 #endif
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
-                            "access to %s failed", r->uri);
+                            "access to %t failed", r->uri);
             return HTTP_FORBIDDEN;
         }
 #else
@@ -1176,7 +1176,7 @@
 {
     if (status == DECLINED) {
         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r,
-                    "configuration error:  couldn't %s: %s", phase, r->uri);
+                    "configuration error:  couldn't %s: %t", phase, r->uri);
         ap_die(SERVER_ERROR, r);
     }
     else
Index: src/main/http_vhost.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_vhost.c,v
retrieving revision 1.35
diff -u -r1.35 http_vhost.c
--- src/main/http_vhost.c	3 Feb 2003 17:13:23 -0000	1.35
+++ src/main/http_vhost.c	18 Dec 2003 14:06:00 -0000
@@ -220,7 +220,7 @@

     if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
 	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
-	    "Cannot resolve host name %s --- ignoring!", w);
+	    "Cannot resolve host name %t --- ignoring!", w);
 	if (t != NULL)
 	    *t = ':';
 	return NULL;
Index: src/main/util.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/util.c,v
retrieving revision 1.208
diff -u -r1.208 util.c
--- src/main/util.c	14 Dec 2003 18:16:50 -0000	1.208
+++ src/main/util.c	18 Dec 2003 14:06:01 -0000
@ -1469,54 +1512,90 @@
     return where;
 }

-/* escape a string for logging */
-API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str)
+/* Take the buffer in 'str' and copy it into buff (up to size
+ * bytes, including the terminating \0) - printing chars from the
+ * T_ESCAPE_LOGITEM in their escaped format. The function returns
+ * a count (excluding the terminating \0); useful in combination with
+ * buff==NULL; which will prevent writing into the buff.
+ */
+API_EXPORT(int ) ap_escape_snbuff(char *buff, int size, const char *str)
 {
-    char *ret;
     unsigned char *d;
     const unsigned char *s;
+    int n = 0;

-    if (str == NULL)
-        return NULL;
+    if (str == NULL || *str == '\0' || size <=0) {
+        if (buff)
+		buff[0] = '\0';
+	return 0;
+    }

-    ret = ap_palloc(p, 4 * strlen(str) + 1);	/* Be safe */
-    d = (unsigned char *)ret;
+    d = (unsigned char *)buff;
     s = (const unsigned char *)str;
     for (; *s; ++s) {
-
 	if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
-	    *d++ = '\\';
+	    if (buff)
+		*d++ = '\\';
+	    if (n >= size - 2)
+		break;
             switch(*s) {
             case '\b':
-                *d++ = 'b';
+            	if (buff) *d++ = 'b';
 	        break;
             case '\n':
-                *d++ = 'n';
+            	if (buff) *d++ = 'n';
 	        break;
             case '\r':
-                *d++ = 'r';
+            	if (buff) *d++ = 'r';
 	        break;
             case '\t':
-                *d++ = 't';
+            	if (buff) *d++ = 't';
 	        break;
             case '\v':
-                *d++ = 'v';
+            	if (buff) *d++ = 'v';
 	        break;
             case '\\':
             case '"':
-                *d++ = *s;
+            	if (buff) *d++ = *s;
 	        break;
 	    default:
-                c2x(*s, d);
-	        *d = 'x';
-		d += 3;
-	    }
+	    	if (n >= size -3)
+			break;
+            	if (buff) {
+			c2x(*s, d);
+			*d = 'x';
+			d += 3;
+		}
+		n+=2;
+	   }
+           n+=2;
+	}
+	else {
+	    if (n >= size -1);
+		break;
+            if (buff)
+		*d++ = *s;
+	    n++;
 	}
-	else
-            *d++ = *s;
     }
-    *d = '\0';
+    if (buff)
+	*d = '\0';
+    n++; /* Also count the terminating \0. */
+    return n;
+}
+
+/* escape a string for logging */
+API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str)
+{
+    char *ret;
+    int n;
+
+    if (str == NULL)
+        return NULL;

+    n = 4 * strlen(str) + 1;    /* Be safe */
+    ret = ap_palloc(p,n);
+    ap_escape_snbuff(ret,n,str);
     return ret;
 }

Index: src/main/util_script.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/util_script.c,v
retrieving revision 1.167
diff -u -r1.167 util_script.c
--- src/main/util_script.c	3 Feb 2003 17:13:23 -0000	1.167
+++ src/main/util_script.c	18 Dec 2003 14:06:02 -0000
@@ -565,7 +565,7 @@

 	    ap_kill_timeout(r);
 	    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
-			  "%s: %s", malformed, r->filename);
+			  "%t: %s", malformed, r->filename);
 	    return HTTP_INTERNAL_SERVER_ERROR;
 	}

Index: src/support/httpd.exp
===================================================================
RCS file: /home/cvs/apache-1.3/src/support/httpd.exp,v
retrieving revision 1.41
diff -u -r1.41 httpd.exp
--- src/support/httpd.exp	17 Jan 2003 12:23:10 -0000	1.41
+++ src/support/httpd.exp	18 Dec 2003 14:06:03 -0000
@@ -107,6 +107,7 @@
 ap_error_log2stderr
 ap_escape_html
 ap_escape_logitem
+ap_escape_snbuff
 ap_escape_path_segment
 ap_escape_quotes
 ap_escape_shell_cmd