Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
lighttpd
lighttpd-1.4.x_log_injection.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File lighttpd-1.4.x_log_injection.patch of Package lighttpd
commit 427120b41a141626dbb40a752c848f199fc9f7a8 Author: Stefan Bühler <stbuehler@web.de> Date: Thu May 28 15:47:14 2015 +0000 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 Index: lighttpd-1.4.35/src/buffer.c =================================================================== --- lighttpd-1.4.35.orig/src/buffer.c 2017-03-06 15:44:36.464809153 +0100 +++ lighttpd-1.4.35/src/buffer.c 2017-03-06 18:00:53.509347023 +0100 @@ -853,6 +853,153 @@ int buffer_append_string_encoded(buffer return 0; } +static size_t buffer_align_size(size_t size) { + size_t align = BUFFER_PIECE_SIZE - (size % BUFFER_PIECE_SIZE); + /* overflow on unsinged size_t is defined to wrap around */ + if (size + align < size) return size; + return size + align; +} + +int buffer_string_is_empty(const buffer *b) { + return 0 == buffer_string_length(b); +} + +/* make sure buffer is at least "size" big. keep old data */ +static void buffer_realloc(buffer *b, size_t size) { + force_assert(NULL != b); + if (0 == size) size = 1; + + if (size <= b->size) return; + + b->size = buffer_align_size(size); + b->ptr = realloc(b->ptr, b->size); + + force_assert(NULL != b->ptr); +} + +static void buffer_alloc(buffer *b, size_t size) { + force_assert(NULL != b); + if (0 == size) size = 1; + + if (size <= b->size) return; + + if (NULL != b->ptr) free(b->ptr); + + b->used = 0; + b->size = buffer_align_size(size); + b->ptr = malloc(b->size); + + force_assert(NULL != b->ptr); +} + +char* buffer_string_prepare_copy(buffer *b, size_t size) { + force_assert(NULL != b); + force_assert(size + 1 > size); + + buffer_alloc(b, size + 1); + + b->used = 1; + b->ptr[0] = '\0'; + + return b->ptr; +} + +char* buffer_string_prepare_append(buffer *b, size_t size) { + force_assert(NULL != b); + + if (buffer_string_is_empty(b)) { + return buffer_string_prepare_copy(b, size); + } else { + size_t req_size = b->used + size; + + /* not empty, b->used already includes a terminating 0 */ + force_assert(req_size >= b->used); + + /* check for overflow: unsigned overflow is defined to wrap around */ + force_assert(req_size >= b->used); + + buffer_realloc(b, req_size); + + return b->ptr + b->used - 1; + } +} + +void buffer_commit(buffer *b, size_t size) +{ + force_assert(NULL != b); + force_assert(b->size > 0); + + if (0 == b->used) b->used = 1; + + if (size > 0) { + /* check for overflow: unsigned overflow is defined to wrap around */ + force_assert(b->used + size > b->used); + + force_assert(b->used + size <= b->size); + b->used += size; + } + + b->ptr[b->used - 1] = '\0'; +} + + +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; + } + } +} /* decodes url-special-chars inplace. * replaces non-printable characters with '_' Index: lighttpd-1.4.35/src/log.c =================================================================== --- lighttpd-1.4.35.orig/src/log.c 2017-03-06 15:44:36.464809153 +0100 +++ lighttpd-1.4.35/src/log.c 2017-03-06 17:49:13.808419104 +0100 @@ -267,12 +267,12 @@ static void log_buffer_append_printf(buf 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(buf 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); Index: lighttpd-1.4.35/src/buffer.h =================================================================== --- lighttpd-1.4.35.orig/src/buffer.h 2017-03-06 15:44:36.464809153 +0100 +++ lighttpd-1.4.35/src/buffer.h 2017-03-06 18:07:49.409855576 +0100 @@ -33,6 +33,38 @@ typedef struct { size_t size; } read_buffer; +/* reset b. if NULL != b && NULL != src, move src content to b. reset src. */ +void buffer_move(buffer *b, buffer *src); + +/* make sure buffer is large enough to store a string of given size + * and a terminating zero. + * sets b to an empty string, and may drop old content. + * @return b->ptr + */ +char* buffer_string_prepare_copy(buffer *b, size_t size); + +/* allocate buffer large enough to be able to append a string of given size + * if b was empty (used == 0) it will contain an empty string (used == 1) + * afterwards + * "used" data is preserved; if not empty buffer must contain a + * zero terminated string. + */ +char* buffer_string_prepare_append(buffer *b, size_t size); + +/* use after prepare_(copy,append) when you have written data to the buffer + * to increase the buffer length by size. also sets the terminating zero. + * requires enough space is present for the terminating zero (prepare with the + * same size to be sure). + */ +void buffer_commit(buffer *b, size_t size); +int buffer_string_is_empty(const buffer *b); + +static inline size_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */ +static inline size_t buffer_string_length(const buffer *b) { + return NULL != b && 0 != b->used ? b->used - 1 : 0; +} + + buffer_array* buffer_array_init(void); void buffer_array_free(buffer_array *b); void buffer_array_reset(buffer_array *b); @@ -95,6 +127,8 @@ typedef enum { } buffer_encoding_t; int 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); int buffer_urldecode_path(buffer *url); int buffer_urldecode_query(buffer *url); @@ -123,7 +157,8 @@ int light_isalnum(int c); if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); } #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0 -#define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0 +// #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0 +#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x) #define UNUSED(x) ( (void)(x) )
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor