package Iodef::Pb::Simple::Plugin::Ipv4; use base 'Iodef::Pb::Simple::Plugin'; use strict; use warnings; use Regexp::Common qw/net/; use Regexp::Common::net::CIDR; sub process { my $self = shift; my $data = shift; my $iodef = shift; my $addr = $data->{'address'}; my $mask = $data->{'address_mask'} || 32; # 32 seems easier than 0 or undef $addr = $addr.'/'.$mask if($mask < 32); return unless($addr && ($addr =~ /^$RE{'net'}{'IPv4'}$/ || $addr =~ /^$RE{'net'}{'CIDR'}{'IPv4'}$/)); my $category = ($addr =~ /^$RE{'net'}{'IPv4'}$/) ? AddressType::AddressCategory::Address_category_ipv4_addr() : AddressType::AddressCategory::Address_category_ipv4_net(); $addr = normalize_address($addr); my @additional_data; if($data->{'prefix'} && $data->{'prefix'} =~ /^$RE{'net'}{'CIDR'}{'IPv4'}$/){ push(@additional_data,ExtensionType->new({ dtype => ExtensionType::DtypeType::dtype_type_string(), meaning => 'prefix', content => $data->{'prefix'}, })); } if($data->{'asn'}){ $data->{'asn'} =~ s/^(AS|as)//; push(@additional_data,ExtensionType->new({ dtype => ExtensionType::DtypeType::dtype_type_string(), meaning => 'asn', content => $data->{'asn'}, })); } if($data->{'asn_desc'}){ push(@additional_data,ExtensionType->new({ dtype => ExtensionType::DtypeType::dtype_type_string(), meaning => 'asn_desc', content => $data->{'asn_desc'}, })); } if($data->{'cc'}){ push(@additional_data, ExtensionType->new({ dtype => ExtensionType::DtypeType::dtype_type_string(), meaning => 'cc', content => uc($data->{'cc'}), }) ); } if($data->{'rir'}){ push(@additional_data, ExtensionType->new({ dtype => ExtensionType::DtypeType::dtype_type_string(), meaning => 'rir', content => uc($data->{'rir'}), }) ); } my $service; if($data->{'service'} && ref($data->{'service'}) eq 'ServiceType'){ $service = $data->{'service'}; } elsif($data->{'protocol'} || $data->{'portlist'}) { if($data->{'service'}){ my $app = SoftwareType->new({ name => $data->{'service'}, }); $service = ServiceType->new({ Application => $app, }); } else { $service = ServiceType->new(); } my $proto = $data->{'protocol'} || $data->{'ip_protocol'}; if($data->{'portlist'}){ # normalize peoples wierd port habbits $data->{'portlist'} =~ m/(\d+(-\d+)?)$/; $data->{'portlist'} = $1; $service->set_Portlist($data->{'portlist'}); # IODEF requires a default $proto = 'tcp' unless($proto); } if($proto){ $proto = $self->normalize_protocol($proto); $service->set_ip_protocol($proto); } } my $system = $data->{'system'}; unless(ref($system) eq 'SystemType'){ $system = SystemType->new({ Node => NodeType->new({ Address => AddressType->new({ category => $category, content => $addr, }), }), category => SystemType::SystemCategory::System_category_infrastructure(), }); } if($#additional_data > -1){ $system->set_AdditionalData(\@additional_data); } if($service){ $system->set_Service($service); } my $event = EventDataType->new({ Flow => FlowType->new({ System => $system, }), }); my $incident = @{$iodef->get_Incident()}[0]; push(@{$incident->{'EventData'}},$event); } sub normalize_address { my $addr = shift; my @bits = split(/\./,$addr); foreach(@bits){ if(/^0+\/(\d+)$/){ $_ = '0/'.$1; } else { next if(/^0$/); next unless(/^0{1,2}/); $_ =~ s/^0{1,2}//; } } return join('.',@bits); } 1;