Feature #478 » 0003-XFF-support-for-alert-debuglog.patch
src/alert-debuglog.c | ||
---|---|---|
#include "util-debug.h"
|
||
#include "util-buffer.h"
|
||
#include "app-layer-htp.h"
|
||
#include "app-layer.h"
|
||
#include "output.h"
|
||
#include "alert-debuglog.h"
|
||
#include "util-privs.h"
|
||
... | ... | |
OutputRegisterModule(MODULE_NAME, "alert-debug", AlertDebugLogInitCtx);
|
||
}
|
||
typedef struct AlertDebugLogThread_ {
|
||
#define ALERT_DEBUGLOG_XFF 1
|
||
#define ALERT_DEBUGLOG_XFF_OVERWRITE 2
|
||
#define ALERT_DEBUGLOG_XFF_DEFAULT "X-Forwarded-For"
|
||
#define ALERT_DEBUGLOG_XFF_MINLEN 7
|
||
typedef struct LogDebugFileCtx_ {
|
||
LogFileCtx *file_ctx;
|
||
uint32_t flags; /** Store mode */
|
||
char *xff_header; /** XFF Header name in case XFF mode is enabled */
|
||
} LogDebugFileCtx;
|
||
typedef struct AlertDebugLogThread_ {
|
||
LogDebugFileCtx *debuglog_ctx;
|
||
/** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
|
||
MemBuffer *buffer;
|
||
} AlertDebugLogThread;
|
||
... | ... | |
MemBufferWriteString(aft->buffer, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt);
|
||
}
|
||
char srcip[46], dstip[46];
|
||
char srcip[46], dstip[46], xffip[128];
|
||
if (PKT_IS_IPV4(p)) {
|
||
PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
|
||
PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
|
||
} else if (PKT_IS_IPV6(p)) {
|
||
PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
|
||
PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
|
||
}
|
||
|
||
/* XFF Code */
|
||
if (aft->debuglog_ctx->flags & ALERT_DEBUGLOG_XFF) {
|
||
HtpState *htp_state = NULL;
|
||
htp_tx_t *tx = NULL;
|
||
htp_header_t *h_xff = NULL;
|
||
char *p_xff = NULL;
|
||
size_t idx = 0;
|
||
size_t hsize = 0;
|
||
if (p->flow && AppLayerGetProtoFromPacket(p) == ALPROTO_HTTP) {
|
||
htp_state = (HtpState *) AppLayerGetProtoStateFromPacket(p);
|
||
if ( htp_state && htp_state->connp && htp_state->connp->conn) {
|
||
hsize = list_size(htp_state->connp->conn->transactions);
|
||
for (idx = 0; idx < hsize; idx++) {
|
||
tx = list_get(htp_state->connp->conn->transactions, idx);
|
||
if (tx != NULL && tx->request_headers != NULL) {
|
||
h_xff = table_getc(tx->request_headers, aft->debuglog_ctx->xff_header);
|
||
if (h_xff != NULL && bstr_len(h_xff->value) > ALERT_DEBUGLOG_XFF_MINLEN - 1
|
||
&& bstr_len(h_xff->value) < 120) {
|
||
strlcpy(xffip, bstr_ptr(h_xff->value), bstr_len(h_xff->value) + 1);
|
||
/* Check for chained ips separated by ", ", we will get the last one */
|
||
p_xff = strrchr(xffip, ' ');
|
||
if (p_xff == NULL) {
|
||
p_xff = xffip;
|
||
} else {
|
||
p_xff++;
|
||
}
|
||
/* Sanity check on extracted IP */
|
||
if (strlen(p_xff) > ALERT_DEBUGLOG_XFF_MINLEN - 1 &&
|
||
strlen(p_xff) < 43 ) {
|
||
if (aft->debuglog_ctx->flags & ALERT_DEBUGLOG_XFF_OVERWRITE) {
|
||
strcpy(srcip, p_xff);
|
||
} else {
|
||
MemBufferWriteString(aft->buffer, "XFF IP: %s\n",
|
||
p_xff);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
MemBufferWriteString(aft->buffer, "SRC IP: %s\n"
|
||
... | ... | |
}
|
||
}
|
||
SCMutexLock(&aft->file_ctx->fp_mutex);
|
||
MemBufferPrintToFPAsString(aft->buffer, aft->file_ctx->fp);
|
||
fflush(aft->file_ctx->fp);
|
||
aft->file_ctx->alerts += p->alerts.cnt;
|
||
SCMutexUnlock(&aft->file_ctx->fp_mutex);
|
||
SCMutexLock(&aft->debuglog_ctx->file_ctx->fp_mutex);
|
||
MemBufferPrintToFPAsString(aft->buffer, aft->debuglog_ctx->file_ctx->fp);
|
||
fflush(aft->debuglog_ctx->file_ctx->fp);
|
||
aft->debuglog_ctx->file_ctx->alerts += p->alerts.cnt;
|
||
SCMutexUnlock(&aft->debuglog_ctx->file_ctx->fp_mutex);
|
||
return TM_ECODE_OK;
|
||
}
|
||
... | ... | |
PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
|
||
GET_PKT_DATA(p), GET_PKT_LEN(p));
|
||
SCMutexLock(&aft->file_ctx->fp_mutex);
|
||
MemBufferPrintToFPAsString(aft->buffer, aft->file_ctx->fp);
|
||
fflush(aft->file_ctx->fp);
|
||
aft->file_ctx->alerts += p->alerts.cnt;
|
||
SCMutexUnlock(&aft->file_ctx->fp_mutex);
|
||
SCMutexLock(&aft->debuglog_ctx->file_ctx->fp_mutex);
|
||
MemBufferPrintToFPAsString(aft->buffer, aft->debuglog_ctx->file_ctx->fp);
|
||
fflush(aft->debuglog_ctx->file_ctx->fp);
|
||
aft->debuglog_ctx->file_ctx->alerts += p->alerts.cnt;
|
||
SCMutexUnlock(&aft->debuglog_ctx->file_ctx->fp_mutex);
|
||
return TM_ECODE_OK;
|
||
}
|
||
... | ... | |
return TM_ECODE_FAILED;
|
||
}
|
||
/** Use the Ouptut Context (file pointer and mutex) */
|
||
aft->file_ctx = ((OutputCtx *)initdata)->data;
|
||
aft->debuglog_ctx = ((OutputCtx *)initdata)->data;
|
||
/* 1 mb seems sufficient enough */
|
||
aft->buffer = MemBufferCreateNew(1 * 1024 * 1024);
|
||
... | ... | |
return;
|
||
}
|
||
SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts);
|
||
SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->debuglog_ctx->file_ctx->alerts);
|
||
}
|
||
static void AlertDebugLogDeInitCtx(OutputCtx *output_ctx)
|
||
{
|
||
if (output_ctx != NULL) {
|
||
LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
|
||
if (logfile_ctx != NULL) {
|
||
LogFileFreeCtx(logfile_ctx);
|
||
}
|
||
LogDebugFileCtx *debuglog_ctx = (LogDebugFileCtx *)output_ctx->data;
|
||
LogFileFreeCtx(debuglog_ctx->file_ctx);
|
||
SCFree(debuglog_ctx);
|
||
SCFree(output_ctx);
|
||
}
|
||
}
|
||
... | ... | |
OutputCtx *AlertDebugLogInitCtx(ConfNode *conf)
|
||
{
|
||
LogFileCtx *file_ctx = NULL;
|
||
OutputCtx *output_ctx =NULL;
|
||
file_ctx = LogFileNewCtx();
|
||
if (file_ctx == NULL) {
|
||
... | ... | |
goto error;
|
||
}
|
||
OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx));
|
||
output_ctx = SCMalloc(sizeof(OutputCtx));
|
||
if (output_ctx == NULL)
|
||
goto error;
|
||
LogDebugFileCtx *debuglog_ctx = SCMalloc(sizeof(LogDebugFileCtx));
|
||
if (debuglog_ctx == NULL) {
|
||
goto error;
|
||
}
|
||
memset(debuglog_ctx, 0x00, sizeof(LogDebugFileCtx));
|
||
debuglog_ctx->file_ctx = file_ctx;
|
||
|
||
memset(output_ctx, 0x00, sizeof(OutputCtx));
|
||
output_ctx->data = file_ctx;
|
||
output_ctx->data = debuglog_ctx;
|
||
output_ctx->DeInit = AlertDebugLogDeInitCtx;
|
||
const char *xff = ConfNodeLookupChildValue(conf, "xff");
|
||
const char *xff_header = ConfNodeLookupChildValue(conf, "xffheadername");
|
||
const char *xff_overwrite = ConfNodeLookupChildValue(conf, "xffoverwrite");
|
||
|
||
if (xff != NULL && ConfValIsTrue(xff)) {
|
||
debuglog_ctx->flags |= ALERT_DEBUGLOG_XFF;
|
||
if (xff_header != NULL) {
|
||
debuglog_ctx->xff_header = (char *) xff_header;
|
||
} else {
|
||
debuglog_ctx->xff_header = ALERT_DEBUGLOG_XFF_DEFAULT;
|
||
}
|
||
if (xff_overwrite != NULL && ConfValIsTrue(xff_overwrite)) {
|
||
debuglog_ctx->flags |= ALERT_DEBUGLOG_XFF_OVERWRITE;
|
||
}
|
||
}
|
||
SCLogDebug("Alert debug log output initialized");
|
||
return output_ctx;
|
||
... | ... | |
if (file_ctx != NULL) {
|
||
LogFileFreeCtx(file_ctx);
|
||
}
|
||
if (output_ctx != NULL) {
|
||
SCFree(output_ctx);
|
||
}
|
||
return NULL;
|
||
}
|