mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-06-09 16:50:01 -04:00
some work on certificate checking for non-OpenSSL libraries
This commit is contained in:
parent
cee5f2777d
commit
55e8d89b0a
1 changed files with 77 additions and 11 deletions
|
|
@ -149,6 +149,10 @@ int onredirect = STATE_OK;
|
|||
int use_ssl = FALSE;
|
||||
int use_sni = TRUE;
|
||||
int check_cert = FALSE;
|
||||
union {
|
||||
struct curl_slist* to_info;
|
||||
struct curl_certinfo* to_certinfo;
|
||||
} cert_ptr;
|
||||
int ssl_version = CURL_SSLVERSION_DEFAULT;
|
||||
char *client_cert = NULL;
|
||||
char *client_privkey = NULL;
|
||||
|
|
@ -212,6 +216,10 @@ main (int argc, char **argv)
|
|||
|
||||
int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||
{
|
||||
/* TODO: we get all certificates of the chain, so which ones
|
||||
* should we test?
|
||||
* TODO: is the last certificate always the server certificate?
|
||||
*/
|
||||
cert = X509_STORE_CTX_get_current_cert(x509_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -330,6 +338,8 @@ check_http (void)
|
|||
/* set HTTP headers */
|
||||
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
|
||||
|
||||
#ifdef LIBCURL_FEATURE_SSL
|
||||
|
||||
/* set SSL version, warn about unsecure or unsupported versions */
|
||||
if (use_ssl) {
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
|
||||
|
|
@ -344,7 +354,7 @@ check_http (void)
|
|||
/* per default if we have a CA verify both the peer and the
|
||||
* hostname in the certificate, can be switched off later */
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
|
||||
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2), "CURLOPT_SSL_VERIFYPEER");
|
||||
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
|
||||
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
|
||||
} else {
|
||||
/* backward-compatible behaviour, be tolerant in checks
|
||||
|
|
@ -354,11 +364,28 @@ check_http (void)
|
|||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER");
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST");
|
||||
}
|
||||
|
||||
/* set callback to extract certificate */
|
||||
if(check_cert) {
|
||||
|
||||
/* try hard to get a stack of certificates to verify against */
|
||||
if (check_cert)
|
||||
#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
|
||||
/* inform curl to report back certificates (this works for OpenSSL, NSS at least) */
|
||||
curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L);
|
||||
#ifdef USE_OPENSSL
|
||||
/* set callback to extract certificate with OpenSSL context function (works with
|
||||
* OpenSSL only!)
|
||||
*/
|
||||
handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
|
||||
}
|
||||
#endif /* USE_OPENSSL */
|
||||
#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
|
||||
#ifdef USE_OPENSSL
|
||||
/* Too old curl library, hope we have OpenSSL */
|
||||
handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
|
||||
#else
|
||||
die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library)\n");
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
|
||||
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* set default or user-given user agent identification */
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT");
|
||||
|
|
@ -402,8 +429,10 @@ check_http (void)
|
|||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
|
||||
else if (address_family == AF_INET)
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
|
||||
#ifdef USE_IPV6
|
||||
else if (address_family == AF_INET6)
|
||||
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
|
||||
#endif
|
||||
|
||||
/* either send http POST data (any data, not only POST)*/
|
||||
if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) {
|
||||
|
|
@ -444,14 +473,41 @@ check_http (void)
|
|||
}
|
||||
|
||||
/* certificate checks */
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef LIBCURL_FEATURE_SSL
|
||||
if (use_ssl == TRUE) {
|
||||
if (check_cert == TRUE) {
|
||||
if (verbose >= 2)
|
||||
printf ("**** REQUEST CERTIFICATES ****\n");
|
||||
cert_ptr.to_info = NULL;
|
||||
res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
|
||||
if (!res && cert_ptr.to_info) {
|
||||
int i;
|
||||
for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) {
|
||||
struct curl_slist *slist;
|
||||
for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
|
||||
if (verbose >= 2)
|
||||
printf ("%d ** %s\n", i, slist->data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"),
|
||||
res, curl_easy_strerror(res));
|
||||
die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
|
||||
}
|
||||
if (verbose >= 2)
|
||||
printf ("**** REQUEST CERTIFICATES ****\n");
|
||||
/* check certificate with OpenSSL functions, curl has been built against OpenSSL
|
||||
* and we actually have OpenSSL in the monitoring tools
|
||||
*/
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef USE_OPENSSL
|
||||
result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
|
||||
return(result);
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* HAVE_SSL */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
#endif /* LIBCURL_FEATURE_SSL */
|
||||
|
||||
/* we got the data and we executed the request in a given time, so we can append
|
||||
* performance data to the answer always
|
||||
|
|
@ -481,7 +537,6 @@ check_http (void)
|
|||
(int)body_buf.buflen);
|
||||
}
|
||||
|
||||
|
||||
/* return a CRITICAL status if we couldn't read any data */
|
||||
if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
|
||||
die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
|
||||
|
|
@ -605,6 +660,16 @@ check_http (void)
|
|||
/* make sure the page is of an appropriate size
|
||||
* TODO: as far I can tell check_http gets the full size of header and
|
||||
* if -N is not given header+body. Does this make sense?
|
||||
*
|
||||
* TODO: check_http.c had a get_length function, the question is really
|
||||
* here what to use? the raw data size of the header_buf, the value of
|
||||
* Content-Length, both and warn if they differ? Should the length be
|
||||
* header+body or only body?
|
||||
*
|
||||
* One possible policy:
|
||||
* - use header_buf.buflen (warning, if it mismatches to the Content-Length value
|
||||
* - if -N (nobody) is given, use Content-Length only and hope the server set
|
||||
* the value correcly
|
||||
*/
|
||||
page_len = header_buf.buflen + body_buf.buflen;
|
||||
if ((max_page_len > 0) && (page_len > max_page_len)) {
|
||||
|
|
@ -637,8 +702,8 @@ check_http (void)
|
|||
curlhelp_free_statusline(&status_line);
|
||||
curl_easy_cleanup (curl);
|
||||
curl_global_cleanup ();
|
||||
curlhelp_freewritebuffer(&body_buf);
|
||||
curlhelp_freewritebuffer(&header_buf);
|
||||
curlhelp_freewritebuffer (&body_buf);
|
||||
curlhelp_freewritebuffer (&header_buf);
|
||||
if (!strcmp (http_method, "PUT")) {
|
||||
curlhelp_freereadbuffer (&put_buf);
|
||||
}
|
||||
|
|
@ -1493,6 +1558,7 @@ get_header_value (const struct phr_header* headers, const size_t nof_headers, co
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: use CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); here */
|
||||
static time_t
|
||||
parse_time_string (const char *string)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue