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   558 use warnings;
  3         6  
  3         81  
4 3     3   15 use strict;
  3         3  
  3         47  
5              
6 3     3   11 use Carp;
  3         5  
  3         138  
7 3     3   1366 use Params::Check qw(allow);
  3         10155  
  3         148  
8 3     3   1347 use Time::Piece;
  3         20697  
  3         11  
9 3     3   1701 use Data::Dumper ();
  3         16603  
  3         76  
10 3     3   18 use Exporter qw(import);
  3         5  
  3         5435  
11              
12             our $VERSION = '0.310';
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 41     41 0 254 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 364 my ($string) = @_;
75              
76 1 50       4 return if ( !$string );
77              
78 1         7 $string =~ s/^\s+|\s+$//g;
79 1         12 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 1240 my (%args) = @_;
130              
131 2         18 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         6 my $params = sc_check_params( $tmpl, \%args );
144              
145 2 100       4 if ( $params->{'type'} eq 'now' ) {
146              
147             return {
148 1         6 'repeatRule' => 'FREQ=NOW;INTERVAL=1',
149             'type' => 'now'
150             };
151              
152             }
153              
154 1 50       3 if ( $params->{'type'} eq 'ical' ) {
155              
156             return {
157             'type' => 'ical',
158             'start' => $params->{'start'},
159 1         5 '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 42     42 0 80 my ( $template, $params ) = @_;
207              
208 42         65 my $args = {};
209 42         58 my $output = {};
210              
211 42         59 foreach my $key ( keys %{$params} ) {
  42         110  
212 32         55 my $lc_key = lc $key;
213 32         67 $args->{$lc_key} = $params->{$key};
214             }
215              
216 42         62 foreach my $key ( keys %{$template} ) {
  42         87  
217              
218 128         160 my $tmpl = $template->{$key};
219              
220 128 50 66     313 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 128 100       229 if ( exists $tmpl->{'default'} ) {
234 3         6 $output->{$key} = $tmpl->{'default'};
235             }
236              
237             }
238              
239 42         60 foreach my $key ( keys %{$args} ) {
  42         81  
240              
241 32 50       67 next if ( !exists $template->{$key} );
242              
243 32         47 my $value = $args->{$key};
244 32         38 my $tmpl = $template->{$key};
245              
246             # Execute pre-validation filter
247 32 100 66     78 if ( exists $tmpl->{'filter'} and ref $tmpl->{'filter'} eq 'CODE' ) {
248 1         4 $value = $tmpl->{'filter'}->($value);
249             }
250              
251 32 100       75 if ( exists $tmpl->{'allow'} ) {
252              
253 27 100       59 if ( ref $value eq 'ARRAY' ) {
254              
255 2         3 foreach ( @{$value} ) {
  2         5  
256              
257 5 50       17 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 25 50       71 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 32 50 33     458 if ( exists $tmpl->{'post_filter'} and ref $tmpl->{'post_filter'} eq 'CODE' ) {
293 0         0 $value = $tmpl->{'post_filter'}->($value);
294             }
295              
296 32 100       59 if ( $key eq 'fields' ) {
297              
298 3 100       6 if ( ref $value eq 'ARRAY' ) {
299 2         3 $value = join( ',', @{$value} );
  2         6  
300             }
301              
302             }
303              
304 32         59 $output->{$key} = $value;
305              
306 32 50       71 if ( exists $tmpl->{'remap'} ) {
307 0         0 $output->{ $tmpl->{'remap'} } = $output->{$key};
308 0         0 delete $output->{$key};
309             }
310              
311             }
312              
313 42         113 return $output;
314              
315             }
316              
317             #-------------------------------------------------------------------------------
318              
319             sub sc_decode_scanner_status {
320              
321 21     21 0 7713 my ($scanner_status) = @_;
322              
323 21         31 foreach ( sort { $b <=> $a } keys %{$NESSUS_SCANNER_STATUS} ) {
  1338         1439  
  21         117  
324              
325 217 100       310 if ( $scanner_status >= $_ ) {
326 21         94 return $NESSUS_SCANNER_STATUS->{$_};
327             }
328              
329             }
330              
331 0         0 return;
332              
333             }
334              
335             #-------------------------------------------------------------------------------
336              
337             sub sc_normalize_hash {
338              
339 202     202 0 274 my ($data) = @_;
340              
341 202         501 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 202         275 my @seconds_fields = qw(
361             scanDuration
362             uptime
363             );
364              
365 202         214 foreach my $item ( keys %{$data} ) {
  202         473  
366 954 100       4151 if ( ref $data->{$item} eq 'HASH' ) {
367 46         129 $data->{$item} = sc_normalize_hash( $data->{$item} );
368             }
369 954 50 66     2272 if ( $item =~ m/(Update|Date|Time)$/ && $data->{$item} =~ /\d+/ && ref $data->{$item} ne 'Time::Piece' ) {
      66        
370 43         179 $data->{$item} = Time::Piece->new( $data->{$item} );
371             }
372             }
373              
374 202         560 foreach my $field (@time_fields) {
375 3232 100 100     5563 if ( exists( $data->{$field} ) && ref $data->{$field} ne 'Time::Piece' ) {
376 11         37 $data->{$field} = Time::Piece->new( $data->{$field} );
377             }
378             }
379              
380 202         442 foreach my $field (@seconds_fields) {
381 404 100 66     773 if ( exists( $data->{$field} ) && ref $data->{$field} ne 'Time::Seconds' ) {
382 5         37 $data->{$field} = Time::Seconds->new( $data->{$field} );
383             }
384             }
385              
386 202         466 return $data;
387              
388             }
389              
390             #-------------------------------------------------------------------------------
391              
392             sub sc_normalize_array {
393              
394 7     7 0 18 my ($data) = @_;
395              
396 7         15 my $results = [];
397              
398 7         10 foreach my $item ( @{$data} ) {
  7         21  
399 106         130 push( @{$results}, sc_normalize_hash($item) );
  106         145  
400             }
401              
402 7         62 return $results;
403              
404             }
405              
406             #-------------------------------------------------------------------------------
407              
408             sub sc_merge {
409              
410 5     5 0 12 my ($data) = @_;
411 5         9 my %hash = ();
412              
413 5         12 foreach my $type ( ( 'usable', 'manageable' ) ) {
414              
415 10 50       25 next unless ( exists( $data->{$type} ) );
416              
417 10         14 foreach my $item ( @{ $data->{$type} } ) {
  10         20  
418              
419 36         56 $item = sc_normalize_hash($item);
420 36         56 $item->{$type} = 1;
421              
422 36 100       63 if ( exists( $hash{ $item->{'id'} } ) ) {
423 16         33 $hash{ $item->{'id'} }->{$type} = 1;
424             } else {
425 20         40 $hash{ $item->{'id'} } = $item;
426             }
427             }
428             }
429              
430 5         13 my @results = values %hash;
431 5         53 return \@results;
432              
433             }
434              
435             #-------------------------------------------------------------------------------
436             # FILTERS
437             #-------------------------------------------------------------------------------
438              
439             sub sc_filter_array_to_string {
440              
441 6     6 0 26 my ($data) = @_;
442              
443 6 100       13 if ( ref $data eq 'ARRAY' ) {
444 1         3 return join( ',', @{$data} );
  1         5  
445             }
446              
447 5         8 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__