1#!/usr/local/bin/perl 2use strict; 3my $VERSION = '0.1'; 4my $COPYRIGHT = 'Copyright (C) 2005-2011 Jonathan Buhacoff <jonathan@buhacoff.net>'; 5my $LICENSE = 'http://www.gnu.org/licenses/gpl.txt'; 6my %status = ( 'OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3 ); 7 8use Getopt::Long; 9use Mail::IMAPClient; 10use IO::Socket::SSL; 11use Net::SSLeay; 12 13# get options from command line 14Getopt::Long::Configure("bundling"); 15my $verbose = 0; 16my $help = ""; 17my $help_usage = ""; 18my $show_version = ""; 19my $imap_server = ""; 20my $default_imap_port = "143"; 21my $default_imap_ssl_port = "993"; 22my $imap_port = ""; 23my $timeout = 60; 24my $ok; 25$ok = Getopt::Long::GetOptions( 26 "V|version"=>\$show_version, 27 "v|verbose+"=>\$verbose,"h|help"=>\$help,"usage"=>\$help_usage, 28 # imap settings 29 "H|hostname=s"=>\$imap_server,"p|port=i"=>\$imap_port, 30 # time 31 "t|timeout=i"=>\$timeout 32 ); 33 34if( $show_version ) { 35 print "$VERSION\n"; 36 exit $status{UNKNOWN}; 37} 38 39if( $help ) { 40 exec "perldoc", $0 or print "Try `perldoc $0`\n"; 41 exit $status{UNKNOWN}; 42} 43 44if( $help_usage 45 || 46 ( $imap_server eq "" ) 47 ) { 48 print "Usage: $0 -H host [-p port]\n"; 49 exit $status{UNKNOWN}; 50} 51 52my @certs = (); # we have to store the certs we get Net::SSLeay here so that we can output them in REVERSE order (server cert first, root cert last) 53 54# connect to IMAP server 55print "connecting to server $imap_server\n" if $verbose > 2; 56my $imap; 57eval { 58 local $SIG{ALRM} = sub { die "exceeded timeout $timeout seconds\n" }; # NB: \n required, see `perldoc -f alarm` 59 alarm $timeout; 60 61 $imap_port = $default_imap_ssl_port unless $imap_port; 62 my $socket = IO::Socket::SSL->new( 63 PeerAddr => "$imap_server:$imap_port", 64 SSL_verify_mode => 1, 65 SSL_ca_file => undef, 66 SSL_verifycn_scheme => 'imap', 67 SSL_verifycn_name => $imap_server, 68 SSL_verify_callback => \&ssl_printer 69 ); 70 die IO::Socket::SSL::errstr() unless $socket; 71 $socket->autoflush(1); 72 $imap = Mail::IMAPClient->new(Socket=>$socket, Debug => 0 ); 73 $imap->State(Mail::IMAPClient->Connected); 74 $imap->_read_line() if "$Mail::IMAPClient::VERSION" le "2.2.9"; # necessary to remove the server's "ready" line from the input buffer for old versions of Mail::IMAPClient. Using string comparison for the version check because the numeric didn't work on Darwin and for Mail::IMAPClient the next version is 2.3.0 and then 3.00 so string comparison works 75# $imap->User($username); 76# $imap->Password($password); 77# $imap->login() or die "Cannot login: $@"; 78 79 print join("\n",reverse(@certs)); 80 alarm 0; 81}; 82if( $@ ) { 83 chomp $@; 84 print "Could not connect to $imap_server port $imap_port: $@\n"; 85 exit $status{CRITICAL}; 86} 87unless( $imap ) { 88 print "Could not connect to $imap_server port $imap_port: $@\n"; 89 exit $status{CRITICAL}; 90} 91 92# deselect the mailbox 93$imap->close(); 94 95# disconnect from IMAP server 96print "disconnecting from server\n" if $verbose > 2; 97$imap->logout(); 98 99 100exit $status{OK}; 101 102# see IO::Socket::SSL documentation for SSL_verify_callback: 103sub ssl_printer { 104 my ($boolOpenSSLResult, $cmemCertificateStore, $strCertIssuerOwnerAttr, $strError, $cmemPeerCertificate) = @_; 105 warn "OpenSSL says certificate is " . ( $boolOpenSSLResult ? "valid" : "invalid" ) if $verbose > 0; 106 warn "Peer certificate: $strCertIssuerOwnerAttr" if $verbose > 0; 107 warn "Errors: $strError" if $verbose > 0; 108 #print Net::SSLeay::PEM_get_string_X509($cmemPeerCertificate); 109 push @certs, $strCertIssuerOwnerAttr . "\n" . Net::SSLeay::PEM_get_string_X509($cmemPeerCertificate); 110} 111 112package main; 1131; 114 115