summaryrefslogtreecommitdiffstats
path: root/plugins/check_http.c
diff options
context:
space:
mode:
authorRincewindsHat <12514511+RincewindsHat@users.noreply.github.com>2022-11-13 23:07:14 +0100
committerSven Nierlein <sven@nierlein.org>2023-01-07 18:34:46 +0100
commitafe92468a54ec44cdda35e46a1eabd0d0de78840 (patch)
tree4e5d95e62c21a303fbcee5cdfd5f846ddc75ca76 /plugins/check_http.c
parent2c658383d5c7742d289e07116c948c6905555405 (diff)
downloadmonitoring-plugins-afe92468a54ec44cdda35e46a1eabd0d0de78840.tar.gz
Implement chunked encoding decoding
Diffstat (limited to 'plugins/check_http.c')
-rw-r--r--plugins/check_http.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/plugins/check_http.c b/plugins/check_http.c
index a2c7571b..5710cfe1 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -146,6 +146,7 @@ char *perfd_time_transfer(double microsec);
146char *perfd_size(int page_len); 146char *perfd_size(int page_len);
147void print_help(void); 147void print_help(void);
148void print_usage(void); 148void print_usage(void);
149char *unchunk_content(char *content);
149 150
150int main(int argc, char **argv) { 151int main(int argc, char **argv) {
151 int result = STATE_UNKNOWN; 152 int result = STATE_UNKNOWN;
@@ -1252,7 +1253,26 @@ int check_http(void) {
1252 } 1253 }
1253 } 1254 }
1254 1255
1255 if (strlen(string_expect)) { 1256 // At this point we should test if the content is chunked and unchunk it, so
1257 // it can be searched (and possibly printed)
1258 const char *chunked_header_regex_string = "Transfer-Encoding:\\s*chunked\\s*"CRLF;
1259 regex_t chunked_header_regex;
1260
1261 if (regcomp(&chunked_header_regex, chunked_header_regex_string, 0)) {
1262 die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to compile chunked_header_regex regex");
1263 }
1264
1265 regmatch_t chre_pmatch[1]; // We actually do not care about this, since we only want to know IF it was found
1266
1267 if (regexec(&chunked_header_regex, header, 1, chre_pmatch, 0) == 0) {
1268 // We actually found the chunked header
1269 char *tmp = unchunk_content(page);
1270 if (tmp == NULL) {
1271 die(STATE_UNKNOWN, "HTTP %s: %s\n", state_text(STATE_UNKNOWN), "Failed to unchunk message body");
1272 }
1273 }
1274
1275 if (strlen(string_expect) > 0) {
1256 if (!strstr(page, string_expect)) { 1276 if (!strstr(page, string_expect)) {
1257 // We found the string the body, the rest is for building the output 1277 // We found the string the body, the rest is for building the output
1258 char output_string_search[30] = ""; 1278 char output_string_search[30] = "";
@@ -1342,6 +1362,87 @@ int check_http(void) {
1342 return STATE_UNKNOWN; 1362 return STATE_UNKNOWN;
1343} 1363}
1344 1364
1365/* Receivces a pointer to the beginning of the body of a HTTP message
1366 * which is chunked and returns a pointer to a freshly allocated memory
1367 * region containing the unchunked body or NULL if something failed.
1368 * The result must be freed by the caller.
1369 */
1370char *unchunk_content(const char *content) {
1371 // https://en.wikipedia.org/wiki/Chunked_transfer_encoding
1372 // https://www.rfc-editor.org/rfc/rfc7230#section-4.1
1373 char *result = NULL;
1374 size_t content_length = strlen(content);
1375 char *start_of_chunk, end_of_chunk;
1376 long size_of_chunk;
1377 char *pointer = content;
1378 char *endptr;
1379 long length_of_chunk = 0;
1380 size_t overall_size = 0;
1381 char *result_ptr;
1382
1383 while (true) {
1384 size_of_chunk = strtol(pointer, &endptr, 16);
1385 if (size_of_chunk == LONG_MIN || size_of_chunk == LONG_MAX) {
1386 // Apparently underflow or overflow, should not happen
1387 if (verbose) {
1388 printf("Got an underflow or overflow from strtol at: %u\n", __LINE__);
1389 }
1390 return NULL;
1391 }
1392 if (endptr == pointer) {
1393 // Apparently this was not a number
1394 if (verbose) {
1395 printf("Chunked content did not start with a number at all (Line: %u)\n", __LINE__);
1396 }
1397 return NULL
1398 }
1399
1400 // So, we got the length of the chunk
1401 if (*endptr == ';') {
1402 // Chunk extension starts here
1403 // TODO
1404 while (*endptr != '\r') {
1405 endptr++;
1406 }
1407 }
1408
1409 start_of_chunk = endptr + 2;
1410 end_of_chunk = start_of_chunk + size_of_chunk;
1411 length_of_chunk = end_of_chunk - start_of_chunk;
1412
1413 if (length_of_chunk == 0) {
1414 // Chunk length is 0, so this is the last one
1415 break;
1416 }
1417
1418 overall_size += length_of_chunk;
1419
1420 if (result == NULL) {
1421 result = (char *)calloc(length_of_chunk, sizeof(char));
1422 if (result == NULL) {
1423 if (verbose) {
1424 printf("Failed to allocate memory for unchunked body\n");
1425 }
1426 return NULL;
1427 }
1428 result_ptr = result;
1429 } else {
1430 void *tmp = realloc(result, overall_size);
1431 if (tmp == NULL) {
1432 if (verbose) {
1433 printf("Failed to allocate memory for unchunked body\n");
1434 }
1435 return NULL;
1436 }
1437 }
1438
1439 memcpy(result_ptr, start_of_chunk, size_of_chunk);
1440 result_ptr = result_ptr + size_of_chunk;
1441 }
1442
1443 return result
1444}
1445
1345/* per RFC 2396 */ 1446/* per RFC 2396 */
1346#define URI_HTTP "%5[HTPShtps]" 1447#define URI_HTTP "%5[HTPShtps]"
1347#define URI_HOST \ 1448#define URI_HOST \