From bec4ca6f3a1db8306bb6ec5cdff7a399e7e8f630 Mon Sep 17 00:00:00 2001 From: Gang Ji Date: Thu, 20 Mar 2025 15:17:51 +0800 Subject: [PATCH 1/4] CA-404460: Expose Stunnel_verify_error for mismatched certificate Xapi uses stunnel to connect to remote peer and exposes certificate verify error by parsing stunnel logs. And when connect with a mismatched certificate, the log from stunnel would be: stunnel 5.60 on x86_64-koji-linux-gnu platform Compiled/running with OpenSSL 3.0.9 30 May 2023 Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,OCSP,SNI Auth:LIBWRAP Reading configuration from descriptor 8 UTF-8 byte order mark not detected FIPS mode disabled Configuration successful Service [stunnel] accepted connection from unnamed socket s_connect: connected 10.63.96.116:443 Service [stunnel] connected remote server from 10.63.97.76:34138 CERT: Pre-verification error: self-signed certificate Rejected by CERT at depth=0: CN=10.63.96.116 SSL_connect: ssl/statem/statem_clnt.c:1889: error:0A000086:SSL routines::certificate verify failed Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket This commit fixes the exposing of Stunnel_verify_error by checking "certificate verify failed" in the log, and expose it with reason "0A000086:SSL routines::certificate verify failed". We can find that the log "VERIFY ERROR" is not print by stunnel 5.60, which is the version of stunnel used in XS now, but it indeed was printed before: 20d6d2faf740ee5eb9b13752b076ee583fec94d8:src/verify.c: s_log(LOG_WARNING, "VERIFY ERROR: depth=%d, error=%s: %s", [gangj@xenrt10715872 stunnel]$ git branch --contains 20d6d2faf740ee5eb9b13752b076ee583fec94d8 master * private/gangj/stunnel-5.60 While we can find the log "certificate verify failed" which comes from openssl library: https://github.com/openssl/openssl/blob/openssl-3.0.9/ssl/ssl_err.c {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERTIFICATE_VERIFY_FAILED), "certificate verify failed"}, Signed-off-by: Gang Ji --- ocaml/libs/stunnel/stunnel.ml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ocaml/libs/stunnel/stunnel.ml b/ocaml/libs/stunnel/stunnel.ml index 93b990d8449..e6732a0c0d7 100644 --- a/ocaml/libs/stunnel/stunnel.ml +++ b/ocaml/libs/stunnel/stunnel.ml @@ -483,12 +483,17 @@ let check_verify_error line = let split_1 c s = match Astring.String.cut ~sep:c s with Some (x, _) -> x | None -> s in - if Astring.String.is_infix ~affix:"VERIFY ERROR: " line then - match Astring.String.find_sub ~sub:"error=" line with + (* When verified with a mismatched certificate, one line of log from stunnel + * would look like: + SSL_connect: ssl/statem/statem_clnt.c:1889: error:0A000086:SSL routines::certificate verify failed + * in this case, Stunnel_verify_error can be raised with detailed error as + * reason if it can found in the log *) + if Astring.String.is_infix ~affix:"certificate verify failed" line then + match Astring.String.find_sub ~sub:"error:" line with | Some e -> raise (Stunnel_verify_error - (split_1 "," (sub_after (e + String.length "error=") line)) + (split_1 "," (sub_after (e + String.length "error:") line)) ) | None -> raise (Stunnel_verify_error "") From 659284ed81115ed4b364d7a82c31ebda8201bde3 Mon Sep 17 00:00:00 2001 From: Gang Ji Date: Thu, 20 Mar 2025 15:34:25 +0800 Subject: [PATCH 2/4] CA-404460: Expose Stunnel_verify_error for corrupted certificate Xapi uses stunnel to connect to remote peer and exposes certificate verify error by parsing stunnel logs. And when connecting with a corrupted certificate, the log from stunnel would be: Initializing inetd mode configuration Clients allowed=500 stunnel 5.60 on x86_64-koji-linux-gnu platform Compiled/running with OpenSSL 3.0.9 30 May 2023 Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,OCSP,SNI Auth:LIBWRAP errno: (*__errno_location ()) Initializing inetd mode configuration Reading configuration from descriptor 8 UTF-8 byte order mark not detected FIPS mode disabled No PRNG seeding was required stunnel default security level set: 2 Ciphers: ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256 TLSv1.3 ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 TLS options: 0x02100000 (+0x00000000, -0x00000000) Session resumption enabled No certificate or private key specified error queue: crypto/x509/by_file.c:234: error:05880009:x509 certificate routines::PEM lib error queue: crypto/pem/pem_info.c:169: error:0488000D:PEM routines::ASN1 lib error queue: crypto/asn1/tasn_dec.c:349: error:0688010A:asn1 encoding routines::nested asn1 error error queue: crypto/asn1/tasn_dec.c:1178: error:06800066:asn1 encoding routines::bad object header SSL_CTX_load_verify_locations: crypto/asn1/asn1_lib.c:95: error:0680009B:asn1 encoding routines::too long Inetd mode: Failed to initialize TLS context Configuration failed Deallocating temporary section defaults This commit exposes Stunnel_verify_error by checking "No certificate or private key specified" in the log, and expose it with reason "The specified certificate is corrupt". And the log "No certificate or private key specified" comes from stunnel: https://github.com/mtrojnar/stunnel/blob/9f291d5ba27f0fa45353ae87cf9ac5f05401b012/src/ctx.c#L690 /* load the certificate and private key */ if(!section->cert || !section->key) { s_log(LOG_DEBUG, "No certificate or private key specified"); return 0; /* OK */ } Signed-off-by: Gang Ji --- ocaml/libs/stunnel/stunnel.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ocaml/libs/stunnel/stunnel.ml b/ocaml/libs/stunnel/stunnel.ml index e6732a0c0d7..c9b18f9b4d1 100644 --- a/ocaml/libs/stunnel/stunnel.ml +++ b/ocaml/libs/stunnel/stunnel.ml @@ -497,6 +497,11 @@ let check_verify_error line = ) | None -> raise (Stunnel_verify_error "") + else if + Astring.String.is_infix ~affix:"No certificate or private key specified" + line + then + raise (Stunnel_verify_error "The specified certificate is corrupt") else () From 95d888eaa9736f9daf7f3dde9a342b5dd33ee5b5 Mon Sep 17 00:00:00 2001 From: Gang Ji Date: Thu, 20 Mar 2025 16:00:22 +0800 Subject: [PATCH 3/4] CA-404460: Fix the exposing of Stunnel_verify_error in check_error There are 4 error logs are checked in check_error: "Connection refused" "No host resolved" "No route to host" "Invalid argument" We can indeed find the logging in stunnel for 2 of them in stunnel 5.60, which is the version used in XS now: [gangj@xenrt10715872 stunnel]$ git grep -C 1 -wn "Connection refused" src/log.c-493- case 10061: src/log.c:494: return "Connection refused (WSAECONNREFUSED)"; src/log.c-495- case 10062: -- src/protocol.c-240- s_log(LOG_ERR, src/protocol.c:241: "SOCKS5 request failed: Connection refused"); src/protocol.c-242- break; [gangj@xenrt10715872 stunnel]$ [gangj@xenrt10715872 stunnel]$ git grep -C 1 -wn "Invalid argument" src/log.c-437- case 10022: src/log.c:438: return "Invalid argument (WSAEINVAL)"; src/log.c-439- case 10024: While the other 2 are not found: [gangj@xenrt10715872 stunnel]$ git grep -C 1 -wn "No host resolved" [gangj@xenrt10715872 stunnel]$ [gangj@xenrt10715872 stunnel]$ git grep -C 1 -wn "No route to host" [gangj@xenrt10715872 stunnel]$ But seems "No host resolved" was in the history of stunnel: ddef8f192ecfe195610000c6f6272f6b77b97e53:src/client.c: s_log(LOG_ERR, "No host resolved"); [gangj@xenrt10715872 stunnel]$ git branch --contains ddef8f192ecfe195610000c6f6272f6b77b97e53 master * private/gangj/stunnel-5.60 And I failed to find the log "No route to host" in any historical code of stunnel or openssl. So at least for the two errors "No host resolved" and "No route to host", I think we will need to test and fix them later. Signed-off-by: Gang Ji --- ocaml/libs/stunnel/stunnel.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocaml/libs/stunnel/stunnel.ml b/ocaml/libs/stunnel/stunnel.ml index c9b18f9b4d1..eef9a041234 100644 --- a/ocaml/libs/stunnel/stunnel.ml +++ b/ocaml/libs/stunnel/stunnel.ml @@ -506,7 +506,7 @@ let check_verify_error line = () let check_error s line = - if Astring.String.is_infix ~affix:line s then + if Astring.String.is_infix ~affix:s line then raise (Stunnel_error s) let diagnose_failure st_proc = From 15df70084b5060359ad30fbe2781e9860130e78a Mon Sep 17 00:00:00 2001 From: Gang Ji Date: Thu, 20 Mar 2025 16:28:55 +0800 Subject: [PATCH 4/4] CA-404460: expose ssl_verify_error during updates syncing Signed-off-by: Gang Ji --- ocaml/xapi/repository.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ocaml/xapi/repository.ml b/ocaml/xapi/repository.ml index bf418ee8b03..1ec1486a3e2 100644 --- a/ocaml/xapi/repository.ml +++ b/ocaml/xapi/repository.ml @@ -306,6 +306,8 @@ let sync ~__context ~self ~token ~token_id ~username ~password = with | Api_errors.Server_error (_, _) as e -> raise e + | Stunnel.Stunnel_verify_error reason -> + raise (Api_errors.Server_error (Api_errors.ssl_verify_error, [reason])) | e -> error "Failed to sync with remote YUM repository: %s" (ExnHelper.string_of_exn e) ;