log: common custom format output

pull/2653/head
fooinha 10 years ago committed by Victor Julien
parent d5a0eb4b2c
commit af174c82bb

@ -261,6 +261,7 @@ log-dnslog.c log-dnslog.h \
log-droplog.c log-droplog.h \
log-file.c log-file.h \
log-filestore.c log-filestore.h \
log-cf-common.c log-cf-common.h \
log-httplog.c log-httplog.h \
log-pcap.c log-pcap.h \
log-stats.c log-stats.h \

@ -0,0 +1,283 @@
/* Copyright (C) 2007-2016 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Paulo Pacheco <fooinha@gmail.com>
* \author Victor Julien <victor@inliniac.net>
* \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
*
* Common custom logging format
*/
#include "log-cf-common.h"
#include "util-print.h"
#include "util-unittest.h"
/**
* \brief Creates a custom format node
* \retval LogCustomFormatNode * ptr if created
* \retval NULL if failed to allocate
*/
LogCustomFormatNode * LogCustomFormatNodeAlloc()
{
LogCustomFormatNode * node = SCMalloc(sizeof(LogCustomFormatNode));
if (unlikely(node == NULL)) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to alloc custom format node");
return NULL;
}
memset(node, '\0', sizeof(LogCustomFormatNode));
memset(node->data, '\0', LOG_NODE_STRLEN);
return node;
}
/**
* \brief Creates a custom format.
* \retval LogCustomFormat * ptr if created
* \retval NULL if failed to allocate
*/
LogCustomFormat * LogCustomFormatAlloc()
{
LogCustomFormat * cf = SCMalloc(sizeof(LogCustomFormat));
if (unlikely(cf == NULL)) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to alloc custom format");
return NULL;
}
memset(cf, '\0', sizeof(LogCustomFormat));
return cf;
}
/**
* \brief Frees memory held by a custom format node
* \param LogCustomFormatNode * node - node to relaease
*/
void LogCustomFormatNodeFree(LogCustomFormatNode *node)
{
if (node==NULL)
return;
SCFree(node);
}
/**
* \brief Frees memory held by a custom format
* \param LogCustomFormat * cf - format to relaease
*/
void LogCustomFormatFree(LogCustomFormat *cf)
{
if (cf==NULL)
return;
for (size_t i = 0; i < cf->cf_n; ++i) {
LogCustomFormatNodeFree(cf->cf_nodes[i]);
}
SCFree(cf);
}
/**
* \brief Parses and saves format nodes for custom format
* \param LogCustomFormat * cf - custom format to build
* \param const char * format - string with format specification
*/
int LogCustomFormatParse(LogCustomFormat *cf, const char *format)
{
const char *p, *np;
uint32_t n;
LogCustomFormatNode *node = NULL;
if (cf==NULL)
return 0;
if (format==NULL)
return 0;
p=format;
for (cf->cf_n = 0; cf->cf_n < LOG_MAXN_NODES-1 && p && *p != '\0';){
node = LogCustomFormatNodeAlloc();
if (node == NULL) {
goto parsererror;
}
node->maxlen = 0;
if (*p != '%'){
/* Literal found in format string */
node->type = LOG_CF_LITERAL;
np = strchr(p, '%');
if (np == NULL){
n = LOG_NODE_STRLEN-2;
np = NULL; /* End */
}else{
n = np-p;
}
strlcpy(node->data,p,n+1);
p = np;
} 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_NODE_MAXOUTPUTLEN) {
node->maxlen = (uint32_t) maxlen;
}
} else {
goto parsererror;
}
p = np + 1;
} else {
goto parsererror;
}
}
if (*p == '{') { /* Simple format char */
np = strchr(p, '}');
if (np != NULL && np-p > 1 && np-p < LOG_NODE_STRLEN-2) {
p++;
n = np-p;
strlcpy(node->data, p, n+1);
p = np;
} else {
goto parsererror;
}
p++;
} else {
node->data[0] = '\0';
}
node->type = *p;
if (*p == '%'){
node->type = LOG_CF_LITERAL;
strlcpy(node->data, "%", 2);
}
p++;
}
LogCustomFormatAddNode(cf, node);
}
return 1;
parsererror:
LogCustomFormatNodeFree(node);
return 0;
}
/**
* \brief Adds a node to custom format
* \param LogCustomFormat * cf - custom format
* \param LogCustomFormatNode * node - node to add
*/
void LogCustomFormatAddNode(LogCustomFormat *cf, LogCustomFormatNode *node)
{
if (cf == NULL || node == NULL)
return;
if (cf->cf_n == LOG_MAXN_NODES) {
SCLogWarning(SC_WARN_LOG_CF_TOO_MANY_NODES, "Too many options for custom format");
return;
}
#ifdef DEBUG
SCLogDebug("%d-> n.type=[%d] n.maxlen=[%d] n.data=[%s]",
cf->cf_n, node->type, node->maxlen, node->data);
#endif
cf->cf_nodes[cf->cf_n] = node;
cf->cf_n++;
}
/**
* \brief Writes a timestamp with given format into a MemBuffer
* \param MemBuffer * buffer - where to write
* \param const char * fmt - format to be used write timestamp
* \param const struct timeveal *ts - the timetstamp
*
*/
void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const struct timeval *ts) {
time_t time = ts->tv_sec;
struct tm local_tm;
struct tm *timestamp = SCLocalTime(time, &local_tm);
char buf[128] = {0};
const char * fmt_to_use = TIMESTAMP_DEFAULT_FORMAT;
if (fmt && *fmt != '\0') {
fmt_to_use = fmt;
}
CreateFormattedTimeString (timestamp, fmt_to_use, buf, sizeof(buf));
PrintRawUriBuf((char *)buffer->buffer, &buffer->offset,
buffer->size, (uint8_t *)buf,strlen(buf));
}
#ifdef UNITTESTS
/**
* \internal
* \brief This test tests default timestamp format
*/
static int LogCustomFormatTest01(void)
{
struct tm tm;
tm.tm_sec = 0;
tm.tm_min = 30;
tm.tm_hour = 4;
tm.tm_mday = 13;
tm.tm_mon = 0;
tm.tm_year = 114;
tm.tm_wday = 1;
tm.tm_yday = 13;
tm.tm_isdst = 0;
time_t secs = mktime(&tm);
struct timeval ts = {secs, 0};
MemBuffer *buffer = MemBufferCreateNew(62);
if (!buffer) {
return 0;
}
LogCustomFormatWriteTimestamp(buffer, "", &ts);
/*
* {buffer = "01/13/14-04:30:00", size = 62, offset = 17}
*/
FAIL_IF_NOT( buffer->offset == 17);
FAIL_IF(strcmp((char *)buffer->buffer, "01/13/14-04:30:00") != 0);
MemBufferFree(buffer);
return 1;
}
void LogCustomFormatRegisterTests(void)
{
UtRegisterTest("LogCustomFormatTest01", LogCustomFormatTest01);
}
#endif /* UNITTESTS */
void LogCustomFormatRegister(void)
{
#ifdef UNITTESTS
LogCustomFormatRegisterTests();
#endif /* UNITTESTS */
}

@ -0,0 +1,81 @@
/* Copyright (C) 2016 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
* \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
* \author Paulo Pacheco <fooinha@gmail.com>
*
* Common custom loggging format
*/
#ifndef __LOG_CF_COMMON_H__
#define __LOG_CF_COMMON_H__
#define LOG_MAXN_NODES 64
#define LOG_NODE_STRLEN 256
#define LOG_NODE_MAXOUTPUTLEN 8192
#define TIMESTAMP_DEFAULT_FORMAT "%D-%H:%M:%S"
#define TIMESTAMP_DEFAULT_FORMAT_LEN 62
/* Common format nodes */
#define LOG_CF_NONE "-"
#define LOG_CF_LITERAL '%'
#define LOG_CF_TIMESTAMP 't'
#define LOG_CF_TIMESTAMP_U 'z'
#define LOG_CF_CLIENT_IP 'a'
#define LOG_CF_SERVER_IP 'A'
#define LOG_CF_CLIENT_PORT 'p'
#define LOG_CF_SERVER_PORT 'P'
/* Line log common separators **/
#define LOG_CF_STAR_SEPARATOR "[**]"
#define LOG_CF_WRITE_STAR_SEPATATOR(buffer) \
MemBufferWriteString(buffer, LOG_CF_STAR_SEPARATOR);
/* Include */
#include "suricata-common.h"
#include "util-buffer.h"
typedef struct LogCustomFormatNode_ {
uint32_t type; /**< Node format type. ie: LOG_CF_LITERAL, ... */
uint32_t maxlen; /**< Maximun length of the data */
char data[LOG_NODE_STRLEN]; /**< optional data. ie: http header name */
} LogCustomFormatNode;
typedef struct LogCustomFormat_ {
uint32_t cf_n; /**< Total number of custom string format nodes */
LogCustomFormatNode *cf_nodes[LOG_MAXN_NODES]; /**< Custom format string nodes */
} LogCustomFormat;
LogCustomFormatNode * LogCustomFormatNodeAlloc(void);
LogCustomFormat * LogCustomFormatAlloc(void);
void LogCustomFormatNodeFree(LogCustomFormatNode *node);
void LogCustomFormatFree(LogCustomFormat *cf);
void LogCustomFormatAddNode(LogCustomFormat *cf, LogCustomFormatNode *node);
int LogCustomFormatParse(LogCustomFormat *cf, const char *format);
void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const struct timeval *ts);
void LogCustomFormatRegister(void);
#endif /* __LOG_CF_COMMON_H__ */

@ -49,6 +49,7 @@
#include "util-logopenfile.h"
#include "util-time.h"
#include "log-cf-common.h"
#define DEFAULT_LOG_FILENAME "http.log"
@ -69,13 +70,6 @@ void LogHttpLogRegister (void)
LogHttpLogThreadDeinit, NULL);
}
#define LOG_HTTP_MAXN_NODES 64
#define LOG_HTTP_NODE_STRLEN 256
#define LOG_HTTP_NODE_MAXOUTPUTLEN 8192
#define TIMESTAMP_DEFAULT_FORMAT "%b %d, %Y; %H:%M:%S"
#define LOG_HTTP_CF_NONE "-"
#define LOG_HTTP_CF_LITERAL '%'
#define LOG_HTTP_CF_REQUEST_HOST 'h'
#define LOG_HTTP_CF_REQUEST_PROTOCOL 'H'
#define LOG_HTTP_CF_REQUEST_METHOD 'm'
@ -87,24 +81,12 @@ void LogHttpLogRegister (void)
#define LOG_HTTP_CF_RESPONSE_STATUS 's'
#define LOG_HTTP_CF_RESPONSE_HEADER 'o'
#define LOG_HTTP_CF_RESPONSE_LEN 'B'
#define LOG_HTTP_CF_TIMESTAMP 't'
#define LOG_HTTP_CF_TIMESTAMP_U 'z'
#define LOG_HTTP_CF_CLIENT_IP 'a'
#define LOG_HTTP_CF_SERVER_IP 'A'
#define LOG_HTTP_CF_CLIENT_PORT 'p'
#define LOG_HTTP_CF_SERVER_PORT 'P'
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;
typedef struct LogHttpFileCtx_ {
LogFileCtx *file_ctx;
uint32_t flags; /** Store mode */
uint32_t cf_n; /** Total number of custom string format nodes */
LogHttpCustomFormatNode *cf_nodes[LOG_HTTP_MAXN_NODES]; /** Custom format string nodes */
LogCustomFormat *cf;
} LogHttpFileCtx;
#define LOG_HTTP_DEFAULT 0
@ -160,49 +142,44 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
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++) {
for (i = 0; i < httplog_ctx->cf->cf_n; i++) {
h_request_hdr = NULL;
h_response_hdr = NULL;
switch (httplog_ctx->cf_nodes[i]->type){
case LOG_HTTP_CF_LITERAL:
LogCustomFormatNode * node = httplog_ctx->cf->cf_nodes[i];
if (! node) /* Should never happen */
continue;
switch (node->type){
case LOG_CF_LITERAL:
/* LITERAL */
MemBufferWriteString(aft->buffer, "%s", httplog_ctx->cf_nodes[i]->data);
MemBufferWriteString(aft->buffer, "%s", node->data);
break;
case LOG_HTTP_CF_TIMESTAMP:
case LOG_CF_TIMESTAMP:
/* TIMESTAMP */
if (httplog_ctx->cf_nodes[i]->data[0] == '\0') {
strftime(buf, 62, TIMESTAMP_DEFAULT_FORMAT, timestamp);
} else {
strftime(buf, 62, httplog_ctx->cf_nodes[i]->data, timestamp);
}
PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
aft->buffer->size, (uint8_t *)buf,strlen(buf));
LogCustomFormatWriteTimestamp(aft->buffer, node->data, ts);
break;
case LOG_HTTP_CF_TIMESTAMP_U:
case LOG_CF_TIMESTAMP_U:
/* TIMESTAMP USECONDS */
snprintf(buf, 62, "%06u", (unsigned int) ts->tv_usec);
snprintf(buf, 6, "%06u", (unsigned int) ts->tv_usec);
PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
aft->buffer->size, (uint8_t *)buf,strlen(buf));
break;
case LOG_HTTP_CF_CLIENT_IP:
case LOG_CF_CLIENT_IP:
/* CLIENT IP ADDRESS */
PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
aft->buffer->size, (uint8_t *)srcip,strlen(srcip));
break;
case LOG_HTTP_CF_SERVER_IP:
case LOG_CF_SERVER_IP:
/* SERVER IP ADDRESS */
PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
aft->buffer->size, (uint8_t *)dstip,strlen(dstip));
break;
case LOG_HTTP_CF_CLIENT_PORT:
case LOG_CF_CLIENT_PORT:
/* CLIENT PORT */
MemBufferWriteString(aft->buffer, "%" PRIu16 "", sp);
break;
case LOG_HTTP_CF_SERVER_PORT:
case LOG_CF_SERVER_PORT:
/* SERVER PORT */
MemBufferWriteString(aft->buffer, "%" PRIu16 "", dp);
break;
@ -213,13 +190,13 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_method),
bstr_len(tx->request_method));
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_URI:
/* URI */
if (tx->request_uri != NULL) {
datalen = httplog_ctx->cf_nodes[i]->maxlen;
datalen = node->maxlen;
if (datalen == 0 || datalen > bstr_len(tx->request_uri)) {
datalen = bstr_len(tx->request_uri);
}
@ -227,14 +204,14 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_uri),
datalen);
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_HOST:
/* HOSTNAME */
if (tx->request_hostname != NULL)
{
datalen = httplog_ctx->cf_nodes[i]->maxlen;
datalen = node->maxlen;
if (datalen == 0 || datalen > bstr_len(tx->request_hostname)) {
datalen = bstr_len(tx->request_hostname);
}
@ -242,7 +219,7 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_hostname),
datalen);
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_PROTOCOL:
@ -252,16 +229,16 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_protocol),
bstr_len(tx->request_protocol));
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_HEADER:
/* REQUEST HEADER */
if (tx->request_headers != NULL) {
h_request_hdr = htp_table_get_c(tx->request_headers, httplog_ctx->cf_nodes[i]->data);
h_request_hdr = htp_table_get_c(tx->request_headers, node->data);
}
if (h_request_hdr != NULL) {
datalen = httplog_ctx->cf_nodes[i]->maxlen;
datalen = node->maxlen;
if (datalen == 0 || datalen > bstr_len(h_request_hdr->value)) {
datalen = bstr_len(h_request_hdr->value);
}
@ -269,7 +246,7 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(h_request_hdr->value),
datalen);
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_COOKIE:
@ -278,19 +255,19 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
h_request_hdr = htp_table_get_c(tx->request_headers, "Cookie");
if (h_request_hdr != NULL) {
cvalue_len = GetCookieValue((uint8_t *) bstr_ptr(h_request_hdr->value),
bstr_len(h_request_hdr->value), (char *) httplog_ctx->cf_nodes[i]->data,
bstr_len(h_request_hdr->value), (char *) node->data,
&cvalue);
}
}
if (cvalue_len > 0 && cvalue != NULL) {
datalen = httplog_ctx->cf_nodes[i]->maxlen;
datalen = node->maxlen;
if (datalen == 0 || datalen > cvalue_len) {
datalen = cvalue_len;
}
PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
aft->buffer->size, cvalue, datalen);
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_REQUEST_LEN:
@ -304,17 +281,17 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(tx->response_status),
bstr_len(tx->response_status));
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_RESPONSE_HEADER:
/* RESPONSE HEADER */
if (tx->response_headers != NULL) {
h_response_hdr = htp_table_get_c(tx->response_headers,
httplog_ctx->cf_nodes[i]->data);
node->data);
}
if (h_response_hdr != NULL) {
datalen = httplog_ctx->cf_nodes[i]->maxlen;
datalen = node->maxlen;
if (datalen == 0 || datalen > bstr_len(h_response_hdr->value)) {
datalen = bstr_len(h_response_hdr->value);
}
@ -322,7 +299,7 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
aft->buffer->size, (uint8_t *)bstr_ptr(h_response_hdr->value),
datalen);
} else {
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
}
break;
case LOG_HTTP_CF_RESPONSE_LEN:
@ -331,8 +308,8 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
break;
default:
/* NO MATCH */
MemBufferWriteString(aft->buffer, LOG_HTTP_CF_NONE);
SCLogDebug("No matching parameter %%%c for custom http log.", httplog_ctx->cf_nodes[i]->type);
MemBufferWriteString(aft->buffer, LOG_CF_NONE);
SCLogDebug("No matching parameter %%%c for custom http log.", node->type);
break;
}
}
@ -341,7 +318,7 @@ static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const struct t
static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
{
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* referer */
htp_header_t *h_referer = NULL;
@ -355,7 +332,8 @@ static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
} else {
MemBufferWriteString(aft->buffer, "<no referer>");
}
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* method */
if (tx->request_method != NULL) {
@ -363,7 +341,7 @@ static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
(uint8_t *)bstr_ptr(tx->request_method),
bstr_len(tx->request_method));
}
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* protocol */
if (tx->request_protocol != NULL) {
@ -373,7 +351,7 @@ static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
} else {
MemBufferWriteString(aft->buffer, "<no protocol>");
}
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* response status */
if (tx->response_status != NULL) {
@ -396,7 +374,8 @@ static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
}
/* length */
MemBufferWriteString(aft->buffer, " [**] %"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
MemBufferWriteString(aft->buffer, "%"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
}
static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, void *data, const Packet *p, Flow *f, HtpState *htp_state, htp_tx_t *tx, uint64_t tx_id, int ipproto)
@ -463,7 +442,7 @@ static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, void *data, const Packet *p,
} else {
MemBufferWriteString(aft->buffer, "<hostname unknown>");
}
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* uri */
if (tx->request_uri != NULL) {
@ -471,7 +450,7 @@ static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, void *data, const Packet *p,
(uint8_t *)bstr_ptr(tx->request_uri),
bstr_len(tx->request_uri));
}
MemBufferWriteString(aft->buffer, " [**] ");
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
/* user agent */
htp_header_t *h_user_agent = NULL;
@ -490,8 +469,9 @@ static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, void *data, const Packet *p,
}
/* ip/tcp header info */
LOG_CF_WRITE_STAR_SEPATATOR(aft->buffer);
MemBufferWriteString(aft->buffer,
" [**] %s:%" PRIu16 " -> %s:%" PRIu16 "\n",
"%s:%" PRIu16 " -> %s:%" PRIu16 "\n",
srcip, sp, dstip, dp);
}
@ -572,8 +552,6 @@ TmEcode LogHttpLogThreadDeinit(ThreadVars *t, void *data)
OutputCtx *LogHttpLogInitCtx(ConfNode *conf)
{
LogFileCtx* file_ctx = LogFileNewCtx();
const char *p, *np;
uint32_t n;
if(file_ctx == NULL) {
SCLogError(SC_ERR_HTTP_LOG_GENERIC, "couldn't create new file_ctx");
return NULL;
@ -592,7 +570,6 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf)
memset(httplog_ctx, 0x00, sizeof(LogHttpFileCtx));
httplog_ctx->file_ctx = file_ctx;
httplog_ctx->cf_n=0;
const char *extended = ConfNodeLookupChildValue(conf, "extended");
const char *custom = ConfNodeLookupChildValue(conf, "custom");
@ -600,74 +577,17 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf)
/* If custom logging format is selected, lets parse it */
if (custom != NULL && customformat != NULL && ConfValIsTrue(custom)) {
p=customformat;
httplog_ctx->cf = LogCustomFormatAlloc();
if (!httplog_ctx->cf) {
goto errorfree;
}
httplog_ctx->flags |= LOG_HTTP_CUSTOM;
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));
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]);
}
LogFileFreeCtx(file_ctx);
SCFree(httplog_ctx);
return NULL;
}
httplog_ctx->cf_nodes[httplog_ctx->cf_n]->maxlen = 0;
if (*p != '%'){
/* Literal found in format string */
httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = LOG_HTTP_CF_LITERAL;
np = strchr(p, '%');
if (np == NULL){
n = LOG_HTTP_NODE_STRLEN-2;
np = NULL; /* End */
}else{
n = np-p;
}
strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data,p,n+1);
p = np;
} 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;
}
} else {
goto parsererror;
}
p = np + 1;
} else {
goto parsererror;
}
}
if (*p == '{') { /* Simple format char */
np = strchr(p, '}');
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);
p = np;
} else {
goto parsererror;
}
p++;
} else {
httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data[0] = '\0';
}
httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = *p;
if (*p == '%'){
httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = LOG_HTTP_CF_LITERAL;
strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data, "%", 2);
}
p++;
}
/* Parsing */
if ( ! LogCustomFormatParse(httplog_ctx->cf, customformat)) {
goto parsererror;
}
} else {
if (extended == NULL) {
@ -695,12 +615,11 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf)
return output_ctx;
parsererror:
for (n = 0;n < httplog_ctx->cf_n;n++) {
SCFree(httplog_ctx->cf_nodes[n]);
}
SCLogError(SC_ERR_INVALID_ARGUMENT,"Syntax error in custom http log format string.");
errorfree:
LogCustomFormatFree(httplog_ctx->cf);
LogFileFreeCtx(file_ctx);
SCFree(httplog_ctx);
SCLogError(SC_ERR_INVALID_ARGUMENT,"Syntax error in custom http log format string.");
return NULL;
}
@ -708,10 +627,7 @@ parsererror:
static void LogHttpLogDeInitCtx(OutputCtx *output_ctx)
{
LogHttpFileCtx *httplog_ctx = (LogHttpFileCtx *)output_ctx->data;
uint32_t i;
for (i = 0; i < httplog_ctx->cf_n; i++) {
SCFree(httplog_ctx->cf_nodes[i]);
}
LogCustomFormatFree(httplog_ctx->cf);
LogFileFreeCtx(httplog_ctx->file_ctx);
SCFree(httplog_ctx);
SCFree(output_ctx);

@ -48,6 +48,7 @@
#include "output-json-alert.h"
#include "output-json-flow.h"
#include "output-json-netflow.h"
#include "log-cf-common.h"
#include "log-droplog.h"
#include "output-json-drop.h"
#include "log-httplog.h"
@ -1025,6 +1026,9 @@ void OutputRegisterRootLoggers(void)
*/
void OutputRegisterLoggers(void)
{
/* custom format log*/
LogCustomFormatRegister();
LuaLogRegister();
/* fast log */
AlertFastLogRegister();

@ -338,6 +338,7 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_REDIS);
CASE_CODE (SC_ERR_VAR_LIMIT);
CASE_CODE (SC_WARN_CHMOD);
CASE_CODE (SC_WARN_LOG_CF_TOO_MANY_NODES);
}
return "UNKNOWN_ERROR";

@ -328,6 +328,7 @@ typedef enum {
SC_ERR_VAR_LIMIT,
SC_WARN_DUPLICATE_OUTPUT,
SC_WARN_CHMOD,
SC_WARN_LOG_CF_TOO_MANY_NODES,
} SCError;
const char *SCErrorToString(SCError);

@ -208,6 +208,15 @@ void CreateUtcIsoTimeString (const struct timeval *ts, char *str, size_t size)
}
}
void CreateFormattedTimeString (const struct tm *t, const char *fmt, char *str, size_t size)
{
if (likely(t != NULL) && likely(fmt != NULL) && likely(str != NULL) ) {
strftime(str, size, fmt, t);
} else {
snprintf(str, size, "ts-error");
}
}
struct tm *SCUtcTime(time_t timep, struct tm *result)
{
return gmtime_r(&timep, result);

@ -51,11 +51,12 @@ void TimeModeSetOffline (void);
int TimeModeIsLive(void);
struct tm *SCLocalTime(time_t timep, struct tm *result);
void CreateTimeString (const struct timeval *ts, char *str, size_t size);
void CreateIsoTimeString (const struct timeval *ts, char *str, size_t size);
void CreateUtcIsoTimeString (const struct timeval *ts, char *str, size_t size);
time_t SCMkTimeUtc (struct tm *tp);
int SCStringPatternToTime (char *string, char **patterns,
void CreateTimeString(const struct timeval *ts, char *str, size_t size);
void CreateIsoTimeString(const struct timeval *ts, char *str, size_t size);
void CreateUtcIsoTimeString(const struct timeval *ts, char *str, size_t size);
void CreateFormattedTimeString(const struct tm *t, const char * fmt, char *str, size_t size);
time_t SCMkTimeUtc(struct tm *tp);
int SCStringPatternToTime(char *string, char **patterns,
int num_patterns, struct tm *time);
#endif /* __UTIL_TIME_H__ */

Loading…
Cancel
Save