kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 616af063e3a83d94d46e75fe33730a6e4025626b
parent 9f2759e7b28489b686ac74b976380049a9f31372
Author: Joris Vink <joris@coders.se>
Date:   Tue, 17 Jul 2018 14:53:55 +0200

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.

Diffstat:
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 @@ -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 @@ -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;