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
363 stars 133 forks source link

Recent versions incompatible with OpenBSD 6.3 #304

Closed arjan-s closed 3 years ago

arjan-s commented 3 years ago

Describe the bug

I just tried to upgrade to check_ssl_cert 2.4.2 from the ancient version 1.84.0. It seems that a call to date has changed, which makes it incompatible with my (also pretty ancient) OpenBSD 6.3 installation. I also have a server with OpenBSD 6.7, where check_ssl_cert 2.4.2 works just fine (i.e. date has the -f flag).

To Reproduce

Run the following command on OpenBSD 6.3: check_ssl_cert -w 30 -c 14 -H localhost -f cert.pem --ignore-sct -d -v

Expected behavior

I wouldn't go as far as say I expect it to work on such an old OS, but that would be great of course. Otherwise, a note in the README about incompatibility with older OSes would be good.

System (please complete the following information):

Additional context/output

[DBG] Checking expiration date of element 1
[DBG] Validity date on cert element 1 is Aug  7 07:39:37 2023 GMT
[DBG] Date computations: BSD
[DBG] Computing number of hours until 'Aug  7 07:39:37 2023 GMT'
date: unknown option -- f
usage: date [-aju] [-d dst] [-r seconds] [-t minutes_west] [-z output_zone]
            [+format] [[[[[[cc]yy]mm]dd]HH]MM[.SS]]
[DBG] Hours until Aug  7 07:39:37 2023 GMT: -452916
[DBG]   valid for -452916 hours
[DBG]   valid for -18871 days
matteocorti commented 3 years ago

It's indeed a bug but I don't have your version of date to test. Could you please give me the output of:

RESULT==$( echo 'Aug  7 07:39:37 2023 GMT' | sed 's/[ ][^ ]*$//' )
echo $RESULT
date  -d "${RESULT}" +%s
arjan-s commented 3 years ago

Sure, thanks for seriously considering my report! Here is the output:

$ RESULT==$( echo 'Aug  7 07:39:37 2023 GMT' | sed 's/[ ][^ ]*$//' )
$ echo $RESULT
=Aug 7 07:39:37 2023
$ date  -d "${RESULT}" +%s
1630501754
$
matteocorti commented 3 years ago

Ok seems to work. Than I could check if -f is there, and if not fallback to the same computation I use on BusyBox Linux.

matteocorti commented 3 years ago

I committed a new version, can you please check it out and test it?

arjan-s commented 3 years ago

Awesome! It's almost correct, if you remove the backslashes from the new grep, it works! I suppose you can also drop the example date from the command, but perhaps there's a logical reason for adding that? By the way, it's not important for my use case, but I just realized that CN and Issuer detection are also broken...

matteocorti commented 3 years ago

Thanks. I committed a fix, can you please test again?

I can also take a look at the other issues: just post the debugging output ...

Matteo

arjan-s commented 3 years ago

Sorry, found another bug with the new version. For CA certificates the expiry, CN and Issuer detection is different from the old version of the script. For non-CA certificates the outputs are identical now. Here are the outputs for you to compare: 1.84.0 SSL_CERT OK - x509 certificate 'subject= C = NL' from 'API' valid until Aug 7 07:39:37 2023 GMT (expires in 704 days)|days=704;30;14;; 2.4.3 SSL_CERT OK - x509 certificate 'CN unavailable' from '' valid until Aug 7 07:39:37 2023 GMT (expires today)|days_chain_elem1=0;30;14;; Perhaps these CN and Issuer output are intended behaviour for CA certificates, so I'm putting it here just in case. The expiry details at the end are a new bug though, I think.

matteocorti commented 3 years ago

Something is buggy ... Do you have the full output?

arjan-s commented 3 years ago

Thanks. I committed a fix, can you please test again?

I can also take a look at the other issues: just post the debugging output ...

Matteo

Yes, the date fix is now correct!

arjan-s commented 3 years ago

Something is buggy ... Do you have the full output?

Sure, here you go!

[DBG] Command line arguments: -w 30 -c 14 -H localhost -f ca.pem --ignore-sct -d
[DBG] SNI         =
[DBG] HOST_NAME   = localhost
[DBG] HOST_ADDR   = localhost
[DBG] COMMON_NAME =
[DBG] COMMON_NAME =
[DBG] -c specified: 14
[DBG] ROOT_CA =
[DBG] file version: file: unknown option -- version
[DBG] usage: file [-bchiLsW] file ...
[DBG] cURL binary needed. SSL Labs = , OCSP = 1, CURL =
[DBG] cURL binary not specified
[DBG] cURL available: /usr/local/bin/curl
[DBG] curl 7.59.0 (x86_64-unknown-openbsd6.3) libcurl/7.59.0 LibreSSL/2.7.2 zlib/1.2.3 nghttp2/1.31.0
[DBG] Release-Date: 2018-03-14
[DBG] Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
[DBG] Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy
[DBG] nmap binary not needed. No disallowed protocols
[DBG] perl available: /usr/bin/perl
[DBG] date available: /bin/date
[DBG] checking date version
[DBG] Old BSD date without -f: fallback to BusyBox date computation
[DBG] check_ssl_cert version: 2.4.3
[DBG] OpenSSL binary: /usr/bin/openssl
[DBG] OpenSSL info:
[DBG]LibreSSL 2.7.2
[DBG]built on: date not available
[DBG]platform: information not available
[DBG]options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) idea(int) blowfish(idx)
[DBG]compiler: information not available
[DBG]OPENSSLDIR: "/etc/ssl"
[DBG] OpenSSL configuration directory: /etc/ssl
[DBG] 133 root certificates installed by default
[DBG]  System info: OpenBSD api-server 6.3 GENERIC.MP#9 amd64
[DBG] Date computation: BUSYBOX
[DBG] '/usr/bin/openssl s_client' supports '-servername': using -servername localhost
[DBG] '/usr/bin/openssl s_client' supports '-xmpphost': using -xmpphost localhost
[DBG] temporary file /tmp/3B0uCB created
[DBG] temporary file /tmp/DjyPG3 created
[DBG] temporary file /tmp/63Sybv created
[DBG] temporary file /tmp/EoODWI created
[DBG] temporary file /tmp/Swuj12 created
[DBG] temporary file /tmp/Fu8RQp created
[DBG] temporary file /tmp/vHgLUZ created
[DBG] localhost is not an IP address
[DBG] Adding -ign_eof to the options
[DBG] check if we have to convert the file /etc/openvpn/server/accessnodes_ca.pem to PEM
[DBG] certificate type (1): PEM certificate
[DBG] temporary file /tmp/iXCe3Q created
[DBG] Copying the certificate to /tmp/3B0uCB
[DBG] storing the certificate to /tmp/3B0uCB
[DBG] certificate type (2): PEM certificate
[DBG] Return value of the command = 0
[DBG] checking TLS renegotiation
[DBG] executing with timeout (120s): printf 'R
[DBG] ' | /usr/bin/openssl s_client  -crlf -connect localhost:443 2>&1 | grep -F -q err
[DBG]   start time = 1630504094
[DBG] eval
[DBG] /bin/sh -c "printf 'R
[DBG] ' | /usr/bin/openssl s_client  -crlf -connect localhost:443 2>&1 | grep -F -q err"
[DBG]   end time = 1630504094
[DBG]   new timeout = 120
[DBG] Skipping 0 element of the chain
[DBG] ISSUERS =
[DBG] issuer= C = NL, ST = Some-State, O = API, emailAddress = ca@api
[DBG] ISSUERS =
[DBG] O = API
[DBG] subject= C = NL, ST = Some-State, O = API, emailAddress = ca@api
[DBG] CN         = CN unavailable
[DBG] CA         = O = API
[DBG] SERIAL     = FBBD6581635FFCEB
[DBG] FINGERPRINT= D5:8F:E8:CE:8B:A6:6B:B4:DA:AC:69:B1:D8:D8:4A:1D:33:0D:BD:61
[DBG] OCSP_URI   =
[DBG] ISSUER_URI =
[DBG]     Signature Algorithm: sha256WithRSAEncryption
[DBG] subjectAlternativeName =
[DBG] Checking expiration date
[DBG] Number of certificates in CA chain: 1
[DBG] Skipping 0 element of the chain
[DBG] ------------------------------------------------------------------------------
[DBG] Checking expiration date of element 1
[DBG] Validity date on cert element 1 is Aug  7 07:39:37 2023 GMT
[DBG] Date computations: BUSYBOX
[DBG] Computing number of hours until 'Aug  7 07:39:37 2023 GMT'
[DBG] Computing number of hours until 'Aug  7 07:39:37 2023' (BusyBox compatible format)
[DBG] Hours until Aug  7 07:39:37 2023 GMT: 0
[DBG]   valid for 0 hours
[DBG]   valid for 0 days
[DBG] executing: /usr/bin/openssl x509 -noout -checkend 0 on cert element 1
[DBG] executing: /usr/bin/openssl x509 -noout -checkend 1209600 on cert element 1
[DBG] executing: /usr/bin/openssl x509 -noout -checkend 2592000 on cert element 1
[DBG] ------------------------------------------------------------------------------
[DBG] Checking OCSP status of element 1
[DBG] temporary file /tmp/RdE8Zt created
[DBG] Storing the chain element in /tmp/RdE8Zt
[DBG] Checking revokation via OCSP
[DBG] Issuer hash: cc9f964a
[DBG] openssl_version 1.1.0
[DBG] Checking if OpenSSL version is at least 1.1.0 ( '1' '1' '0' ':0' )
[DBG] openssl version: LibreSSL 2.7.2
[DBG] Current version 2.7.2 ( '2' '7' '2' ':0' )
[DBG]   true
[DBG] Checking Signed Certificate Timestamps (SCTs)
[DBG] output parameters: CA_ISSUER_MATCHED     =
[DBG] output parameters: CHECKEDNAMES          =
[DBG] output parameters: CN                    = CN unavailable
[DBG] output parameters: DATE                  = Aug  7 07:39:37 2023 GMT
[DBG] output parameters: DAYS_VALID            =  (expires today)
[DBG] output parameters: DYSPLAY_CN            = 'CN unavailable'
[DBG] output parameters: OPENSSL_COMMAND       = x509
[DBG] output parameters: SELFSIGNEDCERT        =
[DBG] output parameters: SHORTNAME             = SSL_CERT
[DBG] output parameters: OCSP_EXPIRES_IN_HOURS =
[DBG] output parameters: SSL_LABS_HOST_GRADE   =
SSL_CERT OK - x509 certificate 'CN unavailable' from '' valid until Aug  7 07:39:37 2023 GMT (expires today)|days_chain_elem1=0;30;14;;
[DBG] cleaning up temporary files
[DBG]
[DBG] /tmp/3B0uCB
[DBG] /tmp/DjyPG3
[DBG] /tmp/63Sybv
[DBG] /tmp/EoODWI
[DBG] /tmp/Swuj12
[DBG] /tmp/Fu8RQp
[DBG] /tmp/vHgLUZ
[DBG] /tmp/iXCe3Q
[DBG] /tmp/RdE8Zt
matteocorti commented 3 years ago

The first problem is that the BusyBox date computation is not working...

matteocorti commented 3 years ago

Can you also post the content of man date? what does date -d do on your version?

arjan-s commented 3 years ago

https://man.openbsd.org/OpenBSD-6.3/date

     -d dst  Set the system's value for Daylight Saving Time.  If dst is non-
             zero, future calls to gettimeofday(2) will return a non-zero
             value for tz_dsttime.
matteocorti commented 3 years ago

The same on macOS but not on BusyBox ...

arjan-s commented 3 years ago

Right. Well, as long as the exit status (for Nagios) is correct, it's already fine for my use case, so thank you for that! Whether you want the rest to work correctly on a pretty old OpenBSD is up to you...

matteocorti commented 3 years ago

The status will be wrong as the time to the expiration is not computed correctly ...

arjan-s commented 3 years ago

Are you sure? The exit code is 0 (so OK for Nagios) right now, which is correct for my certificates.

matteocorti commented 3 years ago

Mmmm strange

matteocorti commented 3 years ago

Would using perl for the date computation be an option? What happens with --force-perl-date?

arjan-s commented 3 years ago

I don't have the prerequisite perl modules on my server to test that... Sorry. Can't locate Date/Parse.pm in @INC (you may need to install the Date::Parse module) (@INC contains: /usr/local/libdata/perl5/site_perl/amd64-openbsd /usr/local/libdata/perl5/site_perl /usr/libdata/perl5/amd64-openbsd /usr/libdata/perl5 .) at - line 3.

matteocorti commented 3 years ago

Ok then I have to understand how to convert a date as 'Aug 7 07:39:37 2023 GMT' in unix time with your version :-)

matteocorti commented 3 years ago

what happens with

date -j  +%s 'Aug  7 07:39:37 2023 GMT'

?

arjan-s commented 3 years ago

Doesn't work, as the date doesn't adhere to "the traditional BSD date format" [[[[[cc]yy]mm]dd]HH]MM[.SS].

date: illegal time format
usage: date [-aju] [-d dst] [-r seconds] [-t minutes_west] [-z output_zone]
            [+format] [[[[[[cc]yy]mm]dd]HH]MM[.SS]]

I did find one other method, which is using Python like you can use Perl now. I do have Python 2.7 on the server, so maybe that's something to try?

matteocorti commented 3 years ago

Mmm do you know a way on you system to parse a date as the one in the example?

arjan-s commented 3 years ago

Not yet, but I'm still searching for it... :)

arjan-s commented 3 years ago

I found I have the dateutils package installed, which provides the dconv utility, which can convert between date formats (not unix timestamp though). That makes it possible to convert the date using these commands (sadly with an extra sed in between to strip padding spaces):

$ echo "Aug  7 07:39:37 2023 GMT" | sed 's/  / /g' | dconv -f "%Y%m%d%H%M.%S" -i "%b %d %H:%M:%S %Y %Z"
202308070739.37
$ date -j +%s 202308070739.37
1691386777
matteocorti commented 3 years ago

Thanks! I'll take a look tomorrow

matteocorti commented 3 years ago

I committed a new version with the computation using dconv. I also added an option --force-dconv-date to force the behaviour to be able to test

It works on macOS but my date has a different format:

[[[mm]dd]HH]MM[[cc]yy][.ss]]

Which BTW makes no sense (day month hour minutes year)????

Anyway can you please test on your OpenBSD?

arjan-s commented 3 years ago

Works perfectly! Thank you!

SSL_CERT OK - x509 certificate 'CN unavailable' from '' valid until Aug  7 07:39:37 2023 GMT (expires in 703 days)|days_chain_elem1=703;30;14;;

The macOS date format is really weird indeed!

matteocorti commented 3 years ago

Thanks for the help! It was "fun" to see how date computations are not really portable. Without dconv it would have been a lot of work to write a date parser using a POSIX shell :-)