File Coverage

blib/lib/Net/SecurityCenter/Utils.pm
Criterion Covered Total %
statement 116 172 67.4
branch 37 70 52.8
condition 14 23 60.8
subroutine 16 21 76.1
pod 0 14 0.0
total 183 300 61.0


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