matteocorti / check_ssl_cert

A shell script (that can be used as a Nagios/Icinga plugin) to check an SSL/TLS connection.
GNU General Public License v3.0
360 stars 132 forks source link

ldap certificate check hangs on checking tls renegotiation #483

Closed Constey closed 8 months ago

Constey commented 8 months ago

Describe the bug

I'll try to check an ldaps server but the script runs in an timeout.

./check_ssl_cert -H dc.domain.de -p 636 -P ldaps -vvvvv

Expected behavior

it hangs on "checking TLS renegotiation" and openssl runs in an timeout, while when running it directly it works. is that maybe a openssl 1.1.x problem?

System (please complete the following information):

Additional context/output Checking via openssl directly, works in general:

openssl s_client -connect dc.domain.de:636
CONNECTED(00000003)
depth=2 CN = ROOTCA
verify return:1
depth=1 DC = de, DC = domain, CN = domain-intca
verify return:1
depth=0 CN = dc.domain.de
verify return:1
---
Certificate chain
 0 s:CN = dc.domain.de
   i:DC = de, DC = domain, CN = domain-intca
 1 s:DC = de, DC = domain, CN = domain-intca
   i:CN = ROOTCA
---
Server certificate
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxx
-----END CERTIFICATE-----
subject=CN = dc.domain.de

issuer=DC = de, DC = domain, CN = domain-intca

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 4005 bytes and written 467 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 3B2B000011AD11AFDB15670B80505C6259F6026375E9898EB74E43735C15461E
    Session-ID-ctx:
    Master-Key: 98F1A95953D098C88F98E72DF7196F96D4DEC1F687ECB3FE1A25E375F1EC538447EF7EF29EA98D614DEF47769446F776
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1700668034
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: yes
---
./check_ssl_cert -H dc.domain.de -p 636 -P ldaps -vvvvv
expect not available
timeout available (/usr/bin/timeout)
Found GNU date with timestamp support: enabling date computations
Downloading certificate to /tmp
checking TLS renegotiation

./check_ssl_cert -H dc.domain.de -p 636 -P ldaps --verbose --debug
[DBG] check_ssl_cert version: 2.76.0
[DBG] System info: Linux monitoring 5.15.0-1051-azure #59~20.04.1-Ubuntu SMP Tue Oct 17 16:45:08 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
[DBG] /etc/os-release:
[DBG]   NAME="Ubuntu"
[DBG]   VERSION="20.04.6 LTS (Focal Fossa)"
[DBG]   ID=ubuntu
[DBG]   ID_LIKE=debian
[DBG]   PRETTY_NAME="Ubuntu 20.04.6 LTS"
[DBG]   VERSION_ID="20.04"
[DBG]   HOME_URL="https://www.ubuntu.com/"
[DBG]   SUPPORT_URL="https://help.ubuntu.com/"
[DBG]   BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
[DBG]   PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
[DBG]   VERSION_CODENAME=focal
[DBG]   UBUNTU_CODENAME=focal
[DBG] User: root
[DBG] Shell: /bin/bash
[DBG]   GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
[DBG]   Copyright (C) 2019 Free Software Foundation, Inc.
[DBG]   License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
[DBG]
[DBG]   This is free software; you are free to change and redistribute it.
[DBG]   There is NO WARRANTY, to the extent permitted by law.
[DBG] grep: /bin/grep
[DBG]   grep (GNU grep) 3.4
[DBG]   Copyright (C) 2020 Free Software Foundation, Inc.
[DBG]   License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
[DBG]   This is free software: you are free to change and redistribute it.
[DBG]   There is NO WARRANTY, to the extent permitted by law.
[DBG]
[DBG]   Written by Mike Haertel and others; see
[DBG]   <https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
[DBG] hostname: /bin/hostname
[DBG] $PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
[DBG] Command line arguments: -H dc.domain.de -p 636 -P ldaps --verbose --debug
[DBG]   TMPDIR = /tmp
[DBG] Required HTTP headers:
[DBG] Unrequired HTTP headers:
[DBG] curl binary needed. SSL Labs = , OCSP = 1, CURL = , IGNORE_CONNECTION_STATE=, FILE_URI=
[DBG] curl binary not specified
[DBG] curl available: /usr/bin/curl
[DBG] curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
[DBG] Release-Date: 2020-01-08
[DBG] Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
[DBG] Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets
[DBG] Proxy settings (after):
[DBG]   http_proxy  =
[DBG]   https_proxy =
[DBG]   HTTP_PROXY  =
[DBG]   HTTPS_PROXY =
[DBG]   s_client    =
[DBG]   curl        =
[DBG] Checking if the host is listed in /etc/hosts
[DBG] Host not found in /etc/hosts: checking DNS
[DBG] Checking if the host (dc.domain.de) exists
[DBG] HOST = dc.domain.de
[DBG] SNI                 =
[DBG] HOST_NAME           = dc.domain.de
[DBG] HOST_ADDR           = dc.domain.de
[DBG] NAMES_TO_BE_CHECKED = __HOST__
[DBG] Checking if dc.domain.de is an IP address
[DBG] dc.domain.de is not an IP address
[DBG] HOST_IS_IP.         = 0
[DBG] Checking if dc.domain.de is an IP address
[DBG] dc.domain.de is not an IP address
[DBG] Adding dc.domain.de to NAMES_TO_BE_CHECKED
[DBG] NAMES_TO_BE_CHECKED = dc.domain.de
[DBG] -c specified: 15
[DBG] -w specified: 20
[DBG] Executing comparison '1728000 < 1296000' (precision 0)
[DBG]   bc result = 0
[DBG]   returning 1
[DBG] ROOT_CA =
[DBG] mktemp available: /bin/mktemp
[DBG] file version: file-5.38
[DBG] magic file from /etc/magic:/usr/share/misc/magic
[DBG] nmap binary not specified
[DBG] nmap available: /usr/bin/nmap
[DBG] Checking IPs: host dc.domain.de
[DBG] perl available: /usr/bin/perl
[DBG] date available: /bin/date
[DBG] checking date version
[DBG] date computation type: GNU
[DBG] OpenSSL binary: /usr/bin/openssl
[DBG] OpenSSL info:
[DBG] OpenSSL 1.1.1f  31 Mar 2020
[DBG] built on: Tue Oct 10 09:03:48 2023 UTC
[DBG] platform: debian-amd64
[DBG] options:  bn(64,64) rc4(16x,int) des(int) blowfish(ptr)
[DBG] compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-Wyyo9w/openssl-1.1.1f=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
[DBG] OPENSSLDIR: "/usr/lib/ssl"
[DBG] ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
[DBG] Seeding source: os-specific
[DBG] OpenSSL configuration directory: /usr/lib/ssl
[DBG] 0 root certificates installed by default
[DBG] Date computation: GNU
[DBG] '/usr/bin/openssl s_client' supports '-servername': using -servername dc.domain.de
[DBG] Proxy settings (before):
[DBG]   http_proxy  =
[DBG]   https_proxy =
[DBG]   HTTP_PROXY  =
[DBG]   HTTPS_PROXY =
[DBG] '/usr/bin/openssl s_client' supports '-name': using monitoring
[DBG] '/usr/bin/openssl s_client' supports '-xmpphost': using -xmpphost dc.domain.de
[DBG] HOST_HEADER = dc.domain.de
[DBG] Testing connection with dc.domain.de:636
[DBG] Executing: '/usr/bin/nmap  --unprivileged -Pn -p 636 dc.domain.de'
[DBG]   Starting Nmap 7.80 ( https://nmap.org ) at 2023-11-22 16:37 CET
[DBG]   Failed to resolve "".
[DBG]   Nmap scan report for dc.domain.de (172.23.134.101)
[DBG]   Host is up (0.00057s latency).
[DBG]   Other addresses for dc.domain.de (not scanned): 172.23.134.102
[DBG]   rDNS record for 172.23.134.101: SVDC01.BKK-RuV.de
[DBG]
[DBG]   PORT    STATE SERVICE
[DBG]   636/tcp open  ldapssl
[DBG]
[DBG]   Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds
[DBG] /bin/grep -q "636.*open"
[DBG] Sanity checks: OK
[DBG] temporary file /tmp/7utiwV created
[DBG] temporary file /tmp/qjnfUz created
[DBG] temporary file /tmp/yNUhfm created
[DBG] temporary file /tmp/10qeM6 created
[DBG] temporary file /tmp/K88Mnj created
[DBG] temporary file /tmp/LLaNmS created
[DBG] temporary file /tmp/CEKyCk created
[DBG] Temporary files created
[DBG] dc.domain.de is not an IP address
[DBG] fetch_certificate: PROTOCOL = ldaps
[DBG 0s] exec_with_timeout: TIMEOUT=120, CURRENT_TIMEOUT=120, ELAPSED=0
[DBG 0s] exec_with_timeout echo | /usr/bin/openssl s_client     -showcerts -connect dc.domain.de:636 -servername dc.domain.de   -verify 6        2> /tmp/qjnfUz 1> /tmp/7utiwV
[DBG 0s] executing with timeout (120s): echo | /usr/bin/openssl s_client     -showcerts -connect dc.domain.de:636 -servername dc.domain.de   -verify 6        2> /tmp/qjnfUz 1> /tmp/7utiwV
[DBG 0s] /usr/bin/timeout 120 /bin/sh -c "echo | /usr/bin/openssl s_client     -showcerts -connect dc.domain.de:636 -servername dc.domain.de   -verify 6        2> /tmp/qjnfUz 1> /tmp/7utiwV"
[DBG 0s] Return value of the command = 0
[DBG 0s] Negotiated protocol:
[DBG 0s] openssl_version 3.0.0
[DBG 0s] Checking if OpenSSL version is at least 3.0.0 ( '3' '0' '0' ':0' )
[DBG 0s] openssl version: OpenSSL 1.1.1f  31 Mar 2020
[DBG 0s] Current version 1.1.1f ( '1' '1' '1' 'f:102' )
[DBG 0s]   false
[DBG 0s] checking TLS renegotiation
[DBG 0s] exec_with_timeout: TIMEOUT=120, CURRENT_TIMEOUT=120, ELAPSED=0
[DBG 0s] exec_with_timeout printf 'R
[DBG 0s] ' | /usr/bin/openssl s_client   -crlf -connect dc.domain.de:636 -servername dc.domain.de   2>&1 | /bin/grep -F -q err
[DBG 0s] executing with timeout (120s): printf 'R
[DBG 0s] ' | /usr/bin/openssl s_client   -crlf -connect dc.domain.de:636 -servername dc.domain.de   2>&1 | /bin/grep -F -q err
[DBG 0s] /usr/bin/timeout 120 /bin/sh -c "printf 'R
[DBG 0s] ' | /usr/bin/openssl s_client   -crlf -connect dc.domain.de:636 -servername dc.domain.de   2>&1 | /bin/grep -F -q err"
CRITICAL error: Timeout after 0 seconds
[DBG 0s] CRITICAL ----------------------------------------
[DBG 0s] prepend_critical_message: new message    = Timeout after 0 seconds
[DBG 0s] prepend_critical_message: CRITICAL_MSG   =
[DBG 0s] prepend_critical_message: ALL_MSG 1      =
[DBG 0s] prepend_critical_message: MSG 2          = SSL_CERT CRITICAL dc.domain.de:636: Timeout after 0 seconds
[DBG 0s] prepend_critical_message: CRITICAL_MSG 2 = SSL_CERT CRITICAL dc.domain.de:636: Timeout after 0 seconds
[DBG 0s] prepend_critical_message: ALL_MSG 2      =
[DBG 0s]     SSL_CERT CRITICAL dc.domain.de:636: Timeout after 0 seconds
[DBG 0s] CRITICAL ----------------------------------------
[DBG 0s] cleaning up temporary files
[DBG 0s]  /tmp/7utiwV /tmp/qjnfUz /tmp/yNUhfm /tmp/10qeM6 /tmp/K88Mnj /tmp/LLaNmS /tmp/CEKyCk
[DBG 0s] exiting with CRITICAL
[DBG 0s] ALL_MSG =
[DBG 0s]     SSL_CERT CRITICAL dc.domain.de:636: Timeout after 0 seconds
[DBG 0s] number of errors = 1
SSL_CERT CRITICAL: Timeout after 0 seconds (checking TLS renegotiation)
Constey commented 8 months ago

I've tested with openssl 3.0.12 that looks better: SSL_CERT CRITICAL dc.domain.de:636: Cannot find Signed Certificate Timestamps (SCT)|days_chain_elem1=1092;20;15;; days_chain_elem2=1616;20;15;;

matteocorti commented 8 months ago

I'll take a look. In any case you can try with

 --ignore-tls-renegotiation
matteocorti commented 8 months ago

It works with 3.0.0 since I do not check for renegotiation (as OpenSSL checks it by default).

matteocorti commented 8 months ago

There is another strange behaviour: you get a timeout after 0 seconds (and also in the DBG timeline you have the error at 0s). Should be 120 ...

Constey commented 8 months ago

I'll take a look. In any case you can try with

 --ignore-tls-renegotiation

With --ignore-tls-renegotiation it works. I can aswell reproduce this issue on at least 3 other ubuntu 20.04 machines with openssl from the original apt repository. Since with openssl 3 everything is fine, im good with it :-) But if there is anything I can help troubleshooting this, just let me know. (And huge thanks for this script at all❤️)

matteocorti commented 8 months ago

Several checks with OpenSSL 1.1.1w work (as 1.1.1f is very old and no more supported). Please reopen if this can be reproduced with the current 1.1. version.

$ --host ldaps-rz-1.ethz.ch --protocol ldaps --openssl /opt/homebrew/Cellar/openssl@1.1/1.1.1w/bin/openssl 
SSL_CERT OK - ldaps-rz-1.ethz.ch:636, ldaps, x509 certificate 'ldapsrz1.ethz.ch' (ldaps-rz-1.ethz.ch) from 'DigiCert Inc' valid until Dec 14 23:59:59 2024 GMT (expires in 383 days)|days_chain_elem1=383;20;15;; days_chain_elem2=2492;20;15;; days_chain_elem3=5162;20;15;;