From 616af063e3a83d94d46e75fe33730a6e4025626b Mon Sep 17 00:00:00 2001 From: Joris Vink Date: Tue, 17 Jul 2018 14:53:55 +0200 Subject: [PATCH] Calculate an md over the incoming HTTP body. This is calculated while the HTTP body is incoming over the wire, once the body is fully received the digest will be available for the page handlers to obtain. You can obtain a hex string for this md via http_body_digest() or dereferences the http_request and look at http_body_digest manually for the bytes. --- include/kore/http.h | 7 +++++++ src/http.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/kore/http.h b/include/kore/http.h index af540d8..11a2d75 100644 --- a/include/kore/http.h +++ b/include/kore/http.h @@ -210,6 +210,9 @@ struct http_file { #define HTTP_VALIDATOR_IS_REQUEST 0x8000 +#define HTTP_BODY_DIGEST_LEN 32 +#define HTTP_BODY_DIGEST_STRLEN ((HTTP_BODY_DIGEST_LEN * 2) + 1) + struct kore_task; struct http_request { @@ -226,6 +229,7 @@ struct http_request { const char *agent; const char *referer; struct connection *owner; + SHA256_CTX hashctx; u_int8_t *headers; struct kore_buf *http_body; int http_body_fd; @@ -238,6 +242,8 @@ struct http_request { char *query_string; struct kore_module_handle *hdlr; + u_int8_t http_body_digest[HTTP_BODY_DIGEST_LEN]; + #if defined(KORE_USE_PYTHON) void *py_coro; #endif @@ -293,6 +299,7 @@ void http_process_request(struct http_request *); int http_body_rewind(struct http_request *); int http_media_register(const char *, const char *); ssize_t http_body_read(struct http_request *, void *, size_t); +int http_body_digest(struct http_request *, char *, size_t); void http_response(struct http_request *, int, const void *, size_t); void http_response_fileref(struct http_request *, int, struct kore_fileref *); diff --git a/src/http.c b/src/http.c index 52b5860..a99f803 100644 --- a/src/http.c +++ b/src/http.c @@ -762,6 +762,9 @@ http_header_recv(struct netbuf *nb) (nb->s_off - len)); } + SHA256_Init(&req->hashctx); + SHA256_Update(&req->hashctx, end_headers, (nb->s_off - len)); + bytes_left = req->content_length - (nb->s_off - len); if (bytes_left > 0) { kore_debug("%ld/%ld (%ld - %ld) more bytes for body", @@ -772,9 +775,10 @@ http_header_recv(struct netbuf *nb) c->rnb->extra = req; http_request_sleep(req); req->content_length = bytes_left; - } else if (bytes_left == 0) { + } else { req->flags |= HTTP_REQUEST_COMPLETE; req->flags &= ~HTTP_REQUEST_EXPECT_BODY; + SHA256_Final(req->http_body_digest, &req->hashctx); if (!http_body_rewind(req)) { req->flags |= HTTP_REQUEST_DELETE; http_error_response(req->owner, 500); @@ -1163,6 +1167,30 @@ http_body_rewind(struct http_request *req) return (KORE_RESULT_OK); } +int +http_body_digest(struct http_request *req, char *out, size_t len) +{ + size_t idx; + int slen; + + if (len != HTTP_BODY_DIGEST_STRLEN) { + fatal("http_body_digest: bad len:%zu wanted:%zu", + len, HTTP_BODY_DIGEST_STRLEN); + } + + if (!(req->flags & HTTP_REQUEST_COMPLETE)) + return (KORE_RESULT_ERROR); + + for (idx = 0; idx < sizeof(req->http_body_digest); idx++) { + slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x", + req->http_body_digest[idx]); + if (slen == -1 || (size_t)slen >= len) + fatal("failed to create hex string"); + } + + return (KORE_RESULT_OK); +} + ssize_t http_body_read(struct http_request *req, void *out, size_t len) { @@ -1662,6 +1690,8 @@ http_body_recv(struct netbuf *nb) u_int64_t bytes_left; struct http_request *req = (struct http_request *)nb->extra; + SHA256_Update(&req->hashctx, nb->buf, nb->s_off); + if (req->http_body_fd != -1) { ret = write(req->http_body_fd, nb->buf, nb->s_off); if (ret == -1 || (size_t)ret != nb->s_off) { @@ -1690,6 +1720,7 @@ http_body_recv(struct netbuf *nb) http_error_response(req->owner, 500); return (KORE_RESULT_ERROR); } + SHA256_Final(req->http_body_digest, &req->hashctx); net_recv_reset(nb->owner, http_header_max, http_header_recv); } else { bytes_left = req->content_length;