diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/check_curl.c | 186 |
1 files changed, 147 insertions, 39 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index b0026378..d3f3930f 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c | |||
| @@ -91,6 +91,14 @@ typedef struct { | |||
| 91 | char *first_line; /* a copy of the first line */ | 91 | char *first_line; /* a copy of the first line */ |
| 92 | } curlhelp_statusline; | 92 | } curlhelp_statusline; |
| 93 | 93 | ||
| 94 | typedef enum curlhelp_ssl_library { | ||
| 95 | CURLHELP_SSL_LIBRARY_UNKNOWN, | ||
| 96 | CURLHELP_SSL_LIBRARY_OPENSSL, | ||
| 97 | CURLHELP_SSL_LIBRARY_LIBRESSL, | ||
| 98 | CURLHELP_SSL_LIBRARY_GNUTLS, | ||
| 99 | CURLHELP_SSL_LIBRARY_NSS | ||
| 100 | } curlhelp_ssl_library; | ||
| 101 | |||
| 94 | enum { | 102 | enum { |
| 95 | REGS = 2, | 103 | REGS = 2, |
| 96 | MAX_RE_SIZE = 256 | 104 | MAX_RE_SIZE = 256 |
| @@ -160,12 +168,14 @@ int ssl_version = CURL_SSLVERSION_DEFAULT; | |||
| 160 | char *client_cert = NULL; | 168 | char *client_cert = NULL; |
| 161 | char *client_privkey = NULL; | 169 | char *client_privkey = NULL; |
| 162 | char *ca_cert = NULL; | 170 | char *ca_cert = NULL; |
| 171 | int is_openssl_callback = FALSE; | ||
| 163 | #ifdef HAVE_SSL | 172 | #ifdef HAVE_SSL |
| 164 | X509 *cert = NULL; | 173 | X509 *cert = NULL; |
| 165 | #endif | 174 | #endif |
| 166 | int no_body = FALSE; | 175 | int no_body = FALSE; |
| 167 | int maximum_age = -1; | 176 | int maximum_age = -1; |
| 168 | int address_family = AF_UNSPEC; | 177 | int address_family = AF_UNSPEC; |
| 178 | curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; | ||
| 169 | 179 | ||
| 170 | int process_arguments (int, char**); | 180 | int process_arguments (int, char**); |
| 171 | void handle_curl_option_return_code (CURLcode res, const char* option); | 181 | void handle_curl_option_return_code (CURLcode res, const char* option); |
| @@ -179,6 +189,8 @@ void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); | |||
| 179 | int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); | 189 | int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); |
| 180 | int curlhelp_buffer_read_callback (void *, size_t , size_t , void *); | 190 | int curlhelp_buffer_read_callback (void *, size_t , size_t , void *); |
| 181 | void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); | 191 | void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); |
| 192 | curlhelp_ssl_library curlhelp_get_ssl_library (CURL*); | ||
| 193 | const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); | ||
| 182 | 194 | ||
| 183 | int curlhelp_parse_statusline (const char*, curlhelp_statusline *); | 195 | int curlhelp_parse_statusline (const char*, curlhelp_statusline *); |
| 184 | void curlhelp_free_statusline (curlhelp_statusline *); | 196 | void curlhelp_free_statusline (curlhelp_statusline *); |
| @@ -368,25 +380,59 @@ check_http (void) | |||
| 368 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER"); | 380 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER"); |
| 369 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST"); | 381 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST"); |
| 370 | } | 382 | } |
| 383 | |||
| 384 | /* detect SSL library used by libcurl */ | ||
| 385 | ssl_library = curlhelp_get_ssl_library (curl); | ||
| 371 | 386 | ||
| 372 | /* try hard to get a stack of certificates to verify against */ | 387 | /* try hard to get a stack of certificates to verify against */ |
| 373 | if (check_cert) | 388 | if (check_cert) |
| 374 | #if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) | 389 | #if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) |
| 375 | /* inform curl to report back certificates (this works for OpenSSL, NSS at least) */ | 390 | /* inform curl to report back certificates */ |
| 376 | curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L); | 391 | switch (ssl_library) { |
| 377 | #ifdef LIBCURL_USES_OPENSSL | 392 | case CURLHELP_SSL_LIBRARY_OPENSSL: |
| 378 | /* set callback to extract certificate with OpenSSL context function (works with | 393 | case CURLHELP_SSL_LIBRARY_LIBRESSL: |
| 379 | * OpenSSL only!) | 394 | /* set callback to extract certificate with OpenSSL context function (works with |
| 380 | */ | 395 | * OpenSSL-style libraries only!) */ |
| 381 | handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); | 396 | #ifdef USE_OPENSSL |
| 397 | /* libcurl and monitoring plugins built with OpenSSL, good */ | ||
| 398 | handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); | ||
| 399 | is_openssl_callback = TRUE; | ||
| 400 | #else /* USE_OPENSSL */ | ||
| 382 | #endif /* USE_OPENSSL */ | 401 | #endif /* USE_OPENSSL */ |
| 402 | /* libcurl is built with OpenSSL, monitoring plugins, so falling | ||
| 403 | * back to manually extracting certificate information */ | ||
| 404 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); | ||
| 405 | break; | ||
| 406 | |||
| 407 | case CURLHELP_SSL_LIBRARY_NSS: | ||
| 408 | #if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) | ||
| 409 | /* NSS: support for CERTINFO is implemented since 7.34.0 */ | ||
| 410 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); | ||
| 411 | #else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ | ||
| 412 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); | ||
| 413 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ | ||
| 414 | break; | ||
| 415 | |||
| 416 | case CURLHELP_SSL_LIBRARY_GNUTLS: | ||
| 417 | #if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) | ||
| 418 | /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ | ||
| 419 | handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); | ||
| 420 | #else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ | ||
| 421 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); | ||
| 422 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ | ||
| 423 | break; | ||
| 424 | |||
| 425 | case CURLHELP_SSL_LIBRARY_UNKNOWN: | ||
| 426 | default: | ||
| 427 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); | ||
| 428 | break; | ||
| 429 | } | ||
| 383 | #else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ | 430 | #else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ |
| 384 | #ifdef LIBCURL_USES_OPENSSL | 431 | /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ |
| 385 | /* Too old curl library, hope we have OpenSSL */ | 432 | if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) |
| 386 | handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); | 433 | handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); |
| 387 | #else | 434 | else |
| 388 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library)\n"); | 435 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n"); |
| 389 | #endif /* LIBCURL_USES_OPENSSL */ | ||
| 390 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ | 436 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ |
| 391 | 437 | ||
| 392 | #endif /* LIBCURL_FEATURE_SSL */ | 438 | #endif /* LIBCURL_FEATURE_SSL */ |
| @@ -480,35 +526,44 @@ check_http (void) | |||
| 480 | #ifdef LIBCURL_FEATURE_SSL | 526 | #ifdef LIBCURL_FEATURE_SSL |
| 481 | if (use_ssl == TRUE) { | 527 | if (use_ssl == TRUE) { |
| 482 | if (check_cert == TRUE) { | 528 | if (check_cert == TRUE) { |
| 483 | if (verbose >= 2) | 529 | if (is_openssl_callback) { |
| 484 | printf ("**** REQUEST CERTIFICATES ****\n"); | 530 | #ifdef HAVE_SSL |
| 485 | cert_ptr.to_info = NULL; | 531 | /* check certificate with OpenSSL functions, curl has been built against OpenSSL |
| 486 | res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); | 532 | * and we actually have OpenSSL in the monitoring tools |
| 487 | if (!res && cert_ptr.to_info) { | 533 | */ |
| 488 | int i; | 534 | result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); |
| 489 | for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { | 535 | return result; |
| 490 | struct curl_slist *slist; | 536 | #else /* HAVE_SSL */ |
| 491 | for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { | 537 | die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); |
| 492 | if (verbose >= 2) | 538 | #endif /* HAVE_SSL */ |
| 493 | printf ("%d ** %s\n", i, slist->data); | 539 | } else { |
| 540 | /* going with the libcurl CURLINFO data */ | ||
| 541 | if (verbose >= 2) | ||
| 542 | printf ("**** REQUEST CERTIFICATES ****\n"); | ||
| 543 | cert_ptr.to_info = NULL; | ||
| 544 | res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); | ||
| 545 | if (!res && cert_ptr.to_info) { | ||
| 546 | int i; | ||
| 547 | for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { | ||
| 548 | struct curl_slist *slist; | ||
| 549 | for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { | ||
| 550 | if (verbose >= 2) | ||
| 551 | printf ("%d ** %s\n", i, slist->data); | ||
| 552 | } | ||
| 494 | } | 553 | } |
| 554 | } else { | ||
| 555 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), | ||
| 556 | res, curl_easy_strerror(res)); | ||
| 557 | die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
| 495 | } | 558 | } |
| 496 | } else { | 559 | if (verbose >= 2) |
| 497 | snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), | 560 | printf ("**** REQUEST CERTIFICATES ****\n"); |
| 498 | res, curl_easy_strerror(res)); | 561 | // TODO: either convert data to X509 certs we can check with np_net_ssl_check_certificate |
| 499 | die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | 562 | // or do something on our own.. |
| 563 | //~ result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); | ||
| 564 | //~ return result; | ||
| 565 | die (STATE_UNKNOWN, "HTTP UNKNOWN - CERTINFO certificate checks not implemented yet\n"); | ||
| 500 | } | 566 | } |
| 501 | if (verbose >= 2) | ||
| 502 | printf ("**** REQUEST CERTIFICATES ****\n"); | ||
| 503 | /* check certificate with OpenSSL functions, curl has been built against OpenSSL | ||
| 504 | * and we actually have OpenSSL in the monitoring tools | ||
| 505 | */ | ||
| 506 | #ifdef HAVE_SSL | ||
| 507 | #ifdef LIBCURL_USES_OPENSSL | ||
| 508 | result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); | ||
| 509 | #endif /* LIBCURL_USES_OPENSSL */ | ||
| 510 | #endif /* HAVE_SSL */ | ||
| 511 | return result; | ||
| 512 | } | 567 | } |
| 513 | } | 568 | } |
| 514 | #endif /* LIBCURL_FEATURE_SSL */ | 569 | #endif /* LIBCURL_FEATURE_SSL */ |
| @@ -1617,3 +1672,56 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA | |||
| 1617 | 1672 | ||
| 1618 | return date_result; | 1673 | return date_result; |
| 1619 | } | 1674 | } |
| 1675 | |||
| 1676 | /* TODO: is there a better way in libcurl to check for the SSL library? */ | ||
| 1677 | curlhelp_ssl_library | ||
| 1678 | curlhelp_get_ssl_library (CURL* curl) | ||
| 1679 | { | ||
| 1680 | curl_version_info_data* version_data; | ||
| 1681 | char *ssl_version; | ||
| 1682 | char *library; | ||
| 1683 | curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; | ||
| 1684 | |||
| 1685 | version_data = curl_version_info (CURLVERSION_NOW); | ||
| 1686 | if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; | ||
| 1687 | |||
| 1688 | ssl_version = strdup (version_data->ssl_version); | ||
| 1689 | if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; | ||
| 1690 | |||
| 1691 | library = strtok (ssl_version, "/"); | ||
| 1692 | if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; | ||
| 1693 | |||
| 1694 | if (strcmp (library, "OpenSSL") == 0) | ||
| 1695 | ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; | ||
| 1696 | else if (strcmp (library, "LibreSSL") == 0) | ||
| 1697 | ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; | ||
| 1698 | else if (strcmp (library, "GnuTLS") == 0) | ||
| 1699 | ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; | ||
| 1700 | else if (strcmp (library, "NSS") == 0) | ||
| 1701 | ssl_library = CURLHELP_SSL_LIBRARY_NSS; | ||
| 1702 | |||
| 1703 | if (verbose >= 2) | ||
| 1704 | printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); | ||
| 1705 | |||
| 1706 | free (ssl_version); | ||
| 1707 | |||
| 1708 | return ssl_library; | ||
| 1709 | } | ||
| 1710 | |||
| 1711 | const char* | ||
| 1712 | curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) | ||
| 1713 | { | ||
| 1714 | switch (ssl_library) { | ||
| 1715 | case CURLHELP_SSL_LIBRARY_OPENSSL: | ||
| 1716 | return "OpenSSL"; | ||
| 1717 | case CURLHELP_SSL_LIBRARY_LIBRESSL: | ||
| 1718 | return "LibreSSL"; | ||
| 1719 | case CURLHELP_SSL_LIBRARY_GNUTLS: | ||
| 1720 | return "GnuTLS"; | ||
| 1721 | case CURLHELP_SSL_LIBRARY_NSS: | ||
| 1722 | return "NSS"; | ||
| 1723 | case CURLHELP_SSL_LIBRARY_UNKNOWN: | ||
| 1724 | default: | ||
| 1725 | return "unknown"; | ||
| 1726 | } | ||
| 1727 | } | ||
