File Coverage

blib/lib/PIX/Accesslist/Line.pm
Criterion Covered Total %
statement 6 110 5.4
branch 0 72 0.0
condition 0 61 0.0
subroutine 2 17 11.7
pod 7 14 50.0
total 15 274 5.4


line stmt bran cond sub pod time code
1             package PIX::Accesslist::Line;
2              
3 1     1   6 use strict;
  1         2  
  1         28  
4 1     1   6 use warnings;
  1         2  
  1         1677  
5              
6             our $VERSION = '1.10';
7              
8             =pod
9              
10             =head1 NAME
11              
12             PIX::Accesslist::Line - ACL line object for each line of an PIX::Accesslist.
13              
14             =head1 SYNOPSIS
15              
16             PIX::Accesslist::Line is used by PIX::Accesslist to hold a single line of an ACL.
17             Each line can be searched against a set of IP & port criteria to find a match.
18             Users will not usually have to create objects from this directly.
19              
20             See B for more information regarding PIX Accesslists.
21              
22             $line = new PIX::Accesslist::Line(
23             $action, $proto, $source,
24             $source_ort, $dest, $dest_port, $idx,
25             $parent_acl_obj
26             );
27              
28             =head1 METHODS
29              
30             =over
31              
32             =cut
33              
34             sub new {
35 0     0 0   my $proto = shift;
36 0   0       my $class = ref($proto) || $proto;
37 0           my $self = { };
38 0           my ($action, $protocol, $source, $sport, $dest, $dport, $idx, $parent) = @_;
39              
40 0           $self->{class} = $class;
41 0           $self->{action} = lc $action;
42 0           $self->{proto} = $protocol;
43 0           $self->{source} = $source;
44 0           $self->{sport} = $sport;
45 0           $self->{dest} = $dest;
46 0           $self->{dport} = $dport;
47 0   0       $self->{idx} = $idx || 0;
48 0           $self->{parent} = $parent; # parent PIX::Accesslist object
49              
50 0           bless($self, $class);
51 0           $self->_init;
52              
53 0           return $self;
54             }
55              
56 0     0     sub _init { }
57              
58             =item B
59              
60             =over
61              
62             Returns the total access-list elements (ACE) for the ACL line.
63             B It's not wise to call this over and over again. Store the result
64             in a variable and use that variable if you need to use this result in multiple
65             places.
66              
67             =back
68              
69             =cut
70             sub elements {
71 0     0 1   my $self = shift;
72 0           my $total = 0;
73 0           foreach my $proto ($self->{proto}->list) {
74 0 0         $total++ unless $self->{source}->list;
75 0           foreach my $src ($self->{source}->list) {
76 0 0         $total++ unless $self->{dest}->list;
77 0           foreach my $dest ($self->{dest}->list) {
78 0 0         my @dport_list = $self->{dport} ? $self->{dport}->list : ();
79 0 0         $total += scalar @dport_list ? @dport_list : 1;
80             }
81             }
82             }
83             # print "LINE " . $self->num . " has $total elements\n";
84 0           return $total;
85             }
86              
87             =item B
88              
89             =over
90              
91             Returns a true value if the criteria given matches the logic of the ACL line.
92             'Loose' matching is performed. For example, If you supply a single IP or port
93             a match may return TRUE on a line even though the final logic of the line might
94             overwise be FALSE according to the OS on the firewall. If you want to be sure
95             you get accurate matching you must provide all criteria shown below.
96              
97             =over
98              
99             * source : Source IP
100              
101             * sport : Source Port
102              
103             * dest : Destination IP
104              
105             * dport : Destionation Port
106              
107             * proto : Protocol
108              
109             =back
110              
111             B source port {sport} is not usually used. You will usually only want to
112             use {dport}.
113              
114             =back
115              
116             =cut
117             sub match {
118 0     0 1   my $self = shift;
119 0 0         my $arg = ref $_[0] ? $_[0] : { @_ };
120 0           my $ok = 0;
121 0   0       $arg->{proto} ||= 'ip'; # default to IP
122            
123             # shortcut, alias {port} to {dport} if specified
124 0 0 0       $arg->{dport} ||= $arg->{port} if exists $arg->{port};
125            
126             # does the protocol match?
127 0 0         if ($arg->{proto} eq 'ip') {
128 0           $ok = 1;
129             } else {
130 0 0         $ok = scalar grep { lc $_ eq 'ip' or lc $_ eq $arg->{proto} } $self->{proto}->list;
  0            
131             }
132             #print "PROTO =$ok\n";
133 0 0         return 0 unless $ok;
134              
135             # check for ICMP TYPES if the protcol is ICMP and we are an icmp-type group
136             #if ($self->{dport}->type eq 'icmp-type' and grep { $_ eq 'icmp' } $self->{proto}->list) {
137             # warn "ICMP TEST\n";
138             #}
139              
140              
141             # does the source IP match?
142 0 0 0       $ok = $self->{source}->matchip($arg->{source}) if $arg->{source} and $self->{source};
143             #print "SOURCE=$ok\n";
144 0 0         return 0 unless $ok;
145              
146             # does the source port match?
147 0 0 0       $ok = $self->{sport}->matchport($arg->{sport}) if $arg->{sport} and $self->{sport};
148             #print "SPORT =$ok\n";
149 0 0         return 0 unless $ok;
150              
151             # does the destination IP match?
152 0 0 0       $ok = $self->{dest}->matchip($arg->{dest}) if $arg->{dest} and $self->{dest};
153             #print "DEST =$ok\n";
154 0 0         return 0 unless $ok;
155              
156             # does the destination port match?
157 0 0 0       $ok = $self->{dport}->matchport($arg->{dport}) if $arg->{dport} and $self->{dport};
158             #print "DPORT =".($ok||'')."\n";
159 0 0         return 0 unless $ok;
160            
161 0           return 1;
162             }
163              
164             =item B
165              
166             =over
167              
168             Pretty prints the ACL line. Tries to make it easy to read. If object-group's are
169             used the names are printed instead of IP's if more than a single IP is present
170             for a line.
171              
172             $any is an optional string that will be used for any IP that represents 'ANY',
173             defaults to: 0.0.0.0/0. It's useful to change this to 'ANY' to make the output
174             easier to read.
175              
176             1) permit (tcp) 192.168.0.0/24 -> 0.0.0.0/0 [Web_Services_tcp: 80,443]
177              
178             =back
179              
180             =cut
181             sub print {
182 0     0 1   my $self = shift;
183 0   0       my $any = shift || '0.0.0.0/0';
184 0           my $output = '';
185              
186 0           $output .= sprintf("%3d) ", $self->num);
187 0           $output .= sprintf("%6s %-10s", $self->{action}, "(" . $self->proto_str . ")");
188              
189             # display the source
190 0           $output .= $self->source_str($any);
191             #if ($self->{proto}->first !~ /^(ip|icmp)$/) {
192 0 0         if ($self->{proto}->first ne 'ip') {
193 0 0 0       if ($self->{sport} and $self->sourceport_str) {
194 0           my $name = $self->{sport}->name;
195 0           my @enum = $self->{sport}->enumerate;
196 0           my @list = $self->{sport}->list;
197 0 0 0       $output .= sprintf(" [%s]", $name =~ /^unnamed/ && @enum == 1
    0          
198             ? @enum
199             : @enum <= 4
200             ? $name . ": " .join(',',@enum)
201             : $name . " (" . @list . " ranges; " . @enum . " ports)"
202             );
203             } else {
204             # since source ports are not usually used in most ACL's
205             # (from my experience) lets not show anything if ANY
206             # is allowed.
207 0           $output .= "";
208             }
209             }
210              
211 0           $output .= " -> ";
212              
213             # display the destination
214 0           $output .= $self->dest_str($any);
215             #if ($self->{proto}->first !~ /^(ip|icmp)$/) {
216 0 0         if ($self->{proto}->first ne 'ip') {
217 0 0 0       if ($self->{dport} and $self->destport_str) {
218 0           my $name = $self->{dport}->name;
219 0           my @enum = $self->{dport}->enumerate;
220 0           my @list = $self->{dport}->list;
221 0 0 0       $output .= sprintf(" [%s]", $name =~ /^unnamed/ && @enum == 1
    0          
222             ? @enum
223             : @enum <= 4
224             ? $name . ": " .join(',',@enum)
225             : $name . " (" . @list . " ranges; " . @enum . " ports)"
226             );
227             } else {
228 0           $output .= " [any]";
229             }
230             }
231              
232 0           return $output;
233             }
234              
235             =item B
236              
237             =over
238              
239             Returns the line number for the ACL line
240              
241             =back
242              
243             =cut
244 0     0 1   sub num { $_[0]->{idx} }
245              
246             =item B
247              
248             =over
249              
250             Returns the action string 'permit' or 'deny' of the ACL line,
251             or true if the ACL line is a permit or deny, respectively.
252              
253             =back
254              
255             =cut
256 0     0 1   sub permit { $_[0]->{action} eq 'permit' }
257 0     0 1   sub deny { $_[0]->{action} eq 'deny' }
258 0     0 1   sub action { $_[0]->{action} }
259              
260 0 0   0 0   sub proto_str { return wantarray ? $_[0]->{proto}->list : join(',',$_[0]->{proto}->list) }
261             sub source_str {
262 0     0 0   my $self = shift;
263 0   0       my $any = shift || '0.0.0.0/0';
264 0           my $str;
265 0 0 0       if ($self->{source}->name =~ /^unnamed/ && $self->{source}->list == 1) {
266 0           $str = $self->{source}->first;
267             } else {
268 0           $str = $self->{source}->name;
269             }
270 0 0         return $str eq '0.0.0.0/0' ? $any : $str;
271             }
272             sub dest_str {
273 0     0 0   my $self = shift;
274 0   0       my $any = shift || '0.0.0.0/0';
275 0           my $str;
276 0 0 0       if ($self->{dest}->name =~ /^unnamed/ && $self->{dest}->list == 1) {
277 0           $str = $self->{dest}->first;
278             } else {
279 0           $str = $self->{dest}->name;
280             }
281 0 0         return $str eq '0.0.0.0/0' ? $any : $str;
282             }
283             sub sourceport_str {
284 0     0 0   my $self = shift;
285 0 0 0       return '' unless $self->{proto}->first ne 'ip' && $self->{sport};
286 0 0 0       if ($self->{sport}->name =~ /^unnamed/ && $self->{sport}->enumerate == 1) {
287 0           return $self->{sport}->enumerate;
288             } else {
289 0           return $self->{sport}->name;
290             }
291             }
292             sub destport_str {
293 0     0 0   my $self = shift;
294 0 0 0       return '' unless $self->{proto}->first ne 'ip' && $self->{dport};
295 0 0 0       if ($self->{dport}->name =~ /^unnamed/ && $self->{dport}->enumerate == 1) {
296 0           return $self->{dport}->enumerate;
297             } else {
298 0           return $self->{dport}->name;
299             }
300             }
301             sub destportdetail_str {
302 0     0 0   my $self = shift;
303 0 0 0       return '' if $self->{dport}->name =~ /^unnamed/ && $self->{dport}->enumerate == 1;
304 0 0         if ($self->{dport}->enumerate <= 4) {
305 0           return join(',', $self->{dport}->enumerate);
306             } else {
307 0           return $self->{dport}->list . " ranges; " . $self->{dport}->enumerate . " ports)";
308             }
309 0           return '';
310             }
311             # if ($self->{dport}->name =~ /^unnamed/ && $self->{dport}->enumerate == 1) {
312             # $output .= join(',',$self->{dport}->enumerate);
313             # } elsif ($self->{dport}->enumerate <= 4) {
314             # $output .= $self->{dport}->name . ": " .join(',',$self->{dport}->enumerate);
315             # } else {
316             # $output .= $self->{dport}->name . " (" . $self->{dport}->list . " ranges; " . $self->{dport}->enumerate . " ports)";
317             # }
318              
319             1;
320              
321             =pod
322              
323             =head1 AUTHOR
324              
325             Jason Morriss
326              
327             =head1 BUGS
328              
329             Please report any bugs or feature requests to
330             C, or through the web interface at
331             L.
332             I will be notified, and then you'll automatically be notified of progress on
333             your bug as I make changes.
334              
335             =head1 SUPPORT
336              
337             perldoc PIX::Walker
338              
339             perldoc PIX::Accesslist
340             perldoc PIX::Accesslist::Line
341              
342             perldoc PIX::Object
343             perldoc PIX::Object::network
344             perldoc PIX::Object::service
345             perldoc PIX::Object::protocol
346             perldoc PIX::Object::icmp_type
347              
348             =head1 COPYRIGHT & LICENSE
349              
350             Copyright 2006-2008 Jason Morriss, all rights reserved.
351              
352             This program is free software; you can redistribute it and/or modify it
353             under the same terms as Perl itself.
354              
355             =cut