add ssl option eval system (#3853)

This commit is contained in:
qgarnier 2022-08-19 15:04:09 +02:00 committed by GitHub
parent f70569a759
commit 0855348c14
4 changed files with 75 additions and 74 deletions

View File

@ -29,6 +29,7 @@ use IO::Socket::INET;
use IO::Socket::SSL; use IO::Socket::SSL;
use Net::SSLeay 1.42; use Net::SSLeay 1.42;
use DateTime; use DateTime;
use centreon::plugins::misc;
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
@ -86,13 +87,10 @@ sub check_options {
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
my $append = ''; $self->{ssl_context} = centreon::plugins::misc::eval_ssl_options(
foreach (@{$self->{option_results}->{ssl_opt}}) { output => $self->{output},
if ($_ ne '') { ssl_opt => $self->{option_results}->{ssl_opt}
$self->{ssl_context} .= $append . $_; );
$append = ', ';
}
}
return 0; return 0;
} }
@ -190,8 +188,8 @@ sub connect_starttls {
sub get_certificate_informations { sub get_certificate_informations {
my ($self, %options) = @_; my ($self, %options) = @_;
if (defined($self->{ssl_context}) && $self->{ssl_context} ne '') { if (scalar(keys %{$self->{ssl_context}}) > 0) {
my $context = new IO::Socket::SSL::SSL_Context(eval $self->{ssl_context}); my $context = new IO::Socket::SSL::SSL_Context(%{$self->{ssl_context}});
eval { IO::Socket::SSL::set_default_context($context) }; eval { IO::Socket::SSL::set_default_context($context) };
if ($@) { if ($@) {
$self->{output}->add_option_msg(short_msg => sprintf("Error setting SSL context: %s", $@)); $self->{output}->add_option_msg(short_msg => sprintf("Error setting SSL context: %s", $@));
@ -265,7 +263,7 @@ Examples:
Do not verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" Do not verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE"
Verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_PEER" --ssl-opt="SSL_version => TLSv1" Verify certificate: --ssl-opt="SSL_verify_mode => SSL_VERIFY_PEER" --ssl-opt="SSL_version => 'TLSv1'"
=item B<--ssl-ignore-errors> =item B<--ssl-ignore-errors>

View File

@ -548,6 +548,55 @@ sub uniq {
return grep { !$seen{$_}++ } @_; return grep { !$seen{$_}++ } @_;
} }
sub eval_ssl_options {
my (%options) = @_;
my $ssl_context = {};
return $ssl_context if (!defined($options{ssl_opt}));
my ($rv) = centreon::plugins::misc::mymodule_load(
output => $options{output}, module => 'Safe',
no_quit => 1
);
centreon::plugins::misc::mymodule_load(
output => $options{output}, module => 'IO::Socket::SSL',
no_quit => 1
);
my $safe;
if ($rv == 0) {
$safe = Safe->new();
$safe->permit_only(':base_core', 'rv2gv', 'padany');
$safe->share('$values');
$safe->share('$assign_var');
$safe->share_from('IO::Socket::SSL', [
'SSL_VERIFY_NONE', 'SSL_VERIFY_PEER', 'SSL_VERIFY_FAIL_IF_NO_PEER_CERT', 'SSL_VERIFY_CLIENT_ONCE',
'SSL_RECEIVED_SHUTDOWN', 'SSL_SENT_SHUTDOWN',
'SSL_OCSP_NO_STAPLE', 'SSL_OCSP_MUST_STAPLE', 'SSL_OCSP_FAIL_HARD', 'SSL_OCSP_FULL_CHAIN', 'SSL_OCSP_TRY_STAPLE'
]);
}
foreach (@{$options{ssl_opt}}) {
if (/(SSL_[A-Za-z_]+)\s+=>\s*(\S+)/) {
my ($label, $eval) = ($1, $2);
our $assign_var;
if (defined($safe)) {
$safe->reval("\$assign_var = $eval", 1);
if ($@) {
die 'Unsafe code evaluation: ' . $@;
}
} else {
eval "\$assign_var = $eval";
}
$ssl_context->{$label} = $assign_var;
}
}
return $ssl_context;
}
1; 1;
__END__ __END__

View File

@ -46,26 +46,26 @@ sub new {
if (!defined($options{noptions})) { if (!defined($options{noptions})) {
$options{options}->add_options(arguments => { $options{options}->add_options(arguments => {
'nrpe-version:s' => { name => 'nrpe_version', default => 2 }, 'nrpe-version:s' => { name => 'nrpe_version', default => 2 },
'nrpe-port:s' => { name => 'nrpe_port', default => 5666 }, 'nrpe-port:s' => { name => 'nrpe_port', default => 5666 },
'nrpe-payload:s' => { name => 'nrpe_payload', default => 1024 }, 'nrpe-payload:s' => { name => 'nrpe_payload', default => 1024 },
'nrpe-bindaddr:s' => { name => 'nrpe_bindaddr' }, 'nrpe-bindaddr:s' => { name => 'nrpe_bindaddr' },
'nrpe-use-ipv4' => { name => 'nrpe_use_ipv4' }, 'nrpe-use-ipv4' => { name => 'nrpe_use_ipv4' },
'nrpe-use-ipv6' => { name => 'nrpe_use_ipv6' }, 'nrpe-use-ipv6' => { name => 'nrpe_use_ipv6' },
'nrpe-timeout:s' => { name => 'nrpe_timeout', default => 10 }, 'nrpe-timeout:s' => { name => 'nrpe_timeout', default => 10 },
'ssl-opt:s@' => { name => 'ssl_opt' }, 'ssl-opt:s@' => { name => 'ssl_opt' }
}); });
} }
$options{options}->add_help(package => __PACKAGE__, sections => 'NRPE CLASS OPTIONS'); $options{options}->add_help(package => __PACKAGE__, sections => 'NRPE CLASS OPTIONS');
$self->{output} = $options{output}; $self->{output} = $options{output};
return $self; return $self;
} }
sub check_options { sub check_options {
my ($self, %options) = @_; my ($self, %options) = @_;
$options{option_results}->{nrpe_version} =~ s/^v//; $options{option_results}->{nrpe_version} =~ s/^v//;
if ($options{option_results}->{nrpe_version} !~ /2|3|4/) { if ($options{option_results}->{nrpe_version} !~ /2|3|4/) {
$self->{output}->add_option_msg(short_msg => "Unknown NRPE version."); $self->{output}->add_option_msg(short_msg => "Unknown NRPE version.");
@ -88,59 +88,12 @@ sub check_options {
$self->{nrpe_params}->{Domain} = AF_INET6; $self->{nrpe_params}->{Domain} = AF_INET6;
} }
$self->{ssl_context} = {}; $self->{ssl_context} = centreon::plugins::misc::eval_ssl_options(
foreach (@{$options{option_results}->{ssl_opt}}) { output => $self->{output},
if (/(SSL_[A-Za-z_]+)\s+=>\s*(\S+)/) { ssl_opt => $self->{option_results}->{ssl_opt}
my $value = $2;
$value = $self->assign_eval(eval => $value);
$self->{ssl_context}->{$1} = $value;
}
}
}
sub load_eval {
my ($self) = @_;
my ($code) = centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => 'Safe',
no_quit => 1
); );
if ($code == 0) {
$self->{safe} = Safe->new();
$self->{safe}->permit_only(':base_core', 'rv2gv', 'padany');
$self->{safe}->share('$values');
$self->{safe}->share('$assign_var');
$self->{safe}->share_from('IO::Socket::SSL', [
'SSL_VERIFY_NONE', 'SSL_VERIFY_PEER', 'SSL_VERIFY_FAIL_IF_NO_PEER_CERT', 'SSL_VERIFY_CLIENT_ONCE',
'SSL_RECEIVED_SHUTDOWN', 'SSL_SENT_SHUTDOWN',
'SSL_OCSP_NO_STAPLE', 'SSL_OCSP_MUST_STAPLE', 'SSL_OCSP_FAIL_HARD', 'SSL_OCSP_FULL_CHAIN', 'SSL_OCSP_TRY_STAPLE'
]);
}
$self->{safe_test} = 1;
} }
sub assign_eval {
my ($self, %options) = @_;
$self->load_eval() if (!defined($self->{safe_test}) || $self->{safe_test} == 0);
our $assign_var;
if (defined($self->{safe})) {
our $values = $options{values};
$self->{safe}->reval("\$assign_var = $options{eval}", 1);
if ($@) {
die 'Unsafe code evaluation: ' . $@;
}
} else {
my $values = $options{values};
eval "\$assign_var = $options{eval}";
}
return $assign_var;
}
sub create_socket { sub create_socket {
my ($self, %options) = @_; my ($self, %options) = @_;

View File

@ -26,6 +26,7 @@ use DateTime;
use MongoDB; use MongoDB;
use Hash::Ordered; use Hash::Ordered;
use URI::Encode; use URI::Encode;
use centreon::plugins::misc;
sub new { sub new {
my ($class, %options) = @_; my ($class, %options) = @_;
@ -83,10 +84,10 @@ sub check_options {
$self->{output}->option_exit(); $self->{output}->option_exit();
} }
foreach (@{$self->{option_results}->{ssl_opt}}) { $self->{ssl_opts} = centreon::plugins::misc::eval_ssl_options(
$_ =~ /(\w+)\s*=>\s*(\w+)/; output => $self->{output},
$self->{ssl_opts}->{$1} = $2; ssl_opt => $self->{option_results}->{ssl_opt}
} );
return 0; return 0;
} }