summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Leung <jleung@v10networks.ca>2015-06-09 00:25:03 -0700
committerJeff Leung <jleung@v10networks.ca>2015-06-09 00:25:03 -0700
commit070c754a733258a4b6900b01dd3ec141debcc9a8 (patch)
tree69046326702eab79a4cea9b8d36b2248cbc188cb
parent7d94dd6e4d32eef9cea4a4f7270b0ea0d895dd12 (diff)
parent6656e3ae1a2e9a1b4bb7d8eecf320f840b6837c2 (diff)
downloadvyatta-cfg-vpn-070c754a733258a4b6900b01dd3ec141debcc9a8.tar.gz
vyatta-cfg-vpn-070c754a733258a4b6900b01dd3ec141debcc9a8.zip
Merge pull request #1 from ryanriske/lithium-strongswan5-rsa
Update support for RSA keys with strongSwan 5.2.x
-rwxr-xr-xlib/Vyatta/VPN/Util.pm48
-rwxr-xr-xscripts/vpn-config.pl27
2 files changed, 68 insertions, 7 deletions
diff --git a/lib/Vyatta/VPN/Util.pm b/lib/Vyatta/VPN/Util.pm
index a40cc90..606178a 100755
--- a/lib/Vyatta/VPN/Util.pm
+++ b/lib/Vyatta/VPN/Util.pm
@@ -27,10 +27,14 @@ use strict;
use warnings;
our @EXPORT = qw(rsa_get_local_key_file LOCAL_KEY_FILE_DEFAULT rsa_get_local_pubkey
- is_vpn_running vpn_debug enableICMP is_tcp_udp get_protocols conv_protocol);
+ rsa_convert_pubkey_pem is_vpn_running vpn_debug enableICMP is_tcp_udp
+ get_protocols conv_protocol);
use base qw(Exporter);
use Vyatta::Config;
+use Crypt::OpenSSL::RSA;
+use MIME::Base64;
+use File::Copy;
use POSIX qw(strftime);
use constant LOCAL_KEY_FILE_DEFAULT
@@ -110,15 +114,57 @@ sub rsa_get_local_pubkey {
my @raw_data=<$dat>;
close($dat);
+ # PEM encoded private key
+ my $rsa = Crypt::OpenSSL::RSA->new_private_key(join("", @raw_data));
+ if (defined $rsa) {
+ my ($n, $e) = $rsa->get_key_parameters();
+ my $eb = $e->to_bin();
+ return "0s" . encode_base64(pack("C", length($eb)) . $eb . $n->to_bin(), '');
+ }
+
+ # legacy private key format
foreach my $line (@raw_data) {
my $file_pubkey;
if (($file_pubkey) = ($line =~ m/\s+\#pubkey=(\S+)/)) {
+ # Found a legacy private key; convert to PEM for strongSwan 5.2.x
+ my $key = join("", @raw_data);
+ $key =~ /^\s+Modulus:\s+0x([0-9a-fA-F]+)$/m;
+ my $n = Crypt::OpenSSL::Bignum->new_from_hex($1);
+ $key =~ /^\s+PublicExponent:\s+0x([0-9a-fA-F]+)$/m;
+ my $e = Crypt::OpenSSL::Bignum->new_from_hex($1);
+ $key =~ /^\s+PrivateExponent:\s+0x([0-9a-fA-F]+)$/m;
+ my $d = Crypt::OpenSSL::Bignum->new_from_hex($1);
+ $key =~ /^\s+Prime1:\s+0x([0-9a-fA-F]+)$/m;
+ my $p = Crypt::OpenSSL::Bignum->new_from_hex($1);
+ $key =~ /^\s+Prime2:\s+0x([0-9a-fA-F]+)$/m;
+ my $q = Crypt::OpenSSL::Bignum->new_from_hex($1);
+
+ my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d, $p, $q);
+ if (defined $rsa) {
+ # write out PEM formatted key
+ move("$file", "$file.bak");
+ open(my $priv, '>', "$file")
+ or return 0;
+ chmod 0600, $file;
+ print {$priv} $rsa->get_private_key_string();
+ close($priv);
+ }
return $file_pubkey;
}
}
return 0;
}
+sub rsa_convert_pubkey_pem {
+ my $key = shift;
+ my $decoded = decode_base64(substr($key, 2));
+ my $len = unpack("C", substr($decoded, 0, 1));
+ my $e = Crypt::OpenSSL::Bignum->new_from_bin(substr($decoded, 1, $len));
+ my $n = Crypt::OpenSSL::Bignum->new_from_bin(substr($decoded, 1 + $len));
+ my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e);
+ return $rsa->get_public_key_x509_string();
+}
+
sub vpn_debug {
my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime);
diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl
index dd5da34..23d97d7 100755
--- a/scripts/vpn-config.pl
+++ b/scripts/vpn-config.pl
@@ -59,6 +59,7 @@ my $dhcp_if = 0;
my $genout;
my $genout_secrets;
my %key_file_list;
+my %public_keys;
# Set $using_klips to 1 if kernel IPsec support is provided by KLIPS.
# Set it to 0 us using NETKEY.
@@ -1010,7 +1011,10 @@ if ($vcVPN->exists('ipsec')) {
vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"authentication"],"$vpn_cfg_err Unable to determine local public key from local key".
" file \"$local_key_file\" for peer \"$peer\".\n");
} else {
- $genout .= "\tleftrsasigkey=\"$local_key\"\n";
+ if (!defined($public_keys{localhost})) {
+ $public_keys{localhost} = $local_key;
+ $genout .= "\tleftsigkey=localhost.pub\n";
+ }
}
my $rsa_key_name = $vcVPN->returnValue("ipsec site-to-site peer $peer authentication rsa-key-name");
@@ -1023,13 +1027,16 @@ if ($vcVPN->exists('ipsec')) {
vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"authentication"],"$vpn_cfg_err No remote key configured for rsa key name ".
"\"$rsa_key_name\" that is specified for peer \"$peer\".\n");
} else {
- $genout .= "\trightrsasigkey=\"$remote_key\"\n";
+ if (!defined($public_keys{$rsa_key_name})) {
+ $public_keys{$rsa_key_name} = $remote_key;
+ $genout .= "\trightsigkey=$rsa_key_name.pub\n";
+ }
}
}
# Prevent duplicate includes for rsa keys.
if (!defined($key_file_list{$local_key_file})) {
$key_file_list{$local_key_file} = 1;
- $genout_secrets .= "include $local_key_file\n";
+ $genout_secrets .= ": RSA $local_key_file\n";
}
} else {
vpn_die(["vpn","ipsec","site-to-site","peer",$peer,"authentication"],"$vpn_cfg_err Unknown authentication mode \"$auth_mode\" for peer ".
@@ -1156,13 +1163,13 @@ if ( $vcVPN->isDeleted('.')
if (!enableICMP('1')) {
vpn_die(["vpn","ipsec"],"VPN commit error. Unable to re-enable ICMP redirects.\n");
}
- write_config($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if);
+ write_config($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if, %public_keys);
} else {
if (!enableICMP('0')) {
vpn_die(["vpn","ipsec"],"VPN commit error. Unable to disable ICMP redirects.\n");
}
- write_config($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if);
+ write_config($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if, %public_keys);
# Assumming that if there was a local IP missmatch and clustering is enabled,
# then the clustering scripts will take care of starting the VPN daemon.
@@ -1251,7 +1258,7 @@ sub vpn_die {
}
sub write_config {
- my ($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if) = @_;
+ my ($genout, $config_file, $genout_secrets, $secrets_file, $dhcp_if, %public_keys) = @_;
open my $output_config, '>', $config_file
or die "Can't open $config_file: $!";
@@ -1272,6 +1279,14 @@ sub write_config {
print ${output_secrets} $genout_secrets;
close $output_secrets;
dhcp_hook($dhcp_if);
+
+ for my $name (keys %public_keys) {
+ my $output_path = "/etc/ipsec.d/certs/$name.pub";
+ open my $output_file, '>', $output_path
+ or die "Can't open $output_path: $!";
+ print ${output_file} rsa_convert_pubkey_pem($public_keys{$name});
+ close $output_file;
+ }
}
sub vpn_exec {