diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2017-04-16 14:53:32 (GMT) |
---|---|---|
committer | Sven Nierlein <sven@nierlein.de> | 2018-10-22 14:30:31 (GMT) |
commit | 54c8f76c72ce73a9e0e23dbce26d09aa15e002ad (patch) | |
tree | 1df96ac98157082ec88e34d3a9922250b261ee7a /plugins/check_curl.c | |
parent | 3c681a2ec5b8329e53bf5cdba9e60e3fb4a0aaee (diff) | |
download | monitoring-plugins-54c8f76c72ce73a9e0e23dbce26d09aa15e002ad.tar.gz |
fixed test outputs for status line checks
handling empty data in POST and PUT
handling data upload (from -P <postdata>) also in PUT
Diffstat (limited to 'plugins/check_curl.c')
-rw-r--r-- | plugins/check_curl.c | 133 |
1 files changed, 99 insertions, 34 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index 103937c..5d3df9e 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c | |||
@@ -67,7 +67,14 @@ typedef struct { | |||
67 | char *buf; | 67 | char *buf; |
68 | size_t buflen; | 68 | size_t buflen; |
69 | size_t bufsize; | 69 | size_t bufsize; |
70 | } curlhelp_curlbuf; | 70 | } curlhelp_write_curlbuf; |
71 | |||
72 | /* for buffering the data sent in PUT */ | ||
73 | typedef struct { | ||
74 | char *buf; | ||
75 | size_t buflen; | ||
76 | off_t pos; | ||
77 | } curlhelp_read_curlbuf; | ||
71 | 78 | ||
72 | /* for parsing the HTTP status line */ | 79 | /* for parsing the HTTP status line */ |
73 | typedef struct { | 80 | typedef struct { |
@@ -115,9 +122,10 @@ char *http_post_data = NULL; | |||
115 | char *http_content_type = NULL; | 122 | char *http_content_type = NULL; |
116 | CURL *curl; | 123 | CURL *curl; |
117 | struct curl_slist *header_list = NULL; | 124 | struct curl_slist *header_list = NULL; |
118 | curlhelp_curlbuf body_buf; | 125 | curlhelp_write_curlbuf body_buf; |
119 | curlhelp_curlbuf header_buf; | 126 | curlhelp_write_curlbuf header_buf; |
120 | curlhelp_statusline status_line; | 127 | curlhelp_statusline status_line; |
128 | curlhelp_read_curlbuf put_buf; | ||
121 | char http_header[DEFAULT_BUFFER_SIZE]; | 129 | char http_header[DEFAULT_BUFFER_SIZE]; |
122 | long code; | 130 | long code; |
123 | long socket_timeout = DEFAULT_SOCKET_TIMEOUT; | 131 | long socket_timeout = DEFAULT_SOCKET_TIMEOUT; |
@@ -155,16 +163,19 @@ int check_http (void); | |||
155 | void print_help (void); | 163 | void print_help (void); |
156 | void print_usage (void); | 164 | void print_usage (void); |
157 | void print_curl_version (void); | 165 | void print_curl_version (void); |
158 | int curlhelp_initbuffer (curlhelp_curlbuf*); | 166 | int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); |
159 | int curlhelp_buffer_callback (void*, size_t , size_t , void*); | 167 | int curlhelp_buffer_write_callback (void*, size_t , size_t , void*); |
160 | void curlhelp_freebuffer (curlhelp_curlbuf*); | 168 | void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); |
169 | int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); | ||
170 | int curlhelp_buffer_read_callback (void *, size_t , size_t , void *); | ||
171 | void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); | ||
161 | 172 | ||
162 | int curlhelp_parse_statusline (const char*, curlhelp_statusline *); | 173 | int curlhelp_parse_statusline (const char*, curlhelp_statusline *); |
163 | void curlhelp_free_statusline (curlhelp_statusline *); | 174 | void curlhelp_free_statusline (curlhelp_statusline *); |
164 | char *perfd_time_ssl (double microsec); | 175 | char *perfd_time_ssl (double microsec); |
165 | char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); | 176 | char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); |
166 | static time_t parse_time_string (const char *string); | 177 | static time_t parse_time_string (const char *string); |
167 | int check_document_dates (const curlhelp_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); | 178 | int check_document_dates (const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); |
168 | 179 | ||
169 | void remove_newlines (char *); | 180 | void remove_newlines (char *); |
170 | void test_file (char *); | 181 | void test_file (char *); |
@@ -251,15 +262,15 @@ check_http (void) | |||
251 | curl_easy_setopt(curl, CURLOPT_STDERR, stdout); | 262 | curl_easy_setopt(curl, CURLOPT_STDERR, stdout); |
252 | 263 | ||
253 | /* initialize buffer for body of the answer */ | 264 | /* initialize buffer for body of the answer */ |
254 | if (curlhelp_initbuffer(&body_buf) < 0) | 265 | if (curlhelp_initwritebuffer(&body_buf) < 0) |
255 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); | 266 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); |
256 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_callback); | 267 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback); |
257 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); | 268 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); |
258 | 269 | ||
259 | /* initialize buffer for header of the answer */ | 270 | /* initialize buffer for header of the answer */ |
260 | if (curlhelp_initbuffer( &header_buf ) < 0) | 271 | if (curlhelp_initwritebuffer( &header_buf ) < 0) |
261 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); | 272 | die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); |
262 | curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_callback); | 273 | curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback); |
263 | curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); | 274 | curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); |
264 | 275 | ||
265 | /* set the error buffer */ | 276 | /* set the error buffer */ |
@@ -282,7 +293,11 @@ check_http (void) | |||
282 | if (!strcmp(http_method, "POST")) | 293 | if (!strcmp(http_method, "POST")) |
283 | curl_easy_setopt (curl, CURLOPT_POST, 1); | 294 | curl_easy_setopt (curl, CURLOPT_POST, 1); |
284 | else if (!strcmp(http_method, "PUT")) | 295 | else if (!strcmp(http_method, "PUT")) |
296 | #if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 12, 1) | ||
297 | curl_easy_setopt (curl, CURLOPT_UPLOAD, 1); | ||
298 | #else | ||
285 | curl_easy_setopt (curl, CURLOPT_PUT, 1); | 299 | curl_easy_setopt (curl, CURLOPT_PUT, 1); |
300 | #endif | ||
286 | else | 301 | else |
287 | curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method); | 302 | curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method); |
288 | } | 303 | } |
@@ -385,12 +400,25 @@ check_http (void) | |||
385 | curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); | 400 | curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); |
386 | 401 | ||
387 | /* either send http POST data (any data, not only POST)*/ | 402 | /* either send http POST data (any data, not only POST)*/ |
388 | if (http_post_data) { | 403 | if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { |
404 | /* set content of payload for POST and PUT */ | ||
389 | if (http_content_type) { | 405 | if (http_content_type) { |
390 | snprintf (http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type); | 406 | snprintf (http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type); |
391 | header_list = curl_slist_append (header_list, http_header); | 407 | header_list = curl_slist_append (header_list, http_header); |
392 | } | 408 | } |
393 | curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data); | 409 | /* NULL indicates "HTTP Continue" in libcurl, provide an empty string |
410 | * in case of no POST/PUT data */ | ||
411 | if (!http_post_data) | ||
412 | http_post_data = ""; | ||
413 | if (!strcmp(http_method, "POST")) { | ||
414 | /* POST method, set payload with CURLOPT_POSTFIELDS */ | ||
415 | curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data); | ||
416 | } else if (!strcmp(http_method, "PUT")) { | ||
417 | curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback); | ||
418 | curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)); | ||
419 | curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf); | ||
420 | curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)); | ||
421 | } | ||
394 | } | 422 | } |
395 | 423 | ||
396 | /* do the request */ | 424 | /* do the request */ |
@@ -472,13 +500,13 @@ check_http (void) | |||
472 | } | 500 | } |
473 | 501 | ||
474 | /* make sure the status line matches the response we are looking for */ | 502 | /* make sure the status line matches the response we are looking for */ |
475 | if (!expected_statuscode(header_buf.buf, server_expect)) { | 503 | if (!expected_statuscode(status_line.first_line, server_expect)) { |
476 | /* TODO: fix first_line being cut off */ | 504 | /* TODO: fix first_line being cut off */ |
477 | if (server_port == HTTP_PORT) | 505 | if (server_port == HTTP_PORT) |
478 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line); | 506 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line); |
479 | else | 507 | else |
480 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line); | 508 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line); |
481 | die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); | 509 | die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); |
482 | } | 510 | } |
483 | 511 | ||
484 | /* TODO: implement -d header tests */ | 512 | /* TODO: implement -d header tests */ |
@@ -604,8 +632,11 @@ check_http (void) | |||
604 | curlhelp_free_statusline(&status_line); | 632 | curlhelp_free_statusline(&status_line); |
605 | curl_easy_cleanup (curl); | 633 | curl_easy_cleanup (curl); |
606 | curl_global_cleanup (); | 634 | curl_global_cleanup (); |
607 | curlhelp_freebuffer(&body_buf); | 635 | curlhelp_freewritebuffer(&body_buf); |
608 | curlhelp_freebuffer(&header_buf); | 636 | curlhelp_freewritebuffer(&header_buf); |
637 | if (!strcmp (http_method, "PUT")) { | ||
638 | curlhelp_freereadbuffer (&put_buf); | ||
639 | } | ||
609 | 640 | ||
610 | return result; | 641 | return result; |
611 | } | 642 | } |
@@ -1250,7 +1281,7 @@ print_curl_version (void) | |||
1250 | } | 1281 | } |
1251 | 1282 | ||
1252 | int | 1283 | int |
1253 | curlhelp_initbuffer (curlhelp_curlbuf *buf) | 1284 | curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) |
1254 | { | 1285 | { |
1255 | buf->bufsize = DEFAULT_BUFFER_SIZE; | 1286 | buf->bufsize = DEFAULT_BUFFER_SIZE; |
1256 | buf->buflen = 0; | 1287 | buf->buflen = 0; |
@@ -1260,9 +1291,9 @@ curlhelp_initbuffer (curlhelp_curlbuf *buf) | |||
1260 | } | 1291 | } |
1261 | 1292 | ||
1262 | int | 1293 | int |
1263 | curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream) | 1294 | curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream) |
1264 | { | 1295 | { |
1265 | curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream; | 1296 | curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream; |
1266 | 1297 | ||
1267 | while (buf->bufsize < buf->buflen + size * nmemb + 1) { | 1298 | while (buf->bufsize < buf->buflen + size * nmemb + 1) { |
1268 | buf->bufsize *= buf->bufsize * 2; | 1299 | buf->bufsize *= buf->bufsize * 2; |
@@ -1277,8 +1308,39 @@ curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream) | |||
1277 | return (int)(size * nmemb); | 1308 | return (int)(size * nmemb); |
1278 | } | 1309 | } |
1279 | 1310 | ||
1311 | int | ||
1312 | curlhelp_buffer_read_callback (void *buffer, size_t size, size_t nmemb, void *stream) | ||
1313 | { | ||
1314 | curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream; | ||
1315 | |||
1316 | size_t n = min (nmemb * size, buf->buflen - buf->pos); | ||
1317 | |||
1318 | memcpy (buffer, buf->buf + buf->pos, n); | ||
1319 | buf->pos += n; | ||
1320 | |||
1321 | return (int)n; | ||
1322 | } | ||
1323 | |||
1280 | void | 1324 | void |
1281 | curlhelp_freebuffer (curlhelp_curlbuf *buf) | 1325 | curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) |
1326 | { | ||
1327 | free (buf->buf); | ||
1328 | buf->buf = NULL; | ||
1329 | } | ||
1330 | |||
1331 | int | ||
1332 | curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) | ||
1333 | { | ||
1334 | buf->buflen = datalen; | ||
1335 | buf->buf = (char *)malloc ((size_t)buf->buflen); | ||
1336 | if (buf->buf == NULL) return -1; | ||
1337 | memcpy (buf->buf, data, datalen); | ||
1338 | buf->pos = 0; | ||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | void | ||
1343 | curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) | ||
1282 | { | 1344 | { |
1283 | free (buf->buf); | 1345 | free (buf->buf); |
1284 | buf->buf = NULL; | 1346 | buf->buf = NULL; |
@@ -1328,6 +1390,7 @@ curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) | |||
1328 | size_t first_line_len; | 1390 | size_t first_line_len; |
1329 | char *pp; | 1391 | char *pp; |
1330 | const char *start; | 1392 | const char *start; |
1393 | char *first_line_buf; | ||
1331 | 1394 | ||
1332 | /* find last start of a new header */ | 1395 | /* find last start of a new header */ |
1333 | start = strrstr2 (buf, "\r\nHTTP"); | 1396 | start = strrstr2 (buf, "\r\nHTTP"); |
@@ -1344,47 +1407,49 @@ curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) | |||
1344 | if (status_line->first_line == NULL) return -1; | 1407 | if (status_line->first_line == NULL) return -1; |
1345 | memcpy (status_line->first_line, buf, first_line_len); | 1408 | memcpy (status_line->first_line, buf, first_line_len); |
1346 | status_line->first_line[first_line_len] = '\0'; | 1409 | status_line->first_line[first_line_len] = '\0'; |
1410 | first_line_buf = strdup( status_line->first_line ); | ||
1347 | 1411 | ||
1348 | /* protocol and version: "HTTP/x.x" SP */ | 1412 | /* protocol and version: "HTTP/x.x" SP */ |
1349 | 1413 | ||
1350 | p = strtok(status_line->first_line, "/"); | 1414 | p = strtok(first_line_buf, "/"); |
1351 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 1415 | if( p == NULL ) { free( first_line_buf ); return -1; } |
1352 | if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; } | 1416 | if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; } |
1353 | 1417 | ||
1354 | p = strtok( NULL, "." ); | 1418 | p = strtok( NULL, "." ); |
1355 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 1419 | if( p == NULL ) { free( first_line_buf ); return -1; } |
1356 | status_line->http_major = (int)strtol( p, &pp, 10 ); | 1420 | status_line->http_major = (int)strtol( p, &pp, 10 ); |
1357 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 1421 | if( *pp != '\0' ) { free( first_line_buf ); return -1; } |
1358 | 1422 | ||
1359 | p = strtok( NULL, " " ); | 1423 | p = strtok( NULL, " " ); |
1360 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 1424 | if( p == NULL ) { free( first_line_buf ); return -1; } |
1361 | status_line->http_minor = (int)strtol( p, &pp, 10 ); | 1425 | status_line->http_minor = (int)strtol( p, &pp, 10 ); |
1362 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 1426 | if( *pp != '\0' ) { free( first_line_buf ); return -1; } |
1363 | 1427 | ||
1364 | /* status code: "404" or "404.1", then SP */ | 1428 | /* status code: "404" or "404.1", then SP */ |
1365 | 1429 | ||
1366 | p = strtok( NULL, " ." ); | 1430 | p = strtok( NULL, " ." ); |
1367 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 1431 | if( p == NULL ) { free( first_line_buf ); return -1; } |
1368 | if( strchr( p, '.' ) != NULL ) { | 1432 | if( strchr( p, '.' ) != NULL ) { |
1369 | char *ppp; | 1433 | char *ppp; |
1370 | ppp = strtok( p, "." ); | 1434 | ppp = strtok( p, "." ); |
1371 | status_line->http_code = (int)strtol( ppp, &pp, 10 ); | 1435 | status_line->http_code = (int)strtol( ppp, &pp, 10 ); |
1372 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 1436 | if( *pp != '\0' ) { free( first_line_buf ); return -1; } |
1373 | 1437 | ||
1374 | ppp = strtok( NULL, "" ); | 1438 | ppp = strtok( NULL, "" ); |
1375 | status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); | 1439 | status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); |
1376 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 1440 | if( *pp != '\0' ) { free( first_line_buf ); return -1; } |
1377 | } else { | 1441 | } else { |
1378 | status_line->http_code = (int)strtol( p, &pp, 10 ); | 1442 | status_line->http_code = (int)strtol( p, &pp, 10 ); |
1379 | status_line->http_subcode = -1; | 1443 | status_line->http_subcode = -1; |
1380 | if( *pp != '\0' ) { free( status_line->first_line ); return -1; } | 1444 | if( *pp != '\0' ) { free( first_line_buf ); return -1; } |
1381 | } | 1445 | } |
1382 | 1446 | ||
1383 | /* Human readable message: "Not Found" CRLF */ | 1447 | /* Human readable message: "Not Found" CRLF */ |
1384 | 1448 | ||
1449 | free( first_line_buf ); | ||
1385 | p = strtok( NULL, "" ); | 1450 | p = strtok( NULL, "" ); |
1386 | if( p == NULL ) { free( status_line->first_line ); return -1; } | 1451 | if( p == NULL ) { free( status_line->first_line ); return -1; } |
1387 | status_line->msg = p; | 1452 | status_line->msg = status_line->first_line + ( p - first_line_buf ); |
1388 | 1453 | ||
1389 | return 0; | 1454 | return 0; |
1390 | } | 1455 | } |
@@ -1515,7 +1580,7 @@ parse_time_string (const char *string) | |||
1515 | } | 1580 | } |
1516 | 1581 | ||
1517 | int | 1582 | int |
1518 | check_document_dates (const curlhelp_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) | 1583 | check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) |
1519 | { | 1584 | { |
1520 | char *server_date = NULL; | 1585 | char *server_date = NULL; |
1521 | char *document_date = NULL; | 1586 | char *document_date = NULL; |