File Coverage

blib/lib/Net/P0f.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Net::P0f;
2 5     5   135522 use strict;
  5         13  
  5         183  
3 5     5   28 use Carp;
  5         11  
  5         455  
4 5     5   6075 use Net::Pcap;
  0            
  0            
5             use Net::P0f::Backend::CmdFE;
6             use Net::P0f::Backend::Socket;
7             use Net::P0f::Backend::XS;
8              
9             { no strict;
10             $VERSION = 0.02;
11             }
12              
13             =head1 NAME
14              
15             Net::P0f - Perl wrapper for the P0f utility
16              
17             =head1 VERSION
18              
19             Version 0.02
20              
21             =head1 SYNOPSIS
22              
23             use Net::P0f;
24              
25             my $p0f = Net::P0f->new(interface => 'eth0', promiscuous => 1);
26             $p0f->loop(callback => \&process_packet);
27              
28             sub process_packet {
29             # do stuff with packet information
30             # see the documentation for more details
31             }
32              
33             =head1 DESCRIPTION
34              
35             This module (and its associated helper modules) is a Perl interface to
36             the P0f utility. P0f is a passive operating system fingerprinting: it
37             identifies the operating system of network devices by I looking
38             at specific patterns in their TCP/IP packets. Therefore, contrary to
39             others tools like Nmap, P0f does not send any packet and stays completly
40             stealth.
41             For more information on P0f, please see L
42              
43             =head1 METHODS
44              
45             =head2 Lookup methods
46              
47             The following methods are class methods, which can of course also
48             be used as object methods.
49              
50             =over 4
51              
52             =item lookupdev()
53              
54             Returns the name of a network device that can be used for operating.
55              
56             B this function may require administrator privileges on some
57             operating systems.
58              
59             =cut
60              
61             sub lookupdev {
62             my $self = shift;
63             my $err = '';
64             my $dev = Net::Pcap::lookupdev(\$err);
65             carp "error: Net::Pcap error: $err" if $err;
66             return $dev
67             }
68              
69             =item findalldevs()
70              
71             Returns a list of all network devices that can be used for operating.
72             If the corresponding fonction is not available in the version of
73             C installed on the system (it appeared in version 0.05),
74             it will print a warning and return the result of C.
75              
76             B this function may require administrator privileges on some
77             operating systems.
78              
79             =cut
80              
81             sub findalldevs {
82             my $self = shift;
83             my $err = '';
84             my @devs = ();
85             eval { @devs = Net::Pcap::findalldevs(\$err) };
86             carp "warning: This function is not available with this version of Net::Pcap"
87             if $@ =~ /findalldevs/;
88             carp "error: Net::Pcap error: $err" if $err;
89             push @devs, __PACKAGE__->lookupdev unless @devs;
90             return @devs
91             }
92              
93             =back
94              
95             =head2 Packet analysis methods
96              
97             =over 4
98              
99             =item new()
100              
101             Create and returns a new objects.
102             The following options are accepted.
103              
104             B
105              
106             =over 4
107              
108             =item *
109              
110             C - selects the back-end.
111             Accepted values are C<"cmd">, C<"socket"> and C<"xs"> to select,
112             respectively, the command line front-end, the socket version and
113             the XS version. If not specified, defaults to C<"cmd">.
114              
115             =item *
116              
117             C - chroot and setuid to this user.
118             Accepted value is any valid user name.
119             Default is not to chroot.
120              
121             =item *
122              
123             C - read fingerpints from the given file.
124              
125             =back
126              
127             B
128              
129             Only one the following options must be used.
130              
131             =over 4
132              
133             =item *
134              
135             C - selects the network device.
136             Accepted values are any interface name that the system can recognize.
137             Remember that such names are usualy not portable. For example, you can
138             check if the interface name belongs to the list returned by
139             Cfindalldevs>.
140              
141             =item *
142              
143             C - reads from the given dump file, as created by B
144             with the C<-w file> option.
145              
146             =back
147              
148             B
149              
150             =over 4
151              
152             =item *
153              
154             C - selects the detection mode.
155             Accepted values are 0 for the SYN mode, 1 for the SYN+ACK mode,
156             and 2 for the RST+ACK mode.
157             Default value is 0.
158              
159             =item *
160              
161             C - activates the fuzzy matching (do not combine with
162             the RST+ACK detection mode).
163             Value can be 0 (fuzzy matching disabled) or 1 (activated).
164             Default value is 0.
165              
166             =item *
167              
168             C - switches the network device to promiscuous mode.
169             Value can be 0 (normal mode) or 1 (promiscuous mode activated).
170             Default value is 0.
171              
172             =item *
173              
174             C - pcap-style BPF expression.
175              
176             =item *
177              
178             C - activates the masquerade detection.
179             Value can be 0 (masquerade detection disabled) or 1 (enabled).
180             Default value is 0.
181              
182             =item *
183              
184             C - sets the masquerade detection threshold.
185             Value can be any integer between 1 and 200.
186             Default value is 100.
187              
188             =item *
189              
190             C - activates the IP to names resolution.
191             Value can be 0 (do not resolve names) or 1 (resolve names).
192             Default value is 0.
193              
194             =back
195              
196             B
197              
198             Common use under Linux:
199              
200             my $p0f = new Net::P0f interface => 'eth0';
201              
202             The same, in a more portable way:
203              
204             my $p0f = new Net::P0f interface => Net::P0f->lookupdev;
205              
206             =cut
207              
208             my %objects = ();
209              
210             sub new {
211             my $class = ref $_[0] || $_[0]; shift;
212             my $self = {
213             options => {
214             # Engine options
215             chroot_as => undef, # arg: user
216             fingerprints_file => undef, # arg: fingerprints file
217              
218             # Input options
219             interface => undef, # arg: network device
220             dump_file => undef, # arg: dump file
221              
222             # Detection options
223             detection_mode => 0, # switch 0/1
224             fuzzy => 0, # switch 0/1
225             promiscuous => 0, # switch 0/1
226             filter => undef, # arg: BPF filter
227             masquerade_detection => 0, # switch 0/1
228             masquerade_detection_threshold => undef, # arg: threshold
229             resolve_names => 0, # switch 0/1
230             },
231             loop => {
232             callback => 0,
233             count => 0,
234             keep_on => 0,
235             }
236             };
237              
238             # gets all options
239             my %opts = @_;
240              
241             # select the backend and create the object
242             my %backends = (
243             cmd => 'Net::P0f::Backend::CmdFE',
244             'socket' => 'Net::P0f::Backend::Socket',
245             xs => 'Net::P0f::Backend::XS',
246             );
247             $opts{backend} ||= 'cmd'; # default backend
248             croak "fatal: Unknown value for option 'backend': $opts{backend}"
249             unless exists $backends{$opts{'backend'}};
250             my $backend = $backends{$opts{backend}};
251             bless $self, $backend;
252             delete $opts{backend};
253              
254             # initialize generic options
255             for my $opt (keys %opts) {
256             $self->{options}{$opt} = $opts{$opt} and delete $opts{$opt}
257             if exists $self->{options}{$opt}
258             }
259              
260             # initialize backend-specific options
261             $self->init(%opts);
262              
263             # keep track of created objects
264             $objects{"$self"} = $self;
265              
266             return $self
267             }
268              
269              
270             #
271             # AUTOLOAD()
272             # --------
273             # generates dynamic accessors for all existing options
274             #
275             sub AUTOLOAD {
276             no strict;
277             my $self = $_[0];
278             my $type = ref $self or croak "I am not an object, so don't call me that way.";
279             my $name = $AUTOLOAD;
280             $name =~ s/.*:://;
281            
282             carp "warning: Unknown option '$name'" unless exists $self->{options}{$name};
283              
284             my $code = q{
285             sub {
286             my $self = shift;
287             my $value = $self->{options}{METHOD};
288             $self->{options}{METHOD} = shift if @_;
289             return $value
290             }
291             };
292             $code =~ s/METHOD/$name/g;
293              
294             *$AUTOLOAD = eval $code;
295             goto &$AUTOLOAD;
296             }
297              
298              
299             #
300             # DESTROY()
301             # -------
302             sub DESTROY {
303             delete $objects{"$_[0]"};
304             }
305              
306              
307             =item loop()
308              
309             This method launches the execution of the P0f engine.
310              
311             B
312              
313             =over 4
314              
315             =item *
316              
317             C - sets the callback function that will be called for
318             each received packets. This option is required.
319             See L<"CALLBACK"> for more information.
320              
321             =item *
322              
323             C - wait for this number of packets, then stop. If set to
324             zero, run until a C signal is received. This option is required.
325              
326             =back
327              
328             B
329              
330             # process 10 packets, giving them to the packet_handler() function
331             $p0f->loop(callback => \&packet_handler, count => 10);
332              
333             =cut
334              
335             sub loop {
336             my $self = shift;
337             my %opts = @_;
338              
339             for my $opt (qw(callback count)) {
340             croak "fatal: Option '$opt' was not set." unless $opts{$opt};
341             $self->{loop}{$opt} = $opts{$opt};
342             }
343            
344             { # check input source
345             my $v = -+-defined($self->{options}{interface}) . -+-defined($self->{options}{dump_file});
346             for($v) {
347             $_ eq '00' and
348             croak "fatal: No input source was defined. Please set one of 'interface' or 'dump_file'.";
349              
350             $_ eq '11' and do {
351             carp "warning: Both 'interface' and 'dump_file' have been set. 'dump_file' prevails.";
352             delete $self->{options}{interface};
353             }
354             }
355             }
356            
357             # run the P0f engine
358             $self->run;
359             }
360              
361             =back
362              
363             =head1 CALLBACK
364              
365             A callback function has the following signature:
366              
367             sub callback {
368             my($self,$header,$os_info,$link_info) = @_;
369             # do something ...
370             }
371              
372             where the parameters have the following meaning:
373              
374             =over 4
375              
376             =item *
377              
378             C<$self> is the C object
379              
380             =item *
381              
382             C<$header> is a hashref with the following keys:
383              
384             =over 4
385              
386             =item *
387              
388             C is the source IP address
389              
390             =item *
391              
392             C is the source DNS name (if any)
393              
394             =item *
395              
396             C is the source port
397              
398             =item *
399              
400             C is the destination IP address
401              
402             =item *
403              
404             C is the destination DNS name (if any)
405              
406             =item *
407              
408             C is the destination port
409              
410             =back
411              
412             =item *
413              
414             C<$os_info> is a hashref with the following keys:
415              
416             =over 4
417              
418             =item *
419              
420             C is the generic genre of the operating system (like C<"Linux">
421             or C<"Windows">)
422              
423             =item *
424              
425             C
gives more information on the operating system, like its
426             version
427              
428             =item *
429              
430             C indicates the uptime of the host
431              
432             =back
433              
434             =item *
435              
436             C<$link_info> is a hashref with the following keys:
437              
438             =over 4
439              
440             =item *
441              
442             C is the distance to the host
443              
444             =item *
445              
446             C is the type of the connection
447              
448             =back
449              
450             =back
451              
452             =head1 SIGNALS
453              
454             =over 4
455              
456             =item sighandler()
457              
458             This function is a signal handler for the C, C
459             and C signals. Its main purpose is to tell all the
460             instancied C objects to cleanly stop their engine.
461              
462             =back
463              
464             =cut
465              
466             sub sighandler {
467             # tell all the created objects to stop their engine
468             for my $key (keys %objects) {
469             $objects{$key}->{loop}{keep_on} = 0;
470             }
471             }
472              
473             $SIG{INT} = \&sighandler;
474             $SIG{TERM} = \&sighandler;
475             $SIG{QUIT} = \&sighandler;
476              
477             =head1 BACKENDS
478              
479             =head2 Command-line version
480              
481             XXX
482              
483              
484             =head2 Socket version
485              
486             XXX
487              
488              
489             =head2 XS version
490              
491             XXX
492              
493              
494             =head1 DIAGNOSTICS
495              
496             These messages are classified as follows (listed in increasing order of
497             desperation):
498              
499             =over 4
500              
501             =item *
502              
503             B<(W)> A warning, usually caused by bad user data.
504              
505             =item *
506              
507             B<(E)> An error caused by external code.
508              
509             =item *
510              
511             B<(F)> A fatal error caused by the code of this module.
512              
513             =back
514              
515             =over 4
516              
517             =item Both 'interface' and 'dump_file' have been set. 'dump_file' prevails.
518              
519             B<(F)> As the message says, you defined two input sources by setting both
520             C and C.
521              
522             =item Net::Pcap error: %s
523              
524             B<(E)> The Net::Pcap module returned the following error.
525              
526             =item No input source was defined. Please set one of 'interface' or 'dump_file'.
527              
528             B<(F)> As the message says, you didn't define an input source by setting one
529             of C or C before calling C.
530              
531             =item Option '%s' was not set.
532              
533             B<(F)> A mandatory option wasn't set, hence preventing the program to work.
534              
535             =item This function is not available with this version of Net::Pcap
536              
537             B<(W)> As the message says, the function C is not available.
538             This is most probably because you have Net::Pcap version 0.04 or earlier,
539             and Net::Pcap version 0.05 is needed.
540              
541             =item Unknown option '%s'
542              
543             B<(W)> You called an accesor which does not correspond to a known option.
544              
545             =item Unknown value for option 'backend': %s
546              
547             B<(F)> The value for the option C<"backend"> was not given a valid value.
548             This is a fatal error because this option is needed to build the object.
549              
550             =back
551              
552             =head1 SEE ALSO
553              
554             L
555              
556             L, L,
557             L for backend specific details
558              
559             L
560              
561             =head1 AUTHOR
562              
563             SEbastien Aperghis-Tramoni Esebastien@aperghis.netE
564              
565             =head1 BUGS
566              
567             Please report any bugs or feature requests to
568             L, or through the web interface at
569             L.
570             I will be notified, and then you'll automatically be notified
571             of progress on your bug as I make changes.
572              
573             =head1 COPYRIGHT & LICENSE
574              
575             Copyright 2004 SEbastien Aperghis-Tramoni, All Rights Reserved.
576              
577             This program is free software; you can redistribute it and/or modify it
578             under the same terms as Perl itself.
579              
580             =cut
581              
582             1; # End of Net::P0f