use File::Temp qw/ tempfile tempdir /;
use strict;
use Sort::Naturally;
+use Sys::Hostname;
# enable only the following on debugging purpose
#use warnings;
#use CGI::Carp 'fatalsToBrowser';
$cgiparams{'ROOTCERT_OU'} = '';
$cgiparams{'ROOTCERT_CITY'} = '';
$cgiparams{'ROOTCERT_STATE'} = '';
+$cgiparams{'RW_ENDPOINT'} = '';
$cgiparams{'RW_NET'} = '';
$cgiparams{'DPD_DELAY'} = '30';
$cgiparams{'DPD_TIMEOUT'} = '120';
$cgiparams{'INTERFACE_MODE'} = "";
$cgiparams{'INTERFACE_ADDRESS'} = "";
$cgiparams{'INTERFACE_MTU'} = 1500;
+$cgiparams{'DNS_SERVERS'} = "";
&Header::getcgihash(\%cgiparams, {'wantfile' => 1, 'filevar' => 'FH'});
+my %APPLE_CIPHERS = (
+ "aes256gcm128" => "AES-256-GCM",
+ "aes128gcm128" => "AES-128-GCM",
+ "aes256" => "AES-256",
+ "aes128" => "AES-128",
+ "3des" => "3DES",
+);
+
+my %APPLE_INTEGRITIES = (
+ "sha2_512" => "SHA2-512",
+ "sha2_384" => "SHA2-384",
+ "sha2_256" => "SHA2-256",
+ "sha1" => "SHA1-160",
+);
+
+my %APPLE_DH_GROUPS = (
+ "768" => 1,
+ "1024" => 2,
+ "1536" => 5,
+ "2048" => 14,
+ "3072" => 15,
+ "4096" => 16,
+ "6144" => 17,
+ "8192" => 18,
+ "e256" => 19,
+ "e384" => 20,
+ "e521" => 21,
+);
+
###
### Useful functions
###
close FILE;
}
if (! -s ">${General::swroot}/certs/index.txt") {
- system ("touch ${General::swroot}/certs/index.txt");
+ open(FILE, ">${General::swroot}/certs/index.txt");
+ close(FILE);
}
if (! -s ">${General::swroot}/certs/index.txt.attr") {
- system ("touch ${General::swroot}/certs/index.txt.attr");
+ open(FILE, ">${General::swroot}/certs/index.txt.attr");
+ close(FILE);
}
unlink ("${General::swroot}/certs/index.txt.old");
unlink ("${General::swroot}/certs/index.txt.attr.old");
###
sub callssl ($) {
my $opt = shift;
- my $retssl = `/usr/bin/openssl $opt 2>&1`; #redirect stderr
+
+ # Split the given argument string into single pieces and assign them to an array.
+ my @opts = split(/ /, $opt);
+
+ my @retssl = &General::system_output("/usr/bin/openssl", @opts); #redirect stderr
my $ret = '';
- foreach my $line (split (/\n/, $retssl)) {
+ foreach my $line (split (/\n/, @retssl)) {
&General::log("ipsec", "$line") if (0); # 1 for verbose logging
$ret .= '<br>'.$line if ( $line =~ /error|unknown/ );
}
###
sub getCNfromcert ($) {
#&General::log("ipsec", "Extracting name from $_[0]...");
- my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
- $temp =~ /Subject:.*CN = (.*)[\n]/;
- $temp = $1;
- $temp =~ s+/Email+, E+;
- $temp =~ s/ ST = / S = /;
- $temp =~ s/,//g;
- $temp =~ s/\'//g;
+ my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "$_[0]");
+ my $temp;
+
+ foreach my $line (@temp) {
+ if ($line =~ /Subject:.*CN = (.*)[\n]/) {
+ $temp = $1;
+ $temp =~ s+/Email+, E+;
+ $temp =~ s/ ST = / S = /;
+ $temp =~ s/,//g;
+ $temp =~ s/\'//g;
+
+ last;
+ }
+ }
+
return $temp;
}
###
###
sub getsubjectfromcert ($) {
#&General::log("ipsec", "Extracting subject from $_[0]...");
- my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
- $temp =~ /Subject: (.*)[\n]/;
- $temp = $1;
- $temp =~ s+/Email+, E+;
- $temp =~ s/ ST = / S = /;
+ my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "$_[0]");
+ my $temp;
+
+ foreach my $line (@temp) {
+ if($line =~ /Subject: (.*)[\n]/) {
+ $temp = $1;
+ $temp =~ s+/Email+, E+;
+ $temp =~ s/ ST = / S = /;
+
+ last;
+ }
+ }
+
return $temp;
}
###
print CONF "\tleftfirewall=yes\n";
print CONF "\tlefthostaccess=yes\n";
+
+ # Always send the host certificate
+ if ($lconfighash{$key}[3] eq 'host') {
+ print CONF "\tleftsendcert=always\n";
+ }
+
print CONF "\tright=$lconfighash{$key}[10]\n";
if ($lconfighash{$key}[3] eq 'net') {
# Fragmentation
print CONF "\tfragmentation=yes\n";
+ # DNS Servers for RW
+ if ($lconfighash{$key}[3] eq 'host') {
+ my @servers = split(/\|/, $lconfighash{$key}[39]);
+
+ print CONF "\trightdns=" . join(",", @servers) . "\n";
+ }
+
print CONF "\n";
} #foreach key
if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq '' && $cgiparams{'KEY'} eq '') {
&General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
+ if ($cgiparams{'RW_ENDPOINT'} ne '' && !&General::validip($cgiparams{'RW_ENDPOINT'}) && !&General::validfqdn($cgiparams{'RW_ENDPOINT'})) {
+ $errormessage = $Lang::tr{'ipsec invalid ip address or fqdn for rw endpoint'};
+ goto SAVE_ERROR;
+ }
+
if ( $cgiparams{'RW_NET'} ne '' and !&General::validipandmask($cgiparams{'RW_NET'}) ) {
$errormessage = $Lang::tr{'urlfilter invalid ip or mask error'};
goto SAVE_ERROR;
}
$vpnsettings{'ENABLED'} = $cgiparams{'ENABLED'};
+ $vpnsettings{'RW_ENDPOINT'} = $cgiparams{'RW_ENDPOINT'};
$vpnsettings{'RW_NET'} = $cgiparams{'RW_NET'};
&General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
&writeipsecfiles();
if (&vpnenabled) {
- system('/usr/local/bin/ipsecctrl', 'S');
+ &General::system('/usr/local/bin/ipsecctrl', 'S');
} else {
- system('/usr/local/bin/ipsecctrl', 'D');
+ &General::system('/usr/local/bin/ipsecctrl', 'D');
}
sleep $sleepDelay;
SAVE_ERROR:
}
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
- system('/usr/local/bin/ipsecctrl', 'R');
+ &General::system('/usr/local/bin/ipsecctrl', 'R');
sleep $sleepDelay;
###
$errormessage = $!;
goto UPLOADCA_ERROR;
}
- my $temp = `/usr/bin/openssl x509 -text -in $filename`;
- if ($temp !~ /CA:TRUE/i) {
+ my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "$filename");
+ if (! grep(/CA:TRUE/, @temp)) {
$errormessage = $Lang::tr{'not a valid ca certificate'};
unlink ($filename);
goto UPLOADCA_ERROR;
$cahash{$key}[1] = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem"));
&General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
- system('/usr/local/bin/ipsecctrl', 'R');
+ &General::system('/usr/local/bin/ipsecctrl', 'R');
sleep $sleepDelay;
UPLOADCA_ERROR:
&Header::openpage($Lang::tr{'ipsec'}, 1, '');
&Header::openbigbox('100%', 'left', '', '');
&Header::openbox('100%', 'left', "$Lang::tr{'ca certificate'}:");
- my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem`;
- $output = &Header::cleanhtml($output,"y");
- print "<pre>$output</pre>\n";
+ my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
+ @output = &Header::cleanhtml(@output,"y");
+ print "<pre>@output</pre>\n";
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
print "Content-Type: application/force-download\n";
print "Content-Type: application/octet-stream\r\n";
print "Content-Disposition: attachment; filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
- print `/usr/bin/openssl x509 -in ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem`;
+
+ my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
+ print "@cert";
exit(0);
} else {
$errormessage = $Lang::tr{'invalid key'};
if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
foreach my $key (keys %confighash) {
- my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/certs/$confighash{$key}[1]cert.pem`;
- if ($test =~ /: OK/) {
+ my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/certs/$confighash{$key}[1]cert.pem");
+ if (grep(/: OK/, @test)) {
# Delete connection
unlink ("${General::swroot}/certs/$confighash{$key}[1]cert.pem");
unlink ("${General::swroot}/certs/$confighash{$key}[1].p12");
delete $confighash{$key};
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
- system('/usr/local/bin/ipsecctrl', 'D', $key) if (&vpnenabled);
+ &General::system('/usr/local/bin/ipsecctrl', 'D', $key) if (&vpnenabled);
}
}
unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
delete $cahash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
- system('/usr/local/bin/ipsecctrl', 'R');
+ &General::system('/usr/local/bin/ipsecctrl', 'R');
sleep $sleepDelay;
} else {
$errormessage = $Lang::tr{'invalid key'};
my $assignedcerts = 0;
if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
foreach my $key (keys %confighash) {
- my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/certs/$confighash{$key}[1]cert.pem`;
- if ($test =~ /: OK/) {
+ my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/certs/$confighash{$key}[1]cert.pem");
+ if (grep(/: OK/, @test)) {
$assignedcerts++;
}
}
unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
delete $cahash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
- system('/usr/local/bin/ipsecctrl', 'R');
+ &General::system('/usr/local/bin/ipsecctrl', 'R');
sleep $sleepDelay;
}
} else {
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'} ||
$cgiparams{'ACTION'} eq $Lang::tr{'show host certificate'}) {
- my $output;
+ my @output;
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'ipsec'}, 1, '');
&Header::openbigbox('100%', 'left', '', '');
if ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'}) {
&Header::openbox('100%', 'left', "$Lang::tr{'root certificate'}:");
- $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/cacert.pem`;
+ @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ca/cacert.pem");
} else {
&Header::openbox('100%', 'left', "$Lang::tr{'host certificate'}:");
- $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/hostcert.pem`;
+ @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/certs/hostcert.pem");
}
- $output = &Header::cleanhtml($output,"y");
- print "<pre>$output</pre>\n";
+ @output = &Header::cleanhtml(@output,"y");
+ print "<pre>@output</pre>\n";
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
if ( -f "${General::swroot}/ca/cacert.pem" ) {
print "Content-Type: application/force-download\n";
print "Content-Disposition: attachment; filename=cacert.pem\r\n\r\n";
- print `/usr/bin/openssl x509 -in ${General::swroot}/ca/cacert.pem`;
+
+ my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ca/cacert.pem");
+ print "@cert";
exit(0);
}
###
if ( -f "${General::swroot}/certs/hostcert.pem" ) {
print "Content-Type: application/force-download\n";
print "Content-Disposition: attachment; filename=hostcert.pem\r\n\r\n";
- print `/usr/bin/openssl x509 -in ${General::swroot}/certs/hostcert.pem`;
+
+ my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/certs/hostcert.pem");
+ print "@cert";
exit(0);
}
###
ROOTCERT_SUCCESS:
if (&vpnenabled) {
- system('/usr/local/bin/ipsecctrl', 'S');
+ &General::system('/usr/local/bin/ipsecctrl', 'S');
sleep $sleepDelay;
}
ROOTCERT_SKIP:
print "Content-Type: application/force-download\n";
print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . ".p12\r\n";
print "Content-Type: application/octet-stream\r\n\r\n";
- print `/bin/cat ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12`;
+
+ open(FILE, "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
+ my @p12 = <FILE>;
+ close(FILE);
+ print "@p12";
+
exit (0);
# Export Apple profile to browser
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download apple profile'}) {
+ # Read global configuration
+ &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
+
+ # Read connections
&General::readhasharray("${General::swroot}/vpn/config", \%confighash);
my $key = $cgiparams{'KEY'};
my $uuid1 = $uuid->create_str();
my $uuid2 = $uuid->create_str();
+ my $ca = "";
+ my $ca_uuid = $uuid->create_str();
+
my $cert = "";
my $cert_uuid = $uuid->create_str();
- # Read and encode certificate
+ # Read and encode the CA & certificate
if ($confighash{$key}[4] eq "cert") {
+ my $ca_path = "${General::swroot}/ca/cacert.pem";
my $cert_path = "${General::swroot}/certs/$confighash{$key}[1].p12";
+ # Read the CA and encode it into Base64
+ open(CA, "<${ca_path}");
+ local($/) = undef; # slurp
+ $ca = MIME::Base64::encode_base64(<CA>);
+ close(CA);
+
# Read certificate and encode it into Base64
open(CERT, "<${cert_path}");
local($/) = undef; # slurp
print "Content-Disposition: attachment; filename=" . $confighash{$key}[1] . ".mobileconfig\n";
print "\n"; # end headers
+ # Use our own FQDN if nothing else is configured
+ my $endpoint = ($vpnsettings{'RW_ENDPOINT'} ne "") ? $vpnsettings{'RW_ENDPOINT'} : &hostname();
+
print "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n";
print "<plist version=\"1.0\">\n";
print " <dict>\n";
print " <key>IKEv2</key>\n";
print " <dict>\n";
print " <key>RemoteAddress</key>\n";
- print " <string>18.206.152.26</string>\n";
+ print " <string>$endpoint</string>\n";
+
+ # PFS
+ my $pfs = $confighash{$key}[28];
+ if ($pfs eq "on") {
+ print " <key>EnablePFS</key>\n";
+ print " <true/>\n";
+ }
+
+ # IKE Cipher Suite
+ print " <key>IKESecurityAssociationParameters</key>\n";
+ print " <dict>\n";
+
+ # Encryption
+ foreach my $cipher (split(/\|/,$confighash{$key}[18])) {
+ # Skip all unsupported ciphers
+ next unless (exists $APPLE_CIPHERS{$cipher});
+
+ print " <key>EncryptionAlgorithm</key>\n";
+ print " <string>$APPLE_CIPHERS{$cipher}</string>\n";
+ last;
+ }
+
+ # Integrity
+ foreach my $integrity (split(/\|/,$confighash{$key}[19])) {
+ # Skip all unsupported algorithms
+ next unless (exists $APPLE_INTEGRITIES{$integrity});
+
+ print " <key>IntegrityAlgorithm</key>\n";
+ print " <string>$APPLE_INTEGRITIES{$integrity}</string>\n";
+ last;
+ }
+
+ # Diffie Hellman Groups
+ foreach my $group (split(/\|/,$confighash{$key}[20])) {
+ # Skip all unsupported algorithms
+ next unless (exists $APPLE_DH_GROUPS{$group});
+
+ print " <key>DiffieHellmanGroup</key>\n";
+ print " <string>$APPLE_DH_GROUPS{$group}</string>\n";
+ last;
+ }
+
+ # Lifetime
+ my $lifetime = $confighash{$key}[16] * 60;
+ print " <key>LifeTimeInMinutes</key>\n";
+ print " <integer>$lifetime</integer>\n";
+ print " </dict>\n";
+
+ # ESP Cipher Suite
+ print " <key>ChildSecurityAssociationParameters</key>\n";
+ print " <dict>\n";
+
+ # Encryption
+ foreach my $cipher (split(/\|/,$confighash{$key}[21])) {
+ # Skip all unsupported ciphers
+ next unless (exists $APPLE_CIPHERS{$cipher});
+
+ print " <key>EncryptionAlgorithm</key>\n";
+ print " <string>$APPLE_CIPHERS{$cipher}</string>\n";
+ last;
+ }
+
+ # Integrity
+ foreach my $integrity (split(/\|/,$confighash{$key}[22])) {
+ # Skip all unsupported algorithms
+ next unless (exists $APPLE_INTEGRITIES{$integrity});
+
+ print " <key>IntegrityAlgorithm</key>\n";
+ print " <string>$APPLE_INTEGRITIES{$integrity}</string>\n";
+ last;
+ }
+
+ # Diffie Hellman Groups
+ foreach my $group (split(/\|/,$confighash{$key}[23])) {
+ # Skip all unsupported algorithms
+ next unless (exists $APPLE_DH_GROUPS{$group});
+
+ print " <key>DiffieHellmanGroup</key>\n";
+ print " <string>$APPLE_DH_GROUPS{$group}</string>\n";
+ last;
+ }
+
+ # Lifetime
+ my $lifetime = $confighash{$key}[17] * 60;
+ print " <key>LifeTimeInMinutes</key>\n";
+ print " <integer>$lifetime</integer>\n";
+ print " </dict>\n";
+
# Left ID
if ($confighash{$key}[9]) {
- print " <key>LocalIdentifier</key>\n";
- print " <string>$confighash{$key}[9]</string>\n";
+ my $leftid = $confighash{$key}[9];
+
+ # Strip leading @ from FQDNs
+ if ($leftid =~ m/^@(.*)$/) {
+ $leftid = $1;
+ }
+
+ print " <key>LocalIdentifier</key>\n";
+ print " <string>$leftid</string>\n";
}
# Right ID
if ($confighash{$key}[7]) {
- print " <key>RemoteIdentifier</key>\n";
- print " <string>$confighash{$key}[7]</string>\n";
+ my $rightid = $confighash{$key}[7];
+
+ # Strip leading @ from FQDNs
+ if ($rightid =~ m/^@(.*)$/) {
+ $rightid = $1;
+ }
+
+ print " <key>RemoteIdentifier</key>\n";
+ print " <string>$rightid</string>\n";
}
if ($confighash{$key}[4] eq "cert") {
- print " <key>AuthenticationMethod</key>\n";
- print " <string>Certificate</string>\n";
+ print " <key>AuthenticationMethod</key>\n";
+ print " <string>Certificate</string>\n";
- print " <key>PayloadCertificateUUID</key>\n";
- print " <string>${cert_uuid}</string>\n";
+ print " <key>PayloadCertificateUUID</key>\n";
+ print " <string>${cert_uuid}</string>\n";
} else {
- print " <key>AuthenticationMethod</key>\n";
- print " <string>SharedSecret</string>\n";
- print " <key>SharedSecret</key>\n";
- print " <string>$confighash{$key}[5]</string>\n";
+ print " <key>AuthenticationMethod</key>\n";
+ print " <string>SharedSecret</string>\n";
+ print " <key>SharedSecret</key>\n";
+ print " <string>$confighash{$key}[5]</string>\n";
}
print " <key>ExtendedAuthEnabled</key>\n";
print " <integer>0</integer>\n";
+
+ # These are not needed, but we provide some default to stop iPhone asking for credentials
+ print " <key>AuthName</key>\n";
+ print " <string>$confighash{$key}[1]</string>\n";
+ print " <key>AuthPassword</key>\n";
+ print " <string></string>\n";
print " </dict>\n";
print " </dict>\n";
print " <dict>\n";
print " <key>PayloadIdentifier</key>\n";
print " <string>org.example.vpn1.client</string>\n";
+ print " <key>PayloadDisplayName</key>\n";
+ print " <string>$confighash{$key}[1]</string>\n";
print " <key>PayloadUUID</key>\n";
print " <string>${cert_uuid}</string>\n";
print " <key>PayloadType</key>\n";
print " </data>\n";
print " </dict>\n";
+
+ print " <dict>\n";
+ print " <key>PayloadIdentifier</key>\n";
+ print " <string>org.example.ca</string>\n";
+ print " <key>PayloadUUID</key>\n";
+ print " <string>${ca_uuid}</string>\n";
+ print " <key>PayloadType</key>\n";
+ print " <string>com.apple.security.root</string>\n";
+ print " <key>PayloadVersion</key>\n";
+ print " <integer>1</integer>\n";
+ print " <key>PayloadContent</key>\n";
+ print " <data>\n";
+
+ foreach (split /\n/,${ca}) {
+ print " $_\n";
+ }
+
+ print " </data>\n";
+ print " </dict>\n";
}
print " </array>\n";
&Header::openpage($Lang::tr{'ipsec'}, 1, '');
&Header::openbigbox('100%', 'left', '', '');
&Header::openbox('100%', 'left', "$Lang::tr{'cert'}:");
- my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem`;
- $output = &Header::cleanhtml($output,"y");
- print "<pre>$output</pre>\n";
+ my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
+ @output = &Header::cleanhtml(@output,"y");
+ print "<pre>@output</pre>\n";
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
if ( -f "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
print "Content-Type: application/force-download\n";
print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . "cert.pem\n\n";
- print `/bin/cat ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem`;
+
+ open(FILE, "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
+ my @pem = <FILE>;
+ close(FILE);
+ print "@pem";
+
exit (0);
}
$confighash{$cgiparams{'KEY'}}[0] = 'on';
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
- system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'}) if (&vpnenabled);
+ &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'}) if (&vpnenabled);
} else {
$confighash{$cgiparams{'KEY'}}[0] = 'off';
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
- system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
+ &General::system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
}
sleep $sleepDelay;
} else {
if ($confighash{$cgiparams{'KEY'}}) {
if (&vpnenabled) {
- system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
+ &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
sleep $sleepDelay;
}
} else {
delete $confighash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
- system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
+ &General::system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
} else {
$errormessage = $Lang::tr{'invalid key'};
}
$cgiparams{'INTERFACE_MODE'} = $confighash{$cgiparams{'KEY'}}[36];
$cgiparams{'INTERFACE_ADDRESS'} = $confighash{$cgiparams{'KEY'}}[37];
$cgiparams{'INTERFACE_MTU'} = $confighash{$cgiparams{'KEY'}}[38];
+ $cgiparams{'DNS_SERVERS'} = $confighash{$cgiparams{'KEY'}}[39];
if (!$cgiparams{'DPD_DELAY'}) {
$cgiparams{'DPD_DELAY'} = 30;
}
}
+ if ($cgiparams{'TYPE'} eq 'host') {
+ my @servers = split(",", $cgiparams{'DNS_SERVERS'});
+ foreach my $server (@servers) {
+ unless (&Network::check_ip_address($server)) {
+ $errormessage = $Lang::tr{'ipsec dns server address is invalid'};
+ goto VPNCONF_ERROR;
+ }
+ }
+ }
+
if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto VPNCONF_ERROR;
unshift (@names,$cahash{$x}[0]);
}
if ($casubject) { # a new one!
- my $temp = `/usr/bin/openssl x509 -text -in /tmp/newcacert`;
- if ($temp !~ /CA:TRUE/i) {
+ my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "/tmp/newcacert");
+ if (! grep(/CA:TRUE/, @temp)) {
$errormessage = $Lang::tr{'not a valid ca certificate'};
} else {
#compute a name for it
$cahash{$key}[0] = $cgiparams{'CA_NAME'};
$cahash{$key}[1] = $casubject;
&General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
- system('/usr/local/bin/ipsecctrl', 'R');
+ &General::system('/usr/local/bin/ipsecctrl', 'R');
}
}
}
# Verify the certificate has a valid CA and move it
&General::log("ipsec", "Validating imported cert against our known CA...");
my $validca = 1; #assume ok
- my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/cacert.pem $filename`;
- if ($test !~ /: OK/) {
+ my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/cacert.pem", "$filename");
+ if (! grep(/: OK/, @test)) {
my $validca = 0;
foreach my $key (keys %cahash) {
- $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$key}[0]cert.pem $filename`;
- if ($test =~ /: OK/) {
+ @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$key}[0]cert.pem", "$filename");
+ if (grep(/: OK/, @test)) {
$validca = 1;
last;
}
my $key = $cgiparams{'KEY'};
if (! $key) {
$key = &General::findhasharraykey (\%confighash);
- foreach my $i (0 .. 38) { $confighash{$key}[$i] = "";}
+ foreach my $i (0 .. 39) { $confighash{$key}[$i] = "";}
}
$confighash{$key}[0] = $cgiparams{'ENABLED'};
$confighash{$key}[1] = $cgiparams{'NAME'};
$confighash{$key}[36] = $cgiparams{'INTERFACE_MODE'};
$confighash{$key}[37] = $cgiparams{'INTERFACE_ADDRESS'};
$confighash{$key}[38] = $cgiparams{'INTERFACE_MTU'};
+ $confighash{$key}[39] = join("|", split(",", $cgiparams{'DNS_SERVERS'}));
# free unused fields!
$confighash{$key}[15] = 'off';
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
if (&vpnenabled) {
- system('/usr/local/bin/ipsecctrl', 'S', $key);
+ &General::system('/usr/local/bin/ipsecctrl', 'S', $key);
sleep $sleepDelay;
}
if ($cgiparams{'EDIT_ADVANCED'} eq 'on') {
#use default advanced value
$cgiparams{'IKE_ENCRYPTION'} = 'chacha20poly1305|aes256gcm128|aes256gcm96|aes256gcm64|aes256|aes192gcm128|aes192gcm96|aes192gcm64|aes192|aes128gcm128|aes128gcm96|aes128gcm64|aes128'; #[18];
$cgiparams{'IKE_INTEGRITY'} = 'sha2_512|sha2_256'; #[19];
- $cgiparams{'IKE_GROUPTYPE'} = 'curve25519|curve448|4096|3072|2048'; #[20];
+ $cgiparams{'IKE_GROUPTYPE'} = 'curve448|curve25519|4096|3072|2048'; #[20];
$cgiparams{'IKE_LIFETIME'} = '3'; #[16];
$cgiparams{'ESP_ENCRYPTION'} = 'chacha20poly1305|aes256gcm128|aes256gcm96|aes256gcm64|aes256|aes192gcm128|aes192gcm96|aes192gcm64|aes192|aes128gcm128|aes128gcm96|aes128gcm64|aes128'; #[21];
$cgiparams{'ESP_INTEGRITY'} = 'sha2_512|sha2_256'; #[22];
- $cgiparams{'ESP_GROUPTYPE'} = 'curve25519|curve448|4096|3072|2048'; #[23];
+ $cgiparams{'ESP_GROUPTYPE'} = 'curve448|curve25519|4096|3072|2048'; #[23];
$cgiparams{'ESP_KEYLIFE'} = '1'; #[17];
$cgiparams{'COMPRESSION'} = 'off'; #[13];
$cgiparams{'ONLY_PROPOSED'} = 'on'; #[24];
$cgiparams{'INTERFACE_MODE'} = "";
$cgiparams{'INTERFACE_ADDRESS'} = "";
$cgiparams{'INTERFACE_MTU'} = 1500;
+ $cgiparams{'DNS_SERVERS'} = "";
}
VPNCONF_ERROR:
EOF
}
- my $disabled;
- my $blob;
- if ($cgiparams{'TYPE'} eq 'host') {
- $disabled = "disabled='disabled'";
- } elsif ($cgiparams{'TYPE'} eq 'net') {
+ my $blob = "";
+ if ($cgiparams{'TYPE'} eq 'net') {
$blob = "<img src='/blob.gif' alt='*' />";
};
my @remote_subnets = split(/\|/, $cgiparams{'REMOTE_SUBNET'});
my $remote_subnets = join(",", @remote_subnets);
+ my @dns_servers = split(/\|/, $cgiparams{'DNS_SERVERS'});
+ my $dns_servers = join(",", @dns_servers);
+
print <<END;
<tr>
<td width='20%'>$Lang::tr{'enabled'}</td>
<td width='30%'>
<input type='text' name='LOCAL_SUBNET' value='$local_subnets' size="25" />
</td>
- <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'remote subnet'} $blob</td>
+END
+
+ if ($cgiparams{'TYPE'} eq "net") {
+ print <<END;
+ <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'remote subnet'} <img src='/blob.gif' alt='*' /></td>
<td width='30%'>
- <input $disabled type='text' name='REMOTE_SUBNET' value='$remote_subnets' size="25" />
+ <input type='text' name='REMOTE_SUBNET' value='$remote_subnets' size="25" />
</td>
+END
+
+ } elsif ($cgiparams{'TYPE'} eq "host") {
+ print <<END;
+ <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'dns servers'}:</td>
+ <td width='30%'>
+ <input type='text' name='DNS_SERVERS' value='$dns_servers' size="25" />
+ </td>
+END
+ }
+
+ print <<END;
</tr>
<tr>
<td class='boldbase' width='20%'>$Lang::tr{'vpn local id'}:</td>
goto ADVANCED_ERROR;
}
foreach my $val (@temp) {
- if ($val !~ /^(curve25519|curve448|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192)$/) {
+ if ($val !~ /^(curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto ADVANCED_ERROR;
}
goto ADVANCED_ERROR;
}
foreach my $val (@temp) {
- if ($val !~ /^(curve25519|curve448|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192|none)$/) {
+ if ($val !~ /^(curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192|none)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto ADVANCED_ERROR;
}
&General::writehasharray("${General::swroot}/vpn/config", \%confighash);
&writeipsecfiles();
if (&vpnenabled) {
- system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
+ &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
sleep $sleepDelay;
}
goto ADVANCED_END;
$cgiparams{'INTERFACE_MODE'} = $confighash{$cgiparams{'KEY'}}[36];
$cgiparams{'INTERFACE_ADDRESS'} = $confighash{$cgiparams{'KEY'}}[37];
$cgiparams{'INTERFACE_MTU'} = $confighash{$cgiparams{'KEY'}}[38];
+ $cgiparams{'DNS_SERVERS'} = $confighash{$cgiparams{'KEY'}}[39];
if (!$cgiparams{'DPD_DELAY'}) {
$cgiparams{'DPD_DELAY'} = 30;
$checked{'IKE_INTEGRITY'}{'aesxcbc'} = '';
@temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
foreach my $key (@temp) {$checked{'IKE_INTEGRITY'}{$key} = "selected='selected'"; }
- $checked{'IKE_GROUPTYPE'}{'curve25519'} = '';
$checked{'IKE_GROUPTYPE'}{'curve448'} = '';
+ $checked{'IKE_GROUPTYPE'}{'curve25519'} = '';
$checked{'IKE_GROUPTYPE'}{'768'} = '';
$checked{'IKE_GROUPTYPE'}{'1024'} = '';
$checked{'IKE_GROUPTYPE'}{'1536'} = '';
$checked{'ESP_INTEGRITY'}{'aesxcbc'} = '';
@temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
foreach my $key (@temp) {$checked{'ESP_INTEGRITY'}{$key} = "selected='selected'"; }
- $checked{'ESP_GROUPTYPE'}{'curve25519'} = '';
$checked{'ESP_GROUPTYPE'}{'curve448'} = '';
+ $checked{'ESP_GROUPTYPE'}{'curve25519'} = '';
$checked{'ESP_GROUPTYPE'}{'768'} = '';
$checked{'ESP_GROUPTYPE'}{'1024'} = '';
$checked{'ESP_GROUPTYPE'}{'1536'} = '';
<td class='boldbase' width="15%">$Lang::tr{'grouptype'}</td>
<td class='boldbase'>
<select name='IKE_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
- <option value='curve25519' $checked{'IKE_GROUPTYPE'}{'curve25519'}>Curve 25519 (256 bit)</option>
<option value='curve448' $checked{'IKE_GROUPTYPE'}{'curve448'}>Curve 448 (224 bit)</option>
+ <option value='curve25519' $checked{'IKE_GROUPTYPE'}{'curve25519'}>Curve 25519 (128 bit)</option>
<option value='e521' $checked{'IKE_GROUPTYPE'}{'e521'}>ECP-521 (NIST)</option>
<option value='e512bp' $checked{'IKE_GROUPTYPE'}{'e512bp'}>ECP-512 (Brainpool)</option>
<option value='e384' $checked{'IKE_GROUPTYPE'}{'e384'}>ECP-384 (NIST)</option>
</td>
<td class='boldbase'>
<select name='ESP_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
- <option value='curve25519' $checked{'ESP_GROUPTYPE'}{'curve25519'}>Curve 25519 (256 bit)</option>
<option value='curve448' $checked{'ESP_GROUPTYPE'}{'curve448'}>Curve 448 (224 bit)</option>
+ <option value='curve25519' $checked{'ESP_GROUPTYPE'}{'curve25519'}>Curve 25519 (128 bit)</option>
<option value='e521' $checked{'ESP_GROUPTYPE'}{'e521'}>ECP-521 (NIST)</option>
<option value='e512bp' $checked{'ESP_GROUPTYPE'}{'e512bp'}>ECP-512 (Brainpool)</option>
<option value='e384' $checked{'ESP_GROUPTYPE'}{'e384'}>ECP-384 (NIST)</option>
&General::readhasharray("${General::swroot}/vpn/config", \%confighash);
$cgiparams{'CA_NAME'} = '';
- my @status = `/usr/local/bin/ipsecctrl I 2>/dev/null`;
+ my @status = &General::system_output("/usr/local/bin/ipsecctrl", "I");
$checked{'ENABLED'} = $cgiparams{'ENABLED'} eq 'on' ? "checked='checked'" : '';
<input type='checkbox' name='ENABLED' $checked{'ENABLED'} />
</td>
</tr>
+ <tr>
+ <td class='base' nowrap='nowrap' width="60%">$Lang::tr{'ipsec roadwarrior endpoint'}:</td>
+ <td width="40%"><input type='text' name='RW_ENDPOINT' value='$cgiparams{'RW_ENDPOINT'}' /></td>
+ </tr>
<tr>
<td class='base' nowrap='nowrap' width="60%">$Lang::tr{'host to net vpn'}:</td>
<td width="40%"><input type='text' name='RW_NET' value='$cgiparams{'RW_NET'}' /></td>
if ($grp =~ m/^e(.*)$/) {
push(@algo, "ecp$1");
- } elsif ($grp =~ m/curve(25519|448)/) {
+ } elsif ($grp =~ m/curve(448|25519)/) {
push(@algo, "$grp");
} else {
push(@algo, "modp$grp");
# noop
} elsif ($grp =~ m/^e(.*)$/) {
push(@algo, "ecp$1");
- } elsif ($grp =~ m/curve(25519|448)/) {
+ } elsif ($grp =~ m/curve(448|25519)/) {
push(@algo, "$grp");
} else {
push(@algo, "modp$grp");