OpenVPN - Path MTU Discovery
Stefan Schantl
stefan.schantl at ipfire.org
Wed Nov 14 21:22:33 CET 2012
Dear Mailinglist Followers,
I've implemented the option to configure "Path MTU Discovery" for OpenVPN.
This can be done by using the Web-Userinterface, and is available for
Roadwarrior and Net-to-Net connections.
To get this cool feature into the main distribution we need more
feedback from testes, so I've attached the files to this announcement.
Just download them and place the ovpnmain.cgi into your
"/srv/web/ipfire/cgi-bin/" directory.
The language files have to be copied to the "/var/ipfire/langs" directory.
At the end, the language cache have to be updated by using the following
command:
perl -e "require '/var/ipfire/lang.pl'; &Lang::BuildCacheLang"
NOTE - Always create a backup of your existing files!
Please test and phone back any problems or errors.
Best regards,
Stefan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: en.pl
Type: application/x-perl
Size: 114659 bytes
Desc: not available
URL: <http://lists.ipfire.org/pipermail/development/attachments/20121114/3082d424/attachment-0002.pl>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: de.pl
Type: application/x-perl
Size: 123618 bytes
Desc: not available
URL: <http://lists.ipfire.org/pipermail/development/attachments/20121114/3082d424/attachment-0003.pl>
-------------- next part --------------
#!/usr/bin/perl
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2011 IPFire Team <info at ipfire.org> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# 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, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
###
# Based on IPFireCore 55
###
use CGI;
use CGI qw/:standard/;
use Net::DNS;
use Net::Ping;
use Net::Telnet;
use File::Copy;
use File::Temp qw/ tempfile tempdir /;
use strict;
use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
require '/var/ipfire/general-functions.pl';
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";
require "${General::swroot}/countries.pl";
# enable only the following on debugging purpose
use warnings;
use CGI::Carp 'fatalsToBrowser';
#workaround to suppress a warning when a variable is used only once
my @dummy = ( ${Header::colourgreen} );
undef (@dummy);
my %color = ();
my %mainsettings = ();
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color);
###
### Initialize variables
###
my %netsettings=();
my %cgiparams=();
my %vpnsettings=();
my %checked=();
my %confighash=();
my %cahash=();
my %selected=();
my $warnmessage = '';
my $errormessage = '';
my %settings=();
my $routes_push_file = '';
&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
$cgiparams{'ENABLED'} = 'off';
$cgiparams{'ENABLED_BLUE'} = 'off';
$cgiparams{'ENABLED_ORANGE'} = 'off';
$cgiparams{'EDIT_ADVANCED'} = 'off';
$cgiparams{'NAT'} = 'off';
$cgiparams{'COMPRESSION'} = 'off';
$cgiparams{'ONLY_PROPOSED'} = 'off';
$cgiparams{'ACTION'} = '';
$cgiparams{'CA_NAME'} = '';
$cgiparams{'DHCP_DOMAIN'} = '';
$cgiparams{'DHCP_DNS'} = '';
$cgiparams{'DHCP_WINS'} = '';
$cgiparams{'ROUTES_PUSH'} = '';
$cgiparams{'DCOMPLZO'} = 'off';
$cgiparams{'MSSFIX'} = '';
$cgiparams{'PMTU_DISCOVERY'} = '';
$routes_push_file = "${General::swroot}/ovpn/routes_push";
unless (-e $routes_push_file) { system("touch $routes_push_file"); }
&Header::getcgihash(\%cgiparams, {'wantfile' => 1, 'filevar' => 'FH'});
# prepare openvpn config file
###
### Useful functions
###
sub haveOrangeNet
{
if ($netsettings{'CONFIG_TYPE'} == 2) {return 1;}
if ($netsettings{'CONFIG_TYPE'} == 4) {return 1;}
return 0;
}
sub haveBlueNet
{
if ($netsettings{'CONFIG_TYPE'} == 3) {return 1;}
if ($netsettings{'CONFIG_TYPE'} == 4) {return 1;}
return 0;
}
sub sizeformat{
my $bytesize = shift;
my $i = 0;
while(abs($bytesize) >= 1024){
$bytesize=$bytesize/1024;
$i++;
last if($i==6);
}
my @units = ("Bytes","KB","MB","GB","TB","PB","EB");
my $newsize=(int($bytesize*100 +0.5))/100;
return("$newsize $units[$i]");
}
sub valid_dns_host {
my $hostname = $_[0];
unless ($hostname) { return "No hostname"};
my $res = new Net::DNS::Resolver;
my $query = $res->search("$hostname");
if ($query) {
foreach my $rr ($query->answer) {
## Potential bug - we are only looking at A records:
return 0 if $rr->type eq "A";
}
} else {
return $res->errorstring;
}
}
sub cleanssldatabase
{
if (open(FILE, ">${General::swroot}/ovpn/certs/serial")) {
print FILE "01";
close FILE;
}
if (open(FILE, ">${General::swroot}/ovpn/certs/index.txt")) {
print FILE "";
close FILE;
}
unlink ("${General::swroot}/ovpn/certs/index.txt.old");
unlink ("${General::swroot}/ovpn/certs/serial.old");
unlink ("${General::swroot}/ovpn/certs/01.pem");
}
sub newcleanssldatabase
{
if (! -s "${General::swroot}/ovpn/certs/serial" ) {
open(FILE, ">${General::swroot}(ovpn/certs/serial");
print FILE "01";
close FILE;
}
if (! -s ">${General::swroot}/ovpn/certs/index.txt") {
system ("touch ${General::swroot}/ovpn/certs/index.txt");
}
unlink ("${General::swroot}/ovpn/certs/index.txt.old");
unlink ("${General::swroot}/ovpn/certs/serial.old");
}
sub deletebackupcert
{
if (open(FILE, "${General::swroot}/ovpn/certs/serial.old")) {
my $hexvalue = <FILE>;
chomp $hexvalue;
close FILE;
unlink ("${General::swroot}/ovpn/certs/$hexvalue.pem");
}
}
sub checkportfw {
my $KEY2 = $_[0]; # key2
my $SRC_PORT = $_[1]; # src_port
my $PROTOCOL = $_[2]; # protocol
my $SRC_IP = $_[3]; # sourceip
my $pfwfilename = "${General::swroot}/portfw/config";
open(FILE, $pfwfilename) or die 'Unable to open config file.';
my @pfwcurrent = <FILE>;
close(FILE);
my $pfwkey1 = 0; # used for finding last sequence number used
foreach my $pfwline (@pfwcurrent)
{
my @pfwtemp = split(/\,/,$pfwline);
chomp ($pfwtemp[8]);
if ($KEY2 eq "0"){ # if key2 is 0 then it is a portfw addition
if ( $SRC_PORT eq $pfwtemp[3] &&
$PROTOCOL eq $pfwtemp[2] &&
$SRC_IP eq $pfwtemp[7])
{
$errormessage = "$Lang::tr{'source port in use'} $SRC_PORT";
}
# Check if key2 = 0, if it is then it is a port forward entry and we want the sequence number
if ( $pfwtemp[1] eq "0") {
$pfwkey1=$pfwtemp[0];
}
# Darren Critchley - Duplicate or overlapping Port range check
if ($pfwtemp[1] eq "0" &&
$PROTOCOL eq $pfwtemp[2] &&
$SRC_IP eq $pfwtemp[7] &&
$errormessage eq '')
{
&portchecks($SRC_PORT, $pfwtemp[5]);
# &portchecks($pfwtemp[3], $pfwtemp[5]);
# &portchecks($pfwtemp[3], $SRC_IP);
}
}
}
# $errormessage="$KEY2 $SRC_PORT $PROTOCOL $SRC_IP";
return;
}
sub checkportoverlap
{
my $portrange1 = $_[0]; # New port range
my $portrange2 = $_[1]; # existing port range
my @tempr1 = split(/\:/,$portrange1);
my @tempr2 = split(/\:/,$portrange2);
unless (&checkportinc($tempr1[0], $portrange2)){ return 0;}
unless (&checkportinc($tempr1[1], $portrange2)){ return 0;}
unless (&checkportinc($tempr2[0], $portrange1)){ return 0;}
unless (&checkportinc($tempr2[1], $portrange1)){ return 0;}
return 1; # Everything checks out!
}
# Darren Critchley - we want to make sure that a port entry is not within an already existing range
sub checkportinc
{
my $port1 = $_[0]; # Port
my $portrange2 = $_[1]; # Port range
my @tempr1 = split(/\:/,$portrange2);
if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) {
return 1;
} else {
return 0;
}
}
# Darren Critchley - Duplicate or overlapping Port range check
sub portchecks
{
my $p1 = $_[0]; # New port range
my $p2 = $_[1]; # existing port range
# $_ = $_[0];
our ($prtrange1, $prtrange2);
$prtrange1 = 0;
# if (m/:/ && $prtrange1 == 1) { # comparing two port ranges
# unless (&checkportoverlap($p1,$p2)) {
# $errormessage = "$Lang::tr{'source port overlaps'} $p1";
# }
# }
if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range
unless (&checkportinc($p2,$p1)) {
$errormessage = "$Lang::tr{'srcprt within existing'} $p1";
}
}
$prtrange1 = 1;
if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range
unless (&checkportinc($p1,$p2)) {
$errormessage = "$Lang::tr{'srcprt range overlaps'} $p2";
}
}
return;
}
# Darren Critchley - certain ports are reserved for IPFire
# TCP 67,68,81,222,445
# UDP 67,68
# Params passed in -> port, rangeyn, protocol
sub disallowreserved
{
# port 67 and 68 same for tcp and udp, don't bother putting in an array
my $msg = "";
my @tcp_reserved = (81,222,445);
my $prt = $_[0]; # the port or range
my $ryn = $_[1]; # tells us whether or not it is a port range
my $prot = $_[2]; # protocol
my $srcdst = $_[3]; # source or destination
if ($ryn) { # disect port range
if ($srcdst eq "src") {
$msg = "$Lang::tr{'rsvd src port overlap'}";
} else {
$msg = "$Lang::tr{'rsvd dst port overlap'}";
}
my @tmprng = split(/\:/,$prt);
unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; }
unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; }
if ($prot eq "tcp") {
foreach my $prange (@tcp_reserved) {
unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; }
}
}
} else {
if ($srcdst eq "src") {
$msg = "$Lang::tr{'reserved src port'}";
} else {
$msg = "$Lang::tr{'reserved dst port'}";
}
if ($prt == 67) { $errormessage="$msg 67"; return; }
if ($prt == 68) { $errormessage="$msg 68"; return; }
if ($prot eq "tcp") {
foreach my $prange (@tcp_reserved) {
if ($prange == $prt) { $errormessage="$msg $prange"; return; }
}
}
}
return;
}
sub writeserverconf {
my %sovpnsettings = ();
my @temp = ();
&General::readhash("${General::swroot}/ovpn/settings", \%sovpnsettings);
&read_routepushfile;
open(CONF, ">${General::swroot}/ovpn/server.conf") or die "Unable to open ${General::swroot}/ovpn/server.conf: $!";
flock CONF, 2;
print CONF "#OpenVPN Server conf\n";
print CONF "\n";
print CONF "daemon openvpnserver\n";
print CONF "writepid /var/run/openvpn.pid\n";
print CONF "#DAN prepare OpenVPN for listening on blue and orange\n";
print CONF ";local $sovpnsettings{'VPN_IP'}\n";
print CONF "dev $sovpnsettings{'DDEVICE'}\n";
print CONF "proto $sovpnsettings{'DPROTOCOL'}\n";
print CONF "port $sovpnsettings{'DDEST_PORT'}\n";
print CONF "script-security 3 system\n";
print CONF "ifconfig-pool-persist /var/ipfire/ovpn/ovpn-leases.db 3600\n";
print CONF "client-config-dir /var/ipfire/ovpn/ccd\n";
print CONF "tls-server\n";
print CONF "ca /var/ipfire/ovpn/ca/cacert.pem\n";
print CONF "cert /var/ipfire/ovpn/certs/servercert.pem\n";
print CONF "key /var/ipfire/ovpn/certs/serverkey.pem\n";
print CONF "dh /var/ipfire/ovpn/ca/dh1024.pem\n";
my @tempovpnsubnet = split("\/",$sovpnsettings{'DOVPN_SUBNET'});
print CONF "server $tempovpnsubnet[0] $tempovpnsubnet[1]\n";
print CONF "push \"route $netsettings{'GREEN_NETADDRESS'} $netsettings{'GREEN_NETMASK'}\"\n";
# Check if we are using mssfix, fragment or mtu-disc and set the corretct mtu of 1500.
# If we doesn't use one of them, we can use the configured mtu value.
if ($sovpnsettings{'MSSFIX'} eq 'on')
{ print CONF "$sovpnsettings{'DDEVICE'}-mtu 1500\n"; }
elsif ($sovpnsettings{'FRAGMENT'} ne '' && $sovpnsettings{'DPROTOCOL'} ne 'tcp')
{ print CONF "$sovpnsettings{'DDEVICE'}-mtu 1500\n"; }
elsif ($sovpnsettings{'PMTU_DISCOVERY'} ne 'off')
{ print CONF "$sovpnsettings{'DDEVICE'}-mtu 1500\n"; }
else
{ print CONF "$sovpnsettings{'DDEVICE'}-mtu $sovpnsettings{'DMTU'}\n"; }
if ($vpnsettings{'ROUTES_PUSH'} ne '') {
@temp = split(/\n/,$vpnsettings{'ROUTES_PUSH'});
foreach (@temp)
{
@tempovpnsubnet = split("\/",&General::ipcidr2msk($_));
print CONF "push \"route " . $tempovpnsubnet[0]. " " . $tempovpnsubnet[1] . "\"\n";
}
}
if ($sovpnsettings{CLIENT2CLIENT} eq 'on') {
print CONF "client-to-client\n";
}
if ($sovpnsettings{MSSFIX} eq 'on') {
print CONF "mssfix\n";
}
if ($sovpnsettings{FRAGMENT} ne '' && $sovpnsettings{'DPROTOCOL'} ne 'tcp') {
print CONF "fragment $sovpnsettings{'FRAGMENT'}\n";
}
if ($sovpnsettings{PMTU_DISCOVERY} ne 'off') {
print CONF "mtu-disc $sovpnsettings{'PMTU_DISCOVERY'}\n";
}
if ($sovpnsettings{KEEPALIVE_1} > 0 && $sovpnsettings{KEEPALIVE_2} > 0) {
print CONF "keepalive $sovpnsettings{'KEEPALIVE_1'} $sovpnsettings{'KEEPALIVE_2'}\n";
}
print CONF "status-version 1\n";
print CONF "status /var/log/ovpnserver.log 30\n";
print CONF "cipher $sovpnsettings{DCIPHER}\n";
if ($sovpnsettings{DCOMPLZO} eq 'on') {
print CONF "comp-lzo\n";
}
if ($sovpnsettings{REDIRECT_GW_DEF1} eq 'on') {
print CONF "push \"redirect-gateway def1\"\n";
}
if ($sovpnsettings{DHCP_DOMAIN} ne '') {
print CONF "push \"dhcp-option DOMAIN $sovpnsettings{DHCP_DOMAIN}\"\n";
}
if ($sovpnsettings{DHCP_DNS} ne '') {
print CONF "push \"dhcp-option DNS $sovpnsettings{DHCP_DNS}\"\n";
}
if ($sovpnsettings{DHCP_WINS} ne '') {
print CONF "push \"dhcp-option WINS $sovpnsettings{DHCP_WINS}\"\n";
}
if ($sovpnsettings{DHCP_WINS} eq '') {
print CONF "max-clients 100\n";
}
if ($sovpnsettings{DHCP_WINS} ne '') {
print CONF "max-clients $sovpnsettings{MAX_CLIENTS}\n";
}
print CONF "tls-verify /var/ipfire/ovpn/verify\n";
print CONF "crl-verify /var/ipfire/ovpn/crls/cacrl.pem\n";
print CONF "user nobody\n";
print CONF "group nobody\n";
print CONF "persist-key\n";
print CONF "persist-tun\n";
if ($sovpnsettings{LOG_VERB} ne '') {
print CONF "verb $sovpnsettings{LOG_VERB}\n";
} else {
print CONF "verb 3\n";
}
print CONF "\n";
close(CONF);
}
#
sub emptyserverlog{
if (open(FILE, ">/var/log/ovpnserver.log")) {
flock FILE, 2;
print FILE "";
close FILE;
}
}
###
# m.a.d net2net
###
sub validdotmask
{
my $ipdotmask = $_[0];
if (&General::validip($ipdotmask)) { return 0; }
if (!($ipdotmask =~ /^(.*?)\/(.*?)$/)) { }
my $mask = $2;
if (($mask =~ /\./ )) { return 0; }
return 1;
}
# -------------------------------------------------------------------
sub write_routepushfile
{
open(FILE, ">$routes_push_file");
flock(FILE, 2);
if ($vpnsettings{'ROUTES_PUSH'} ne '') {
print FILE $vpnsettings{'ROUTES_PUSH'};
}
close(FILE);
}
sub read_routepushfile
{
if (-e "$routes_push_file") {
open(FILE,"$routes_push_file");
delete $vpnsettings{'ROUTES_PUSH'};
while (<FILE>) { $vpnsettings{'ROUTES_PUSH'} .= $_ };
close(FILE);
$cgiparams{'ROUTES_PUSH'} = $vpnsettings{'ROUTES_PUSH'};
}
}
#hier die refresh page
if ( -e "${General::swroot}/ovpn/gencanow") {
my $refresh = '';
$refresh = "<meta http-equiv='refresh' content='15;' />";
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'OVPN'}, 1, $refresh);
&Header::openbigbox('100%', 'center');
&Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
print "<tr>\n<td align='center'><img src='/images/clock.gif' alt='' /></td>\n";
print "<td colspan='2'><font color='red'>Please be patient this realy can take some time on older hardware...</font></td></tr>\n";
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
exit (0);
}
##hier die refresh page
###
### OpenVPN Server Control
###
if ($cgiparams{'ACTION'} eq $Lang::tr{'start ovpn server'} ||
$cgiparams{'ACTION'} eq $Lang::tr{'stop ovpn server'} ||
$cgiparams{'ACTION'} eq $Lang::tr{'restart ovpn server'}) {
#start openvpn server
if ($cgiparams{'ACTION'} eq $Lang::tr{'start ovpn server'}){
&emptyserverlog();
system('/usr/local/bin/openvpnctrl', '-s');
}
#stop openvpn server
if ($cgiparams{'ACTION'} eq $Lang::tr{'stop ovpn server'}){
system('/usr/local/bin/openvpnctrl', '-k');
&emptyserverlog();
}
# #restart openvpn server
if ($cgiparams{'ACTION'} eq $Lang::tr{'restart ovpn server'}){
#workarund, till SIGHUP also works when running as nobody
system('/usr/local/bin/openvpnctrl', '-r');
&emptyserverlog();
}
}
###
### Save Advanced options
###
if ($cgiparams{'ACTION'} eq $Lang::tr{'save-adv-options'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
#DAN do we really need (to to check) this value? Besides if we listen on blue and orange too,
#DAN this value has to leave.
#new settings for daemon
$vpnsettings{'LOG_VERB'} = $cgiparams{'LOG_VERB'};
$vpnsettings{'KEEPALIVE_1'} = $cgiparams{'KEEPALIVE_1'};
$vpnsettings{'KEEPALIVE_2'} = $cgiparams{'KEEPALIVE_2'};
$vpnsettings{'MAX_CLIENTS'} = $cgiparams{'MAX_CLIENTS'};
$vpnsettings{'REDIRECT_GW_DEF1'} = $cgiparams{'REDIRECT_GW_DEF1'};
$vpnsettings{'CLIENT2CLIENT'} = $cgiparams{'CLIENT2CLIENT'};
$vpnsettings{'DHCP_DOMAIN'} = $cgiparams{'DHCP_DOMAIN'};
$vpnsettings{'DHCP_DNS'} = $cgiparams{'DHCP_DNS'};
$vpnsettings{'DHCP_WINS'} = $cgiparams{'DHCP_WINS'};
$vpnsettings{'ROUTES_PUSH'} = $cgiparams{'ROUTES_PUSH'};
$vpnsettings{'PMTU_DISCOVERY'} = $cgiparams{'PMTU_DISCOVERY'};
my @temp=();
if ($cgiparams{'FRAGMENT'} eq '') {
delete $vpnsettings{'FRAGMENT'};
} else {
if ($cgiparams{'FRAGMENT'} !~ /^[0-9]+$/) {
$errormessage = "Incorrect value, please insert only numbers.";
goto ADV_ERROR;
} else {
$vpnsettings{'FRAGMENT'} = $cgiparams{'FRAGMENT'};
}
}
if ($cgiparams{'MSSFIX'} ne 'on') {
delete $vpnsettings{'MSSFIX'};
} else {
$vpnsettings{'MSSFIX'} = $cgiparams{'MSSFIX'};
}
if ($cgiparams{'PMTU_DISCOVERY'} ne 'off') {
if (($cgiparams{'MSSFIX'} eq 'on') || ($cgiparams{'FRAGMENT'} ne '')) {
$errormessage = $Lang::tr{'ovpn mtu-disc with mssfix or fragment'};
goto ADV_ERROR;
}
}
if ($cgiparams{'DHCP_DOMAIN'} ne ''){
unless (&General::validfqdn($cgiparams{'DHCP_DOMAIN'}) || &General::validip($cgiparams{'DHCP_DOMAIN'})) {
$errormessage = $Lang::tr{'invalid input for dhcp domain'};
goto ADV_ERROR;
}
}
if ($cgiparams{'DHCP_DNS'} ne ''){
unless (&General::validfqdn($cgiparams{'DHCP_DNS'}) || &General::validip($cgiparams{'DHCP_DNS'})) {
$errormessage = $Lang::tr{'invalid input for dhcp dns'};
goto ADV_ERROR;
}
}
if ($cgiparams{'DHCP_WINS'} ne ''){
unless (&General::validfqdn($cgiparams{'DHCP_WINS'}) || &General::validip($cgiparams{'DHCP_WINS'})) {
$errormessage = $Lang::tr{'invalid input for dhcp wins'};
goto ADV_ERROR;
}
}
if ($cgiparams{'ROUTES_PUSH'} ne ''){
@temp = split(/\n/,$cgiparams{'ROUTES_PUSH'});
undef $vpnsettings{'ROUTES_PUSH'};
foreach (@temp)
{
s/^\s+//g; s/\s+$//g;
if ($_)
{
unless (&General::validipandmask($_)) {
$errormessage = $Lang::tr{'ovpn errmsg invalid ip or mask'};
goto ADV_ERROR;
}
my ($ip, $cidr) = split("\/",&General::ipcidr2msk($_));
if ($ip eq $netsettings{'GREEN_NETADDRESS'} && $cidr eq $netsettings{'GREEN_NETMASK'}) {
$errormessage = $Lang::tr{'ovpn errmsg green already pushed'};
goto ADV_ERROR;
}
$vpnsettings{'ROUTES_PUSH'} .= $_."\n";
}
}
&write_routepushfile;
undef $vpnsettings{'ROUTES_PUSH'};
}
else {
undef $vpnsettings{'ROUTES_PUSH'};
&write_routepushfile;
}
if ((length($cgiparams{'MAX_CLIENTS'}) == 0) || (($cgiparams{'MAX_CLIENTS'}) < 1 ) || (($cgiparams{'MAX_CLIENTS'}) > 255 )) {
$errormessage = $Lang::tr{'invalid input for max clients'};
goto ADV_ERROR;
}
if ($cgiparams{'KEEPALIVE_1'} ne '') {
if ($cgiparams{'KEEPALIVE_1'} !~ /^[0-9]+$/) {
$errormessage = $Lang::tr{'invalid input for keepalive 1'};
goto ADV_ERROR;
}
}
if ($cgiparams{'KEEPALIVE_2'} ne ''){
if ($cgiparams{'KEEPALIVE_2'} !~ /^[0-9]+$/) {
$errormessage = $Lang::tr{'invalid input for keepalive 2'};
goto ADV_ERROR;
}
}
if ($cgiparams{'KEEPALIVE_2'} < ($cgiparams{'KEEPALIVE_1'} * 2)){
$errormessage = $Lang::tr{'invalid input for keepalive 1:2'};
goto ADV_ERROR;
}
&General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
&writeserverconf();#hier ok
}
###
# m.a.d net2net
###
if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && $cgiparams{'SIDE'} eq 'server')
{
my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'});
my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'});
my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
my $tunmtu = '';
unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";}
unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}", 0770 or die "Unable to create dir $!";}
open(SERVERCONF, ">${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Unable to open ${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf: $!";
flock SERVERCONF, 2;
print SERVERCONF "# IPFire n2n Open VPN Server Config by ummeegge und m.a.d\n";
print SERVERCONF "\n";
print SERVERCONF "# User Security\n";
print SERVERCONF "user nobody\n";
print SERVERCONF "group nobody\n";
print SERVERCONF "persist-tun\n";
print SERVERCONF "persist-key\n";
print SERVERCONF "script-security 2\n";
print SERVERCONF "# IP/DNS for remote Server Gateway\n";
print SERVERCONF "remote $cgiparams{'REMOTE'}\n";
print SERVERCONF "float\n";
print SERVERCONF "# IP adresses of the VPN Subnet\n";
print SERVERCONF "ifconfig $ovsubnet.1 $ovsubnet.2\n";
print SERVERCONF "# Client Gateway Network\n";
print SERVERCONF "route $remsubnet[0] $remsubnet[1]\n";
print SERVERCONF "# tun Device\n";
print SERVERCONF "dev tun\n";
print SERVERCONF "# Port and Protokol\n";
print SERVERCONF "port $cgiparams{'DEST_PORT'}\n";
if ($cgiparams{'PROTOCOL'} eq 'tcp') {
print SERVERCONF "proto tcp-server\n";
print SERVERCONF "# Packet size\n";
if ($cgiparams{'MTU'} eq '') {$tunmtu = '1400'} else {$tunmtu = $cgiparams{'MTU'}};
print SERVERCONF "tun-mtu $tunmtu\n";
}
if ($cgiparams{'PROTOCOL'} eq 'udp') {
print SERVERCONF "proto udp\n";
print SERVERCONF "# Paketsize\n";
if ($cgiparams{'MTU'} eq '') {$tunmtu = '1500'} else {$tunmtu = $cgiparams{'MTU'}};
print SERVERCONF "tun-mtu $tunmtu\n";
if ($cgiparams{'FRAGMENT'} ne '') {print SERVERCONF "fragment $cgiparams{'FRAGMENT'}\n";}
if ($cgiparams{'MSSFIX'} eq 'on') {print SERVERCONF "mssfix\n"; };
}
if ($cgiparams{'PMTU_DISCOVERY'} ne 'off') {
if(($cgiparams{'MSSFIX'} ne 'on') || ($cgiparams{'FRAGMENT'} eq '')) {
if($cgiparams{'MTU'} eq '1500') {
print SERVERCONF "mtu-disc $cgiparams{'PMTU_DISCOVERY'}\n";
}
}
}
print SERVERCONF "# Auth. Server\n";
print SERVERCONF "tls-server\n";
print SERVERCONF "ca ${General::swroot}/ovpn/ca/cacert.pem\n";
print SERVERCONF "cert ${General::swroot}/ovpn/certs/servercert.pem\n";
print SERVERCONF "key ${General::swroot}/ovpn/certs/serverkey.pem\n";
print SERVERCONF "dh ${General::swroot}/ovpn/ca/dh1024.pem\n";
print SERVERCONF "# Cipher\n";
print SERVERCONF "cipher AES-256-CBC\n";
if ($cgiparams{'COMPLZO'} eq 'on') {
print SERVERCONF "# Enable Compression\n";
print SERVERCONF "comp-lzo\r\n";
}
print SERVERCONF "# Debug Level\n";
print SERVERCONF "verb 3\n";
print SERVERCONF "# Tunnel check\n";
print SERVERCONF "keepalive 10 60\n";
print SERVERCONF "# Start as daemon\n";
print SERVERCONF "daemon $cgiparams{'NAME'}n2n\n";
print SERVERCONF "writepid /var/run/$cgiparams{'NAME'}n2n.pid\n";
print SERVERCONF "# Activate Management Interface and Port\n";
if ($cgiparams{'OVPN_MGMT'} eq '') {print SERVERCONF "management localhost $cgiparams{'DEST_PORT'}\n"}
else {print SERVERCONF "management localhost $cgiparams{'OVPN_MGMT'}\n"};
close(SERVERCONF);
}
###
# m.a.d net2net
###
if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && $cgiparams{'SIDE'} eq 'client')
{
my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'});
my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'});
my $tunmtu = '';
unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";}
unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}", 0770 or die "Unable to create dir $!";}
open(CLIENTCONF, ">${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Unable to open ${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf: $!";
flock CLIENTCONF, 2;
print CLIENTCONF "# IPFire rewritten n2n Open VPN Client Config by ummeegge und m.a.d\n";
print CLIENTCONF "#\n";
print CLIENTCONF "# User Security\n";
print CLIENTCONF "user nobody\n";
print CLIENTCONF "group nobody\n";
print CLIENTCONF "persist-tun\n";
print CLIENTCONF "persist-key\n";
print CLIENTCONF "script-security 2\n";
print CLIENTCONF "# IP/DNS for remote Server Gateway\n";
print CLIENTCONF "remote $cgiparams{'REMOTE'}\n";
print CLIENTCONF "float\n";
print CLIENTCONF "# IP adresses of the VPN Subnet\n";
print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n";
print CLIENTCONF "# Server Gateway Network\n";
print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n";
print CLIENTCONF "# tun Device\n";
print CLIENTCONF "dev tun\n";
print CLIENTCONF "# Port and Protokol\n";
print CLIENTCONF "port $cgiparams{'DEST_PORT'}\n";
if ($cgiparams{'PROTOCOL'} eq 'tcp') {
print CLIENTCONF "proto tcp-client\n";
print CLIENTCONF "# Packet size\n";
if ($cgiparams{'MTU'} eq '') {$tunmtu = '1400'} else {$tunmtu = $cgiparams{'MTU'}};
print CLIENTCONF "tun-mtu $tunmtu\n";
}
if ($cgiparams{'PROTOCOL'} eq 'udp') {
print CLIENTCONF "proto udp\n";
print CLIENTCONF "# Paketsize\n";
if ($cgiparams{'MTU'} eq '') {$tunmtu = '1500'} else {$tunmtu = $cgiparams{'MTU'}};
print CLIENTCONF "tun-mtu $tunmtu\n";
if ($cgiparams{'FRAGMENT'} ne '') {print CLIENTCONF "fragment $cgiparams{'FRAGMENT'}\n";}
if ($cgiparams{'MSSFIX'} eq 'on') {print CLIENTCONF "mssfix\n"; };
}
if ($cgiparams{'PMTU_DISCOVERY'} ne 'off') {
if(($cgiparams{'MSSFIX'} ne 'on') || ($cgiparams{'FRAGMENT'} eq '')) {
if ($cgiparams{'MTU'} eq '1500') {
print CLIENTCONF "mtu-disc $cgiparams{'PMTU_DISCOVERY'}\n";
}
}
}
print CLIENTCONF "ns-cert-type server\n";
print CLIENTCONF "# Auth. Client\n";
print CLIENTCONF "tls-client\n";
print CLIENTCONF "# Cipher\n";
print CLIENTCONF "cipher AES-256-CBC\n";
print CLIENTCONF "pkcs12 ${General::swroot}/ovpn/certs/$cgiparams{'NAME'}.p12\r\n";
if ($cgiparams{'COMPLZO'} eq 'on') {
print CLIENTCONF "# Enable Compression\n";
print CLIENTCONF "comp-lzo\r\n";
}
print CLIENTCONF "# Debug Level\n";
print CLIENTCONF "verb 3\n";
print CLIENTCONF "# Tunnel check\n";
print CLIENTCONF "keepalive 10 60\n";
print CLIENTCONF "# Start as daemon\n";
print CLIENTCONF "daemon $cgiparams{'NAME'}n2n\n";
print CLIENTCONF "writepid /var/run/$cgiparams{'NAME'}n2n.pid\n";
print CLIENTCONF "# Activate Management Interface and Port\n";
if ($cgiparams{'OVPN_MGMT'} eq '') {print CLIENTCONF "management localhost $cgiparams{'DEST_PORT'}\n"}
else {print CLIENTCONF "management localhost $cgiparams{'OVPN_MGMT'}\n"};
close(CLIENTCONF);
}
###
### Save main settings
###
if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq '' && $cgiparams{'KEY'} eq '') {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
#DAN do we really need (to to check) this value? Besides if we listen on blue and orange too,
#DAN this value has to leave.
if ($cgiparams{'ENABLED'} eq 'on'){
unless (&General::validfqdn($cgiparams{'VPN_IP'}) || &General::validip($cgiparams{'VPN_IP'})) {
$errormessage = $Lang::tr{'invalid input for hostname'};
goto SETTINGS_ERROR;
}
}
if ($cgiparams{'ENABLED'} eq 'on'){
&disallowreserved($cgiparams{'DDEST_PORT'},0,$cgiparams{'DPROTOCOL'},"dest");
}
if ($errormessage) { goto SETTINGS_ERROR; }
if ($cgiparams{'ENABLED'} eq 'on'){
&checkportfw(0,$cgiparams{'DDEST_PORT'},$cgiparams{'DPROTOCOL'},'0.0.0.0');
}
if ($errormessage) { goto SETTINGS_ERROR; }
if (! &General::validipandmask($cgiparams{'DOVPN_SUBNET'})) {
$errormessage = $Lang::tr{'ovpn subnet is invalid'};
goto SETTINGS_ERROR;
}
my @tmpovpnsubnet = split("\/",$cgiparams{'DOVPN_SUBNET'});
if (&General::IpInSubnet ( $netsettings{'RED_ADDRESS'},
$tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire RED Network $netsettings{'RED_ADDRESS'}";
goto SETTINGS_ERROR;
}
if (&General::IpInSubnet ( $netsettings{'GREEN_ADDRESS'},
$tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Green Network $netsettings{'GREEN_ADDRESS'}";
goto SETTINGS_ERROR;
}
if (&General::IpInSubnet ( $netsettings{'BLUE_ADDRESS'},
$tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Blue Network $netsettings{'BLUE_ADDRESS'}";
goto SETTINGS_ERROR;
}
if (&General::IpInSubnet ( $netsettings{'ORANGE_ADDRESS'},
$tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Orange Network $netsettings{'ORANGE_ADDRESS'}";
goto SETTINGS_ERROR;
}
open(ALIASES, "${General::swroot}/ethernet/aliases") or die 'Unable to open aliases file.';
while (<ALIASES>)
{
chomp($_);
my @tempalias = split(/\,/,$_);
if ($tempalias[1] eq 'on') {
if (&General::IpInSubnet ($tempalias[0] ,
$tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire alias entry $tempalias[0]";
}
}
}
close(ALIASES);
if ($errormessage ne ''){
goto SETTINGS_ERROR;
}
if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto SETTINGS_ERROR;
}
if ((length($cgiparams{'DMTU'})==0) || (($cgiparams{'DMTU'}) < 1000 )) {
$errormessage = $Lang::tr{'invalid mtu input'};
goto SETTINGS_ERROR;
}
unless (&General::validport($cgiparams{'DDEST_PORT'})) {
$errormessage = $Lang::tr{'invalid port'};
goto SETTINGS_ERROR;
}
$vpnsettings{'ENABLED_BLUE'} = $cgiparams{'ENABLED_BLUE'};
$vpnsettings{'ENABLED_ORANGE'} =$cgiparams{'ENABLED_ORANGE'};
$vpnsettings{'ENABLED'} = $cgiparams{'ENABLED'};
$vpnsettings{'VPN_IP'} = $cgiparams{'VPN_IP'};
#new settings for daemon
$vpnsettings{'DOVPN_SUBNET'} = $cgiparams{'DOVPN_SUBNET'};
$vpnsettings{'DDEVICE'} = $cgiparams{'DDEVICE'};
$vpnsettings{'DPROTOCOL'} = $cgiparams{'DPROTOCOL'};
$vpnsettings{'DDEST_PORT'} = $cgiparams{'DDEST_PORT'};
$vpnsettings{'DMTU'} = $cgiparams{'DMTU'};
$vpnsettings{'DCOMPLZO'} = $cgiparams{'DCOMPLZO'};
$vpnsettings{'DCIPHER'} = $cgiparams{'DCIPHER'};
#wrtie enable
if ( $vpnsettings{'ENABLED_BLUE'} eq 'on' ) {system("touch ${General::swroot}/ovpn/enable_blue 2>/dev/null");}else{system("unlink ${General::swroot}/ovpn/enable_blue 2>/dev/null");}
if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' ) {system("touch ${General::swroot}/ovpn/enable_orange 2>/dev/null");}else{system("unlink ${General::swroot}/ovpn/enable_orange 2>/dev/null");}
if ( $vpnsettings{'ENABLED'} eq 'on' ) {system("touch ${General::swroot}/ovpn/enable 2>/dev/null");}else{system("unlink ${General::swroot}/ovpn/enable 2>/dev/null");}
#new settings for daemon
&General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
&writeserverconf();#hier ok
SETTINGS_ERROR:
###
### Reset all step 2
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'reset'} && $cgiparams{'AREUSURE'} eq 'yes') {
my $file = '';
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
foreach my $key (keys %confighash) {
if ($confighash{$key}[4] eq 'cert') {
delete $confighash{$cgiparams{'$key'}};
}
}
while ($file = glob("${General::swroot}/ovpn/ca/*")) {
unlink $file
}
while ($file = glob("${General::swroot}/ovpn/certs/*")) {
unlink $file
}
while ($file = glob("${General::swroot}/ovpn/crls/*")) {
unlink $file
}
&cleanssldatabase();
if (open(FILE, ">${General::swroot}/ovpn/caconfig")) {
print FILE "";
close FILE;
}
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
#&writeserverconf();
###
### Reset all step 1
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'reset'}) {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
&Header::openbox('100%', 'LEFT', $Lang::tr{'are you sure'});
print <<END
<table><form method='post'><input type='hidden' name='AREUSURE' value='yes' />
<tr><td align='center'>
<b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:
$Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}
<tr><td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' />
<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td></tr>
</form></table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
exit (0);
###
### Upload CA Certificate
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload ca certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
if ($cgiparams{'CA_NAME'} !~ /^[a-zA-Z0-9]+$/) {
$errormessage = $Lang::tr{'name must only contain characters'};
goto UPLOADCA_ERROR;
}
if (length($cgiparams{'CA_NAME'}) >60) {
$errormessage = $Lang::tr{'name too long'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CA_NAME'} eq 'ca') {
$errormessage = $Lang::tr{'name is invalid'};
goto UPLOAD_CA_ERROR;
}
# Check if there is no other entry with this name
foreach my $key (keys %cahash) {
if ($cahash{$key}[0] eq $cgiparams{'CA_NAME'}) {
$errormessage = $Lang::tr{'a ca certificate with this name already exists'};
goto UPLOADCA_ERROR;
}
}
if (ref ($cgiparams{'FH'}) ne 'Fh') {
$errormessage = $Lang::tr{'there was no file upload'};
goto UPLOADCA_ERROR;
}
# Move uploaded ca to a temporary file
(my $fh, my $filename) = tempfile( );
if (copy ($cgiparams{'FH'}, $fh) != 1) {
$errormessage = $!;
goto UPLOADCA_ERROR;
}
my $temp = `/usr/bin/openssl x509 -text -in $filename`;
if ($temp !~ /CA:TRUE/i) {
$errormessage = $Lang::tr{'not a valid ca certificate'};
unlink ($filename);
goto UPLOADCA_ERROR;
} else {
move($filename, "${General::swroot}/ovpn/ca/$cgiparams{'CA_NAME'}cert.pem");
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
goto UPLOADCA_ERROR;
}
}
my $casubject = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/ca/$cgiparams{'CA_NAME'}cert.pem`;
$casubject =~ /Subject: (.*)[\n]/;
$casubject = $1;
$casubject =~ s+/Email+, E+;
$casubject =~ s/ ST=/ S=/;
$casubject = &Header::cleanhtml($casubject);
my $key = &General::findhasharraykey (\%cahash);
$cahash{$key}[0] = $cgiparams{'CA_NAME'};
$cahash{$key}[1] = $casubject;
&General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
# system('/usr/local/bin/ipsecctrl', 'R');
UPLOADCA_ERROR:
###
### Display ca certificate
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show ca certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem") {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
&Header::openbox('100%', 'LEFT', "$Lang::tr{'ca certificate'}:");
my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/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/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Download ca certificate
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download ca certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
print "Content-Type: application/octet-stream\r\n";
print "Content-Disposition: filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
print `/usr/bin/openssl x509 -in ${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem`;
exit(0);
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Remove ca certificate (step 2)
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'} && $cgiparams{'AREUSURE'} eq 'yes') {
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
foreach my $key (keys %confighash) {
my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem`;
if ($test =~ /: OK/) {
# Delete connection
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'D', $key);
# }
unlink ("${General::swroot}/ovpn//certs/$confighash{$key}[1]cert.pem");
unlink ("${General::swroot}/ovpn/certs/$confighash{$key}[1].p12");
delete $confighash{$key};
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
# &writeipsecfiles();
}
}
unlink ("${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
delete $cahash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
# system('/usr/local/bin/ipsecctrl', 'R');
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Remove ca certificate (step 1)
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
my $assignedcerts = 0;
if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
foreach my $key (keys %confighash) {
my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem`;
if ($test =~ /: OK/) {
$assignedcerts++;
}
}
if ($assignedcerts) {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
&Header::openbox('100%', 'LEFT', $Lang::tr{'are you sure'});
print <<END
<table><form method='post'><input type='hidden' name='AREUSURE' value='yes' />
<input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
<tr><td align='center'>
<b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>: $assignedcerts
$Lang::tr{'connections are associated with this ca. deleting the ca will delete these connections as well.'}
<tr><td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td></tr>
</form></table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
exit (0);
} else {
unlink ("${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
delete $cahash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
# system('/usr/local/bin/ipsecctrl', 'R');
}
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Display root certificate
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'} ||
$cgiparams{'ACTION'} eq $Lang::tr{'show host certificate'}) {
my $output;
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 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}/ovpn/ca/cacert.pem`;
} else {
&Header::openbox('100%', 'LEFT', "$Lang::tr{'host certificate'}:");
$output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/servercert.pem`;
}
$output = &Header::cleanhtml($output,"y");
print "<pre>$output</pre>\n";
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
###
### Download root certificate
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download root certificate'}) {
if ( -f "${General::swroot}/ovpn/ca/cacert.pem" ) {
print "Content-Type: application/octet-stream\r\n";
print "Content-Disposition: filename=cacert.pem\r\n\r\n";
print `/usr/bin/openssl x509 -in ${General::swroot}/ovpn/ca/cacert.pem`;
exit(0);
}
###
### Download host certificate
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download host certificate'}) {
if ( -f "${General::swroot}/ovpn/certs/servercert.pem" ) {
print "Content-Type: application/octet-stream\r\n";
print "Content-Disposition: filename=servercert.pem\r\n\r\n";
print `/usr/bin/openssl x509 -in ${General::swroot}/ovpn/certs/servercert.pem`;
exit(0);
}
###
### Form for generating a root certificate
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate root/host certificates'} ||
$cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
if (-f "${General::swroot}/ovpn/ca/cacert.pem") {
$errormessage = $Lang::tr{'valid root certificate already exists'};
$cgiparams{'ACTION'} = '';
goto ROOTCERT_ERROR;
}
if (($cgiparams{'ROOTCERT_HOSTNAME'} eq '') && -e "${General::swroot}/red/active") {
if (open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
my $ipaddr = <IPADDR>;
close IPADDR;
chomp ($ipaddr);
$cgiparams{'ROOTCERT_HOSTNAME'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
$cgiparams{'ROOTCERT_HOSTNAME'} = $ipaddr;
}
}
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
if (ref ($cgiparams{'FH'}) ne 'Fh') {
$errormessage = $Lang::tr{'there was no file upload'};
goto ROOTCERT_ERROR;
}
# Move uploaded certificate request to a temporary file
(my $fh, my $filename) = tempfile( );
if (copy ($cgiparams{'FH'}, $fh) != 1) {
$errormessage = $!;
goto ROOTCERT_ERROR;
}
# Create a temporary dirctory
my $tempdir = tempdir( CLEANUP => 1 );
# Extract the CA certificate from the file
my $pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
if ($pid) { # parent
if ($cgiparams{'P12_PASS'} ne '') {
print OPENSSL "$cgiparams{'P12_PASS'}\n";
}
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ($filename);
goto ROOTCERT_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'pkcs12', '-cacerts', '-nokeys',
'-in', $filename,
'-out', "$tempdir/cacert.pem")) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
unlink ($filename);
goto ROOTCERT_ERROR;
}
}
# Extract the Host certificate from the file
$pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
if ($pid) { # parent
if ($cgiparams{'P12_PASS'} ne '') {
print OPENSSL "$cgiparams{'P12_PASS'}\n";
}
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ($filename);
goto ROOTCERT_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'pkcs12', '-clcerts', '-nokeys',
'-in', $filename,
'-out', "$tempdir/hostcert.pem")) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
unlink ($filename);
goto ROOTCERT_ERROR;
}
}
# Extract the Host key from the file
$pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
if ($pid) { # parent
if ($cgiparams{'P12_PASS'} ne '') {
print OPENSSL "$cgiparams{'P12_PASS'}\n";
}
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ($filename);
goto ROOTCERT_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'pkcs12', '-nocerts',
'-nodes',
'-in', $filename,
'-out', "$tempdir/serverkey.pem")) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
unlink ($filename);
goto ROOTCERT_ERROR;
}
}
move("$tempdir/cacert.pem", "${General::swroot}/ovpn/ca/cacert.pem");
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
goto ROOTCERT_ERROR;
}
move("$tempdir/hostcert.pem", "${General::swroot}/ovpn/certs/servercert.pem");
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
goto ROOTCERT_ERROR;
}
move("$tempdir/serverkey.pem", "${General::swroot}/ovpn/certs/serverkey.pem");
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
goto ROOTCERT_ERROR;
}
goto ROOTCERT_SUCCESS;
} elsif ($cgiparams{'ROOTCERT_COUNTRY'} ne '') {
# Validate input since the form was submitted
if ($cgiparams{'ROOTCERT_ORGANIZATION'} eq ''){
$errormessage = $Lang::tr{'organization cant be empty'};
goto ROOTCERT_ERROR;
}
if (length($cgiparams{'ROOTCERT_ORGANIZATION'}) >60) {
$errormessage = $Lang::tr{'organization too long'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for organization'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_HOSTNAME'} eq ''){
$errormessage = $Lang::tr{'hostname cant be empty'};
goto ROOTCERT_ERROR;
}
unless (&General::validfqdn($cgiparams{'ROOTCERT_HOSTNAME'}) || &General::validip($cgiparams{'ROOTCERT_HOSTNAME'})) {
$errormessage = $Lang::tr{'invalid input for hostname'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'ROOTCERT_EMAIL'}))) {
$errormessage = $Lang::tr{'invalid input for e-mail address'};
goto ROOTCERT_ERROR;
}
if (length($cgiparams{'ROOTCERT_EMAIL'}) > 40) {
$errormessage = $Lang::tr{'e-mail address too long'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_OU'} ne '' && $cgiparams{'ROOTCERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for department'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_CITY'} ne '' && $cgiparams{'ROOTCERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for city'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_STATE'} ne '' && $cgiparams{'ROOTCERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for state or province'};
goto ROOTCERT_ERROR;
}
if ($cgiparams{'ROOTCERT_COUNTRY'} !~ /^[A-Z]*$/) {
$errormessage = $Lang::tr{'invalid input for country'};
goto ROOTCERT_ERROR;
}
# Copy the cgisettings to vpnsettings and save the configfile
$vpnsettings{'ROOTCERT_ORGANIZATION'} = $cgiparams{'ROOTCERT_ORGANIZATION'};
$vpnsettings{'ROOTCERT_HOSTNAME'} = $cgiparams{'ROOTCERT_HOSTNAME'};
$vpnsettings{'ROOTCERT_EMAIL'} = $cgiparams{'ROOTCERT_EMAIL'};
$vpnsettings{'ROOTCERT_OU'} = $cgiparams{'ROOTCERT_OU'};
$vpnsettings{'ROOTCERT_CITY'} = $cgiparams{'ROOTCERT_CITY'};
$vpnsettings{'ROOTCERT_STATE'} = $cgiparams{'ROOTCERT_STATE'};
$vpnsettings{'ROOTCERT_COUNTRY'} = $cgiparams{'ROOTCERT_COUNTRY'};
&General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
# Replace empty strings with a .
(my $ou = $cgiparams{'ROOTCERT_OU'}) =~ s/^\s*$/\./;
(my $city = $cgiparams{'ROOTCERT_CITY'}) =~ s/^\s*$/\./;
(my $state = $cgiparams{'ROOTCERT_STATE'}) =~ s/^\s*$/\./;
# refresh
#system ('/bin/touch', "${General::swroot}/ovpn/gencanow");
# Create the CA certificate
my $pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
if ($pid) { # parent
print OPENSSL "$cgiparams{'ROOTCERT_COUNTRY'}\n";
print OPENSSL "$state\n";
print OPENSSL "$city\n";
print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
print OPENSSL "$ou\n";
print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'} CA\n";
print OPENSSL "$cgiparams{'ROOTCERT_EMAIL'}\n";
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/ca/cakey.pem");
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
goto ROOTCERT_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'req', '-x509', '-nodes', '-rand', '/proc/interrupts:/proc/net/rt_cache',
'-days', '999999', '-newkey', 'rsa:2048',
'-keyout', "${General::swroot}/ovpn/ca/cakey.pem",
'-out', "${General::swroot}/ovpn/ca/cacert.pem",
'-config',"${General::swroot}/ovpn/openssl/ovpn.cnf")) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
goto ROOTCERT_ERROR;
}
}
# Create the Host certificate request
$pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
if ($pid) { # parent
print OPENSSL "$cgiparams{'ROOTCERT_COUNTRY'}\n";
print OPENSSL "$state\n";
print OPENSSL "$city\n";
print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
print OPENSSL "$ou\n";
print OPENSSL "$cgiparams{'ROOTCERT_HOSTNAME'}\n";
print OPENSSL "$cgiparams{'ROOTCERT_EMAIL'}\n";
print OPENSSL ".\n";
print OPENSSL ".\n";
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
goto ROOTCERT_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'req', '-nodes', '-rand', '/proc/interrupts:/proc/net/rt_cache',
'-newkey', 'rsa:1024',
'-keyout', "${General::swroot}/ovpn/certs/serverkey.pem",
'-out', "${General::swroot}/ovpn/certs/serverreq.pem",
'-extensions', 'server',
'-config', "${General::swroot}/ovpn/openssl/ovpn.cnf" )) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
unlink ("${General::swroot}/ovpn/ca/cakey.pem");
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
goto ROOTCERT_ERROR;
}
}
# Sign the host certificate request
system('/usr/bin/openssl', 'ca', '-days', '999999',
'-batch', '-notext',
'-in', "${General::swroot}/ovpn/certs/serverreq.pem",
'-out', "${General::swroot}/ovpn/certs/servercert.pem",
'-extensions', 'server',
'-config', "${General::swroot}/ovpn/openssl/ovpn.cnf");
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/ca/cakey.pem");
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/serverkey.pem");
unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
&newcleanssldatabase();
goto ROOTCERT_ERROR;
} else {
unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
&deletebackupcert();
}
# Create an empty CRL
system('/usr/bin/openssl', 'ca', '-gencrl',
'-out', "${General::swroot}/ovpn/crls/cacrl.pem",
'-config', "${General::swroot}/ovpn/openssl/ovpn.cnf" );
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/crls/cacrl.pem");
&cleanssldatabase();
goto ROOTCERT_ERROR;
# } else {
# &cleanssldatabase();
}
# Create Diffie Hellmann Parameter
system('/usr/bin/openssl', 'dhparam', '-rand', '/proc/interrupts:/proc/net/rt_cache',
'-out', "${General::swroot}/ovpn/ca/dh1024.pem",
'1024' );
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
unlink ("${General::swroot}/ovpn/certs/servercert.pem");
unlink ("${General::swroot}/ovpn/ca/cacert.pem");
unlink ("${General::swroot}/ovpn/crls/cacrl.pem");
unlink ("${General::swroot}/ovpn/ca/dh1024.pem");
&cleanssldatabase();
goto ROOTCERT_ERROR;
# } else {
# &cleanssldatabase();
}
goto ROOTCERT_SUCCESS;
}
ROOTCERT_ERROR:
if ($cgiparams{'ACTION'} ne '') {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
if ($errormessage) {
&Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
print "<class name='base'>$errormessage";
print " </class>";
&Header::closebox();
}
&Header::openbox('100%', 'LEFT', "$Lang::tr{'generate root/host certificates'}:");
print <<END
<form method='post' enctype='multipart/form-data'>
<table width='100%' border='0' cellspacing='1' cellpadding='0'>
<tr><td width='30%' class='base'>$Lang::tr{'organization name'}:</td>
<td width='35%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td>
<td width='35%' colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'ipfires hostname'}:</td>
<td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'your e-mail'}: <img src='/blob.gif' alt'*' /></td>
<td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'your department'}: <img src='/blob.gif' alt'*' /></td>
<td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'city'}: <img src='/blob.gif' alt'*' /></td>
<td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'state or province'}: <img src='/blob.gif' alt'*' /></td>
<td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'country'}:</td>
<td class='base'><select name='ROOTCERT_COUNTRY'>
END
;
foreach my $country (sort keys %{Countries::countries}) {
print "<option value='$Countries::countries{$country}'";
if ( $Countries::countries{$country} eq $cgiparams{'ROOTCERT_COUNTRY'} ) {
print " selected='selected'";
}
print ">$country</option>";
}
print <<END
</select></td>
<td colspan='2'> </td></tr>
<tr><td> </td>
<td><input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' /></td>
<td> </td><td> </td></tr>
<tr><td class='base' colspan='4' align='left'>
<img src='/blob.gif' valign='top' alt='*' /> $Lang::tr{'this field may be blank'}</td></tr>
<tr><td class='base' colspan='4' align='left'>
<b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:
$Lang::tr{'generating the root and host certificates may take a long time. it can take up to several minutes on older hardware. please be patient'}
</td></tr>
<tr><td colspan='4' bgcolor='#000000'><img src='/images/null.gif' width='1' height='1' border='0' /></td></tr>
<tr><td class='base' nowrap='nowrap'>$Lang::tr{'upload p12 file'}:</td>
<td nowrap='nowrap'><input type='file' name='FH' size='32'></td>
<td colspan='2'> </td></tr>
<tr><td class='base'>$Lang::tr{'pkcs12 file password'}: <img src='/blob.gif' alt='*' ></td>
<td class='base' nowrap='nowrap'><input type='password' name='P12_PASS' value='$cgiparams{'P12_PASS'}' size='32' /></td>
<td colspan='2'> </td></tr>
<tr><td> </td>
<td><input type='submit' name='ACTION' value='$Lang::tr{'upload p12 file'}' /></td>
<td colspan='2'> </td></tr>
<tr><td class='base' colspan='4' align='left'>
<img src='/blob.gif' valign='top' al='*' > $Lang::tr{'this field may be blank'}</td></tr>
</form></table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
exit(0)
}
ROOTCERT_SUCCESS:
system ("chmod 600 ${General::swroot}/ovpn/certs/serverkey.pem");
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLE_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'S');
# }
###
### Enable/Disable connection
###
###
# m.a.d net2net
###
}elsif ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
# my $n2nactive = '';
my $n2nactive = `/bin/ps ax|grep $confighash{$cgiparams{'KEY'}}[1]|grep -v grep|awk \'{print \$1}\'`;
if ($confighash{$cgiparams{'KEY'}}) {
if ($confighash{$cgiparams{'KEY'}}[0] eq 'off') {
$confighash{$cgiparams{'KEY'}}[0] = 'on';
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
system('/usr/local/bin/openvpnctrl', '-sn2n', $confighash{$cgiparams{'KEY'}}[1]);
}
} else {
$confighash{$cgiparams{'KEY'}}[0] = 'off';
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
if ($n2nactive ne ''){
system('/usr/local/bin/openvpnctrl', '-kn2n', $confighash{$cgiparams{'KEY'}}[1]);
}
} else {
$errormessage = $Lang::tr{'invalid key'};
}
}
}
###
### Download OpenVPN client package
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'dl client arch'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
my $file = '';
my $clientovpn = '';
my @fileholder;
my $tempdir = tempdir( CLEANUP => 1 );
my $zippath = "$tempdir/";
###
# m.a.d net2net
###
if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
my $zipname = "$confighash{$cgiparams{'KEY'}}[1]-Client.zip";
my $zippathname = "$zippath$zipname";
$clientovpn = "$confighash{$cgiparams{'KEY'}}[1].conf";
my @ovsubnettemp = split(/\./,$confighash{$cgiparams{'KEY'}}[27]);
my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
my $tunmtu = '';
my @remsubnet = split(/\//,$confighash{$cgiparams{'KEY'}}[8]);
my $n2nfragment = '';
open(CLIENTCONF, ">$tempdir/$clientovpn") or die "Unable to open tempfile: $!";
flock CLIENTCONF, 2;
my $zip = Archive::Zip->new();
print CLIENTCONF "# IPFire n2n Open VPN Client Config by ummeegge und m.a.d\n";
print CLIENTCONF "# \n";
print CLIENTCONF "# User Security\n";
print CLIENTCONF "user nobody\n";
print CLIENTCONF "group nobody\n";
print CLIENTCONF "persist-tun\n";
print CLIENTCONF "persist-key\n";
print CLIENTCONF "script-security 2\n";
print CLIENTCONF "# IP/DNS for remote Server Gateway\n";
print CLIENTCONF "remote $vpnsettings{'VPN_IP'}\n";
print CLIENTCONF "float\n";
print CLIENTCONF "# IP adresses of the VPN Subnet\n";
print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n";
print CLIENTCONF "# Server Gateway Network\n";
print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n";
print CLIENTCONF "# tun Device\n";
print CLIENTCONF "dev $vpnsettings{'DDEVICE'}\n";
print CLIENTCONF "# Port and Protokoll\n";
print CLIENTCONF "port $confighash{$cgiparams{'KEY'}}[29]\n";
if ($confighash{$cgiparams{'KEY'}}[28] eq 'tcp') {
print CLIENTCONF "proto tcp-client\n";
print CLIENTCONF "# Packet size\n";
if ($confighash{$cgiparams{'KEY'}}[31] eq '') {$tunmtu = '1400'} else {$tunmtu = $confighash{$cgiparams{'KEY'}}[31]};
print CLIENTCONF "tun-mtu $tunmtu\n";
}
if ($confighash{$cgiparams{'KEY'}}[28] eq 'udp') {
print CLIENTCONF "proto udp\n";
print CLIENTCONF "# Paketsize\n";
if ($confighash{$cgiparams{'KEY'}}[31] eq '') {$tunmtu = '1500'} else {$tunmtu = $confighash{$cgiparams{'KEY'}}[31]};
print CLIENTCONF "tun-mtu $tunmtu\n";
if ($confighash{$cgiparams{'KEY'}}[24] ne '') {print CLIENTCONF "fragment $confighash{$cgiparams{'KEY'}}[24]\n";}
if ($confighash{$cgiparams{'KEY'}}[23] eq 'on') {print CLIENTCONF "mssfix\n";}
}
if ($confighash{$cgiparams{'KEY'}}[32] ne 'off') {
if (($confighash{$cgiparams{'KEY'}}[23] ne 'on') || ($confighash{$cgiparams{'KEY'}}[24] eq '')) {
if ($tunmtu eq '1500' ) {
print CLIENTCONF "mtu-disc $confighash{$cgiparams{'KEY'}}[32]\n";
}
}
}
print CLIENTCONF "ns-cert-type server\n";
print CLIENTCONF "# Auth. Client\n";
print CLIENTCONF "tls-client\n";
print CLIENTCONF "# Cipher\n";
print CLIENTCONF "cipher AES-256-CBC\n";
if ($confighash{$cgiparams{'KEY'}}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12") {
print CLIENTCONF "pkcs12 ${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12\r\n";
$zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12", "$confighash{$cgiparams{'KEY'}}[1].p12") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1].p12\n";
}
if ($confighash{$cgiparams{'KEY'}}[30] eq 'on') {
print CLIENTCONF "# Enable Compression\n";
print CLIENTCONF "comp-lzo\r\n";
}
print CLIENTCONF "# Debug Level\n";
print CLIENTCONF "verb 3\n";
print CLIENTCONF "# Tunnel check\n";
print CLIENTCONF "keepalive 10 60\n";
print CLIENTCONF "# Start as daemon\n";
print CLIENTCONF "daemon $confighash{$cgiparams{'KEY'}}[1]n2n\n";
print CLIENTCONF "writepid /var/run/$confighash{$cgiparams{'KEY'}}[1]n2n.pid\n";
print CLIENTCONF "# Activate Management Interface and Port\n";
if ($confighash{$cgiparams{'KEY'}}[22] eq '') {print CLIENTCONF "management localhost $confighash{$cgiparams{'KEY'}}[29]\n"}
else {print CLIENTCONF "management localhost $confighash{$cgiparams{'KEY'}}[22]\n"};
print CLIENTCONF "# remsub $confighash{$cgiparams{'KEY'}}[11]\n";
close(CLIENTCONF);
$zip->addFile( "$tempdir/$clientovpn", $clientovpn) or die "Can't add file $clientovpn\n";
my $status = $zip->writeToFileNamed($zippathname);
open(DLFILE, "<$zippathname") or die "Unable to open $zippathname: $!";
@fileholder = <DLFILE>;
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$zipname\n\n";
print @fileholder;
exit (0);
}
else
{
my $zipname = "$confighash{$cgiparams{'KEY'}}[1]-TO-IPFire.zip";
my $zippathname = "$zippath$zipname";
$clientovpn = "$confighash{$cgiparams{'KEY'}}[1]-TO-IPFire.ovpn";
###
# m.a.d net2net
###
open(CLIENTCONF, ">$tempdir/$clientovpn") or die "Unable to open tempfile: $!";
flock CLIENTCONF, 2;
my $zip = Archive::Zip->new();
print CLIENTCONF "#OpenVPN Server conf\r\n";
print CLIENTCONF "tls-client\r\n";
print CLIENTCONF "client\r\n";
print CLIENTCONF "dev $vpnsettings{'DDEVICE'}\r\n";
print CLIENTCONF "proto $vpnsettings{'DPROTOCOL'}\r\n";
# Check if we are using fragment, mssfix or mtu-disc and set MTU to 1500
# or use configured value.
if ($vpnsettings{FRAGMENT} ne '' && $vpnsettings{DPROTOCOL} ne 'tcp' )
{ print CLIENTCONF "$vpnsettings{'DDEVICE'}-mtu 1500\n"; }
elsif ($vpnsettings{MSSFIX} eq 'on')
{ print CLIENTCONF "$vpnsettings{'DDEVICE'}-mtu 1500\n"; }
elsif ($vpnsettings{PMTU_DISCOVERY} ne 'off')
{ print CLIENTCONF "$vpnsettings{'DDEVICE'}-mtu 1500\n"; }
else
{ print CLIENTCONF "$vpnsettings{'DDEVICE'}-mtu $vpnsettings{'DMTU'}\r\n"; }
if ( $vpnsettings{'ENABLED'} eq 'on'){
print CLIENTCONF "remote $vpnsettings{'VPN_IP'} $vpnsettings{'DDEST_PORT'}\r\n";
if ( $vpnsettings{'ENABLED_BLUE'} eq 'on' && (&haveBlueNet())){
print CLIENTCONF "#Coment the above line and uncoment the next line, if you want to connect on the Blue interface\r\n";
print CLIENTCONF ";remote $netsettings{'BLUE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
}
if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
print CLIENTCONF "#Coment the above line and uncoment the next line, if you want to connect on the Orange interface\r\n";
print CLIENTCONF ";remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
}
} elsif ( $vpnsettings{'ENABLED_BLUE'} eq 'on' && (&haveBlueNet())){
print CLIENTCONF "remote $netsettings{'BLUE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
print CLIENTCONF "#Coment the above line and uncoment the next line, if you want to connect on the Orange interface\r\n";
print CLIENTCONF ";remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
}
} elsif ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
print CLIENTCONF "remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
}
if ($confighash{$cgiparams{'KEY'}}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12") {
print CLIENTCONF "pkcs12 $confighash{$cgiparams{'KEY'}}[1].p12\r\n";
$zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12", "$confighash{$cgiparams{'KEY'}}[1].p12") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1].p12\n";
} else {
print CLIENTCONF "ca cacert.pem\r\n";
print CLIENTCONF "cert $confighash{$cgiparams{'KEY'}}[1]cert.pem\r\n";
print CLIENTCONF "key $confighash{$cgiparams{'KEY'}}[1].key\r\n";
$zip->addFile( "${General::swroot}/ovpn/ca/cacert.pem", "cacert.pem") or die "Can't add file cacert.pem\n";
$zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem", "$confighash{$cgiparams{'KEY'}}[1]cert.pem") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1]cert.pem\n";
}
print CLIENTCONF "cipher $vpnsettings{DCIPHER}\r\n";
if ($vpnsettings{DCOMPLZO} eq 'on') {
print CLIENTCONF "comp-lzo\r\n";
}
print CLIENTCONF "verb 3\r\n";
print CLIENTCONF "ns-cert-type server\r\n";
print CLIENTCONF "tls-remote $vpnsettings{ROOTCERT_HOSTNAME}\r\n";
if ($vpnsettings{MSSFIX} eq 'on') {
print CLIENTCONF "mssfix\r\n";
}
if ($vpnsettings{FRAGMENT} ne '' && $vpnsettings{DPROTOCOL} ne 'tcp' ) {
print CLIENTCONF "fragment $vpnsettings{'FRAGMENT'}\r\n";
}
if ($vpnsettings{PMTU_DISCOVERY} ne 'off') {
if(($vpnsettings{MSSFIX} ne 'on') || ($vpnsettings{FRAGMENT} eq '')) {
print CLIENTCONF "mtu-disc $vpnsettings{'PMTU_DISCOVERY'}\n";
}
}
close(CLIENTCONF);
$zip->addFile( "$tempdir/$clientovpn", $clientovpn) or die "Can't add file $clientovpn\n";
my $status = $zip->writeToFileNamed($zippathname);
open(DLFILE, "<$zippathname") or die "Unable to open $zippathname: $!";
@fileholder = <DLFILE>;
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$zipname\n\n";
print @fileholder;
exit (0);
}
###
### Remove connection
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}) {
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'});
# }
#
my $temp = `/usr/bin/openssl ca -revoke ${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem -config ${General::swroot}/ovpn/openssl/ovpn.cnf`;
###
# m.a.d net2net
###
if ($confighash{$cgiparams{'KEY'}}[3] eq 'net') {
my $conffile = glob("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]/$confighash{$cgiparams{'KEY'}}[1].conf");
my $certfile = glob("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
unlink ($certfile) or die "Removing $certfile fail: $!";
unlink ($conffile) or die "Removing $conffile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]") || die "Kann Verzeichnis nicht loeschen: $!";
}
unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
delete $confighash{$cgiparams{'KEY'}};
my $temp2 = `/usr/bin/openssl ca -gencrl -out ${General::swroot}/ovpn/crls/cacrl.pem -config ${General::swroot}/ovpn/openssl/ovpn.cnf`;
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
#&writeserverconf();
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Download PKCS12 file
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download pkcs12 file'}) {
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
print "Content-Disposition: filename=" . $confighash{$cgiparams{'KEY'}}[1] . ".p12\r\n";
print "Content-Type: application/octet-stream\r\n\r\n";
print `/bin/cat ${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12`;
exit (0);
###
### Display certificate
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ( -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
&Header::openbox('100%', 'LEFT', "$Lang::tr{'certificate'}:");
my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/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/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
}
###
### Display Certificate Revoke List
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show crl'}) {
# &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ( -f "${General::swroot}/ovpn/crls/cacrl.pem") {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
&Header::openbox('100%', 'LEFT', "$Lang::tr{'crl'}:");
my $output = `/usr/bin/openssl crl -text -noout -in ${General::swroot}/ovpn/crls/cacrl.pem`;
$output = &Header::cleanhtml($output,"y");
print "<pre>$output</pre>\n";
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
}
###
### Advanced Server Settings
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'advanced server'}) {
%cgiparams = ();
%cahash = ();
%confighash = ();
&General::readhash("${General::swroot}/ovpn/settings", \%cgiparams);
read_routepushfile;
# if ($cgiparams{'CLIENT2CLIENT'} eq '') {
# $cgiparams{'CLIENT2CLIENT'} = 'on';
# }
ADV_ERROR:
if ($cgiparams{'MAX_CLIENTS'} eq '') {
$cgiparams{'MAX_CLIENTS'} = '100';
}
if ($cgiparams{'KEEPALIVE_1'} eq '') {
$cgiparams{'KEEPALIVE_1'} = '10';
}
if ($cgiparams{'KEEPALIVE_2'} eq '') {
$cgiparams{'KEEPALIVE_2'} = '60';
}
if ($cgiparams{'LOG_VERB'} eq '') {
$cgiparams{'LOG_VERB'} = '3';
}
$checked{'CLIENT2CLIENT'}{'off'} = '';
$checked{'CLIENT2CLIENT'}{'on'} = '';
$checked{'CLIENT2CLIENT'}{$cgiparams{'CLIENT2CLIENT'}} = 'CHECKED';
$checked{'REDIRECT_GW_DEF1'}{'off'} = '';
$checked{'REDIRECT_GW_DEF1'}{'on'} = '';
$checked{'REDIRECT_GW_DEF1'}{$cgiparams{'REDIRECT_GW_DEF1'}} = 'CHECKED';
$selected{'ENGINES'}{$cgiparams{'ENGINES'}} = 'SELECTED';
$checked{'MSSFIX'}{'off'} = '';
$checked{'MSSFIX'}{'on'} = '';
$checked{'MSSFIX'}{$cgiparams{'MSSFIX'}} = 'CHECKED';
$checked{'PMTU_DISCOVERY'}{$cgiparams{'PMTU_DISCOVERY'}} = 'checked=\'checked\'';
$selected{'LOG_VERB'}{'1'} = '';
$selected{'LOG_VERB'}{'2'} = '';
$selected{'LOG_VERB'}{'3'} = '';
$selected{'LOG_VERB'}{'4'} = '';
$selected{'LOG_VERB'}{'5'} = '';
$selected{'LOG_VERB'}{'6'} = '';
$selected{'LOG_VERB'}{'7'} = '';
$selected{'LOG_VERB'}{'8'} = '';
$selected{'LOG_VERB'}{'9'} = '';
$selected{'LOG_VERB'}{'10'} = '';
$selected{'LOG_VERB'}{'11'} = '';
$selected{'LOG_VERB'}{'0'} = '';
$selected{'LOG_VERB'}{$cgiparams{'LOG_VERB'}} = 'SELECTED';
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'status ovpn'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
if ($errormessage) {
&Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
print "<class name='base'>$errormessage\n";
print " </class>\n";
&Header::closebox();
}
&Header::openbox('100%', 'LEFT', $Lang::tr{'advanced server'});
print <<END
<form method='post' enctype='multipart/form-data'>
<table width='100%'>
<tr>
<td colspan='4'><b>$Lang::tr{'dhcp-options'}</b></td>
</tr>
<tr>
<td width='25%'></td> <td width='20%'> </td><td width='25%'> </td><td width='30%'></td>
</tr>
<tr>
<td class='base'>Domain</td>
<td><input type='TEXT' name='DHCP_DOMAIN' value='$cgiparams{'DHCP_DOMAIN'}' size='30' /></td>
</tr>
<tr>
<td class='base'>DNS</td>
<td><input type='TEXT' name='DHCP_DNS' value='$cgiparams{'DHCP_DNS'}' size='30' /></td>
</tr>
<tr>
<td class='base'>WINS</td>
<td><input type='TEXT' name='DHCP_WINS' value='$cgiparams{'DHCP_WINS'}' size='30' /></td>
</tr>
<tr>
<td colspan='4'><b>$Lang::tr{'ovpn routes push options'}</b></td>
</tr>
<tr>
<td class='base'>$Lang::tr{'ovpn routes push'}</td>
<td colspan='2'>
<textarea name='ROUTES_PUSH' cols='26' rows='6' wrap='off'>
END
;
if ($cgiparams{'ROUTES_PUSH'} ne '')
{
print $cgiparams{'ROUTES_PUSH'};
}
print <<END
</textarea></td>
</tr>
</tr>
</table>
<hr size='1'>
<table width='100%'>
<tr>
<td class'base'><b>$Lang::tr{'misc-options'}</b></td>
</tr>
<tr>
<td width='20%'></td> <td width='15%'> </td><td width='15%'> </td><td width='15%'></td><td width='35%'></td>
</tr>
<tr>
<td class='base'>Client-To-Client</td>
<td><input type='checkbox' name='CLIENT2CLIENT' $checked{'CLIENT2CLIENT'}{'on'} /></td>
</tr>
<tr>
<td class='base'>Redirect-Gateway def1</td>
<td><input type='checkbox' name='REDIRECT_GW_DEF1' $checked{'REDIRECT_GW_DEF1'}{'on'} /></td>
</tr>
<tr>
<td class='base'>Max-Clients</td>
<td><input type='text' name='MAX_CLIENTS' value='$cgiparams{'MAX_CLIENTS'}' size='10' /></td>
</tr>
<tr>
<td class='base'>Keppalive <br />
(ping/ping-restart)</td>
<td><input type='TEXT' name='KEEPALIVE_1' value='$cgiparams{'KEEPALIVE_1'}' size='10' /></td>
<td><input type='TEXT' name='KEEPALIVE_2' value='$cgiparams{'KEEPALIVE_2'}' size='10' /></td>
</tr>
<tr>
<td class='base'>fragment <br></td>
<td><input type='TEXT' name='FRAGMENT' value='$cgiparams{'FRAGMENT'}' size='10' /></td>
<td>Default: <span class="base">1300</span></td>
</tr>
<tr>
<td class='base'>mssfix</td>
<td><input type='checkbox' name='MSSFIX' $checked{'MSSFIX'}{'on'} /></td>
<td>Default: on</td>
</tr>
<tr>
<td class='base'>$Lang::tr{'ovpn mtu-disc'}</td>
<td><input type='radio' name='PMTU_DISCOVERY' value='yes' $checked{'PMTU_DISCOVERY'}{'yes'} /> $Lang::tr{'ovpn mtu-disc yes'}</td>
<td><input type='radio' name='PMTU_DISCOVERY' value='maybe' $checked{'PMTU_DISCOVERY'}{'maybe'} /> $Lang::tr{'ovpn mtu-disc maybe'}</td>
<td><input type='radio' name='PMTU_DISCOVERY' value='no' $checked{'PMTU_DISCOVERY'}{'no'} /> $Lang::tr{'ovpn mtu-disc no'}</td>
<td><input type='radio' name='PMTU_DISCOVERY' value='off' $checked{'PMTU_DISCOVERY'}{'off'} /> $Lang::tr{'ovpn mtu-disc off'}</td>
</tr>
</table>
<!--
<hr size='1'>
<table width='100%'>
<tr>
<td class'base'><b>Crypto-Engines</b></td>
</tr>
<tr>
<td width='15%'></td> <td width='30%'> </td><td width='25%'> </td><td width='30%'></td>
</tr>
<tr><td class='base'>Engines:</td>
<td><select name='ENGINES'><option value="none" $selected{'ENGINES'}{'none'}>none</option>
<option value="cryptodev" $selected{'ENGINES'}{'cryptodev'}>cryptodev</option>
<option value="padlock" $selected{'ENGINES'}{'padlock'}>padlock</option>
</select>
</td>
</table>
-->
<hr size='1'>
<table width='100%'>
<tr>
<td class'base'><b>$Lang::tr{'log-options'}</b></td>
</tr>
<tr>
<td width='15%'></td> <td width='30%'> </td><td width='25%'> </td><td width='30%'></td>
</tr>
<tr><td class='base'>VERB</td>
<td><select name='LOG_VERB'><option value='1' $selected{'LOG_VERB'}{'1'}>1</option>
<option value='2' $selected{'LOG_VERB'}{'2'}>2</option>
<option value='3' $selected{'LOG_VERB'}{'3'}>3</option>
<option value='4' $selected{'LOG_VERB'}{'4'}>4</option>
<option value='5' $selected{'LOG_VERB'}{'5'}>5</option>
<option value='6' $selected{'LOG_VERB'}{'6'}>6</option>
<option value='7' $selected{'LOG_VERB'}{'7'}>7</option>
<option value='8' $selected{'LOG_VERB'}{'8'}>8</option>
<option value='9' $selected{'LOG_VERB'}{'9'}>9</option>
<option value='10' $selected{'LOG_VERB'}{'10'}>10</option>
<option value='11' $selected{'LOG_VERB'}{'11'}>11</option>
<option value='0' $selected{'LOG_VERB'}{'0'}>0</option></select></td>
</table>
<hr size='1'>
<table width='100%'>
<tr>
<td> </td>
<td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'save-adv-options'}' /></td>
<td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'cancel-adv-options'}' /></td>
<td> </td>
</tr>
</table>
</form>
END
;
&Header::closebox();
# print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
###
### Openvpn Connections Statistics
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'ovpn con stat'}) {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'ovpn con stat'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
&Header::openbox('100%', 'LEFT', $Lang::tr{'ovpn con stat'});
#
# <td><b>$Lang::tr{'protocol'}</b></td>
# protocol temp removed
print <<END
<table width='100%' border='0' cellpadding='2' cellspacing='0'>
<tr>
<td><b>$Lang::tr{'common name'}</b></td>
<td><b>$Lang::tr{'real address'}</b></td>
<td><b>$Lang::tr{'virtual address'}</b></td>
<td><b>$Lang::tr{'loged in at'}</b></td>
<td><b>$Lang::tr{'bytes sent'}</b></td>
<td><b>$Lang::tr{'bytes received'}</b></td>
<td><b>$Lang::tr{'last activity'}</b></td>
</tr>
END
;
my $filename = "/var/log/ovpnserver.log";
open(FILE, $filename) or die 'Unable to open config file.';
my @current = <FILE>;
close(FILE);
my @users =();
my $status;
my $uid = 0;
my $cn;
my @match = ();
my $proto = "udp";
my $address;
my %userlookup = ();
foreach my $line (@current)
{
chomp($line);
if ( $line =~ /^Updated,(.+)/){
@match = split( /^Updated,(.+)/, $line);
$status = $match[1];
}
#gian
if ( $line =~ /^(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(\d+),(\d+),(.+)/) {
@match = split(m/^(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(\d+),(\d+),(.+)/, $line);
if ($match[1] ne "Common Name") {
$cn = $match[1];
$userlookup{$match[2]} = $uid;
$users[$uid]{'CommonName'} = $match[1];
$users[$uid]{'RealAddress'} = $match[2];
$users[$uid]{'BytesReceived'} = &sizeformat($match[3]);
$users[$uid]{'BytesSent'} = &sizeformat($match[4]);
$users[$uid]{'Since'} = $match[5];
$users[$uid]{'Proto'} = $proto;
$uid++;
}
}
if ( $line =~ /^(\d+\.\d+\.\d+\.\d+),(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(.+)/) {
@match = split(m/^(\d+\.\d+\.\d+\.\d+),(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(.+)/, $line);
if ($match[1] ne "Virtual Address") {
$address = $match[3];
#find the uid in the lookup table
$uid = $userlookup{$address};
$users[$uid]{'VirtualAddress'} = $match[1];
$users[$uid]{'LastRef'} = $match[4];
}
}
}
my $user2 = @users;
if ($user2 >= 1){
for (my $idx = 1; $idx <= $user2; $idx++){
if ($idx % 2) {
print "<tr bgcolor='$color{'color20'}'>\n";
} else {
print "<tr bgcolor='$color{'color22'}'>\n";
}
print "<td align='left'>$users[$idx-1]{'CommonName'}</td>";
print "<td align='left'>$users[$idx-1]{'RealAddress'}</td>";
print "<td align='left'>$users[$idx-1]{'VirtualAddress'}</td>";
print "<td align='left'>$users[$idx-1]{'Since'}</td>";
print "<td align='left'>$users[$idx-1]{'BytesSent'}</td>";
print "<td align='left'>$users[$idx-1]{'BytesReceived'}</td>";
print "<td align='left'>$users[$idx-1]{'LastRef'}</td>";
# print "<td align='left'>$users[$idx-1]{'Proto'}</td>";
}
}
print "</table>";
print <<END
<table width='100%' border='0' cellpadding='2' cellspacing='0'>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td align='center' >$Lang::tr{'the statistics were last updated at'} <b>$status</b></td></tr>
</table>
END
;
&Header::closebox();
print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
&Header::closebigbox();
&Header::closepage();
exit(0);
###
### Download Certificate
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download certificate'}) {
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ( -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
print "Content-Disposition: filename=" . $confighash{$cgiparams{'KEY'}}[1] . "cert.pem\r\n";
print "Content-Type: application/octet-stream\r\n\r\n";
print `/bin/cat ${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem`;
exit (0);
}
###
### Enable/Disable connection
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}) {
if ($confighash{$cgiparams{'KEY'}}[0] eq 'off') {
$confighash{$cgiparams{'KEY'}}[0] = 'on';
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
#&writeserverconf();
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
# }
} else {
$confighash{$cgiparams{'KEY'}}[0] = 'off';
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'});
# }
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
#&writeserverconf();
}
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Restart connection
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'restart'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}) {
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
# }
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
### Remove connection
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove'}) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}) {
# if ($vpnsettings{'ENABLED'} eq 'on' ||
# $vpnsettings{'ENABLED_BLUE'} eq 'on') {
# system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'});
# }
unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
delete $confighash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
#&writeserverconf();
} else {
$errormessage = $Lang::tr{'invalid key'};
}
#test33
###
### Choose between adding a host-net or net-net connection
###
###
# m.a.d net2net
###
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'add'} && $cgiparams{'TYPE'} eq '') {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', '');
&Header::openbox('100%', 'LEFT', $Lang::tr{'connection type'});
if ( -s "${General::swroot}/ovpn/settings") {
print <<END
<b>$Lang::tr{'connection type'}:</b><br />
<table><form method='post' ENCTYPE="multipart/form-data">
<tr><td><input type='radio' name='TYPE' value='host' checked /></td>
<td class='base'>$Lang::tr{'host to net vpn'}</td></tr>
<tr><td><input type='radio' name='TYPE' value='net' /></td>
<td class='base'>$Lang::tr{'net to net vpn'}</td></tr>
<tr><td><input type='radio' name='TYPE' value='net2net' /></td>
<td class='base'>$Lang::tr{'net to net vpn'} (Upload Client Package)</td></tr>
<tr><td> </td><td class='base'><input type='file' name='FH' size='30'></td></tr>
<tr><td> </td><td>Import Connection Name <img src='/blob.gif' /></td></tr>
<tr><td> </td><td class='base'><input type='text' name='n2nname' size='30'><td class='base'>Default : Client Packagename</td></td></tr>
<tr><td colspan='3'><hr /></td></tr>
<tr><td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td></tr>
<tr><td> </td></tr>
<tr><td class='base' colspan='3' align='left'><img src='/blob.gif' alt='*' /> $Lang::tr{'this field may be blank'}</td></tr>
</form></table>
END
;
} else {
print <<END
<b>$Lang::tr{'connection type'}:</b><br />
<table><form method='post' ENCTYPE="multipart/form-data">
<tr><td><input type='radio' name='TYPE' value='host' checked /></td> <td class='base'>$Lang::tr{'host to net vpn'}</td></tr>
<tr><td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td></tr>
</form></table>
END
;
}
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
exit (0);
###
# m.a.d net2net
###
} elsif (($cgiparams{'ACTION'} eq $Lang::tr{'add'}) && ($cgiparams{'TYPE'} eq 'net2net')){
my @firen2nconf;
my @confdetails;
my $uplconffilename ='';
my $uplconffilename2 ='';
my $uplp12name = '';
my $uplp12name2 = '';
my @rem_subnet;
my @rem_subnet2;
my @tmposupnet3;
my $key;
my @n2nname;
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
# Check if a file is uploaded
if (ref ($cgiparams{'FH'}) ne 'Fh') {
$errormessage = $Lang::tr{'there was no file upload'};
goto N2N_ERROR;
}
# Move uploaded IPfire n2n package to temporary file
(my $fh, my $filename) = tempfile( );
if (copy ($cgiparams{'FH'}, $fh) != 1) {
$errormessage = $!;
goto N2N_ERROR;
}
my $zip = Archive::Zip->new();
my $zipName = $filename;
my $status = $zip->read( $zipName );
if ($status != AZ_OK) {
$errormessage = "Read of $zipName failed\n";
goto N2N_ERROR;
}
my $tempdir = tempdir( CLEANUP => 1 );
my @files = $zip->memberNames();
for(@files) {
$zip->extractMemberWithoutPaths($_,"$tempdir/$_");
}
my $countfiles = @files;
# Check if we have not more then 2 files
if ( $countfiles == 2){
foreach (@files){
if ( $_ =~ /.conf$/){
$uplconffilename = $_;
}
if ( $_ =~ /.p12$/){
$uplp12name = $_;
}
}
if (($uplconffilename eq '') || ($uplp12name eq '')){
$errormessage = "Either no *.conf or no *.p12 file found\n";
goto N2N_ERROR;
}
open(FILE, "$tempdir/$uplconffilename") or die 'Unable to open*.conf file';
@firen2nconf = <FILE>;
close (FILE);
chomp(@firen2nconf);
} else {
$errormessage = "Filecount does not match only 2 files are allowed\n";
goto N2N_ERROR;
}
###
# m.a.d net2net
###
if ($cgiparams{'n2nname'} ne ''){
$uplconffilename2 = "$cgiparams{'n2nname'}.conf";
$uplp12name2 = "$cgiparams{'n2nname'}.p12";
$n2nname[0] = $cgiparams{'n2nname'};
my @n2nname2 = split(/\./,$uplconffilename);
$n2nname2[0] =~ s/\n|\r//g;
my $input1 = "${General::swroot}/ovpn/certs/$uplp12name";
my $output1 = "${General::swroot}/ovpn/certs/$uplp12name2";
my $input2 = "$n2nname2[0]n2n";
my $output2 = "$n2nname[0]n2n";
my $filename = "$tempdir/$uplconffilename";
open(FILE, "< $filename") or die 'Unable to open config file.';
my @current = <FILE>;
close(FILE);
foreach (@current) {s/$input1/$output1/g;}
foreach (@current) {s/$input2/$output2/g;}
open (OUT, "> $filename") || die 'Unable to open config file.';
print OUT @current;
close OUT;
}else{
$uplconffilename2 = $uplconffilename;
$uplp12name2 = $uplp12name;
@n2nname = split(/\./,$uplconffilename);
$n2nname[0] =~ s/\n|\r//g;
}
unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";}
unless(-d "${General::swroot}/ovpn/n2nconf/$n2nname[0]"){mkdir "${General::swroot}/ovpn/n2nconf/$n2nname[0]", 0770 or die "Unable to create dir $!";}
move("$tempdir/$uplconffilename", "${General::swroot}/ovpn/n2nconf/$n2nname[0]/$uplconffilename2");
if ($? ne 0) {
$errormessage = "*.conf move failed: $!";
unlink ($filename);
goto N2N_ERROR;
}
move("$tempdir/$uplp12name", "${General::swroot}/ovpn/certs/$uplp12name2");
chmod 0600, "${General::swroot}/ovpn/certs/$uplp12name";
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
goto N2N_ERROR;
}
my $complzoactive;
my $mssfixactive;
my $n2nfragment;
my @n2nmtudisc = split(/ /, (grep { /^mtu-disc/ } @firen2nconf)[0]);;
my @n2nproto2 = split(/ /, (grep { /^proto/ } @firen2nconf)[0]);
my @n2nproto = split(/-/, $n2nproto2[1]);
my @n2nport = split(/ /, (grep { /^port/ } @firen2nconf)[0]);
my @n2ntunmtu = split(/ /, (grep { /^tun-mtu/ } @firen2nconf)[0]);
my @n2ncomplzo = grep { /^comp-lzo/ } @firen2nconf;
if ($n2ncomplzo[0] =~ /comp-lzo/){$complzoactive = "on";} else {$complzoactive = "off";}
my @n2nmssfix = grep { /^mssfix/ } @firen2nconf;
if ($n2nmssfix[0] =~ /mssfix/){$mssfixactive = "on";} else {$mssfixactive = "off";}
#my @n2nmssfix = split(/ /, (grep { /^mssfix/ } @firen2nconf)[0]);
my @n2nfragment = split(/ /, (grep { /^fragment/ } @firen2nconf)[0]);
my @n2nremote = split(/ /, (grep { /^remote/ } @firen2nconf)[0]);
my @n2novpnsuball = split(/ /, (grep { /^ifconfig/ } @firen2nconf)[0]);
my @n2novpnsub = split(/\./,$n2novpnsuball[1]);
my @n2nremsub = split(/ /, (grep { /^route/ } @firen2nconf)[0]);
my @n2nmgmt = split(/ /, (grep { /^management/ } @firen2nconf)[0]);
my @n2nlocalsub = split(/ /, (grep { /^# remsub/ } @firen2nconf)[0]);
###
# m.a.d delete CR and LF from arrays for this chomp doesnt work
###
$n2nremote[1] =~ s/\n|\r//g;
$n2novpnsub[0] =~ s/\n|\r//g;
$n2novpnsub[1] =~ s/\n|\r//g;
$n2novpnsub[2] =~ s/\n|\r//g;
$n2nproto[0] =~ s/\n|\r//g;
$n2nport[1] =~ s/\n|\r//g;
$n2ntunmtu[1] =~ s/\n|\r//g;
$n2nremsub[1] =~ s/\n|\r//g;
$n2nremsub[2] =~ s/\n|\r//g;
$n2nlocalsub[2] =~ s/\n|\r//g;
$n2nfragment[1] =~ s/\n|\r//g;
$n2nmgmt[2] =~ s/\n|\r//g;
$n2nmtudisc[1] =~ s/\n|\r//g;
chomp ($complzoactive);
chomp ($mssfixactive);
###
# m.a.d net2net
###
###
# Check if there is no other entry with this name
###
foreach my $dkey (keys %confighash) {
if ($confighash{$dkey}[1] eq $n2nname[0]) {
$errormessage = $Lang::tr{'a connection with this name already exists'};
unlink ("${General::swroot}/ovpn/n2nconf/$n2nname[0]/$n2nname[0].conf") or die "Removing Configfile fail: $!";
unlink ("${General::swroot}/ovpn/certs/$n2nname[0].p12") or die "Removing Certfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$n2nname[0]") || die "Removing Directory fail: $!";
goto N2N_ERROR;
}
}
###
# Check if OpenVPN Subnet is valid
###
foreach my $dkey (keys %confighash) {
if ($confighash{$dkey}[27] eq "$n2novpnsub[0].$n2novpnsub[1].$n2novpnsub[2].0/255.255.255.0") {
$errormessage = 'The OpenVPN Subnet is already in use';
unlink ("${General::swroot}/ovpn/n2nconf/$n2nname[0]/$n2nname[0].conf") or die "Removing Configfile fail: $!";
unlink ("${General::swroot}/ovpn/certs/$n2nname[0].p12") or die "Removing Certfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$n2nname[0]") || die "Removing Directory fail: $!";
goto N2N_ERROR;
}
}
###
# Check im Dest Port is vaild
###
foreach my $dkey (keys %confighash) {
if ($confighash{$dkey}[29] eq $n2nport[1] ) {
$errormessage = 'The OpenVPN Port is already in use';
unlink ("${General::swroot}/ovpn/n2nconf/$n2nname[0]/$n2nname[0].conf") or die "Removing Configfile fail: $!";
unlink ("${General::swroot}/ovpn/certs/$n2nname[0].p12") or die "Removing Certfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$n2nname[0]") || die "Removing Directory fail: $!";
goto N2N_ERROR;
}
}
$key = &General::findhasharraykey (\%confighash);
foreach my $i (0 .. 32) { $confighash{$key}[$i] = "";}
$confighash{$key}[0] = 'off';
$confighash{$key}[1] = $n2nname[0];
$confighash{$key}[2] = $n2nname[0];
$confighash{$key}[3] = 'net';
$confighash{$key}[4] = 'cert';
$confighash{$key}[6] = 'client';
$confighash{$key}[8] = $n2nlocalsub[2];
$confighash{$key}[10] = $n2nremote[1];
$confighash{$key}[11] = "$n2nremsub[1]/$n2nremsub[2]";
$confighash{$key}[22] = $n2nmgmt[2];
$confighash{$key}[23] = $mssfixactive;
$confighash{$key}[24] = $n2nfragment[1];
$confighash{$key}[25] = 'IPFire n2n Client';
$confighash{$key}[26] = 'red';
$confighash{$key}[27] = "$n2novpnsub[0].$n2novpnsub[1].$n2novpnsub[2].0/255.255.255.0";
$confighash{$key}[28] = $n2nproto[0];
$confighash{$key}[29] = $n2nport[1];
$confighash{$key}[30] = $complzoactive;
$confighash{$key}[31] = $n2ntunmtu[1];
$confighash{$key}[32] = $n2nmtudisc[1];
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
N2N_ERROR:
&Header::showhttpheaders();
&Header::openpage('Validate imported configuration', 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
if ($errormessage) {
&Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
print "<class name='base'>$errormessage";
print " </class>";
&Header::closebox();
} else
{
&Header::openbox('100%', 'LEFT', 'import ipfire net2net config');
}
if ($errormessage eq ''){
print <<END
<!-- ipfire net2net config gui -->
<table width='100%'>
<tr><td width='25%'> </td><td width='25%'> </td></tr>
<tr><td class='boldbase'>$Lang::tr{'name'}:</td><td><b>$n2nname[0]</b></td></tr>
<tr><td> </td><td> </td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'Act as'}</td><td><b>$confighash{$key}[6]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>Remote Host </td><td><b>$confighash{$key}[10]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'local subnet'}</td><td><b>$confighash{$key}[8]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'remote subnet'}</td><td><b>$confighash{$key}[11]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'ovpn subnet'}</td><td><b>$confighash{$key}[27]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'protocol'}</td><td><b>$confighash{$key}[28]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'destination port'}:</td><td><b>$confighash{$key}[29]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'comp-lzo'}</td><td><b>$confighash{$key}[30]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>MSSFIX </td><td><b>$confighash{$key}[23]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>Fragment </td><td><b>$confighash{$key}[24]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'MTU'}</td><td><b>$confighash{$key}[31]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'ovpn mtu-disc'}</td><td><b>$confighash{$key}[32]</b></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>Management Port </td><td><b>$confighash{$key}[22]</b></td></tr>
<tr><td> </td><td> </td></tr>
</table>
END
;
&Header::closebox();
}
if ($errormessage) {
print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
} else {
print "<div align='center'><form method='post' ENCTYPE='multipart/form-data'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' />";
print "<input type='hidden' name='TYPE' value='net2netakn' />";
print "<input type='hidden' name='KEY' value='$key' />";
print "<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></div></form>";
}
&Header::closebigbox();
&Header::closepage();
exit(0);
##
### Accept IPFire n2n Package Settings
###
} elsif (($cgiparams{'ACTION'} eq $Lang::tr{'add'}) && ($cgiparams{'TYPE'} eq 'net2netakn')){
###
### Discard and Rollback IPFire n2n Package Settings
###
} elsif (($cgiparams{'ACTION'} eq $Lang::tr{'cancel'}) && ($cgiparams{'TYPE'} eq 'net2netakn')){
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($confighash{$cgiparams{'KEY'}}) {
my $conffile = glob("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]/$confighash{$cgiparams{'KEY'}}[1].conf");
my $certfile = glob("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
unlink ($certfile) or die "Removing $certfile fail: $!";
unlink ($conffile) or die "Removing $conffile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]") || die "Kann Verzeichnis nicht loeschen: $!";
delete $confighash{$cgiparams{'KEY'}};
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
} else {
$errormessage = $Lang::tr{'invalid key'};
}
###
# m.a.d net2net
###
###
### Adding a new connection
###
} elsif (($cgiparams{'ACTION'} eq $Lang::tr{'add'}) ||
($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) ||
($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'ADVANCED'} eq '')) {
&General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) {
if (! $confighash{$cgiparams{'KEY'}}[0]) {
$errormessage = $Lang::tr{'invalid key'};
goto VPNCONF_END;
}
$cgiparams{'ENABLED'} = $confighash{$cgiparams{'KEY'}}[0];
$cgiparams{'NAME'} = $confighash{$cgiparams{'KEY'}}[1];
$cgiparams{'TYPE'} = $confighash{$cgiparams{'KEY'}}[3];
$cgiparams{'AUTH'} = $confighash{$cgiparams{'KEY'}}[4];
$cgiparams{'PSK'} = $confighash{$cgiparams{'KEY'}}[5];
$cgiparams{'SIDE'} = $confighash{$cgiparams{'KEY'}}[6];
$cgiparams{'LOCAL_SUBNET'} = $confighash{$cgiparams{'KEY'}}[8];
$cgiparams{'REMOTE'} = $confighash{$cgiparams{'KEY'}}[10];
$cgiparams{'REMOTE_SUBNET'} = $confighash{$cgiparams{'KEY'}}[11];
# n2n m.a.d new fields
$cgiparams{'OVPN_MGMT'} = $confighash{$cgiparams{'KEY'}}[22];
$cgiparams{'MSSFIX'} = $confighash{$cgiparams{'KEY'}}[23];
$cgiparams{'FRAGMENT'} = $confighash{$cgiparams{'KEY'}}[24];
$cgiparams{'REMARK'} = $confighash{$cgiparams{'KEY'}}[25];
$cgiparams{'INTERFACE'} = $confighash{$cgiparams{'KEY'}}[26];
#new fields
$cgiparams{'OVPN_SUBNET'} = $confighash{$cgiparams{'KEY'}}[27];
$cgiparams{'PROTOCOL'} = $confighash{$cgiparams{'KEY'}}[28];
$cgiparams{'DEST_PORT'} = $confighash{$cgiparams{'KEY'}}[29];
$cgiparams{'COMPLZO'} = $confighash{$cgiparams{'KEY'}}[30];
$cgiparams{'MTU'} = $confighash{$cgiparams{'KEY'}}[31];
$cgiparams{'PMTU_DISCOVERY'} = $confighash{$cgiparams{'KEY'}}[32];
#new fields
#ab hiere error uebernehmen
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
$cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
if ($cgiparams{'TYPE'} !~ /^(host|net)$/) {
$errormessage = $Lang::tr{'connection type is invalid'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
if ($cgiparams{'NAME'} !~ /^[a-zA-Z0-9]+$/) {
$errormessage = $Lang::tr{'name must only contain characters'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
if ($cgiparams{'NAME'} =~ /^(host|01|block|private|clear|packetdefault)$/) {
$errormessage = $Lang::tr{'name is invalid'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
if (length($cgiparams{'NAME'}) >60) {
$errormessage = $Lang::tr{'name too long'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
###
# m.a.d net2net
###
if ($cgiparams{'TYPE'} eq 'net') {
if ($cgiparams{'DEST_PORT'} eq $vpnsettings{'DDEST_PORT'}) {
$errormessage = $Lang::tr{'openvpn destination port used'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ($cgiparams{'DEST_PORT'} eq '') {
$errormessage = $Lang::tr{'openvpn destination port used'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ($cgiparams{'OVPN_SUBNET'} eq $vpnsettings{'DOVPN_SUBNET'}) {
$errormessage = $Lang::tr{'openvpn subnet is used'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if (($cgiparams{'PROTOCOL'} eq 'tcp') && ($cgiparams{'MSSFIX'} eq 'on')) {
$errormessage = $Lang::tr{'openvpn mssfix allowed with udp'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if (($cgiparams{'PROTOCOL'} eq 'tcp') && ($cgiparams{'FRAGMENT'} ne '')) {
$errormessage = $Lang::tr{'openvpn fragment allowed with udp'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if (($cgiparams{'PMTU_DISCOVERY'} ne 'off') && ($cgiparams{'MTU'} ne '1500')) {
$errormessage = $Lang::tr{'ovpn mtu-disc and mtu not 1500'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ($cgiparams{'PMTU_DISCOVERY'} ne 'off') {
if (($cgiparams{'FRAGMENT'} ne '') || ($cgiparams{'MSSFIX'} eq 'on')) {
$errormessage = $Lang::tr{'ovpn mtu-disc with mssfix or fragment'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
}
if ( &validdotmask ($cgiparams{'LOCAL_SUBNET'})) {
$errormessage = $Lang::tr{'openvpn prefix local subnet'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ( &validdotmask ($cgiparams{'OVPN_SUBNET'})) {
$errormessage = $Lang::tr{'openvpn prefix openvpn subnet'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ( &validdotmask ($cgiparams{'REMOTE_SUBNET'})) {
$errormessage = $Lang::tr{'openvpn prefix remote subnet'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ($cgiparams{'OVPN_MGMT'} eq '') {
$cgiparams{'OVPN_MGMT'} = $cgiparams{'DEST_PORT'};
}
}
# if (($cgiparams{'TYPE'} eq 'net') && ($cgiparams{'SIDE'} !~ /^(left|right)$/)) {
# $errormessage = $Lang::tr{'ipfire side is invalid'};
# goto VPNCONF_ERROR;
# }
# Check if there is no other entry with this name
if (! $cgiparams{'KEY'}) {
foreach my $key (keys %confighash) {
if ($confighash{$key}[1] eq $cgiparams{'NAME'}) {
$errormessage = $Lang::tr{'a connection with this name already exists'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
}
}
if (($cgiparams{'TYPE'} eq 'net') && (! $cgiparams{'REMOTE'})) {
$errormessage = $Lang::tr{'invalid input for remote host/ip'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
}
if ($cgiparams{'REMOTE'}) {
if (! &General::validip($cgiparams{'REMOTE'})) {
if (! &General::validfqdn ($cgiparams{'REMOTE'})) {
$errormessage = $Lang::tr{'invalid input for remote host/ip'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;
} else {
if (&valid_dns_host($cgiparams{'REMOTE'})) {
$warnmessage = "$Lang::tr{'check vpn lr'} $cgiparams{'REMOTE'}. $Lang::tr{'dns check failed'}";
if ($cgiparams{'TYPE'} eq 'net') {
}
}
}
}
}
if ($cgiparams{'TYPE'} ne 'host') {
unless (&General::validipandmask($cgiparams{'LOCAL_SUBNET'})) {
$errormessage = $Lang::tr{'local subnet is invalid'};
if ($cgiparams{'TYPE'} eq 'net') {
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
}
goto VPNCONF_ERROR;}
}
# Check if there is no other entry without IP-address and PSK
if ($cgiparams{'REMOTE'} eq '') {
foreach my $key (keys %confighash) {
if(($cgiparams{'KEY'} ne $key) &&
($confighash{$key}[4] eq 'psk' || $cgiparams{'AUTH'} eq 'psk') &&
$confighash{$key}[10] eq '') {
$errormessage = $Lang::tr{'you can only define one roadwarrior connection when using pre-shared key authentication'};
goto VPNCONF_ERROR;
}
}
}
if (($cgiparams{'TYPE'} eq 'net') && (! &General::validipandmask($cgiparams{'REMOTE_SUBNET'}))) {
$errormessage = $Lang::tr{'remote subnet is invalid'};
unlink ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Removing Configfile fail: $!";
rmdir ("${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}") || die "Removing Directory fail: $!";
goto VPNCONF_ERROR;
}
if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'EDIT_ADVANCED'} !~ /^(on|off)$/) {
$errormessage = $Lang::tr{'invalid input'};
goto VPNCONF_ERROR;
}
#fixplausi
if ($cgiparams{'AUTH'} eq 'psk') {
# if (! length($cgiparams{'PSK'}) ) {
# $errormessage = $Lang::tr{'pre-shared key is too short'};
# goto VPNCONF_ERROR;
# }
# if ($cgiparams{'PSK'} =~ /['",&]/) {
# $errormessage = $Lang::tr{'invalid characters found in pre-shared key'};
# goto VPNCONF_ERROR;
# }
} elsif ($cgiparams{'AUTH'} eq 'certreq') {
if ($cgiparams{'KEY'}) {
$errormessage = $Lang::tr{'cant change certificates'};
goto VPNCONF_ERROR;
}
if (ref ($cgiparams{'FH'}) ne 'Fh') {
$errormessage = $Lang::tr{'there was no file upload'};
goto VPNCONF_ERROR;
}
# Move uploaded certificate request to a temporary file
(my $fh, my $filename) = tempfile( );
if (copy ($cgiparams{'FH'}, $fh) != 1) {
$errormessage = $!;
goto VPNCONF_ERROR;
}
# Sign the certificate request and move it
# Sign the host certificate request
system('/usr/bin/openssl', 'ca', '-days', "$cgiparams{'DAYS_VALID'}",
'-batch', '-notext',
'-in', $filename,
'-out', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem",
'-config',"${General::swroot}/ovpn/openssl/ovpn.cnf");
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ($filename);
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem");
&newcleanssldatabase();
goto VPNCONF_ERROR;
} else {
unlink ($filename);
&deletebackupcert();
}
my $temp = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem`;
$temp =~ /Subject:.*CN=(.*)[\n]/;
$temp = $1;
$temp =~ s+/Email+, E+;
$temp =~ s/ ST=/ S=/;
$cgiparams{'CERT_NAME'} = $temp;
$cgiparams{'CERT_NAME'} =~ s/,//g;
$cgiparams{'CERT_NAME'} =~ s/\'//g;
if ($cgiparams{'CERT_NAME'} eq '') {
$errormessage = $Lang::tr{'could not retrieve common name from certificate'};
goto VPNCONF_ERROR;
}
} elsif ($cgiparams{'AUTH'} eq 'certfile') {
if ($cgiparams{'KEY'}) {
$errormessage = $Lang::tr{'cant change certificates'};
goto VPNCONF_ERROR;
}
if (ref ($cgiparams{'FH'}) ne 'Fh') {
$errormessage = $Lang::tr{'there was no file upload'};
goto VPNCONF_ERROR;
}
# Move uploaded certificate to a temporary file
(my $fh, my $filename) = tempfile( );
if (copy ($cgiparams{'FH'}, $fh) != 1) {
$errormessage = $!;
goto VPNCONF_ERROR;
}
# Verify the certificate has a valid CA and move it
my $validca = 0;
my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ovpn/ca/cacert.pem $filename`;
if ($test =~ /: OK/) {
$validca = 1;
} else {
foreach my $key (keys %cahash) {
$test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ovpn/ca/$cahash{$key}[0]cert.pem $filename`;
if ($test =~ /: OK/) {
$validca = 1;
}
}
}
if (! $validca) {
$errormessage = $Lang::tr{'certificate does not have a valid ca associated with it'};
unlink ($filename);
goto VPNCONF_ERROR;
} else {
move($filename, "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem");
if ($? ne 0) {
$errormessage = "$Lang::tr{'certificate file move failed'}: $!";
unlink ($filename);
goto VPNCONF_ERROR;
}
}
my $temp = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem`;
$temp =~ /Subject:.*CN=(.*)[\n]/;
$temp = $1;
$temp =~ s+/Email+, E+;
$temp =~ s/ ST=/ S=/;
$cgiparams{'CERT_NAME'} = $temp;
$cgiparams{'CERT_NAME'} =~ s/,//g;
$cgiparams{'CERT_NAME'} =~ s/\'//g;
if ($cgiparams{'CERT_NAME'} eq '') {
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem");
$errormessage = $Lang::tr{'could not retrieve common name from certificate'};
goto VPNCONF_ERROR;
}
} elsif ($cgiparams{'AUTH'} eq 'certgen') {
if ($cgiparams{'KEY'}) {
$errormessage = $Lang::tr{'cant change certificates'};
goto VPNCONF_ERROR;
}
# Validate input since the form was submitted
if (length($cgiparams{'CERT_NAME'}) >60) {
$errormessage = $Lang::tr{'name too long'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_NAME'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
$errormessage = $Lang::tr{'invalid input for name'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'CERT_EMAIL'}))) {
$errormessage = $Lang::tr{'invalid input for e-mail address'};
goto VPNCONF_ERROR;
}
if (length($cgiparams{'CERT_EMAIL'}) > 40) {
$errormessage = $Lang::tr{'e-mail address too long'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_OU'} ne '' && $cgiparams{'CERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for department'};
goto VPNCONF_ERROR;
}
if (length($cgiparams{'CERT_ORGANIZATION'}) >60) {
$errormessage = $Lang::tr{'organization too long'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
$errormessage = $Lang::tr{'invalid input for organization'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_CITY'} ne '' && $cgiparams{'CERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for city'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_STATE'} ne '' && $cgiparams{'CERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
$errormessage = $Lang::tr{'invalid input for state or province'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_COUNTRY'} !~ /^[A-Z]*$/) {
$errormessage = $Lang::tr{'invalid input for country'};
goto VPNCONF_ERROR;
}
if ($cgiparams{'CERT_PASS1'} ne '' && $cgiparams{'CERT_PASS2'} ne ''){
if (length($cgiparams{'CERT_PASS1'}) < 5) {
$errormessage = $Lang::tr{'password too short'};
goto VPNCONF_ERROR;
}
}
if ($cgiparams{'CERT_PASS1'} ne $cgiparams{'CERT_PASS2'}) {
$errormessage = $Lang::tr{'passwords do not match'};
goto VPNCONF_ERROR;
}
# Replace empty strings with a .
(my $ou = $cgiparams{'CERT_OU'}) =~ s/^\s*$/\./;
(my $city = $cgiparams{'CERT_CITY'}) =~ s/^\s*$/\./;
(my $state = $cgiparams{'CERT_STATE'}) =~ s/^\s*$/\./;
# Create the Host certificate request client
my $pid = open(OPENSSL, "|-");
$SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto VPNCONF_ERROR;};
if ($pid) { # parent
print OPENSSL "$cgiparams{'CERT_COUNTRY'}\n";
print OPENSSL "$state\n";
print OPENSSL "$city\n";
print OPENSSL "$cgiparams{'CERT_ORGANIZATION'}\n";
print OPENSSL "$ou\n";
print OPENSSL "$cgiparams{'CERT_NAME'}\n";
print OPENSSL "$cgiparams{'CERT_EMAIL'}\n";
print OPENSSL ".\n";
print OPENSSL ".\n";
close (OPENSSL);
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}ovpn/certs/$cgiparams{'NAME'}key.pem");
unlink ("${General::swroot}ovpn/certs/$cgiparams{'NAME'}req.pem");
goto VPNCONF_ERROR;
}
} else { # child
unless (exec ('/usr/bin/openssl', 'req', '-nodes', '-rand', '/proc/interrupts:/proc/net/rt_cache',
'-newkey', 'rsa:1024',
'-keyout', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem",
'-out', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}req.pem",
'-config',"${General::swroot}/ovpn/openssl/ovpn.cnf")) {
$errormessage = "$Lang::tr{'cant start openssl'}: $!";
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem");
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}req.pem");
goto VPNCONF_ERROR;
}
}
# Sign the host certificate request
system('/usr/bin/openssl', 'ca', '-days', "$cgiparams{'DAYS_VALID'}",
'-batch', '-notext',
'-in', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}req.pem",
'-out', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem",
'-config',"${General::swroot}/ovpn/openssl/ovpn.cnf");
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem");
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}req.pem");
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem");
&newcleanssldatabase();
goto VPNCONF_ERROR;
} else {
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}req.pem");
&deletebackupcert();
}
# Create the pkcs12 file
system('/usr/bin/openssl', 'pkcs12', '-export',
'-inkey', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem",
'-in', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem",
'-name', $cgiparams{'NAME'},
'-passout', "pass:$cgiparams{'CERT_PASS1'}",
'-certfile', "${General::swroot}/ovpn/ca/cacert.pem",
'-caname', "$vpnsettings{'ROOTCERT_ORGANIZATION'} CA",
'-out', "${General::swroot}/ovpn/certs/$cgiparams{'NAME'}.p12");
if ($?) {
$errormessage = "$Lang::tr{'openssl produced an error'}: $?";
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem");
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}cert.pem");
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}.p12");
goto VPNCONF_ERROR;
} else {
unlink ("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}key.pem");
}
} elsif ($cgiparams{'AUTH'} eq 'cert') {
;# Nothing, just editing
} else {
$errormessage = $Lang::tr{'invalid input for authentication method'};
goto VPNCONF_ERROR;
}
# Check if there is no other entry with this common name
if ((! $cgiparams{'KEY'}) && ($cgiparams{'AUTH'} ne 'psk')) {
foreach my $key (keys %confighash) {
if ($confighash{$key}[2] eq $cgiparams{'CERT_NAME'}) {
$errormessage = $Lang::tr{'a connection with this common name already exists'};
goto VPNCONF_ERROR;
}
}
}
# Save the config
my $key = $cgiparams{'KEY'};
if (! $key) {
$key = &General::findhasharraykey (\%confighash);
foreach my $i (0 .. 31) { $confighash{$key}[$i] = "";}
}
$confighash{$key}[0] = $cgiparams{'ENABLED'};
$confighash{$key}[1] = $cgiparams{'NAME'};
if ((! $cgiparams{'KEY'}) && $cgiparams{'AUTH'} ne 'psk') {
$confighash{$key}[2] = $cgiparams{'CERT_NAME'};
}
$confighash{$key}[3] = $cgiparams{'TYPE'};
if ($cgiparams{'AUTH'} eq 'psk') {
$confighash{$key}[4] = 'psk';
$confighash{$key}[5] = $cgiparams{'PSK'};
} else {
$confighash{$key}[4] = 'cert';
}
if ($cgiparams{'TYPE'} eq 'net') {
$confighash{$key}[6] = $cgiparams{'SIDE'};
$confighash{$key}[11] = $cgiparams{'REMOTE_SUBNET'};
}
$confighash{$key}[8] = $cgiparams{'LOCAL_SUBNET'};
$confighash{$key}[10] = $cgiparams{'REMOTE'};
if ($cgiparams{'OVPN_MGMT'} eq '') {
$confighash{$key}[22] = $confighash{$key}[29];
} else {
$confighash{$key}[22] = $cgiparams{'OVPN_MGMT'};
}
$confighash{$key}[23] = $cgiparams{'MSSFIX'};
$confighash{$key}[24] = $cgiparams{'FRAGMENT'};
$confighash{$key}[25] = $cgiparams{'REMARK'};
$confighash{$key}[26] = $cgiparams{'INTERFACE'};
# new fields
$confighash{$key}[27] = $cgiparams{'OVPN_SUBNET'};
$confighash{$key}[28] = $cgiparams{'PROTOCOL'};
$confighash{$key}[29] = $cgiparams{'DEST_PORT'};
$confighash{$key}[30] = $cgiparams{'COMPLZO'};
$confighash{$key}[31] = $cgiparams{'MTU'};
$confighash{$key}[32] = $cgiparams{'PMTU_DISCOVERY'};
# new fileds
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
###
# m.a.d n2n begin
###
if ($cgiparams{'TYPE'} eq 'net') {
if (-e "/var/run/$confighash{$key}[1]n2n.pid") {
system('/usr/local/bin/openvpnctrl', '-kn2n', $confighash{$cgiparams{'KEY'}}[1]);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
my $key = $cgiparams{'KEY'};
if (! $key) {
$key = &General::findhasharraykey (\%confighash);
foreach my $i (0 .. 31) { $confighash{$key}[$i] = "";}
}
$confighash{$key}[0] = 'on';
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
system('/usr/local/bin/openvpnctrl', '-sn2n', $confighash{$cgiparams{'KEY'}}[1]);
}
}
###
# m.a.d n2n end
###
if ($cgiparams{'EDIT_ADVANCED'} eq 'on') {
$cgiparams{'KEY'} = $key;
$cgiparams{'ACTION'} = $Lang::tr{'advanced'};
}
goto VPNCONF_END;
} else {
$cgiparams{'ENABLED'} = 'on';
###
# m.a.d n2n begin
###
$cgiparams{'MSSFIX'} = 'on';
$cgiparams{'FRAGMENT'} = '1300';
###
# m.a.d n2n end
###
$cgiparams{'SIDE'} = 'left';
if ( ! -f "${General::swroot}/ovpn/ca/cakey.pem" ) {
$cgiparams{'AUTH'} = 'psk';
} elsif ( ! -f "${General::swroot}/ovpn/ca/cacert.pem") {
$cgiparams{'AUTH'} = 'certfile';
} else {
$cgiparams{'AUTH'} = 'certgen';
}
$cgiparams{'LOCAL_SUBNET'} ="$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}";
$cgiparams{'CERT_ORGANIZATION'} = $vpnsettings{'ROOTCERT_ORGANIZATION'};
$cgiparams{'CERT_CITY'} = $vpnsettings{'ROOTCERT_CITY'};
$cgiparams{'CERT_STATE'} = $vpnsettings{'ROOTCERT_STATE'};
$cgiparams{'CERT_COUNTRY'} = $vpnsettings{'ROOTCERT_COUNTRY'};
}
VPNCONF_ERROR:
$checked{'ENABLED'}{'off'} = '';
$checked{'ENABLED'}{'on'} = '';
$checked{'ENABLED'}{$cgiparams{'ENABLED'}} = 'CHECKED';
$checked{'ENABLED_BLUE'}{'off'} = '';
$checked{'ENABLED_BLUE'}{'on'} = '';
$checked{'ENABLED_BLUE'}{$cgiparams{'ENABLED_BLUE'}} = 'CHECKED';
$checked{'ENABLED_ORANGE'}{'off'} = '';
$checked{'ENABLED_ORANGE'}{'on'} = '';
$checked{'ENABLED_ORANGE'}{$cgiparams{'ENABLED_ORANGE'}} = 'CHECKED';
$checked{'EDIT_ADVANCED'}{'off'} = '';
$checked{'EDIT_ADVANCED'}{'on'} = '';
$checked{'EDIT_ADVANCED'}{$cgiparams{'EDIT_ADVANCED'}} = 'CHECKED';
$selected{'SIDE'}{'server'} = '';
$selected{'SIDE'}{'client'} = '';
$selected{'SIDE'}{$cgiparams{'SIDE'}} = 'SELECTED';
$selected{'PROTOCOL'}{'udp'} = '';
$selected{'PROTOCOL'}{'tcp'} = '';
$selected{'PROTOCOL'}{$cgiparams{'PROTOCOL'}} = 'SELECTED';
$checked{'AUTH'}{'psk'} = '';
$checked{'AUTH'}{'certreq'} = '';
$checked{'AUTH'}{'certgen'} = '';
$checked{'AUTH'}{'certfile'} = '';
$checked{'AUTH'}{$cgiparams{'AUTH'}} = 'CHECKED';
$selected{'INTERFACE'}{$cgiparams{'INTERFACE'}} = 'SELECTED';
$checked{'COMPLZO'}{'off'} = '';
$checked{'COMPLZO'}{'on'} = '';
$checked{'COMPLZO'}{$cgiparams{'COMPLZO'}} = 'CHECKED';
$checked{'MSSFIX'}{'off'} = '';
$checked{'MSSFIX'}{'on'} = '';
$checked{'MSSFIX'}{$cgiparams{'MSSFIX'}} = 'CHECKED';
$checked{'PMTU_DISCOVERY'}{$cgiparams{'PMTU_DISCOVERY'}} = 'checked=\'checked\'';
if (1) {
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
if ($errormessage) {
&Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
print "<class name='base'>$errormessage";
print " </class>";
&Header::closebox();
}
if ($warnmessage) {
&Header::openbox('100%', 'LEFT', "$Lang::tr{'warning messages'}:");
print "<class name='base'>$warnmessage";
print " </class>";
&Header::closebox();
}
print "<form method='post' enctype='multipart/form-data'>";
print "<input type='hidden' name='TYPE' value='$cgiparams{'TYPE'}' />";
if ($cgiparams{'KEY'}) {
print "<input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />";
print "<input type='hidden' name='AUTH' value='$cgiparams{'AUTH'}' />";
}
&Header::openbox('100%', 'LEFT', "$Lang::tr{'connection'}:");
print "<table width='100%'>\n";
print "<tr><td width='25%' class='boldbase'>$Lang::tr{'name'}:</td>";
if ($cgiparams{'TYPE'} eq 'host') {
if ($cgiparams{'KEY'}) {
print "<td width='35%' class='base'><input type='hidden' name='NAME' value='$cgiparams{'NAME'}' />$cgiparams{'NAME'}</td>\n";
} else {
print "<td width='35%'><input type='text' name='NAME' value='$cgiparams{'NAME'}' maxlength='20' size='30' /></td>";
}
# print "<tr><td>$Lang::tr{'interface'}</td>";
# print "<td><select name='INTERFACE'>";
# print "<option value='RED' $selected{'INTERFACE'}{'RED'}>RED</option>";
# if ($netsettings{'BLUE_DEV'} ne '') {
# print "<option value='BLUE' $selected{'INTERFACE'}{'BLUE'}>BLUE</option>";
# }
# print "<option value='GREEN' $selected{'INTERFACE'}{'GREEN'}>GREEN</option>";
# print "<option value='ORANGE' $selected{'INTERFACE'}{'ORANGE'}>ORANGE</option>";
# print "</select></td></tr>";
# print <<END
} else {
print "<input type='hidden' name='INTERFACE' value='red' />";
if ($cgiparams{'KEY'}) {
print "<td width='25%' class='base' nowrap='nowrap'><input type='hidden' name='NAME' value='$cgiparams{'NAME'}' />$cgiparams{'NAME'}</td>";
} else {
print "<td width='25%'><input type='text' name='NAME' value='$cgiparams{'NAME'}' maxlength='20' /></td>";
}
print <<END
<td width='25%'> </td>
<td width='25%'> </td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'Act as'}</td>
<td><select name='SIDE'><option value='server' $selected{'SIDE'}{'server'}>$Lang::tr{'openvpn server'}</option>
<option value='client' $selected{'SIDE'}{'client'}>$Lang::tr{'openvpn client'}</option></select></td>
<td class='boldbase'>$Lang::tr{'remote host/ip'}:</td>
<td><input type='TEXT' name='REMOTE' value='$cgiparams{'REMOTE'}' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'local subnet'}</td>
<td><input type='TEXT' name='LOCAL_SUBNET' value='$cgiparams{'LOCAL_SUBNET'}' /></td>
<td class='boldbase' nowrap='nowrap'>$Lang::tr{'remote subnet'}</td>
<td><input type='text' name='REMOTE_SUBNET' value='$cgiparams{'REMOTE_SUBNET'}' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'ovpn subnet'}</td>
<td><input type='TEXT' name='OVPN_SUBNET' value='$cgiparams{'OVPN_SUBNET'}' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'protocol'}</td>
<td><select name='PROTOCOL'><option value='udp' $selected{'PROTOCOL'}{'udp'}>UDP</option>
<option value='tcp' $selected{'PROTOCOL'}{'tcp'}>TCP</option></select></td>
<td class='boldbase'>$Lang::tr{'destination port'}:</td>
<td><input type='TEXT' name='DEST_PORT' value='$cgiparams{'DEST_PORT'}' size='5' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'comp-lzo'} <img src='/blob.gif'</td>
<td><input type='checkbox' name='COMPLZO' $checked{'COMPLZO'}{'on'} /></td>
<tr><td class='boldbase' nowrap='nowrap'>mssfix <img src='/blob.gif' /></td>
<td><input type='checkbox' name='MSSFIX' $checked{'MSSFIX'}{'on'} /></td>
<td>$Lang::tr{'openvpn default'}: <span class="base">on</span></td>
<tr><td class='boldbase' nowrap='nowrap'>fragment <img src='/blob.gif' /></td>
<td><input type='TEXT' name='FRAGMENT' VALUE='$cgiparams{'FRAGMENT'}'size='5' /></td>
<td>$Lang::tr{'openvpn default'}: <span class="base">1300</span></td>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'MTU'} <img src='/blob.gif' /></td>
<td> <input type='TEXT' name='MTU' VALUE='$cgiparams{'MTU'}'size='5' /></td>
<td colspan='2'>$Lang::tr{'openvpn default'}: udp/tcp <span class="base">1500/1400</span></td>
<tr><td class='boldbase' nowrap='nowrap'>Management Port <img src='/blob.gif' /></td>
<td> <input type='TEXT' name='OVPN_MGMT' VALUE='$cgiparams{'OVPN_MGMT'}'size='5' /></td>
<td colspan='2'>$Lang::tr{'openvpn default'}: <span class="base">$Lang::tr{'destination port'}</span></td>
<tr>
<td class='boldbase' nowrap='nowrap'>$Lang::tr{'ovpn mtu-disc'}</td>
<td colspan='2'>
<input type='radio' name='PMTU_DISCOVERY' value='yes' $checked{'PMTU_DISCOVERY'}{'yes'} /> $Lang::tr{'ovpn mtu-disc yes'}
<input type='radio' name='PMTU_DISCOVERY' value='maybe' $checked{'PMTU_DISCOVERY'}{'maybe'} /> $Lang::tr{'ovpn mtu-disc maybe'}
<input type='radio' name='PMTU_DISCOVERY' value='no' $checked{'PMTU_DISCOVERY'}{'no'} /> $Lang::tr{'ovpn mtu-disc no'}
<input type='radio' name='PMTU_DISCOVERY' value='off' $checked{'PMTU_DISCOVERY'}{'off'} /> $Lang::tr{'ovpn mtu-disc off'}
</td>
</tr>
END
;
}
#jumper
print "<tr><td class='boldbase'>$Lang::tr{'remark title'} <img src='/blob.gif' /></td>";
print "<td colspan='3'><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td></tr>";
if ($cgiparams{'TYPE'} eq 'host') {
print "<tr><td>$Lang::tr{'enabled'} <input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\n";
}
# if ($cgiparams{'KEY'}) {
# print "<td colspan='3'> </td></tr></table>";
# } else {
# print "<td colspan='3'><input type='checkbox' name='EDIT_ADVANCED' $checked{'EDIT_ADVANCED'}{'on'} /> $Lang::tr{'edit advanced settings when done'}</tr></table>";
# }
# }else{
print "<td colspan='3'> </td></tr></table>";
# }
&Header::closebox();
if ($cgiparams{'KEY'} && $cgiparams{'AUTH'} eq 'psk') {
# &Header::openbox('100%', 'LEFT', $Lang::tr{'authentication'});
# print <<END
# <table width='100%' cellpadding='0' cellspacing='5' border='0'>
# <tr><td class='base' width='50%'>$Lang::tr{'use a pre-shared key'}</td>
# <td class='base' width='50%'><input type='text' name='PSK' size='30' value='$cgiparams{'PSK'}' /></td></tr>
# </table>
END
# ;
# &Header::closebox();
} elsif (! $cgiparams{'KEY'}) {
my $disabled='';
my $cakeydisabled='';
my $cacrtdisabled='';
if ( ! -f "${General::swroot}/ovpn/ca/cakey.pem" ) { $cakeydisabled = "disabled='disabled'" } else { $cakeydisabled = "" };
if ( ! -f "${General::swroot}/ovpn/ca/cacert.pem" ) { $cacrtdisabled = "disabled='disabled'" } else { $cacrtdisabled = "" };
&Header::openbox('100%', 'LEFT', $Lang::tr{'authentication'});
if ($cgiparams{'TYPE'} eq 'host') {
print <<END
<table width='100%' cellpadding='0' cellspacing='5' border='0'>
<tr><td><input type='radio' name='AUTH' value='certreq' $checked{'AUTH'}{'certreq'} $cakeydisabled /></td><td class='base'>$Lang::tr{'upload a certificate request'}</td><td class='base' rowspan='2'><input type='file' name='FH' size='30' $cacrtdisabled></td></tr>
<tr><td><input type='radio' name='AUTH' value='certfile' $checked{'AUTH'}{'certfile'} $cacrtdisabled /></td><td class='base'>$Lang::tr{'upload a certificate'}</td></tr>
<tr><td colspan='3'> </td></tr>
<tr><td colspan='3'><hr /></td></tr>
<tr><td colspan='3'> </td></tr>
<tr><td><input type='radio' name='AUTH' value='certgen' $checked{'AUTH'}{'certgen'} $cakeydisabled /></td><td class='base'>$Lang::tr{'generate a certificate'}</td><td> </td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users fullname or system hostname'}:</td><td class='base' nowrap='nowrap'><input type='text' name='CERT_NAME' value='$cgiparams{'CERT_NAME'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users email'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_EMAIL' value='$cgiparams{'CERT_EMAIL'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users department'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_OU' value='$cgiparams{'CERT_OU'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'organization name'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_ORGANIZATION' value='$cgiparams{'CERT_ORGANIZATION'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'city'}: <img src='/blob.gif'></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_CITY' value='$cgiparams{'CERT_CITY'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'state or province'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_STATE' value='$cgiparams{'CERT_STATE'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'country'}:</td><td class='base'><select name='CERT_COUNTRY' $cakeydisabled>
END
;
###
# m.a.d net2net
###
} else {
print <<END
<table width='100%' cellpadding='0' cellspacing='5' border='0'>
<tr><td><input type='radio' name='AUTH' value='certgen' $checked{'AUTH'}{'certgen'} $cakeydisabled /></td><td class='base'>$Lang::tr{'generate a certificate'}</td><td> </td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users fullname or system hostname'}:</td><td class='base' nowrap='nowrap'><input type='text' name='CERT_NAME' value='$cgiparams{'CERT_NAME'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users email'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_EMAIL' value='$cgiparams{'CERT_EMAIL'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'users department'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_OU' value='$cgiparams{'CERT_OU'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'organization name'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_ORGANIZATION' value='$cgiparams{'CERT_ORGANIZATION'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'city'}: <img src='/blob.gif'></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_CITY' value='$cgiparams{'CERT_CITY'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'state or province'}: <img src='/blob.gif' /></td><td class='base' nowrap='nowrap'><input type='text' name='CERT_STATE' value='$cgiparams{'CERT_STATE'}' SIZE='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'country'}:</td><td class='base'><select name='CERT_COUNTRY' $cakeydisabled>
END
;
}
###
# m.a.d net2net
###
foreach my $country (sort keys %{Countries::countries}) {
print "<option value='$Countries::countries{$country}'";
if ( $Countries::countries{$country} eq $cgiparams{'CERT_COUNTRY'} ) {
print " selected='selected'";
}
print ">$country</option>";
}
###
# m.a.d net2net
###
if ($cgiparams{'TYPE'} eq 'host') {
print <<END
</select></td></tr>
<td> </td><td class='base'>$Lang::tr{'valid till'} (days):</td>
<td class='base' nowrap='nowrap'><input type='text' name='DAYS_VALID' value='$cgiparams{'DAYS_VALID'}' size='32' $cakeydisabled /></td></tr>
<tr><td> </td>
<td class='base'>$Lang::tr{'pkcs12 file password'}:</td>
<td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS1' value='$cgiparams{'CERT_PASS1'}' size='32' $cakeydisabled /></td></tr>
<tr><td> </td><td class='base'>$Lang::tr{'pkcs12 file password'}:<BR>($Lang::tr{'confirmation'})</td>
<td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS2' value='$cgiparams{'CERT_PASS2'}' size='32' $cakeydisabled /></td></tr>
<tr><td colspan='3'> </td></tr>
<tr><td colspan='3'><hr /></td></tr>
<tr><td class='base' colspan='3' align='left'><img src='/blob.gif' alt='*' /> $Lang::tr{'this field may be blank'}</td></tr>
</table>
END
}else{
print <<END
</select></td></tr>
<tr><td> </td><td> </td><td> </td></tr>
<tr><td> </td><td> </td><td> </td></tr>
<tr><td colspan='3'><hr /></td></tr>
<tr><td class='base' colspan='3' align='left'><img src='/blob.gif' alt='*' /> $Lang::tr{'this field may be blank'}</td></tr>
</table>
END
}
###
# m.a.d net2net
###
;
&Header::closebox();
}
print "<div align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' />";
if ($cgiparams{'KEY'}) {
# print "<input type='submit' name='ACTION' value='$Lang::tr{'advanced'}' />";
}
print "<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></div></form>";
&Header::closebigbox();
&Header::closepage();
exit (0);
}
VPNCONF_END:
}
# SETTINGS_ERROR:
###
### Default status page
###
%cgiparams = ();
%cahash = ();
%confighash = ();
&General::readhash("${General::swroot}/ovpn/settings", \%cgiparams);
&General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
my @status = `/bin/cat /var/log/ovpnserver.log`;
if ($cgiparams{'VPN_IP'} eq '' && -e "${General::swroot}/red/active") {
if (open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
my $ipaddr = <IPADDR>;
close IPADDR;
chomp ($ipaddr);
$cgiparams{'VPN_IP'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
if ($cgiparams{'VPN_IP'} eq '') {
$cgiparams{'VPN_IP'} = $ipaddr;
}
}
}
#default setzen
if ($cgiparams{'DCIPHER'} eq '') {
$cgiparams{'DCIPHER'} = 'BF-CBC';
}
# if ($cgiparams{'DCOMPLZO'} eq '') {
# $cgiparams{'DCOMPLZO'} = 'on';
# }
if ($cgiparams{'DDEST_PORT'} eq '') {
$cgiparams{'DDEST_PORT'} = '1194';
}
if ($cgiparams{'DMTU'} eq '') {
$cgiparams{'DMTU'} = '1400';
}
if ($cgiparams{'DOVPN_SUBNET'} eq '') {
$cgiparams{'DOVPN_SUBNET'} = '10.' . int(rand(256)) . '.' . int(rand(256)) . '.0/255.255.255.0';
}
$checked{'ENABLED'}{'off'} = '';
$checked{'ENABLED'}{'on'} = '';
$checked{'ENABLED'}{$cgiparams{'ENABLED'}} = 'CHECKED';
$checked{'ENABLED_BLUE'}{'off'} = '';
$checked{'ENABLED_BLUE'}{'on'} = '';
$checked{'ENABLED_BLUE'}{$cgiparams{'ENABLED_BLUE'}} = 'CHECKED';
$checked{'ENABLED_ORANGE'}{'off'} = '';
$checked{'ENABLED_ORANGE'}{'on'} = '';
$checked{'ENABLED_ORANGE'}{$cgiparams{'ENABLED_ORANGE'}} = 'CHECKED';
$selected{'DDEVICE'}{'tun'} = '';
$selected{'DDEVICE'}{'tap'} = '';
$selected{'DDEVICE'}{$cgiparams{'DDEVICE'}} = 'SELECTED';
$selected{'DPROTOCOL'}{'udp'} = '';
$selected{'DPROTOCOL'}{'tcp'} = '';
$selected{'DPROTOCOL'}{$cgiparams{'DPROTOCOL'}} = 'SELECTED';
$selected{'DCIPHER'}{'DES-CBC'} = '';
$selected{'DCIPHER'}{'DES-EDE-CBC'} = '';
$selected{'DCIPHER'}{'DES-EDE3-CBC'} = '';
$selected{'DCIPHER'}{'DESX-CBC'} = '';
$selected{'DCIPHER'}{'RC2-CBC'} = '';
$selected{'DCIPHER'}{'RC2-40-CBC'} = '';
$selected{'DCIPHER'}{'RC2-64-CBC'} = '';
$selected{'DCIPHER'}{'BF-CBC'} = '';
$selected{'DCIPHER'}{'CAST5-CBC'} = '';
$selected{'DCIPHER'}{'AES-128-CBC'} = '';
$selected{'DCIPHER'}{'AES-192-CBC'} = '';
$selected{'DCIPHER'}{'AES-256-CBC'} = '';
$selected{'DCIPHER'}{$cgiparams{'DCIPHER'}} = 'SELECTED';
$checked{'DCOMPLZO'}{'off'} = '';
$checked{'DCOMPLZO'}{'on'} = '';
$checked{'DCOMPLZO'}{$cgiparams{'DCOMPLZO'}} = 'CHECKED';
# m.a.d
$checked{'MSSFIX'}{'off'} = '';
$checked{'MSSFIX'}{'on'} = '';
$checked{'MSSFIX'}{$cgiparams{'MSSFIX'}} = 'CHECKED';
#new settings
&Header::showhttpheaders();
&Header::openpage($Lang::tr{'status ovpn'}, 1, '');
&Header::openbigbox('100%', 'LEFT', '', $errormessage);
if ($errormessage) {
&Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
print "<class name='base'>$errormessage\n";
print " </class>\n";
&Header::closebox();
}
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
my $srunning = "no";
my $activeonrun = "";
if ( -e "/var/run/openvpn.pid"){
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
$srunning ="yes";
$activeonrun = "";
} else {
$activeonrun = "disabled='disabled'";
}
&Header::openbox('100%', 'LEFT', $Lang::tr{'global settings'});
print <<END
<table width='100%'>
<form method='post'>
<td width='25%'> </td>
<td width='25%'> </td>
<td width='25%'> </td></tr>
<tr><td class='boldbase'>$Lang::tr{'ovpn server status'}</td>
<td align='left'>$sactive</td>
<tr><td class='boldbase'>$Lang::tr{'ovpn on red'}</td>
<td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>
END
;
if (&haveBlueNet()) {
print "<tr><td class='boldbase'>$Lang::tr{'ovpn on blue'}</td>";
print "<td><input type='checkbox' name='ENABLED_BLUE' $checked{'ENABLED_BLUE'}{'on'} /></td>";
}
if (&haveOrangeNet()) {
print "<tr><td class='boldbase'>$Lang::tr{'ovpn on orange'}</td>";
print "<td><input type='checkbox' name='ENABLED_ORANGE' $checked{'ENABLED_ORANGE'}{'on'} /></td>";
}
print <<END
<tr><td class='base' nowrap='nowrap' colspan='2'>$Lang::tr{'local vpn hostname/ip'}:<br /><input type='text' name='VPN_IP' value='$cgiparams{'VPN_IP'}' size='30' /></td>
<td class='boldbase' nowrap='nowrap' colspan='2'>$Lang::tr{'ovpn subnet'}<br /><input type='TEXT' name='DOVPN_SUBNET' value='$cgiparams{'DOVPN_SUBNET'}' size='30' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'ovpn device'}</td>
<td><select name='DDEVICE' ><option value='tun' $selected{'DDEVICE'}{'tun'}>TUN</option>
<!-- this is still not working
<option value='tap' $selected{'DDEVICE'}{'tap'}>TAP</option></select>--> </td>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'protocol'}</td>
<td><select name='DPROTOCOL'><option value='udp' $selected{'DPROTOCOL'}{'udp'}>UDP</option>
<option value='tcp' $selected{'DPROTOCOL'}{'tcp'}>TCP</option></select></td>
<td class='boldbase'>$Lang::tr{'destination port'}:</td>
<td><input type='TEXT' name='DDEST_PORT' value='$cgiparams{'DDEST_PORT'}' size='5' /></td></tr>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'MTU'} </td>
<td> <input type='TEXT' name='DMTU' VALUE='$cgiparams{'DMTU'}'size='5' /></TD>
<tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'comp-lzo'}</td>
<td><input type='checkbox' name='DCOMPLZO' $checked{'DCOMPLZO'}{'on'} /></td>
<td class='boldbase' nowrap='nowrap'>$Lang::tr{'cipher'}</td>
<td><select name='DCIPHER'><option value='DES-CBC' $selected{'DCIPHER'}{'DES-CBC'}>DES-CBC</option>
<option value='DES-EDE-CBC' $selected{'DCIPHER'}{'DES-EDE-CBC'}>DES-EDE-CBC</option>
<option value='DES-EDE3-CBC' $selected{'DCIPHER'}{'DES-EDE3-CBC'}>DES-EDE3-CBC</option>
<option value='DESX-CBC' $selected{'DCIPHER'}{'DESX-CBC'}>DESX-CBC</option>
<option value='RC2-CBC' $selected{'DCIPHER'}{'RC2-CBC'}>RC2-CBC</option>
<option value='RC2-40-CBC' $selected{'DCIPHER'}{'RC2-40-CBC'}>RC2-40-CBC</option>
<option value='RC2-64-CBC' $selected{'DCIPHER'}{'RC2-64-CBC'}>RC2-64-CBC</option>
<option value='BF-CBC' $selected{'DCIPHER'}{'BF-CBC'}>BF-CBC</option>
<option value='CAST5-CBC' $selected{'DCIPHER'}{'CAST5-CBC'}>CAST5-CBC</option>
<option value='AES-128-CBC' $selected{'DCIPHER'}{'AES-128-CBC'}>AES-128-CBC</option>
<option value='AES-192-CBC' $selected{'DCIPHER'}{'AES-192-CBC'}>AES-192-CBC</option>
<option value='AES-256-CBC' $selected{'DCIPHER'}{'AES-256-CBC'}>AES-256-CBC</option></select></td>
END
;
if ( $srunning eq "yes" ) {
print "<tr><td align='left'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' disabled='disabled' /></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'advanced server'}' disabled='disabled'/></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'stop ovpn server'}' /></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'restart ovpn server'}' /></td></tr>";
} else{
print "<tr><td align='left'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'advanced server'}' /></td>";
if (( -e "${General::swroot}/ovpn/ca/cacert.pem" &&
-e "${General::swroot}/ovpn/ca/dh1024.pem" &&
-e "${General::swroot}/ovpn/certs/servercert.pem" &&
-e "${General::swroot}/ovpn/certs/serverkey.pem") &&
(( $cgiparams{'ENABLED'} eq 'on') ||
( $cgiparams{'ENABLED_BLUE'} eq 'on') ||
( $cgiparams{'ENABLED_ORANGE'} eq 'on'))){
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'start ovpn server'}' /></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'restart ovpn server'}' /></td></tr>";
} else {
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'start ovpn server'}' disabled='disabled' /></td>";
print "<td><input type='submit' name='ACTION' value='$Lang::tr{'restart ovpn server'}' disabled='disabled' /></td></tr>";
}
}
print "</form></table>";
&Header::closebox();
&Header::openbox('100%', 'LEFT', "$Lang::tr{'certificate authorities'}:");
print <<EOF#'
<table width='100%' border='0' cellspacing='1' cellpadding='0'>
<tr>
<td width='25%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></td>
<td width='65%' class='boldbase' align='center'><b>$Lang::tr{'subject'}</b></td>
<td width='10%' class='boldbase' colspan='3' align='center'><b>$Lang::tr{'action'}</b></td>
</tr>
EOF
;
if (-f "${General::swroot}/ovpn/ca/cacert.pem") {
my $casubject = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/ca/cacert.pem`;
$casubject =~ /Subject: (.*)[\n]/;
$casubject = $1;
$casubject =~ s+/Email+, E+;
$casubject =~ s/ ST=/ S=/;
print <<END
<tr bgcolor='$color{'color22'}'>
<td class='base'>$Lang::tr{'root certificate'}</td>
<td class='base'>$casubject</td>
<form method='post' name='frmrootcrta'><td width='3%' align='center'>
<input type='hidden' name='ACTION' value='$Lang::tr{'show root certificate'}' />
<input type='image' name='$Lang::tr{'edit'}' src='/images/info.gif' alt='$Lang::tr{'show root certificate'}' title='$Lang::tr{'show root certificate'}' width='20' height='20' border='0' />
</td></form>
<form method='post' name='frmrootcrtb'><td width='3%' align='center'>
<input type='image' name='$Lang::tr{'download root certificate'}' src='/images/media-floppy.png' alt='$Lang::tr{'download root certificate'}' title='$Lang::tr{'download root certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'download root certificate'}' />
</td></form>
<td width='4%'> </td></tr>
END
;
} else {
# display rootcert generation buttons
print <<END
<tr bgcolor='$color{'color22'}'>
<td class='base'>$Lang::tr{'root certificate'}:</td>
<td class='base'>$Lang::tr{'not present'}</td>
<td colspan='3'> </td></tr>
END
;
}
if (-f "${General::swroot}/ovpn/certs/servercert.pem") {
my $hostsubject = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/servercert.pem`;
$hostsubject =~ /Subject: (.*)[\n]/;
$hostsubject = $1;
$hostsubject =~ s+/Email+, E+;
$hostsubject =~ s/ ST=/ S=/;
print <<END
<tr bgcolor='$color{'color20'}'>
<td class='base'>$Lang::tr{'host certificate'}</td>
<td class='base'>$hostsubject</td>
<form method='post' name='frmhostcrta'><td width='3%' align='center'>
<input type='hidden' name='ACTION' value='$Lang::tr{'show host certificate'}' />
<input type='image' name='$Lang::tr{'show host certificate'}' src='/images/info.gif' alt='$Lang::tr{'show host certificate'}' title='$Lang::tr{'show host certificate'}' width='20' height='20' border='0' />
</td></form>
<form method='post' name='frmhostcrtb'><td width='3%' align='center'>
<input type='image' name='$Lang::tr{'download host certificate'}' src='/images/media-floppy.png' alt='$Lang::tr{'download host certificate'}' title='$Lang::tr{'download host certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'download host certificate'}' />
</td></form>
<td width='4%'> </td></tr>
END
;
} else {
# Nothing
print <<END
<tr bgcolor='$color{'color20'}'>
<td width='25%' class='base'>$Lang::tr{'host certificate'}:</td>
<td class='base'>$Lang::tr{'not present'}</td>
</td><td colspan='3'> </td></tr>
END
;
}
if (! -f "${General::swroot}/ovpn/ca/cacert.pem") {
print "<tr><td colspan='5' align='center'><form method='post'>";
print "<input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' />";
print "</form></td></tr>\n";
}
if (keys %cahash > 0) {
foreach my $key (keys %cahash) {
if (($key + 1) % 2) {
print "<tr bgcolor='$color{'color20'}'>\n";
} else {
print "<tr bgcolor='$color{'color22'}'>\n";
}
print "<td class='base'>$cahash{$key}[0]</td>\n";
print "<td class='base'>$cahash{$key}[1]</td>\n";
print <<END
<form method='post' name='cafrm${key}a'><td align='center'>
<input type='image' name='$Lang::tr{'show ca certificate'}' src='/images/info.gif' alt='$Lang::tr{'show ca certificate'}' title='$Lang::tr{'show ca certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'show ca certificate'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
<form method='post' name='cafrm${key}b'><td align='center'>
<input type='image' name='$Lang::tr{'download ca certificate'}' src='/images/media-floppy.png' alt='$Lang::tr{'download ca certificate'}' title='$Lang::tr{'download ca certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'download ca certificate'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
<form method='post' name='cafrm${key}c'><td align='center'>
<input type='hidden' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
<input type='image' name='$Lang::tr{'remove ca certificate'}' src='/images/delete.gif' alt='$Lang::tr{'remove ca certificate'}' title='$Lang::tr{'remove ca certificate'}' width='20' height='20' border='0' />
<input type='hidden' name='KEY' value='$key' />
</td></form></tr>
END
;
}
}
print "</table>";
# If the file contains entries, print Key to action icons
if ( -f "${General::swroot}/ovpn/ca/cacert.pem") {
print <<END
<table>
<tr>
<td class='boldbase'> <b>$Lang::tr{'legend'}:</b></td>
<td> <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
<td class='base'>$Lang::tr{'show certificate'}</td>
<td> <img src='/images/media-floppy.png' alt='$Lang::tr{'download certificate'}' /></td>
<td class='base'>$Lang::tr{'download certificate'}</td>
</tr>
</table>
END
;
}
print <<END
<form method='post' enctype='multipart/form-data'>
<table width='100%' border='0' cellspacing='1' cellpadding='0'>
<tr><td class='base' nowrap='nowrap'>$Lang::tr{'ca name'}:</td>
<td nowrap='nowrap'><input type='text' name='CA_NAME' value='$cgiparams{'CA_NAME'}' size='15' />
<td nowrap='nowrap'><input type='file' name='FH' size='30' /></td>
<td nowrap='nowrap'><input type='submit' name='ACTION' value='$Lang::tr{'upload ca certificate'}' /><br /><input type='submit' name='ACTION' value='$Lang::tr{'show crl'}' /></td>
</tr></table></form>
END
;
&Header::closebox();
if ( $srunning eq "yes" ) {
print "<div align='center'><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' disabled='disabled' /></div></form>\n";
}else{
print "<div align='center'><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></div></form>\n";
}
if ( -f "${General::swroot}/ovpn/ca/cacert.pem" ) {
###
# m.a.d net2net
#<td width='25%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b><br /><img src='/images/null.gif' width='125' height='1' border='0' alt='L2089' /></td>
###
&Header::openbox('100%', 'LEFT', $Lang::tr{'Client status and controlc' });
print <<END
<table width='100%' border='0' cellspacing='1' cellpadding='0'>
<tr>
<td width='10%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></td>
<td width='15%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></td>
<td width='18%' class='boldbase' align='center'><b>$Lang::tr{'common name'}</b></td>
<td width='22%' class='boldbase' align='center'><b>$Lang::tr{'valid till'}</b></td>
<td width='20%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td>
<td width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></td>
<td width='5%' class='boldbase' colspan='6' align='center'><b>$Lang::tr{'action'}</b></td>
</tr>
END
;
my $id = 0;
my $gif;
foreach my $key (sort { uc($confighash{$a}[1]) cmp uc($confighash{$b}[1]) } keys %confighash) {
if ($confighash{$key}[0] eq 'on') { $gif = 'on.gif'; } else { $gif = 'off.gif'; }
if ($id % 2) {
print "<tr bgcolor='$color{'color20'}'>\n";
} else {
print "<tr bgcolor='$color{'color22'}'>\n";
}
print "<td align='center' nowrap='nowrap'>$confighash{$key}[1]</td>";
print "<td align='center' nowrap='nowrap'>" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ")</td>";
if ($confighash{$key}[4] eq 'cert') {
print "<td align='left' nowrap='nowrap'>$confighash{$key}[2]</td>";
} else {
print "<td align='left'> </td>";
}
my $cavalid = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem`;
$cavalid =~ /Not After : (.*)[\n]/;
$cavalid = $1;
print "<td align='center'>$cavalid</td>";
print "<td align='center'>$confighash{$key}[25]</td>";
my $active = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='100%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'capsclosed'}</font></b></td></tr></table>";
if ($confighash{$key}[0] eq 'off') {
$active = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourblue}' width='100%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'capsclosed'}</font></b></td></tr></table>";
} else {
###
# m.a.d net2net
###
if ($confighash{$key}[3] eq 'net') {
if (-e "/var/run/$confighash{$key}[1]n2n.pid") {
my @output = "";
my @tustate = "";
my $tport = $confighash{$key}[22];
my $tnet = new Net::Telnet ( Timeout=>5, Errmode=>'return', Port=>$tport);
if ($tport ne '') {
$tnet->open('127.0.0.1');
@output = $tnet->cmd(String => 'state', Prompt => '/(END.*\n|ERROR:.*\n)/');
@tustate = split(/\,/, $output[1]);
###
#CONNECTING -- OpenVPN's initial state.
#WAIT -- (Client only) Waiting for initial response from server.
#AUTH -- (Client only) Authenticating with server.
#GET_CONFIG -- (Client only) Downloading configuration options from server.
#ASSIGN_IP -- Assigning IP address to virtual network interface.
#ADD_ROUTES -- Adding routes to system.
#CONNECTED -- Initialization Sequence Completed.
#RECONNECTING -- A restart has occurred.
#EXITING -- A graceful exit is in progress.
####
if ( $tustate[1] eq 'CONNECTED') {
$active = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='100%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'capsopen'}</font></b></tr></td></table>";
} else {
$active = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='100%'><tr><td align='center'><b><font color='#FFFFFF'>$tustate[1]</font></b></td></tr></table>";
}
}
}
} else {
my $cn;
my @match = ();
foreach my $line (@status) {
chomp($line);
if ( $line =~ /^(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(\d+),(\d+),(.+)/) {
@match = split(m/^(.+),(\d+\.\d+\.\d+\.\d+\:\d+),(\d+),(\d+),(.+)/, $line);
if ($match[1] ne "Common Name") {
$cn = $match[1];
}
$cn =~ s/[_]/ /g;
if ($cn eq "$confighash{$key}[2]") {
$active = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='100%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'capsopen'}</font></b></td></tr></table>";
}
}
}
}
}
my $disable_clientdl = "disabled='disabled'";
if (( $cgiparams{'ENABLED'} eq 'on') ||
( $cgiparams{'ENABLED_BLUE'} eq 'on') ||
( $cgiparams{'ENABLED_ORANGE'} eq 'on')){
$disable_clientdl = "";
}
print <<END
<td align='center'>$active</td>
<form method='post' name='frm${key}a'><td align='center'>
<input type='image' name='$Lang::tr{'dl client arch'}' $disable_clientdl src='/images/openvpn.png' alt='$Lang::tr{'dl client arch'}' title='$Lang::tr{'dl client arch'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'dl client arch'}' $disable_clientdl />
<input type='hidden' name='KEY' value='$key' $disable_clientdl />
</td></form>
END
;
if ($confighash{$key}[4] eq 'cert') {
print <<END
<form method='post' name='frm${key}b'><td align='center'>
<input type='image' name='$Lang::tr{'show certificate'}' src='/images/info.gif' alt='$Lang::tr{'show certificate'}' title='$Lang::tr{'show certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'show certificate'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
END
; } else {
print "<td> </td>";
}
if ($confighash{$key}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$key}[1].p12") {
print <<END
<form method='post' name='frm${key}c'><td align='center'>
<input type='image' name='$Lang::tr{'download pkcs12 file'}' src='/images/media-floppy.png' alt='$Lang::tr{'download pkcs12 file'}' title='$Lang::tr{'download pkcs12 file'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'download pkcs12 file'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
END
; } elsif ($confighash{$key}[4] eq 'cert') {
print <<END
<form method='post' name='frm${key}c'><td align='center'>
<input type='image' name='$Lang::tr{'download certificate'}' src='/images/media-floppy.png' alt='$Lang::tr{'download certificate'}' title='$Lang::tr{'download certificate'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'download certificate'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
END
; } else {
print "<td> </td>";
}
print <<END
<form method='post' name='frm${key}d'><td align='center'>
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' border='0' />
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
<form method='post' name='frm${key}e'><td align='center'>
<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' width='20' height='20' border='0'/>
<input type='hidden' name='KEY' value='$key' />
</td></form>
<form method='post' name='frm${key}f'><td align='center'>
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' width='20' height='20' border='0' />
<input type='hidden' name='KEY' value='$key' />
</td></form>
</tr>
END
;
$id++;
}
;
# If the config file contains entries, print Key to action icons
if ( $id ) {
print <<END
<table>
<tr>
<td class='boldbase'> <b>$Lang::tr{'legend'}:</b></td>
<td> <img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
<td class='base'>$Lang::tr{'click to disable'}</td>
<td> <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
<td class='base'>$Lang::tr{'show certificate'}</td>
<td> <img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
<td class='base'>$Lang::tr{'edit'}</td>
<td> <img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
<td class='base'>$Lang::tr{'remove'}</td>
</tr>
<tr>
<td> </td>
<td> <img src='/images/off.gif' alt='?OFF' /></td>
<td class='base'>$Lang::tr{'click to enable'}</td>
<td> <img src='/images/media-floppy.png' alt='?FLOPPY' /></td>
<td class='base'>$Lang::tr{'download certificate'}</td>
<td> <img src='/images/openvpn.png' alt='?RELOAD'/></td>
<td class='base'>$Lang::tr{'dl client arch'}</td>
</tr>
</table>
END
;
}
print <<END
<table width='100%'>
<form method='post'>
<tr><td width='50%' ><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>
<td width='50%' ><input type='submit' name='ACTION' value='$Lang::tr{'ovpn con stat'}' $activeonrun /></td></tr>
</form>
</table>
END
;
&Header::closebox();
}
&Header::closepage();
More information about the Development
mailing list