53#define DEFAULT_LOG_FILENAME "http.log"
55#define MODULE_NAME "LogHttpLog"
57#define OUTPUT_BUFFER_SIZE 65535
61static void LogHttpLogDeInitCtx(
OutputCtx *);
71#define LOG_HTTP_CF_REQUEST_HOST 'h'
72#define LOG_HTTP_CF_REQUEST_PROTOCOL 'H'
73#define LOG_HTTP_CF_REQUEST_METHOD 'm'
74#define LOG_HTTP_CF_REQUEST_URI 'u'
75#define LOG_HTTP_CF_REQUEST_HEADER 'i'
76#define LOG_HTTP_CF_REQUEST_COOKIE 'C'
77#define LOG_HTTP_CF_REQUEST_LEN 'b'
78#define LOG_HTTP_CF_RESPONSE_STATUS 's'
79#define LOG_HTTP_CF_RESPONSE_HEADER 'o'
80#define LOG_HTTP_CF_RESPONSE_LEN 'B'
89#define LOG_HTTP_DEFAULT 0
90#define LOG_HTTP_EXTENDED 1
91#define LOG_HTTP_CUSTOM 2
102static uint32_t GetCookieValue(
const uint8_t *rawcookies, uint32_t rawcookies_len,
char *cookiename,
103 const uint8_t **cookievalue)
105 const uint8_t *p = rawcookies;
106 const uint8_t *cn = p;
107 const uint8_t *cv = NULL;
108 while (p < rawcookies + rawcookies_len) {
109 if (cv == NULL && *p ==
'=') {
111 }
else if (cv != NULL && (*p ==
';' || p == rawcookies + rawcookies_len - 1) ) {
114 if (strlen(cookiename) == (
unsigned int) (cv-cn-1) &&
115 strncmp(cookiename, (
char *) cn, cv-cn-1) == 0) {
117 return (uint32_t) (p-cv);
136 const uint8_t *cvalue = NULL;
137 uint32_t cvalue_len = 0;
139 const htp_header_t *h_request_hdr;
140 const htp_header_t *h_response_hdr;
142 for (i = 0; i < httplog_ctx->
cf->
cf_n; i++) {
143 h_request_hdr = NULL;
144 h_response_hdr = NULL;
161 snprintf(buf,
sizeof(buf),
"%06u", (
unsigned int)
SCTIME_USECS(
ts));
163 (uint8_t *)buf,
MIN(strlen(buf), 6));
168 aft->
buffer->
size, (uint8_t *)srcip,strlen(srcip));
173 aft->
buffer->
size, (uint8_t *)dstip,strlen(dstip));
185 if (htp_tx_request_method(tx) != NULL) {
187 (uint8_t *)bstr_ptr(htp_tx_request_method(tx)),
188 bstr_len(htp_tx_request_method(tx)));
195 if (htp_tx_request_uri(tx) != NULL) {
197 if (datalen == 0 || datalen > bstr_len(htp_tx_request_uri(tx))) {
198 datalen = bstr_len(htp_tx_request_uri(tx));
201 (uint8_t *)bstr_ptr(htp_tx_request_uri(tx)), datalen);
208 if (htp_tx_request_hostname(tx) != NULL) {
210 if (datalen == 0 || datalen > bstr_len(htp_tx_request_hostname(tx))) {
211 datalen = bstr_len(htp_tx_request_hostname(tx));
214 (uint8_t *)bstr_ptr(htp_tx_request_hostname(tx)), datalen);
221 if (htp_tx_request_protocol(tx) != NULL) {
223 (uint8_t *)bstr_ptr(htp_tx_request_protocol(tx)),
224 bstr_len(htp_tx_request_protocol(tx)));
231 h_request_hdr = htp_tx_request_header(tx, node->
data);
232 if (h_request_hdr != NULL) {
234 if (datalen == 0 || datalen > htp_header_value_len(h_request_hdr)) {
235 datalen = htp_header_value_len(h_request_hdr);
238 htp_header_value_ptr(h_request_hdr), datalen);
245 if (htp_tx_request_headers(tx) != NULL) {
246 h_request_hdr = htp_tx_request_header(tx,
"Cookie");
247 if (h_request_hdr != NULL) {
248 cvalue_len = GetCookieValue(htp_header_value_ptr(h_request_hdr),
249 (uint32_t)htp_header_value_len(h_request_hdr), (
char *)node->
data,
253 if (cvalue_len > 0 && cvalue != NULL) {
255 if (datalen == 0 || datalen > cvalue_len) {
256 datalen = cvalue_len;
267 aft->
buffer,
"%" PRIuMAX
"", (uintmax_t)htp_tx_request_message_len(tx));
271 if (htp_tx_response_status(tx) != NULL) {
273 (uint8_t *)bstr_ptr(htp_tx_response_status(tx)),
274 bstr_len(htp_tx_response_status(tx)));
281 if (htp_tx_response_headers(tx) != NULL) {
282 h_response_hdr = htp_tx_response_header(tx, node->
data);
284 if (h_response_hdr != NULL) {
286 if (datalen == 0 || datalen > htp_header_value_len(h_response_hdr)) {
287 datalen = htp_header_value_len(h_response_hdr);
290 aft->
buffer->
size, htp_header_value_ptr(h_response_hdr), datalen);
298 aft->
buffer,
"%" PRIuMAX
"", (uintmax_t)htp_tx_response_message_len(tx));
303 SCLogDebug(
"No matching parameter %%%c for custom http log.", node->
type);
315 const htp_header_t *h_referer = htp_tx_request_header(tx,
"referer");
317 if (h_referer != NULL) {
319 htp_header_value_ptr(h_referer), htp_header_value_len(h_referer));
327 if (htp_tx_request_method(tx) != NULL) {
329 (uint8_t *)bstr_ptr(htp_tx_request_method(tx)),
330 bstr_len(htp_tx_request_method(tx)));
335 if (htp_tx_request_protocol(tx) != NULL) {
337 (uint8_t *)bstr_ptr(htp_tx_request_protocol(tx)),
338 bstr_len(htp_tx_request_protocol(tx)));
345 if (htp_tx_response_status(tx) != NULL) {
347 (uint8_t *)bstr_ptr(htp_tx_response_status(tx)),
348 bstr_len(htp_tx_response_status(tx)));
350 if ((htp_tx_response_status_number(tx) > 300) &&
351 ((htp_tx_response_status_number(tx)) < 303)) {
352 const htp_header_t *h_location = htp_tx_response_header(tx,
"location");
353 if (h_location != NULL) {
357 htp_header_value_ptr(h_location), htp_header_value_len(h_location));
367 aft->
buffer,
"%" PRIuMAX
" bytes", (uintmax_t)htp_tx_response_message_len(tx));
381 char srcip[46], dstip[46];
415 SCLogDebug(
"got a HTTP request and now logging !!");
418 MemBufferReset(aft->
buffer);
421 LogHttpLogCustom(aft, tx, p->
ts, srcip, sp, dstip, dp);
427 if (htp_tx_request_hostname(tx) != NULL) {
429 (uint8_t *)bstr_ptr(htp_tx_request_hostname(tx)),
430 bstr_len(htp_tx_request_hostname(tx)));
437 if (htp_tx_request_uri(tx) != NULL) {
439 (uint8_t *)bstr_ptr(htp_tx_request_uri(tx)), bstr_len(htp_tx_request_uri(tx)));
444 const htp_header_t *h_user_agent = htp_tx_request_header(tx,
"user-agent");
445 if (h_user_agent != NULL) {
447 htp_header_value_ptr(h_user_agent), htp_header_value_len(h_user_agent));
452 LogHttpLogExtended(aft, tx);
458 "%s:%" PRIu16
" -> %s:%" PRIu16
"\n",
459 srcip, sp, dstip, dp);
476 if (!(PacketIsTCP(p))) {
481 if (PacketIsIPv4(p)) {
482 r = LogHttpLogIPWrapper(
tv, thread_data, p, f, (
HtpState *)state, (htp_tx_t *)tx, tx_id, AF_INET);
483 }
else if (PacketIsIPv6(p)) {
484 r = LogHttpLogIPWrapper(
tv, thread_data, p, f, (
HtpState *)state, (htp_tx_t *)tx, tx_id, AF_INET6);
498 SCLogDebug(
"Error getting context for LogHTTPLog. \"initdata\" argument NULL");
504 if (aft->
buffer == NULL) {
537 SCLogWarning(
"The http-log output has been deprecated and will be removed in Suricata 9.0.");
540 if(file_ctx == NULL) {
551 if (
unlikely(httplog_ctx == NULL)) {
563 if (custom != NULL && customformat != NULL &&
SCConfValIsTrue(custom)) {
566 if (!httplog_ctx->
cf) {
577 if (extended == NULL) {
591 output_ctx->
data = httplog_ctx;
592 output_ctx->
DeInit = LogHttpLogDeInitCtx;
599 result.
ctx = output_ctx;
604 SCLogError(
"Syntax error in custom http log format string.");
613static void LogHttpLogDeInitCtx(
OutputCtx *output_ctx)
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
int SCConfValIsTrue(const char *val)
Check if a value is true.
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
#define GET_IPV6_DST_ADDR(p)
#define GET_IPV4_SRC_ADDR_PTR(p)
#define GET_IPV6_SRC_ADDR(p)
#define PKT_IS_TOSERVER(p)
#define GET_IPV4_DST_ADDR_PTR(p)
void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const SCTime_t ts)
Writes a timestamp with given format into a MemBuffer.
void LogCustomFormatFree(LogCustomFormat *cf)
Frees memory held by a custom format.
LogCustomFormat * LogCustomFormatAlloc(void)
Creates a custom format.
int LogCustomFormatParse(LogCustomFormat *cf, const char *format)
Parses and saves format nodes for custom format.
#define LOG_CF_WRITE_STAR_SEPARATOR(buffer)
#define LOG_CF_CLIENT_PORT
#define LOG_CF_SERVER_PORT
#define LOG_CF_TIMESTAMP_U
#define LOG_HTTP_CF_REQUEST_HEADER
TmEcode LogHttpLogThreadInit(ThreadVars *, const void *, void **)
struct LogHttpFileCtx_ LogHttpFileCtx
TmEcode LogHttpLogThreadDeinit(ThreadVars *, void *)
#define OUTPUT_BUFFER_SIZE
#define LOG_HTTP_CF_RESPONSE_HEADER
#define LOG_HTTP_EXTENDED
void LogHttpLogRegister(void)
#define LOG_HTTP_CF_RESPONSE_STATUS
#define LOG_HTTP_CF_REQUEST_HOST
int LogHttpLogger(ThreadVars *tv, void *thread_data, const Packet *, Flow *f, void *state, void *tx, uint64_t tx_id)
#define LOG_HTTP_CF_RESPONSE_LEN
#define LOG_HTTP_CF_REQUEST_COOKIE
#define DEFAULT_LOG_FILENAME
#define LOG_HTTP_CF_REQUEST_LEN
struct LogHttpLogThread_ LogHttpLogThread
#define LOG_HTTP_CF_REQUEST_URI
#define LOG_HTTP_CF_REQUEST_METHOD
#define LOG_HTTP_CF_REQUEST_PROTOCOL
OutputInitResult LogHttpLogInitCtx(SCConfNode *conf)
Create a new http log LogFileCtx.
void OutputRegisterTxModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, AppProto alproto, TxLogger TxLogFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Register a tx output module.
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
LogHttpFileCtx * httplog_ctx
void(* DeInit)(struct OutputCtx_ *)
Per thread variable structure.
void MemBufferWriteString(MemBuffer *dst, const char *fmt,...)
MemBuffer * MemBufferCreateNew(uint32_t size)
void MemBufferFree(MemBuffer *buffer)
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
#define SCLogWarning(...)
Macro used to log WARNING messages.
#define SCLogError(...)
Macro used to log ERROR messages.
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
int SCConfLogOpenGeneric(SCConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, const uint8_t *buf, size_t buflen)
void CreateTimeString(const SCTime_t ts, char *str, size_t size)