]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - html/cgi-bin/ovpnmain.cgi
suricata: Change midstream policy to "pass-flow"
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / ovpnmain.cgi
old mode 100644 (file)
new mode 100755 (executable)
index fd6d14a..c92d023
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2014  IPFire Team  <info@ipfire.org>                     #
+# Copyright (C) 2007-2023  IPFire Team  <info@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        #
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
 #                                                                             #
 ###############################################################################
-###
-# Based on IPFireCore 77
-###
+
 use CGI;
 use CGI qw/:standard/;
+use Imager::QRCode;
+use MIME::Base32;
+use MIME::Base64;
+use URI::Encode qw(uri_encode uri_decode);;
 use Net::DNS;
 use Net::Ping;
 use Net::Telnet;
@@ -31,6 +33,7 @@ use File::Temp qw/ tempfile tempdir /;
 use strict;
 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
 use Sort::Naturally;
+use Date::Parse;
 require '/var/ipfire/general-functions.pl';
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
@@ -40,6 +43,7 @@ require "${General::swroot}/location-functions.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}, ${Header::colourblue} );
 undef (@dummy);
@@ -75,6 +79,7 @@ my $name;
 my $col="";
 my $local_serverconf = "${General::swroot}/ovpn/scripts/server.conf.local";
 my $local_clientconf = "${General::swroot}/ovpn/scripts/client.conf.local";
+my $dhparameter = "/etc/ssl/ffdhe4096.pem";
 
 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
 $cgiparams{'ENABLED'} = 'off';
@@ -86,8 +91,6 @@ $cgiparams{'COMPRESSION'} = 'off';
 $cgiparams{'ONLY_PROPOSED'} = 'off';
 $cgiparams{'ACTION'} = '';
 $cgiparams{'CA_NAME'} = '';
-$cgiparams{'DH_NAME'} = 'dh1024.pem';
-$cgiparams{'DHLENGHT'} = '';
 $cgiparams{'DHCP_DOMAIN'} = '';
 $cgiparams{'DHCP_DNS'} = '';
 $cgiparams{'DHCP_WINS'} = '';
@@ -135,6 +138,17 @@ unless (-e "$local_clientconf") {
 ###
 ### Useful functions
 ###
+sub iscertlegacy
+{
+       my $file=$_[0];
+       my @certinfo = &General::system_output("/usr/bin/openssl", "pkcs12", "-info", "-nodes", 
+       "-in", "$file.p12", "-noout", "-passin", "pass:''");
+       if (index ($certinfo[0], "MAC: sha1") != -1) {
+               return 1;
+       }
+       return 0;
+}
+
 sub haveOrangeNet
 {
        if ($netsettings{'CONFIG_TYPE'} == 2) {return 1;}
@@ -218,28 +232,6 @@ sub deletebackupcert
 
 sub pkiconfigcheck
 {
-       # Warning if DH parameter is 1024 bit
-       if (-f "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}") {
-               my @dhparameter = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}");
-               my $dhbit;
-
-               # Loop through the output and search for the DH bit lenght.
-               foreach my $line (@dhparameter) {
-                       if ($line =~ (/(\d+)/)) {
-                               # Assign match to dhbit value.
-                               $dhbit = $1;
-
-                               last;
-                       }
-               }
-
-               # Check if the used key lenght is at least 2048 bit.
-               if ($dhbit < 2048) {
-                       $cryptoerror = "$Lang::tr{'ovpn error dh'}";
-                       goto CRYPTO_ERROR;
-               }
-       }
-
        # Warning if md5 is in usage
        if (-f "${General::swroot}/ovpn/certs/servercert.pem") {
                my @signature = &General::system_output("/usr/bin/openssl", "x509", "-noout", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
@@ -287,7 +279,7 @@ sub writeserverconf {
     print CONF "ca ${General::swroot}/ovpn/ca/cacert.pem\n";
     print CONF "cert ${General::swroot}/ovpn/certs/servercert.pem\n";
     print CONF "key ${General::swroot}/ovpn/certs/serverkey.pem\n";
-    print CONF "dh ${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}\n";
+    print CONF "dh $dhparameter\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";
@@ -372,6 +364,8 @@ sub writeserverconf {
     }
     print CONF "tls-verify /usr/lib/openvpn/verify\n";
     print CONF "crl-verify /var/ipfire/ovpn/crls/cacrl.pem\n";
+    print CONF "auth-user-pass-optional\n";
+    print CONF "reneg-sec 86400\n";
     print CONF "user nobody\n";
     print CONF "group nobody\n";
     print CONF "persist-key\n";
@@ -385,6 +379,11 @@ sub writeserverconf {
     print CONF "# Log clients connecting/disconnecting\n";
     print CONF "client-connect \"/usr/sbin/openvpn-metrics client-connect\"\n";
     print CONF "client-disconnect \"/usr/sbin/openvpn-metrics client-disconnect\"\n";
+    print CONF "\n";
+
+    print CONF "# Enable Management Socket\n";
+    print CONF "management /var/run/openvpn.sock unix\n";
+    print CONF "management-client-auth\n";
 
     # Print server.conf.local if entries exist to server.conf
     if ( !-z $local_serverconf  && $sovpnsettings{'ADDITIONAL_CONFIGS'} eq 'on') {
@@ -461,7 +460,7 @@ sub addccdnet
                return
        }
 
-       if(!&General::validhostname($ccdname))
+       if(!&General::validccdname($ccdname))
        {
                $errormessage=$Lang::tr{'ccd err invalidname'};
                return;
@@ -506,7 +505,7 @@ sub modccdnet
        my %ccdhash=();
 
        # Check if the new name is valid.
-       if(!&General::validhostname($newname)) {
+       if(!&General::validccdname($newname)) {
                $errormessage=$Lang::tr{'ccd err invalidname'};
                return;
        }
@@ -990,7 +989,7 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General
   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/$cgiparams{'DH_NAME'}\n";
+  print SERVERCONF "dh $dhparameter\n";
   print SERVERCONF "# Cipher\n";
   print SERVERCONF "cipher $cgiparams{'DCIPHER'}\n";
 
@@ -1127,6 +1126,9 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General
   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"};
+  if (&iscertlegacy("${General::swroot}/ovpn/certs/$cgiparams{'NAME'}")) {
+       print CLIENTCONF "providers legacy default\n";
+  }
   close(CLIENTCONF);
 
 }
@@ -1348,102 +1350,6 @@ END
     exit (0);
 
 ###
-### Generate DH key step 2
-###
-} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate dh key'} && $cgiparams{'AREUSURE'} eq 'yes') {
-    # Delete if old key exists
-    if (-f "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}") {
-        unlink "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}";
-       }
-       # Create Diffie Hellmann Parameter
-       # The system call is safe, because all arguments are passed as an array.
-       system("/usr/bin/openssl", "dhparam", "-out", "${General::swroot}/ovpn/ca/dh1024.pem", "$cgiparams{'DHLENGHT'}");
-       if ($?) {
-               $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
-               unlink ("${General::swroot}/ovpn/ca/dh1024.pem");
-       }
-
-###
-### Generate DH key step 1
-###
-} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate dh key'}) {
-       &Header::showhttpheaders();
-       &Header::openpage($Lang::tr{'ovpn'}, 1, '');
-       &Header::openbigbox('100%', 'LEFT', '', '');
-       &Header::openbox('100%', 'LEFT', "$Lang::tr{'gen dh'}:");
-       print <<END;
-       <table width='100%'>
-       <tr>
-               <td width='20%'> </td> <td width='15%'></td> <td width='65%'></td>
-       </tr>
-       <tr>
-               <td class='base'>$Lang::tr{'ovpn dh'}:</td>
-               <td align='center'>
-               <form method='post'><input type='hidden' name='AREUSURE' value='yes' />
-               <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
-                       <select name='DHLENGHT'>
-                               <option value='2048' $selected{'DHLENGHT'}{'2048'}>2048 $Lang::tr{'bit'}</option>
-                               <option value='3072' $selected{'DHLENGHT'}{'3072'}>3072 $Lang::tr{'bit'}</option>
-                               <option value='4096' $selected{'DHLENGHT'}{'4096'}>4096 $Lang::tr{'bit'}</option>
-                       </select>
-               </td>
-       </tr>
-       <tr><td colspan='4'><br></td></tr>
-       </table>
-       <table width='100%'>
-       <tr>
-               <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}: </font></b>$Lang::tr{'dh key warn'}
-       </tr>
-       <tr>
-               <td class='base'>$Lang::tr{'dh key warn1'}</td>
-       </tr>
-       <tr><td colspan='2'><br></td></tr>
-       <tr>
-               <td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'generate dh key'}' /></td>
-               </form>
-       </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);
-
-###
-### Upload DH key
-###
-} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload dh key'}) {
-    unless (ref ($cgiparams{'FH'})) {
-         $errormessage = $Lang::tr{'there was no file upload'};
-         goto UPLOADCA_ERROR;
-    }
-    # Move uploaded dh key to a temporary file
-    (my $fh, my $filename) = tempfile( );
-    if (copy ($cgiparams{'FH'}, $fh) != 1) {
-        $errormessage = $!;
-       goto UPLOADCA_ERROR;
-    }
-    my @temp = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "$filename");
-    if ( ! grep(/DH Parameters: \((2048|3072|4096) bit\)/, @temp)) {
-        $errormessage = $Lang::tr{'not a valid dh key'};
-        unlink ($filename);
-        goto UPLOADCA_ERROR;
-    } else {
-       # Delete if old key exists
-       if (-f "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}") {
-               unlink "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}";
-       }
-
-       unless(move($filename, "${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}")) {
-               $errormessage = "$Lang::tr{'dh key move failed'}: $!";
-               unlink ($filename);
-               goto UPLOADCA_ERROR;
-       }
-    }
-###
 ### Upload CA Certificate
 ###
 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload ca certificate'}) {
@@ -1552,7 +1458,7 @@ END
        print "Content-Disposition: filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
 
        my @tmp =  &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
-       print "@tmp";
+       print @tmp;
 
        exit(0);
     } else {
@@ -1667,7 +1573,7 @@ END
        print "Content-Disposition: filename=cacert.pem\r\n\r\n";
 
        my @tmp = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/ca/cacert.pem");
-       print "@tmp";
+       print @tmp;
 
        exit(0);
     }
@@ -1681,7 +1587,7 @@ END
        print "Content-Disposition: filename=servercert.pem\r\n\r\n";
 
        my @tmp = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
-       print "@tmp";
+       print @tmp;
 
        exit(0);
     }
@@ -1698,7 +1604,7 @@ END
        my @tmp = <FILE>;
        close(FILE);
 
-       print "@tmp";
+       print @tmp;
 
        exit(0);
     }
@@ -1958,7 +1864,7 @@ END
            }
        } else {        # child
            unless (exec ('/usr/bin/openssl', 'req', '-nodes',
-                       '-newkey', 'rsa:2048',
+                       '-newkey', 'rsa:4096',
                        '-keyout', "${General::swroot}/ovpn/certs/serverkey.pem",
                        '-out', "${General::swroot}/ovpn/certs/serverreq.pem",
                        '-extensions', 'server',
@@ -2018,21 +1924,6 @@ END
            &cleanssldatabase();
            goto ROOTCERT_ERROR;
        }
-       # Create Diffie Hellmann Parameter
-       # The system call is safe, because all arguments are passed as an array.
-       system('/usr/bin/openssl', 'dhparam', '-out', "${General::swroot}/ovpn/ca/dh1024.pem", "$cgiparams{'DHLENGHT'}");
-       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:
@@ -2082,14 +1973,6 @@ END
        }
        print <<END;
            </select></td>
-       <tr><td class='base'>$Lang::tr{'ovpn dh'}:</td>
-               <td class='base'><select name='DHLENGHT'>
-                               <option value='2048' $selected{'DHLENGHT'}{'2048'}>2048 $Lang::tr{'bit'}</option>
-                               <option value='3072' $selected{'DHLENGHT'}{'3072'}>3072 $Lang::tr{'bit'}</option>
-                               <option value='4096' $selected{'DHLENGHT'}{'4096'}>4096 $Lang::tr{'bit'}</option>
-                       </select>
-               </td>
-       </tr>
 
        <tr><td>&nbsp;</td>
            <td><input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' /></td>
@@ -2097,16 +1980,6 @@ END
        <tr><td class='base' colspan='4' align='left'>
            <img src='/blob.gif' valign='top' alt='*' />&nbsp;$Lang::tr{'required field'}</td></tr>
        <tr><td colspan='2'><br></td></tr>
-       <table width='100%'>
-       <tr>
-               <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}: </font></b>$Lang::tr{'ovpn generating the root and host certificates'}
-               <td class='base'>$Lang::tr{'dh key warn'}</td>
-       </tr>
-       <tr>
-               <td class='base'>$Lang::tr{'dh key warn1'}</td>
-       </tr>
-       <tr><td colspan='2'><br></td></tr>
-       <tr>
        </table>
 
        <table width='100%'>
@@ -2297,6 +2170,10 @@ if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
    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";
+  if (&iscertlegacy("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]")) {
+       print CLIENTCONF "providers legacy default\n";
+  }
+
 
 
     close(CLIENTCONF);
@@ -2337,17 +2214,17 @@ else
     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 "#comment the above line and uncomment 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 "#comment the above line and uncomment 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 "#comment the above line and uncomment 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())){
@@ -2368,10 +2245,18 @@ else
 
                # Extract the certificate
                # This system call is safe, because all arguments are passed as an array.
-               system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
-                       '-clcerts', '-nokeys', '-nodes', '-out', "$file_crt" , '-passin', 'pass:');
-               if ($?) {
-                       die "openssl error: $?";
+               if (&iscertlegacy("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]")) {
+                       system('/usr/bin/openssl', 'pkcs12', '-legacy', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
+                               '-clcerts', '-nokeys', '-nodes', '-out', "$file_crt" , '-passin', 'pass:');
+                       if ($?) {
+                               die "openssl error: $?";
+                       }
+               } else {
+                       system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
+                               '-clcerts', '-nokeys', '-nodes', '-out', "$file_crt" , '-passin', 'pass:');
+                       if ($?) {
+                               die "openssl error: $?";
+                       }
                }
 
                $zip->addFile("$file_crt", "$confighash{$cgiparams{'KEY'}}[1].pem") or die;
@@ -2379,10 +2264,18 @@ else
 
                # Extract the key
                # This system call is safe, because all arguments are passed as an array.
-               system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
-                       '-nocerts', '-nodes', '-out', "$file_key", '-passin', 'pass:');
-               if ($?) {
-                       die "openssl error: $?";
+               if (&iscertlegacy("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]")) {
+                       system('/usr/bin/openssl', 'pkcs12', '-legacy', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
+                               '-nocerts', '-nodes', '-out', "$file_key", '-passin', 'pass:');
+                       if ($?) {
+                               die "openssl error: $?";
+                       }
+               } else {
+                       system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
+                               '-nocerts', '-nodes', '-out', "$file_key", '-passin', 'pass:');
+                       if ($?) {
+                               die "openssl error: $?";
+                       }
                }
 
                $zip->addFile("$file_key", "$confighash{$cgiparams{'KEY'}}[1].key") or die;
@@ -2431,6 +2324,21 @@ else
        print CLIENTCONF "fragment $vpnsettings{'FRAGMENT'}\r\n";
     }
 
+    # Disable storing any credentials in memory
+    print CLIENTCONF "auth-nocache\r\n";
+
+    # Set a fake user name for authentication
+    print CLIENTCONF "auth-token-user USER\r\n";
+    print CLIENTCONF "auth-token TOTP\r\n";
+
+    # If the server is asking for TOTP this needs to happen interactively
+    print CLIENTCONF "auth-retry interact\r\n";
+
+    # Add provider line if certificate is legacy type
+    if (&iscertlegacy("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]")) {
+       print CLIENTCONF "providers legacy default\r\n";
+    }
+
     if ($include_certs) {
        print CLIENTCONF "\r\n";
 
@@ -2593,7 +2501,7 @@ else
     my @tmp = <FILE>;
     close(FILE);
 
-    print "@tmp";
+    print @tmp;
     exit (0);
 
 ###
@@ -2617,19 +2525,58 @@ else
        exit(0);
     }
 
+###
+### Display OTP QRCode
+###
+} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show otp qrcode'}) {
+   &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
+
+   my $qrcode = Imager::QRCode->new(
+      size          => 6,
+      margin        => 0,
+      version       => 0,
+      level         => 'M',
+      mode          => '8-bit',
+      casesensitive => 1,
+      lightcolor    => Imager::Color->new(255, 255, 255),
+      darkcolor     => Imager::Color->new(0, 0, 0),
+   );
+   my $cn = uri_encode($confighash{$cgiparams{'KEY'}}[2]);
+   my $secret = encode_base32(pack('H*', $confighash{$cgiparams{'KEY'}}[44]));
+   my $issuer = uri_encode("$mainsettings{'HOSTNAME'}.$mainsettings{'DOMAINNAME'}");
+   my $qrcodeimg = $qrcode->plot("otpauth://totp/$cn?secret=$secret&issuer=$issuer");
+   my $qrcodeimgdata;
+   $qrcodeimg->write(data => \$qrcodeimgdata, type=> 'png')
+      or die $qrcodeimg->errstr;
+   $qrcodeimgdata = encode_base64($qrcodeimgdata, '');
+
+   &Header::showhttpheaders();
+   &Header::openpage($Lang::tr{'ovpn'}, 1, '');
+   &Header::openbigbox('100%', 'LEFT', '', '');
+   &Header::openbox('100%', 'LEFT', "$Lang::tr{'otp qrcode'}:");
+   print <<END;
+$Lang::tr{'secret'}:&nbsp;$secret</br></br>
+<img alt="$Lang::tr{'otp qrcode'}" src="data:image/png;base64,$qrcodeimgdata">
+END
+   &Header::closebox();
+   print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
+   &Header::closebigbox();
+   &Header::closepage();
+   exit(0);
+
 ###
 ### Display Diffie-Hellman key
 ###
 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show dh'}) {
 
-    if (! -e "${General::swroot}/ovpn/ca/dh1024.pem") {
+    if (! -e "$dhparameter") {
        $errormessage = $Lang::tr{'not present'};
        } else {
                &Header::showhttpheaders();
                &Header::openpage($Lang::tr{'ovpn'}, 1, '');
                &Header::openbigbox('100%', 'LEFT', '', '');
                &Header::openbox('100%', 'LEFT', "$Lang::tr{'dh'}:");
-               my @output = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "${General::swroot}/ovpn/ca/dh1024.pem");
+               my @output = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "$dhparameter");
                my $output = &Header::cleanhtml(join("", @output) ,"y");
                print "<pre>$output</pre>\n";
                &Header::closebox();
@@ -2803,7 +2750,7 @@ print <<END;
 <hr size='1'>
 <table width='100%'>
        <tr>
-               <td class'base'><b>$Lang::tr{'misc-options'}</b></td>
+               <td class='base'><b>$Lang::tr{'misc-options'}</b></td>
        </tr>
 
        <tr>
@@ -2858,7 +2805,7 @@ print <<END;
 <hr size='1'>
 <table width='100%'>
     <tr>
-       <td class'base'><b>$Lang::tr{'log-options'}</b></td>
+       <td class='base'><b>$Lang::tr{'log-options'}</b></td>
     </tr>
     <tr>
        <td width='20%'></td> <td width='30%'> </td><td width='25%'> </td><td width='25%'></td>
@@ -3173,7 +3120,7 @@ END
        my @tmp = <FILE>;
        close(FILE);
 
-       print "@tmp";
+       print @tmp;
        exit (0);
     }
 
@@ -3388,6 +3335,10 @@ END
        print FILE "# Logfile\n";
        print FILE "status-version 1\n";
        print FILE "status /var/run/openvpn/$n2nname[0]-n2n 10\n";
+       if (&iscertlegacy("${General::swroot}/ovpn/certs/$cgiparams{'n2nname'}")) {
+               print CLIENTCONF "providers legacy default\n";
+       }
+
        close FILE;
 
        unless(move("$tempdir/$uplconffilename", "${General::swroot}/ovpn/n2nconf/$n2nname[0]/$uplconffilename2")) {
@@ -3521,7 +3472,7 @@ foreach my $dkey (keys %confighash) {
        $confighash{$key}[31] = $n2ntunmtu[1];
        $confighash{$key}[39] = $n2nauth[1];
        $confighash{$key}[40] = $n2ncipher[1];
-       $confighash{$key}[41] = 'disabled';
+       $confighash{$key}[41] = 'no-pass';
 
   &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
 
@@ -3660,6 +3611,7 @@ if ($confighash{$cgiparams{'KEY'}}) {
                $cgiparams{'DAUTH'}             = $confighash{$cgiparams{'KEY'}}[39];
                $cgiparams{'DCIPHER'}           = $confighash{$cgiparams{'KEY'}}[40];
                $cgiparams{'TLSAUTH'}           = $confighash{$cgiparams{'KEY'}}[41];
+               $cgiparams{'OTP_STATE'}         = $confighash{$cgiparams{'KEY'}}[43];
        } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
        $cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
 
@@ -4264,15 +4216,25 @@ if ($cgiparams{'TYPE'} eq 'net') {
                }
            }
 
-               # Check for RW if client name is already set
-               if ($cgiparams{'TYPE'} eq 'host') {
-                       foreach my $key (keys %confighash) {
-                               if ($confighash{$key}[1] eq $cgiparams{'NAME'}) {
-                                       $errormessage = $Lang::tr{'a connection with this name already exists'};
-                                       goto VPNCONF_ERROR;
-                               }
-                       }
-               }
+           # Check for RW if client name is already set
+           if ($cgiparams{'TYPE'} eq 'host') {
+                   foreach my $key (keys %confighash) {
+                           if ($confighash{$key}[1] eq $cgiparams{'NAME'}) {
+                                   $errormessage = $Lang::tr{'a connection with this name already exists'};
+                                   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;
+                   }
+               }
+           }
 
            # Replace empty strings with a .
            (my $ou = $cgiparams{'CERT_OU'}) =~ s/^\s*$/\./;
@@ -4301,7 +4263,7 @@ if ($cgiparams{'TYPE'} eq 'net') {
                }
            } else {    # child
                unless (exec ('/usr/bin/openssl', 'req', '-nodes',
-                       '-newkey', 'rsa:2048',
+                       '-newkey', 'rsa:4096',
                        '-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")) {
@@ -4357,16 +4319,6 @@ if ($cgiparams{'TYPE'} eq 'net') {
            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'};
 
@@ -4418,8 +4370,24 @@ if ($cgiparams{'TYPE'} eq 'net') {
        $confighash{$key}[39]           = $cgiparams{'DAUTH'};
        $confighash{$key}[40]           = $cgiparams{'DCIPHER'};
 
-       if (($cgiparams{'TYPE'} eq 'host') && ($cgiparams{'CERT_PASS1'} eq "")) {
-               $confighash{$key}[41] = "no-pass";
+       if ($confighash{$key}[41] eq "") {
+               if (($cgiparams{'TYPE'} eq 'host') && ($cgiparams{'CERT_PASS1'} eq "")) {
+                       $confighash{$key}[41] = "no-pass";
+               } elsif (($cgiparams{'TYPE'} eq 'host') && ($cgiparams{'CERT_PASS1'} ne "")) {
+                       $confighash{$key}[41] = "pass";
+               } elsif ($cgiparams{'TYPE'} eq 'net') {
+                       $confighash{$key}[41] = "no-pass";
+               }
+       }
+
+   $confighash{$key}[42] = 'HOTP/T30/6';
+       $confighash{$key}[43] = $cgiparams{'OTP_STATE'};
+       if (($confighash{$key}[43] eq 'on') && ($confighash{$key}[44] eq '')) {
+               my @otp_secret = &General::system_output("/usr/bin/openssl", "rand", "-hex", "20");
+      chomp($otp_secret[0]);
+               $confighash{$key}[44] = $otp_secret[0];
+       } elsif ($confighash{$key}[43] eq '') {
+               $confighash{$key}[44] = '';
        }
 
        &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
@@ -4730,7 +4698,7 @@ if ($cgiparams{'TYPE'} eq 'net') {
        <tr><td colspan=4><hr /></td></tr><tr>
 
        <tr>
-               <td class'base'><b>$Lang::tr{'MTU settings'}</b></td>
+               <td class='base'><b>$Lang::tr{'MTU settings'}</b></td>
        </tr>
 
         <tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'MTU'}</td>
@@ -4754,7 +4722,7 @@ if ($cgiparams{'TYPE'} eq 'net') {
 
 <tr><td colspan=4><hr /></td></tr><tr>
        <tr>
-               <td class'base'><b>$Lang::tr{'ovpn crypt options'}:</b></td>
+               <td class='base'><b>$Lang::tr{'ovpn crypt options'}:</b></td>
        </tr>
 
        <tr><td class='boldbase'>$Lang::tr{'cipher'}</td>
@@ -4835,6 +4803,7 @@ if ($cgiparams{'TYPE'} eq 'host') {
            print"</td></tr></table><br><br>";
                my $name=$cgiparams{'CHECK1'};
                $checked{'RG'}{$cgiparams{'RG'}} = 'CHECKED';
+               $checked{'OTP_STATE'}{$cgiparams{'OTP_STATE'}} = 'CHECKED';
 
        if (! -z "${General::swroot}/ovpn/ccd.conf"){
                print"<table border='0' width='100%' cellspacing='1' cellpadding='0'><tr><td width='1%'></td><td width='30%' class='boldbase' align='center'><b>$Lang::tr{'ccd name'}</td><td width='15%' class='boldbase' align='center'><b>$Lang::tr{'network'}</td><td class='boldbase' align='center' width='18%'><b>$Lang::tr{'ccd clientip'}</td></tr>";
@@ -4970,6 +4939,7 @@ if ($cgiparams{'TYPE'} eq 'host') {
 
        print <<END;
        <table border='0' width='100%'>
+       <tr><td width='20%'>$Lang::tr{'enable otp'}:</td><td colspan='3'><input type='checkbox' name='OTP_STATE' $checked{'OTP_STATE'}{'on'} /></td></tr>
        <tr><td width='20%'>Redirect Gateway:</td><td colspan='3'><input type='checkbox' name='RG' $checked{'RG'}{'on'} /></td></tr>
        <tr><td colspan='4'><b><br>$Lang::tr{'ccd routes'}</b></td></tr>
        <tr><td colspan='4'>&nbsp</td></tr>
@@ -5302,7 +5272,7 @@ END
 
        <tr><td colspan='4'><br></td></tr>
        <tr>
-               <td class'base'><b>$Lang::tr{'net config'}:</b></td>
+               <td class='base'><b>$Lang::tr{'net config'}:</b></td>
        </tr>
     <tr><td colspan='1'><br></td></tr>
 
@@ -5319,7 +5289,7 @@ END
 
        <tr><td colspan='4'><br></td></tr>
        <tr>
-               <td class'base'><b>$Lang::tr{'ovpn crypt options'}:</b></td>
+               <td class='base'><b>$Lang::tr{'ovpn crypt options'}:</b></td>
        </tr>
        <tr><td colspan='1'><br></td></tr>
 
@@ -5375,7 +5345,7 @@ END
        print "<input type='submit' name='ACTION' value='$Lang::tr{'ccd net'}' />";
        print "<input type='submit' name='ACTION' value='$Lang::tr{'advanced server'}' />";
        if (( -e "${General::swroot}/ovpn/ca/cacert.pem" &&
-            -e "${General::swroot}/ovpn/ca/dh1024.pem" &&
+            -e "$dhparameter" &&
             -e "${General::swroot}/ovpn/certs/servercert.pem" &&
             -e "${General::swroot}/ovpn/certs/serverkey.pem") &&
            (( $cgiparams{'ENABLED'} eq 'on') ||
@@ -5413,7 +5383,7 @@ END
        <th width='15%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></th>
        <th width='20%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></th>
        <th width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></th>
-       <th width='5%' class='boldbase' colspan='7' align='center'><b>$Lang::tr{'action'}</b></th>
+       <th width='5%' class='boldbase' colspan='8' align='center'><b>$Lang::tr{'action'}</b></th>
 </tr>
 END
                }
@@ -5427,36 +5397,61 @@ END
        <th width='15%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></th>
        <th width='20%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></th>
        <th width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></th>
-       <th width='5%' class='boldbase' colspan='7' align='center'><b>$Lang::tr{'action'}</b></th>
+       <th width='5%' class='boldbase' colspan='8' align='center'><b>$Lang::tr{'action'}</b></th>
 </tr>
 END
                }
        if ($confighash{$key}[0] eq 'on') { $gif = 'on.gif'; } else { $gif = 'off.gif'; }
-       if ($id % 2) {
-               print "<tr>";
+
+       # Create some simple booleans to check the status
+       my $hasExpired;
+       my $expiresSoon;
+
+       # Fetch information about the certificate for non-N2N connections only
+       if ($confighash{$key}[3] ne 'net') {
+               my @cavalid = &General::system_output("/usr/bin/openssl", "x509", "-text",
+                       "-in", "${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem");
+
+               my $expiryDate = 0;
+
+               # Parse the certificate information
+               foreach my $line (@cavalid) {
+                       if ($line =~ /Not After : (.*)[\n]/) {
+                               $expiryDate = &Date::Parse::str2time($1);
+                               last;
+                       }
+               }
+
+               # Calculate the remaining time
+               my $remainingTime = $expiryDate - time();
+
+               # Determine whether the certificate has already expired, or will so soon
+               $hasExpired = ($remainingTime <= 0);
+               $expiresSoon = ($remainingTime <= 30 * 24 * 3600);
+
+       } else {
+               # Populate booleans with dummy values for N2N connections (#13066)
+               $hasExpired = 0;
+               $expiresSoon = 0;
+       }
+
+       print "<tr>";
+
+       if ($hasExpired || $expiresSoon) {
+               $col="bgcolor='$color{'color14'}'";
+       } elsif ($id % 2) {
                $col="bgcolor='$color{'color20'}'";
        } else {
-               print "<tr>";
                $col="bgcolor='$color{'color22'}'";
        }
-       print "<td align='center' nowrap='nowrap' $col>$confighash{$key}[1]</td>";
-       print "<td align='center' nowrap='nowrap' $col>" . $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'>&nbsp;</td>";
-       #}
-       my @cavalid = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem");
-       my $cavalid;
-
-       foreach my $line (@cavalid) {
-               if ($line =~ /Not After : (.*)[\n]/) {
-                       $cavalid    = $1;
-
-                       last;
-               }
+       print "<td align='center' nowrap='nowrap' $col>$confighash{$key}[1]";
+       if ($hasExpired) {
+               print " ($Lang::tr{'openvpn cert has expired'})";
+       } elsif ($expiresSoon) {
+               print " ($Lang::tr{'openvpn cert expires soon'})";
        }
-
+       print "</td>";
+       print "<td align='center' nowrap='nowrap' $col>" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ")</td>";
        print "<td align='center' $col>$confighash{$key}[25]</td>";
        $col1="bgcolor='${Header::colourred}'";
        my $active = "<b><font color='#FFFFFF'>$Lang::tr{'capsclosed'}</font></b>";
@@ -5513,7 +5508,6 @@ END
                                if ($match[1] ne "Common Name") {
                                        $cn = $match[1];
                                }
-                               $cn =~ s/[_]/ /g;
                                if ($cn eq "$confighash{$key}[2]") {
                                        $col1="bgcolor='${Header::colourgreen}'";
                                        $active = "<b><font color='#FFFFFF'>$Lang::tr{'capsopen'}</font></b>";
@@ -5524,20 +5518,24 @@ END
 }
 
 
-    print <<END;
-       <td align='center' $col1>$active</td>
+       if ($confighash{$key}[41] eq "pass") {
+               print <<END;
+                       <td align='center' $col1>$active</td>
 
-       <form method='post' name='frm${key}a'><td align='center' $col>
-           <input type='image'  name='$Lang::tr{'dl client arch'}' 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'}' />
-           <input type='hidden' name='KEY' value='$key' />
-       </td></form>
+                       <form method='post' name='frm${key}a'><td align='center' $col>
+                           <input type='image'  name='$Lang::tr{'dl client arch'}' src='/images/openvpn_encrypted.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'}' />
+                           <input type='hidden' name='MODE' value='secure' />
+                           <input type='hidden' name='KEY' value='$key' />
+                       </td></form>
 END
-       ;
 
-       if ($confighash{$key}[41] eq "no-pass") {
+       ; } elsif ($confighash{$key}[41] eq "no-pass") {
                print <<END;
-                       <form method='post' name='frm${key}g'><td align='center' $col>
+                       <td align='center' $col1>$active</td>
+
+                       <form method='post' name='frm${key}a'><td align='center' $col>
                                <input type='image'  name='$Lang::tr{'dl client arch insecure'}' src='/images/openvpn.png'
                                        alt='$Lang::tr{'dl client arch insecure'}' title='$Lang::tr{'dl client arch insecure'}' border='0' />
                                <input type='hidden' name='ACTION' value='$Lang::tr{'dl client arch'}' />
@@ -5545,7 +5543,7 @@ END
                                <input type='hidden' name='KEY' value='$key' />
                        </td></form>
 END
-       } else {
+       } else {
                print "<td $col>&nbsp;</td>";
        }
 
@@ -5560,6 +5558,19 @@ END
        ; } else {
            print "<td>&nbsp;</td>";
        }
+
+   if ($confighash{$key}[43] eq 'on') {
+      print <<END;
+<form method='post' name='frm${key}o'><td align='center' $col>
+<input type='image' name='$Lang::tr{'show otp qrcode'}' src='/images/qr-code.png' alt='$Lang::tr{'show otp qrcode'}' title='$Lang::tr{'show otp qrcode'}' border='0' />
+<input type='hidden' name='ACTION' value='$Lang::tr{'show otp qrcode'}' />
+<input type='hidden' name='KEY' value='$key' />
+</td></form>
+END
+; } else {
+      print "<td $col>&nbsp;</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' $col>
@@ -5608,28 +5619,33 @@ END
     # If the config file contains entries, print Key to action icons
     if ( $id ) {
     print <<END;
-    <table border='0'>
-    <tr>
+       <table width='85%' border='0'>
+       <tr>
                <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
-               <td>&nbsp; <img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
-               <td class='base'>$Lang::tr{'click to disable'}</td>
+              <td>&nbsp; &nbsp; <img src='/images/openvpn.png' alt='?RELOAD'/></td>
+              <td class='base'>$Lang::tr{'dl client arch insecure'}</td>
+              <td>&nbsp; &nbsp; <img src='/images/openvpn_encrypted.png' alt='?RELOAD'/></td>
+              <td class='base'>$Lang::tr{'dl client arch'}</td>
                <td>&nbsp; &nbsp; <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
                <td class='base'>$Lang::tr{'show certificate'}</td>
+              <td>&nbsp; &nbsp; <img src='/images/qr-code.png' alt='$Lang::tr{'show otp qrcode'}'/></td>
+              <td class='base'>$Lang::tr{'show otp qrcode'}</td>
+       </tr>
+       <tr>
+              <td>&nbsp; </td>
+              <td>&nbsp; &nbsp; <img src='/images/media-floppy.png' alt='?FLOPPY' /></td>
+              <td class='base'>$Lang::tr{'download certificate'}</td>
+              <td>&nbsp; <img src='/images/off.gif' alt='?OFF' /></td>
+              <td class='base'>$Lang::tr{'click to enable'}</td>
+              <td>&nbsp; <img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
+              <td class='base'>$Lang::tr{'click to disable'}</td>              
+
                <td>&nbsp; &nbsp; <img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
                <td class='base'>$Lang::tr{'edit'}</td>
                <td>&nbsp; &nbsp; <img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
                <td class='base'>$Lang::tr{'remove'}</td>
-    </tr>
-    <tr>
-               <td>&nbsp; </td>
-               <td>&nbsp; <img src='/images/off.gif' alt='?OFF' /></td>
-               <td class='base'>$Lang::tr{'click to enable'}</td>
-               <td>&nbsp; &nbsp; <img src='/images/media-floppy.png' alt='?FLOPPY' /></td>
-               <td class='base'>$Lang::tr{'download certificate'}</td>
-               <td>&nbsp; &nbsp; <img src='/images/openvpn.png' alt='?RELOAD'/></td>
-               <td class='base'>$Lang::tr{'dl client arch'}</td>
-               </tr>
-    </table><br>
+       </tr>
+       </table><br>
 END
     ;
     }
@@ -5751,8 +5767,8 @@ END
     }
 
     # Adding DH parameter to chart
-    if (-f "${General::swroot}/ovpn/ca/dh1024.pem") {
-               my @dhsubject = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "${General::swroot}/ovpn/ca/dh1024.pem");
+    if (-f "$dhparameter") {
+               my @dhsubject = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "$dhparameter");
                my $dhsubject;
 
                foreach my $line (@dhsubject) {
@@ -5765,7 +5781,7 @@ END
 
        print <<END;
                <tr>
-                       <td class='base' $col3>$Lang::tr{'dh parameter'}</td>
+                       <td class='base' $col3>$Lang::tr{'dh'}</td>
                        <td class='base' $col3>$dhsubject</td>
                        <form method='post' name='frmdhparam'><td width='3%' align='center' $col3>
                        <input type='hidden' name='ACTION' value='$Lang::tr{'show dh'}' />
@@ -5781,7 +5797,7 @@ END
                # Nothing
                print <<END;
                <tr>
-                       <td width='25%' class='base' $col3>$Lang::tr{'dh parameter'}:</td>
+                       <td width='25%' class='base' $col3>$Lang::tr{'dh'}:</td>
                        <td class='base' $col3>$Lang::tr{'not present'}</td>
                        </td><td colspan='3' $col3>&nbsp;</td>
                </tr>
@@ -5909,25 +5925,6 @@ END
                                <td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'show crl'}' /></td>
                        </tr>
                </table>
-
-               <br>
-
-               <table border='0' width='100%'>
-                       <tr>
-                               <td colspan='4'><b>$Lang::tr{'ovpn dh parameters'}</b></td>
-                       </tr>
-
-                       <tr>
-                               <td width='40%'>$Lang::tr{'ovpn dh upload'}:</td>
-                               <td width='30%'><input type='file' name='FH' size='25'>
-                               <td width='30%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'upload dh key'}'></td>
-                       </tr>
-
-                       <tr>
-                               <td width='40%'>$Lang::tr{'ovpn dh new key'}:</td>
-                               <td colspan='2' width='60%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'generate dh key'}' /></td>
-                       </tr>
-               </table>
        </form>
 
        <br><hr>