From df7ab970d2d934579ef0632d821653a46c06b587 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 12 Feb 2020 16:03:58 +0100 Subject: [PATCH] Fix #1834 --- apps/protocols/imap/lib/imap.pm | 46 ++++++++------ apps/protocols/imap/mode/login.pm | 64 ++++++++++++------- apps/protocols/imap/mode/searchmessage.pm | 75 ++++++++++++++--------- 3 files changed, 116 insertions(+), 69 deletions(-) diff --git a/apps/protocols/imap/lib/imap.pm b/apps/protocols/imap/lib/imap.pm index b6953ee89..1dca756da 100644 --- a/apps/protocols/imap/lib/imap.pm +++ b/apps/protocols/imap/lib/imap.pm @@ -23,6 +23,7 @@ package apps::protocols::imap::lib::imap; use strict; use warnings; use Net::IMAP::Simple; +use IO::Socket::SSL; my $imap_handle; @@ -32,63 +33,72 @@ sub quit { sub search { my ($self, %options) = @_; - + if (!defined($imap_handle->select($self->{option_results}->{folder}))) { my $output = $imap_handle->errstr; $output =~ s/\r//g; - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'Folder Select Error: ' . $output); + $self->{output}->output_add( + severity => 'UNKNOWN', + short_msg => 'Folder Select Error: ' . $output + ); quit(); $self->{output}->display(); $self->{output}->exit(); } - + my @ids = $imap_handle->search($self->{option_results}->{search}); - + if (defined($self->{option_results}->{delete})) { foreach my $msg_num (@ids) { $imap_handle->delete($msg_num); } $imap_handle->expunge_mailbox(); } - + return scalar(@ids); } sub connect { my ($self, %options) = @_; my %imap_options = (); - + my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown'; $imap_options{port} = $self->{option_results}->{port} if (defined($self->{option_results}->{port})); $imap_options{use_ssl} = 1 if (defined($self->{option_results}->{use_ssl})); $imap_options{timeout} = $self->{option_results}->{timeout} if (defined($self->{option_results}->{timeout})); - + if ($self->{ssl_options} ne '') { + $imap_options{ssl_options} = [ eval $self->{ssl_options} ]; + } + if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' && !defined($self->{option_results}->{password})) { - $self->{output}->add_option_msg(short_msg => "Please set --password option."); + $self->{output}->add_option_msg(short_msg => 'Please set --password option.'); $self->{output}->option_exit(); } - - $imap_handle = Net::IMAP::Simple->new($self->{option_results}->{hostname}, + + $imap_handle = Net::IMAP::Simple->new( + $self->{option_results}->{hostname}, %imap_options ); - - + if (!defined($imap_handle)) { - $self->{output}->output_add(severity => $connection_exit, - short_msg => 'Unable to connect to IMAP: ' . $Net::IMAP::Simple::errstr); + $self->{output}->output_add( + severity => $connection_exit, + short_msg => 'Unable to connect to IMAP: ' . $Net::IMAP::Simple::errstr + ); $self->{output}->display(); $self->{output}->exit(); } - + if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '') { if (!$imap_handle->login($self->{option_results}->{username}, $self->{option_results}->{password})) { # Exchange put '\r'... my $output = $imap_handle->errstr; $output =~ s/\r//g; - $self->{output}->output_add(severity => $connection_exit, - short_msg => 'Login failed: ' . $output); + $self->{output}->output_add( + severity => $connection_exit, + short_msg => 'Login failed: ' . $output + ); quit(); $self->{output}->display(); $self->{output}->exit(); diff --git a/apps/protocols/imap/mode/login.pm b/apps/protocols/imap/mode/login.pm index 438ae899a..3f3a132ac 100644 --- a/apps/protocols/imap/mode/login.pm +++ b/apps/protocols/imap/mode/login.pm @@ -32,17 +32,18 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', }, - "ssl" => { name => 'use_ssl' }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - "timeout:s" => { name => 'timeout', default => '30' }, - }); + $options{options}->add_options(arguments => { + 'hostname:s' => { name => 'hostname' }, + 'port:s' => { name => 'port', }, + 'ssl' => { name => 'use_ssl' }, + 'ssl-opt:s@' => { name => 'ssl_opt' }, + 'username:s' => { name => 'username' }, + 'password:s' => { name => 'password' }, + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'timeout:s' => { name => 'timeout', default => '30' } + }); + return $self; } @@ -63,26 +64,40 @@ sub check_options { $self->{output}->add_option_msg(short_msg => "Please set the hostname option"); $self->{output}->option_exit(); } + + my $append = ''; + $self->{ssl_options} = ''; + foreach (@{$self->{option_results}->{ssl_opt}}) { + if ($_ ne '') { + $self->{ssl_options} .= $append . $_; + $append = ', '; + } + } } sub run { my ($self, %options) = @_; - + my $timing0 = [gettimeofday]; - apps::protocols::imap::lib::imap::connect($self, connection_exit => 'critical'); apps::protocols::imap::lib::imap::quit(); my $timeelapsed = tv_interval($timing0, [gettimeofday]); - - my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Response time %.3f ", $timeelapsed)); - $self->{output}->perfdata_add(label => "time", - value => sprintf('%.3f', $timeelapsed), - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); + + my $exit = $self->{perfdata}->threshold_check( + value => $timeelapsed, + threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] + ); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Response time %.3f ", $timeelapsed) + ); + $self->{output}->perfdata_add( + label => 'time', + value => sprintf('%.3f', $timeelapsed), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical') + ); $self->{output}->display(); $self->{output}->exit(); @@ -109,7 +124,10 @@ Port used =item B<--ssl> Use SSL connection. -(no attempt is made to check the certificate validity by default). + +=item B<--ssl-opt> + +Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'" =item B<--username> diff --git a/apps/protocols/imap/mode/searchmessage.pm b/apps/protocols/imap/mode/searchmessage.pm index cac3c8451..adea0ca80 100644 --- a/apps/protocols/imap/mode/searchmessage.pm +++ b/apps/protocols/imap/mode/searchmessage.pm @@ -31,20 +31,21 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', }, - "ssl" => { name => 'use_ssl' }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - "timeout:s" => { name => 'timeout', default => '30' }, - "search:s" => { name => 'search' }, - "delete" => { name => 'delete' }, - "folder:s" => { name => 'folder', default => 'INBOX' }, - }); + $options{options}->add_options(arguments => { + 'hostname:s' => { name => 'hostname' }, + 'port:s' => { name => 'port', }, + 'ssl' => { name => 'use_ssl' }, + 'ssl-opt:s@' => { name => 'ssl_opt' }, + 'username:s' => { name => 'username' }, + 'password:s' => { name => 'password' }, + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'timeout:s' => { name => 'timeout', default => '30' }, + 'search:s' => { name => 'search' }, + 'delete' => { name => 'delete' }, + 'folder:s' => { name => 'folder', default => 'INBOX' } + }); + return $self; } @@ -62,32 +63,47 @@ sub check_options { } if (!defined($self->{option_results}->{hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); + $self->{output}->add_option_msg(short_msg => 'Please set the --hostname option'); $self->{output}->option_exit(); } if (!defined($self->{option_results}->{search})) { - $self->{output}->add_option_msg(short_msg => "Please set the --search option"); + $self->{output}->add_option_msg(short_msg => 'Please set the --search option'); $self->{output}->option_exit(); } + + my $append = ''; + $self->{ssl_options} = ''; + foreach (@{$self->{option_results}->{ssl_opt}}) { + if ($_ ne '') { + $self->{ssl_options} .= $append . $_; + $append = ', '; + } + } } sub run { my ($self, %options) = @_; - + apps::protocols::imap::lib::imap::connect($self); my ($num) = apps::protocols::imap::lib::imap::search($self); apps::protocols::imap::lib::imap::quit(); - - my $exit = $self->{perfdata}->threshold_check(value => $num, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("%d message found(s)", $num)); - $self->{output}->perfdata_add(label => "numbers", - value => $num, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); - + my $exit = $self->{perfdata}->threshold_check( + value => $num, + threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ] + ); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf('%d message(s) found', $num) + ); + $self->{output}->perfdata_add( + label => 'numbers', + value => $num, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), + min => 0 + ); + $self->{output}->display(); $self->{output}->exit(); } @@ -113,7 +129,10 @@ Port used =item B<--ssl> Use SSL connection. -(no attempt is made to check the certificate validity by default). + +=item B<--ssl-opt> + +Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'" =item B<--username>