diff options
Diffstat (limited to 'lib/network/ipsec.pm')
-rw-r--r-- | lib/network/ipsec.pm | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/lib/network/ipsec.pm b/lib/network/ipsec.pm new file mode 100644 index 0000000..846b07a --- /dev/null +++ b/lib/network/ipsec.pm @@ -0,0 +1,619 @@ +package network::ipsec; + + + +use detect_devices; +use run_program; +use common; +use log; + +#- debugg functions ---------- +sub recreate_ipsec_conf { + my ($ipsec) = @_; + foreach my $key1 (ikeys %$ipsec) { + if (! $ipsec->{$key1}{command}) { + print "$ipsec->{$key1}\n"; + } else { + print $ipsec->{$key1}{command} . " " . + $ipsec->{$key1}{src_range} . " " . + $ipsec->{$key1}{dst_range} . " " . + $ipsec->{$key1}{upperspec} . " " . + $ipsec->{$key1}{flag} . " " . + $ipsec->{$key1}{direction} . " " . + $ipsec->{$key1}{ipsec} . "\n\t" . + $ipsec->{$key1}{protocol} . "/" . + $ipsec->{$key1}{mode} . "/" . + $ipsec->{$key1}{src_dest} . "/" . + $ipsec->{$key1}{level} . ";\n"; + } + } +} + +sub recreate_racoon_conf { + my ($racoon) = @_; + my $in_a_section = "n"; + my $in_a_proposal_section = "n"; + foreach my $key1 (ikeys %$racoon) { + if ($in_a_proposal_section eq "y") { + print "\t}\n}\n$racoon->{$key1}\n" if ! $racoon->{$key1}{1}; + } elsif ($in_a_section eq "y") { + print "}\n$racoon->{$key1}\n" if ! $racoon->{$key1}{1}; + } else { + print "$racoon->{$key1}\n" if ! $racoon->{$key1}{1}; + } + $in_a_section = "n"; + $in_a_proposal_section = "n"; + foreach my $key2 (ikeys %{$racoon->{$key1}}) { + if ($racoon->{$key1}{$key2}[0] =~ /^path/) { + print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2];\n"; + } elsif ($racoon->{$key1}{$key2}[0] =~ /^remote/) { + $in_a_section = "y"; + $in_a_proposal_section = "n"; + print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] {\n"; + } elsif ($racoon->{$key1}{$key2}[0] =~ /^sainfo/) { + $in_a_section = "y"; + $in_a_proposal_section = "n"; + if ($racoon->{$key1}{$key2}[2] && $racoon->{$key1}{$key2}[5]) { + print "$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2] $racoon->{$key1}{$key2}[3] $racoon->{$key1}{$key2}[4] $racoon->{$key1}{$key2}[5] $racoon->{$key1}{$key2}[6] {\n"; + } else { + print "$racoon->{$key1}{$key2}[0] anonymous {\n"; + } + } elsif ($racoon->{$key1}{$key2}[0] =~ /^proposal /) { + $in_a_proposal_section = "y"; + print "\t$racoon->{$key1}{$key2}[0] {\n"; + } elsif ($in_a_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^certificate_type/) { + print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1] $racoon->{$key1}{$key2}[2] $racoon->{$key1}{$key2}[3];\n"; + } elsif ($in_a_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^#/) { + print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1]\n"; + } elsif ($in_a_section eq "y") { + print "\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1];\n"; + } elsif ($in_a_proposal_section eq "y" && $racoon->{$key1}{$key2}[0] =~ /^#/) { + print "\t\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1]\n"; + } elsif ($in_a_proposal_section eq "y") { + print "\t\t$racoon->{$key1}{$key2}[0] $racoon->{$key1}{$key2}[1];\n"; + } + } + } + +print "}\n"; +} + +sub recreate_ipsec_conf1_k24 { + my ($ipsec) = @_; + foreach my $key1 (ikeys %$ipsec) { + print "$key1-->$ipsec->{$key1}\n" if ! $ipsec->{$key1}{1}; + foreach my $key2 (ikeys %{$ipsec->{$key1}}) { + if ($ipsec->{$key1}{$key2}[0] =~ m/^#/) { + print "\t$key2-->$ipsec->{$key1}{$key2}[0]\n"; + } elsif ($ipsec->{$key1}{$key2}[0] =~ m/(conn|config|version)/) { + print "$key1-->$key2-->$ipsec->{$key1}{$key2}[0] $ipsec->{$key1}{$key2}[1]\n"; + } else { + print "\t$key2-->$ipsec->{$key1}{$key2}[0]=$ipsec->{$key1}{$key2}[1]\n"; + } + } + } +} +#- end of debug functions -------- + +sub sys { system(@_) == 0 or log::l("[drakvpn] Warning, sys failed for $_[0]") } + +sub start_daemons () { + return if $::testing; + log::explanations("Starting daemons"); + if (-e "/etc/rc.d/init.d/ipsec") { + system("/etc/rc.d/init.d/ipsec status >/dev/null") == 0 and sys("/etc/rc.d/init.d/ipsec stop"); + sys("/etc/rc.d/init.d/$_ start >/dev/null"), sys("/sbin/chkconfig --level 345 $_ on") foreach 'ipsec'; + } else { + + } + sys("/etc/rc.d/init.d/$_ start >/dev/null"), sys("/sbin/chkconfig --level 345 $_ on") foreach 'shorewall'; +} + +sub stop_daemons () { + return if $::testing; + log::explanations("Stopping daemons"); + if (-e "/etc/rc.d/init.d/ipsec") { + foreach (qw(ipsec)) { + system("/etc/rc.d/init.d/$_ status >/dev/null 2>/dev/null") == 0 and sys("/etc/rc.d/init.d/$_ stop"); + } + sys("/sbin/chkconfig --level 345 $_ off") && -e "/etc/rc.d/init.d/$_" foreach 'ipsec'; + } + system("/etc/rc.d/init.d/shorewall status >/dev/null 2>/dev/null") == 0 and sys("/etc/rc.d/init.d/shorewall stop >/dev/null"); + +} + +sub set_config_file { + my ($file, @l) = @_; + + my $done; + substInFile { + if (!$done && (/^#LAST LINE/ || eof)) { + $_ = join('', map { join("\t", @$_) . "\n" } @l) . $_; + $done = 1; + } else { + $_ = '' if /^[^#]/; + } + } "$::prefix/$file"; +} + +sub get_config_file { + my ($file) = @_; + map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix/$file"); +} + + +#------------------------------------------------------------------- +#---------------------- configure racoon_conf ----------------------- +#------------------------------------------------------------------- + +sub read_racoon_conf { + my ($racoon_conf) = @_; + my %conf; + my $nb = 0; #total number + my $i = 0; #nb within a section + my $in_a_section = "n"; + my @line1; + my $line = ""; + local $_; + open(my $LIST, "< $racoon_conf"); + while (<$LIST>) { + chomp($_); + $line = $_; + $in_a_section = "n" if $line =~ /}/ && $line !~ /^#/; + $line =~ s/^\s+|\s*;|\s*{//g if $line !~ /^#/; + $line =~ /(.*)#(.*)/ if $line !~ /^#/; #- define before and after comment +# print "--line-->$line\n"; + my $data_part = $1; + my $comment_part = "#" . $2; + if ($data_part) { + $data_part =~ s/,//g; +# print "@@".$data_part."->".$comment_part."\n"; + @line1 = split /\s+/,$data_part; + @line1 = (@line1, $comment_part) if $comment_part; + } else { + @line1 = split /\s+/,$line; + } + if (!$line && $in_a_section eq "n") { + $nb++; + put_in_hash(\%conf, { $nb => $line }); + $in_a_section = "n"; + } elsif (!$line && $in_a_section eq "y") { + put_in_hash($conf{$nb} ||= {}, { $i => [ '' ] }); + $i++; + } elsif ($line =~ /^path/) { + $i=1; + $nb++; + put_in_hash($conf{$nb} ||= {}, { $i => [@line1] }); + $in_a_section = "n"; + $i++; + } elsif ($line =~ /^#|^{|^}/) { + if ($in_a_section eq "y") { + put_in_hash($conf{$nb} ||= {}, { $i => [$line] }); + $i++; + } else { + $nb++; + put_in_hash(\%conf, { $nb => $line }); + $in_a_section = "n"; + } + } elsif ($line =~ /^sainfo|^remote|^listen|^timer|^padding/ && $in_a_section eq "n") { + $i=1; + $nb++; + put_in_hash($conf{$nb} ||= {}, { $i => [@line1] }); + $in_a_section = "y"; + $i++; + } elsif ($line eq "proposal" && $in_a_section eq "y") { + $i=1; + $nb++; + put_in_hash($conf{$nb} ||= {}, { $i => [@line1] }); + $in_a_section = "y"; + $i++; + } else { + put_in_hash($conf{$nb} ||= {}, { $i => [@line1] }); + $i++; + } + } + +\%conf; +} + +sub display_racoon_conf { + my ($racoon) = @_; + my $display = ""; + my $prefix_to_simple_line = ""; + foreach my $key1 (ikeys %$racoon) { + if (!$racoon->{$key1}{1}) { + $display .= $prefix_to_simple_line . $racoon->{$key1} . "\n"; + $prefix_to_simple_line = ""; + } else { + foreach my $key2 (ikeys %{$racoon->{$key1}}) { + my $t = $racoon->{$key1}{1}[0]; + my $f = $racoon->{$key1}{$key2}[0]; + my $list_length = scalar @{$racoon->{$key1}{$key2}}; + my $line = ""; + + if ($racoon->{$key1}{$key2}[0] eq "sainfo" && !$racoon->{$key1}{$key2}[2]) { + $line = "sainfo anonymous"; + } else { + for (my $i = 0; $i <= $list_length-1; $i++) { + + my $c = $racoon->{$key1}{$key2}[$i]; + my $n = $racoon->{$key1}{$key2}[$i+1]; + + if ($c =~ /^path|^log|^timer|^listen|^padding|^remote|^proposal|^sainfo/) { + $line .= "$c "; + } elsif ($i == $list_length-2 && $n =~ /^#/) { + $line .= "$c; "; + } elsif ($i == $list_length-1) { + if ($f =~ /^#|^$|^timer|^listen|^padding|^remote|^proposal\s+|^sainfo/) { + $line .= $c; + } elsif ($c =~ /^#/) { + $line .= "\t$c"; + } else { + $line .= "$c;"; + } + } else { + $line .= "$c "; + } + } + } + + if ($f =~ /^timer|^listen|^padding|^remote|^sainfo/) { + $line .= " {"; + $prefix_to_simple_line = ""; + } elsif ($f eq "proposal") { + $line = "\t" . $line . " {"; + } elsif ($t eq "proposal") { + $line = "\t\t" . $line if $line ne "proposal"; + $prefix_to_simple_line = "\t"; + } else { + $line = "\t" . $line if $t !~ /^path|^log/; + $prefix_to_simple_line = ""; + } + $display .= "$line\n"; + } + } + } + +$display; + +} + +sub write_racoon_conf { + my ($racoon_conf, $racoon) = @_; + my $display = ""; + my $prefix_to_simple_line = ""; + foreach my $key1 (ikeys %$racoon) { + if (!$racoon->{$key1}{1}) { + $display .= $prefix_to_simple_line . $racoon->{$key1} . "\n"; + $prefix_to_simple_line = ""; + } else { + foreach my $key2 (ikeys %{$racoon->{$key1}}) { + my $t = $racoon->{$key1}{1}[0]; + my $f = $racoon->{$key1}{$key2}[0]; + my $list_length = scalar @{$racoon->{$key1}{$key2}}; + my $line = ""; + + if ($racoon->{$key1}{$key2}[0] eq "sainfo" && !$racoon->{$key1}{$key2}[2]) { + $line = "sainfo anonymous"; + } else { + for (my $i = 0; $i <= $list_length-1; $i++) { + + my $c = $racoon->{$key1}{$key2}[$i]; + my $n = $racoon->{$key1}{$key2}[$i+1]; + + if ($c =~ /^path|^log|^timer|^listen|^padding|^remote|^proposal|^sainfo/) { + $line .= "$c "; + } elsif ($i == $list_length-2 && $n =~ /^#/) { + $line .= "$c; "; + } elsif ($i == $list_length-1) { + if ($f =~ /^#|^$|^timer|^listen|^padding|^remote|^proposal\s+|^sainfo/) { + $line .= $c; + } elsif ($c =~ /^#/) { + $line .= "\t$c"; + } else { + $line .= "$c;"; + } + } else { + $line .= "$c "; + } + } + } + + if ($f =~ /^timer|^listen|^padding|^remote|^sainfo/) { + $line .= " {"; + $prefix_to_simple_line = ""; + } elsif ($f eq "proposal") { + $line = "\t" . $line . " {"; + } elsif ($t eq "proposal") { + $line = "\t\t" . $line if $line ne "proposal"; + $prefix_to_simple_line = "\t"; + } else { + $line = "\t" . $line if $t !~ /^path|^log/; + $prefix_to_simple_line = ""; + } + $display .= "$line\n"; + } + } + } + +open(my $ADD, "> $racoon_conf") or die "Can not open the $racoon_conf file for writing"; + print $ADD "$display\n"; + +} + +sub get_section_names_racoon_conf { + my ($racoon) = @_; + my @section_names; + + foreach my $key1 (ikeys %$racoon) { + if (!$racoon->{$key1}{1}) { + next; + } else { + my $list_length = scalar @{$racoon->{$key1}{1}}; + my $section_title = ""; + my $separator = ""; + for (my $i = 0; $i <= $list_length-1; $i++) { + my $s = $racoon->{$key1}{1}[$i]; + if ($s !~ /^#|^proposal/) { + $section_title .= $separator . $s; + $separator = " "; + } + } + push(@section_names, $section_title) if $section_title ne ""; + } + } + + @section_names; + +} + +sub add_section_racoon_conf { + my ($new_section, $racoon) = @_; + put_in_hash($racoon, { max(keys %$racoon) + 1 => '' }); + put_in_hash($racoon, { max(keys %$racoon) + 1 => $new_section }); + put_in_hash($racoon, { max(keys %$racoon) + 1 => '}' }) if $new_section->{1}[0] !~ /^path|^remote/; + put_in_hash($racoon, { max(keys %$racoon) + 1 => '' }) if $new_section->{1}[0] =~ /^proposal/; + put_in_hash($racoon, { max(keys %$racoon) + 1 => '}' }) if $new_section->{1}[0] =~ /^proposal/; +} + +sub matched_section_key_number_racoon_conf { + my ($section_name, $racoon) = @_; + foreach my $key1 (ikeys %$racoon) { + if (!$racoon->{$key1}{1}) { + next; + } else { + my $list_length = scalar @{$racoon->{$key1}{1}}; + my $section_title = ""; + my $separator = ""; + for (my $i = 0; $i <= $list_length-1; $i++) { + my $s = $racoon->{$key1}{1}[$i]; + if ($s !~ /^#|^proposal/) { + $section_title .= $separator . $s; + $separator = " "; + } + } + if ($section_title eq $section_name) { + return $key1; + } + } + } + +} + +sub already_existing_section_racoon_conf { + my ($section_name, $racoon, $racoon_conf) = @_; + if (-e $racoon_conf) { + foreach my $key1 (ikeys %$racoon) { + if (!$racoon->{$key1}{1}) { + next; + } elsif (find { + my $list_length = scalar @{$racoon->{$key1}{1}}; + my $section_title = ""; + my $separator = ""; + for (my $i = 0; $i <= $list_length-1; $i++) { + my $s = $racoon->{$key1}{1}[$i]; + if ($s !~ /^#|^proposal/) { + $section_title .= $separator . $s; + $separator = " "; + } + } + + $section_title eq $section_name; + + } ikeys %{$racoon->{$key1}}) { + + return "already existing"; + } + } + } + +} + +sub remove_section_racoon_conf { + my ($section_name, $racoon, $k) = @_; + if ($section_name =~ /^remote/) { + + delete $racoon->{$k} if $k > 1 && !$racoon->{$k-1}; + my $closing_curly_bracket = 0; + while ($closing_curly_bracket < 2) { + print "-->$k\n"; + $closing_curly_bracket++ if $racoon->{$k} eq "}"; + delete $racoon->{$k}; + $k++; + } + + } elsif ($section_name =~ /^path/) { + + delete $racoon->{$k}; + delete $racoon->{$k+1} if $racoon->{$k+1}{1} eq ""; + + } else { + + delete $racoon->{$k}; + delete $racoon->{$k+1} if $racoon->{$k+1}{1} eq ""; + delete $racoon->{$k+2} if $racoon->{$k+2}{1} eq ""; #- remove assoc } + + } + +} + +#------------------------------------------------------------------- +#---------------------- configure ipsec_conf ----------------------- +#------------------------------------------------------------------- + +sub read_ipsec_conf { + my ($ipsec_conf) = @_; + my %conf; + my $nb = 0; #total number + my $i = 0; #nb within a connexion + my $in_a_conn = "n"; + my $line = ""; + my @line1; + local $_; + my @mylist; + my $myline = ""; + open(my $LIST, "< $ipsec_conf"); #or die "Can not open the $ipsec_conf file for reading"; + while (<$LIST>) { + chomp($_); + $myline = $_; + $myline =~ s/^\s+//; + $myline =~ s/;$//; + if ($myline =~ /^spdadd/) { + @mylist = split /\s+/,$myline; + $in_a_conn = "y"; + $nb++; + next; + } elsif ($in_a_conn eq "y") { + @mylist = (@mylist, split '\s+|/',$myline); + put_in_hash(\%conf, { $nb => { command => $mylist[0], + src_range => $mylist[1], + dst_range => $mylist[2], + upperspec => $mylist[3], + flag => $mylist[4], + direction => $mylist[5], + ipsec => $mylist[6], + protocol => $mylist[7], + mode => $mylist[8], + src_dest => $mylist[9], + level => $mylist[10] } }); + $in_a_conn = "n"; + } else { + $nb++; + put_in_hash(\%conf, { $nb => $myline }); + } + } + + \%conf; +} + +sub write_ipsec_conf { + my ($ipsec_conf, $ipsec) = @_; + my $display = ""; + foreach my $key1 (ikeys %$ipsec) { + if (! $ipsec->{$key1}{command}) { + $display .= "$ipsec->{$key1}\n"; + } else { + $display .= $ipsec->{$key1}{command} . " " . + $ipsec->{$key1}{src_range} . " " . + $ipsec->{$key1}{dst_range} . " " . + $ipsec->{$key1}{upperspec} . " " . + $ipsec->{$key1}{flag} . " " . + $ipsec->{$key1}{direction} . " " . + $ipsec->{$key1}{ipsec} . "\n\t" . + $ipsec->{$key1}{protocol} . "/" . + $ipsec->{$key1}{mode} . "/" . + $ipsec->{$key1}{src_dest} . "/" . + $ipsec->{$key1}{level} . ";\n"; + } + } + open(my $ADD, "> $ipsec_conf") or die "Can not open the $ipsec_conf file for writing"; + print $ADD $display; +} + +sub display_ipsec_conf { + my ($ipsec) = @_; + my $display = ""; + + foreach my $key1 (ikeys %$ipsec) { + if (! $ipsec->{$key1}{command}) { + $display .= "$ipsec->{$key1}\n"; + } else { + $display .= $ipsec->{$key1}{command} . " " . + $ipsec->{$key1}{src_range} . " " . + $ipsec->{$key1}{dst_range} . " " . + $ipsec->{$key1}{upperspec} . " " . + $ipsec->{$key1}{flag} . " " . + $ipsec->{$key1}{direction} . " " . + $ipsec->{$key1}{ipsec} . "\n\t" . + $ipsec->{$key1}{protocol} . "/" . + $ipsec->{$key1}{mode} . "/" . + $ipsec->{$key1}{src_dest} . "/" . + $ipsec->{$key1}{level} . ";\n"; + } + } + + $display; + +} + +sub get_section_names_ipsec_conf { + my ($ipsec) = @_; + my @section_names; + + foreach my $key1 (ikeys %$ipsec) { + if ($ipsec->{$key1}{command} =~ m/(^spdadd)/) { + push(@section_names, "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}"); + } + } + + @section_names; + +} + +sub remove_section_ipsec_conf { + my ($section_name, $ipsec) = @_; + foreach my $key1 (ikeys %$ipsec) { + if (find { + my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}"; + $s !~ /^#/ && $ipsec->{$key1}{src_range} && $section_name eq $s; + } ikeys %{$ipsec->{$key1}}) { + delete $ipsec->{$key1-1}; + delete $ipsec->{$key1}; + } + } +} + +sub add_section_ipsec_conf { + my ($new_section, $ipsec) = @_; + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => '' }); + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => $new_section }); +} + +sub already_existing_section_ipsec_conf { + my ($section_name, $ipsec) = @_; + foreach my $key1 (ikeys %$ipsec) { + if (find { + my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}"; + $s !~ /^#/ && $ipsec->{$key1}{src_range} && + $section_name eq $s; + } ikeys %{$ipsec->{$key1}}) { + return "already existing"; + } + } + return "no"; +} + +#- returns the hash key number of $section_name +sub matched_section_key_number_ipsec_conf { + my ($section_name, $ipsec) = @_; + foreach my $key1 (ikeys %$ipsec) { + if (find { + my $s = "$ipsec->{$key1}{src_range} $ipsec->{$key1}{dst_range}"; + $s !~ /^#/ && $ipsec->{$key1}{src_range} && + $section_name eq $s; + } ikeys %{$ipsec->{$key1}}) { + return $key1; + } + } +} +1 |