Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/log-httplog.c
Line
Count
Source
1
/* Copyright (C) 2007-2013 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 * \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
23
 *
24
 * Implements http logging portion of the engine.
25
 */
26
27
#include "suricata-common.h"
28
#include "detect.h"
29
#include "pkt-var.h"
30
#include "conf.h"
31
32
#include "threads.h"
33
#include "threadvars.h"
34
#include "tm-threads.h"
35
36
#include "util-print.h"
37
#include "util-unittest.h"
38
39
#include "util-debug.h"
40
41
#include "output.h"
42
#include "log-httplog.h"
43
#include "app-layer-htp.h"
44
#include "app-layer.h"
45
#include "app-layer-parser.h"
46
#include "util-privs.h"
47
#include "util-buffer.h"
48
49
#include "util-logopenfile.h"
50
#include "util-time.h"
51
#include "log-cf-common.h"
52
53
4
#define DEFAULT_LOG_FILENAME "http.log"
54
55
71
#define MODULE_NAME "LogHttpLog"
56
57
4
#define OUTPUT_BUFFER_SIZE 65535
58
59
TmEcode LogHttpLogThreadInit(ThreadVars *, const void *, void **);
60
TmEcode LogHttpLogThreadDeinit(ThreadVars *, void *);
61
static void LogHttpLogDeInitCtx(OutputCtx *);
62
63
int LogHttpLogger(ThreadVars *tv, void *thread_data, const Packet *, Flow *f, void *state, void *tx, uint64_t tx_id);
64
65
void LogHttpLogRegister (void)
66
71
{
67
71
    OutputRegisterTxModule(LOGGER_HTTP, MODULE_NAME, "http-log", LogHttpLogInitCtx, ALPROTO_HTTP1,
68
71
            LogHttpLogger, LogHttpLogThreadInit, LogHttpLogThreadDeinit, NULL);
69
71
}
70
71
0
#define LOG_HTTP_CF_REQUEST_HOST 'h'
72
0
#define LOG_HTTP_CF_REQUEST_PROTOCOL 'H'
73
0
#define LOG_HTTP_CF_REQUEST_METHOD 'm'
74
0
#define LOG_HTTP_CF_REQUEST_URI 'u'
75
#define LOG_HTTP_CF_REQUEST_TIME 't'
76
0
#define LOG_HTTP_CF_REQUEST_HEADER 'i'
77
0
#define LOG_HTTP_CF_REQUEST_COOKIE 'C'
78
0
#define LOG_HTTP_CF_REQUEST_LEN 'b'
79
0
#define LOG_HTTP_CF_RESPONSE_STATUS 's'
80
0
#define LOG_HTTP_CF_RESPONSE_HEADER 'o'
81
0
#define LOG_HTTP_CF_RESPONSE_LEN 'B'
82
83
84
typedef struct LogHttpFileCtx_ {
85
    LogFileCtx *file_ctx;
86
    uint32_t flags; /** Store mode */
87
    LogCustomFormat *cf;
88
} LogHttpFileCtx;
89
90
0
#define LOG_HTTP_DEFAULT 0
91
80.0k
#define LOG_HTTP_EXTENDED 1
92
80.0k
#define LOG_HTTP_CUSTOM 2
93
94
typedef struct LogHttpLogThread_ {
95
    LogHttpFileCtx *httplog_ctx;
96
    /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
97
    uint32_t uri_cnt;
98
99
    MemBuffer *buffer;
100
} LogHttpLogThread;
101
102
/* Retrieves the selected cookie value */
103
static uint32_t GetCookieValue(uint8_t *rawcookies, uint32_t rawcookies_len, char *cookiename,
104
                                                        uint8_t **cookievalue)
105
0
{
106
0
    uint8_t *p = rawcookies;
107
0
    uint8_t *cn = p; /* ptr to cookie name start */
108
0
    uint8_t *cv = NULL; /* ptr to cookie value start */
109
0
    while (p < rawcookies + rawcookies_len) {
110
0
        if (cv == NULL && *p == '=') {
111
0
            cv = p + 1;
112
0
        } else if (cv != NULL && (*p == ';' || p == rawcookies + rawcookies_len - 1) ) {
113
            /* Found end of cookie */
114
0
            p++;
115
0
            if (strlen(cookiename) == (unsigned int) (cv-cn-1) &&
116
0
                        strncmp(cookiename, (char *) cn, cv-cn-1) == 0) {
117
0
                *cookievalue = cv;
118
0
                return (uint32_t) (p-cv);
119
0
            }
120
0
            cv = NULL;
121
0
            cn = p + 1;
122
0
        }
123
0
        p++;
124
0
    }
125
0
    return 0;
126
0
}
127
128
/* Custom format logging */
129
static void LogHttpLogCustom(LogHttpLogThread *aft, htp_tx_t *tx, const SCTime_t ts, char *srcip,
130
        Port sp, char *dstip, Port dp)
131
0
{
132
0
    LogHttpFileCtx *httplog_ctx = aft->httplog_ctx;
133
0
    uint32_t i;
134
0
    uint32_t datalen;
135
0
    char buf[128];
136
137
0
    uint8_t *cvalue = NULL;
138
0
    uint32_t cvalue_len = 0;
139
140
0
    htp_header_t *h_request_hdr;
141
0
    htp_header_t *h_response_hdr;
142
143
0
    for (i = 0; i < httplog_ctx->cf->cf_n; i++) {
144
0
        h_request_hdr = NULL;
145
0
        h_response_hdr = NULL;
146
147
0
        LogCustomFormatNode * node = httplog_ctx->cf->cf_nodes[i];
148
0
        if (! node) /* Should never happen */
149
0
            continue;
150
151
0
        switch (node->type){
152
0
            case LOG_CF_LITERAL:
153
            /* LITERAL */
154
0
                MemBufferWriteString(aft->buffer, "%s", node->data);
155
0
                break;
156
0
            case LOG_CF_TIMESTAMP:
157
            /* TIMESTAMP */
158
0
            LogCustomFormatWriteTimestamp(aft->buffer, node->data, ts);
159
0
            break;
160
0
            case LOG_CF_TIMESTAMP_U:
161
            /* TIMESTAMP USECONDS */
162
0
            snprintf(buf, sizeof(buf), "%06u", (unsigned int)SCTIME_USECS(ts));
163
0
            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
164
0
                    (uint8_t *)buf, MIN(strlen(buf), 6));
165
0
            break;
166
0
            case LOG_CF_CLIENT_IP:
167
            /* CLIENT IP ADDRESS */
168
0
                PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
169
0
                            aft->buffer->size, (uint8_t *)srcip,strlen(srcip));
170
0
                break;
171
0
            case LOG_CF_SERVER_IP:
172
            /* SERVER IP ADDRESS */
173
0
                PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
174
0
                            aft->buffer->size, (uint8_t *)dstip,strlen(dstip));
175
0
                break;
176
0
            case LOG_CF_CLIENT_PORT:
177
            /* CLIENT PORT */
178
0
                MemBufferWriteString(aft->buffer, "%" PRIu16 "", sp);
179
0
                break;
180
0
            case LOG_CF_SERVER_PORT:
181
            /* SERVER PORT */
182
0
                MemBufferWriteString(aft->buffer, "%" PRIu16 "", dp);
183
0
                break;
184
0
            case LOG_HTTP_CF_REQUEST_METHOD:
185
            /* METHOD */
186
0
                if (tx->request_method != NULL) {
187
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
188
0
                                aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_method),
189
0
                                bstr_len(tx->request_method));
190
0
                } else {
191
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
192
0
                }
193
0
                break;
194
0
            case LOG_HTTP_CF_REQUEST_URI:
195
            /* URI */
196
0
                if (tx->request_uri != NULL) {
197
0
                    datalen = node->maxlen;
198
0
                    if (datalen == 0 || datalen > bstr_len(tx->request_uri)) {
199
0
                        datalen = bstr_len(tx->request_uri);
200
0
                    }
201
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
202
0
                                aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_uri),
203
0
                                datalen);
204
0
                } else {
205
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
206
0
                }
207
0
                break;
208
0
            case LOG_HTTP_CF_REQUEST_HOST:
209
            /* HOSTNAME */
210
0
                if (tx->request_hostname != NULL)
211
0
                {
212
0
                    datalen = node->maxlen;
213
0
                    if (datalen == 0 || datalen > bstr_len(tx->request_hostname)) {
214
0
                        datalen = bstr_len(tx->request_hostname);
215
0
                    }
216
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
217
0
                                aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_hostname),
218
0
                                datalen);
219
0
                } else {
220
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
221
0
                }
222
0
                break;
223
0
            case LOG_HTTP_CF_REQUEST_PROTOCOL:
224
            /* PROTOCOL */
225
0
                if (tx->request_protocol != NULL) {
226
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
227
0
                                    aft->buffer->size, (uint8_t *)bstr_ptr(tx->request_protocol),
228
0
                                    bstr_len(tx->request_protocol));
229
0
                } else {
230
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
231
0
                }
232
0
                break;
233
0
            case LOG_HTTP_CF_REQUEST_HEADER:
234
            /* REQUEST HEADER */
235
0
                if (tx->request_headers != NULL) {
236
0
                    h_request_hdr = htp_table_get_c(tx->request_headers, node->data);
237
0
                }
238
0
                if (h_request_hdr != NULL) {
239
0
                    datalen = node->maxlen;
240
0
                    if (datalen == 0 || datalen > bstr_len(h_request_hdr->value)) {
241
0
                        datalen = bstr_len(h_request_hdr->value);
242
0
                    }
243
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
244
0
                                    aft->buffer->size, (uint8_t *)bstr_ptr(h_request_hdr->value),
245
0
                                    datalen);
246
0
                } else {
247
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
248
0
                }
249
0
                break;
250
0
            case LOG_HTTP_CF_REQUEST_COOKIE:
251
            /* REQUEST COOKIE */
252
0
                if (tx->request_headers != NULL) {
253
0
                    h_request_hdr = htp_table_get_c(tx->request_headers, "Cookie");
254
0
                    if (h_request_hdr != NULL) {
255
0
                        cvalue_len = GetCookieValue((uint8_t *) bstr_ptr(h_request_hdr->value),
256
0
                                    bstr_len(h_request_hdr->value), (char *) node->data,
257
0
                                    &cvalue);
258
0
                    }
259
0
                }
260
0
                if (cvalue_len > 0 && cvalue != NULL) {
261
0
                    datalen = node->maxlen;
262
0
                    if (datalen == 0 || datalen > cvalue_len) {
263
0
                        datalen = cvalue_len;
264
0
                    }
265
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
266
0
                                    aft->buffer->size, cvalue, datalen);
267
0
                } else {
268
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
269
0
                }
270
0
                break;
271
0
            case LOG_HTTP_CF_REQUEST_LEN:
272
            /* REQUEST LEN */
273
0
                MemBufferWriteString(aft->buffer, "%"PRIuMAX"", (uintmax_t)tx->request_message_len);
274
0
                break;
275
0
            case LOG_HTTP_CF_RESPONSE_STATUS:
276
            /* RESPONSE STATUS */
277
0
                if (tx->response_status != NULL) {
278
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
279
0
                                    aft->buffer->size, (uint8_t *)bstr_ptr(tx->response_status),
280
0
                                    bstr_len(tx->response_status));
281
0
                } else {
282
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
283
0
                }
284
0
                break;
285
0
            case LOG_HTTP_CF_RESPONSE_HEADER:
286
            /* RESPONSE HEADER */
287
0
                if (tx->response_headers != NULL) {
288
0
                    h_response_hdr = htp_table_get_c(tx->response_headers,
289
0
                                    node->data);
290
0
                }
291
0
                if (h_response_hdr != NULL) {
292
0
                    datalen = node->maxlen;
293
0
                    if (datalen == 0 || datalen > bstr_len(h_response_hdr->value)) {
294
0
                        datalen = bstr_len(h_response_hdr->value);
295
0
                    }
296
0
                    PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
297
0
                                    aft->buffer->size, (uint8_t *)bstr_ptr(h_response_hdr->value),
298
0
                                    datalen);
299
0
                } else {
300
0
                    MemBufferWriteString(aft->buffer, LOG_CF_NONE);
301
0
                }
302
0
                break;
303
0
            case LOG_HTTP_CF_RESPONSE_LEN:
304
            /* RESPONSE LEN */
305
0
                MemBufferWriteString(aft->buffer, "%"PRIuMAX"", (uintmax_t)tx->response_message_len);
306
0
                break;
307
0
            default:
308
            /* NO MATCH */
309
0
                MemBufferWriteString(aft->buffer, LOG_CF_NONE);
310
0
                SCLogDebug("No matching parameter %%%c for custom http log.", node->type);
311
0
                break;
312
0
        }
313
0
    }
314
0
    MemBufferWriteString(aft->buffer, "\n");
315
0
}
316
317
static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
318
80.0k
{
319
80.0k
    LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
320
321
    /* referer */
322
80.0k
    htp_header_t *h_referer = NULL;
323
80.0k
    if (tx->request_headers != NULL) {
324
80.0k
        h_referer = htp_table_get_c(tx->request_headers, "referer");
325
80.0k
    }
326
80.0k
    if (h_referer != NULL) {
327
4.07k
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
328
4.07k
                       (uint8_t *)bstr_ptr(h_referer->value),
329
4.07k
                       bstr_len(h_referer->value));
330
75.9k
    } else {
331
75.9k
        MemBufferWriteString(aft->buffer, "<no referer>");
332
75.9k
    }
333
334
80.0k
    LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
335
336
    /* method */
337
80.0k
    if (tx->request_method != NULL) {
338
49.8k
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
339
49.8k
                       (uint8_t *)bstr_ptr(tx->request_method),
340
49.8k
                       bstr_len(tx->request_method));
341
49.8k
    }
342
80.0k
    LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
343
344
    /* protocol */
345
80.0k
    if (tx->request_protocol != NULL) {
346
30.6k
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
347
30.6k
                       (uint8_t *)bstr_ptr(tx->request_protocol),
348
30.6k
                       bstr_len(tx->request_protocol));
349
49.4k
    } else {
350
49.4k
        MemBufferWriteString(aft->buffer, "<no protocol>");
351
49.4k
    }
352
80.0k
    LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
353
354
    /* response status */
355
80.0k
    if (tx->response_status != NULL) {
356
25.3k
        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
357
25.3k
                       (uint8_t *)bstr_ptr(tx->response_status),
358
25.3k
                       bstr_len(tx->response_status));
359
        /* Redirect? */
360
25.3k
        if ((tx->response_status_number > 300) && ((tx->response_status_number) < 303)) {
361
479
            htp_header_t *h_location = htp_table_get_c(tx->response_headers, "location");
362
479
            if (h_location != NULL) {
363
476
                MemBufferWriteString(aft->buffer, " => ");
364
365
476
                PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
366
476
                               (uint8_t *)bstr_ptr(h_location->value),
367
476
                               bstr_len(h_location->value));
368
476
            }
369
479
        }
370
54.7k
    } else {
371
54.7k
        MemBufferWriteString(aft->buffer, "<no status>");
372
54.7k
    }
373
374
    /* length */
375
80.0k
    LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
376
80.0k
    MemBufferWriteString(aft->buffer, "%"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
377
80.0k
}
378
379
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)
380
80.0k
{
381
80.0k
    SCEnter();
382
383
80.0k
    LogHttpLogThread *aft = (LogHttpLogThread *)data;
384
80.0k
    LogHttpFileCtx *hlog = aft->httplog_ctx;
385
80.0k
    char timebuf[64];
386
387
    /* check if we have HTTP state or not */
388
80.0k
    CreateTimeString(p->ts, timebuf, sizeof(timebuf));
389
390
80.0k
    char srcip[46], dstip[46];
391
80.0k
    Port sp, dp;
392
80.0k
    if ((PKT_IS_TOSERVER(p))) {
393
48.0k
        switch (ipproto) {
394
47.8k
            case AF_INET:
395
47.8k
                PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
396
47.8k
                PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
397
47.8k
                break;
398
282
            case AF_INET6:
399
282
                PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
400
282
                PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
401
282
                break;
402
0
            default:
403
0
                goto end;
404
48.0k
        }
405
48.0k
        sp = p->sp;
406
48.0k
        dp = p->dp;
407
48.0k
    } else {
408
31.9k
        switch (ipproto) {
409
31.9k
            case AF_INET:
410
31.9k
                PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), srcip, sizeof(srcip));
411
31.9k
                PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), dstip, sizeof(dstip));
412
31.9k
                break;
413
51
            case AF_INET6:
414
51
                PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), srcip, sizeof(srcip));
415
51
                PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), dstip, sizeof(dstip));
416
51
                break;
417
0
            default:
418
0
                goto end;
419
31.9k
        }
420
31.9k
        sp = p->dp;
421
31.9k
        dp = p->sp;
422
31.9k
    }
423
424
80.0k
    SCLogDebug("got a HTTP request and now logging !!");
425
426
    /* reset */
427
80.0k
    MemBufferReset(aft->buffer);
428
429
80.0k
    if (hlog->flags & LOG_HTTP_CUSTOM) {
430
0
        LogHttpLogCustom(aft, tx, p->ts, srcip, sp, dstip, dp);
431
80.0k
    } else {
432
        /* time */
433
80.0k
        MemBufferWriteString(aft->buffer, "%s ", timebuf);
434
435
        /* hostname */
436
80.0k
        if (tx->request_hostname != NULL) {
437
17.4k
            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
438
17.4k
                    (uint8_t *)bstr_ptr(tx->request_hostname),
439
17.4k
                    bstr_len(tx->request_hostname));
440
62.6k
        } else {
441
62.6k
            MemBufferWriteString(aft->buffer, "<hostname unknown>");
442
62.6k
        }
443
80.0k
        LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
444
445
        /* uri */
446
80.0k
        if (tx->request_uri != NULL) {
447
66.3k
            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
448
66.3k
                    (uint8_t *)bstr_ptr(tx->request_uri),
449
66.3k
                    bstr_len(tx->request_uri));
450
66.3k
        }
451
80.0k
        LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
452
453
        /* user agent */
454
80.0k
        htp_header_t *h_user_agent = NULL;
455
80.0k
        if (tx->request_headers != NULL) {
456
80.0k
            h_user_agent = htp_table_get_c(tx->request_headers, "user-agent");
457
80.0k
        }
458
80.0k
        if (h_user_agent != NULL) {
459
12.6k
            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
460
12.6k
                    (uint8_t *)bstr_ptr(h_user_agent->value),
461
12.6k
                    bstr_len(h_user_agent->value));
462
67.4k
        } else {
463
67.4k
            MemBufferWriteString(aft->buffer, "<useragent unknown>");
464
67.4k
        }
465
80.0k
        if (hlog->flags & LOG_HTTP_EXTENDED) {
466
80.0k
            LogHttpLogExtended(aft, tx);
467
80.0k
        }
468
469
        /* ip/tcp header info */
470
80.0k
        LOG_CF_WRITE_STAR_SEPARATOR(aft->buffer);
471
80.0k
        MemBufferWriteString(aft->buffer,
472
80.0k
                "%s:%" PRIu16 " -> %s:%" PRIu16 "\n",
473
80.0k
                srcip, sp, dstip, dp);
474
80.0k
    }
475
476
80.0k
    aft->uri_cnt ++;
477
478
80.0k
    hlog->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
479
80.0k
        MEMBUFFER_OFFSET(aft->buffer), hlog->file_ctx);
480
481
80.0k
end:
482
80.0k
    SCReturnInt(0);
483
484
80.0k
}
485
486
int LogHttpLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
487
80.0k
{
488
80.0k
    SCEnter();
489
490
80.0k
    if (!(PKT_IS_TCP(p))) {
491
0
        SCReturnInt(TM_ECODE_OK);
492
0
    }
493
494
80.0k
    int r = 0;
495
80.0k
    if (PKT_IS_IPV4(p)) {
496
79.7k
        r = LogHttpLogIPWrapper(tv, thread_data, p, f, (HtpState *)state, (htp_tx_t *)tx, tx_id, AF_INET);
497
79.7k
    } else if (PKT_IS_IPV6(p)) {
498
333
        r = LogHttpLogIPWrapper(tv, thread_data, p, f, (HtpState *)state, (htp_tx_t *)tx, tx_id, AF_INET6);
499
333
    }
500
501
80.0k
    SCReturnInt(r);
502
80.0k
}
503
504
TmEcode LogHttpLogThreadInit(ThreadVars *t, const void *initdata, void **data)
505
4
{
506
4
    LogHttpLogThread *aft = SCMalloc(sizeof(LogHttpLogThread));
507
4
    if (unlikely(aft == NULL))
508
0
        return TM_ECODE_FAILED;
509
4
    memset(aft, 0, sizeof(LogHttpLogThread));
510
511
4
    if(initdata == NULL)
512
0
    {
513
0
        SCLogDebug("Error getting context for LogHTTPLog.  \"initdata\" argument NULL");
514
0
        SCFree(aft);
515
0
        return TM_ECODE_FAILED;
516
0
    }
517
518
4
    aft->buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE);
519
4
    if (aft->buffer == NULL) {
520
0
        SCFree(aft);
521
0
        return TM_ECODE_FAILED;
522
0
    }
523
524
    /* Use the Output Context (file pointer and mutex) */
525
4
    aft->httplog_ctx= ((OutputCtx *)initdata)->data;
526
527
4
    *data = (void *)aft;
528
4
    return TM_ECODE_OK;
529
4
}
530
531
TmEcode LogHttpLogThreadDeinit(ThreadVars *t, void *data)
532
0
{
533
0
    LogHttpLogThread *aft = (LogHttpLogThread *)data;
534
0
    if (aft == NULL) {
535
0
        return TM_ECODE_OK;
536
0
    }
537
538
0
    MemBufferFree(aft->buffer);
539
    /* clear memory */
540
0
    memset(aft, 0, sizeof(LogHttpLogThread));
541
542
0
    SCFree(aft);
543
0
    return TM_ECODE_OK;
544
0
}
545
546
/** \brief Create a new http log LogFileCtx.
547
 *  \param conf Pointer to ConfNode containing this loggers configuration.
548
 *  \return NULL if failure, LogFileCtx* to the file_ctx if succesful
549
 * */
550
OutputInitResult LogHttpLogInitCtx(ConfNode *conf)
551
4
{
552
4
    OutputInitResult result = { NULL, false };
553
4
    LogFileCtx* file_ctx = LogFileNewCtx();
554
4
    if(file_ctx == NULL) {
555
0
        SCLogError("couldn't create new file_ctx");
556
0
        return result;
557
0
    }
558
559
4
    if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) {
560
0
        LogFileFreeCtx(file_ctx);
561
0
        return result;
562
0
    }
563
564
4
    LogHttpFileCtx *httplog_ctx = SCMalloc(sizeof(LogHttpFileCtx));
565
4
    if (unlikely(httplog_ctx == NULL)) {
566
0
        LogFileFreeCtx(file_ctx);
567
0
        return result;
568
0
    }
569
4
    memset(httplog_ctx, 0x00, sizeof(LogHttpFileCtx));
570
571
4
    httplog_ctx->file_ctx = file_ctx;
572
573
4
    const char *extended = ConfNodeLookupChildValue(conf, "extended");
574
4
    const char *custom = ConfNodeLookupChildValue(conf, "custom");
575
4
    const char *customformat = ConfNodeLookupChildValue(conf, "customformat");
576
577
    /* If custom logging format is selected, lets parse it */
578
4
    if (custom != NULL && customformat != NULL && ConfValIsTrue(custom)) {
579
580
0
        httplog_ctx->cf = LogCustomFormatAlloc();
581
0
        if (!httplog_ctx->cf) {
582
0
            goto errorfree;
583
0
        }
584
585
0
        httplog_ctx->flags |= LOG_HTTP_CUSTOM;
586
587
        /* Parsing */
588
0
        if ( ! LogCustomFormatParse(httplog_ctx->cf, customformat)) {
589
0
            goto parsererror;
590
0
        }
591
4
    } else {
592
4
        if (extended == NULL) {
593
0
            httplog_ctx->flags |= LOG_HTTP_DEFAULT;
594
4
        } else {
595
4
            if (ConfValIsTrue(extended)) {
596
4
                httplog_ctx->flags |= LOG_HTTP_EXTENDED;
597
4
            }
598
4
        }
599
4
    }
600
601
4
    OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
602
4
    if (unlikely(output_ctx == NULL)) {
603
0
        goto parsererror;
604
0
    }
605
606
4
    output_ctx->data = httplog_ctx;
607
4
    output_ctx->DeInit = LogHttpLogDeInitCtx;
608
609
4
    SCLogDebug("HTTP log output initialized");
610
611
    /* enable the logger for the app layer */
612
4
    AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_HTTP1);
613
614
4
    result.ctx = output_ctx;
615
4
    result.ok = true;
616
4
    return result;
617
618
0
parsererror:
619
0
    SCLogError("Syntax error in custom http log format string.");
620
0
errorfree:
621
0
    LogCustomFormatFree(httplog_ctx->cf);
622
0
    LogFileFreeCtx(file_ctx);
623
0
    SCFree(httplog_ctx);
624
0
    return result;
625
626
0
}
627
628
static void LogHttpLogDeInitCtx(OutputCtx *output_ctx)
629
0
{
630
0
    LogHttpFileCtx *httplog_ctx = (LogHttpFileCtx *)output_ctx->data;
631
0
    LogCustomFormatFree(httplog_ctx->cf);
632
0
    LogFileFreeCtx(httplog_ctx->file_ctx);
633
0
    SCFree(httplog_ctx);
634
0
    SCFree(output_ctx);
635
0
}