From e37ecc64c320cad1c264c28127bdc07d2858fac1 Mon Sep 17 00:00:00 2001 From: Tomas Plesnik <plesnik@ics.muni.cz> Date: Tue, 14 Oct 2014 16:09:34 +0200 Subject: [PATCH] bugfix: opraveno ziskavani udalosti z databaze ve funkci getNewEvents (dva SELECTy nahrazeny jednim SELECT JOINem); odstraneno nadbytecne preukladani hodnot z db do novych promennych; uprava a zjednoduseni logovacich hlasek; lepsi prehlednost kodu (nahrazeni negovanych ifu za unless); uprava odsazeni --- src/warden-server/lib/Warden.pm | 246 ++++++++++++-------------------- 1 file changed, 94 insertions(+), 152 deletions(-) diff --git a/src/warden-server/lib/Warden.pm b/src/warden-server/lib/Warden.pm index faeae35..75804ae 100755 --- a/src/warden-server/lib/Warden.pm +++ b/src/warden-server/lib/Warden.pm @@ -90,6 +90,7 @@ sub getAltNames push(@an_array, $DBH->quote($tmp)); } } + my $alt_names = join(',', @an_array); return $alt_names; } @@ -116,7 +117,7 @@ sub authorizeClient } # check if db handler is defined - if (!defined $sth) { + unless (defined $sth) { sendMsg("err", "Cannot prepare authorization statement in function 'authorizeClient': $DBH->errstr", "Internal 'prepare' server error"); @@ -125,14 +126,14 @@ sub authorizeClient # execute query for two or none params functions if ($function_name eq 'saveNewEvent' || $function_name eq 'getNewEvents') { $rc = $sth->execute($service_type, $client_type); - if (!$rc) { + unless ($rc) { sendMsg("err", "Cannot execute authorization statement in function 'authorizeClient': $DBH->errstr", "Internal 'execute' server error"); } } else { $rc = $sth->execute; - if (!$rc) { + unless ($rc) { sendMsg("err", "Cannot execute authorization statement in function 'authorizeClient': $DBH->errstr", "Internal 'execute' server error"); @@ -143,7 +144,7 @@ sub authorizeClient my ($client_id, $ip_net_client, $receive_own, $ip_net_client_list); my $correct_ip_source = 0; my %ret; - while(($client_id, $ip_net_client, $receive_own) = $sth->fetchrow()) { + while(($client_id, $ip_net_client, $receive_own) = $sth->fetchrow()) { my $ip_net_client_list = Net::CIDR::Lite->new->add($ip_net_client); $ret{'client_id'} = $client_id; @@ -164,7 +165,7 @@ sub authorizeClient } # check if client has IP from registered CIDR - if (!$correct_ip_source) { + unless ($correct_ip_source) { sendMsg ("err", "Unauthorized access to function '$function_name' from [IP: '$ip'; CN(AN): $alt_names; Client_type: '$client_type'; Service/Type: '$service_type'] - access to Warden server '$ENV{'SERVER_NAME'}' from another subnet than '$ip_net_client'", "Access denied - access to Warden server '$ENV{'SERVER_NAME'}' from unauthorized subnet '$ip_net_client'"); @@ -215,16 +216,17 @@ sub saveNewEvent my %client = authorizeClient($alt_names, $ip, $service, $client_type, $function_name); if (defined %client) { sendMsg("debug", - "Incoming event: [service: '$service', detected: '$detected', type: '$type', source_type: '$source_type', source: '$source', target_proto: '$target_proto', target_port: '$target_port', attack_scale: '$attack_scale', note: '$note', priority: '$priority', timeout: '$timeout']", + "Incoming event: [client_id: '$client{'client_id'}', service: '$service', detected: '$detected', type: '$type', source_type: '$source_type', source: '$source', target_proto: '$target_proto', target_port: '$target_port', attack_scale: '$attack_scale', note: '$note', priority: '$priority', timeout: '$timeout']", undef); + if (%WardenCommon::VALID_STRINGS) { # check if hash is not empty - use VALIDATION HASH if (!(exists $WardenCommon::VALID_STRINGS{'type'} && grep $type eq $_, @{$WardenCommon::VALID_STRINGS{'type'}})) { sendMsg("err", - "Unknown event type from [IP: '$ip'; CN(AN): $alt_names; Service: '$service'; Type: '$type']", + "Unknown event_type from client '$client{'client_id'}': '$type'", "Unknown event type: '$type'"); } elsif (!(exists $WardenCommon::VALID_STRINGS{'source_type'} && grep $source_type eq $_, @{$WardenCommon::VALID_STRINGS{'source_type'}})) { sendMsg("err", - "Unknown source type from [IP '$ip'; CN(AN): $alt_names; Service: '$service'; Source_type: '$source_type']", + "Unknown source_type from client '$client{'client_id'}': '$source_type'", "Unknown source type: '$source_type'"); } } @@ -232,7 +234,7 @@ sub saveNewEvent # http://my.safaribooksonline.com/book/programming/regular-expressions/9780596802837/4dot-validation-and-formatting/id2983571 if ($detected !~ /^((?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?/) { sendMsg("err", - "Unknown detected time format from [IP: '$ip'; CN(AN): $alt_names; Service: '$service'; Detected: '$detected']", + "Unknown detected time format from client '$client{'client_id'}': '$detected'", "Unknown detected time format: '$detected'"); } @@ -241,33 +243,38 @@ sub saveNewEvent push(@change_list, "target_port: '$target_port'"); $target_port = undef; } + if (defined $attack_scale && $attack_scale !~ /^\d+\z/) { push(@change_list, "attack_scale: '$attack_scale'"); $attack_scale = undef; } + if (defined $priority && $priority !~ /^\d+\z/) { push(@change_list, "priority: '$priority'"); $priority = undef; } + if (defined $timeout && $timeout !~ /^\d+\z/) { push(@change_list, "timeout: '$timeout'"); $timeout = undef; } + my $change_string = join(", ", @change_list); - if ($change_string ne "") { + unless ($change_string eq "") { sendMsg("info", - "Unknown event items detected {originaly - $change_string} received in $received from [IP '$ip'; CN(AN): $alt_names; Service: '$service'; Type: '$type'; Detected: $detected]", + "Unknown other event entries from client '$client{'client_id'}': ($change_string)", undef); } $sth = $DBH->prepare("INSERT INTO events VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); - if (!defined $sth) { + unless (defined $sth) { sendMsg("err", "Cannot prepare statement in function '$function_name': $DBH->errstr", "Internal 'prepare' server error"); } + $rc = $sth->execute(undef, $detected, $received, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $valid, $client{'client_id'}); - if (!$rc) { + unless ($rc) { sendMsg("err", "Cannot execute statement in function '$function_name': $DBH->errstr", "Internal 'execute' server error"); @@ -283,15 +290,14 @@ sub saveNewEvent sub getNewEvents { my ($class, $data) = @_; - my ($sth, $sth2, $rc, @events, $event, @ids); - my ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $client_id); + my ($sth, $rc, @events, $event, @ids, $used_limit); # client network information my $cn = $ENV{'SSL_CLIENT_S_DN_CN'}; my $alt_names = getAltNames(undef); my $ip = $ENV{'REMOTE_ADDR'}; - my $client_type = 'r'; # incoming client MUST be sender + my $client_type = 'r'; # incoming client MUST be receiver my $function_name = 'getNewEvents'; # parse SOAP data object @@ -300,139 +306,82 @@ sub getNewEvents my $max_rcv_events_limit = $data->{'MAX_RCV_EVENTS_LIMIT'}; # client events limit # comparison of client and server limit - which can be used - my $used_limit; if (defined $max_rcv_events_limit && $max_rcv_events_limit < $WardenCommon::MAX_EVENTS_LIMIT) { $used_limit = $max_rcv_events_limit; } else { $used_limit = $WardenCommon::MAX_EVENTS_LIMIT; } + # authorize incoming client my %client = authorizeClient($alt_names, $ip, $requested_type, $client_type, $function_name); - if(defined %client) { - if ($client{'receive_own'} eq 't') { - if ($requested_type eq '_any_') { - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND valid = 't' ORDER BY id ASC LIMIT ?;"); - if (!defined $sth) { - sendMsg("err", - "Cannot prepare ROE-ANY statement in function '$function_name': $DBH->errstr", - "Internal 'prepare' server error"); - } - $rc = $sth->execute($last_id, $used_limit); - if (!$rc) { - sendMsg("err", - "Cannot execute ROE-ANY statement in function '$function_name': $DBH->errstr", - "Internal 'execute' server error"); - } - } else { - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' ORDER BY id ASC LIMIT ?;"); - if (!defined $sth) { - sendMsg("err", - "Cannot prepare ROE statement in function '$function_name': $DBH->errstr", - "Internal 'prepare' server error"); - } - $rc = $sth->execute($last_id, $requested_type, $used_limit); - if (!$rc) { - sendMsg("err", - "Cannot execute ROE statement in function '$function_name': $DBH->errstr", - "Internal 'execute' server error"); - } - } - } else { - if ($requested_type eq '_any_') { - $sth = $DBH->prepare("SELECT * FROM events e, clients c WHERE e.type != 'test' AND e.id > ? AND e.valid = 't' AND e.client_id = c.client_id AND c.hostname NOT LIKE ? ORDER BY id ASC LIMIT ?;"); - if (!defined $sth) { - sendMsg("err", - "Cannot prepare ANY statement in function '$function_name': $DBH->errstr", - "Internal 'prepare' server error"); - } - my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; - $domain = '%' . $domain; - $rc = $sth->execute($last_id, $domain, $used_limit); - if (!$rc) { - sendMsg("err", - "Cannot execute ANY statement in function '$function_name': $DBH->errstr", - "Internal 'execute' server error"); - } - } else { - $sth = $DBH->prepare("SELECT * FROM events e, clients c WHERE e.type != 'test' AND e.id > ? AND e.type = ? AND e.valid = 't' AND e.client_id = c.client_id AND c.hostname NOT LIKE ? ORDER BY id ASC LIMIT ?;"); - if (!defined $sth) { - sendMsg("err", - "Cannot prepare statement in function '$function_name': $DBH->errstr", - "Internal 'prepare' server error"); - } - my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; - $domain = '%' . $domain; - $rc = $sth->execute($last_id, $requested_type, $domain, $used_limit); - if (!$rc) { - sendMsg("err", - "Cannot execute statement in function '$function_name': $DBH->errstr", - "Internal 'execute' server error"); - } - } + if (defined %client) { + my $query = "SELECT id, hostname, service, detected, events.type, source_type, source, target_proto, target_port, attack_scale, note, priority, timeout FROM events INNER JOIN clients ON events.client_id = clients.client_id WHERE events.type != 'test' AND id > ? AND events.valid = 't'"; + my @params = ($last_id); + + unless ($requested_type eq '_any_') { + $query .= " AND events.type = ?"; + push(@params, $requested_type); + } + + unless ($client{'receive_own'} eq 't') { + my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; + $query .= " AND hostname NOT LIKE ?"; + push(@params, '%' . $domain); + } + + $query .= " ORDER BY id ASC LIMIT ?;"; + push(@params, $used_limit); + + $sth = $DBH->prepare($query); + unless (defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + + $rc = $sth->execute(@params); + unless (defined $rc) { + sendMsg("err", + "Cannot execute statement in function '$function_name': $DBH->errstr", + "Internal 'execute' server error"); } # obtain items of events stored in events table while (my @result = $sth->fetchrow()) { - $id = $result[0]; - $detected = $result[1]; - $type = $result[3]; - $source_type = $result[4]; - $source = $result[5]; - $target_proto = $result[6]; - $target_port = $result[7]; - $attack_scale = $result[8]; - $note = $result[9]; - $priority = $result[10]; - $timeout = $result[11]; - $client_id = $result[13]; - - # obtain hostname and service of events based on client_id from clients table - $sth2 = $DBH->prepare("SELECT hostname, service FROM clients WHERE client_id = ?;"); - if (!defined $sth2) { - sendMsg("err", - "Cannot prepare statement in function '$function_name': $DBH->errstr", - "Internal 'prepare' server error"); - } - $rc = $sth2->execute($client_id); - if (!$rc) { - sendMsg("err", - "Cannot execute statement in function '$function_name': $DBH->errstr", - "Internal 'execute' server error"); - } - ($hostname, $service) = $sth2->fetchrow(); - - # create SOAP data object + # create SOAP data object set values $event = SOAP::Data->name(event => \SOAP::Data->value( - SOAP::Data->name(ID => $id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(DETECTED => $detected), - SOAP::Data->name(TYPE => $type), - SOAP::Data->name(SOURCE_TYPE => $source_type), - SOAP::Data->name(SOURCE => $source), - SOAP::Data->name(TARGET_PROTO => $target_proto), - SOAP::Data->name(TARGET_PORT => $target_port), - SOAP::Data->name(ATTACK_SCALE => $attack_scale), - SOAP::Data->name(NOTE => $note), - SOAP::Data->name(PRIORITY => $priority), - SOAP::Data->name(TIMEOUT => $timeout) - )); + SOAP::Data->name(ID => $result[0]), + SOAP::Data->name(HOSTNAME => $result[1]), + SOAP::Data->name(SERVICE => $result[2]), + SOAP::Data->name(DETECTED => $result[3]), + SOAP::Data->name(TYPE => $result[4]), + SOAP::Data->name(SOURCE_TYPE => $result[5]), + SOAP::Data->name(SOURCE => $result[6]), + SOAP::Data->name(TARGET_PROTO => $result[7]), + SOAP::Data->name(TARGET_PORT => $result[8]), + SOAP::Data->name(ATTACK_SCALE => $result[9]), + SOAP::Data->name(NOTE => $result[10]), + SOAP::Data->name(PRIORITY => $result[11]), + SOAP::Data->name(TIMEOUT => $result[12]), + ), + ); push(@events, $event); - push(@ids, $id); + push(@ids, $result[0]); } # log sent ID of events if (scalar @events != 0) { if (scalar @ids == 1) { sendMsg("info", - "Sent 1 event [#$ids[0]] to [IP: '$ip'; CN(AN): $alt_names; Client_limit: '$max_rcv_events_limit'; Requested_type: '$requested_type'; ROE: '$client{'receive_own'}']", + "Sent 1 event [#$ids[0]] of type '$requested_type' to client '$client{'client_id'}'", undef); } else { sendMsg("info", - "Sent " . scalar @ids . " events [#$ids[0] - #$ids[-1]] to [IP: '$ip'; CN(AN): $alt_names; Client_limit: '$max_rcv_events_limit'; Requested_type: '$requested_type'; ROE: '$client{'receive_own'}']", + "Sent " . scalar @ids . " events [#$ids[0] - #$ids[-1]] of type '$requested_type' to client '$client{'client_id'}'", undef); } } + return @events; } } # END of getNewEvents @@ -458,17 +407,19 @@ sub getLastId my %client = authorizeClient($alt_names, $ip, $service, $client_type, $function_name); if (defined %client) { my $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if (!defined $sth) { + unless (defined $sth) { sendMsg("err", "Cannot prepare statement in function '$function_name': $DBH->errstr", "Internal 'prepare' server error"); } + my $rc = $sth->execute; - if (!$rc) { + unless ($rc) { sendMsg("err", "Cannot execute statement in function '$function_name': $DBH->errstr", "Internal 'execute' server error"); } + my $result = $sth->fetchrow(); return $result; } @@ -483,7 +434,6 @@ sub getClientInfo { my ($class, $data) = @_; my (@clients, $client); - my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); # client network information my $cn = $ENV{'SSL_CLIENT_S_DN_CN'}; @@ -498,47 +448,39 @@ sub getClientInfo my %client = authorizeClient($alt_names, $ip, $service, $client_type, $function_name); if (defined %client) { my $sth = $DBH->prepare("SELECT * FROM clients WHERE valid = 't' ORDER BY client_id ASC;"); - if (!defined $sth) { + unless (defined $sth) { sendMsg("err", "Cannot prepare statement in function '$function_name': $DBH->errstr", "Internal 'prepare' server error"); } + my $rc = $sth->execute; - if (!$rc) { + unless ($rc) { sendMsg("err", "Cannot execute statement in function '$function_name': $DBH->errstr", "Internal 'execute' server error"); } while ( my @result = $sth->fetchrow() ) { - $client_id = $result[0]; - $hostname = $result[1]; - $registered = $result[2]; - $requestor = $result[3]; - $service = $result[4]; - $client_type = $result[5]; - $type = $result[6]; - $receive_own_events = $result[7]; - $description_tags = $result[8]; - $ip_net_client = $result[9]; - $client = SOAP::Data->name(client => \SOAP::Data->value( - SOAP::Data->name(CLIENT_ID => $client_id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(REGISTERED => $registered), - SOAP::Data->name(REQUESTOR => $requestor), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(CLIENT_TYPE => $client_type), - SOAP::Data->name(TYPE => $type), - SOAP::Data->name(RECEIVE_OWN_EVENTS => $receive_own_events), - SOAP::Data->name(DESCRIPTION_TAGS => $description_tags), - SOAP::Data->name(IP_NET_CLIENT => $ip_net_client), - )); + SOAP::Data->name(CLIENT_ID => $result[0]), + SOAP::Data->name(HOSTNAME => $result[1]), + SOAP::Data->name(REGISTERED => $result[2]), + SOAP::Data->name(REQUESTOR => $result[3]), + SOAP::Data->name(SERVICE => $result[4]), + SOAP::Data->name(CLIENT_TYPE => $result[5]), + SOAP::Data->name(TYPE => $result[6]), + SOAP::Data->name(RECEIVE_OWN_EVENTS => $result[7]), + SOAP::Data->name(DESCRIPTION_TAGS => $result[8]), + SOAP::Data->name(IP_NET_CLIENT => $result[9]), + ), + ); push(@clients, $client); } + my $sum = scalar @clients; sendMsg("info", - "Sent information about $sum registered clients from Warden server '$ENV{'SERVER_NAME'}'", + "Sent information about $sum registered clients from Warden server '$ENV{'SERVER_NAME'}' to client '$client{'client_id'}'", undef); return @clients; } -- GitLab