68 #define MAX_SIZE_HEADER_NAME 256
69 #define MAX_SIZE_HEADER_VALUE 2048
71 #define LOG_HTTP_DEFAULT 0
72 #define LOG_HTTP_EXTENDED 1
73 #define LOG_HTTP_REQUEST 2
74 #define LOG_HTTP_ARRAY 4
75 #define LOG_HTTP_REQ_HEADERS 8
76 #define LOG_HTTP_RES_HEADERS 16
161 {
"accept_range",
"accept-range", 0 },
163 {
"allow",
"allow", 0 },
164 {
"connection",
"connection", 0 },
165 {
"content_encoding",
"content-encoding", 0 },
166 {
"content_language",
"content-language", 0 },
167 {
"content_length",
"content-length", 0 },
168 {
"content_location",
"content-location", 0 },
169 {
"content_md5",
"content-md5", 0 },
170 {
"content_range",
"content-range", 0 },
171 {
"content_type",
"content-type", 0 },
172 {
"date",
"date", 0 },
173 {
"etag",
"etags", 0 },
174 {
"expires",
"expires", 0 },
175 {
"last_modified",
"last-modified", 0 },
176 {
"link",
"link", 0 },
177 {
"location",
"location", 0 },
178 {
"proxy_authenticate",
"proxy-authenticate", 0 },
180 {
"refresh",
"refresh", 0 },
181 {
"retry_after",
"retry-after", 0 },
182 {
"server",
"server", 0 },
183 {
"set_cookie",
"set-cookie", 0 },
184 {
"trailer",
"trailer", 0 },
185 {
"transfer_encoding",
"transfer-encoding", 0 },
186 {
"upgrade",
"upgrade", 0 },
187 {
"vary",
"vary", 0 },
188 {
"warning",
"warning", 0 },
189 {
"www_authenticate",
"www-authenticate", 0 },
195 static void EveHttpLogJSONBasic(
SCJsonBuilder *js, htp_tx_t *tx)
198 if (htp_tx_request_hostname(tx) != NULL) {
199 SCJbSetStringFromBytes(js,
"hostname", bstr_ptr(htp_tx_request_hostname(tx)),
200 (uint32_t)bstr_len(htp_tx_request_hostname(tx)));
209 if (htp_tx_request_port_number(tx) >= 0) {
210 SCJbSetUint(js,
"http_port", htp_tx_request_port_number(tx));
214 if (htp_tx_request_uri(tx) != NULL) {
215 SCJbSetStringFromBytes(js,
"url", bstr_ptr(htp_tx_request_uri(tx)),
216 (uint32_t)bstr_len(htp_tx_request_uri(tx)));
219 if (htp_tx_request_headers(tx) != NULL) {
221 const htp_header_t *h_user_agent = htp_tx_request_header(tx,
"user-agent");
222 if (h_user_agent != NULL) {
223 SCJbSetStringFromBytes(js,
"http_user_agent", htp_header_value_ptr(h_user_agent),
224 (uint32_t)htp_header_value_len(h_user_agent));
228 const htp_header_t *h_x_forwarded_for = htp_tx_request_header(tx,
"x-forwarded-for");
229 if (h_x_forwarded_for != NULL) {
230 SCJbSetStringFromBytes(js,
"xff", htp_header_value_ptr(h_x_forwarded_for),
231 (uint32_t)htp_header_value_len(h_x_forwarded_for));
236 if (htp_tx_response_headers(tx) != NULL) {
237 const htp_header_t *h_content_type = htp_tx_response_header(tx,
"content-type");
238 if (h_content_type != NULL) {
239 uint32_t
len = (uint32_t)htp_header_value_len(h_content_type);
240 const uint8_t *
p = memchr(htp_header_value_ptr(h_content_type),
';',
len);
242 len = (uint32_t)(
p - htp_header_value_ptr(h_content_type));
243 SCJbSetStringFromBytes(
244 js,
"http_content_type", htp_header_value_ptr(h_content_type),
len);
246 const htp_header_t *h_content_range = htp_tx_response_header(tx,
"content-range");
247 if (h_content_range != NULL) {
248 SCJbOpenObject(js,
"content_range");
249 SCJbSetStringFromBytes(js,
"raw", htp_header_value_ptr(h_content_range),
250 (uint32_t)htp_header_value_len(h_content_range));
253 if (crparsed.start >= 0)
254 SCJbSetUint(js,
"start", crparsed.start);
255 if (crparsed.end >= 0)
256 SCJbSetUint(js,
"end", crparsed.end);
257 if (crparsed.size >= 0)
258 SCJbSetUint(js,
"size", crparsed.size);
265 static void EveHttpLogJSONExtended(
SCJsonBuilder *js, htp_tx_t *tx)
268 const htp_header_t *h_referer = NULL;
269 if (htp_tx_request_headers(tx) != NULL) {
270 h_referer = htp_tx_request_header(tx,
"referer");
272 if (h_referer != NULL) {
273 SCJbSetStringFromBytes(js,
"http_refer", htp_header_value_ptr(h_referer),
274 (uint32_t)htp_header_value_len(h_referer));
278 if (htp_tx_request_method(tx) != NULL) {
279 SCJbSetStringFromBytes(js,
"http_method", bstr_ptr(htp_tx_request_method(tx)),
280 (uint32_t)bstr_len(htp_tx_request_method(tx)));
284 if (htp_tx_request_protocol(tx) != NULL) {
285 SCJbSetStringFromBytes(js,
"protocol", bstr_ptr(htp_tx_request_protocol(tx)),
286 (uint32_t)bstr_len(htp_tx_request_protocol(tx)));
290 const int resp = htp_tx_response_status_number(tx);
292 SCJbSetUint(js,
"status", (uint32_t)resp);
293 }
else if (htp_tx_response_status(tx) != NULL) {
294 SCJbSetStringFromBytes(js,
"status_string", bstr_ptr(htp_tx_response_status(tx)),
295 (uint32_t)bstr_len(htp_tx_response_status(tx)));
298 const htp_header_t *h_location = htp_tx_response_header(tx,
"location");
299 if (h_location != NULL) {
300 SCJbSetStringFromBytes(js,
"redirect", htp_header_value_ptr(h_location),
301 (uint32_t)htp_header_value_len(h_location));
305 SCJbSetUint(js,
"length", htp_tx_response_message_len(tx));
308 static void EveHttpLogJSONHeaders(
312 : htp_tx_response_headers(tx);
315 size_t n = htp_headers_size(headers);
316 SCJsonBuilderMark mark = { 0, 0, 0 };
317 SCJbGetMark(js, &mark);
318 bool array_empty =
true;
320 for (
size_t i = 0; i < n; i++) {
321 const htp_header_t *h = htp_headers_get_index(headers, i);
322 if ((http_ctx->
flags & direction) == 0 && http_ctx->
fields != 0) {
325 if ((http_ctx->
fields & (1ULL <<
f)) != 0) {
345 ? htp_header_name_len(h)
347 memcpy(
name, htp_header_name_ptr(h), size_name);
348 name[size_name] =
'\0';
349 SCJbSetString(js,
"name",
name);
351 ? htp_header_value_len(h)
353 memcpy(value, htp_header_value_ptr(h), size_value);
354 value[size_value] =
'\0';
355 SCJbSetString(js,
"value", value);
359 SCJbRestoreMark(js, &mark);
369 const uint8_t *body_data;
370 uint32_t body_data_len;
371 uint64_t body_offset;
374 &body_data_len, &body_offset) == 0) {
378 SCJbSetPrintAsciiString(js, key, body_data, body_data_len);
389 BodyPrintableBuffer(js, &htud->
request_body,
"http_request_body_printable");
390 BodyPrintableBuffer(js, &htud->
response_body,
"http_response_body_printable");
398 const uint8_t *body_data;
399 uint32_t body_data_len;
400 uint64_t body_offset;
403 &body_data_len, &body_offset) == 0) {
407 SCJbSetBase64(js, key, body_data, body_data_len);
418 BodyBase64Buffer(js, &htud->
request_body,
"http_request_body");
419 BodyBase64Buffer(js, &htud->
response_body,
"http_response_body");
428 SCJbOpenObject(js,
"http");
430 EveHttpLogJSONBasic(js, tx);
432 EveHttpLogJSONExtended(js, tx);
441 static int JsonHttpLogger(
ThreadVars *
tv,
void *thread_data,
const Packet *
p,
Flow *
f,
void *alstate,
void *txptr, uint64_t tx_id)
445 htp_tx_t *tx = txptr;
453 SCLogDebug(
"got a HTTP request and now logging !!");
455 EveHttpLogJSON(jhl, js, tx, tx_id);
468 SCJbSetString(js,
"xff", buffer);
472 SCJbSetString(js,
"dest_ip", buffer);
474 SCJbSetString(js,
"src_ip", buffer);
493 EveHttpLogJSONBasic(js, tx);
494 EveHttpLogJSONExtended(js, tx);
502 static void OutputHttpLogDeinitSub(
OutputCtx *output_ctx)
520 memset(http_ctx, 0x00,
sizeof(*http_ctx));
534 if (extended != NULL) {
541 if (all_headers != NULL) {
542 if (strncmp(all_headers,
"both", 4) == 0) {
545 }
else if (strncmp(all_headers,
"request", 7) == 0) {
547 }
else if (strncmp(all_headers,
"response", 8) == 0) {
555 SCLogWarning(
"No need for custom as dump-all-headers is already present");
563 http_ctx->
fields |= (1ULL <<
f);
573 if (http_ctx->
xff_cfg != NULL) {
580 output_ctx->
data = http_ctx;
581 output_ctx->
DeInit = OutputHttpLogDeinitSub;
586 result.
ctx = output_ctx;
591 static TmEcode JsonHttpLogThreadInit(
ThreadVars *t,
const void *initdata,
void **data)
599 SCLogDebug(
"Error getting context for EveLogHTTP. \"initdata\" argument NULL");
639 OutputHttpLogInitSub,
ALPROTO_HTTP1, JsonHttpLogger, JsonHttpLogThreadInit,
640 JsonHttpLogThreadDeinit);