X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=html%2Fcgi-bin%2Fovpnmain.cgi;h=e76a688fe7dcda0b77bf716eb2538342cd775b00;hb=refs%2Fheads%2Fnext;hp=42a7354fc9368efc249c24613dab2286b96de46a;hpb=f99ed824205d8a585c02df4b3f0b4d2b55c2cb33;p=ipfire-2.x.git diff --git a/html/cgi-bin/ovpnmain.cgi b/html/cgi-bin/ovpnmain.cgi old mode 100644 new mode 100755 index 42a7354fc9..c92d0237d2 --- a/html/cgi-bin/ovpnmain.cgi +++ b/html/cgi-bin/ovpnmain.cgi @@ -2,7 +2,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2022 IPFire Team # +# Copyright (C) 2007-2023 IPFire Team # # # # 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 # @@ -33,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"; @@ -137,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;} @@ -493,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; } @@ -1114,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); } @@ -2155,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); @@ -2226,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; @@ -2237,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; @@ -2299,6 +2334,11 @@ else # 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"; @@ -3295,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")) { @@ -3428,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); @@ -4172,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*$/\./; @@ -4265,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'}; @@ -4326,9 +4370,15 @@ 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'}; @@ -5352,31 +5402,56 @@ END END } if ($confighash{$key}[0] eq 'on') { $gif = 'on.gif'; } else { $gif = 'off.gif'; } - if ($id % 2) { - print ""; + + # 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 ""; + + if ($hasExpired || $expiresSoon) { + $col="bgcolor='$color{'color14'}'"; + } elsif ($id % 2) { $col="bgcolor='$color{'color20'}'"; } else { - print ""; $col="bgcolor='$color{'color22'}'"; } - print "$confighash{$key}[1]"; - print "" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ")"; - #if ($confighash{$key}[4] eq 'cert') { - #print "$confighash{$key}[2]"; - #} else { - #print " "; - #} - 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 "$confighash{$key}[1]"; + if ($hasExpired) { + print " ($Lang::tr{'openvpn cert has expired'})"; + } elsif ($expiresSoon) { + print " ($Lang::tr{'openvpn cert expires soon'})"; } - + print ""; + print "" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ")"; print "$confighash{$key}[25]"; $col1="bgcolor='${Header::colourred}'"; my $active = "$Lang::tr{'capsclosed'}"; @@ -5433,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 = "$Lang::tr{'capsopen'}"; @@ -5444,20 +5518,24 @@ END } - print <$active + if ($confighash{$key}[41] eq "pass") { + print <$active -
- - - -
+
+ + + + +
END - ; - if ($confighash{$key}[41] eq "no-pass") { + ; } elsif ($confighash{$key}[41] eq "no-pass") { print < + $active + +
@@ -5465,7 +5543,7 @@ END
END - } else { + ; } else { print " "; } @@ -5541,30 +5619,33 @@ END # If the config file contains entries, print Key to action icons if ( $id ) { print < - + + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - -
  $Lang::tr{'legend'}:  $Lang::tr{$Lang::tr{'click to disable'}    ?RELOAD$Lang::tr{'dl client arch insecure'}    ?RELOAD$Lang::tr{'dl client arch'}     $Lang::tr{ $Lang::tr{'show certificate'}    $Lang::tr{$Lang::tr{'show otp qrcode'}
      ?FLOPPY$Lang::tr{'download certificate'}  ?OFF$Lang::tr{'click to enable'}  $Lang::tr{$Lang::tr{'click to disable'}    $Lang::tr{ $Lang::tr{'edit'}     $Lang::tr{ $Lang::tr{'remove'}
    ?OFF$Lang::tr{'click to enable'}    ?FLOPPY$Lang::tr{'download certificate'}    ?RELOAD$Lang::tr{'dl client arch'}    $Lang::tr{$Lang::tr{'show otp qrcode'}

+ +
END ; }