diff options
Diffstat (limited to 'bin/drakvpn')
-rw-r--r-- | bin/drakvpn | 1136 |
1 files changed, 1136 insertions, 0 deletions
diff --git a/bin/drakvpn b/bin/drakvpn new file mode 100644 index 0000000..09ddae8 --- /dev/null +++ b/bin/drakvpn @@ -0,0 +1,1136 @@ +#!/usr/bin/perl + +# +# author Florin Grad (florin@mandrakesoft.com) +# +# Copyright 2005 Mandriva +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + + +use lib qw(/usr/lib/libDrakX); + +use standalone; #- warning, standalone must be loaded very first, for 'explanations' + +use common; +use detect_devices; +use interactive; +use network::network; +use log; +use c; +use network::netconnect; +use network::shorewall; +use network::ipsec; +use Data::Dumper; + +$::isInstall and die "Not supported during install.\n"; + + +local $_ = join '', @ARGV; + +$::Wizard_pix_up = "drakvpn.png"; +$ugtk2::wm_icon = "drakvpn"; + +my $direct = /-direct/; + +my ($kernel_version) = c::kernel_version() =~ /(...)/; +log::l("[drakvpn] kernel_version $kernel_version"); + +$kernel_version >= 2.4 or fatal_quit(N("Sorry, we support only 2.4 and above kernels.")); + +my $tunnels_file = "/etc/shorewall/tunnels"; +my $ipsec_conf = ""; +my $racoon_conf = "/etc/racoon/racoon.conf"; +my $proc_version = ""; +my $ipsec_package = ""; + +my $in = interactive->vnew('su'); +my $shorewall = network::shorewall::read($in); +my @section_names; + +if ($kernel_version > 2.5) { + $ipsec_conf = "/etc/ipsec.conf"; +} else { + $ipsec_conf = "/etc/freeswan/ipsec.conf"; +} +my $ipsec = network::ipsec::read_ipsec_conf($ipsec_conf,$kernel_version); +my $racoon = network::ipsec::read_racoon_conf($racoon_conf); + +#print network::ipsec::display_ipsec_conf($ipsec_conf,$ipsec,$kernel_version); + +$::Wizard_title = N("DrakVPN"); + +$in->isa('interactive::gtk') and $::isWizard = 1; + +my $wait_configuring; + +sub fatal_quit ($) { + log::l("[drakvpn] FATAL: $_[0]"); + undef $wait_configuring; + $in->ask_warn('', $_[0]); + quit_global($in, -1); +} + +begin: + +#- ********************************** +#- * 0th step: verify if we are already set up + +if ($shorewall && any { !/^\s*(?:#|\n)/ } cat_($tunnels_file)) { + $::Wizard_no_previous = 1; + + if (!$shorewall->{disabled}) { + my $r = $in->ask_from_list_(N("The VPN connection is enabled."), +N("The setup of a VPN connection has already been done. + +It's currently enabled. + +What would you like to do?"), + [ N_("disable"), N_("reconfigure"), N_("dismiss") ]) or quit_global($in, 0); + # FIXME: reconfigure is not handled + if ($r eq "disable") { + if (!$::testing) { + my $_wait_disabl = $in->wait_message('', N("Disabling VPN...")); + network::ipsec::stop_daemons(); + } + foreach ($ipsec_conf, $tunnels_file) { + if (-f $_) { rename($_, "$_.drakvpndisable") or die "Could not rename $_ to $_.drakvpndisable" } + } + network::ipsec::sys("/etc/init.d/shorewall restart >/dev/null"); + log::l("[drakvpn] Disabled"); + $::Wizard_finished = 1; + $in->ask_okcancel('', N("The VPN connection is now disabled.")); + quit_global($in, 0); + } + if ($r eq "dismiss") { + quit_global($in, 0); + } + } else { + my $r = $in->ask_from_list_(N("VPN connection currently disabled"), +N("The setup of a VPN connection has already been done. + +It's currently disabled. + +What would you like to do?"), + [ N_("enable"), N_("reconfigure"), N_("dismiss") ]); + # FIXME: reconfigure is not handled + if ($r eq "enable") { + foreach ($ipsec_conf, $tunnels_file) { + rename($_, "$_.old") if -f $_; + rename("$_.drakvpndisable", $_) or die "Could not find configuration. Please reconfigure."; + } + { + my $_wait_enabl = $in->wait_message('', N("Enabling VPN...")); + network::ipsec::start_daemons(); + } + log::l("[drakvpn] Enabled"); + } + $::Wizard_finished = 1; + $in->ask_okcancel('', N("The VPN connection is now enabled.")); + quit_global($in, 0); + if ($r eq "dismiss") { + quit_global($in, 0); + } + } + } + +#- ********************************** +#- * 1st step: detect/setup +step_ask_confirm: + +$::Wizard_no_previous = 1; + +$direct or $in->ask_okcancel(N("Simple VPN setup."), +N("You are about to configure your computer to use a VPN connection. + +With this feature, computers on your local private network and computers +on some other remote private networks, can share resources, through +their respective firewalls, over the Internet, in a secure manner. + +The communication over the Internet is encrypted. The local and remote +computers look as if they were on the same network. + +Make sure you have configured your Network/Internet access using +drakconnect before going any further."), 1) or goto begin; + +undef $::Wizard_no_previous; + +if ($kernel_version < 2.5) { + system("/sbin/modprobe ipsec") if -e "/sbin/modprobe"; + $proc_version = cat_("/proc/net/ipsec_version") if -e "/proc/net/ipsec_version"; + if ($proc_version =~ /super/i) { + $ipsec_package = "super-freeswan"; + } else { + $ipsec_package = "freeswan"; + } +} else { + $ipsec_package = "ipsec-tools"; + $proc_version = "ipsec native"; +} + +$direct or $in->ask_okcancel(N("Simple VPN setup."), +N("VPN connection. + +This program is based on the following projects: + - FreeSwan: \t\t\thttp://www.freeswan.org/ + - Super-FreeSwan: \t\thttp://www.freeswan.ca/ + - ipsec-tools: \t\t\thttp://ipsec-tools.sourceforge.net/ + - ipsec-howto: \t\thttp://www.ipsec-howto.org + - the docs and man pages coming with the %s package + +Please read AT LEAST the ipsec-howto docs +before going any further.",$ipsec_package)) or goto begin; + +$direct or $in->ask_okcancel(N("Kernel module."), +N("The kernel needs to have ipsec support. + +You're running a %s kernel version. + +This kernel has '%s' support.", $kernel_version, $proc_version)) or goto begin; + +step_detectsetup: + +#my @configured_devices = map { /ifcfg-(\S+)/ } glob('/etc/sysconfig/network-scripts/ifcfg*'); + +my %aliased_devices; +/^\s*alias\s+(eth[0-9])\s+(\S+)/ and $aliased_devices{$1} = $2 foreach cat_("/etc/modules.conf"); + +#- ********************************** +#- * 2nd step: configure + +#$wait_configuring = $in->wait_message(N("Configuring..."), +# N("Configuring scripts, installing software, starting servers...")); + +#- if the kernel has super-freeswan support, remove the freeswan package +#- and vice-versa +#- if you're using e kernel 2.5 and above with native ipsec support, remove +#- both freeswan and super-freeswan packages + +if (!$::testing && $ipsec_package =~ /super/i && $kernel_version < 2.5) { + log::l("[drakvpn] removing the freeswan package"); + $in->do_pkgs->remove("freeswan") if -e "/etc/freeswan/ipsec.d/policies/clear"; + log::l("[drakvpn] removing the ipsec-tools package"); + $in->do_pkgs->remove("ipsec-tools") if -e "/sbin/setkey"; + $in->do_pkgs->remove("libipsec-tools0") if -e "/lib/libipsec.so.0"; +} elsif (!$::testing && $kernel_version < 2.5) { + log::l("[drakvpn] removing the $ipsec_package package"); + $in->do_pkgs->remove("super-freeswan") if -e "/usr/lib/ipsec/auto.advroute"; + log::l("[drakvpn] removing the ipsec-tools package"); + $in->do_pkgs->remove("ipsec-tools") if -e "/sbin/setkey"; + $in->do_pkgs->remove("libipsec-tools0") if -e "/sbin/setkey"; +} else { + log::l("[drakvpn] removing the freeswan AND the super-freeswan packages"); + $in->do_pkgs->remove("freeswan") if -e "/etc/freeswan/ipsec.d/policies/clear"; + $in->do_pkgs->remove("super-freeswan-doc") if -e "/usr/sbin/ipsec"; + $in->do_pkgs->remove("super-freeswan") if -e "/usr/lib/ipsec/auto.advroute"; +} + + +#- install and setup the RPM packages, if needed + +my %rpm2file; +log::l("[drakvpn] install the $ipsec_package and the shorewall rpm packages"); +if (!$::testing && $ipsec_package =~ /ipsec-tools/i) { + %rpm2file = ($ipsec_package => '/sbin/setkey', + shorewall => '/sbin/shorewall'); +} else { + %rpm2file = ($ipsec_package => '/usr/sbin/ipsec', + shorewall => '/sbin/shorewall'); +} + +#- first: try to install all in one step, if needed +if (! ($ipsec_package =~ /super/i && -e "/usr/lib/ipsec/auto.advroute" || + $ipsec_package =~ /^freeswan/i && -e "/etc/freeswan/ipsec.d/policies/clear" || + $ipsec_package =~ /ipsec-tools/i && -e "/sbin/setkey")) { + + my @needed_to_install = grep { !-e $rpm2file{$_} } keys %rpm2file; + @needed_to_install and $in->do_pkgs->install(@needed_to_install) if !$::testing; + #- second: try one by one if failure detected + if (!$::testing && any { !-e $rpm2file{$_} } keys %rpm2file) { + foreach (keys %rpm2file) { + -e $rpm2file{$_} or $in->do_pkgs->install($_); + -e $rpm2file{$_} or fatal_quit(N("Problems installing package %s", $_)); + } + } +} + +undef $wait_configuring; + +#- configure the $ipsec_conf file +#- Add, Remove config|conn entries + +step_configuration: + +my $c; + +my %messages = (ipsec => N("Security Policies"), racoon => N("IKE daemon racoon")); + +if ($kernel_version > 2.5) { + $in->ask_from(N("Configuration file"), +N("Configuration step! + +You need to define the Security Policies and then to +configure the automatic key exchange (IKE) daemon. +The KAME IKE daemon we're using is called 'racoon'. + +What would you like to configure?\n"), + [ { val => \$c, type => "list", list => [ keys %messages ], format => sub { $messages{$_[0]} } } ]) or goto step_detectsetup; + +} else { +$in->ask_okcancel(N("Configuration file"), +N("Next, we will configure the %s file.\n + +Simply click on Next.\n", $ipsec_conf)) or goto step_detectsetup; + + $c = "configure"; +} + +#------------------------------------------------------------------- +#---------------------- configure ipsec_conf ----------------------- +#------------------------------------------------------------------- + +if ($c eq "ipsec" || $c eq "configure") { + +step_configure_ipsec_conf: + +@section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version) if $ipsec; + +my $choice = $section_names[0]; +my $d = $in->ask_from_list_(N("%s entries", $ipsec_conf), +N("The %s file contents +is divided into sections.\n +You can now:\n + - display, add, edit, or remove sections, then + - commit the changes + +What would you like to do?\n", $ipsec_conf), + [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; + +my $existing_section = ""; + +#- display $ipsec_conf ------------------------- + +step_display_ipsec_conf: + +if ($d eq "display $ipsec_conf" || $d eq "_:display here is a verb\nDisplay") { + my $ipsec_exists = 0; + foreach my $key (keys %$ipsec) { + $ipsec_exists = 1 if $ipsec->{$key}; + } + if ($ipsec_exists) { + $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), + network::ipsec::display_ipsec_conf($ipsec,$kernel_version)); + goto step_configure_ipsec_conf; + } else { +$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), +N("The %s file does not exist.\n +This must be a new configuration.\n +You'll have to go back and choose 'add'.\n", $ipsec_conf)); + goto step_configure_ipsec_conf; + } + +#- add --------------------- + +} elsif ($d eq "Add") { + +step_add_section: + +if ($kernel_version < 2.5) { + +#- add ---- kernel 2.4 part ------------------------------- + +my $e = $in->ask_from_list_(N("ipsec.conf entries"), +N("The %s file contains different sections.\n +Here is its skeleton: 'config setup' + 'conn default' + 'normal1' + 'normal2' \n +You can now add one of these sections.\n +Choose the section you would like to add.\n", $ipsec_conf), + [ N_("config setup"), N_("conn %default"), N_("normal conn"), N_("dismiss") ]) or goto step_configure_ipsec_conf; + if ($e eq "config setup") { + + $existing_section = network::ipsec::already_existing_section_ipsec_conf("config setup", $ipsec, $kernel_version); + + if ($existing_section eq "already existing") { +$in->ask_okcancel(N("Exists!"), +N("A section with this name already exists. +The section names have to be unique.\n +You'll have to go back and add another section +or change its name.\n")); + goto step_add_section; +} + + my $config_setup = { + 1 => [ "config", "setup" ], + 2 => [ "interfaces", "%defaultroute" ], + 3 => [ "klipsdebug", "none" ], + 4 => [ "plutodebug", "none" ], + 5 => [ "plutoload", "%search" ], + 6 => [ "plutostart", "%search" ], + 7 => [ "uniqueids", "yes" ], + }; + $in->ask_from('', +N("This section has to be on top of your +%s file.\n +Make sure all other sections follow this config +setup section.\n +Choose continue or previous when you are done.\n", $ipsec_conf), + [ { label => N("interfaces"), val => \$config_setup->{2}[1], type => 'entry' }, + { label => N("klipsdebug"), val => \$config_setup->{3}[1], type => 'entry' }, + { label => N("plutodebug"), val => \$config_setup->{4}[1], type => 'entry' }, + { label => N("plutoload"), val => \$config_setup->{5}[1], type => 'entry' }, + { label => N("plutostart"), val => \$config_setup->{6}[1], type => 'entry' }, + { label => N("uniqueids"), val => \$config_setup->{7}[1], type => 'entry' }, + ] +) or goto step_configure_ipsec_conf; + + network::ipsec::add_section_ipsec_conf($config_setup, $ipsec); + + goto step_configure_ipsec_conf; + + } elsif ($e eq "conn %default") { + + $existing_section = network::ipsec::already_existing_section_ipsec_conf("conn %default", $ipsec, $kernel_version); + + if ($existing_section eq "already existing") { +$in->ask_okcancel(N("Exists!"), +N("A section with this name already exists. +The section names have to be unique.\n +You'll have to go back and add another section +or change its name.\n")); + goto step_add_section; +} + + my $conn_default = { + 1 => [ "conn", "%default" ], + 2 => [ "pfs", "yes" ], + 3 => [ "keyingtries", "1" ], + 4 => [ "compress", "yes" ], + 5 => [ "disablearrivalcheck", "no" ], + 6 => [ "left", "" ], + 7 => [ "leftcert", "" ], + 8 => [ "leftrsasigkey", "%cert" ], + 9 => [ "leftsubnet", "" ], + 10 => [ "leftnexthop", "" ], + }; + $in->ask_from('', +N("This is the first section after the config +setup one.\n +Here you define the default settings. +All the other sections will follow this one. +The left settings are optional. If do not define +them here, globally, you can define them in each +section.\n",), + [ { label => N("PFS"), val => \$conn_default->{2}[1], type => 'entry' }, + { label => N("keyingtries"), val => \$conn_default->{3}[1], type => 'entry' }, + { label => N("compress"), val => \$conn_default->{4}[1], type => 'entry' }, + { label => N("disablearrivalcheck"), val => \$conn_default->{5}[1], type => 'entry' }, + { label => N("left"), val => \$conn_default->{6}[1], type => 'entry' }, + { label => N("leftcert"), val => \$conn_default->{7}[1], type => 'entry' }, + { label => N("leftrsasigkey"), val => \$conn_default->{8}[1], type => 'entry' }, + { label => N("leftsubnet"), val => \$conn_default->{9}[1], type => 'entry' }, + { label => N("leftnexthop"), val => \$conn_default->{10}[1], type => 'entry' }, + ] +) or goto step_configure_ipsec_conf; + + network::ipsec::add_section_ipsec_conf($conn_default, $ipsec); + + goto step_configure_ipsec_conf; + + } elsif ($e eq "normal conn") { + + + my $normal_conn = { + 1 => [ "conn", "my-connection" ], + 2 => [ "authby", "rsasig" ], + 3 => [ "auto", "start" ], + 4 => [ "left", "" ], + 5 => [ "leftcert", "" ], + 6 => [ "leftrsasigkey", "%cert" ], + 7 => [ "leftsubnet", "" ], + 8 => [ "leftnexthop", "" ], + 9 => [ "right", "" ], + 10 => [ "rightcert", "" ], + 11 => [ "rightrsasigkey", "%cert" ], + 12 => [ "rightsubnet", "" ], + 13 => [ "rightnexthop", "" ], + }; + +step_add_normal_conn: + $in->ask_from('', +N("Your %s file has several sections, or connections.\n +You can now add a new section. +Choose continue when you are done to write the data.\n", $ipsec_conf), + [ { label => N("section name"), val => \$normal_conn->{1}[1], type => 'entry' }, + { label => N("authby"), val => \$normal_conn->{2}[1], type => 'entry' }, + { label => N("auto"), val => \$normal_conn->{3}[1], type => 'entry' }, + { label => N("left"), val => \$normal_conn->{4}[1], type => 'entry' }, + { label => N("leftcert"), val => \$normal_conn->{5}[1], type => 'entry' }, + { label => N("leftrsasigkey"), val => \$normal_conn->{6}[1], type => 'entry' }, + { label => N("leftsubnet"), val => \$normal_conn->{7}[1], type => 'entry' }, + { label => N("leftnexthop"), val => \$normal_conn->{8}[1], type => 'entry' }, + { label => N("right"), val => \$normal_conn->{9}[1], type => 'entry' }, + { label => N("rightcert"), val => \$normal_conn->{10}[1], type => 'entry' }, + { label => N("rightrsasigkey"), val => \$normal_conn->{11}[1], type => 'entry' }, + { label => N("rightsubnet"), val => \$normal_conn->{12}[1], type => 'entry' }, + { label => N("rightnexthop"), val => \$normal_conn->{13}[1], type => 'entry' }, + ] +) or goto step_configure_ipsec_conf; + + $existing_section = network::ipsec::already_existing_section_ipsec_conf($normal_conn->{1}[0] . " " . $normal_conn->{1}[1], $ipsec, $kernel_version); + + if ($existing_section eq "already existing") { +$in->ask_okcancel(N("Exists!"), +N("A section with this name already exists. +The section names have to be unique.\n +You'll have to go back and add another section +or change the name of the section.\n")); + goto step_add_normal_conn; +} + + network::ipsec::add_section_ipsec_conf($normal_conn, $ipsec); + + goto step_configure_ipsec_conf; + + } + +} else { + +#- add ---- kernel 2.6 part ------------------------------- + + my $section = { command => 'spdadd', + src_range => 'src_network_address', + dst_range => 'dest_network_address', + upperspec => 'any', + flag => '-P', + direction => 'in or out', + ipsec => 'ipsec', + protocol => 'esp', + mode => 'tunnel', + src_dest => 'source-destination', + level => 'require' }; + +step_add_section_ipsec_conf_k26: + + ask_info3('', +N("Add a Security Policy.\n +You can now add a Security Policy.\n +Choose continue when you are done to write the data.\n"), $section) or goto step_configure_ipsec_conf; + +# $existing_section = network::ipsec::already_existing_section_ipsec_conf($section->{src_dest}, $ipsec, $kernel_version); +# +# if ($existing_section eq "already existing") { +#$in->ask_okcancel(N("Exists!"), +#N("A section with this name already exists. +#The section names have to be unique.\n +#You'll have to go back and add another section +#or change the name of the section.\n")); +# goto step_add_section_ipsec_conf_k26; +#}; + + if (!$ipsec->{1}) { + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "#!/sbin/setkey -f" }); + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "flush;" }); + put_in_hash($ipsec, { max(keys %$ipsec) + 1 => "spdflush;" }); + } + + network::ipsec::add_section_ipsec_conf($section, $ipsec); + + @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version); + + goto step_configure_ipsec_conf; +} + +#- edit --------------------- + +} elsif ($d eq "Edit") { + +step_edit_ipsec_conf: +$in->ask_from(N("Edit section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to edit +and then click on next.\n", $ipsec_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) + or goto step_configure_ipsec_conf; + +my $number = network::ipsec::matched_section_key_number_ipsec_conf($choice,$ipsec,$kernel_version); + +#- edit ---- kernel 2.4 part ------------------------------- + +if ($kernel_version < 2.5) { +if ($choice =~ /^version|block|private|clear|packet/) { + +$in->ask_okcancel(N("Can not edit!"), +N("You cannot edit this section.\n +This section is mandatory for Freeswan 2.X. +One has to specify version 2.0 on the top +of the %s file, and eventually, disable or +enable the opportunistic encryption.\n",$ipsec_conf)); + goto step_edit_ipsec_conf; + +} elsif ($choice =~ /^config setup/) { + $in->ask_from('', +N("Your %s file has several sections.\n +You can now edit the config setup section entries. +Choose continue when you are done to write the data.\n", $ipsec_conf), + +[ network::ipsec::dynamic_list($number, $ipsec) ] + +) or goto step_configure_ipsec_conf; + + goto step_configure_ipsec_conf; +} elsif ($choice =~ /^conn %default/) { + $in->ask_from('', +N("Your %s file has several sections or connections.\n +You can now edit the default section entries. +Choose continue when you are done to write the data.\n", $ipsec_conf), + +[ network::ipsec::dynamic_list($number, $ipsec) ] + +) or goto step_configure_ipsec_conf; + + goto step_configure_ipsec_conf; + +} elsif ($choice =~ /^conn/) { + + $in->ask_from('', +N("Your %s file has several sections or connections.\n +You can now edit the normal section entries.\n +Choose continue when you are done to write the data.\n", $ipsec_conf), + +[ network::ipsec::dynamic_list($number, $ipsec) ] + +) or goto step_configure_ipsec_conf; + + goto step_configure_ipsec_conf; + +} else { + + goto step_configure_ipsec_conf; + +} + +#- edit ---- kernel 2.6 part ------------------------------- + +} else { + + ask_info3('', +N("Edit a Security Policy.\n +You can now edit a Security Policy.\n +Choose continue when you are done to write the data.\n"), $ipsec->{$number}) or goto step_configure_ipsec_conf; + +goto step_configure_ipsec_conf; + +} + +#- remove --------------------- + +} elsif ($d eq "Remove") { +$in->ask_from(N("Remove section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to remove +and then click on next.\n", $ipsec_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); + + network::ipsec::remove_section_ipsec_conf($choice,$ipsec,$kernel_version); + + @section_names = network::ipsec::get_section_names_ipsec_conf($ipsec,$kernel_version) if $ipsec; + + goto step_configure_ipsec_conf; + +#- continue and write --------------------- + +} elsif ($d eq "Commit") { + log::l("[drakvpn] Modify the $ipsec_conf file"); + network::ipsec::write_ipsec_conf($ipsec_conf, $ipsec,$kernel_version); + } +#------------------------------------------------------------------- +#---------------------- configure racoon_conf ----------------------- +#------------------------------------------------------------------- + +} elsif ($c eq "racoon") { + +step_configure_racoon_conf: + +@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + +my $choice = $section_names[0]; +my $d = $in->ask_from_list_(N("%s entries", $racoon_conf), +N("The racoon.conf file configuration.\n +The contents of this file is divided into sections. +You can now: + - display \t\t (display the file contents) + - add \t\t (add one section) + - edit \t\t\t (modify parameters of an existing section) + - remove \t\t (remove an existing section) + - commit \t\t (writes the changes to the real file)"), + [ N_("_:display here is a verb\nDisplay"), N_("Add"), N_("Edit"), N_("Remove"), N_("Commit") ]) or goto step_configuration; + + +#- display $racoon_conf ------------------------- + +step_display_racoon_conf: + +if ($d eq "_:display here is a verb\nDisplay") { + + my $racoon_exists = 0; + foreach my $key (keys %$racoon) { + $racoon_exists = 1 if $racoon->{$key}; + } + + if ($racoon_exists) { + $in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), + network::ipsec::display_racoon_conf($racoon)); + goto step_configure_racoon_conf; + } else { +$in->ask_okcancel(N("_:display here is a verb\nDisplay configuration"), +N("The %s file does not exist\n +This must be a new configuration.\n +You'll have to go back and choose configure.\n", $racoon_conf)); + goto step_configure_racoon_conf; + } + +#- add $racoon_conf ------------------------------ + +} elsif ($d eq "Add") { + +step_add_section_racoon: + +#my $existing_section = ""; + +my $e = $in->ask_from_list_(N("racoonf.conf entries"), +N("The 'add' sections step.\n +Here below is the racoon.conf file skeleton: +\t'path' +\t'remote' +\t'sainfo' \n +Choose the section you would like to add.\n"), + [ N_("path"), N_("remote"), N_("sainfo"), N_("dismiss") ]) or goto step_configure_racoon_conf; +if ($e eq "path") { + + my $path_section = { + 1 => [ 'path', 'path_type', '"/etc/racoon/certs"' ], + }; + + $in->ask_from('', +N("The 'add path' section step.\n +The path sections have to be on top of your racoon.conf file.\n +Put your mouse over the certificate entry to obtain online help."), + [ { label => N("path type"), + val => \$path_section->{1}[1], + list => [ 'certificate', 'pre_shared_key', 'include' ], + help => +N("path include path: specifies a path to include +a file. See File Inclusion. + Example: path include '/etc/racoon' + +path pre_shared_key file: specifies a file containing +pre-shared key(s) for various ID(s). See Pre-shared key File. + Example: path pre_shared_key '/etc/racoon/psk.txt' ; + +path certificate path: racoon(8) will search this directory +if a certificate or certificate request is received. + Example: path certificate '/etc/cert' ; + +File Inclusion: include file +other configuration files can be included. + Example: include \"remote.conf\" ; + +Pre-shared key File: Pre-shared key file defines a pair +of the identifier and the shared secret key which are used at +Pre-shared key authentication method in phase 1."), +}, + { label => N("real file"), val => \$path_section->{1}[2], type => 'entry' }, + ] +) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($path_section, $racoon); +} elsif ($e eq "remote") { + my $main_remote_section = { 1 => [ 'remote', 'address' ], + 2 => [ 'exchange_mode', 'aggressive,main' ], + 3 => [ 'generate_policy', 'on' ], + 4 => [ 'passive', 'on' ], + 5 => [ 'certificate_type', 'x509', '"my_certificate.pem"', '"my_private_key.pem"' ], + 6 => [ 'peers_certfile', '"remote.public"' ], + 7 => [ 'verify_cert', 'on' ], + 8 => [ 'my_identifier', 'asn1dn' ], + 9 => [ 'peers_identifier', 'asn1dn' ] + }; + my $proposal_remote_section = { 1 => [ 'proposal' ], + 2 => [ 'encryption_algorithm', '3des' ], + 3 => [ 'hash_algorithm', 'md5' ], + 4 => [ 'authentication_method', 'rsasig' ], + 5 => [ 'dh_group', 'modp1024' ] + }; + ask_info2('', +N("Make sure you already have the path sections +on the top of your racoon.conf file. + +You can now choose the remote settings. +Choose continue or previous when you are done.\n"), $main_remote_section, $proposal_remote_section) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($main_remote_section, $racoon); +network::ipsec::add_section_racoon_conf($proposal_remote_section, $racoon); +} elsif ($e eq "sainfo") { + my $sainfo_section = { 1 => [ 'sainfo', 'address', '192.168.100.2', 'any', 'address', '10.0.0.2', 'any' ], + 2 => [ 'pfs_group', '1' ], + 3 => [ 'lifetime', 'time', '30', 'sec' ], + 4 => [ 'encryption_algorithm', '3des' ], + 5 => [ 'authentication_algorithm', 'hmac_sha1' ], + 6 => [ 'compression_algorithm', 'deflate' ], + }; + ask_info('', +N("Make sure you already have the path sections +on the top of your %s file. + +You can now choose the sainfo settings. +Choose continue or previous when you are done.\n", $racoon_conf), $sainfo_section) or goto step_configure_racoon_conf; + +network::ipsec::add_section_racoon_conf($sainfo_section, $racoon); +} + +@section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + +goto step_configure_racoon_conf; + +#- edit $racoon_conf ----------------------------- + +} elsif ($d eq "Edit") { +$in->ask_from(N("Edit section"), +N("Your %s file has several sections or connections. + +You can choose here in the list below the one you want +to edit and then click on next.\n", $racoon_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]) + or goto step_configure_racoon_conf; + +my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); + +if ($choice =~ /^remote/) { + ask_info2('', +N("Your %s file has several sections.\n + +You can now edit the remote section entries. + +Choose continue when you are done to write the data.\n", $racoon_conf), $racoon->{$number}, $racoon->{$number+2}) + or goto step_configure_racoon_conf; + +} elsif ($choice =~ /^sainfo/) { + ask_info('', +N("Your %s file has several sections. + +You can now edit the sainfo section entries. + +Choose continue when you are done to write the data.", $racoon_conf), $racoon->{$number}) or goto step_configure_racoon_conf; + +} elsif ($choice =~ /^path/) { + $in->ask_from('', +N("This section has to be on top of your +%s file.\n +Make sure all other sections follow these path +sections.\n +You can now edit the path entries. + +Choose continue or previous when you are done.\n", $racoon_conf), + [ { label => N("path_type"), val => \$racoon->{$number}{1}[1], list => [ 'certificate', 'pre_shared_key', 'include' ] }, + { label => N("real file"), val => \$racoon->{$number}{1}[2], type => 'entry' }, + ] +) or goto step_configure_racoon_conf; +} + +goto step_configure_racoon_conf; + +#- remove $racoon_conf --------------------------- + +} elsif ($d eq "Remove") { +$in->ask_from(N("Remove section"), +N("Your %s file has several sections or connections.\n +You can choose here below the one you want to remove +and then click on next.\n", $racoon_conf), + [ { val => \$choice, list => \@section_names, label => N("Section names"), sort => 0, not_edit => 0 } ]); + +my $number = network::ipsec::matched_section_key_number_racoon_conf($choice,$racoon); +network::ipsec::remove_section_racoon_conf($choice,$racoon,$number); + @section_names = network::ipsec::get_section_names_racoon_conf($racoon) if $racoon; + + goto step_configure_racoon_conf; + +#- write $racoon_conf and continue --------------- +} elsif ($d eq "Commit") { + log::l("[drakvpn] Modify the $racoon_conf file"); + network::ipsec::write_racoon_conf($racoon_conf, $racoon); +} +} + +#- start the daemons +network::ipsec::start_daemons(); + +#- bye-bye message + +undef $wait_configuring; + +$::Wizard_no_previous = 1; +$::Wizard_finished = 1; + +$in->ask_okcancel(N("Congratulations!"), +N("Everything has been configured.\n +You may now share resources through the Internet, +in a secure way, using a VPN connection. + +You should make sure that that the tunnels shorewall +section is configured.")); + +log::l("[drakvpn] Installation complete, exiting"); +quit_global($in, 0); + +sub quit_global { + my ($in, $exitcode) = @_; + $in->exit($exitcode); + goto begin; +} + + +sub ask_info { + my ($title, $text, $data) = @_; + $in->ask_from($title, $text, + [ { label => N("Sainfo source address"), val => \$data->{1}[2], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + 203.178.141.209 is the source address + +sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any + 172.16.1.0/24 is the source address") }, + { label => N("Sainfo source protocol"), val => \$data->{1}[3], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + the first 'any' allows any protocol for the source") }, + { label => N("Sainfo destination address"), val => \$data->{1}[5], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + 203.178.141.218 is the destination address + +sainfo address 172.16.1.0/24 any address 172.16.2.0/24 any + 172.16.2.0/24 is the destination address") }, + { label => N("Sainfo destination protocol"), val => \$data->{1}[6], type => 'entry', + help => N("sainfo (source_id destination_id | anonymous) { statements } +defines the parameters of the IKE phase 2 +(IPsec-SA establishment). + +source_id and destination_id are constructed like: + + address address [/ prefix] [[port]] ul_proto + +Examples: \n +sainfo anonymous (accepts connections from anywhere) + leave blank this entry if you want anonymous + +sainfo address 203.178.141.209 any address 203.178.141.218 any + the last 'any' allows any protocol for the destination") }, + { label => N("PFS group"), val => \$data->{2}[1], + list => [ qw(modp768 modp1024 modp1536 1 2 5) ], + help => N("define the group of Diffie-Hellman exponentiations. +If you do not require PFS then you can omit this directive. +Any proposal will be accepted if you do not specify one. +group is one of the following: modp768, modp1024, modp1536. +Or you can define 1, 2, or 5 as the DH group number.") }, + { label => N("Lifetime number"), val => \$data->{3}[2], type => 'entry', + help => N("define a lifetime of a certain time which will be pro- +posed in the phase 1 negotiations. Any proposal will be +accepted, and the attribute(s) will not be proposed to +the peer if you do not specify it(them). They can be +individually specified in each proposal. + +Examples: \n + lifetime time 1 min; # sec,min,hour + lifetime time 1 min; # sec,min,hour + lifetime time 30 sec; + lifetime time 30 sec; + lifetime time 60 sec; + lifetime time 12 hour; + +So, here, the lifetime numbers are 1, 1, 30, 30, 60 and 12. +") }, + { label => N("Lifetime unit"), val => \$data->{3}[3], + list => [ qw(sec min hour) ], + help => N("define a lifetime of a certain time which will be pro- +posed in the phase 1 negotiations. Any proposal will be +accepted, and the attribute(s) will not be proposed to +the peer if you do not specify it(them). They can be +individually specified in each proposal. + +Examples: \n + lifetime time 1 min; # sec,min,hour + lifetime time 1 min; # sec,min,hour + lifetime time 30 sec; + lifetime time 30 sec; + lifetime time 60 sec; + lifetime time 12 hour; + +So, here, the lifetime units are 'min', 'min', 'sec', 'sec', 'sec' and 'hour'. +") }, + { label => N("Encryption algorithm"), val => \$data->{4}[1], + list => [ qw(des 3des des_iv64 des_iv32 rc5 rc4 idea 3idea cast128 blowfish null_enc twofish rijndae) ] }, + { label => N("Authentication algorithm"), val => \$data->{5}[1], + list => [ qw(des 3des des_iv64 des_iv32 hmac_md5 hmac_sha1 non_auth) ] }, + { label => N("Compression algorithm"), val => \$data->{6}[1], + list => [ N_("deflate") ], format => \&translate, allow_empty_list => 1 } + +]) } + +sub ask_info2 { + my ($title, $text, $main_remote_section, $proposal_remote_section) = @_; + $in->ask_from($title, $text,, + [ { label => N("Remote"), val => \$main_remote_section->{1}[1], type => 'entry', + help => N("remote (address | anonymous) [[port]] { statements } +specifies the parameters for IKE phase 1 for each remote node. +The default port is 500. If anonymous is specified, the state- +ments apply to all peers which do not match any other remote +directive.\n +Examples: \n +remote anonymous +remote ::1 [8000]") }, + { label => N("Exchange mode"), val => \$main_remote_section->{2}[1], + list => [ qw(main,agressive agressive,main) ], + help => N("defines the exchange mode for phase 1 when racoon is the +initiator. Also it means the acceptable exchange mode +when racoon is responder. More than one mode can be +specified by separating them with a comma. All of the +modes are acceptable. The first exchange mode is what +racoon uses when it is the initiator.\n") }, + { label => N("Generate policy"), val => \$main_remote_section->{3}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("This directive is for the responder. Therefore you +should set passive on in order that racoon(8) only +becomes a responder. If the responder does not have any +policy in SPD during phase 2 negotiation, and the direc- +tive is set on, then racoon(8) will choice the first pro- +posal in the SA payload from the initiator, and generate +policy entries from the proposal. It is useful to nego- +tiate with the client which is allocated IP address +dynamically. Note that inappropriate policy might be +installed into the responder's SPD by the initiator. So +that other communication might fail if such policies +installed due to some policy mismatches between the ini- +tiator and the responder. This directive is ignored in +the initiator case. The default value is off.") }, + { label => N("Passive"), val => \$main_remote_section->{4}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("If you do not want to initiate the negotiation, set this +to on. The default value is off. It is useful for a +server.") }, + { label => N("Certificate type"), val => \$main_remote_section->{5}[1], + list => [ 'x509' ], allow_empty_list => 1 }, + { label => N("My certfile"), val => \$main_remote_section->{5}[2], type => 'entry', + help => N("Name of the certificate") }, + { label => N("My private key"), val => \$main_remote_section->{5}[3], type => 'entry', + help => N("Name of the private key") }, + { label => N("Peers certfile"), val => \$main_remote_section->{6}[1], type => 'entry', + help => N("Name of the peers certificate") }, + { label => N("Verify cert"), val => \$main_remote_section->{7}[1], + list => [ N_("off"), N_("on") ], format => \&translate, + help => N("If you do not want to verify the peer's certificate for +some reason, set this to off. The default is on.") }, + { label => N("My identifier"), val => \$main_remote_section->{8}[1], type => 'entry', + help => N("specifies the identifier sent to the remote host and the +type to use in the phase 1 negotiation. address, FQDN, +user_fqdn, keyid and asn1dn can be used as an idtype. +they are used like: + my_identifier address [address]; + the type is the IP address. This is the default + type if you do not specify an identifier to use. + my_identifier user_fqdn string; + the type is a USER_FQDN (user fully-qualified + domain name). + my_identifier FQDN string; + the type is a FQDN (fully-qualified domain name). + my_identifier keyid file; + the type is a KEY_ID. + my_identifier asn1dn [string]; + the type is an ASN.1 distinguished name. If + string is omitted, racoon(8) will get DN from + Subject field in the certificate.\n +Examples: \n +my_identifier user_fqdn \"myemail\@mydomain.com\"") }, + { label => N("Peers identifier"), val => \$main_remote_section->{9}[1], type => 'entry' }, + { label => N("Proposal"), val => \$proposal_remote_section->{1}[0], list => [ 'proposal' ], allow_empty_list => 1 }, + { label => N("Encryption algorithm"), val => \$proposal_remote_section->{2}[1], list => [ qw(des 3des blowfish cast128) ], + help => N("specify the encryption algorithm used for the +phase 1 negotiation. This directive must be defined. +algorithm is one of the following: + +DES, 3DES, blowfish, cast128 for oakley. + +For other transforms, this statement should not be used.") }, + { label => N("Hash algorithm"), val => \$proposal_remote_section->{3}[1], type => 'entry' }, + { label => N("Authentication method"), val => \$proposal_remote_section->{4}[1], type => 'entry' }, + { label => N("DH group"), val => \$proposal_remote_section->{5}[1], list => [ qw(modp768 modp1024 modp1536 1 2 5) ], }, + ]); +} + +sub ask_info3 { + my ($title, $text, $section) = @_; + $in->ask_from($title, $text,, + [ { label => N("Command"), val => \$section->{command}, list => [ 'spdadd' ], allow_empty_list => 1 }, + { label => N("Source IP range"), val => \$section->{src_range}, type => 'entry' }, + { label => N("Destination IP range"), val => \$section->{dst_range}, type => 'entry' }, + { label => N("Upper-layer protocol"), val => \$section->{upperspec}, list => [ N_("any") ], + format => \&translate, allow_empty_list => 1 }, + { label => N("Flag"), val => \$section->{flag}, list => [ '-P' ], allow_empty_list => 1 }, + { label => N("Direction"), val => \$section->{direction}, list => [ 'in', 'out' ] }, + { label => N("IPsec policy"), val => \$section->{ipsec}, list => [ N_("ipsec"), N_("discard"), N_("none") ], + format => \&translate }, + { label => N("Protocol"), val => \$section->{protocol}, list => [ 'esp', 'ah', 'ipcomp' ] }, + { label => N("Mode"), val => \$section->{mode}, list => [ N_("tunnel"), N_("transport"), N_("any") ], + format => \&translate }, + { label => N("Source/destination"), val => \$section->{src_dest}, type => 'entry' }, + { label => N("Level"), val => \$section->{level}, list => [ N_("require"), N_("default"), N_("use"), N_("unique") ], + format => \&translate }, + ]); +} + |