Giter Club home page Giter Club logo

check_ssl_cert's Introduction

check_ssl_cert

© Matteo Corti, ETH Zurich, 2007-2012.
© Matteo Corti, 2007-2024.

see AUTHORS.md for the complete list of contributors

     

A POSIX shell script (that can be used as a Nagios/Icinga plugin) to check an SSL/TLS connection and certificate

Usage

Usage: check_ssl_cert -H host [OPTIONS]
       check_ssl_cert -f file [OPTIONS]

Arguments:
   -f,--file file                  Local file path or URI.
                                   With -f you can not only pass a x509
                                   certificate file but also a certificate
                                   revocation list (CRL) to check the
                                   validity period or a Java KeyStore file
   -H,--host host                  Server

Options:
   -A,--noauth                     Ignore authority warnings (expiration
                                   only)
      --all                        Enable all the possible optional checks
                                   at the maximum level
      --all-local                  Enable all the possible optional checks
                                   at the maximum level (without SSL-Labs)
      --allow-empty-san            Allow certificates without Subject
                                   Alternative Names (SANs)
   -C,--clientcert path            Use client certificate to authenticate
   -c,--critical days              Minimum number of days a certificate has
                                   to be valid to issue a critical status.
                                   Can be a floating point number, e.g., 0.5
                                   Default: 15
      --check-chain                The certificate chain cannot contain
                                   double or root certificates
      --check-ciphers grade        Check the offered ciphers
      --check-ciphers-warnings     Critical if nmap reports a warning for an
                                   offered cipher
      --check-http-headers         Check the HTTP headers for best practices
      --check-ssl-labs-warn grade  SSL Labs grade on which to warn
      --clientpass phrase          Set passphrase for client certificate.
      --configuration file         Read options from the specified file
      --crl                        Check revocation via CRL (requires
                                   --rootcert-file)
      --curl-bin path              Path of the curl binary to be used
      --custom-http-header string  Custom HTTP header sent when getting the
                                   cert example: 'X-Check-Ssl-Cert: Foobar=1'
      --default-format             Print the default output format and exit
      --dane                       Verify that valid DANE records exist
                                   (since OpenSSL 1.1.0)
      --dane 211                   Verify that a valid DANE-TA(2) SPKI(1)
                                   SHA2-256(1) TLSA record exists
      --dane 301                   Verify that a valid DANE-EE(3) Cert(0)
                                   SHA2-256(1) TLSA record exists
      --dane 302                   Verify that a valid DANE-EE(3) Cert(0)
                                   SHA2-512(2) TLSA record exists
      --dane 311                   Verify that a valid DANE-EE(3) SPKI(1)
                                   SHA2-256(1) TLSA record exists
      --dane 312                   Verify that a valid DANE-EE(3)
                                   SPKI(1) SHA2-512(1) TLSA record exists
      --date path                  Path of the date binary to be used
   -d,--debug                      Produce debugging output (can be
                                   specified more than once)
      --debug-cert                 Store the retrieved certificates in the
                                   current directory
      --debug-headers              Store the retrieved HTLM headers in the
                                   headers.txt file
      --debug-file file            Write the debug messages to file
      --debug-time                 Write timing information in the
                                   debugging output
      --dig-bin path               Path of the dig binary to be used
      --do-not-resolve             Do not check if the host can be resolved
      --dtls                       Use the DTLS protocol
      --dtls1                      Use the DTLS protocol 1.0
      --dtls1_2                    Use the DTLS protocol 1.2
   -e,--email address              Pattern to match the email address
                                   contained in the certificate
      --ecdsa                      Signature algorithm selection: force ECDSA
                                   certificate
      --element number             Check up to the N cert element from the
                                   beginning of the chain
      --file-bin path              Path of the file binary to be used
      --fingerprint hash           Pattern to match the fingerprint
      --fingerprint-alg algorithm  Algorithm for fingerprint. Default sha1
      --first-element-only         Verify just the first cert element, not
                                   the whole chain
      --force-dconv-date           Force the usage of dconv for date
                                   computations
      --force-perl-date            Force the usage of Perl for date
                                   computations
      --format FORMAT              Format output template on success, for
                                   example: '%SHORTNAME% OK %CN% from
                                   %CA_ISSUER_MATCHED%'
                                   list of possible variables:
                                   - %CA_ISSUER_MATCHED%
                                   - %CHECKEDNAMES%
                                   - %CN%
                                   - %DATE%
                                   - %DAYS_VALID%
                                   - %DYSPLAY_CN%
                                   - %HOST%
                                   - %OCSP_EXPIRES_IN_HOURS%
                                   - %OPENSSL_COMMAND%
                                   - %PORT%
                                   - %SELFSIGNEDCERT%
                                   - %SHORTNAME%
                                   - %SIGALGO%
                                   - %SSL_LABS_HOST_GRADE%
                                   See --default-format for the default
      --grep-bin path              Path of the grep binary to be used
   -h,--help,-?                    This help message
      --http-headers-path path     The path to be used to fetch HTTP headers
      --http-use-get               Use GET instead of HEAD (default) for the
                                   HTTP related checks
   -i,--issuer issuer              Pattern to match the issuer of the
                                   certificate
      --ignore-altnames            Ignore alternative names when matching
                                   pattern specified in -n (or the host name)
      --ignore-connection-problems [state] In case of connection problems
                                   returns OK or the optional state
      --ignore-exp                 Ignore expiration date
      --ignore-http-headers        Ignore checks on HTTP headers with --all
                                   and --all-local
      --ignore-host-cn             Do not complain if the CN does not match
                                   the host name
      --ignore-incomplete-chain    Do not check chain integrity
      --ignore-maximum-validity    Ignore the certificate maximum validity
      --ignore-ocsp                Do not check revocation with OCSP
      --ignore-ocsp-errors         Continue if the OCSP status cannot be
                                   checked
      --ignore-ocsp-timeout        Ignore OCSP result when timeout occurs
                                   while checking
      --ignore-sct                 Do not check for signed certificate
                                   timestamps (SCT)
      --ignore-sig-alg             Do not check if the certificate was signed
                                   with SHA1 or MD5
      --ignore-ssl-labs-cache      Force a new check by SSL Labs (see -L)
      --ignore-ssl-labs-errors     Ignore errors if SSL Labs is not
                                   accessible or times out
      --ignore-tls-renegotiation   Ignore the TLS renegotiation check
      --ignore-unexpected-eof      Ignore unclean TLS shutdowns
      --inetproto protocol         Force IP version 4 or 6
      --info                       Print certificate information
      --init-host-cache            Initialize the host cache
      --issuer-cert-cache dir      Directory where to store issuer
                                   certificates cache
      --jks-alias alias            Alias name of the Java KeyStore entry
                                   (requires --file)
   -K,--clientkey path             Use client certificate key to authenticate
   -L,--check-ssl-labs grade       SSL Labs assessment (please check
                                   https://www.ssllabs.com/about/terms.html)
      --long-output list           Append the specified comma separated (no
                                   spaces) list of attributes to the plugin
                                   output on additional lines
                                   Valid attributes are:
                                     enddate, startdate, subject, issuer,
                                     modulus, serial, hash, email, ocsp_uri
                                     and fingerprint.
                                   'all' will include all the available
                                   attributes.
   -m,--match                      Pattern to match the CN or AltName
                                   (can be specified multiple times)
      --maximum-validity [days]    The maximum validity of the certificate
                                   must not exceed 'days' (default 397)
                                   This check is automatic for HTTPS
      --nmap-bin path              Path of the nmap binary to be used
      --nmap-with-proxy            Allow nmap to be used with a proxy
      --no-perf                    Do not show performance data
      --no-proxy                   Ignore the http_proxy and https_proxy
                                   environment variables
      --no-proxy-curl              Ignore the http_proxy and https_proxy
                                   environment variables for curl
      --no-proxy-s_client          Ignore the http_proxy and https_proxy
                                   environment variables for openssl s_client
      --no-ssl2                    Disable SSL version 2
      --no-ssl3                    Disable SSL version 3
      --no-tls1                    Disable TLS version 1
      --no-tls1_1                  Disable TLS version 1.1
      --no-tls1_2                  Disable TLS version 1.2
      --no-tls1_3                  Disable TLS version 1.3
      --not-issued-by issuer       Check that the issuer of the certificate
                                   does not match the given pattern
      --not-valid-longer-than days Critical if the certificate validity is
                                   longer than the specified period
   -o,--org org                    Pattern to match the organization of the
                                   certificate
      --ocsp-critical hours        Minimum number of hours an OCSP response
                                   has to be valid to issue a critical status
      --ocsp-warning hours         Minimum number of hours an OCSP response
                                   has to be valid to issue a warning status
      --openssl path               Path of the openssl binary to be used
      --path path                  Set the PATH variable to 'path'
   -p,--port port                  TCP port (default 443)
      --precision digits           Number of decimal places for durations:
                                   defaults to 0 if critical or warning are
                                   integers, 2 otherwise
   -P,--protocol protocol          Use the specific protocol:
                                   dns, ftp, ftps, http, https (default),
                                   h2 (HTTP/2), h3 (HTTP/3), imap, imaps,
                                   irc, ircs, ldap, ldaps, mqtts, mysql,
                                   pop3, pop3s, postgres, sieve, sips, smtp,
                                   smtps, tds, xmpp, xmpp-server.
                                   ftp, imap, irc, ldap, pop3, postgres,
                                   sieve, smtp: switch to TLS using StartTLS
      --password source            Password source for a local certificate,
                                   see the PASS PHRASE ARGUMENTS section
                                   openssl(1)
      --prometheus                 Generate Prometheus/OpenMetrics output
      --proxy proxy                Set http_proxy and the s_client -proxy
                                   option
      --python-bin path            Path of the python binary to be used
      --quic                       Use QUIC
   -q,--quiet                      Do not produce any output
   -r,--rootcert path              Root certificate or directory to be used
                                   for certificate validation
      --require-client-cert [list] The server must accept a client
                                   certificate. 'list' is an optional comma
                                   separated list of expected client
                                   certificate CAs
      --require-dnssec             Require DNSSEC
      --require-http-header header Require the specified HTTP header
                                    (e.g., X-Frame-Options)
      --require-no-http-header header Require the absence of the specified
                                   HTTP header (e.g., X-Powered-By)
      --require-no-ssl2            Critical if SSL version 2 is offered
      --require-no-ssl3            Critical if SSL version 3 is offered
      --require-no-tls1            Critical if TLS 1 is offered
      --require-no-tls1_1          Critical if TLS 1.1 is offered
      --require-ocsp-stapling      Require OCSP stapling
      --require-purpose usage      Require the specified key usage (can be
                                   specified more then once)
      --require-purpose-critical   The key usage must be critical
      --resolve-over-http [server] Resolve the host over HTTP using Google or
                                   the specified server
      --resolve ip                 Provide a custom IP address for the
                                   specified host
      --rootcert-dir path          Root directory to be used for certificate
                                   validation
      --rootcert-file path         Root certificate to be used for
                                   certificate validation
      --rsa                        Signature algorithm selection: force RSA
                                   certificate
      --security-level number      Set the security level to specified value
                                   See SSL_CTX_set_security_level(3) for a
                                   description of what each level means
   -s,--selfsigned                 Allow self-signed certificates
      --serial serialnum           Pattern to match the serial number
      --skip-element number        Skip checks on the Nth cert element (can
                                   be specified multiple times)
      --sni name                   Set the TLS SNI (Server Name Indication)
                                   extension in the ClientHello message to
                                   'name'
      --ssl2                       Force SSL version 2
      --ssl3                       Force SSL version 3
   -t,--timeout seconds            Timeout after the specified time
                                   (defaults to 120 seconds)
      --temp dir                   Directory where to store the temporary
                                   files
      --terse                      Terse output
      --tls1                       Force TLS version 1
      --tls1_1                     Force TLS version 1.1
      --tls1_2                     Force TLS version 1.2
      --tls1_3                     Force TLS version 1.3
   -u,--url URL                    HTTP request URL
      --user-agent string          User agent that shall be used for HTTPS
                                   connections
   -v,--verbose                    Verbose output (can be specified more than
                                   once)
   -V,--version                    Version
   -w,--warning days               Minimum number of days a certificate has
                                   to be valid to issue a warning status.
                                   Can be a floating point number, e.g., 0.5
                                   Default: 20
      --xmpphost name              Specify the host for the 'to' attribute
                                   of the stream element
   -4                              Force IPv4
   -6                              Force IPv6

Deprecated options:
      --altnames                   Match the pattern specified in -n with
                                   alternate names too (enabled by default)
   -n,--cn name                    Pattern to match the CN or AltName
                                   (can be specified multiple times)
      --curl-user-agent string     User agent that curl shall use to obtain
                                   the issuer cert
      --days days                  Minimum number of days a certificate has
                                   to be valid
                                   (see --critical and --warning)
   -N,--host-cn                    Match CN with the host name
                                   (enabled by default)
      --no_ssl2                    Disable SSLv2 (deprecated use --no-ssl2)
      --no_ssl3                    Disable SSLv3 (deprecated use --no-ssl3)
      --no_tls1                    Disable TLSv1 (deprecated use --no-tls1)
      --no_tls1_1                  Disable TLSv1.1 (deprecated use
                                   --no-tls1_1)
      --no_tls1_2                  Disable TLSv1.1 (deprecated use
                                   --no-tls1_2)
      --no_tls1_3                  Disable TLSv1.1 (deprecated use
                                   --no-tls1_3)
      --ocsp                       Check revocation via OCSP (enabled by
                                   default)
      --require-hsts               Require HTTP Strict Transport Security
                                   (deprecated use --require-security-header
                                   strict-transport-security)
      --require-san                Require the presence of a Subject
                                   Alternative Name
                                   extension
      --require-security-header header require the specified HTTP
                                   security header (e.g., X-Frame-Options)
                                   (deprecated use --require-http-header)
      --require-security-headers   Require all the HTTP security headers:
                                     Content-Security-Policy
                                     Permissions-Policy
                                     Referrer-Policy
                                     strict-transport-security
                                     X-Content-Type-Options
                                     X-Frame-Options
      --require-security-headers-path path the path to be used to fetch HTTP
                                   security headers
      --require-x-frame-options [path] Require the presence of the
                                   X-Frame-Options HTTP header
                                   'path' is the optional path to be used
                                   in the URL to check for the header
                                   (deprecated use --require-security-header
                                   X-Frame-Options and
                                   --require-security-headers-path path)
   -S,--ssl version                Force SSL version (2,3)
                                   (see: --ssl2 or --ssl3)

Report bugs to https://github.com/matteocorti/check_ssl_cert/issues

Configuration

Command line options can be specified in a configuration file (${HOME}/.check_ssl_certrc). For example

$ cat ${HOME}/.check_ssl_certrc
--verbose
--critical 20
--warning 40

Options specified in the configuration file are read before processing the arguments and can be overridden.

Expect & timeout

check_ssl_cert requires expect or timeout to enable timeouts. If expect or timeout are not present on your system, timeouts will be disabled.

Virtual servers

check_ssl_cert supports the servername TLS extension in ClientHello if the installed OpenSSL version provides it. This is needed if you are checking a server with virtual hosts.

SSL Labs

If -L or --check-ssl-labs are specified, the plugin will check the cached status using the SSL Labs Assessment API.

The plugin will ask for a cached result (maximum age 1 day) to avoid too many checks. The first time you issue the check you could therefore get an outdated result.

Root Certificate

The root certificate corresponding to the checked certificate must be available to OpenSSL or must be specified with the -r cabundle or --rootcert cabundle option, where cabundle is either a file for -CAfile or a directory for -CApath.

On macOS the root certificates bundle is stored in the Keychain and OpenSSL will complain with:

verification error: unable to get local issuer certificate

The bundle can be extracted with:

$ sudo security find-certificate -a \
  -p /System/Library/Keychains/SystemRootCertificates.keychain > cabundle.crt

and then submitted to check_ssl_cert with the -r,--rootcert path option

 ./check_ssl_cert -H www.google.com -r ./cabundle.crt

Quoting in Nagios

An asterisk * is automatically escaped by nagios. If you need to specify an option (e.g., --cn) with an argument containing an asterisk you need to enclose it in double quotes (e.g., ''*.github.com'')

bash completion and caching

Once the host name cache (${HOME}/.check_ssl_cert-cache) is initialized (with the --init-host-cache option), every specified host is cached.

The host name cache is a plain text file which contains an host name per line. Each time a new host is specified, it is automatically added to the cache. The file can be edited with a text editor (to delete or edit entries).

When using bash completion with the --host command line option the cache is then read and used as a suggestion.

Development

Testing

To run the test suite you will need shUnit2

  • Manual install: github
  • macOS with Homebrew: brew install shunit2
  • Debian, Ubuntu: apt-get install shunit2
  • Fedora: dnf install shunit2

Run make test to execute the whole test suite.

To enable debugging output for the tests set the TEST_DEBUG environment variable to --debug:

export TEST_DEBUG=--debug
make test

With make disttest you can check the formatting of the files (e.g. tabs and blanks at the end of the lines) and run ShellCheck to lint the scripts.

With make codespell ypu can perform a spell check on the code and documentation.

To run a single test:

  • set the SHUNIT2 environment variable with the location of the shUnit2 binary
  • change the directory to the test suite: cd test
  • execute the test suite with the tests to be run as argument after --. For example ./unit_tests.sh -- testName

Documentation

The majority of the documentation files are written using the GitHub Flavored Markdown language.

Supporters

We are very grateful to our amazing supporters and sponsors!

If you'd like to support this script, please visit our sponsorship page on GitHub.

Bugs

Report bugs to https://github.com/matteocorti/check_ssl_cert/issues

check_ssl_cert's People

Contributors

agibson2 avatar aslafy-z avatar barakatsoluto avatar bb-ricardo avatar booboo-at-gluga-de avatar claudioth avatar d7415 avatar danpritts avatar dependabot[bot] avatar derdakon avatar dilyanpalauzov avatar eimamagi avatar gbotti avatar grizzlydev-sarl avatar iasdeoupxe avatar idahopl avatar matsimon avatar matteocorti avatar mic92 avatar mookie- avatar naveensrinivasan avatar peternewman avatar rpv-tomsk avatar scornelissen85 avatar szepeviktor avatar va1entin avatar vhotspur avatar waja avatar wimvr avatar yasirmx2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

check_ssl_cert's Issues

Multiple OCSP responder

Hi,

I found that check_ssl_cert fails with multiple ocsp responders:

check_ssl_cert --debug --host netlock.hu
[DBG] OCSP: host = ocsp1.netlock.hu
ocsp2.netlock.hu
ocsp3.netlock.hu

I can fix it with addition of "head -n1", but I don't think it's the best way:

OCSP_URI="$($OPENSSL ${OPENSSL_COMMAND} ${OPENSSL_PARAMS} -in "${CERT}" -ocsp_uri -noout | head -n1)"

check_ssl_cert bug?

I've been using check_ssl_cert for years with Nagios to monitor multiple hosts and it's working great! Recently however, I renewed an SSL cert for www.perturb.org, but check_ssl_cert is reporting that the SSL cert is expired. Somehow it still has the expiration date from the previous cert. The command Nagios runs is:

check_ssl_cert -H perturb.org --protocol https --port 443 --cn www.perturb.org --warning 14 --critical 7 --altnames

Which does indeed generate a critical alarm. All the browsers I've checked are happy, as are various SSL checking services:

https://www.sslshopper.com/ssl-checker.html#hostname=www.perturb.org
https://www.digicert.com/help/

Am I missing something, or is check_ssl_cert just confused?

Cannot verify certificate: unable to get local issuer certificate, unable to verify the first certificate

Hi,
I try to check the expiration date of a certificate (Let's Encrypt) on a FTP server.

But it fail with "Cannot verify certificate: unable to get local issuer certificate, unable to verify the first certificate"

Here the detail debug output :

In the above log, all seems to work to my eyes.

Don't think it's related to the Let's Encrypt root CA, because if I test with hellowolrd, it work's (./check_ssl_cert -H helloworld.letsencrypt.org -v -d)

Thank's for the help.

Best regards

OCSP check not working

See for example

./check_ssl_cert -H www.google.com -r ./check_ssl_cert --ocsp
Error querying OCSP responder
140735307825232:error:27076072:OCSP routines:PARSE_HTTP_LINE1:server response error:ocsp_ht.c:314:Code=400,Reason=Bad Request
SSL_CERT WARN www.google.com: |days=76;;;;

Warning and Criticals don't work for me

Thank you for your plug in. Its a a huge help for our organization. I have several web servers that host multiple websites. I am trying to make your plugin pull the SSL cert from the server for specific websites and check the date before it expires. I have it pulling the SSL cert but it says the cert is OK instead of warning or critical days I set in the command. Can you help me?

Here is my command:

./check_ssl_cert -H xxx.somedomain.com -N webserver.domain.com -w 30 -c 15

SSL_CERT OK - X.509 certificate for 'xxx.somedomain.com' from 'InCommon RSA Server CA' valid until Feb 26 23:59:59 2017 GMT (expires in 25 days)|days=25;;;;

I appreciate any help you can give. Thanks
Jeff

Misleading error message (SSL_CERT CRITICAL: Error: verify depth is 6)

I had a check failing which turned out to be due to a DNS issue. However, check_ssl_cert reported the error message:

SSL_CERT CRITICAL: Error: verify depth is 6

Line 228 of check_ssl_cert reports the first line from the captured stderr from openssl, but if -verify 6 is specified then the first line to stderr is always "verify depth is 6". The actual output to stderr was:

verify depth is 6
getaddrinfo: Temporary failure in name resolution
connect:errno=110

So the second line is the error that should be reported.

(check_ssl_cert 1.18.0 on CentOS 6 and 7 with openssl-1.0.1e).

Not passing right hostname to XMPP server

I'm having trouble getting the plugin to validate my XMPP server's cert, because it doesn't pass the correct hostname via openssl:

[root@localhost ~]# /usr/lib64/nagios/plugins/check_ssl_cert  --host server.example.com --port 5222 --protocol xmpp --cn example.com -d
#...
[DBG] '/usr/bin/openssl s_client' supports '-xmpphost': using -xmpphost server.example.com
#...
[DBG] executing with timeout (15s): echo 'Q' | /usr/bin/openssl s_client   -starttls xmpp -connect server.example.com:5222 -xmpphost server.example.com -verify 6     2> /tmp/check_ssl_certky8Jdg 1> /tmp/check_ssl_certNtjjQp
[DBG]   /usr/bin/timeout 15 /bin/sh -c "echo 'Q' | /usr/bin/openssl s_client   -starttls xmpp -connect server.example.com:5222 -xmpphost server.example.com -verify 6     2> /tmp/check_ssl_certky8Jdg 1> /tmp/check_ssl_certNtjjQp"
[...]
Error: verify depth is 6
SSL_CERT CRITICAL server.example.com: No certificate returned

Running the underlying openssl command manually, there's no cert:

[root@localhost ~]# /usr/bin/openssl s_client   -starttls xmpp -connect server.example.com:5222 -xmpphost server.example.com -verify 6 
verify depth is 6
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 300 bytes and written 134 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
---

...but if I pass the right host name as -xmpphost, I get the expected result:

[root@localhost ~]# /usr/bin/openssl s_client   -starttls xmpp -connect server.example.com:5222 -xmpphost example.com -verify 6 
verify depth is 6
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = example.com
verify return:1
---
Certificate chain
 0 s:/CN=example.com
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
#...

I can't see an obvious way to make the plugin pass the right name to the server. I tried using "--sni" but that doesn't work (maybe it should).

Validity bug?

I am trying to use this on a centos 7 machine with nagios 4 + it all
works fine but how do we get it to warn show crytical on the number of
days? this appears not to work whatever we set the min number of days
too.

# ./check_ssl_cert -H www.cnn.com -w 1000
SSL_CERT OK - X.509 certificate for 'a.ssl.fastly.net' from 'DigiCert
SHA2 High Assurance Server CA' valid until Feb  6 12:00:00 2018 GMT
(expires in 707 days)|days=707;1000;;;

multiple issuer URIs breaking OCSP revokation checking

OCSP revokation checking breaks if there are multiple issuer URIs. You would need to use only one of them or some kind of loop.

This is the part of the debug log (with curl output)

[DBG] OCSP: fetching issuer certificate http://cdp1.pca.dfn.de/tu-berlin-ca/pub/cacert/cacert.crt
http://cdp2.pca.dfn.de/tu-berlin-ca/pub/cacert/cacert.crt to /tmp/check_ssl_cert0BdFcl
curl: (3) Illegal characters found in URL
[DBG] OCSP: issuer certificate type:  empty
SSL_CERT UNKNOWN XXX.de: Unable to fetch OCSP issuer certificate.

For now I fixed it by adding this before line 1626: if [ -z "${ISSUER_CERT}" ]; then:

ISSUER_URI=$(echo "${ISSUER_URI}" | head -n1)

Add support for OCSP staple check

It would be nice to have a --ocsp-staple option, to not only test the OCSP servers, but also if your own servers include the staple.

Issue warning if the certificate name is not "contained" in the specified SNI

hi Matteo,

would it be possible to return a warning if the ${CHECKEDNAMES} is not contained in the specified SNI name ?

Background:
When specifying a SNI name we would expect a certificate name that is contained in the SNI name (wildcard handling should be considered). Otherwise a warning should be issued.

Example:
Correct:
/usr/local/nagios-commands/check_ssl_certificate.sh --sni teamplay.siemens.com -H webclient.eu.api.teamplay.siemens.com -r /etc/ssl/certs
SSL_CERT OK - X.509 certificate 'teamplay.siemens.com' from 'Siemens Issuing CA Internet Server 2017' valid until Mar 21 13:30:13 2019 GMT (expires in 346 days)|days=346;;;;

Proposed warning situation:
/var/tmp/check_ssl_certificate.sh --sni teamplay-cn.siemens.com -H webclient.eu.api.teamplay.siemens.com -r /etc/ssl/certs
SSL_CERT WARN webclient.eu.api.teamplay.siemens.com: SNI name {teamplay-cn.siemens.com} does not match certificate name: *.azurewebsites.net|days=616;;;;

A possible solution would be this:

if [ -n "${SNI}" ]; then
  NWCN=${CN#\*.}
  if echo "${SNI}" | grep -qv "${NWCN}" ; then
    warning "SNI name {$SNI} does not match certificate name: ${CN}"
  fi
fi

Do you think this is worth adding to the check ?

tnx & bye //emil

wrong exit status

check_ssl_cert -H expired.badssl.com --host-cn --sni expired.badssl.com correctly states that `SSL_CERT CRITICAL expired.badssl.com: x509 certificate is expired (was valid until Apr 12 23:59:59 2015 GMT)|days=-1173;;;;", but the return value is 0, whereas i expected 2 for critical.

according to git bisect this is a regression of 5b427ba, however it's rather late both in my physical and my internal/biological timezone, so i'm just reporting this and hoping you'll know where to look. upon first glance at the changes, i think that trapping on EXIT with cleanup is clever from a resource-cleanup point, but the plain exit (with a notable absence of a statuscode != 0) may cause this bug. i'm not sure how to properly fix this while keeping the nice cleanup mechanism.

Handle OCSP timeouts gracefully

Earlier this week, the Let's Encrypt OCSP servers went down. This caused all our checks to say 'service check timed out'. We used version 1.54.0 at the time, but looking at the diff, OCSP handling hasn't changed.

Not sure what the best way to deal with outage is. Perhaps --ignore-ocsp-timeout? Because I do want to see OCSP errors, but Nagios doesn't have to trip for dozens/hundreds of checks for a benign temporary error that is outside of my control.

Curious problem with wildcard match

I am seeing an error like this :

SSL_​CERT CRITICAL *.domain.​com: invalid CN ('*.domain.​com' does not match '*.domain.​com')

I am not sure how to tackle this issue.

No longer able to use pattern to match the CN

I recently updated openssl to the latest version 1.1.0.e. Since the update I've had strange SSL issues with almost everything depending on SSL. I have multiple virtual hosts on a single box and have been using check_ssl_cert to validate each sub/domain's SSL certificates using

check_ssl_cert -H domain4.net -n domain4.net

This has all been successful prior to updating openssl where check_ssl_cert would return an OK status. Now since the openssl update check_ssl_cert is failing for any domain except the primary domain name that shows up in reverse DNS.

SSL_CERT CRITICAL domain4.net: invalid CN ('*.maindomain.net' does not match 'domain4.net')|days=1067;;;;

It seems that using -n should still continue to return OK statuses, but I am not sure what exactly changed with openssl that would suddenly cause this.

  -n,--cn name               pattern to match the CN of the certificate (can be specified multiple times)

I have not had success even with the latest check_ssl_cert-1.44.0 release.

Weird ocsp issue

@matteocorti

While testing I had a weird issue. Some certificates we made today in the same way as some other certificates we made last week somehow fail, as the ocsp url and header seems empty. We don't get why this certificate suddenly doesn't contain the ocsp url?

/usr/local/nagios/libexec/check_ssl_cert. -H servername -p 9200 -w 40 -c 10 --issuer 'MYISSUER' --tls1_2 --altnames --cn servername -d
[DBG] ROOT_CA =
expect not available
timeout available (/usr/bin/timeout)
[DBG] perl available: /usr/bin/perl
[DBG] date available: /bin/date
found GNU date with timestamp support: enabling date computations
[DBG] check_ssl_version: 1.47.0
[DBG] OpenSSL binary: /usr/bin/openssl
[DBG] OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
[DBG] System info: Linux nagiosserver2.6.32-696.1.1.el6.x86_64 #1 SMP Tue Apr 11 17:13:24 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[DBG] Date computation: GNU
[DBG] '/usr/bin/openssl s_client' supports '-servername': using -servername servername
downloading certificate to /tmp
[DBG] executing with timeout (15s): echo 'Q' | /usr/bin/openssl s_client   -connect servername:9200 -servername servername -verify 6  -tls1_2   2> /tmp/check_ssl_cert.sheL9aBg 1> /tmp/check_ssl_cert.shDH5low
[DBG]   /usr/bin/timeout 15 /bin/sh -c "echo 'Q' | /usr/bin/openssl s_client   -connect servername:9200 -servername servername -verify 6  -tls1_2   2> /tmp/check_ssl_cert.sheL9aBg 1> /tmp/check_ssl_cert.shDH5low"
[DBG] storing a copy of the retrieved certificate in servername.crt
[DBG] storing a copy of the OpenSSL errors in servername.error
parsing the certificate file
[DBG]  subject= CN = servername
[DBG] CN         = servername
[DBG] CA_O       = City
[DBG] CA_CN      = MYISSUER
[DBG] SERIAL     = 57000007A9000007A9
[DBG] OCSP_URI   =
[DBG] ISSUER_URI = http://mypkiurl/pki/MYISSUER.crt
[DBG]     Signature Algorithm: sha256WithRSAEncryption
[DBG] Date computations: GNU
The certificate will expire in 729 day(s)
[DBG] check CN: servername 
[DBG] CN check finished
[DBG] check ISSUER: MYISSUER
[DBG] Checking expiration date
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_cert.shDH5low -noout -checkend 864000
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_cert.shDH5low -noout -checkend 3456000
[DBG] Checking revokation via OCSP
[DBG] OCSP: fetching issuer certificate http://mypkiurl/pki/MYISSUER.crt to /tmp/check_ssl_cert.sh4W6FfZ
[DBG] OCSP: issuer certificate type:  data
[DBG] OCSP: converting issuer certificate from DER to PEM
[DBG] OCSP: storing a copy of the retrieved issuer certificate to http://mypkiurl/pki/MYISSUER.crt
[DBG] OCSP: host =
[DBG] openssl ocsp support the -header option
[DBG] openssl ocsp -header requires 'key value'
[DBG] executing /usr/bin/openssl ocsp -no_nonce -issuer /tmp/check_ssl_cert.sh4W6FfZ -cert /tmp/check_ssl_cert.shDH5low  -url   -header HOST
[DBG] OCSP: response = Error parsing URL
[DBG] OCSP: response = OCSP utility
[DBG] OCSP: response = Usage ocsp [options]
[DBG] OCSP: response = where options are
[DBG] OCSP: response = -out file          output filename
[DBG] OCSP: response = -issuer file       issuer certificate
[DBG] OCSP: response = -cert file         certificate to check
[DBG] OCSP: response = -serial n          serial number to check
[DBG] OCSP: response = -signer file       certificate to sign OCSP request with
[DBG] OCSP: response = -signkey file      private key to sign OCSP request with
[DBG] OCSP: response = -sign_other file   additional certificates to include in signed request
[DBG] OCSP: response = -no_certs          don't include any certificates in signed request
[DBG] OCSP: response = -req_text          print text form of request
[DBG] OCSP: response = -resp_text         print text form of response
[DBG] OCSP: response = -text              print text form of request and response
[DBG] OCSP: response = -reqout file       write DER encoded OCSP request to "file"
[DBG] OCSP: response = -respout file      write DER encoded OCSP reponse to "file"
[DBG] OCSP: response = -reqin file        read DER encoded OCSP request from "file"
[DBG] OCSP: response = -respin file       read DER encoded OCSP reponse from "file"
[DBG] OCSP: response = -nonce             add OCSP nonce to request
[DBG] OCSP: response = -no_nonce          don't add OCSP nonce to request
[DBG] OCSP: response = -url URL           OCSP responder URL
[DBG] OCSP: response = -host host:n       send OCSP request to host on port n
[DBG] OCSP: response = -path              path to use in OCSP request
[DBG] OCSP: response = -CApath dir        trusted certificates directory
[DBG] OCSP: response = -CAfile file       trusted certificates file
[DBG] OCSP: response = -trusted_first     use trusted certificates first when building the trust chain
[DBG] OCSP: response = -VAfile file       validator certificates file
[DBG] OCSP: response = -validity_period n maximum validity discrepancy in seconds
[DBG] OCSP: response = -status_age n      maximum status age in seconds
[DBG] OCSP: response = -noverify          don't verify response at all
[DBG] OCSP: response = -verify_other file additional certificates to search for signer
[DBG] OCSP: response = -trust_other       don't verify additional certificates
[DBG] OCSP: response = -no_intern         don't search certificates contained in response for signer
[DBG] OCSP: response = -no_signature_verify don't check signature on response
[DBG] OCSP: response = -no_cert_verify    don't check signing certificate
[DBG] OCSP: response = -no_chain          don't chain verify response
[DBG] OCSP: response = -no_cert_checks    don't do additional checks on signing certificate
[DBG] OCSP: response = -port num                 port to run responder on
[DBG] OCSP: response = -index file       certificate status index file
[DBG] OCSP: response = -CA file          CA certificate
[DBG] OCSP: response = -rsigner file     responder certificate to sign responses with
[DBG] OCSP: response = -rkey file        responder key to sign responses with
[DBG] OCSP: response = -rother file      other certificates to include in response
[DBG] OCSP: response = -resp_no_certs     don't include any certificates in response
[DBG] OCSP: response = -nmin n           number of minutes before next update
[DBG] OCSP: response = -ndays n          number of days before next update
[DBG] OCSP: response = -resp_key_id       identify reponse by signing certificate key ID
[DBG] OCSP: response = -nrequest n        number of requests to accept (default unlimited)
[DBG] OCSP: response = -<dgst alg>     use specified digest in the request
[DBG] OCSP: response = 139659720894280:error:27072079:OCSP routines:OCSP_parse_url:error parsing url:ocsp_lib.c:254:
SSL_CERT CRITICAL servername : Error parsing URL
OCSP utility
Usage ocsp [options]
where options are
-out file          output filename
-issuer file       issuer certificate
-cert file         certificate to check
-serial n          serial number to check
-signer file       certificate to sign OCSP request with
-signkey file      private key to sign OCSP request with
-sign_other file   additional certificates to include in signed request
-no_certs          don't include any certificates in signed request
-req_text          print text form of request
-resp_text         print text form of response
-text              print text form of request and response
-reqout file       write DER encoded OCSP request to "file"
-respout file      write DER encoded OCSP reponse to "file"
-reqin file        read DER encoded OCSP request from "file"
-respin file       read DER encoded OCSP reponse from "file"
-nonce             add OCSP nonce to request
-no_nonce          don't add OCSP nonce to request
-url URL           OCSP responder URL
-host host:n       send OCSP request to host on port n
-path              path to use in OCSP request
-CApath dir        trusted certificates directory
-CAfile file       trusted certificates file
-trusted_first     use trusted certificates first when building the trust chain
-VAfile file       validator certificates file
-validity_period n maximum validity discrepancy in seconds
-status_age n      maximum status age in seconds
-noverify          don't verify response at all
-verify_other file additional certificates to search for signer
-trust_other       don't verify additional certificates
-no_intern         don't search certificates contained in response for signer
-no_signature_verify don't check signature on response
-no_cert_verify    don't check signing certificate
-no_chain          don't chain verify response
-no_cert_checks    don't do additional checks on signing certificate
-port num                port to run responder on
-index file      certificate status index file
-CA file                 CA certificate
-rsigner file    responder certificate to sign responses with
-rkey file       responder key to sign responses with
-rother file     other certificates to include in response
-resp_no_certs     don't include any certificates in response
-nmin n          number of minutes before next update
-ndays n                 number of days before next update
-resp_key_id       identify reponse by signing certificate key ID
-nrequest n        number of requests to accept (default unlimited)
-<dgst alg>     use specified digest in the request
139973889894216:error:27072079:OCSP routines:OCSP_parse_url:error parsing url:ocsp_lib.c:254:|days=729;40;10;;

No certificate returned on loadbalanced AWS sites

Hi,

When checking a site that is hosted on AWS and is using loadbalancing, the check returns the error that the certificate is not returned.

/usr/lib64/nagios/plugins/check_ssl_cert -H an awshosted url -c 30 -w 60 -v -A
expect not available
timeout available (/usr/bin/timeout)
found GNU date with timestamp support: enabling date computations
downloading certificate to /tmp
Error: verify depth is 6
SSL_CERT CRITICAL an awshosted url: No certificate returned

Is there a way to get around this?
I have tried for several sites hosted on AWS, all returning in the same result.

timeout not working

From @matteocorti on October 16, 2015 13:17

Original reporter: [email protected]

the plugin does not time out after 15 seconds, at least when used with STARTTLS mode and when a connection can be established, but STARTTLS is not supported. Try the following for an example:

check_ssl_cert -H mx3.safe-mail.net -p 25 -P smtp

The connection hangs indefinitely, rather than returning an error condition after the timeout has expired. This doesn't seem to happen with all hosts that don't support STARTTLS, I've so far been unable to figure out what triggers this. Calling openssl s_client with the parameters used by the plugin does return a result.

Copied from original issue: matteocorti/nagios_plugins#71

UTF-8 names in certificates

Hi Matteo,

You are so helpful, so I'm getting greedy... ;-)

Can you implement a custom parameter or something like that for openssl to properly display utf-8 names in certificates?

Now check_ssl_cert displays this:

> ./check_ssl_cert --host netlock.hu
SSL_CERT OK - x509 certificate 'www.netlock.hu' from 'NetLock \xC3\x9Czleti (Class B) Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3' valid until Apr  6 08:29:01 2018 GMT (expires today)|days=0;;;;

But I would like to see this:

> ./check_ssl_cert_utf8 --host netlock.hu
SSL_CERT OK - x509 certificate 'www.netlock.hu' from 'NetLock Üzleti (Class B) Tanúsítványkiadó' valid until Apr  6 08:29:01 2018 GMT (expires today)|days=0;;;;

I achieve this by adding -nameopt oneline,-esc_msb to your code:

--- check_ssl_cert      2018-04-05 14:05:50.000000000 +0200
+++ check_ssl_cert_utf8 2018-04-05 16:06:13.881137137 +0200
@@ -1215,7 +1215,7 @@
                         echo "File is DER encoded CRL"
                     fi
                     OPENSSL_COMMAND="crl"
-                    OPENSSL_PARAMS="-inform DER"
+                    OPENSSL_PARAMS="-inform DER -nameopt oneline,-esc_msb"
                     OPENSSL_ENDDATE_OPTION="-nextupdate"
                 else
                     critical "'${FILE}' is not a valid certificate file"
@@ -1240,7 +1240,7 @@
         else
             # parameters for regular x509 certifcates
             OPENSSL_COMMAND="x509"
-            OPENSSL_PARAMS=""
+            OPENSSL_PARAMS="-nameopt oneline,-esc_msb"
             OPENSSL_ENDDATE_OPTION="-enddate"
         fi

But I don't know if this is the right way.

Regards,
Krisztián

Curl is missing from command

Hi Matteo,

I found that if I run check_ssl_cert only with the --host option, then curl is missing from the command:

> check_ssl_cert_1.65.0 -d --host netlock.hu
[DBG] Checking revokation via OCSP
[DBG] OCSP: fetching issuer certificate http://aia1.netlock.hu/index.cgi?ca=cbca to /tmp/check_ssl_cert_1.65.0W8PjcG
[DBG] executing with timeout (15s):  --silent --location http://aia1.netlock.hu/index.cgi?ca=cbca > /tmp/check_ssl_cert_1.65.0W8PjcG
[DBG]   /usr/bin/timeout 15 /bin/sh -c " --silent --location http://aia1.netlock.hu/index.cgi?ca=cbca > /tmp/check_ssl_cert_1.65.0W8PjcG"
[DBG] OCSP: issuer certificate type:  empty

But there is no problem running like this:

> check_ssl_cert_1.65.0 -d --host netlock.hu --check-ssl-labs A
[DBG] Checking revokation via OCSP
[DBG] OCSP: fetching issuer certificate http://aia1.netlock.hu/index.cgi?ca=cbca to /tmp/check_ssl_cert_1.65.0EhK8Ws
[DBG] executing with timeout (15s): /usr/bin/curl --silent --location http://aia1.netlock.hu/index.cgi?ca=cbca > /tmp/check_ssl_cert_1.65.0EhK8Ws
[DBG]   /usr/bin/timeout 15 /bin/sh -c "/usr/bin/curl --silent --location http://aia1.netlock.hu/index.cgi?ca=cbca > /tmp/check_ssl_cert_1.65.0EhK8Ws"
[DBG] OCSP: issuer certificate type:  PEM certificate

Add support to check via IPv4 or IPv6

Is it possible to add a feature to check the certificate via IPv4 or IPv6. By default IPv6 get's preference.

Would be nice to have an option to check via IPv4 or IPv6, thanks for your efforts!

Check for missing SAN

Hello,

Thanks for this plugin, seems very useful. I was wondering if it is possible already to check for missing SAN attributes. As you might know Google has recently changes it's Chrome policy and no longer allows certificates who have no SAN. This is the error generated in Chrome:

Subject Alternative Name Missing
The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address.

For now it's possible to ignore this issue, see https://www.chromium.org/administrators/policy-list-3#EnableCommonNameFallbackForLocalAnchors

But somehwere at the end of 2017 this will no longer be possible, so I'd love to monitor for missing SAN's. :)

Grtz

Willem

Error: verify depth is 6

Hey here’s another interesting one for you, by all means let me know if you want me to throw it up as an Issue, I don’t want to be hassling you over email!

It looks like the check throws an error when it tries to evaluate the cert validity of a server that requires client certificate auth, so for example

./check_ssl_cert -H ******
SSL_CERT CRITICAL: Error: verify depth is 6

Openssl would exit with an error when run against this server, but I think you should still be able to get the server cert and validate it right?

SSL_CERT CRITICAL: Can't get connection fd

Hi

I updated check_ssl_cert to v1.51.0 from this repo (before, we had v1.16.1 installed).

Now some of the checks return the following:

SSL_CERT CRITICAL 192.168.185.112: Can't get connection fd

But this is only returned, when our Icinga installation runs the check. When I run the check manually from an SSH session, it works:

root@app2-ewmon-prod ~ # sudo -u icinga /data/icinga/libexec/check_ssl_cert -H 192.168.185.112 -w 30 -c 7 --noauth --selfsigned
SSL_CERT OK - X.509 certificate 'mail.scalera.ch' from 'QuoVadis Global SSL ICA G2' valid until Jan 12 08:37:15 2018 GMT (expires in 151 days)|days=151;30;7;;

Any idea, why this might be so?

Thanks,
Alexander

unable to load certificate

Using check_ssl_cert on Debian stretch (9.x) produces the following problem:

$ ./check_ssl_cert -v  -H www.google.com
expect available (/usr/bin/expect)
timeout available (/usr/bin/timeout)
found GNU date with timestamp support: enabling date computations
'/usr/bin/openssl s_client' does not support '-servername': disabling virtual server support
downloading certificate to /tmp
parsing the certificate file
The certificate will expire in 69 day(s)
Certificate will not expire
unable to load certificate
140524407637120:error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long:crypto/asn1/asn1_lib.c:101:
SSL_CERT CRITICAL www.google.com: unable to load certificate
140378701767808:error:0906D06C:PEM routines:PEM_read_bio:no start line:crypto/pem/pem_lib.c:691:Expecting: TRUSTED CERTIFICATE|days=69;;;;
$ dpkg -l | grep openssl
ii  openssl                                      1.1.0d-2                    amd64        Secure Sockets Layer toolkit - cryptographic utility

There is a Debian bugreport about that. Searching the network indicated that other applications have this issue too.

It seems dehydrated found a solution for this, maybe this helps.

Many thanks for looking into this and maintaining check_ssl_cert. Cheers, Jan.

Plugin run into timeout

Newest version of the plugin.
Debian: 8.8
Nagios Version: 4.2.4

The plugin runs always into a timeout.
Over the commandline:
sudo -u nagios ./check_ssl_cert -H hostname
working fine and i get a response but when nagios itself executes the command i get the error
(Service check timed out after 60.01 seconds)

Command:

define command{
	command_name	check_ssl_cert
	command_line	$USER1$/check_ssl_cert -H hostname
}

(defined already the hostname in the command to be sure it's not a other problem)

Debug:

**** BEGIN MACRO PROCESSING ***********
'$USER1$/check_ssl_cert -H hostname'
Done.  Final output: '/usr/local/nagios/libexec/check_ssl_cert -H hostname'
**** END MACRO PROCESSING *************

All other commands are working fine.

Any solutions?
Greetz

wrong regex in CN matching

Hi,

the CN matching (-N) fails when having additional informations, like an email address, in the subject.

$ openssl x509 -in mycert.pem -subject -noout -nameopt utf8,oneline,-esc_msb
subject= C = DE, ST = Foo, L = Bar, O = Baz, OU = yatta zonk, CN = my.host.name, emailAddress = [email protected]
$ openssl x509 -in mycert.pem -subject -noout -nameopt utf8,oneline,-esc_msb | sed -e "s/^.*[[:space:]]CN[[:space:]]=[[:space:]]//" -e "s/\/[[:alpha:]][[:alpha:]]*=.*\$//"
my.host.name, emailAddress = [email protected]

The slash is not a field delimiter, so the second sed instruction doesn't do anything. Better replace it with a simple -e 's/,.*//':

--- nagios-plugins-ssl_cert-1.30.0/check_ssl_cert.cnmatch
+++ nagios-plugins-ssl_cert-1.30.0/check_ssl_cert
@@ -965,7 +965,7 @@ main() {
     DATE="$($OPENSSL x509 -in "${CERT}" -enddate -noout | sed -e "s/^notAfter=//")"

     CN="$($OPENSSL x509 -in "${CERT}" -subject -noout -nameopt utf8,oneline,-esc_msb |
-        sed -e "s/^.*[[:space:]]CN[[:space:]]=[[:space:]]//" -e "s/\/[[:alpha:]][[:alpha:]]*=.*\$//")"
+        sed -e "s/^.*[[:space:]]CN[[:space:]]=[[:space:]]//" -e "s/.*\$//")"

     CA_O="$($OPENSSL x509 -in "${CERT}" -issuer -noout | sed -e "s/^.*\/O=//" -e "s/\/[A-Z][A-Z]*=.*\$//")"
     CA_CN="$($OPENSSL x509 -in "${CERT}" -issuer -noout  | sed -e "s/^.*\/CN=//" -e "s/\/[A-Za-z][A-Za-z]*=.*\$//")"

kind regards

Philippe

Feature Request Proxy for OCSP / Curl Commands

Hello,

what about a feature extension to add proxy support for the ocsp "curl" request.

For short fix i've added just the proxy for every curl command.
CURL_BIN="$CURL_BIN --proxy http://proxy:8080"

Don't force presence of Subject Altenative Name

After upgrading to V.1.51.0 the script returns an error message "The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address" if the certificate has no SAN extension.

Even though the CA/Browser Forum has recommended in 2011 that the SAN must contain at least one entry, this refers only to the use of ssl in web browsers (https) and not for other ssl uses.

RFC 2818 states: "If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used." This implies that it is perfectly legal to have a CN entry only.

It would be very helpful if there were a command line switch that would loosen the new requirement for SAN entries to be present and maybe make it the default behaviour at https checks only. I have a number of internal legacy sites that are perfectly correct but don't contain SAN entries. It makes no sense to take the risk and time of upgrading them for the only reason of pleasing my ssl cert check.

It should work with ipv6 without brackets

/usr/lib64/nagios/plugins/check_ssl_cert --host 2001:2001:2001::10 --cn example.com --warning 14 --critical 7 -p 443  --sni example.com
SSL_CERT CRITICAL 2001:2001:2001::10: No certificate returned

/usr/lib64/nagios/plugins/check_ssl_cert --host [2001:2001:2001::10] --cn example.com --warning 14 --critical 7 -p 443  --sni example.com
SSL_CERT OK - x509 certificate 'example.com' from 'Let's Encrypt Authority X3' valid until Feb 11 12:10:26 2018 GMT (expires in 89 days)|days=89;14;7;;

Temp files in /tmp

Hi,

Our HIDS gave us this alert on our Icinga 2 master:

Anomaly detected in file '/tmp/check_ssl_certmBpt6O'. Hidden from stats, but showing up on readdir. Possible kernel level rootkit.

Which made me look in /tmp folder, discovering there are thousands of files like these:

-rw-------  1 nagios   nagios     2151 May 28 22:49 check_ssl_certZZScEn
-rw-------  1 nagios   nagios     1548 May 29 16:04 check_ssl_certZZSs7R
-rw-------  1 nagios   nagios     1548 May 25 19:40 check_ssl_certzZsYGe
-rw-------  1 nagios   nagios     2151 May 30 00:18 check_ssl_certZzTyMU
-rw-------  1 nagios   nagios     1548 May 24 17:10 check_ssl_certzZzlvN

What can we do to avoid this?

Thanks and regards,
iodisciple

ISSUER_URI with trailing /

ISSUER_URIs with trailing / causes cp to fail:

        if [ -n "${DEBUG}" ] ; then
            echo "[DBG] OCSP: storing a copy of the retrieved issuer certificate to ${ISSUER_URI##*/}"
            cp "${ISSUER_CERT}" "${ISSUER_URI##*/}"
[DBG] ISSUER_URI = http://cert.int-x3.letsencrypt.org/
...
[DBG] OCSP: storing a copy of the retrieved issuer certificate to
cp: reguläre Datei „“ kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden

--altnames option question/issue.

Option description is:

--altnames matches the pattern specified in -n with alternate names too

With this option in use, I have the following issue:

./check_ssl_cert --altnames -N  -H mail.domain.com -p 465 -d
...
[DBG] check CN: *.domain.com
[DBG] the common name *.domain.com begins with a '*'
[DBG] checking if the common name matches ^domain.com$
[DBG] checking if the common name matches ^[A-Za-z0-9-]*[.]domain[.]com$
[DBG] the common name mail.domain.com matches ^[A-Za-z0-9-]*[.]domain[.]com$
[DBG] checking if the common name mail.domain.com matches ^*.domain.com$
[DBG] checking altnames against mail.domain.com
[DBG]   *.domain.com
[DBG]   domain.com
SSL_CERT CRITICAL *.domain.com: invalid CN ('*.domain.com' does not match 'mail.domain.com')|days=318;;;;

Without this option all is good:

./check_ssl_cert -N  -H mail.domain.com -p 465 -d
...
[DBG] check CN: *.domain.com
[DBG] the common name *.domain.com begins with a '*'
[DBG] checking if the common name matches ^domain.com$
[DBG] checking if the common name matches ^[A-Za-z0-9-]*[.]domain[.]com$
[DBG] the common name mail.domain.com matches ^[A-Za-z0-9-]*[.]domain[.]com$
[DBG] checking if the common name mail.domain.com matches ^*.domain.com$
[DBG] CN check finished
...

I think this option behaviour should be 'allow', not 'require', so any can use this option for unified check if certificate is good for hostname, whether this hostname will be in CN field or in 'Alternative name' field of certificate.

Proposed patch:

@@ -1250,7 +1250,7 @@
         fi

         # Check alterante names
-        if [ -n "${ALTNAMES}" ] ; then
+        if [ -n "${ALTNAMES}" ] && [ -z "$ok" ]; then

             for cn in ${COMMON_NAME} ; do

Or maybe support of wildcard should be added to alternate names check. (I don't know if CN value is always passed as first altname at all certificates too).

Unable to fetch OCSP issuer certificate

Hi,

I'm Using VERSION=1.46.0.
We're trying to check several webservers internally with your script. Unfortunately, using certs of the internal CA is causing an issue:
"SSL_CERT UNKNOWN weberserver1.lan: Unable to fetch OCSP issuer certificate"

Using the command with the parameter "-r" doesnt fix, as we referred to a local path where the ROOTCA.cer file is located.

Could you help us here? I guess the OCSP issue didnt occur before Version 1.46

checking servers that require a client certificate without having one

Sometimes a server requires a client certificate and there is no way to get one for Nagios to use when making checks.

In these cases, it would be desirable for check_ssl_cert to check the validity of the server cert and do nothing more

Currently, if it tries to connect to such a server it fails mysteriously:

$ /usr/lib/nagios/plugins/check_ssl_cert -r /etc/ssl/certs -H host.example.org -w 30 -c 21 
SSL_CERT CRITICAL: Error: verify depth is 6

Looking at the openssl s_client output, I notice these lines:

139641715861136:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1294:SSL alert number 40
139641715861136:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:618:

Could you consider adding an option to allow users to check such services?

Check against SMTP server results in extraneous output about MIME types

 ./check_ssl_cert -d -r /etc/ssl/certs -H smtp.premieronline.net -w 30 -c 15 -n *.premieronline.net -p 25 -P smtp  --ignore-sig-alg --altnames
[DBG] ROOT_CA = -CApath /etc/ssl/certs
[DBG] executing with timeout (15s): echo 'Q' | /usr/bin/openssl s_client   -starttls smtp -connect smtp.premieronline.net:25 -servername *.premieronline.net -verify 6 -CApath /etc/ssl/certs  2> /tmp/check_ssl_certa7ZyGL 1> /tmp/check_ssl_certjW0THs
[DBG]   /usr/bin/timeout 15 /bin/sh -c "echo 'Q' | /usr/bin/openssl s_client   -starttls smtp -connect smtp.premieronline.net:25 -servername *.premieronline.net -verify 6 -CApath /etc/ssl/certs  2> /tmp/check_ssl_certa7ZyGL 1> /tmp/check_ssl_certjW0THs"
[DBG] check CN: *.premieronline.net
_Warning: unknown mime-type for "\n*.premieronline.net\n" -- using "application/octet-stream"
Error: no such file "\n*.premieronline.net\n"
Warning: unknown mime-type for "\npremieronline.net\n" -- using "application/octet-stream"
Error: no such file "\npremieronline.net\n"_
[DBG] CN check finished
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_certjW0THs -noout -checkend 1296000
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_certjW0THs -noout -checkend 2592000
SSL_CERT OK - X.509 certificate for '*.premieronline.net' from 'COMODO SSL CA' valid until Jan  7 23:59:59 2018 GMT (expires in 603 days)|days=603;30;15;;

Error opening issuer certificate

Hi, the plugin was working perfectly for a longer time on CentOS 7.
Since yesterday, I get a timeout, and on manual execution/Ctrl-C the following error:

CSSL_CERT CRITICAL www.mydomain.de: Error opening issuer certificate /tmp/check_ssl_certZgQ1V0
139756719761312:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/tmp/check_ssl_certZgQ1V0','r')
139756719761312:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
unable to load certificate|days=884;;;;

OCSP falure's

Seeing "Unable to fetch OCSP issuer certificate." when checking a working domain.

Looks like the latest Centos 7 "file" command will recognise a PEM file so "file cert.crt" returns "cert.crt: PEM certificate" instead of "cert.crt: ASCII text". So some OCSP checks will fail.

Quick workaround is to change
# check the result
if ! file "${ISSUER_CERT}" | grep -q ': ASCII' ; then
to
# check the result
if ! file "${ISSUER_CERT}" | grep -q ': (ASCII|PEM)' ; then

CN check is case-sensitive

Browsers are not case-sensitive when verifying the CN of a certificate, but check_ssl_cert is:

root@xxx:~# ./check_ssl_cert-1.30.0/check_ssl_cert -H xxx.xxx.gad.local --host-cn
SSL_CERT CRITICAL xxx.xxx.GAD.local: invalid CN ('xxx.xxx.GAD.local' does not match 'xxx.xxx.gad.local')|days=501;;;;

root@xxx:~# ./check_ssl_cert-1.31.0/check_ssl_cert -H xxx.xxx.gad.local --host-cn
SSL_CERT CRITICAL xxx.xxx.GAD.local: invalid CN ('xxx.xxx.GAD.local' does not match 'xxx.xxx.gad.local')|days=501;;;;

I think it should be default to ignore the case while checking the CN.

SNI Problems

See https://sni.velox.ch for a list of SNI examples.

./check_ssl_cert -H alice.sni.velox.ch --ignore-ocsp -n bob.sni.velox.ch --Atlantis -n carol.sni.velox.ch

issues a critical status (which is correct) but with only one alternative name

./check_ssl_cert -H alice.sni.velox.ch --ignore-ocsp -n bob.sni.velox.ch --altnames -d

The result is OK as bob.sni.velox.ch is used for -servername but bob is not in the certificate delivered for alice

Cannot verify certificate: unable to get local issuer certificate

Hi,

I am attempting to use this plugin with Let's Encrypt issued certificates, but I keep running into the same error. At first I thought this was related to my specific certificate, but it seems to be a problem on all LE certificates. For testing, I used the helloworld.letsencrypt.org domain.

Is this a problem with my syntax or with the plugin?

I've tested it with various domains on various servers and have used different servers to test running the command from as well, all with the same result.

Hope you can help!

root@nagios:/home/myuser# ./check_ssl_cert -H helloworld.letsencrypt.org -c 5 -w 14 -v -d
[DBG] ROOT_CA =
expect not available
timeout available (/usr/bin/timeout)
[DBG] perl available: /usr/bin/perl
[DBG] date available: /bin/date
found GNU date with timestamp support: enabling date computations
[DBG] check_ssl_version: 1.51.0
[DBG] OpenSSL binary: /usr/bin/openssl
[DBG] OpenSSL version: OpenSSL 1.0.1f 6 Jan 2014
[DBG] System info: Linux nagios 3.13.0-73-generic #116-Ubuntu SMP Fri Dec 4 15:31:30 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
[DBG] Date computation: GNU
[DBG] '/usr/bin/openssl s_client' supports '-servername': using -servername helloworld.letsencrypt.org
downloading certificate to /tmp
[DBG] executing with timeout (15s): echo 'Q' | /usr/bin/openssl s_client -connect helloworld.letsencrypt.org:443 -servername helloworld.letsencrypt.org -verify 6 2> /tmp/check_ssl_certUtfcxw 1> /tmp/check_ssl_certfdDmsm
[DBG] /usr/bin/timeout 15 /bin/sh -c "echo 'Q' | /usr/bin/openssl s_client -connect helloworld.letsencrypt.org:443 -servername helloworld.letsencrypt.org -verify 6 2> /tmp/check_ssl_certUtfcxw 1> /tmp/check_ssl_certfdDmsm"
[DBG] storing a copy of the retrieved certificate in helloworld.letsencrypt.org.crt
[DBG] storing a copy of the OpenSSL errors in helloworld.letsencrypt.org.error
parsing the certificate file
[DBG] subject= CN = helloworld.letsencrypt.org
[DBG] CN = helloworld.letsencrypt.org
[DBG] CA_O = Let's Encrypt
[DBG] CA_CN = Let's Encrypt Authority X3
[DBG] SERIAL = 03138CE4E010536F7E690296073C556AC9D7
[DBG] OCSP_URI = http://ocsp.int-x3.letsencrypt.org
[DBG] ISSUER_URI = http://cert.int-x3.letsencrypt.org/
[DBG] Signature Algorithm: sha256WithRSAEncryption
[DBG] Date computations: GNU
The certificate will expire in 50 day(s)
[DBG] subjectAlternativeName = helloworld.letsencrypt.org
[DBG] Checking expiration date
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_certfdDmsm -noout -checkend 432000
[DBG] executing: /usr/bin/openssl x509 -in /tmp/check_ssl_certfdDmsm -noout -checkend 1209600
[DBG] Checking revokation via OCSP
[DBG] OCSP: fetching issuer certificate http://cert.int-x3.letsencrypt.org/ to /tmp/check_ssl_certaM7nxr
[DBG] OCSP: issuer certificate type: data
[DBG] OCSP: converting issuer certificate from DER to PEM
[DBG] OCSP: storing a copy of the retrieved issuer certificate to cert.int-x3.letsencrypt.org
[DBG] OCSP: host = ocsp.int-x3.letsencrypt.org
[DBG] openssl ocsp supports the -header option
[DBG] openssl ocsp -header requires 'key value'
[DBG] executing /usr/bin/openssl ocsp -no_nonce -issuer /tmp/check_ssl_certaM7nxr -cert /tmp/check_ssl_certfdDmsm -url http://ocsp.int-x3.letsencrypt.org -header HOST ocsp.int-x3.letsencrypt.org
[DBG] OCSP: response = Response Verify Failure
[DBG] OCSP: response = 140015886833312:error:27069076:OCSP routines:OCSP_basic_verify:signer certificate not found:ocsp_vfy.c:85:
[DBG] OCSP: response = /tmp/check_ssl_certfdDmsm: good
[DBG] OCSP: response = This Update: Aug 13 16:00:00 2017 GMT
[DBG] OCSP: response = Next Update: Aug 20 16:00:00 2017 GMT
[DBG] Error: verify depth is 6
[DBG] Error: depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
[DBG] Error: verify error:num=20:unable to get local issuer certificate
[DBG] Error: verify return:1
[DBG] Error: depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
[DBG] Error: verify error:num=27:certificate not trusted
[DBG] Error: verify return:1
[DBG] Error: depth=0 CN = helloworld.letsencrypt.org
[DBG] Error: verify return:1
[DBG] Error: DONE
SSL_CERT CRITICAL helloworld.letsencrypt.org: Cannot verify certificate: unable to get local issuer certificate, certificate not trusted|days=50;14;5;;

SSL Nagios

Hi
thanks for your script
i have a question
i have a server web with multi-domains and virtual host on apache server
i have 2 domains
https://www.domain.com
https://www.domain2.com
when i run the check on https://www.domain2.com the check get the date of the SSL certificate of the first virtual host
below an example
./check_ssl_cert -H www.domain2.com
i got an answer like that
SSL_CERT OK - X.509 certificate '*.domain.com' from 'COMODO RSA Domain

any ideas ?

Thanks

xmpp check not working

hi,
with OpenSSL 1.1.0f 25 May 2017 using --procotol xmpp there is no cert returned.

running bash -x check_ssl_cert shows:

/usr/bin/openssl s_client -starttls xmpp -connect localhost:5222 -servername xmpphost -verify 6

which does connect, but not return a cert.

using

/usr/bin/openssl s_client -starttls xmpp -connect localhost:5222 -xmpphost xmpphost -verify 6

a proper cert is returned.

otherwise, good work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.