| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | ############################################################################ | 
| 3 |  |  |  |  |  |  | # Connection object | 
| 4 |  |  |  |  |  |  | # derived from Net::Inspect::L7::HTTP | 
| 5 |  |  |  |  |  |  | # just pipes all input into conn->in(...) | 
| 6 |  |  |  |  |  |  | ############################################################################ | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 34 |  | 
| 9 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 53 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | package App::HTTP_Proxy_IMP::Conn; | 
| 12 | 1 |  |  | 1 |  | 7 | use base 'Net::Inspect::L7::HTTP'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1103 |  | 
| 13 | 1 |  |  | 1 |  | 12555 | use App::HTTP_Proxy_IMP::Debug; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 112 |  | 
| 14 | 1 |  |  | 1 |  | 7 | use Scalar::Util 'weaken'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 62 |  | 
| 15 |  |  |  |  |  |  | use fields ( | 
| 16 |  |  |  |  |  |  | # all connections | 
| 17 | 1 |  |  |  |  | 8 | 'pcapdir',     # dir for writing pcaps | 
| 18 |  |  |  |  |  |  | 'mitm',        # IO::Socket::SSL::Intercept object for SSL interception | 
| 19 |  |  |  |  |  |  | 'capath',      # path to file|direcory with CA certificates | 
| 20 |  |  |  |  |  |  | 'imp_factory', # App::HTTP_Proxy_IMP::IMP factory | 
| 21 |  |  |  |  |  |  | # per connection | 
| 22 |  |  |  |  |  |  | 'spool',       # any data which cannot be processed yet? | 
| 23 |  |  |  |  |  |  | 'pcapw',       # Net::PcapWriter object | 
| 24 |  |  |  |  |  |  | 'intunnel',    # true if connections is inside intercepted SSL tunnel | 
| 25 |  |  |  |  |  |  | 'relay',       # weak reference to managing relay | 
| 26 | 1 |  |  | 1 |  | 5 | ); | 
|  | 1 |  |  |  |  | 1 |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | sub new { | 
| 29 | 2 |  |  | 2 | 1 | 10 | my ($class,$upper_flow,%args) = @_; | 
| 30 | 2 |  |  |  |  | 14 | my $self = $class->SUPER::new($upper_flow); | 
| 31 | 2 | 50 |  |  |  | 434 | %$self = ( %$self, %args ) if %args; | 
| 32 | 2 | 50 |  |  |  | 8 | if ( ref($class)) { # from factory | 
| 33 | 0 |  | 0 |  |  | 0 | $self->{pcapdir} ||= $class->{pcapdir}; | 
| 34 | 0 |  | 0 |  |  | 0 | $self->{imp_factory} ||= $class->{imp_factory}; | 
| 35 | 0 |  | 0 |  |  | 0 | $self->{mitm} ||= $class->{mitm}; | 
| 36 | 0 |  | 0 |  |  | 0 | $self->{capath} ||= $class->{capath}; | 
| 37 |  |  |  |  |  |  | } | 
| 38 | 2 |  |  |  |  | 8 | return $self; | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | sub DESTROY { | 
| 42 | 0 | 0 |  | 0 |  |  | my $self = shift or return; | 
| 43 | 0 |  |  |  |  |  | $self->xdebug("connection done"); | 
| 44 | 0 |  |  |  |  |  | $self->SUPER::DESTROY(); | 
| 45 |  |  |  |  |  |  | } | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | sub clone { | 
| 48 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 49 |  |  |  |  |  |  | return $self->new_connection( | 
| 50 |  |  |  |  |  |  | $self->{meta}, | 
| 51 |  |  |  |  |  |  | $self->{relay} | 
| 52 | 0 |  |  |  |  |  | ); | 
| 53 |  |  |  |  |  |  | } | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | sub new_connection { | 
| 56 | 0 |  |  | 0 | 1 |  | my ($self,$meta,$relay) = @_; | 
| 57 | 0 |  |  |  |  |  | my $obj = $self->SUPER::new_connection($meta); | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 0 | 0 |  |  |  |  | if ( my $pcapdir = $self->{pcapdir} ) { | 
| 60 | 0 | 0 |  |  |  |  | open( my $fh,'>', sprintf("%s/%d.%d.pcap",$pcapdir,$$,$obj->{connid})) | 
| 61 |  |  |  |  |  |  | or die "cannot open pcap file: $!"; | 
| 62 | 0 |  |  |  |  |  | $fh->autoflush; | 
| 63 | 0 |  |  |  |  |  | my $w = Net::PcapWriter->new($fh); | 
| 64 |  |  |  |  |  |  | my $c = $w->tcp_conn( | 
| 65 |  |  |  |  |  |  | $meta->{daddr}, $meta->{dport}, | 
| 66 |  |  |  |  |  |  | $meta->{saddr}, $meta->{sport} | 
| 67 | 0 |  |  |  |  |  | ); | 
| 68 | 0 |  |  |  |  |  | $obj->{pcapw} = [$c,$w], | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 0 |  |  |  |  |  | weaken( $obj->{relay} = $relay ); | 
| 72 | 0 |  |  |  |  |  | return $obj; | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | sub in { | 
| 76 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 77 | 0 | 0 |  |  |  |  | return $self->SUPER::in(@_) if ! $self->{pcapw}; | 
| 78 | 0 |  |  |  |  |  | my ($dir,$data,$eof,$time) = @_; | 
| 79 | 0 | 0 |  |  |  |  | if ( defined ( my $bytes = eval { $self->SUPER::in(@_) } )) { | 
|  | 0 |  |  |  |  |  |  | 
| 80 | 0 |  |  |  |  |  | $self->{pcapw}[0]->write($dir,substr($data,0,$bytes)); | 
| 81 | 0 |  |  |  |  |  | return $bytes; | 
| 82 |  |  |  |  |  |  | } else { | 
| 83 |  |  |  |  |  |  | # save final data | 
| 84 | 0 |  |  |  |  |  | $self->{pcapw}[0]->write($dir,$data); | 
| 85 | 0 | 0 |  |  |  |  | die $@ if $@; | 
| 86 | 0 |  |  |  |  |  | return; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | sub id { | 
| 92 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 93 | 0 |  |  |  |  |  | return "$$.$self->{connid}"; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | 1; |