Squashed commit of the following:

commit bb6ab10fdb1e8540a034ec23d869c4cac1ee1073
Merge: 45d2529 fb8f058
Author: Ramon Novoa <rnovoa@artica.es>
Date:   Wed Feb 22 13:41:36 2017 +0100

    Merge branch 'develop' into 186-tentacle-inverso-sync-server

commit 45d2529e385832c07b12b59c880602be12372dea
Author: Ramon Novoa <rnovoa@artica.es>
Date:   Wed Feb 22 13:20:35 2017 +0100

    Merge the tentacle_server with support for insecure operations.

commit 3cada513738a7034e77a275b7ecdf646354ee577
Author: Ramon Novoa <rnovoa@artica.es>
Date:   Wed Feb 22 12:59:29 2017 +0100

    Add a basic implementation of the Sync Server.

(cherry picked from commit 48b5bc54085d5a23a9b7b1d90b9d54be19aabb7d)
This commit is contained in:
Ramon Novoa 2017-02-23 14:16:26 +01:00
parent 6466a69181
commit 9d78d25c1a
4 changed files with 158 additions and 2 deletions

View File

@ -122,6 +122,9 @@ my $t_directory = '';
# Filters
my @t_filters;
# Enable (1) or disable (0) insecure mode
my $t_insecure = 0;
# String containing quoted invalid file name characters
my $t_invalid_chars = '\?\[\]\/\\\=\+\<\>\:\;\'\,\*\~';
@ -215,6 +218,7 @@ sub print_help {
print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n");
print ("\t-f ca_cert\tVerify that the peer certificate is signed by a ca.\n");
print ("\t-h\t\tShow help.\n");
print ("\t-I\t\tEnable insecure operations (file listing and moving).\n");
print ("\t-i\t\tFilters.\n");
print ("\t-k key\t\tOpenSSL private key file.\n");
print ("\t-l log_file\t\tFile to write logs.\n");
@ -278,7 +282,7 @@ sub parse_options {
my @t_addresses_tmp;
# Get options
if (getopts ('a:b:c:de:f:g:hi:k:l:m:op:qr:s:S:t:TvVwx:', \%opts) == 0 || defined ($opts{'h'})) {
if (getopts ('a:b:c:de:f:g:hIi:k:l:m:op:qr:s:S:t:TvVwx:', \%opts) == 0 || defined ($opts{'h'})) {
print_help ();
exit 1;
}
@ -356,6 +360,11 @@ sub parse_options {
}
}
# Insecure mode
if (defined ($opts{'I'})) {
$t_insecure = 1;
}
# Filters (regexp:dir;regexp:dir...)
if (defined ($opts{'i'})) {
my @filters = split (';', $opts{'i'});
@ -850,6 +859,26 @@ sub serve_connection {
print_info ("Connection closed from " . $t_client_socket->sockhost ());
last;
}
# File listing.
elsif ($command =~ /^LS <(.*)>$/) {
if ($t_insecure == 0) {
print_info ("Insecure mode disabled. Rejected request to list files matched by filter $1 from " . $t_client_socket->sockhost ());
last;
}
print_info ("Request to list files matched by filter $1 from " . $t_client_socket->sockhost ());
send_file_list ($1);
}
# Client wants to move a file
elsif ($command =~ /^MV <(.*)>$/) {
if ($t_insecure == 0) {
print_info ("Insecure mode disabled. Rejected request to move file $1 from " . $t_client_socket->sockhost ());
last;
}
print_info ("Request to move file '$1' from " . $t_client_socket->sockhost ());
move_file ($1);
}
# Unknown command
else {
print_log ("Unknown command '$command' from " . $t_client_socket->sockhost ());
@ -1055,6 +1084,110 @@ sub error {
die("\n");
}
################################################################################
## SUB move_file
## Send a file to the client and delete it
################################################################################
sub move_file {
my $base_name = $_[0];
my $data = '';
my $file;
my $response;
my $size;
# Check file name
if ($base_name =~ /[$t_invalid_chars]/) {
print_log ("Requested file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name");
send_data ("MV ERR\n");
return;
}
# Apply filters
$file = "$t_directory/" . apply_filters ($base_name) . $base_name;
# Check if file exists
if (! -f $file) {
print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " does not exist");
send_data ("MV ERR\n");
return;
}
$size = -s $file;
send_data ("MV SIZE $size\n");
# Wait for client response
$response = recv_command ($t_block_size);
if ($response ne "MV OK") {
print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " not sent");
return;
}
# Send the file
open (FILE, $file) || error ("Cannot open file '$file' for reading.");
binmode (FILE);
while ($data = <FILE>) {
send_data ($data);
}
close (FILE);
unlink($file);
print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " sent and deleted");
}
################################################################################
## SUB send_file_list
## Send a list of files to the client after applying the given filter.
################################################################################
sub send_file_list {
my $filter = $_[0];
my $data = '';
my $dir;
my $dh;
my $response;
my $size;
# Check file name
if ($filter =~ /[$t_invalid_chars]/) {
print_log ("Invalid file listing filter '$filter' from " . $t_client_socket->sockhost ());
send_data ("LS ERR\n");
return;
}
# Apply filters
$dir = "$t_directory/" . apply_filters ($filter);
# Open the directory.
if (! opendir ($dh, $dir)) {
print_log ("Error opening directory $dir as requested from " . $t_client_socket->sockhost () . ": $!");
send_data ("LS ERR\n");
return;
}
# List files.
while (my $file = readdir ($dh)) {
next if ($file =~ /[$t_invalid_chars]/); # Only list files valid for Tentacle.
next if (-d $file); # Skip directories.
$data .= "$file\n";
}
closedir $dh;
$size = length ($data);
send_data ("LS SIZE $size\n");
# Wait for client response
$response = recv_command ($t_block_size);
if ($response ne "LS OK") {
print_log ("Requested directory listing from " . $t_client_socket->sockhost () . " not sent");
return;
}
send_data ($data);
print_log ("Requested directory listing from " . $t_client_socket->sockhost () . " sent");
}
################################################################################
## SUB recv_data_proxy
## Recv data from proxy socket.

View File

@ -259,6 +259,11 @@ sub pandora_load_config {
$pa_config->{"snmpconsole_threads"} = 1; # 5.1
$pa_config->{"translate_variable_bindings"} = 0; # 5.1
$pa_config->{"translate_enterprise_strings"} = 1; # 5.1
$pa_config->{"syncserver"} = 0; # 7.0
$pa_config->{"sync_address"} = ''; # 7.0
$pa_config->{"sync_port"} = '41121'; # 7.0
$pa_config->{"sync_timeout"} = 5; # 7.0
$pa_config->{"sync_retries"} = 2; # 7.0
# Internal MTA for alerts, each server need its own config.
$pa_config->{"mta_address"} = '127.0.0.1'; # Introduced on 2.0
@ -925,6 +930,21 @@ sub pandora_load_config {
elsif ($parametro =~ m/^unknown_events\s+([0-1])/i) {
$pa_config->{'unknown_events'} = clean_blank($1);
}
elsif ($parametro =~ m/^syncserver\s+([0-9]*)/i) {
$pa_config->{'syncserver'}= clean_blank($1);
}
elsif ($parametro =~ m/^sync_address\s+(.*)/i) {
$pa_config->{'sync_address'}= clean_blank($1);
}
elsif ($parametro =~ m/^sync_port\s+([0-9]*)/i) {
$pa_config->{'sync_port'}= clean_blank($1);
}
elsif ($parametro =~ m/^sync_retries\s+([0-9]*)/i) {
$pa_config->{'sync_retries'}= clean_blank($1);
}
elsif ($parametro =~ m/^sync_timeout\s+([0-9]*)/i) {
$pa_config->{'sync_timeout'}= clean_blank($1);
}
} # end of loop for parameter #
# Set to RDBMS' standard port

View File

@ -239,7 +239,7 @@ our @EXPORT = qw(
# Some global variables
our @DayNames = qw(sunday monday tuesday wednesday thursday friday saturday);
our @ServerTypes = qw (dataserver networkserver snmpconsole reconserver pluginserver predictionserver wmiserver exportserver inventoryserver webserver eventserver icmpserver snmpserver satelliteserver);
our @ServerTypes = qw (dataserver networkserver snmpconsole reconserver pluginserver predictionserver wmiserver exportserver inventoryserver webserver eventserver icmpserver snmpserver satelliteserver transactionalserver mfserver syncserver);
our @AlertStatus = ('Execute the alert', 'Do not execute the alert', 'Do not execute the alert, but increment its internal counter', 'Cease the alert', 'Recover the alert', 'Reset internal counter');
# Event storm protection (no alerts or events)

View File

@ -58,6 +58,8 @@ our @EXPORT = qw(
SNMPSERVER
SATELLITESERVER
MFSERVER
TRANSACTIONALSERVER
SYNCSERVER
METACONSOLE_LICENSE
$DEVNULL
$OS
@ -121,6 +123,7 @@ use constant ICMPSERVER => 11;
use constant SNMPSERVER => 12;
use constant SATELLITESERVER => 13;
use constant MFSERVER => 15;
use constant SYNCSERVER => 16;
# Module statuses.
use constant STATUS_NORMAL => 0;