From 796bfab2317699779bb0d7dca257bb97083399d8 Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Date: Sun, 7 Oct 2012 16:09:01 +0100 Subject: [PATCH] Added support for %{cookiename}C Added support for the definition of maximun length. ie: %[50]{user-agent}i Some small bugfixes --- src/log-httplog.c | 104 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/src/log-httplog.c b/src/log-httplog.c index 7674089335..b06bf85807 100644 --- a/src/log-httplog.c +++ b/src/log-httplog.c @@ -98,6 +98,7 @@ void TmModuleLogHttpLogIPv6Register (void) { #define LOG_HTTP_MAXN_NODES 64 #define LOG_HTTP_NODE_STRLEN 256 +#define LOG_HTTP_NODE_MAXOUTPUTLEN 8048 #define TIMESTAMP_DEFAULT_FORMAT "%b %d, %Y; %H:%M:%S" #define LOG_HTTP_CF_NONE "-" @@ -121,6 +122,7 @@ void TmModuleLogHttpLogIPv6Register (void) { typedef struct LogHttpCustomFormatNode_ { uint32_t type; /** Node format type. ie: LOG_HTTP_CF_LITERAL, LOG_HTTP_CF_REQUEST_HEADER */ + uint32_t maxlen; /** Maximun length of the data */ char data[LOG_HTTP_NODE_STRLEN]; /** optional data. ie: http header name */ } LogHttpCustomFormatNode; @@ -143,22 +145,54 @@ typedef struct LogHttpLogThread_ { MemBuffer *buffer; } LogHttpLogThread; +/* Retrieves the selected cookie value */ +/* to be used as a workaround until libhtp supported cookie parsing */ +/* Rewrite this!! */ +uint32_t getCookieValue(char *rawcookies, uint32_t rawcookies_len, char *cookiename, + char **cookievalue) { + char *p = rawcookies; + char *cn = p; /* ptr to cookie name start */ + char *cv = NULL; /* ptr to cookie value start */ + while (p < rawcookies + rawcookies_len) { + if (cv == NULL && *p == '=') { + cv = p + 1; + } else if (cv != NULL && (*p == ' ' || p == rawcookies + rawcookies_len - 1) ) { + /* Found end of cookie */ + if (strlen(cookiename) == (unsigned int) (cv-cn-1) && + strncmp(cookiename, cn, cv-cn-1) == 0) { + *cookievalue = cv; + return (uint32_t) (p-cv); + } + cv = NULL; + cn = p + 1; + } + p++; + } + return 0; +} + /* Custom format logging */ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct timeval *ts, char *srcip, Port sp, char *dstip, Port dp) { LogHttpFileCtx *httplog_ctx = aft->httplog_ctx; uint32_t i; + uint32_t datalen; char buf[128]; - htp_header_t *h_request_hdr = NULL; - htp_header_t *h_response_hdr = NULL; + char *cvalue; + uint32_t cvalue_len = 0; + + htp_header_t *h_request_hdr; + htp_header_t *h_response_hdr; time_t time = ts->tv_sec; struct tm local_tm; struct tm *timestamp = SCLocalTime(time, &local_tm); for (i = 0; i < httplog_ctx->cf_n; i++) { + h_request_hdr = NULL; + h_response_hdr = NULL; switch (httplog_ctx->cf_nodes[i]->type){ case LOG_HTTP_CF_LITERAL: /* LITERAL */ @@ -213,9 +247,13 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t case LOG_HTTP_CF_REQUEST_URI: /* URI */ if (tx->request_uri != NULL) { + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > bstr_len(tx->request_uri)) { + datalen = bstr_len(tx->request_uri); + } PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_uri), - bstr_len(tx->request_uri)); + datalen); } else { MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE); } @@ -224,6 +262,10 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t /* HOSTNAME */ if (tx->request_hostname != NULL) { + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > bstr_len(tx->parsed_uri->hostname)) { + datalen = bstr_len(tx->parsed_uri->hostname); + } PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_hostname), bstr_len(tx->request_hostname)); @@ -247,9 +289,34 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t h_request_hdr = htp_table_get_c(tx->request_headers, httplog_ctx->cf_nodes[i]->data); } if (h_request_hdr != NULL) { + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > bstr_len(h_request_hdr->value)) { + datalen = bstr_len(h_request_hdr->value); + } PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)bstr_ptr(h_request_hdr->value), - bstr_len(h_request_hdr->value)); + datalen); + } else { + MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE); + } + break; + case LOG_HTTP_CF_REQUEST_COOKIE: + /* REQUEST COOKIE */ + if (tx->request_headers != NULL) { + h_request_hdr = table_getc(tx->request_headers, "Cookie"); + if (h_request_hdr != NULL) { + cvalue_len = getCookieValue((char *)bstr_ptr(h_request_hdr->value), + bstr_len(h_request_hdr->value), httplog_ctx->cf_nodes[i]->data, + (char **) &cvalue); + } + } + if (cvalue_len > 0) { + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > cvalue_len) { + datalen = cvalue_len; + } + PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, + aft->buffer->size, (uint8_t *)cvalue, datalen); } else { MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE); } @@ -268,10 +335,13 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t htp_header_t *h_location = htp_table_get_c(tx->response_headers, "location"); if (h_location != NULL) { MemBufferWriteString(aft->buffer, "("); - + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > bstr_len(h_location->value)) { + datalen = bstr_len(h_location->value); + } PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)bstr_ptr(h_location->value), - bstr_len(h_location->value)); + datalen); MemBufferWriteString(aft->buffer, ")"); } } @@ -286,9 +356,13 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t httplog_ctx->cf_nodes[i]->data); } if (h_response_hdr != NULL) { + datalen = httplog_ctx->cf_nodes[i]->maxlen; + if (datalen == 0 || datalen > bstr_len(h_response_hdr->value)) { + datalen = bstr_len(h_response_hdr->value); + } PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, (uint8_t *)bstr_ptr(h_response_hdr->value), - bstr_len(h_response_hdr->value)); + datalen); } else { MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE); } @@ -644,6 +718,7 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf) for (httplog_ctx->cf_n = 0; httplog_ctx->cf_n < LOG_HTTP_MAXN_NODES-1 && p && *p != '\0'; httplog_ctx->cf_n++){ httplog_ctx->cf_nodes[httplog_ctx->cf_n] = SCMalloc(sizeof(LogHttpCustomFormatNode)); + httplog_ctx->cf_nodes[httplog_ctx->cf_n]->maxlen=0; if (httplog_ctx->cf_nodes[httplog_ctx->cf_n] == NULL) { for (n = 0; n < httplog_ctx->cf_n; n++) { SCFree(httplog_ctx->cf_nodes[n]); @@ -667,9 +742,22 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf) } else { /* Non Literal found in format string */ p++; + if (*p == '[') { /* Check if maxlength has been specified (ie: [25]) */ + p++; + np = strchr(p, ']'); + if (np != NULL) { + if (np-p > 0 && np-p < 10){ + long maxlen = strtol(p,NULL,10); + if (maxlen > 0 && maxlen < LOG_HTTP_NODE_MAXOUTPUTLEN) { + httplog_ctx->cf_nodes[httplog_ctx->cf_n]->maxlen = (uint32_t) maxlen; + } + } + p = np + 1; + } + } if (*p == '{') { /* Simple format char */ np = strchr(p, '}'); - if (np != NULL && np-p > 1 && np-p < LOG_HTTP_NODE_STRLEN-2) { + if (np != NULL && np-p > 1 && np-p < LOG_HTTP_NODE_STRLEN-2) { p++; n = np-p; strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data, p, n+1);