From 3b960442485b965d853205bddeaa7f6a6b03253e Mon Sep 17 00:00:00 2001 From: Sven Nierlein Date: Wed, 9 Oct 2024 09:50:39 +0200 Subject: fix check_curl: OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 using check_curl on a probably embedded device responding as 'Server: GoAhead-Webs' %> check_curl -H ... -S -vvv > GET / HTTP/1.1 Host: ... User-Agent: check_curl/v2.4.0 (monitoring-plugins 2.4.0, libcurl/7.76.1 OpenSSL/3.0.7 zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.1 (+libidn2/2.3.0) libssh/0.10.4/openssl/zlib nghttp2/1.43.0) Accept: */* Connection: close * Mark bundle as not supporting multiuse * HTTP 1.0, assume close after body < HTTP/1.0 302 Redirect < Server: GoAhead-Webs < Date: Tue Mar 26 17:57:16 2019 < Cache-Control: no-cache, no-store, must-revalidate,private < Pragma: no-cache < Expires: 0 < Content-Type: text/html < X-Frame-Options: sameorigin < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < Location: https://... < * OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 * Closing connection 0 reading the discussion on https://github.com/openssl/openssl/discussions/22690 suggest to set the option SSL_OP_IGNORE_UNEXPECTED_EOF which makes check_curl behave like check_http at this point. Since this is a rather new flag, fencing it in ifdefs. And since there can only be one ssl ctx function, we need to move both tasks into one function. diff --git a/plugins/check_curl.c b/plugins/check_curl.c index 7f45b5a..d3bddac 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c @@ -214,6 +214,7 @@ char *client_privkey = NULL; char *ca_cert = NULL; bool verify_peer_and_host = false; bool is_openssl_callback = false; +bool add_sslctx_verify_fun = false; #if defined(HAVE_SSL) && defined(USE_OPENSSL) X509 *cert = NULL; #endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ @@ -299,7 +300,7 @@ main (int argc, char **argv) int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) { - (void) preverify_ok; + (void) preverify_ok; /* TODO: we get all certificates of the chain, so which ones * should we test? * TODO: is the last certificate always the server certificate? @@ -324,9 +325,18 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) { - (void) curl; // ignore unused parameter - (void) parm; // ignore unused parameter - SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); + (void) curl; // ignore unused parameter + (void) parm; // ignore unused parameter + if(add_sslctx_verify_fun) { + SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); + } + + // workaround for issue: + // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 + // see discussion https://github.com/openssl/openssl/discussions/22690 +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF + SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF); +#endif return CURLE_OK; } @@ -678,9 +688,8 @@ check_http (void) * OpenSSL-style libraries only!) */ #ifdef USE_OPENSSL /* libcurl and monitoring plugins built with OpenSSL, good */ - handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); + add_sslctx_verify_fun = true; is_openssl_callback = true; -#else /* USE_OPENSSL */ #endif /* USE_OPENSSL */ /* libcurl is built with OpenSSL, monitoring plugins, so falling * back to manually extracting certificate information */ @@ -713,12 +722,18 @@ check_http (void) #else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) - handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); + add_sslctx_verify_fun = true; else 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"); #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ } +#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */ + // ssl ctx function is not available with all ssl backends + if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION) + handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); +#endif + #endif /* LIBCURL_FEATURE_SSL */ /* set default or user-given user agent identification */ -- cgit v0.10-9-g596f