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;