[monitoring-plugins] Implement chunked encoding decoding
Sven Nierlein
git at monitoring-plugins.org
Sat Jan 7 18:40:13 CET 2023
Module: monitoring-plugins
Branch: master
Commit: afe92468a54ec44cdda35e46a1eabd0d0de78840
Author: RincewindsHat <12514511+RincewindsHat at users.noreply.github.com>
Committer: Sven Nierlein <sven at nierlein.org>
Date: Sun Nov 13 23:07:14 2022 +0100
URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=afe9246
Implement chunked encoding decoding
---
plugins/check_http.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 102 insertions(+), 1 deletion(-)
diff --git a/plugins/check_http.c b/plugins/check_http.c
index a2c7571..5710cfe 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -146,6 +146,7 @@ char *perfd_time_transfer(double microsec);
char *perfd_size(int page_len);
void print_help(void);
void print_usage(void);
+char *unchunk_content(char *content);
int main(int argc, char **argv) {
int result = STATE_UNKNOWN;
@@ -1252,7 +1253,26 @@ int check_http(void) {
}
}
- if (strlen(string_expect)) {
+ // At this point we should test if the content is chunked and unchunk it, so
+ // it can be searched (and possibly printed)
+ const char *chunked_header_regex_string = "Transfer-Encoding:\\s*chunked\\s*"CRLF;
+ regex_t chunked_header_regex;
+
+ if (regcomp(&chunked_header_regex, chunked_header_regex_string, 0)) {
+ die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to compile chunked_header_regex regex");
+ }
+
+ regmatch_t chre_pmatch[1]; // We actually do not care about this, since we only want to know IF it was found
+
+ if (regexec(&chunked_header_regex, header, 1, chre_pmatch, 0) == 0) {
+ // We actually found the chunked header
+ char *tmp = unchunk_content(page);
+ if (tmp == NULL) {
+ die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to unchunk message body");
+ }
+ }
+
+ if (strlen(string_expect) > 0) {
if (!strstr(page, string_expect)) {
// We found the string the body, the rest is for building the output
char output_string_search[30] = "";
@@ -1342,6 +1362,87 @@ int check_http(void) {
return STATE_UNKNOWN;
}
+/* Receivces a pointer to the beginning of the body of a HTTP message
+ * which is chunked and returns a pointer to a freshly allocated memory
+ * region containing the unchunked body or NULL if something failed.
+ * The result must be freed by the caller.
+ */
+char *unchunk_content(const char *content) {
+ // https://en.wikipedia.org/wiki/Chunked_transfer_encoding
+ // https://www.rfc-editor.org/rfc/rfc7230#section-4.1
+ char *result = NULL;
+ size_t content_length = strlen(content);
+ char *start_of_chunk, end_of_chunk;
+ long size_of_chunk;
+ char *pointer = content;
+ char *endptr;
+ long length_of_chunk = 0;
+ size_t overall_size = 0;
+ char *result_ptr;
+
+ while (true) {
+ size_of_chunk = strtol(pointer, &endptr, 16);
+ if (size_of_chunk == LONG_MIN || size_of_chunk == LONG_MAX) {
+ // Apparently underflow or overflow, should not happen
+ if (verbose) {
+ printf("Got an underflow or overflow from strtol at: %u\n", __LINE__);
+ }
+ return NULL;
+ }
+ if (endptr == pointer) {
+ // Apparently this was not a number
+ if (verbose) {
+ printf("Chunked content did not start with a number at all (Line: %u)\n", __LINE__);
+ }
+ return NULL
+ }
+
+ // So, we got the length of the chunk
+ if (*endptr == ';') {
+ // Chunk extension starts here
+ // TODO
+ while (*endptr != '\r') {
+ endptr++;
+ }
+ }
+
+ start_of_chunk = endptr + 2;
+ end_of_chunk = start_of_chunk + size_of_chunk;
+ length_of_chunk = end_of_chunk - start_of_chunk;
+
+ if (length_of_chunk == 0) {
+ // Chunk length is 0, so this is the last one
+ break;
+ }
+
+ overall_size += length_of_chunk;
+
+ if (result == NULL) {
+ result = (char *)calloc(length_of_chunk, sizeof(char));
+ if (result == NULL) {
+ if (verbose) {
+ printf("Failed to allocate memory for unchunked body\n");
+ }
+ return NULL;
+ }
+ result_ptr = result;
+ } else {
+ void *tmp = realloc(result, overall_size);
+ if (tmp == NULL) {
+ if (verbose) {
+ printf("Failed to allocate memory for unchunked body\n");
+ }
+ return NULL;
+ }
+ }
+
+ memcpy(result_ptr, start_of_chunk, size_of_chunk);
+ result_ptr = result_ptr + size_of_chunk;
+ }
+
+ return result
+}
+
/* per RFC 2396 */
#define URI_HTTP "%5[HTPShtps]"
#define URI_HOST \
More information about the Commits
mailing list