#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);
'name=s',
'url=s',
'warning=i',
+ 'debug',
) || usage();
if (defined($opt{'help'})) {
} 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;
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`)));
}
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( <TLSIN> ){
+ debug( "< ", $_ );
+ last if( /^220/ );
+ }
+
+ # Introduce ourselves:
+ debug( ">\n> EHLO $hostname\n>\n" );
+ print TLSOUT "EHLO $hostname\n";
+
+ # Wait until we have capabalities returned:
+ while( <TLSIN> ){
+ 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( <TLSIN> ){
+ 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( <TLSIN> ){
+ debug( "> ", $_ );
+ $return .= $_;
+ }
+ };
+
+ debug( ">\n> QUIT\n>\n" );
+ print TLSOUT "QUIT\n";
+ while( <TLSIN> ){
+ debug( "< ", $_ );
+ }
+ waitpid $pid, 0;
+
+ my $sslpid;
+ eval{
+ $sslpid = open3( \*SSLOUT, \*SSLIN, \*SSLERR, "openssl", "x509", "-text" );
+ };
+ if( $@ ){
+ die "open3: $!\n$@\n";
+ }
+ print SSLOUT $return;
+
+ while( <SSLIN> ){
+ debug( "> ", $_ );
+ $certreturn .= $_;
+ }
+
+ waitpid $sslpid, 0;
+
+ return( parse_certificate( $certreturn ) );
+
+}
+
+sub debug {
+ if( $opt{'debug'} ){
+ print @_;
+ }
+}