escape all strings for logging (fixes #2646 log file injection, reported by Jaanus Kääp)
From: Stefan Bühler <stbuehler@web.de> git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2989 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
parent
33cebeb0f7
commit
427120b41a
5
NEWS
5
NEWS
|
@ -19,6 +19,7 @@ NEWS
|
|||
* [mod_auth] use crypt_r instead of crypt if available
|
||||
* fix error message for T_CONFIG_ARRAY config values if an entry value is not a string
|
||||
* fix segfaults in many plugins if they failed configuration
|
||||
* escape all strings for logging (fixes #2646 log file injection, reported by Jaanus Kääp)
|
||||
|
||||
- 1.4.35 - 2014-03-12
|
||||
* [network/ssl] fix build error if TLSEXT is disabled
|
||||
|
@ -557,10 +558,10 @@ NEWS
|
|||
* ignore empty packets from STDERR stream. #998
|
||||
* fix a crash for files with an mtime of 0 reported by cubiq on irc [1519]
|
||||
CVE-2007-1870
|
||||
* allow empty passwords with ldap (Jörg Sonnenberger) [1516]
|
||||
* allow empty passwords with ldap (Jörg Sonnenberger) [1516]
|
||||
* mod_scgi.c segfault fix #964 [1501]
|
||||
* Added round-robin support to mod_fastcgi [1500]
|
||||
* Handle DragonFlyBSD the same way as Freebsd (Jörg Sonnenberger) [1492,1676]
|
||||
* Handle DragonFlyBSD the same way as Freebsd (Jörg Sonnenberger) [1492,1676]
|
||||
* added now and weeks support to mod_expire. #943
|
||||
* fix cpu hog in certain requests [1473] CVE-2007-1869
|
||||
* fix for handling hostnames with trailing dot [1406]
|
||||
|
|
59
src/buffer.c
59
src/buffer.c
|
@ -731,6 +731,65 @@ void buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer
|
|||
}
|
||||
}
|
||||
|
||||
void buffer_append_string_c_escaped(buffer *b, const char *s, size_t s_len) {
|
||||
unsigned char *ds, *d;
|
||||
size_t d_len, ndx;
|
||||
|
||||
force_assert(NULL != b);
|
||||
force_assert(NULL != s || 0 == s_len);
|
||||
|
||||
if (0 == s_len) return;
|
||||
|
||||
/* count to-be-encoded-characters */
|
||||
for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
|
||||
if ((*ds < 0x20) /* control character */
|
||||
|| (*ds >= 0x7f)) { /* DEL + non-ASCII characters */
|
||||
switch (*ds) {
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
d_len += 2;
|
||||
break;
|
||||
default:
|
||||
d_len += 4; /* \xCC */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
d_len++;
|
||||
}
|
||||
}
|
||||
|
||||
d = (unsigned char*) buffer_string_prepare_append(b, d_len);
|
||||
buffer_commit(b, d_len); /* fill below */
|
||||
force_assert('\0' == *d);
|
||||
|
||||
for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
|
||||
if ((*ds < 0x20) /* control character */
|
||||
|| (*ds >= 0x7f)) { /* DEL + non-ASCII characters */
|
||||
d[d_len++] = '\\';
|
||||
switch (*ds) {
|
||||
case '\t':
|
||||
d[d_len++] = 't';
|
||||
break;
|
||||
case '\r':
|
||||
d[d_len++] = 'r';
|
||||
break;
|
||||
case '\n':
|
||||
d[d_len++] = 'n';
|
||||
break;
|
||||
default:
|
||||
d[d_len++] = 'x';
|
||||
d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
|
||||
d[d_len++] = hex_chars[(*ds) & 0x0F];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
d[d_len++] = *ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void buffer_copy_string_encoded_cgi_varnames(buffer *b, const char *s, size_t s_len, int is_http_header) {
|
||||
size_t i, j;
|
||||
|
||||
|
|
|
@ -133,6 +133,9 @@ typedef enum {
|
|||
|
||||
void buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding);
|
||||
|
||||
/* escape non-printable characters; simple escapes for \t, \r, \n; fallback to \xCC */
|
||||
void buffer_append_string_c_escaped(buffer *b, const char *s, size_t s_len);
|
||||
|
||||
/* to upper case, replace non alpha-numerics with '_'; if is_http_header prefix with "HTTP_" unless s is "content-type" */
|
||||
void buffer_copy_string_encoded_cgi_varnames(buffer *b, const char *s, size_t s_len, int is_http_header);
|
||||
|
||||
|
@ -164,7 +167,7 @@ static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty st
|
|||
buffer_copy_string_len(x, y, sizeof(y) - 1)
|
||||
|
||||
#define CONST_STR_LEN(x) x, (x) ? sizeof(x) - 1 : 0
|
||||
#define CONST_BUF_LEN(x) (x)->ptr, buffer_string_length(x)
|
||||
#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
|
||||
|
||||
|
||||
#define UNUSED(x) ( (void)(x) )
|
||||
|
|
|
@ -267,12 +267,12 @@ static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) {
|
|||
switch(*fmt) {
|
||||
case 's': /* string */
|
||||
s = va_arg(ap, char *);
|
||||
buffer_append_string(out, s);
|
||||
buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0);
|
||||
buffer_append_string_len(out, CONST_STR_LEN(" "));
|
||||
break;
|
||||
case 'b': /* buffer */
|
||||
b = va_arg(ap, buffer *);
|
||||
buffer_append_string_buffer(out, b);
|
||||
buffer_append_string_c_escaped(out, CONST_BUF_LEN(b));
|
||||
buffer_append_string_len(out, CONST_STR_LEN(" "));
|
||||
break;
|
||||
case 'd': /* int */
|
||||
|
@ -293,11 +293,11 @@ static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) {
|
|||
break;
|
||||
case 'S': /* string */
|
||||
s = va_arg(ap, char *);
|
||||
buffer_append_string(out, s);
|
||||
buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0);
|
||||
break;
|
||||
case 'B': /* buffer */
|
||||
b = va_arg(ap, buffer *);
|
||||
buffer_append_string_buffer(out, b);
|
||||
buffer_append_string_c_escaped(out, CONST_BUF_LEN(b));
|
||||
break;
|
||||
case 'D': /* int */
|
||||
d = va_arg(ap, int);
|
||||
|
|
Loading…
Reference in New Issue