File: 16_check_curl_openssl_error

package info (click to toggle)
monitoring-plugins 2.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 11,704 kB
  • sloc: ansic: 76,177; sh: 13,717; perl: 7,655; makefile: 489
file content (115 lines) | stat: -rw-r--r-- 5,052 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
From 528e92c180148703ee2cb90d7291f4edbfc270d4 Mon Sep 17 00:00:00 2001
From: Sven Nierlein <sven@consol.de>
Date: Wed, 9 Oct 2024 09:50:39 +0200
Subject: [PATCH] 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.
---
 plugins/check_curl.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 7f45b5a79..d3bddacd2 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 */