From 30993a027ea54aaaf7e43e31684dc23e960603a3 Mon Sep 17 00:00:00 2001 From: Michael Howe Date: Sun, 19 Jun 2011 18:53:03 +0000 Subject: [PATCH] nagios-plugins-local check_cert plugin now handles SMTP TLS, which gnutls-cli needed some hand-holding for --- debian/changelog | 6 +++ plugins/check_cert | 108 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index b279b73..1dc1d0a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +nagios-plugins-local (0.4) unstable; urgency=low + + * check_cert plugin now handles SMTP TLS. + + -- Michael Howe Sun, 19 Jun 2011 19:51:30 +0100 + nagios-plugins-local (0.3) unstable; urgency=low * check_cert plugin now handles IPv6 diff --git a/plugins/check_cert b/plugins/check_cert index 204cd03..ba48c54 100755 --- a/plugins/check_cert +++ b/plugins/check_cert @@ -9,13 +9,16 @@ #use 5.6.1; use strict; use warnings; -no warnings qw(redefine); +no warnings qw(redefine once); use Date::Parse qw(str2time); use English; use Getopt::Long; use URI; +use IPC::Open3; +use Sys::Hostname; + #use lib '/usr/local/nagios/libexec'; use lib '/usr/lib/nagios/plugins'; use utils qw(%ERRORS); @@ -64,6 +67,7 @@ GetOptions(\%opt, 'name=s', 'url=s', 'warning=i', + 'debug', ) || usage(); if (defined($opt{'help'})) { @@ -128,7 +132,7 @@ if ($scheme eq 'file') { } elsif ($scheme eq 'smtp') { $port ||= 25; - $certdata = s_client("quit", "--starttls --port $port $host"); + $certdata = get_smtp_starttls_cert( $port, $host ); } elsif ($scheme eq 'smtps') { $port ||= 465; @@ -201,6 +205,7 @@ exit($ERRORS{'OK'}); sub s_client { my ($command, $arguments) = @_; + print scalar(`/bin/echo $command | /usr/bin/gnutls-cli --insecure --print-cert $arguments 2>/dev/null | /usr/bin/openssl x509 -text 2>/dev/null`); return(parse_certificate(scalar(`/bin/echo $command | /usr/bin/gnutls-cli --insecure --print-cert $arguments 2>/dev/null | /usr/bin/openssl x509 -text 2>/dev/null`))); } @@ -233,3 +238,102 @@ sub parse_certificate { return(\%result); } +# Much of this inspired by http://www.moeding.net/archives/15-Testing-SMTP-AUTH-after-STARTTLS.html +sub get_smtp_starttls_cert { + my ( $port, $host ) = @_; + + my $hostname = hostname(); + + my $has_starttls; + my $pid; + + my $return; + my $certreturn; + + eval { + $pid = open3(\*TLSOUT, \*TLSIN, \*TLSERR, "gnutls-cli", "--crlf", "--starttls", "--insecure", "--print-cert", "--port", $port, $host ); + }; + if( $@ ){ + die "open3: $!\n$@\n"; + } + + # Wait until we receive a welcome message from SMTP server: + while( ){ + debug( "< ", $_ ); + last if( /^220/ ); + } + + # Introduce ourselves: + debug( ">\n> EHLO $hostname\n>\n" ); + print TLSOUT "EHLO $hostname\n"; + + # Wait until we have capabalities returned: + while( ){ + debug( "< ", $_ ); + + $has_starttls = 1 if( /^250-STARTTLS/ ); + last if( /^250 / ); + } + if( ! $has_starttls ){ + print "CRITICAL: SMTP server does not offer STARTTLS\n"; + exit( $ERRORS{'CRITICAL'} ); + } + + # Initialize STARTTLS + debug( ">\n> STARTTLS\n>\n" ); + print TLSOUT "STARTTLS\n"; + + # Wait until server is ready: + while( ){ + debug( "< ", $_ ); + + last if( /^220 / ); + } + + # Signal gnutls-cli to perform TLS negotiation + kill( "ALRM", $pid ); + + # Print output from process; recover from blocking read after 5s + $SIG{ALRM} = sub { die "timeout" }; + + eval { + alarm( 5 ); + + while( ){ + debug( "> ", $_ ); + $return .= $_; + } + }; + + debug( ">\n> QUIT\n>\n" ); + print TLSOUT "QUIT\n"; + while( ){ + debug( "< ", $_ ); + } + waitpid $pid, 0; + + my $sslpid; + eval{ + $sslpid = open3( \*SSLOUT, \*SSLIN, \*SSLERR, "openssl", "x509", "-text" ); + }; + if( $@ ){ + die "open3: $!\n$@\n"; + } + print SSLOUT $return; + + while( ){ + debug( "> ", $_ ); + $certreturn .= $_; + } + + waitpid $sslpid, 0; + + return( parse_certificate( $certreturn ) ); + +} + +sub debug { + if( $opt{'debug'} ){ + print @_; + } +} -- 2.39.5