From: Giuseppe Longo Date: Thu, 14 Apr 2016 12:26:58 +0000 (+0200) Subject: output-json-http: add functions to log http body X-Git-Tag: suricata-4.0.0-rc1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fff5f7f1f979673ab22f1d90df84785ddaa45179;p=thirdparty%2Fsuricata.git output-json-http: add functions to log http body This patch adds two functions that permits to log the http body in printable or base64 format. --- diff --git a/src/output-json-http.c b/src/output-json-http.c index a23308388c..02127928af 100644 --- a/src/output-json-http.c +++ b/src/output-json-http.c @@ -47,7 +47,9 @@ #include "util-proto-name.h" #include "util-logopenfile.h" #include "util-time.h" +#include "util-crypt.h" #include "output-json.h" +#include "output-json-alert.h" #include "output-json-http.h" #ifdef HAVE_LIBJANSSON @@ -350,6 +352,79 @@ static void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx) json_object_set_new(js, "length", json_integer(tx->response_message_len)); } +static void BodyPrintableBuffer(json_t *js, HtpBody *body, const char *key) +{ + if (body->sb != NULL && body->sb->buf != NULL) { + uint32_t offset = 0; + const uint8_t *body_data; + uint32_t body_data_len; + uint64_t body_offset; + + if (StreamingBufferGetData(body->sb, &body_data, + &body_data_len, &body_offset) == 0) { + return; + } + + uint8_t printable_buf[body_data_len + 1]; + PrintStringsToBuffer(printable_buf, &offset, + sizeof(printable_buf), + body_data, body_data_len); + if (offset > 0) { + json_object_set_new(js, key, json_string((char *)printable_buf)); + } + } +} + +void JsonHttpLogJSONBodyPrintable(json_t *js, Flow *f, uint64_t tx_id) +{ + HtpState *htp_state = (HtpState *)FlowGetAppState(f); + if (htp_state) { + htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, tx_id); + if (tx) { + HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx); + if (htud != NULL) { + BodyPrintableBuffer(js, &htud->request_body, "http_request_body_printable"); + BodyPrintableBuffer(js, &htud->response_body, "http_response_body_printable"); + } + } + } +} + +static void BodyBase64Buffer(json_t *js, HtpBody *body, const char *key) +{ + if (body->sb != NULL && body->sb->buf != NULL) { + const uint8_t *body_data; + uint32_t body_data_len; + uint64_t body_offset; + + if (StreamingBufferGetData(body->sb, &body_data, + &body_data_len, &body_offset) == 0) { + return; + } + + unsigned long len = body_data_len * 2 + 1; + uint8_t encoded[len]; + if (Base64Encode(body_data, body_data_len, encoded, &len) == SC_BASE64_OK) { + json_object_set_new(js, key, json_string((char *)encoded)); + } + } +} + +void JsonHttpLogJSONBodyBase64(json_t *js, Flow *f, uint64_t tx_id) +{ + HtpState *htp_state = (HtpState *)FlowGetAppState(f); + if (htp_state) { + htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, tx_id); + if (tx) { + HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx); + if (htud != NULL) { + BodyBase64Buffer(js, &htud->request_body, "http_request_body"); + BodyBase64Buffer(js, &htud->response_body, "http_response_body"); + } + } + } +} + /* JSON format logging */ static void JsonHttpLogJSON(JsonHttpLogThread *aft, json_t *js, htp_tx_t *tx, uint64_t tx_id) { @@ -409,7 +484,6 @@ json_t *JsonHttpAddMetadata(const Flow *f, uint64_t tx_id) JsonHttpLogJSONBasic(hjs, tx); JsonHttpLogJSONExtended(hjs, tx); - return hjs; } } diff --git a/src/output-json-http.h b/src/output-json-http.h index a82e928009..a37fe92fe6 100644 --- a/src/output-json-http.h +++ b/src/output-json-http.h @@ -28,6 +28,8 @@ void JsonHttpLogRegister(void); #ifdef HAVE_LIBJANSSON json_t *JsonHttpAddMetadata(const Flow *f, uint64_t tx_id); +void JsonHttpLogJSONBodyPrintable(json_t *js, Flow *f, uint64_t tx_id); +void JsonHttpLogJSONBodyBase64(json_t *js, Flow *f, uint64_t tx_id); #endif /* HAVE_LIBJANSSON */ #endif /* __OUTPUT_JSON_HTTP_H__ */