File Coverage

blib/lib/Net/SecurityCenter/Utils.pm
Criterion Covered Total %
statement 114 172 66.2
branch 36 70 51.4
condition 14 23 60.8
subroutine 16 21 76.1
pod 0 14 0.0
total 180 300 60.0


line stmt bran cond sub pod time code
1             package Net::SecurityCenter::Utils;
2              
3 3     3   676 use warnings;
  3         8  
  3         103  
4 3     3   16 use strict;
  3         6  
  3         57  
5              
6 3     3   13 use Carp;
  3         6  
  3         195  
7 3     3   1675 use Params::Check qw(allow);
  3         12571  
  3         190  
8 3     3   1620 use Time::Piece;
  3         25817  
  3         13  
9 3     3   2085 use Data::Dumper ();
  3         20809  
  3         95  
10 3     3   22 use Exporter qw(import);
  3         7  
  3         6859  
11              
12             our $VERSION = '0.300';
13              
14             our @EXPORT_OK = qw(
15             sc_check_params
16             sc_decode_scanner_status
17             sc_filter_array_to_string
18             sc_filter_int_to_bool
19             sc_filter_datetime_to_epoch
20             sc_merge
21             sc_normalize_hash
22             sc_normalize_array
23             sc_method_usage
24             sc_schedule
25              
26             dumper
27             trim
28             deprecated
29             cpe_decode
30             file_slurp
31             config_parse_line
32             config_parser
33             );
34              
35             our %EXPORT_TAGS = ( all => \@EXPORT_OK );
36              
37             our $NESSUS_SCANNER_STATUS = {
38              
39             1 => 'Working',
40             2 => 'Connection Error',
41             4 => 'Connection Timeout',
42             8 => 'Certificate mismatch',
43             16 => 'Protocol Error',
44             32 => 'Authentication Error',
45             64 => 'Invalid Configuration',
46             128 => 'Reloading Scanner',
47             256 => 'Plugins out-of-sync',
48             512 => 'PVS results ready',
49             1024 => 'Updating plugins',
50             2048 => 'LCE main daemon down',
51             4096 => 'LCE query daemon down',
52             8192 => 'Updating Status',
53             16384 => 'Scanner disabled by user',
54             32768 => 'Scanner requires an upgrade',
55             65536 => 'LCE version too low',
56             131072 => 'License Invalid',
57             262144 => 'Not used',
58             524288 => 'Resource Unavailable',
59              
60             };
61              
62             #-------------------------------------------------------------------------------
63             # COMMON UTILS
64             #-------------------------------------------------------------------------------
65              
66             sub dumper {
67 39     39 0 382 return Data::Dumper->new( [@_] )->Indent(1)->Sortkeys(1)->Terse(1)->Useqq(1)->Dump;
68             }
69              
70             #-------------------------------------------------------------------------------
71              
72             sub trim {
73              
74 1     1 0 460 my ($string) = @_;
75              
76 1 50       6 return if ( !$string );
77              
78 1         9 $string =~ s/^\s+|\s+$//g;
79 1         24 return $string;
80              
81             }
82              
83             #-------------------------------------------------------------------------------
84              
85             sub deprecated {
86 0     0 0 0 local $Carp::CarpLevel = 1;
87 0         0 carp @_;
88             }
89              
90             #-------------------------------------------------------------------------------
91              
92             sub cpe_decode {
93              
94 0     0 0 0 my ($cpe) = @_;
95              
96 0         0 $cpe =~ s/cpe:\///;
97              
98             my (
99 0         0 $part, $vendor, $product, $version, $update, $edition,
100             $language, $sw_edition, $target_sw, $target_hw, $other
101             );
102              
103 0         0 ( $part, $vendor, $product, $version, $update, $edition, $language ) = split( /:/, $cpe );
104              
105 0 0       0 ( $sw_edition, $target_sw, $target_hw, $other ) = split( /~/, $language ) if ($language);
106              
107             return {
108 0         0 'part' => $part,
109             'vendor' => $vendor,
110             'product' => $product,
111             'version' => $version,
112             'update' => $update,
113             'edition' => $edition,
114             'language' => $language,
115             'sw_edition' => $sw_edition,
116             'target_sw' => $target_sw,
117             'target_hw' => $target_hw,
118             'other' => $other
119             };
120              
121             }
122              
123             #-------------------------------------------------------------------------------
124             # COMMON CLASS UTILS
125             #-------------------------------------------------------------------------------
126              
127             sub sc_schedule {
128              
129 2     2 0 1555 my (%args) = @_;
130              
131 2         21 my $tmpl = {
132             type => {
133             allow => [ 'dependent', 'ical', 'never', 'rollover', 'template', 'now' ],
134             default => 'never',
135             required => 1,
136             },
137             start => {},
138             repeat_rule => {
139             remap => 'repeatRule',
140             },
141             };
142              
143 2         10 my $params = sc_check_params( $tmpl, \%args );
144              
145 2 100       7 if ( $params->{'type'} eq 'now' ) {
146              
147             return {
148 1         7 'repeatRule' => 'FREQ=NOW;INTERVAL=1',
149             'type' => 'now'
150             };
151              
152             }
153              
154 1 50       4 if ( $params->{'type'} eq 'ical' ) {
155              
156             return {
157             'type' => 'ical',
158             'start' => $params->{'start'},
159 1         8 'repeatRule' => $params->{'repeatRule'},
160             };
161              
162             }
163              
164 0         0 return $params;
165              
166             }
167              
168             #-------------------------------------------------------------------------------
169              
170             sub sc_method_usage {
171              
172 0     0 0 0 my ($template) = @_;
173              
174 0   0     0 my $usage_class = ( caller(2) )[3] || q{};
175 0         0 $usage_class =~ s/(::)(\w+)$/->$2/;
176              
177 0         0 my $usage_args = q{};
178              
179 0         0 my @usage_req_args;
180             my @usage_opt_args;
181              
182 0         0 foreach my $key ( sort keys %{$template} ) {
  0         0  
183              
184 0 0       0 ( exists $template->{$key}->{'required'} )
185             ? push @usage_req_args, "$key => ..."
186             : push @usage_opt_args, "$key => ...";
187              
188             }
189              
190 0         0 $usage_args .= join ' , ', @usage_req_args;
191              
192 0 0       0 if (@usage_req_args) {
193 0         0 $usage_args .= ' , ';
194             }
195              
196 0         0 $usage_args .= '[ ' . ( join ' , ', @usage_opt_args ) . ' ]';
197              
198 0         0 return "Usage: $usage_class( $usage_args )";
199              
200             }
201              
202             #-------------------------------------------------------------------------------
203              
204             sub sc_check_params {
205              
206 40     40 0 91 my ( $template, $params ) = @_;
207              
208 40         75 my $args = {};
209 40         69 my $output = {};
210              
211 40         86 foreach my $key ( keys %{$params} ) {
  40         139  
212 31         101 my $lc_key = lc $key;
213 31         89 $args->{$lc_key} = $params->{$key};
214             }
215              
216 40         72 foreach my $key ( keys %{$template} ) {
  40         112  
217              
218 123         193 my $tmpl = $template->{$key};
219              
220 123 50 66     346 if ( exists $tmpl->{'required'} and not exists $args->{$key} ) {
221              
222 0         0 my $error_message = "Required '$key' param is not provided";
223              
224 0 0       0 if ( defined $tmpl->{'messages'}->{'required'} ) {
225 0         0 $error_message = $tmpl->{'messages'}->{'required'};
226             }
227              
228 0         0 carp $error_message;
229 0         0 croak sc_method_usage($template);
230              
231             }
232              
233 123 100       281 if ( exists $tmpl->{'default'} ) {
234 3         8 $output->{$key} = $tmpl->{'default'};
235             }
236              
237             }
238              
239 40         76 foreach my $key ( keys %{$args} ) {
  40         132  
240              
241 31 50       87 next if ( !exists $template->{$key} );
242              
243 31         63 my $value = $args->{$key};
244 31         51 my $tmpl = $template->{$key};
245              
246             # Execute pre-validation filter
247 31 100 66     115 if ( exists $tmpl->{'filter'} and ref $tmpl->{'filter'} eq 'CODE' ) {
248 1         5 $value = $tmpl->{'filter'}->($value);
249             }
250              
251 31 100       98 if ( exists $tmpl->{'allow'} ) {
252              
253 26 100       86 if ( ref $value eq 'ARRAY' ) {
254              
255 2         4 foreach ( @{$value} ) {
  2         7  
256              
257 5 50       21 if ( !allow( $_, $tmpl->{'allow'} ) ) {
258 0         0 carp "Invalid '$key' ($_) value (allowed values: " . join( ', ', @{ $tmpl->{'allow'} } ) . ')';
  0         0  
259 0         0 croak sc_method_usage($template);
260             }
261              
262             }
263              
264             } else {
265              
266 24 50       129 if ( !allow( $value, $tmpl->{'allow'} ) ) {
267              
268 0         0 my $error_message = q{};
269              
270 0 0       0 if ( ref $tmpl->{'allow'} eq 'ARRAY' ) {
271             $error_message
272             = "Invalid '$key' ($value) value (allowed values: "
273 0         0 . join( ', ', @{ $tmpl->{'allow'} } ) . ')';
  0         0  
274             }
275              
276 0 0       0 if ( ref $tmpl->{'allow'} eq 'Regexp' ) {
277 0         0 $error_message = "Invalid param '$key' ($value) value";
278             }
279              
280 0 0       0 if ( exists $tmpl->{'messages'}->{'allow'} ) {
281 0         0 $error_message = $tmpl->{'messages'}->{'allow'};
282             }
283              
284 0         0 carp $error_message;
285 0         0 croak sc_method_usage($template);
286              
287             }
288             }
289             }
290              
291             # Execute post validation filter
292 31 50 33     602 if ( exists $tmpl->{'post_filter'} and ref $tmpl->{'post_filter'} eq 'CODE' ) {
293 0         0 $value = $tmpl->{'post_filter'}->($value);
294             }
295              
296 31 100       78 if ( $key eq 'fields' ) {
297              
298 3 100       14 if ( ref $value eq 'ARRAY' ) {
299 2         4 $value = join( ',', @{$value} );
  2         7  
300             }
301              
302             }
303              
304 31         76 $output->{$key} = $value;
305              
306 31 50       93 if ( exists $tmpl->{'remap'} ) {
307 0         0 $output->{ $tmpl->{'remap'} } = $output->{$key};
308 0         0 delete $output->{$key};
309             }
310              
311             }
312              
313 40         180 return $output;
314              
315             }
316              
317             #-------------------------------------------------------------------------------
318              
319             sub sc_decode_scanner_status {
320              
321 21     21 0 9584 my ($scanner_status) = @_;
322              
323 21         37 foreach ( sort { $b <=> $a } keys %{$NESSUS_SCANNER_STATUS} ) {
  1382         1823  
  21         153  
324              
325 217 100       427 if ( $scanner_status >= $_ ) {
326 21         129 return $NESSUS_SCANNER_STATUS->{$_};
327             }
328              
329             }
330              
331 0         0 return;
332              
333             }
334              
335             #-------------------------------------------------------------------------------
336              
337             sub sc_normalize_hash {
338              
339 194     194 0 332 my ($data) = @_;
340              
341 194         650 my @time_fields = qw(
342             createdTime
343             finishTime
344             importFinish
345             importStart
346             lastSyncTime
347             lastTrendUpdate
348             lastVulnUpdate
349             modifiedTime
350             startTime
351             updateTime
352             diagnosticsGenerated
353             statusLastChecked
354             lastScan
355             lastUnauthRun
356             lastAuthRun
357             time
358             );
359              
360 194         312 my @seconds_fields = qw(
361             scanDuration
362             uptime
363             );
364              
365 194         273 foreach my $item ( keys %{$data} ) {
  194         549  
366 911 100       4411 if ( ref $data->{$item} eq 'HASH' ) {
367 41         102 $data->{$item} = sc_normalize_hash( $data->{$item} );
368             }
369 911 50 66     2748 if ( $item =~ m/(Update|Date|Time)$/ && $data->{$item} =~ /\d+/ && ref $data->{$item} ne 'Time::Piece' ) {
      66        
370 38         201 $data->{$item} = Time::Piece->new( $data->{$item} );
371             }
372             }
373              
374 194         727 foreach my $field (@time_fields) {
375 3104 100 100     6696 if ( exists( $data->{$field} ) && ref $data->{$field} ne 'Time::Piece' ) {
376 11         51 $data->{$field} = Time::Piece->new( $data->{$field} );
377             }
378             }
379              
380 194         533 foreach my $field (@seconds_fields) {
381 388 100 66     867 if ( exists( $data->{$field} ) && ref $data->{$field} ne 'Time::Seconds' ) {
382 5         48 $data->{$field} = Time::Seconds->new( $data->{$field} );
383             }
384             }
385              
386 194         559 return $data;
387              
388             }
389              
390             #-------------------------------------------------------------------------------
391              
392             sub sc_normalize_array {
393              
394 7     7 0 21 my ($data) = @_;
395              
396 7         18 my $results = [];
397              
398 7         16 foreach my $item ( @{$data} ) {
  7         33  
399 106         151 push( @{$results}, sc_normalize_hash($item) );
  106         187  
400             }
401              
402 7         88 return $results;
403              
404             }
405              
406             #-------------------------------------------------------------------------------
407              
408             sub sc_merge {
409              
410 4     4 0 12 my ($data) = @_;
411 4         12 my %hash = ();
412              
413 4         14 foreach my $type ( ( 'usable', 'manageable' ) ) {
414              
415 8 50       25 next unless ( exists( $data->{$type} ) );
416              
417 8         13 foreach my $item ( @{ $data->{$type} } ) {
  8         23  
418              
419 34         64 $item = sc_normalize_hash($item);
420 34         60 $item->{$type} = 1;
421              
422 34 100       72 if ( exists( $hash{ $item->{'id'} } ) ) {
423 15         38 $hash{ $item->{'id'} }->{$type} = 1;
424             } else {
425 19         57 $hash{ $item->{'id'} } = $item;
426             }
427             }
428             }
429              
430 4         17 my @results = values %hash;
431 4         66 return \@results;
432              
433             }
434              
435             #-------------------------------------------------------------------------------
436             # FILTERS
437             #-------------------------------------------------------------------------------
438              
439             sub sc_filter_array_to_string {
440              
441 6     6 0 35 my ($data) = @_;
442              
443 6 100       19 if ( ref $data eq 'ARRAY' ) {
444 1         2 return join( ',', @{$data} );
  1         5  
445             }
446              
447 5         9 return $data;
448              
449             }
450              
451             sub sc_filter_int_to_bool {
452 0 0   0 0   return ( $_[0] == 1 ) ? \1 : \0;
453             }
454              
455             sub sc_filter_datetime_to_epoch {
456              
457 0     0 0   my ($date) = @_;
458              
459 0 0         if ( ref $date eq 'Time::Piece' ) {
460 0           return $date->epoch;
461             }
462              
463 0 0         if ( $date =~ /^\d{4}-\d{2}-\d{2}$/ ) {
464 0           my $t = Time::Piece->strptime( $date, '%Y-%m-%d' );
465 0           return $t->epoch;
466             }
467              
468 0 0         if ( $date =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/ ) {
469 0           my $t = Time::Piece->strptime( $date, '%Y-%m-%d %H:%M:%S' );
470 0           return $t->epoch;
471             }
472              
473 0 0         if ( $date =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/ ) {
474 0           my $t = Time::Piece->strptime( $date, '%Y-%m-%dT%H:%M:%S' );
475 0           return $t->epoch;
476             }
477              
478 0           return $date;
479              
480             }
481              
482             #-------------------------------------------------------------------------------
483              
484             1;
485              
486             __END__