]>
git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - html/cgi-bin/vpnmain.cgi
2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007-2011 IPFire Team info@ipfire.org #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
24 use File
:: Temp qw
/ tempfile tempdir / ;
27 # enable only the following on debugging purpose
29 #use CGI::Carp 'fatalsToBrowser';
31 require '/var/ipfire/general-functions.pl' ;
32 require "${General::swroot}/lang.pl" ;
33 require "${General::swroot}/header.pl" ;
34 require "${General::swroot}/countries.pl" ;
36 #workaround to suppress a warning when a variable is used only once
37 my @dummy = ( ${ Header
:: colourgreen
}, ${ Header
:: colourblue
} );
41 ### Initialize variables
43 my $sleepDelay = 4 ; # after a call to ipsecctrl S or R, wait this delay (seconds) before reading status
44 # (let the ipsec do its job)
53 my $errormessage = '' ;
56 my %mainsettings = ();
57 & General
:: readhash
( "${General::swroot}/main/settings" , \
%mainsettings );
58 & General
:: readhash
( "/srv/web/ipfire/html/themes/" . $mainsettings { 'THEME' }. "/include/colors.txt" , \
%color );
60 & General
:: readhash
( "${General::swroot}/ethernet/settings" , \
%netsettings );
62 my $green_cidr = & General
:: ipcidr
( " $netsettings {'GREEN_NETADDRESS'}/ $netsettings {'GREEN_NETMASK'}" );
63 my $blue_cidr = "# Blue not defined" ;
64 if ( $netsettings { 'BLUE_DEV' }) {
65 $blue_cidr = & General
:: ipcidr
( " $netsettings {'BLUE_NETADDRESS'}/ $netsettings {'BLUE_NETMASK'}" );
67 my $orange_cidr = "# Orange not defined" ;
68 if ( $netsettings { 'ORANGE_DEV' }) {
69 $orange_cidr = & General
:: ipcidr
( " $netsettings {'ORANGE_NETADDRESS'}/ $netsettings {'ORANGE_NETMASK'}" );
72 $cgiparams { 'ENABLED' } = 'off' ;
73 $cgiparams { 'EDIT_ADVANCED' } = 'off' ;
74 $cgiparams { 'ACTION' } = '' ;
75 $cgiparams { 'CA_NAME' } = '' ;
76 $cgiparams { 'KEY' } = '' ;
77 $cgiparams { 'TYPE' } = '' ;
78 $cgiparams { 'ADVANCED' } = '' ;
79 $cgiparams { 'NAME' } = '' ;
80 $cgiparams { 'LOCAL_SUBNET' } = '' ;
81 $cgiparams { 'REMOTE_SUBNET' } = '' ;
82 $cgiparams { 'REMOTE' } = '' ;
83 $cgiparams { 'LOCAL_ID' } = '' ;
84 $cgiparams { 'REMOTE_ID' } = '' ;
85 $cgiparams { 'REMARK' } = '' ;
86 $cgiparams { 'PSK' } = '' ;
87 $cgiparams { 'CERT_NAME' } = '' ;
88 $cgiparams { 'CERT_EMAIL' } = '' ;
89 $cgiparams { 'CERT_OU' } = '' ;
90 $cgiparams { 'CERT_ORGANIZATION' } = '' ;
91 $cgiparams { 'CERT_CITY' } = '' ;
92 $cgiparams { 'CERT_STATE' } = '' ;
93 $cgiparams { 'CERT_COUNTRY' } = '' ;
94 $cgiparams { 'SUBJECTALTNAME' } = '' ;
95 $cgiparams { 'CERT_PASS1' } = '' ;
96 $cgiparams { 'CERT_PASS2' } = '' ;
97 $cgiparams { 'ROOTCERT_HOSTNAME' } = '' ;
98 $cgiparams { 'ROOTCERT_COUNTRY' } = '' ;
99 $cgiparams { 'P12_PASS' } = '' ;
100 $cgiparams { 'ROOTCERT_ORGANIZATION' } = '' ;
101 $cgiparams { 'ROOTCERT_HOSTNAME' } = '' ;
102 $cgiparams { 'ROOTCERT_EMAIL' } = '' ;
103 $cgiparams { 'ROOTCERT_OU' } = '' ;
104 $cgiparams { 'ROOTCERT_CITY' } = '' ;
105 $cgiparams { 'ROOTCERT_STATE' } = '' ;
106 $cgiparams { 'RW_NET' } = '' ;
108 & Header
:: getcgihash
( \
%cgiparams , { 'wantfile' => 1 , 'filevar' => 'FH' });
114 my $hostname = $_ [ 0 ];
115 unless ( $hostname ) { return "No hostname" };
116 my $res = new Net
:: DNS
:: Resolver
;
117 my $query = $res -> search ( " $hostname " );
119 foreach my $rr ( $query -> answer ) {
120 ## Potential bug - we are only looking at A records:
121 return 0 if $rr -> type eq "A" ;
124 return $res -> errorstring ;
128 ### Just return true is one interface is vpn enabled
131 return ( $vpnsettings { 'ENABLED' } eq 'on' );
134 ### old version: maintain serial number to one, without explication.
135 ### this : let the counter go, so that each cert is numbered.
139 if ( open ( FILE
, ">${General::swroot}/certs/serial" )) {
143 if ( open ( FILE
, ">${General::swroot}/certs/index.txt" )) {
147 unlink ( "${General::swroot}/certs/index.txt.old" );
148 unlink ( "${General::swroot}/certs/serial.old" );
149 unlink ( "${General::swroot}/certs/01.pem" );
151 sub newcleanssldatabase
153 if (! - s
"${General::swroot}/certs/serial" ) {
154 open ( FILE
, ">${General::swroot}/certs/serial" );
158 if (! - s
">${General::swroot}/certs/index.txt" ) {
159 system ( "touch ${General::swroot}/certs/index.txt" );
161 unlink ( "${General::swroot}/certs/index.txt.old" );
162 unlink ( "${General::swroot}/certs/serial.old" );
163 # unlink ("${General::swroot}/certs/01.pem"); numbering evolves. Wrong place to delete
167 ### Call openssl and return errormessage if any
171 my $retssl = `/usr/bin/openssl $opt 2>&1` ; #redirect stderr
173 foreach my $line ( split ( /\n/ , $retssl )) {
174 & General
:: log ( "ipsec" , " $line " ) if ( 0 ); # 1 for verbose logging
175 $ret .= '<br>' . $line if ( $line =~ /error|unknown/ );
178 $ret = & Header
:: cleanhtml
( $ret );
180 return $ret ?
" $Lang ::tr{'openssl produced an error'}: $ret " : '' ;
183 ### Obtain a CN from given cert
185 sub getCNfromcert
($) {
186 #&General::log("ipsec", "Extracting name from $_[0]...");
187 my $temp = `/usr/bin/openssl x509 -text -in $_ [0]` ;
188 $temp =~ /Subject:.*CN=(.*)[\n]/ ;
190 $temp =~ s
+/ Email
+, E
+;
191 $temp =~ s/ ST=/ S=/ ;
197 ### Obtain Subject from given cert
199 sub getsubjectfromcert
($) {
200 #&General::log("ipsec", "Extracting subject from $_[0]...");
201 my $temp = `/usr/bin/openssl x509 -text -in $_ [0]` ;
202 $temp =~ /Subject: (.*)[\n]/ ;
204 $temp =~ s
+/ Email
+, E
+;
205 $temp =~ s/ ST=/ S=/ ;
209 ### Combine local subnet and connection name to make a unique name for each connection section
210 ### (this sub is not used now)
212 sub makeconnname
($) {
216 $subnet =~ /^(.*?)\/ (.* ?
)$/; # $1=IP $2=mask
217 my $ip = unpack ( 'N' , & Socket
:: inet_aton
( $1 ));
218 if ( length ( $2 ) > 2 ) {
219 my $mm = unpack ( 'N' , & Socket
:: inet_aton
( $2 ));
220 while ( ( $mm & 1 )== 0 ) {
227 return sprintf ( " %s - %X " , $conn , $ip );
230 ### Write a config file.
232 ###Type=Host : GUI can choose the interface used (RED,GREEN,BLUE) and
233 ### the side is always defined as 'left'.
234 ### configihash[14]: 'VHOST' is allowed
237 sub writeipsecfiles
{
238 my %lconfighash = ();
239 my %lvpnsettings = ();
240 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%lconfighash );
241 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%lvpnsettings );
243 open ( CONF
, ">${General::swroot}/vpn/ipsec.conf" ) or die "Unable to open ${General::swroot}/vpn/ipsec.conf: $!" ;
244 open ( SECRETS
, ">${General::swroot}/vpn/ipsec.secrets" ) or die "Unable to open ${General::swroot}/vpn/ipsec.secrets: $!" ;
247 print CONF
"version 2 \n\n " ;
248 print CONF
"config setup \n " ;
249 print CONF
" \t charondebug= \" dmn 0, mgr 0, ike 0, chd 0, job 0, cfg 0, knl 0, net 0, asn 0, enc 0, lib 0, esp 0, tls 0, tnc 0, imc 0, imv 0, pts 0 \"\n " ;
251 print CONF
"conn %default \n " ;
252 print CONF
" \t keyingtries= %forever \n " ;
255 # Add user includes to config file
256 print CONF
"include /etc/ipsec.user.conf \n " ;
259 print SECRETS
"include /etc/ipsec.user.secrets \n " ;
261 if (- f
"${General::swroot}/certs/hostkey.pem" ) {
262 print SECRETS
": RSA ${General::swroot}/certs/hostkey.pem \n "
264 my $last_secrets = '' ; # old the less specifics connections
266 foreach my $key ( keys %lconfighash ) {
267 next if ( $lconfighash { $key }[ 0 ] ne 'on' );
269 #remote peer is not set? => use '%any'
270 $lconfighash { $key }[ 10 ] = ' %any ' if ( $lconfighash { $key }[ 10 ] eq '' );
273 if ( $lconfighash { $key }[ 26 ] eq 'BLUE' ) {
274 $localside = $netsettings { 'BLUE_ADDRESS' };
275 } elsif ( $lconfighash { $key }[ 26 ] eq 'GREEN' ) {
276 $localside = $netsettings { 'GREEN_ADDRESS' };
277 } elsif ( $lconfighash { $key }[ 26 ] eq 'ORANGE' ) {
278 $localside = $netsettings { 'ORANGE_ADDRESS' };
280 $localside = $lvpnsettings { 'VPN_IP' };
283 print CONF
"conn $lconfighash { $key }[1] \n " ;
284 print CONF
" \t left= $localside \n " ;
285 my $cidr_net =& General
:: ipcidr
( $lconfighash { $key }[ 8 ]);
286 print CONF
" \t leftsubnet= $cidr_net \n " ;
287 print CONF
" \t leftfirewall=yes \n " ;
288 print CONF
" \t lefthostaccess=yes \n " ;
290 print CONF
" \t right= $lconfighash { $key }[10] \n " ;
291 if ( $lconfighash { $key }[ 3 ] eq 'net' ) {
292 my $cidr_net =& General
:: ipcidr
( $lconfighash { $key }[ 11 ]);
293 print CONF
" \t rightsubnet= $cidr_net \n " ;
294 } elsif ( $lconfighash { $key }[ 10 ] eq ' %any ' && $lconfighash { $key }[ 14 ] eq 'on' ) { #vhost allowed for roadwarriors?
295 print CONF
" \t rightsubnet=vhost: %no , %priv \n " ;
298 # Local Cert and Remote Cert (unless auth is DN dn-auth)
299 if ( $lconfighash { $key }[ 4 ] eq 'cert' ) {
300 print CONF
" \t leftcert=${General::swroot}/certs/hostcert.pem \n " ;
301 print CONF
" \t rightcert=${General::swroot}/certs/ $lconfighash { $key }[1]cert.pem \n " if ( $lconfighash { $key }[ 2 ] ne ' %auth -dn' );
304 # Local and Remote IDs
305 print CONF
" \t leftid= \" $lconfighash { $key }[7] \"\n " if ( $lconfighash { $key }[ 7 ]);
306 print CONF
" \t rightid= \" $lconfighash { $key }[9] \"\n " if ( $lconfighash { $key }[ 9 ]);
309 my $pfs = $lconfighash { $key }[ 28 ] eq 'on' ?
'on' : 'off' ;
312 if ( $lconfighash { $key }[ 18 ] && $lconfighash { $key }[ 19 ] && $lconfighash { $key }[ 20 ]) {
314 my @encs = split ( '\|' , $lconfighash { $key }[ 18 ]);
315 my @ints = split ( '\|' , $lconfighash { $key }[ 19 ]);
316 my @groups = split ( '\|' , $lconfighash { $key }[ 20 ]);
318 foreach my $i ( @encs ) {
319 foreach my $j ( @ints ) {
320 foreach my $k ( @groups ) {
321 if ( $comma != 0 ) { print CONF
"," ; } else { $comma = 1 ; }
322 print CONF
" $i - $j -modp $k " ;
326 if ( $lconfighash { $key }[ 24 ] eq 'on' ) { #only proposed algorythms?
332 if ( $lconfighash { $key }[ 21 ] && $lconfighash { $key }[ 22 ]) {
334 my @encs = split ( '\|' , $lconfighash { $key }[ 21 ]);
335 my @ints = split ( '\|' , $lconfighash { $key }[ 22 ]);
336 my @groups = split ( '\|' , $lconfighash { $key }[ 20 ]);
338 foreach my $i ( @encs ) {
339 foreach my $j ( @ints ) {
342 foreach my $k ( @groups ) {
343 if ( $comma != 0 ) { print CONF
"," ; } else { $comma = 1 ; }
349 print CONF
" $i - $j $modp " ;
352 if ( $comma != 0 ) { print CONF
"," ; } else { $comma = 1 ; }
357 if ( $lconfighash { $key }[ 24 ] eq 'on' ) { #only proposed algorythms?
365 if (! $lconfighash { $key }[ 29 ]) {
366 $lconfighash { $key }[ 29 ] = "ikev1" ;
368 print CONF
" \t keyexchange= $lconfighash { $key }[29] \n " ;
371 print CONF
" \t ikelifetime= $lconfighash { $key }[16]h \n " if ( $lconfighash { $key }[ 16 ]);
372 print CONF
" \t keylife= $lconfighash { $key }[17]h \n " if ( $lconfighash { $key }[ 17 ]);
375 print CONF
" \t compress=yes \n " if ( $lconfighash { $key }[ 13 ] eq 'on' );
377 # Dead Peer Detection
378 print CONF
" \t dpddelay=30 \n " ;
379 print CONF
" \t dpdtimeout=120 \n " ;
380 print CONF
" \t dpdaction= $lconfighash { $key }[27] \n " ;
382 # Build Authentication details: LEFTid RIGHTid : PSK psk
384 if ( $lconfighash { $key }[ 4 ] eq 'psk' ) {
385 $psk_line = ( $lconfighash { $key }[ 7 ] ?
$lconfighash { $key }[ 7 ] : $localside ) . " " ;
386 $psk_line .= $lconfighash { $key }[ 9 ] ?
$lconfighash { $key }[ 9 ] : $lconfighash { $key }[ 10 ]; #remoteid or remote address?
387 $psk_line .= " : PSK ' $lconfighash { $key }[5]' \n " ;
388 # if the line contains %any, it is less specific than two IP or ID, so move it at end of file.
389 if ( $psk_line =~ /%any/ ) {
390 $last_secrets .= $psk_line ;
392 print SECRETS
$psk_line ;
394 print CONF
" \t authby=secret \n " ;
396 print CONF
" \t authby=rsasig \n " ;
397 print CONF
" \t leftrsasigkey= %cert \n " ;
398 print CONF
" \t rightrsasigkey= %cert \n " ;
401 # Automatically start only if a net-to-net connection
402 if ( $lconfighash { $key }[ 3 ] eq 'host' ) {
403 print CONF
" \t auto=add \n " ;
404 print CONF
" \t rightsourceip= $lvpnsettings {'RW_NET'} \n " ;
406 print CONF
" \t auto=start \n " ;
410 print SECRETS
$last_secrets if ( $last_secrets );
415 # Hook to regenerate the configuration files.
416 if ( $ENV { "REMOTE_ADDR" } eq "" ) {
422 ### Save main settings
424 if ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' } && $cgiparams { 'TYPE' } eq '' && $cgiparams { 'KEY' } eq '' ) {
425 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
426 unless (& General
:: validfqdn
( $cgiparams { 'VPN_IP' }) || & General
:: validip
( $cgiparams { 'VPN_IP' })
427 || $cgiparams { 'VPN_IP' } eq ' %defaultroute ' ) {
428 $errormessage = $Lang :: tr
{ 'invalid input for hostname' };
432 unless ( $cgiparams { 'VPN_DELAYED_START' } =~ /^[0-9]{1,3}$/ ) { #allow 0-999 seconds !
433 $errormessage = $Lang :: tr
{ 'invalid time period' };
437 if ( $cgiparams { 'RW_NET' } ne '' and !& General
:: validipandmask
( $cgiparams { 'RW_NET' }) ) {
438 $errormessage = $Lang :: tr
{ 'urlfilter invalid ip or mask error' };
442 $vpnsettings { 'ENABLED' } = $cgiparams { 'ENABLED' };
443 $vpnsettings { 'VPN_IP' } = $cgiparams { 'VPN_IP' };
444 $vpnsettings { 'VPN_DELAYED_START' } = $cgiparams { 'VPN_DELAYED_START' };
445 $vpnsettings { 'RW_NET' } = $cgiparams { 'RW_NET' };
446 & General
:: writehash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
449 system ( '/usr/local/bin/ipsecctrl' , 'S' );
451 system ( '/usr/local/bin/ipsecctrl' , 'D' );
458 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'remove x509' } && $cgiparams { 'AREUSURE' } eq 'yes' ) {
459 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
461 foreach my $key ( keys %confighash ) {
462 if ( $confighash { $key }[ 4 ] eq 'cert' ) {
463 delete $confighash { $key };
466 while ( my $file = glob ( "${General::swroot}/{ca,certs,crls,private}/*" )) {
470 if ( open ( FILE
, ">${General::swroot}/vpn/caconfig" )) {
474 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
476 system ( '/usr/local/bin/ipsecctrl' , 'R' );
482 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'remove x509' }) {
483 & Header
:: showhttpheaders
();
484 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
485 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
486 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'are you sure' });
488 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
492 <input type='hidden' name='AREUSURE' value='yes' />
493 <b><font color='${Header::colourred}'> $Lang ::tr{'capswarning'}</font></b>:
494 $Lang ::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}</td>
497 <input type='submit' name='ACTION' value=' $Lang ::tr{'remove x509'}' />
498 <input type='submit' name='ACTION' value=' $Lang ::tr{'cancel'}' /></td>
505 & Header
:: closebigbox
();
506 & Header
:: closepage
();
510 ### Upload CA Certificate
512 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'upload ca certificate' }) {
513 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
515 if ( $cgiparams { 'CA_NAME' } !~ /^[a-zA-Z0-9]+$/ ) {
516 $errormessage = $Lang :: tr
{ 'name must only contain characters' };
520 if ( length ( $cgiparams { 'CA_NAME' }) > 60 ) {
521 $errormessage = $Lang :: tr
{ 'name too long' };
525 if ( $cgiparams { 'CA_NAME' } eq 'ca' ) {
526 $errormessage = $Lang :: tr
{ 'name is invalid' };
527 goto UPLOAD_CA_ERROR
;
530 # Check if there is no other entry with this name
531 foreach my $key ( keys %cahash ) {
532 if ( $cahash { $key }[ 0 ] eq $cgiparams { 'CA_NAME' }) {
533 $errormessage = $Lang :: tr
{ 'a ca certificate with this name already exists' };
538 if ( ref ( $cgiparams { 'FH' }) ne 'Fh' ) {
539 $errormessage = $Lang :: tr
{ 'there was no file upload' };
542 # Move uploaded ca to a temporary file
543 ( my $fh , my $filename ) = tempfile
( );
544 if ( copy
( $cgiparams { 'FH' }, $fh ) != 1 ) {
548 my $temp = `/usr/bin/openssl x509 -text -in $filename ` ;
549 if ( $temp !~ /CA:TRUE/i ) {
550 $errormessage = $Lang :: tr
{ 'not a valid ca certificate' };
554 move
( $filename , "${General::swroot}/ca/ $cgiparams {'CA_NAME'}cert.pem" );
556 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" ;
562 my $key = & General
:: findhasharraykey
( \
%cahash );
563 $cahash { $key }[ 0 ] = $cgiparams { 'CA_NAME' };
564 $cahash { $key }[ 1 ] = & Header
:: cleanhtml
( getsubjectfromcert
( "${General::swroot}/ca/ $cgiparams {'CA_NAME'}cert.pem" ));
565 & General
:: writehasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
567 system ( '/usr/local/bin/ipsecctrl' , 'R' );
573 ### Display ca certificate
575 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'show ca certificate' }) {
576 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
578 if ( - f
"${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" ) {
579 & Header
:: showhttpheaders
();
580 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
581 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
582 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'ca certificate'}:" );
583 my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem` ;
584 $output = & Header
:: cleanhtml
( $output , "y" );
585 print "<pre> $output </pre> \n " ;
587 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'> $Lang ::tr{'back'}</a></div>" ;
588 & Header
:: closebigbox
();
589 & Header
:: closepage
();
592 $errormessage = $Lang :: tr
{ 'invalid key' };
596 ### Export ca certificate to browser
598 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'download ca certificate' }) {
599 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
601 if ( - f
"${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" ) {
602 print "Content-Type: application/force-download \n " ;
603 print "Content-Type: application/octet-stream \r\n " ;
604 print "Content-Disposition: attachment; filename= $cahash { $cgiparams {'KEY'}}[0]cert.pem \r\n\r\n " ;
605 print `/usr/bin/openssl x509 -in ${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem` ;
608 $errormessage = $Lang :: tr
{ 'invalid key' };
612 ### Remove ca certificate (step 2)
614 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'remove ca certificate' } && $cgiparams { 'AREUSURE' } eq 'yes' ) {
615 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
616 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
618 if ( - f
"${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" ) {
619 foreach my $key ( keys %confighash ) {
620 my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem ${General::swroot}/certs/ $confighash { $key }[1]cert.pem` ;
621 if ( $test =~ /: OK/ ) {
623 system ( '/usr/local/bin/ipsecctrl' , 'D' , $key ) if (& vpnenabled
);
624 unlink ( "${General::swroot}/certs/ $confighash { $key }[1]cert.pem" );
625 unlink ( "${General::swroot}/certs/ $confighash { $key }[1].p12" );
626 delete $confighash { $key };
627 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
631 unlink ( "${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" );
632 delete $cahash { $cgiparams { 'KEY' }};
633 & General
:: writehasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
634 system ( '/usr/local/bin/ipsecctrl' , 'R' );
637 $errormessage = $Lang :: tr
{ 'invalid key' };
640 ### Remove ca certificate (step 1)
642 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'remove ca certificate' }) {
643 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
644 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
646 my $assignedcerts = 0 ;
647 if ( - f
"${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" ) {
648 foreach my $key ( keys %confighash ) {
649 my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem ${General::swroot}/certs/ $confighash { $key }[1]cert.pem` ;
650 if ( $test =~ /: OK/ ) {
654 if ( $assignedcerts ) {
655 & Header
:: showhttpheaders
();
656 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
657 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
658 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'are you sure' });
660 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
664 <input type='hidden' name='KEY' value=' $cgiparams {'KEY'}' />
665 <input type='hidden' name='AREUSURE' value='yes' /></td>
668 <b><font color='${Header::colourred}'> $Lang ::tr{'capswarning'}</font></b>
669 $Lang ::tr{'connections are associated with this ca. deleting the ca will delete these connections as well.'}</td>
672 <input type='submit' name='ACTION' value=' $Lang ::tr{'remove ca certificate'}' />
673 <input type='submit' name='ACTION' value=' $Lang ::tr{'cancel'}' /></td>
680 & Header
:: closebigbox
();
681 & Header
:: closepage
();
684 unlink ( "${General::swroot}/ca/ $cahash { $cgiparams {'KEY'}}[0]cert.pem" );
685 delete $cahash { $cgiparams { 'KEY' }};
686 & General
:: writehasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
687 system ( '/usr/local/bin/ipsecctrl' , 'R' );
691 $errormessage = $Lang :: tr
{ 'invalid key' };
695 ### Display root certificate
697 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'show root certificate' } ||
698 $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'show host certificate' }) {
700 & Header
:: showhttpheaders
();
701 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
702 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
703 if ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'show root certificate' }) {
704 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'root certificate'}:" );
705 $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/cacert.pem` ;
707 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'host certificate'}:" );
708 $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/hostcert.pem` ;
710 $output = & Header
:: cleanhtml
( $output , "y" );
711 print "<pre> $output </pre> \n " ;
713 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'> $Lang ::tr{'back'}</a></div>" ;
714 & Header
:: closebigbox
();
715 & Header
:: closepage
();
719 ### Export root certificate to browser
721 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'download root certificate' }) {
722 if ( - f
"${General::swroot}/ca/cacert.pem" ) {
723 print "Content-Type: application/force-download \n " ;
724 print "Content-Disposition: attachment; filename=cacert.pem \r\n\r\n " ;
725 print `/usr/bin/openssl x509 -in ${General::swroot}/ca/cacert.pem` ;
729 ### Export host certificate to browser
731 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'download host certificate' }) {
732 if ( - f
"${General::swroot}/certs/hostcert.pem" ) {
733 print "Content-Type: application/force-download \n " ;
734 print "Content-Disposition: attachment; filename=hostcert.pem \r\n\r\n " ;
735 print `/usr/bin/openssl x509 -in ${General::swroot}/certs/hostcert.pem` ;
739 ### Form for generating/importing the caroot+host certificate
741 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'generate root/host certificates' } ||
742 $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'upload p12 file' }) {
744 if (- f
"${General::swroot}/ca/cacert.pem" ) {
745 $errormessage = $Lang :: tr
{ 'valid root certificate already exists' };
749 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
750 # fill in initial values
751 if ( $cgiparams { 'ROOTCERT_HOSTNAME' } eq '' ) {
752 if (- e
"${General::swroot}/red/active" && open ( IPADDR
, "${General::swroot}/red/local-ipaddress" )) {
753 my $ipaddr = < IPADDR
>;
756 $cgiparams { 'ROOTCERT_HOSTNAME' } = ( gethostbyaddr ( pack ( "C4" , split ( /\./ , $ipaddr )), 2 ))[ 0 ];
757 if ( $cgiparams { 'ROOTCERT_HOSTNAME' } eq '' ) {
758 $cgiparams { 'ROOTCERT_HOSTNAME' } = $ipaddr ;
761 $cgiparams { 'ROOTCERT_COUNTRY' } = $vpnsettings { 'ROOTCERT_COUNTRY' } if (! $cgiparams { 'ROOTCERT_COUNTRY' });
762 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'upload p12 file' }) {
763 & General
:: log ( "ipsec" , "Importing from p12..." );
765 if ( ref ( $cgiparams { 'FH' }) ne 'Fh' ) {
766 $errormessage = $Lang :: tr
{ 'there was no file upload' };
770 # Move uploaded certificate request to a temporary file
771 ( my $fh , my $filename ) = tempfile
( );
772 if ( copy
( $cgiparams { 'FH' }, $fh ) != 1 ) {
777 # Extract the CA certificate from the file
778 & General
:: log ( "ipsec" , "Extracting caroot from p12..." );
779 if ( open ( STDIN
, "-|" )) {
780 my $opt = " pkcs12 -cacerts -nokeys" ;
781 $opt .= " -in $filename " ;
782 $opt .= " -out /tmp/newcacert" ;
783 $errormessage = & callssl
( $opt );
785 print " $cgiparams {'P12_PASS'} \n " ;
789 # Extract the Host certificate from the file
790 if (! $errormessage ) {
791 & General
:: log ( "ipsec" , "Extracting host cert from p12..." );
792 if ( open ( STDIN
, "-|" )) {
793 my $opt = " pkcs12 -clcerts -nokeys" ;
794 $opt .= " -in $filename " ;
795 $opt .= " -out /tmp/newhostcert" ;
796 $errormessage = & callssl
( $opt );
798 print " $cgiparams {'P12_PASS'} \n " ;
803 # Extract the Host key from the file
804 if (! $errormessage ) {
805 & General
:: log ( "ipsec" , "Extracting private key from p12..." );
806 if ( open ( STDIN
, "-|" )) {
807 my $opt = " pkcs12 -nocerts -nodes" ;
808 $opt .= " -in $filename " ;
809 $opt .= " -out /tmp/newhostkey" ;
810 $errormessage = & callssl
( $opt );
812 print " $cgiparams {'P12_PASS'} \n " ;
817 if (! $errormessage ) {
818 & General
:: log ( "ipsec" , "Moving cacert..." );
819 move
( "/tmp/newcacert" , "${General::swroot}/ca/cacert.pem" );
820 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" if ($ ?
ne 0 );
823 if (! $errormessage ) {
824 & General
:: log ( "ipsec" , "Moving host cert..." );
825 move
( "/tmp/newhostcert" , "${General::swroot}/certs/hostcert.pem" );
826 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" if ($ ?
ne 0 );
829 if (! $errormessage ) {
830 & General
:: log ( "ipsec" , "Moving private key..." );
831 move
( "/tmp/newhostkey" , "${General::swroot}/certs/hostkey.pem" );
832 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" if ($ ?
ne 0 );
837 unlink ( '/tmp/newcacert' );
838 unlink ( '/tmp/newhostcert' );
839 unlink ( '/tmp/newhostkey' );
841 unlink ( "${General::swroot}/ca/cacert.pem" );
842 unlink ( "${General::swroot}/certs/hostcert.pem" );
843 unlink ( "${General::swroot}/certs/hostkey.pem" );
847 # Create empty CRL cannot be done because we don't have
848 # the private key for this CAROOT
849 # IPFire can only import certificates
851 & General
:: log ( "ipsec" , "p12 import completed!" );
853 goto ROOTCERT_SUCCESS
;
855 } elsif ( $cgiparams { 'ROOTCERT_COUNTRY' } ne '' ) {
857 # Validate input since the form was submitted
858 if ( $cgiparams { 'ROOTCERT_ORGANIZATION' } eq '' ){
859 $errormessage = $Lang :: tr
{ 'organization cant be empty' };
862 if ( length ( $cgiparams { 'ROOTCERT_ORGANIZATION' }) > 60 ) {
863 $errormessage = $Lang :: tr
{ 'organization too long' };
866 if ( $cgiparams { 'ROOTCERT_ORGANIZATION' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
867 $errormessage = $Lang :: tr
{ 'invalid input for organization' };
870 if ( $cgiparams { 'ROOTCERT_HOSTNAME' } eq '' ){
871 $errormessage = $Lang :: tr
{ 'hostname cant be empty' };
874 unless (& General
:: validfqdn
( $cgiparams { 'ROOTCERT_HOSTNAME' }) || & General
:: validip
( $cgiparams { 'ROOTCERT_HOSTNAME' })) {
875 $errormessage = $Lang :: tr
{ 'invalid input for hostname' };
878 if ( $cgiparams { 'ROOTCERT_EMAIL' } ne '' && (! & General
:: validemail
( $cgiparams { 'ROOTCERT_EMAIL' }))) {
879 $errormessage = $Lang :: tr
{ 'invalid input for e-mail address' };
882 if ( length ( $cgiparams { 'ROOTCERT_EMAIL' }) > 40 ) {
883 $errormessage = $Lang :: tr
{ 'e-mail address too long' };
886 if ( $cgiparams { 'ROOTCERT_OU' } ne '' && $cgiparams { 'ROOTCERT_OU' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
887 $errormessage = $Lang :: tr
{ 'invalid input for department' };
890 if ( $cgiparams { 'ROOTCERT_CITY' } ne '' && $cgiparams { 'ROOTCERT_CITY' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
891 $errormessage = $Lang :: tr
{ 'invalid input for city' };
894 if ( $cgiparams { 'ROOTCERT_STATE' } ne '' && $cgiparams { 'ROOTCERT_STATE' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
895 $errormessage = $Lang :: tr
{ 'invalid input for state or province' };
898 if ( $cgiparams { 'ROOTCERT_COUNTRY' } !~ /^[A-Z]*$/ ) {
899 $errormessage = $Lang :: tr
{ 'invalid input for country' };
902 #the exact syntax is a list comma separated of
903 # email:any-validemail
904 # URI: a uniform resource indicator
905 # DNS: a DNS domain name
906 # RID: a registered OBJECT IDENTIFIER
908 # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
910 if ( $cgiparams { 'SUBJECTALTNAME' } ne '' && $cgiparams { 'SUBJECTALTNAME' } !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/ , \
. \
- _@
]*$/) {
911 $errormessage = $Lang :: tr
{ 'vpn altname syntax' };
915 # Copy the cgisettings to vpnsettings and save the configfile
916 $vpnsettings { 'ROOTCERT_ORGANIZATION' } = $cgiparams { 'ROOTCERT_ORGANIZATION' };
917 $vpnsettings { 'ROOTCERT_HOSTNAME' } = $cgiparams { 'ROOTCERT_HOSTNAME' };
918 $vpnsettings { 'ROOTCERT_EMAIL' } = $cgiparams { 'ROOTCERT_EMAIL' };
919 $vpnsettings { 'ROOTCERT_OU' } = $cgiparams { 'ROOTCERT_OU' };
920 $vpnsettings { 'ROOTCERT_CITY' } = $cgiparams { 'ROOTCERT_CITY' };
921 $vpnsettings { 'ROOTCERT_STATE' } = $cgiparams { 'ROOTCERT_STATE' };
922 $vpnsettings { 'ROOTCERT_COUNTRY' } = $cgiparams { 'ROOTCERT_COUNTRY' };
923 & General
:: writehash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
925 # Replace empty strings with a .
926 ( my $ou = $cgiparams { 'ROOTCERT_OU' }) =~ s/^\s*$/\./ ;
927 ( my $city = $cgiparams { 'ROOTCERT_CITY' }) =~ s/^\s*$/\./ ;
928 ( my $state = $cgiparams { 'ROOTCERT_STATE' }) =~ s/^\s*$/\./ ;
930 # Create the CA certificate
931 if (! $errormessage ) {
932 & General
:: log ( "ipsec" , "Creating cacert..." );
933 if ( open ( STDIN
, "-|" )) {
934 my $opt = " req -x509 -nodes -rand /proc/interrupts:/proc/net/rt_cache" ;
935 $opt .= " -days 999999" ;
936 $opt .= " -newkey rsa:2048" ;
937 $opt .= " -keyout ${General::swroot}/private/cakey.pem" ;
938 $opt .= " -out ${General::swroot}/ca/cacert.pem" ;
940 $errormessage = & callssl
( $opt );
942 print " $cgiparams {'ROOTCERT_COUNTRY'} \n " ;
945 print " $cgiparams {'ROOTCERT_ORGANIZATION'} \n " ;
947 print " $cgiparams {'ROOTCERT_ORGANIZATION'} CA \n " ;
948 print " $cgiparams {'ROOTCERT_EMAIL'} \n " ;
953 # Create the Host certificate request
954 if (! $errormessage ) {
955 & General
:: log ( "ipsec" , "Creating host cert..." );
956 if ( open ( STDIN
, "-|" )) {
957 my $opt = " req -nodes -rand /proc/interrupts:/proc/net/rt_cache" ;
958 $opt .= " -newkey rsa:1024" ;
959 $opt .= " -keyout ${General::swroot}/certs/hostkey.pem" ;
960 $opt .= " -out ${General::swroot}/certs/hostreq.pem" ;
961 $errormessage = & callssl
( $opt );
963 print " $cgiparams {'ROOTCERT_COUNTRY'} \n " ;
966 print " $cgiparams {'ROOTCERT_ORGANIZATION'} \n " ;
968 print " $cgiparams {'ROOTCERT_HOSTNAME'} \n " ;
969 print " $cgiparams {'ROOTCERT_EMAIL'} \n " ;
976 # Sign the host certificate request
977 if (! $errormessage ) {
978 & General
:: log ( "ipsec" , "Self signing host cert..." );
980 #No easy way for specifying the contain of subjectAltName without writing a config file...
981 my ( $fh , $v3extname ) = tempfile
( '/tmp/XXXXXXXX' );
983 basicConstraints=CA:FALSE
984 nsComment="OpenSSL Generated Certificate"
985 subjectKeyIdentifier=hash
986 authorityKeyIdentifier=keyid,issuer:always
987 extendedKeyUsage = serverAuth
990 print $fh "subjectAltName= $cgiparams {'SUBJECTALTNAME'}" if ( $cgiparams { 'SUBJECTALTNAME' });
993 my $opt = " ca -days 999999" ;
994 $opt .= " -batch -notext" ;
995 $opt .= " -in ${General::swroot}/certs/hostreq.pem" ;
996 $opt .= " -out ${General::swroot}/certs/hostcert.pem" ;
997 $opt .= " -extfile $v3extname " ;
998 $errormessage = & callssl
( $opt );
999 unlink ( "${General::swroot}/certs/hostreq.pem" ); #no more needed
1000 unlink ( $v3extname );
1003 # Create an empty CRL
1004 if (! $errormessage ) {
1005 & General
:: log ( "ipsec" , "Creating emptycrl..." );
1006 my $opt = " ca -gencrl" ;
1007 $opt .= " -out ${General::swroot}/crls/cacrl.pem" ;
1008 $errormessage = & callssl
( $opt );
1011 # Successfully build CA / CERT!
1012 if (! $errormessage ) {
1013 & cleanssldatabase
();
1014 goto ROOTCERT_SUCCESS
;
1018 unlink ( "${General::swroot}/ca/cacert.pem" );
1019 unlink ( "${General::swroot}/certs/hostkey.pem" );
1020 unlink ( "${General::swroot}/certs/hostcert.pem" );
1021 unlink ( "${General::swroot}/crls/cacrl.pem" );
1022 & cleanssldatabase
();
1026 & Header
:: showhttpheaders
();
1027 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
1028 & Header
:: openbigbox
( '100%' , 'left' , '' , $errormessage );
1029 if ( $errormessage ) {
1030 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'error messages' });
1031 print "<class name='base'> $errormessage " ;
1032 print " </class>" ;
1033 & Header
:: closebox
();
1035 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'generate root/host certificates'}:" );
1037 <form method='post' enctype='multipart/form-data' action=' $ENV {'SCRIPT_NAME'}'>
1038 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
1039 <tr><td width='40%' class='base'> $Lang ::tr{'organization name'}:</td>
1040 <td width='60%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value=' $cgiparams {'ROOTCERT_ORGANIZATION'}' size='32' /></td></tr>
1041 <tr><td class='base'> $Lang ::tr{'ipfires hostname'}:</td>
1042 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value=' $cgiparams {'ROOTCERT_HOSTNAME'}' size='32' /></td></tr>
1043 <tr><td class='base'> $Lang ::tr{'your e-mail'}: <img src='/blob.gif' alt='*' /></td>
1044 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value=' $cgiparams {'ROOTCERT_EMAIL'}' size='32' /></td></tr>
1045 <tr><td class='base'> $Lang ::tr{'your department'}: <img src='/blob.gif' alt='*' /></td>
1046 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value=' $cgiparams {'ROOTCERT_OU'}' size='32' /></td></tr>
1047 <tr><td class='base'> $Lang ::tr{'city'}: <img src='/blob.gif' alt='*' /></td>
1048 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value=' $cgiparams {'ROOTCERT_CITY'}' size='32' /></td></tr>
1049 <tr><td class='base'> $Lang ::tr{'state or province'}: <img src='/blob.gif' alt='*' /></td>
1050 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value=' $cgiparams {'ROOTCERT_STATE'}' size='32' /></td></tr>
1051 <tr><td class='base'> $Lang ::tr{'country'}:</td>
1052 <td class='base'><select name='ROOTCERT_COUNTRY'>
1055 foreach my $country ( sort keys %{ Countries
:: countries
}) {
1056 print "<option value=' $Countries ::countries{ $country }'" ;
1057 if ( $Countries :: countries
{ $country } eq $cgiparams { 'ROOTCERT_COUNTRY' } ) {
1058 print " selected='selected'" ;
1060 print "> $country </option>" ;
1064 <tr><td class='base'> $Lang ::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*) <img src='/blob.gif' alt='*' /></td>
1065 <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value=' $cgiparams {'SUBJECTALTNAME'}' size='32' /></td></tr>
1067 <td><br /><input type='submit' name='ACTION' value=' $Lang ::tr{'generate root/host certificates'}' /><br /><br /></td></tr>
1068 <tr><td class='base' colspan='2' align='left'>
1069 <b><font color='${Header::colourred}'> $Lang ::tr{'capswarning'}</font></b>:
1070 $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'}
1072 <tr><td colspan='2'><hr /></td></tr>
1073 <tr><td class='base' nowrap='nowrap'> $Lang ::tr{'upload p12 file'}:</td>
1074 <td nowrap='nowrap'><input type='file' name='FH' size='32' /></td></tr>
1075 <tr><td class='base'> $Lang ::tr{'pkcs12 file password'}: <img src='/blob.gif' alt='*' /></td>
1076 <td class='base' nowrap='nowrap'><input type='password' name='P12_PASS' value=' $cgiparams {'P12_PASS'}' size='32' /></td></tr>
1078 <td><input type='submit' name='ACTION' value=' $Lang ::tr{'upload p12 file'}' /></td></tr>
1079 <tr><td class='base' colspan='2' align='left'>
1080 <img src='/blob.gif' alt='*' /> $Lang ::tr{'this field may be blank'}</td></tr>
1084 & Header
:: closebox
();
1085 & Header
:: closebigbox
();
1086 & Header
:: closepage
();
1091 system ( '/usr/local/bin/ipsecctrl' , 'S' );
1096 ### Export PKCS12 file to browser
1098 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'download pkcs12 file' }) {
1099 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1100 print "Content-Type: application/force-download \n " ;
1101 print "Content-Disposition: attachment; filename=" . $confighash { $cgiparams { 'KEY' }}[ 1 ] . ".p12 \r\n " ;
1102 print "Content-Type: application/octet-stream \r\n\r\n " ;
1103 print `/bin/cat ${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1].p12` ;
1107 ### Display certificate
1109 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'show certificate' }) {
1110 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1112 if ( - f
"${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1]cert.pem" ) {
1113 & Header
:: showhttpheaders
();
1114 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
1115 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
1116 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'cert'}:" );
1117 my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1]cert.pem` ;
1118 $output = & Header
:: cleanhtml
( $output , "y" );
1119 print "<pre> $output </pre> \n " ;
1120 & Header
:: closebox
();
1121 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'> $Lang ::tr{'back'}</a></div>" ;
1122 & Header
:: closebigbox
();
1123 & Header
:: closepage
();
1128 ### Export Certificate to browser
1130 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'download certificate' }) {
1131 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1133 if ( - f
"${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1]cert.pem" ) {
1134 print "Content-Type: application/force-download \n " ;
1135 print "Content-Disposition: attachment; filename=" . $confighash { $cgiparams { 'KEY' }}[ 1 ] . "cert.pem \n\n " ;
1136 print `/bin/cat ${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1]cert.pem` ;
1141 ### Enable/Disable connection
1143 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'toggle enable disable' }) {
1145 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
1146 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1148 if ( $confighash { $cgiparams { 'KEY' }}) {
1149 if ( $confighash { $cgiparams { 'KEY' }}[ 0 ] eq 'off' ) {
1150 $confighash { $cgiparams { 'KEY' }}[ 0 ] = 'on' ;
1151 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1153 system ( '/usr/local/bin/ipsecctrl' , 'S' , $cgiparams { 'KEY' }) if (& vpnenabled
);
1155 system ( '/usr/local/bin/ipsecctrl' , 'D' , $cgiparams { 'KEY' }) if (& vpnenabled
);
1156 $confighash { $cgiparams { 'KEY' }}[ 0 ] = 'off' ;
1157 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1162 $errormessage = $Lang :: tr
{ 'invalid key' };
1166 ### Restart connection
1168 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'restart' }) {
1169 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
1170 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1172 if ( $confighash { $cgiparams { 'KEY' }}) {
1174 system ( '/usr/local/bin/ipsecctrl' , 'S' , $cgiparams { 'KEY' });
1178 $errormessage = $Lang :: tr
{ 'invalid key' };
1182 ### Remove connection
1184 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'remove' }) {
1185 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
1186 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1188 if ( $confighash { $cgiparams { 'KEY' }}) {
1189 system ( '/usr/local/bin/ipsecctrl' , 'D' , $cgiparams { 'KEY' }) if (& vpnenabled
);
1190 unlink ( "${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1]cert.pem" );
1191 unlink ( "${General::swroot}/certs/ $confighash { $cgiparams {'KEY'}}[1].p12" );
1192 delete $confighash { $cgiparams { 'KEY' }};
1193 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1196 $errormessage = $Lang :: tr
{ 'invalid key' };
1200 ### Choose between adding a host-net or net-net connection
1202 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'add' } && $cgiparams { 'TYPE' } eq '' ) {
1203 & Header
:: showhttpheaders
();
1204 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
1205 & Header
:: openbigbox
( '100%' , 'left' , '' , '' );
1206 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'connection type' });
1208 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
1209 <b> $Lang ::tr{'connection type'}:</b><br />
1211 <tr><td><input type='radio' name='TYPE' value='host' checked='checked' /></td>
1212 <td class='base'> $Lang ::tr{'host to net vpn'}</td>
1214 <td><input type='radio' name='TYPE' value='net' /></td>
1215 <td class='base'> $Lang ::tr{'net to net vpn'}</td>
1217 <td align='center' colspan='2'><input type='submit' name='ACTION' value=' $Lang ::tr{'add'}' /></td>
1222 & Header
:: closebox
();
1223 & Header
:: closebigbox
();
1224 & Header
:: closepage
();
1227 ### Adding/Editing/Saving a connection
1229 } elsif (( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'add' }) ||
1230 ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'edit' }) ||
1231 ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' } && $cgiparams { 'ADVANCED' } eq '' )) {
1233 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
1234 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
1235 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1237 if ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'edit' }) {
1238 if (! $confighash { $cgiparams { 'KEY' }}[ 0 ]) {
1239 $errormessage = $Lang :: tr
{ 'invalid key' };
1242 $cgiparams { 'ENABLED' } = $confighash { $cgiparams { 'KEY' }}[ 0 ];
1243 $cgiparams { 'NAME' } = $confighash { $cgiparams { 'KEY' }}[ 1 ];
1244 $cgiparams { 'TYPE' } = $confighash { $cgiparams { 'KEY' }}[ 3 ];
1245 $cgiparams { 'AUTH' } = $confighash { $cgiparams { 'KEY' }}[ 4 ];
1246 $cgiparams { 'PSK' } = $confighash { $cgiparams { 'KEY' }}[ 5 ];
1247 #$cgiparams{'free'} = $confighash{$cgiparams{'KEY'}}[6];
1248 $cgiparams { 'LOCAL_ID' } = $confighash { $cgiparams { 'KEY' }}[ 7 ];
1249 $cgiparams { 'LOCAL_SUBNET' } = $confighash { $cgiparams { 'KEY' }}[ 8 ];
1250 $cgiparams { 'REMOTE_ID' } = $confighash { $cgiparams { 'KEY' }}[ 9 ];
1251 $cgiparams { 'REMOTE' } = $confighash { $cgiparams { 'KEY' }}[ 10 ];
1252 $cgiparams { 'REMOTE_SUBNET' } = $confighash { $cgiparams { 'KEY' }}[ 11 ];
1253 $cgiparams { 'REMARK' } = $confighash { $cgiparams { 'KEY' }}[ 25 ];
1254 $cgiparams { 'DPD_ACTION' } = $confighash { $cgiparams { 'KEY' }}[ 27 ];
1255 $cgiparams { 'IKE_VERSION' } = $confighash { $cgiparams { 'KEY' }}[ 29 ];
1256 $cgiparams { 'IKE_ENCRYPTION' } = $confighash { $cgiparams { 'KEY' }}[ 18 ];
1257 $cgiparams { 'IKE_INTEGRITY' } = $confighash { $cgiparams { 'KEY' }}[ 19 ];
1258 $cgiparams { 'IKE_GROUPTYPE' } = $confighash { $cgiparams { 'KEY' }}[ 20 ];
1259 $cgiparams { 'IKE_LIFETIME' } = $confighash { $cgiparams { 'KEY' }}[ 16 ];
1260 $cgiparams { 'ESP_ENCRYPTION' } = $confighash { $cgiparams { 'KEY' }}[ 21 ];
1261 $cgiparams { 'ESP_INTEGRITY' } = $confighash { $cgiparams { 'KEY' }}[ 22 ];
1262 $cgiparams { 'ESP_GROUPTYPE' } = $confighash { $cgiparams { 'KEY' }}[ 23 ];
1263 $cgiparams { 'ESP_KEYLIFE' } = $confighash { $cgiparams { 'KEY' }}[ 17 ];
1264 $cgiparams { 'COMPRESSION' } = $confighash { $cgiparams { 'KEY' }}[ 13 ];
1265 $cgiparams { 'ONLY_PROPOSED' } = $confighash { $cgiparams { 'KEY' }}[ 24 ];
1266 $cgiparams { 'PFS' } = $confighash { $cgiparams { 'KEY' }}[ 28 ];
1267 $cgiparams { 'VHOST' } = $confighash { $cgiparams { 'KEY' }}[ 14 ];
1269 } elsif ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' }) {
1270 $cgiparams { 'REMARK' } = & Header
:: cleanhtml
( $cgiparams { 'REMARK' });
1271 if ( $cgiparams { 'TYPE' } !~ /^(host|net)$/ ) {
1272 $errormessage = $Lang :: tr
{ 'connection type is invalid' };
1276 if ( $cgiparams { 'NAME' } !~ /^[a-zA-Z0-9]+$/ ) {
1277 $errormessage = $Lang :: tr
{ 'name must only contain characters' };
1281 if ( $cgiparams { 'NAME' } =~ /^(host|01|block|private|clear|packetdefault)$/ ) {
1282 $errormessage = $Lang :: tr
{ 'name is invalid' };
1286 if ( length ( $cgiparams { 'NAME' }) > 60 ) {
1287 $errormessage = $Lang :: tr
{ 'name too long' };
1291 # Check if there is no other entry with this name
1292 if (! $cgiparams { 'KEY' }) { #only for add
1293 foreach my $key ( keys %confighash ) {
1294 if ( $confighash { $key }[ 1 ] eq $cgiparams { 'NAME' }) {
1295 $errormessage = $Lang :: tr
{ 'a connection with this name already exists' };
1301 if (( $cgiparams { 'TYPE' } eq 'net' ) && (! $cgiparams { 'REMOTE' })) {
1302 $errormessage = $Lang :: tr
{ 'invalid input for remote host/ip' };
1306 if ( $cgiparams { 'REMOTE' }) {
1307 if (( $cgiparams { 'REMOTE' } ne ' %any ' ) && (! & General
:: validip
( $cgiparams { 'REMOTE' }))) {
1308 if (! & General
:: validfqdn
( $cgiparams { 'REMOTE' })) {
1309 $errormessage = $Lang :: tr
{ 'invalid input for remote host/ip' };
1312 if (& valid_dns_host
( $cgiparams { 'REMOTE' })) {
1313 $warnmessage = " $Lang ::tr{'check vpn lr'} $cgiparams {'REMOTE'}. $Lang ::tr{'dns check failed'}" ;
1319 unless (& General
:: validipandmask
( $cgiparams { 'LOCAL_SUBNET' })) {
1320 $errormessage = $Lang :: tr
{ 'local subnet is invalid' };
1324 # Allow only one roadwarrior/psk without remote IP-address
1325 if ( $cgiparams { 'REMOTE' } eq '' && $cgiparams { 'AUTH' } eq 'psk' ) {
1326 foreach my $key ( keys %confighash ) {
1327 if ( ( $cgiparams { 'KEY' } ne $key ) &&
1328 ( $confighash { $key }[ 4 ] eq 'psk' ) &&
1329 ( $confighash { $key }[ 10 ] eq '' ) ) {
1330 $errormessage = $Lang :: tr
{ 'you can only define one roadwarrior connection when using pre-shared key authentication' };
1335 if (( $cgiparams { 'TYPE' } eq 'net' ) && (! & General
:: validipandmask
( $cgiparams { 'REMOTE_SUBNET' }))) {
1336 $errormessage = $Lang :: tr
{ 'remote subnet is invalid' };
1340 if ( $cgiparams { 'ENABLED' } !~ /^(on|off)$/ ) {
1341 $errormessage = $Lang :: tr
{ 'invalid input' };
1344 if ( $cgiparams { 'EDIT_ADVANCED' } !~ /^(on|off)$/ ) {
1345 $errormessage = $Lang :: tr
{ 'invalid input' };
1349 # Allow nothing or a string (DN,FDQN,) beginning with @
1350 # with no comma but slashes between RID eg @O=FR/C=Paris/OU=myhome/CN=franck
1351 if ( ( $cgiparams { 'LOCAL_ID' } !~ /^(|[\w.-]*@[\w. =*\/ -]+| \d
+ \
. \d
+ \
. \d
+ \
. \d
+)$/) ||
1352 ( $cgiparams { 'REMOTE_ID' } !~ /^(|[\w.-]*@[\w. =*\/ -]+| \d
+ \
. \d
+ \
. \d
+ \
. \d
+)$/) ||
1353 (( $cgiparams { 'REMOTE_ID' } eq $cgiparams { 'LOCAL_ID' }) && ( $cgiparams { 'LOCAL_ID' } ne '' ))
1355 $errormessage = $Lang :: tr
{ 'invalid local-remote id' } . '<br />' .
1356 'DER_ASN1_DN: @c =FR/ou=Paris/ou=Home/cn=*<br />' .
1357 'FQDN: @ipfire .org<br />' .
1358 'USER_FQDN: info @ipfire .org<br />' .
1359 'IPV4_ADDR: 123.123.123.123' ;
1362 # If Auth is DN, verify existance of Remote ID.
1363 if ( $cgiparams { 'REMOTE_ID' } eq '' && (
1364 $cgiparams { 'AUTH' } eq 'auth-dn' || # while creation
1365 $confighash { $cgiparams { 'KEY' }}[ 2 ] eq ' %auth -dn' )){ # while editing
1366 $errormessage = $Lang :: tr
{ 'vpn missing remote id' };
1371 if ( $cgiparams { 'TYPE' } eq 'net' ){
1372 $errormessage =& General
:: checksubnets
( $cgiparams { 'NAME' }, $cgiparams { 'REMOTE_SUBNET' });
1373 if ( $errormessage ne '' ){
1378 if ( $cgiparams { 'AUTH' } eq 'psk' ) {
1379 if (! length ( $cgiparams { 'PSK' }) ) {
1380 $errormessage = $Lang :: tr
{ 'pre-shared key is too short' };
1383 if ( $cgiparams { 'PSK' } =~ /'/ ) {
1384 $cgiparams { 'PSK' } =~ tr/'/ / ;
1385 $errormessage = $Lang :: tr
{ 'invalid characters found in pre-shared key' };
1388 } elsif ( $cgiparams { 'AUTH' } eq 'certreq' ) {
1389 if ( $cgiparams { 'KEY' }) {
1390 $errormessage = $Lang :: tr
{ 'cant change certificates' };
1393 if ( ref ( $cgiparams { 'FH' }) ne 'Fh' ) {
1394 $errormessage = $Lang :: tr
{ 'there was no file upload' };
1398 # Move uploaded certificate request to a temporary file
1399 ( my $fh , my $filename ) = tempfile
( );
1400 if ( copy
( $cgiparams { 'FH' }, $fh ) != 1 ) {
1405 # Sign the certificate request
1406 & General
:: log ( "ipsec" , "Signing your cert $cgiparams {'NAME'}..." );
1407 my $opt = " ca -days 999999" ;
1408 $opt .= " -batch -notext" ;
1409 $opt .= " -in $filename " ;
1410 $opt .= " -out ${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" ;
1412 if ( $errormessage = & callssl
( $opt ) ) {
1414 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1415 & cleanssldatabase
();
1419 & cleanssldatabase
();
1422 $cgiparams { 'CERT_NAME' } = getCNfromcert
( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1423 if ( $cgiparams { 'CERT_NAME' } eq '' ) {
1424 $errormessage = $Lang :: tr
{ 'could not retrieve common name from certificate' };
1427 } elsif ( $cgiparams { 'AUTH' } eq 'pkcs12' ) {
1428 & General
:: log ( "ipsec" , "Importing from p12..." );
1430 if ( ref ( $cgiparams { 'FH' }) ne 'Fh' ) {
1431 $errormessage = $Lang :: tr
{ 'there was no file upload' };
1432 goto ROOTCERT_ERROR
;
1435 # Move uploaded certificate request to a temporary file
1436 ( my $fh , my $filename ) = tempfile
( );
1437 if ( copy
( $cgiparams { 'FH' }, $fh ) != 1 ) {
1439 goto ROOTCERT_ERROR
;
1442 # Extract the CA certificate from the file
1443 & General
:: log ( "ipsec" , "Extracting caroot from p12..." );
1444 if ( open ( STDIN
, "-|" )) {
1445 my $opt = " pkcs12 -cacerts -nokeys" ;
1446 $opt .= " -in $filename " ;
1447 $opt .= " -out /tmp/newcacert" ;
1448 $errormessage = & callssl
( $opt );
1450 print " $cgiparams {'P12_PASS'} \n " ;
1454 # Extract the Host certificate from the file
1455 if (! $errormessage ) {
1456 & General
:: log ( "ipsec" , "Extracting host cert from p12..." );
1457 if ( open ( STDIN
, "-|" )) {
1458 my $opt = " pkcs12 -clcerts -nokeys" ;
1459 $opt .= " -in $filename " ;
1460 $opt .= " -out /tmp/newhostcert" ;
1461 $errormessage = & callssl
( $opt );
1463 print " $cgiparams {'P12_PASS'} \n " ;
1468 if (! $errormessage ) {
1469 & General
:: log ( "ipsec" , "Moving cacert..." );
1470 #If CA have new subject, add it to our list of CA
1471 my $casubject = & Header
:: cleanhtml
( getsubjectfromcert
( '/tmp/newcacert' ));
1473 foreach my $x ( keys %cahash ) {
1474 $casubject = '' if ( $cahash { $x }[ 1 ] eq $casubject );
1475 unshift ( @names , $cahash { $x }[ 0 ]);
1477 if ( $casubject ) { # a new one!
1478 my $temp = `/usr/bin/openssl x509 -text -in /tmp/newcacert` ;
1479 if ( $temp !~ /CA:TRUE/i ) {
1480 $errormessage = $Lang :: tr
{ 'not a valid ca certificate' };
1482 #compute a name for it
1484 while ( grep ( /Imported-$idx/ , @names ) ) { $idx ++};
1485 $cgiparams { 'CA_NAME' }= "Imported- $idx " ;
1486 $cgiparams { 'CERT_NAME' }=& Header
:: cleanhtml
( getCNfromcert
( '/tmp/newhostcert' ));
1487 move
( "/tmp/newcacert" , "${General::swroot}/ca/ $cgiparams {'CA_NAME'}cert.pem" );
1488 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" if ($ ?
ne 0 );
1489 if (! $errormessage ) {
1490 my $key = & General
:: findhasharraykey
( \
%cahash );
1491 $cahash { $key }[ 0 ] = $cgiparams { 'CA_NAME' };
1492 $cahash { $key }[ 1 ] = $casubject ;
1493 & General
:: writehasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
1494 system ( '/usr/local/bin/ipsecctrl' , 'R' );
1499 if (! $errormessage ) {
1500 & General
:: log ( "ipsec" , "Moving host cert..." );
1501 move
( "/tmp/newhostcert" , "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1502 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" if ($ ?
ne 0 );
1507 unlink ( '/tmp/newcacert' );
1508 unlink ( '/tmp/newhostcert' );
1509 if ( $errormessage ) {
1510 unlink ( "${General::swroot}/ca/ $cgiparams {'CA_NAME'}cert.pem" );
1511 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1514 & General
:: log ( "ipsec" , "p12 import completed!" );
1515 } elsif ( $cgiparams { 'AUTH' } eq 'certfile' ) {
1516 if ( $cgiparams { 'KEY' }) {
1517 $errormessage = $Lang :: tr
{ 'cant change certificates' };
1520 if ( ref ( $cgiparams { 'FH' }) ne 'Fh' ) {
1521 $errormessage = $Lang :: tr
{ 'there was no file upload' };
1524 # Move uploaded certificate to a temporary file
1525 ( my $fh , my $filename ) = tempfile
( );
1526 if ( copy
( $cgiparams { 'FH' }, $fh ) != 1 ) {
1531 # Verify the certificate has a valid CA and move it
1532 & General
:: log ( "ipsec" , "Validating imported cert against our known CA..." );
1533 my $validca = 1 ; #assume ok
1534 my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/cacert.pem $filename ` ;
1535 if ( $test !~ /: OK/ ) {
1537 foreach my $key ( keys %cahash ) {
1538 $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/ $cahash { $key }[0]cert.pem $filename ` ;
1539 if ( $test =~ /: OK/ ) {
1546 $errormessage = $Lang :: tr
{ 'certificate does not have a valid ca associated with it' };
1550 move
( $filename , "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1552 $errormessage = " $Lang ::tr{'certificate file move failed'}: $!" ;
1558 $cgiparams { 'CERT_NAME' } = getCNfromcert
( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1559 if ( $cgiparams { 'CERT_NAME' } eq '' ) {
1560 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1561 $errormessage = $Lang :: tr
{ 'could not retrieve common name from certificate' };
1564 } elsif ( $cgiparams { 'AUTH' } eq 'certgen' ) {
1565 if ( $cgiparams { 'KEY' }) {
1566 $errormessage = $Lang :: tr
{ 'cant change certificates' };
1569 # Validate input since the form was submitted
1570 if ( length ( $cgiparams { 'CERT_NAME' }) > 60 ) {
1571 $errormessage = $Lang :: tr
{ 'name too long' };
1574 if ( $cgiparams { 'CERT_NAME' } !~ /^[a-zA-Z0-9 ,\.\-_]+$/ ) {
1575 $errormessage = $Lang :: tr
{ 'invalid input for name' };
1578 if ( $cgiparams { 'CERT_EMAIL' } ne '' && (! & General
:: validemail
( $cgiparams { 'CERT_EMAIL' }))) {
1579 $errormessage = $Lang :: tr
{ 'invalid input for e-mail address' };
1582 if ( length ( $cgiparams { 'CERT_EMAIL' }) > 40 ) {
1583 $errormessage = $Lang :: tr
{ 'e-mail address too long' };
1586 if ( $cgiparams { 'CERT_OU' } ne '' && $cgiparams { 'CERT_OU' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
1587 $errormessage = $Lang :: tr
{ 'invalid input for department' };
1590 if ( length ( $cgiparams { 'CERT_ORGANIZATION' }) > 60 ) {
1591 $errormessage = $Lang :: tr
{ 'organization too long' };
1594 if ( $cgiparams { 'CERT_ORGANIZATION' } !~ /^[a-zA-Z0-9 ,\.\-_]+$/ ) {
1595 $errormessage = $Lang :: tr
{ 'invalid input for organization' };
1598 if ( $cgiparams { 'CERT_CITY' } ne '' && $cgiparams { 'CERT_CITY' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
1599 $errormessage = $Lang :: tr
{ 'invalid input for city' };
1602 if ( $cgiparams { 'CERT_STATE' } ne '' && $cgiparams { 'CERT_STATE' } !~ /^[a-zA-Z0-9 ,\.\-_]*$/ ) {
1603 $errormessage = $Lang :: tr
{ 'invalid input for state or province' };
1606 if ( $cgiparams { 'CERT_COUNTRY' } !~ /^[A-Z]*$/ ) {
1607 $errormessage = $Lang :: tr
{ 'invalid input for country' };
1610 #the exact syntax is a list comma separated of
1611 # email:any-validemail
1612 # URI: a uniform resource indicator
1613 # DNS: a DNS domain name
1614 # RID: a registered OBJECT IDENTIFIER
1616 # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
1618 if ( $cgiparams { 'SUBJECTALTNAME' } ne '' && $cgiparams { 'SUBJECTALTNAME' } !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/ , \
. \
- _@
]*$/) {
1619 $errormessage = $Lang :: tr
{ 'vpn altname syntax' };
1623 if ( length ( $cgiparams { 'CERT_PASS1' }) < 5 ) {
1624 $errormessage = $Lang :: tr
{ 'password too short' };
1627 if ( $cgiparams { 'CERT_PASS1' } ne $cgiparams { 'CERT_PASS2' }) {
1628 $errormessage = $Lang :: tr
{ 'passwords do not match' };
1632 # Replace empty strings with a .
1633 ( my $ou = $cgiparams { 'CERT_OU' }) =~ s/^\s*$/\./ ;
1634 ( my $city = $cgiparams { 'CERT_CITY' }) =~ s/^\s*$/\./ ;
1635 ( my $state = $cgiparams { 'CERT_STATE' }) =~ s/^\s*$/\./ ;
1637 # Create the Host certificate request
1638 & General
:: log ( "ipsec" , "Creating a cert..." );
1640 if ( open ( STDIN
, "-|" )) {
1641 my $opt = " req -nodes -rand /proc/interrupts:/proc/net/rt_cache" ;
1642 $opt .= " -newkey rsa:1024" ;
1643 $opt .= " -keyout ${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" ;
1644 $opt .= " -out ${General::swroot}/certs/ $cgiparams {'NAME'}req.pem" ;
1646 if ( $errormessage = & callssl
( $opt ) ) {
1647 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" );
1648 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}req.pem" );
1652 print " $cgiparams {'CERT_COUNTRY'} \n " ;
1655 print " $cgiparams {'CERT_ORGANIZATION'} \n " ;
1657 print " $cgiparams {'CERT_NAME'} \n " ;
1658 print " $cgiparams {'CERT_EMAIL'} \n " ;
1664 # Sign the host certificate request
1665 & General
:: log ( "ipsec" , "Signing the cert $cgiparams {'NAME'}..." );
1667 #No easy way for specifying the contain of subjectAltName without writing a config file...
1668 my ( $fh , $v3extname ) = tempfile
( '/tmp/XXXXXXXX' );
1670 basicConstraints=CA:FALSE
1671 nsComment="OpenSSL Generated Certificate"
1672 subjectKeyIdentifier=hash
1673 authorityKeyIdentifier=keyid,issuer:always
1676 print $fh "subjectAltName= $cgiparams {'SUBJECTALTNAME'}" if ( $cgiparams { 'SUBJECTALTNAME' });
1679 my $opt = " ca -days 999999 -batch -notext" ;
1680 $opt .= " -in ${General::swroot}/certs/ $cgiparams {'NAME'}req.pem" ;
1681 $opt .= " -out ${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" ;
1682 $opt .= " -extfile $v3extname " ;
1684 if ( $errormessage = & callssl
( $opt ) ) {
1685 unlink ( $v3extname );
1686 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" );
1687 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}req.pem" );
1688 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1689 & cleanssldatabase
();
1692 unlink ( $v3extname );
1693 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}req.pem" );
1694 & cleanssldatabase
();
1697 # Create the pkcs12 file
1698 & General
:: log ( "ipsec" , "Packing a pkcs12 file..." );
1699 $opt = " pkcs12 -export" ;
1700 $opt .= " -inkey ${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" ;
1701 $opt .= " -in ${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" ;
1702 $opt .= " -name \" $cgiparams {'NAME'} \" " ;
1703 $opt .= " -passout pass: $cgiparams {'CERT_PASS1'}" ;
1704 $opt .= " -certfile ${General::swroot}/ca/cacert.pem" ;
1705 $opt .= " -caname \" $vpnsettings {'ROOTCERT_ORGANIZATION'} CA \" " ;
1706 $opt .= " -out ${General::swroot}/certs/ $cgiparams {'NAME'}.p12" ;
1708 if ( $errormessage = & callssl
( $opt ) ) {
1709 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" );
1710 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}cert.pem" );
1711 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}.p12" );
1714 unlink ( "${General::swroot}/certs/ $cgiparams {'NAME'}key.pem" );
1716 } elsif ( $cgiparams { 'AUTH' } eq 'cert' ) {
1717 ; # Nothing, just editing
1718 } elsif ( $cgiparams { 'AUTH' } eq 'auth-dn' ) {
1719 $cgiparams { 'CERT_NAME' } = ' %auth -dn' ; # a special value saying 'no cert file'
1721 $errormessage = $Lang :: tr
{ 'invalid input for authentication method' };
1725 # 1)Error message here is not accurate.
1726 # 2)Test is superfluous, openswan can reference same cert multiple times
1727 # 3)Present since initial version (1.3.2.11), it isn't a bug correction
1728 # Check if there is no other entry with this certificate name
1729 #if ((! $cgiparams{'KEY'}) && ($cgiparams{'AUTH'} ne 'psk') && ($cgiparams{'AUTH'} ne 'auth-dn')) {
1730 # foreach my $key (keys %confighash) {
1731 # if ($confighash{$key}[2] eq $cgiparams{'CERT_NAME'}) {
1732 # $errormessage = $Lang::tr{'a connection with this common name already exists'};
1733 # goto VPNCONF_ERROR;
1739 my $key = $cgiparams { 'KEY' };
1741 $key = & General
:: findhasharraykey
( \
%confighash );
1742 foreach my $i ( 0 .. 28 ) { $confighash { $key }[ $i ] = "" ;}
1744 $confighash { $key }[ 0 ] = $cgiparams { 'ENABLED' };
1745 $confighash { $key }[ 1 ] = $cgiparams { 'NAME' };
1746 if ((! $cgiparams { 'KEY' }) && $cgiparams { 'AUTH' } ne 'psk' ) {
1747 $confighash { $key }[ 2 ] = $cgiparams { 'CERT_NAME' };
1749 $confighash { $key }[ 3 ] = $cgiparams { 'TYPE' };
1750 if ( $cgiparams { 'AUTH' } eq 'psk' ) {
1751 $confighash { $key }[ 4 ] = 'psk' ;
1752 $confighash { $key }[ 5 ] = $cgiparams { 'PSK' };
1754 $confighash { $key }[ 4 ] = 'cert' ;
1756 if ( $cgiparams { 'TYPE' } eq 'net' ) {
1757 $confighash { $key }[ 11 ] = $cgiparams { 'REMOTE_SUBNET' };
1759 $confighash { $key }[ 7 ] = $cgiparams { 'LOCAL_ID' };
1760 $confighash { $key }[ 8 ] = $cgiparams { 'LOCAL_SUBNET' };
1761 $confighash { $key }[ 9 ] = $cgiparams { 'REMOTE_ID' };
1762 $confighash { $key }[ 10 ] = $cgiparams { 'REMOTE' };
1763 $confighash { $key }[ 25 ] = $cgiparams { 'REMARK' };
1764 $confighash { $key }[ 26 ] = "" ; # Formerly INTERFACE
1765 $confighash { $key }[ 27 ] = $cgiparams { 'DPD_ACTION' };
1766 $confighash { $key }[ 29 ] = $cgiparams { 'IKE_VERSION' };
1768 #dont forget advanced value
1769 $confighash { $key }[ 18 ] = $cgiparams { 'IKE_ENCRYPTION' };
1770 $confighash { $key }[ 19 ] = $cgiparams { 'IKE_INTEGRITY' };
1771 $confighash { $key }[ 20 ] = $cgiparams { 'IKE_GROUPTYPE' };
1772 $confighash { $key }[ 16 ] = $cgiparams { 'IKE_LIFETIME' };
1773 $confighash { $key }[ 21 ] = $cgiparams { 'ESP_ENCRYPTION' };
1774 $confighash { $key }[ 22 ] = $cgiparams { 'ESP_INTEGRITY' };
1775 $confighash { $key }[ 23 ] = $cgiparams { 'ESP_GROUPTYPE' };
1776 $confighash { $key }[ 17 ] = $cgiparams { 'ESP_KEYLIFE' };
1777 $confighash { $key }[ 12 ] = 'off' ; # $cgiparams{'AGGRMODE'};
1778 $confighash { $key }[ 13 ] = $cgiparams { 'COMPRESSION' };
1779 $confighash { $key }[ 24 ] = $cgiparams { 'ONLY_PROPOSED' };
1780 $confighash { $key }[ 28 ] = $cgiparams { 'PFS' };
1781 $confighash { $key }[ 14 ] = $cgiparams { 'VHOST' };
1783 #free unused fields!
1784 $confighash { $key }[ 6 ] = 'off' ;
1785 $confighash { $key }[ 15 ] = 'off' ;
1787 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
1790 system ( '/usr/local/bin/ipsecctrl' , 'S' , $key );
1793 if ( $cgiparams { 'EDIT_ADVANCED' } eq 'on' ) {
1794 $cgiparams { 'KEY' } = $key ;
1795 $cgiparams { 'ACTION' } = $Lang :: tr
{ 'advanced' };
1798 } else { # add new connection
1799 $cgiparams { 'ENABLED' } = 'on' ;
1800 if ( ! - f
"${General::swroot}/private/cakey.pem" ) {
1801 $cgiparams { 'AUTH' } = 'psk' ;
1802 } elsif ( ! - f
"${General::swroot}/ca/cacert.pem" ) {
1803 $cgiparams { 'AUTH' } = 'certfile' ;
1805 $cgiparams { 'AUTH' } = 'certgen' ;
1807 $cgiparams { 'LOCAL_SUBNET' } = " $netsettings {'GREEN_NETADDRESS'}/ $netsettings {'GREEN_NETMASK'}" ;
1808 $cgiparams { 'CERT_EMAIL' } = $vpnsettings { 'ROOTCERT_EMAIL' };
1809 $cgiparams { 'CERT_OU' } = $vpnsettings { 'ROOTCERT_OU' };
1810 $cgiparams { 'CERT_ORGANIZATION' } = $vpnsettings { 'ROOTCERT_ORGANIZATION' };
1811 $cgiparams { 'CERT_CITY' } = $vpnsettings { 'ROOTCERT_CITY' };
1812 $cgiparams { 'CERT_STATE' } = $vpnsettings { 'ROOTCERT_STATE' };
1813 $cgiparams { 'CERT_COUNTRY' } = $vpnsettings { 'ROOTCERT_COUNTRY' };
1815 # choose appropriate dpd action
1816 if ( $cgiparams { 'TYPE' } eq 'host' ) {
1817 $cgiparams { 'DPD_ACTION' } = 'clear' ;
1819 $cgiparams { 'DPD_ACTION' } = 'restart' ;
1822 # Default IKE Version to v2
1823 if (! $cgiparams { 'IKE_VERSION' }) {
1824 $cgiparams { 'IKE_VERSION' } = 'ikev2' ;
1828 $cgiparams { 'LOCAL_ID' } = '' ;
1829 $cgiparams { 'REMOTE_ID' } = '' ;
1831 #use default advanced value
1832 $cgiparams { 'IKE_ENCRYPTION' } = 'aes256|aes192|aes128|3des' ; #[18];
1833 $cgiparams { 'IKE_INTEGRITY' } = 'sha2_256|sha|md5' ; #[19];
1834 $cgiparams { 'IKE_GROUPTYPE' } = '8192|6144|4096|3072|2048|1536|1024' ; #[20];
1835 $cgiparams { 'IKE_LIFETIME' } = '1' ; #[16];
1836 $cgiparams { 'ESP_ENCRYPTION' } = 'aes256|aes192|aes128|3des' ; #[21];
1837 $cgiparams { 'ESP_INTEGRITY' } = 'sha2_256|sha1|md5' ; #[22];
1838 $cgiparams { 'ESP_GROUPTYPE' } = '' ; #[23];
1839 $cgiparams { 'ESP_KEYLIFE' } = '8' ; #[17];
1840 $cgiparams { 'COMPRESSION' } = 'on' ; #[13];
1841 $cgiparams { 'ONLY_PROPOSED' } = 'off' ; #[24];
1842 $cgiparams { 'PFS' } = 'on' ; #[28];
1843 $cgiparams { 'VHOST' } = 'on' ; #[14];
1847 $checked { 'ENABLED' }{ 'off' } = '' ;
1848 $checked { 'ENABLED' }{ 'on' } = '' ;
1849 $checked { 'ENABLED' }{ $cgiparams { 'ENABLED' }} = "checked='checked'" ;
1851 $checked { 'EDIT_ADVANCED' }{ 'off' } = '' ;
1852 $checked { 'EDIT_ADVANCED' }{ 'on' } = '' ;
1853 $checked { 'EDIT_ADVANCED' }{ $cgiparams { 'EDIT_ADVANCED' }} = "checked='checked'" ;
1855 $checked { 'AUTH' }{ 'psk' } = '' ;
1856 $checked { 'AUTH' }{ 'certreq' } = '' ;
1857 $checked { 'AUTH' }{ 'certgen' } = '' ;
1858 $checked { 'AUTH' }{ 'certfile' } = '' ;
1859 $checked { 'AUTH' }{ 'pkcs12' } = '' ;
1860 $checked { 'AUTH' }{ 'auth-dn' } = '' ;
1861 $checked { 'AUTH' }{ $cgiparams { 'AUTH' }} = "checked='checked'" ;
1863 $selected { 'DPD_ACTION' }{ 'clear' } = '' ;
1864 $selected { 'DPD_ACTION' }{ 'hold' } = '' ;
1865 $selected { 'DPD_ACTION' }{ 'restart' } = '' ;
1866 $selected { 'DPD_ACTION' }{ $cgiparams { 'DPD_ACTION' }} = "selected='selected'" ;
1868 $selected { 'IKE_VERSION' }{ 'ikev1' } = '' ;
1869 $selected { 'IKE_VERSION' }{ 'ikev2' } = '' ;
1870 $selected { 'IKE_VERSION' }{ $cgiparams { 'IKE_VERSION' }} = "selected='selected'" ;
1872 & Header
:: showhttpheaders
();
1873 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
1874 & Header
:: openbigbox
( '100%' , 'left' , '' , $errormessage );
1875 if ( $errormessage ) {
1876 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'error messages' });
1877 print "<class name='base'> $errormessage " ;
1878 print " </class>" ;
1879 & Header
:: closebox
();
1883 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'warning messages'}:" );
1884 print "<class name='base'> $warnmessage " ;
1885 print " </class>" ;
1886 & Header
:: closebox
();
1889 print "<form method='post' enctype='multipart/form-data' action=' $ENV {'SCRIPT_NAME'}'>" ;
1891 <input type='hidden' name='TYPE' value=' $cgiparams {'TYPE'}' />
1892 <input type='hidden' name='IKE_ENCRYPTION' value=' $cgiparams {'IKE_ENCRYPTION'}' />
1893 <input type='hidden' name='IKE_INTEGRITY' value=' $cgiparams {'IKE_INTEGRITY'}' />
1894 <input type='hidden' name='IKE_GROUPTYPE' value=' $cgiparams {'IKE_GROUPTYPE'}' />
1895 <input type='hidden' name='IKE_LIFETIME' value=' $cgiparams {'IKE_LIFETIME'}' />
1896 <input type='hidden' name='ESP_ENCRYPTION' value=' $cgiparams {'ESP_ENCRYPTION'}' />
1897 <input type='hidden' name='ESP_INTEGRITY' value=' $cgiparams {'ESP_INTEGRITY'}' />
1898 <input type='hidden' name='ESP_GROUPTYPE' value=' $cgiparams {'ESP_GROUPTYPE'}' />
1899 <input type='hidden' name='ESP_KEYLIFE' value=' $cgiparams {'ESP_KEYLIFE'}' />
1900 <input type='hidden' name='COMPRESSION' value=' $cgiparams {'COMPRESSION'}' />
1901 <input type='hidden' name='ONLY_PROPOSED' value=' $cgiparams {'ONLY_PROPOSED'}' />
1902 <input type='hidden' name='PFS' value=' $cgiparams {'PFS'}' />
1903 <input type='hidden' name='VHOST' value=' $cgiparams {'VHOST'}' />
1906 if ( $cgiparams { 'KEY' }) {
1907 print "<input type='hidden' name='KEY' value=' $cgiparams {'KEY'}' />" ;
1908 print "<input type='hidden' name='AUTH' value=' $cgiparams {'AUTH'}' />" ;
1911 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'connection'}:" );
1912 print "<table width='100%'>" ;
1913 print "<tr><td width='25%' class='boldbase'> $Lang ::tr{'name'}:</td>" ;
1914 if ( $cgiparams { 'KEY' }) {
1915 print "<td width='25%' class='base'><input type='hidden' name='NAME' value=' $cgiparams {'NAME'}' /><b> $cgiparams {'NAME'}</b></td>" ;
1917 print "<td width='25%'><input type='text' name='NAME' value=' $cgiparams {'NAME'}' size='30' /></td>" ;
1919 print "<td> $Lang ::tr{'enabled'}</td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td></tr>" ;
1920 print '</tr><td><br /></td><tr>' ;
1924 if ( $cgiparams { 'TYPE' } eq 'host' ) {
1925 $disabled = "disabled='disabled'" ;
1926 $blob = "<img src='/blob.gif' alt='*' />" ;
1931 <td class='boldbase'> $Lang ::tr{'remote host/ip'}: $blob </td>
1933 <input type='text' name='REMOTE' value=' $cgiparams {'REMOTE'}' size='30' />
1935 <td class='boldbase' nowrap='nowrap'> $Lang ::tr{'remote subnet'}</td>
1937 <input $disabled type='text' name='REMOTE_SUBNET' value=' $cgiparams {'REMOTE_SUBNET'}' size='30' />
1941 <td class='boldbase' nowrap='nowrap'> $Lang ::tr{'local subnet'}</td>
1943 <input type='text' name='LOCAL_SUBNET' value=' $cgiparams {'LOCAL_SUBNET'}' size='30' />
1947 <td class='boldbase'> $Lang ::tr{'vpn local id'}:<br />( $Lang ::tr{'eg'} <tt>@xy.example.com</tt>)</td>
1948 <td><input type='text' name='LOCAL_ID' value=' $cgiparams {'LOCAL_ID'}' /></td>
1949 <td class='boldbase'> $Lang ::tr{'vpn remote id'}:</td>
1950 <td><input type='text' name='REMOTE_ID' value=' $cgiparams {'REMOTE_ID'}' /></td>
1952 </tr><td><br /></td><tr>
1953 <td> $Lang ::tr{'vpn keyexchange'}:</td>
1954 <td><select name='IKE_VERSION'>
1955 <option value='ikev2' $selected {'IKE_VERSION'}{'ikev2'}>IKEv2</option>
1956 <option value='ikev1' $selected {'IKE_VERSION'}{'ikev1'}>IKEv1</option>
1959 <td> $Lang ::tr{'dpd action'}:</td>
1960 <td><select name='DPD_ACTION'>
1961 <option value='clear' $selected {'DPD_ACTION'}{'clear'}>clear</option>
1962 <option value='hold' $selected {'DPD_ACTION'}{'hold'}>hold</option>
1963 <option value='restart' $selected {'DPD_ACTION'}{'restart'}>restart</option>
1967 <td class='boldbase'> $Lang ::tr{'remark title'} <img src='/blob.gif' alt='*' /></td>
1968 <td colspan='3'><input type='text' name='REMARK' value=' $cgiparams {'REMARK'}' size='55' maxlength='50' /></td>
1972 if (! $cgiparams { 'KEY' }) {
1973 print "<tr><td colspan='3'><input type='checkbox' name='EDIT_ADVANCED' $checked {'EDIT_ADVANCED'}{'on'} /> $Lang ::tr{'edit advanced settings when done'}</td></tr>" ;
1976 & Header
:: closebox
();
1978 if ( $cgiparams { 'KEY' } && $cgiparams { 'AUTH' } eq 'psk' ) {
1979 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'authentication' });
1981 <table width='100%' cellpadding='0' cellspacing='5' border='0'>
1982 <tr><td class='base' width='50%'> $Lang ::tr{'use a pre-shared key'}</td>
1983 <td class='base' width='50%'><input type='password' name='PSK' size='30' value=' $cgiparams {'PSK'}' /></td>
1988 & Header
:: closebox
();
1989 } elsif (! $cgiparams { 'KEY' }) {
1990 my $pskdisabled = ( $vpnsettings { 'VPN_IP' } eq ' %defaultroute ' ) ?
"disabled='disabled'" : '' ;
1991 $cgiparams { 'PSK' } = $Lang :: tr
{ 'vpn incompatible use of defaultroute' } if ( $pskdisabled );
1992 my $cakeydisabled = ( ! - f
"${General::swroot}/private/cakey.pem" ) ?
"disabled='disabled'" : '' ;
1993 $cgiparams { 'CERT_NAME' } = $Lang :: tr
{ 'vpn no full pki' } if ( $cakeydisabled );
1994 my $cacrtdisabled = ( ! - f
"${General::swroot}/ca/cacert.pem" ) ?
"disabled='disabled'" : '' ;
1996 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'authentication' });
1998 <table width='100%' cellpadding='0' cellspacing='5' border='0'>
1999 <tr><td width='5%'><input type='radio' name='AUTH' value='psk' $checked {'AUTH'}{'psk'} $pskdisabled /></td>
2000 <td class='base' width='55%'> $Lang ::tr{'use a pre-shared key'}</td>
2001 <td class='base' width='40%'><input type='password' name='PSK' size='30' value=' $cgiparams {'PSK'}' $pskdisabled /></td></tr>
2002 <tr><td colspan='3' bgcolor='#000000'></td></tr>
2003 <tr><td><input type='radio' name='AUTH' value='certreq' $checked {'AUTH'}{'certreq'} $cakeydisabled /></td>
2004 <td class='base'><hr /> $Lang ::tr{'upload a certificate request'}</td>
2005 <td class='base' rowspan='3' valign='middle'><input type='file' name='FH' size='30' $cacrtdisabled /></td></tr>
2006 <tr><td><input type='radio' name='AUTH' value='certfile' $checked {'AUTH'}{'certfile'} $cacrtdisabled /></td>
2007 <td class='base'> $Lang ::tr{'upload a certificate'}</td></tr>
2008 <tr><td><input type='radio' name='AUTH' value='pkcs12' $cacrtdisabled /></td>
2009 <td class='base'> $Lang ::tr{'upload p12 file'} $Lang ::tr{'pkcs12 file password'}:<input type='password' name='P12_PASS'/></td></tr>
2010 <tr><td><input type='radio' name='AUTH' value='auth-dn' $checked {'AUTH'}{'auth-dn'} $cacrtdisabled /></td>
2011 <td class='base'><hr /> $Lang ::tr{'vpn auth-dn'}</td></tr>
2012 <tr><td colspan='3' bgcolor='#000000'></td></tr>
2013 <tr><td><input type='radio' name='AUTH' value='certgen' $checked {'AUTH'}{'certgen'} $cakeydisabled /></td>
2014 <td class='base'><hr /> $Lang ::tr{'generate a certificate'}</td><td> </td></tr>
2016 <td class='base'> $Lang ::tr{'users fullname or system hostname'}:</td>
2017 <td class='base' nowrap='nowrap'><input type='text' name='CERT_NAME' value=' $cgiparams {'CERT_NAME'}' size='32' $cakeydisabled /></td></tr>
2019 <td class='base'> $Lang ::tr{'users email'}: <img src='/blob.gif' alt='*' /></td>
2020 <td class='base' nowrap='nowrap'><input type='text' name='CERT_EMAIL' value=' $cgiparams {'CERT_EMAIL'}' size='32' $cakeydisabled /></td></tr>
2022 <td class='base'> $Lang ::tr{'users department'}: <img src='/blob.gif' alt='*' /></td>
2023 <td class='base' nowrap='nowrap'><input type='text' name='CERT_OU' value=' $cgiparams {'CERT_OU'}' size='32' $cakeydisabled /></td></tr>
2025 <td class='base'> $Lang ::tr{'organization name'}: <img src='/blob.gif' alt='*' /></td>
2026 <td class='base' nowrap='nowrap'><input type='text' name='CERT_ORGANIZATION' value=' $cgiparams {'CERT_ORGANIZATION'}' size='32' $cakeydisabled /></td></tr>
2028 <td class='base'> $Lang ::tr{'city'}: <img src='/blob.gif' alt='*' /></td>
2029 <td class='base' nowrap='nowrap'><input type='text' name='CERT_CITY' value=' $cgiparams {'CERT_CITY'}' size='32' $cakeydisabled /></td></tr>
2031 <td class='base'> $Lang ::tr{'state or province'}: <img src='/blob.gif' alt='*' /></td>
2032 <td class='base' nowrap='nowrap'><input type='text' name='CERT_STATE' value=' $cgiparams {'CERT_STATE'}' size='32' $cakeydisabled /></td></tr>
2034 <td class='base'> $Lang ::tr{'country'}:</td>
2035 <td class='base'><select name='CERT_COUNTRY' $cakeydisabled >
2038 foreach my $country ( sort keys %{ Countries
:: countries
}) {
2039 print " \t\t\t <option value=' $Countries ::countries{ $country }'" ;
2040 if ( $Countries :: countries
{ $country } eq $cgiparams { 'CERT_COUNTRY' } ) {
2041 print " selected='selected'" ;
2043 print "> $country </option> \n " ;
2048 <tr><td> </td><td class='base'> $Lang ::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*)<img src='/blob.gif' alt='*' /></td>
2049 <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value=' $cgiparams {'SUBJECTALTNAME'}' size='32' $cakeydisabled /></td></tr>
2051 <td class='base'> $Lang ::tr{'pkcs12 file password'}:</td>
2052 <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS1' value=' $cgiparams {'CERT_PASS1'}' size='32' $cakeydisabled /></td></tr>
2053 <tr><td> </td><td class='base'> $Lang ::tr{'pkcs12 file password'}:( $Lang ::tr{'confirmation'})</td>
2054 <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS2' value=' $cgiparams {'CERT_PASS2'}' size='32' $cakeydisabled /></td></tr>
2058 & Header
:: closebox
();
2061 print "<div align='center'><input type='submit' name='ACTION' value=' $Lang ::tr{'save'}' />" ;
2062 if ( $cgiparams { 'KEY' }) {
2063 print "<input type='submit' name='ACTION' value=' $Lang ::tr{'advanced'}' />" ;
2065 print "<input type='submit' name='ACTION' value=' $Lang ::tr{'cancel'}' /></div></form>" ;
2066 & Header
:: closebigbox
();
2067 & Header
:: closepage
();
2074 ### Advanced settings
2076 if (( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'advanced' }) ||
2077 ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' } && $cgiparams { 'ADVANCED' } eq 'yes' )) {
2078 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%vpnsettings );
2079 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
2080 if (! $confighash { $cgiparams { 'KEY' }}) {
2081 $errormessage = $Lang :: tr
{ 'invalid key' };
2085 if ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' }) {
2086 # I didn't read any incompatibilities here....
2087 #if ($cgiparams{'VHOST'} eq 'on' && $cgiparams{'COMPRESSION'} eq 'on') {
2088 # $errormessage = $Lang::tr{'cannot enable both nat traversal and compression'};
2089 # goto ADVANCED_ERROR;
2091 my @temp = split ( '\|' , $cgiparams { 'IKE_ENCRYPTION' });
2093 $errormessage = $Lang :: tr
{ 'invalid input' };
2094 goto ADVANCED_ERROR
;
2096 foreach my $val ( @temp ) {
2097 if ( $val !~ /^(aes256|aes128|3des)$/ ) {
2098 $errormessage = $Lang :: tr
{ 'invalid input' };
2099 goto ADVANCED_ERROR
;
2102 @temp = split ( '\|' , $cgiparams { 'IKE_INTEGRITY' });
2104 $errormessage = $Lang :: tr
{ 'invalid input' };
2105 goto ADVANCED_ERROR
;
2107 foreach my $val ( @temp ) {
2108 if ( $val !~ /^(sha2_512|sha2_384|sha2_256|sha|md5|aesxcbc)$/ ) {
2109 $errormessage = $Lang :: tr
{ 'invalid input' };
2110 goto ADVANCED_ERROR
;
2113 @temp = split ( '\|' , $cgiparams { 'IKE_GROUPTYPE' });
2115 $errormessage = $Lang :: tr
{ 'invalid input' };
2116 goto ADVANCED_ERROR
;
2118 foreach my $val ( @temp ) {
2119 if ( $val !~ /^(1024|1536|2048|3072|4096|6144|8192)$/ ) {
2120 $errormessage = $Lang :: tr
{ 'invalid input' };
2121 goto ADVANCED_ERROR
;
2124 if ( $cgiparams { 'IKE_LIFETIME' } !~ /^\d+$/ ) {
2125 $errormessage = $Lang :: tr
{ 'invalid input for ike lifetime' };
2126 goto ADVANCED_ERROR
;
2128 if ( $cgiparams { 'IKE_LIFETIME' } < 1 || $cgiparams { 'IKE_LIFETIME' } > 8 ) {
2129 $errormessage = $Lang :: tr
{ 'ike lifetime should be between 1 and 8 hours' };
2130 goto ADVANCED_ERROR
;
2132 @temp = split ( '\|' , $cgiparams { 'ESP_ENCRYPTION' });
2134 $errormessage = $Lang :: tr
{ 'invalid input' };
2135 goto ADVANCED_ERROR
;
2137 foreach my $val ( @temp ) {
2138 if ( $val !~ /^(aes256|aes192|aes128|3des)$/ ) {
2139 $errormessage = $Lang :: tr
{ 'invalid input' };
2140 goto ADVANCED_ERROR
;
2143 @temp = split ( '\|' , $cgiparams { 'ESP_INTEGRITY' });
2145 $errormessage = $Lang :: tr
{ 'invalid input' };
2146 goto ADVANCED_ERROR
;
2148 foreach my $val ( @temp ) {
2149 if ( $val !~ /^(sha2_512|sha2_384|sha2_256|sha1|md5|aesxcbc)$/ ) {
2150 $errormessage = $Lang :: tr
{ 'invalid input' };
2151 goto ADVANCED_ERROR
;
2154 if ( $cgiparams { 'ESP_GROUPTYPE' } ne '' &&
2155 $cgiparams { 'ESP_GROUPTYPE' } !~ /^modp(1024|1536|2048|3072|4096|6144|8192)$/ ) {
2156 $errormessage = $Lang :: tr
{ 'invalid input' };
2157 goto ADVANCED_ERROR
;
2160 if ( $cgiparams { 'ESP_KEYLIFE' } !~ /^\d+$/ ) {
2161 $errormessage = $Lang :: tr
{ 'invalid input for esp keylife' };
2162 goto ADVANCED_ERROR
;
2164 if ( $cgiparams { 'ESP_KEYLIFE' } < 1 || $cgiparams { 'ESP_KEYLIFE' } > 24 ) {
2165 $errormessage = $Lang :: tr
{ 'esp keylife should be between 1 and 24 hours' };
2166 goto ADVANCED_ERROR
;
2170 ( $cgiparams { 'COMPRESSION' } !~ /^(|on|off)$/ ) ||
2171 ( $cgiparams { 'ONLY_PROPOSED' } !~ /^(|on|off)$/ ) ||
2172 ( $cgiparams { 'PFS' } !~ /^(|on|off)$/ ) ||
2173 ( $cgiparams { 'VHOST' } !~ /^(|on|off)$/ )
2175 $errormessage = $Lang :: tr
{ 'invalid input' };
2176 goto ADVANCED_ERROR
;
2179 $confighash { $cgiparams { 'KEY' }}[ 18 ] = $cgiparams { 'IKE_ENCRYPTION' };
2180 $confighash { $cgiparams { 'KEY' }}[ 19 ] = $cgiparams { 'IKE_INTEGRITY' };
2181 $confighash { $cgiparams { 'KEY' }}[ 20 ] = $cgiparams { 'IKE_GROUPTYPE' };
2182 $confighash { $cgiparams { 'KEY' }}[ 16 ] = $cgiparams { 'IKE_LIFETIME' };
2183 $confighash { $cgiparams { 'KEY' }}[ 21 ] = $cgiparams { 'ESP_ENCRYPTION' };
2184 $confighash { $cgiparams { 'KEY' }}[ 22 ] = $cgiparams { 'ESP_INTEGRITY' };
2185 $confighash { $cgiparams { 'KEY' }}[ 23 ] = $cgiparams { 'ESP_GROUPTYPE' };
2186 $confighash { $cgiparams { 'KEY' }}[ 17 ] = $cgiparams { 'ESP_KEYLIFE' };
2187 $confighash { $cgiparams { 'KEY' }}[ 12 ] = 'off' ; #$cgiparams{'AGGRMODE'};
2188 $confighash { $cgiparams { 'KEY' }}[ 13 ] = $cgiparams { 'COMPRESSION' };
2189 $confighash { $cgiparams { 'KEY' }}[ 24 ] = $cgiparams { 'ONLY_PROPOSED' };
2190 $confighash { $cgiparams { 'KEY' }}[ 28 ] = $cgiparams { 'PFS' };
2191 $confighash { $cgiparams { 'KEY' }}[ 14 ] = $cgiparams { 'VHOST' };
2192 & General
:: writehasharray
( "${General::swroot}/vpn/config" , \
%confighash );
2195 system ( '/usr/local/bin/ipsecctrl' , 'S' , $cgiparams { 'KEY' });
2200 $cgiparams { 'IKE_ENCRYPTION' } = $confighash { $cgiparams { 'KEY' }}[ 18 ];
2201 $cgiparams { 'IKE_INTEGRITY' } = $confighash { $cgiparams { 'KEY' }}[ 19 ];
2202 $cgiparams { 'IKE_GROUPTYPE' } = $confighash { $cgiparams { 'KEY' }}[ 20 ];
2203 $cgiparams { 'IKE_LIFETIME' } = $confighash { $cgiparams { 'KEY' }}[ 16 ];
2204 $cgiparams { 'ESP_ENCRYPTION' } = $confighash { $cgiparams { 'KEY' }}[ 21 ];
2205 $cgiparams { 'ESP_INTEGRITY' } = $confighash { $cgiparams { 'KEY' }}[ 22 ];
2206 $cgiparams { 'ESP_GROUPTYPE' } = $confighash { $cgiparams { 'KEY' }}[ 23 ];
2207 $cgiparams { 'ESP_KEYLIFE' } = $confighash { $cgiparams { 'KEY' }}[ 17 ];
2208 $cgiparams { 'COMPRESSION' } = $confighash { $cgiparams { 'KEY' }}[ 13 ];
2209 $cgiparams { 'ONLY_PROPOSED' } = $confighash { $cgiparams { 'KEY' }}[ 24 ];
2210 $cgiparams { 'PFS' } = $confighash { $cgiparams { 'KEY' }}[ 28 ];
2211 $cgiparams { 'VHOST' } = $confighash { $cgiparams { 'KEY' }}[ 14 ];
2213 if ( $confighash { $cgiparams { 'KEY' }}[ 3 ] eq 'net' || $confighash { $cgiparams { 'KEY' }}[ 10 ]) {
2214 $cgiparams { 'VHOST' } = 'off' ;
2219 $checked { 'IKE_ENCRYPTION' }{ 'aes256' } = '' ;
2220 $checked { 'IKE_ENCRYPTION' }{ 'aes192' } = '' ;
2221 $checked { 'IKE_ENCRYPTION' }{ 'aes128' } = '' ;
2222 $checked { 'IKE_ENCRYPTION' }{ '3des' } = '' ;
2223 my @temp = split ( '\|' , $cgiparams { 'IKE_ENCRYPTION' });
2224 foreach my $key ( @temp ) { $checked { 'IKE_ENCRYPTION' }{ $key } = "selected='selected'" ; }
2225 $checked { 'IKE_INTEGRITY' }{ 'sha2_512' } = '' ;
2226 $checked { 'IKE_INTEGRITY' }{ 'sha2_384' } = '' ;
2227 $checked { 'IKE_INTEGRITY' }{ 'sha2_256' } = '' ;
2228 $checked { 'IKE_INTEGRITY' }{ 'sha' } = '' ;
2229 $checked { 'IKE_INTEGRITY' }{ 'md5' } = '' ;
2230 $checked { 'IKE_INTEGRITY' }{ 'aesxcbc' } = '' ;
2231 @temp = split ( '\|' , $cgiparams { 'IKE_INTEGRITY' });
2232 foreach my $key ( @temp ) { $checked { 'IKE_INTEGRITY' }{ $key } = "selected='selected'" ; }
2233 $checked { 'IKE_GROUPTYPE' }{ '768' } = '' ;
2234 $checked { 'IKE_GROUPTYPE' }{ '1024' } = '' ;
2235 $checked { 'IKE_GROUPTYPE' }{ '1536' } = '' ;
2236 $checked { 'IKE_GROUPTYPE' }{ '2048' } = '' ;
2237 $checked { 'IKE_GROUPTYPE' }{ '3072' } = '' ;
2238 $checked { 'IKE_GROUPTYPE' }{ '4096' } = '' ;
2239 $checked { 'IKE_GROUPTYPE' }{ '6144' } = '' ;
2240 $checked { 'IKE_GROUPTYPE' }{ '8192' } = '' ;
2241 @temp = split ( '\|' , $cgiparams { 'IKE_GROUPTYPE' });
2242 foreach my $key ( @temp ) { $checked { 'IKE_GROUPTYPE' }{ $key } = "selected='selected'" ; }
2244 # 768 is not supported by strongswan
2245 $checked { 'IKE_GROUPTYPE' }{ '768' } = '' ;
2247 $checked { 'ESP_ENCRYPTION' }{ 'aes256' } = '' ;
2248 $checked { 'ESP_ENCRYPTION' }{ 'aes192' } = '' ;
2249 $checked { 'ESP_ENCRYPTION' }{ 'aes128' } = '' ;
2250 $checked { 'ESP_ENCRYPTION' }{ '3des' } = '' ;
2251 @temp = split ( '\|' , $cgiparams { 'ESP_ENCRYPTION' });
2252 foreach my $key ( @temp ) { $checked { 'ESP_ENCRYPTION' }{ $key } = "selected='selected'" ; }
2253 $checked { 'ESP_INTEGRITY' }{ 'sha2_512' } = '' ;
2254 $checked { 'ESP_INTEGRITY' }{ 'sha2_384' } = '' ;
2255 $checked { 'ESP_INTEGRITY' }{ 'sha2_256' } = '' ;
2256 $checked { 'ESP_INTEGRITY' }{ 'sha1' } = '' ;
2257 $checked { 'ESP_INTEGRITY' }{ 'md5' } = '' ;
2258 $checked { 'ESP_INTEGRITY' }{ 'aesxcbc' } = '' ;
2259 @temp = split ( '\|' , $cgiparams { 'ESP_INTEGRITY' });
2260 foreach my $key ( @temp ) { $checked { 'ESP_INTEGRITY' }{ $key } = "selected='selected'" ; }
2261 $checked { 'ESP_GROUPTYPE' }{ $cgiparams { 'ESP_GROUPTYPE' }} = "selected='selected'" ;
2263 $checked { 'COMPRESSION' } = $cgiparams { 'COMPRESSION' } eq 'on' ?
"checked='checked'" : '' ;
2264 $checked { 'ONLY_PROPOSED' } = $cgiparams { 'ONLY_PROPOSED' } eq 'on' ?
"checked='checked'" : '' ;
2265 $checked { 'PFS' } = $cgiparams { 'PFS' } eq 'on' ?
"checked='checked'" : '' ;
2266 $checked { 'VHOST' } = $cgiparams { 'VHOST' } eq 'on' ?
"checked='checked'" : '' ;
2268 & Header
:: showhttpheaders
();
2269 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
2270 & Header
:: openbigbox
( '100%' , 'left' , '' , $errormessage );
2272 if ( $errormessage ) {
2273 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'error messages' });
2274 print "<class name='base'> $errormessage " ;
2275 print " </class>" ;
2276 & Header
:: closebox
();
2280 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'warning messages' });
2281 print "<class name='base'> $warnmessage " ;
2282 print " </class>" ;
2283 & Header
:: closebox
();
2286 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'advanced'}:" );
2288 <form method='post' enctype='multipart/form-data' action=' $ENV {'SCRIPT_NAME'}'>
2289 <input type='hidden' name='ADVANCED' value='yes' />
2290 <input type='hidden' name='KEY' value=' $cgiparams {'KEY'}' />
2292 <table width='100%'>
2293 <tr><td class='boldbase' align='right' valign='top'> $Lang ::tr{'ike encryption'}</td><td class='boldbase' valign='top'>
2294 <select name='IKE_ENCRYPTION' multiple='multiple' size='4'>
2295 <option value='aes256' $checked {'IKE_ENCRYPTION'}{'aes256'}>AES (256 bit)</option>
2296 <option value='aes192' $checked {'IKE_ENCRYPTION'}{'aes192'}>AES (192 bit)</option>
2297 <option value='aes128' $checked {'IKE_ENCRYPTION'}{'aes128'}>AES (128 bit)</option>
2298 <option value='3des' $checked {'IKE_ENCRYPTION'}{'3des'}>3DES</option>
2301 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'ike integrity'}</td><td class='boldbase' valign='top'>
2302 <select name='IKE_INTEGRITY' multiple='multiple' size='4'>
2303 <option value='sha2_512' $checked {'IKE_INTEGRITY'}{'sha2_512'}>SHA2 512 bit</option>
2304 <option value='sha2_384' $checked {'IKE_INTEGRITY'}{'sha2_384'}>SHA2 384 bit</option>
2305 <option value='sha2_256' $checked {'IKE_INTEGRITY'}{'sha2_256'}>SHA2 256 bit</option>
2306 <option value='sha' $checked {'IKE_INTEGRITY'}{'sha'}>SHA1</option>
2307 <option value='md5' $checked {'IKE_INTEGRITY'}{'md5'}>MD5</option>
2308 <option value='aesxcbc' $checked {'IKE_INTEGRITY'}{'aesxcbc'}>AES XCBC</option>
2311 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'ike grouptype'}</td><td class='boldbase' valign='top'>
2312 <select name='IKE_GROUPTYPE' multiple='multiple' size='4'>
2313 <option value='8192' $checked {'IKE_GROUPTYPE'}{'8192'}>MODP-8192</option>
2314 <option value='6144' $checked {'IKE_GROUPTYPE'}{'6144'}>MODP-6144</option>
2315 <option value='4096' $checked {'IKE_GROUPTYPE'}{'4096'}>MODP-4096</option>
2316 <option value='3072' $checked {'IKE_GROUPTYPE'}{'3072'}>MODP-3072</option>
2317 <option value='2048' $checked {'IKE_GROUPTYPE'}{'2048'}>MODP-2048</option>
2318 <option value='1536' $checked {'IKE_GROUPTYPE'}{'1536'}>MODP-1536</option>
2319 <option value='1024' $checked {'IKE_GROUPTYPE'}{'1024'}>MODP-1024</option>
2322 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'ike lifetime'}</td><td class='boldbase' valign='top'>
2323 <input type='text' name='IKE_LIFETIME' value=' $cgiparams {'IKE_LIFETIME'}' size='5' /> $Lang ::tr{'hours'}</td>
2326 <td colspan='1'><hr /></td>
2328 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'esp encryption'}</td><td class='boldbase' valign='top'>
2329 <select name='ESP_ENCRYPTION' multiple='multiple' size='4'>
2330 <option value='aes256' $checked {'ESP_ENCRYPTION'}{'aes256'}>AES (256 bit)</option>
2331 <option value='aes192' $checked {'ESP_ENCRYPTION'}{'aes192'}>AES (192 bit)</option>
2332 <option value='aes128' $checked {'ESP_ENCRYPTION'}{'aes128'}>AES (128 bit)</option>
2333 <option value='3des' $checked {'ESP_ENCRYPTION'}{'3des'}>3DES</option>
2335 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'esp integrity'}</td><td class='boldbase' valign='top'>
2336 <select name='ESP_INTEGRITY' multiple='multiple' size='4'>
2337 <option value='sha2_512' $checked {'ESP_INTEGRITY'}{'sha2_512'}>SHA2 512 bit</option>
2338 <option value='sha2_384' $checked {'ESP_INTEGRITY'}{'sha2_384'}>SHA2 384 bit</option>
2339 <option value='sha2_256' $checked {'ESP_INTEGRITY'}{'sha2_256'}>SHA2 256 bit</option>
2340 <option value='sha1' $checked {'ESP_INTEGRITY'}{'sha1'}>SHA1</option>
2341 <option value='md5' $checked {'ESP_INTEGRITY'}{'md5'}>MD5</option>
2342 <option value='aesxcbc' $checked {'ESP_INTEGRITY'}{'aesxcbc'}>AES XCBC</option>
2345 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'esp grouptype'}</td><td class='boldbase' valign='top'>
2346 <select name='ESP_GROUPTYPE'>
2347 <option value=''> $Lang ::tr{'phase1 group'}</option></select></td>
2349 <td class='boldbase' align='right' valign='top'> $Lang ::tr{'esp keylife'}</td><td class='boldbase' valign='top'>
2350 <input type='text' name='ESP_KEYLIFE' value=' $cgiparams {'ESP_KEYLIFE'}' size='5' /> $Lang ::tr{'hours'}</td>
2352 <td colspan='1'><hr /></td>
2354 <td colspan='5'><input type='checkbox' name='ONLY_PROPOSED' $checked {'ONLY_PROPOSED'} />
2355 IKE+ESP: $Lang ::tr{'use only proposed settings'}</td>
2357 <td colspan='5'><input type='checkbox' name='PFS' $checked {'PFS'} />
2358 $Lang ::tr{'pfs yes no'}</td>
2359 <td align='right'><input type='submit' name='ACTION' value=' $Lang ::tr{'save'}' /></td>
2361 <td colspan='5'><input type='checkbox' name='COMPRESSION' $checked {'COMPRESSION'} />
2362 $Lang ::tr{'vpn payload compression'}</td>
2363 <td align='right'><input type='submit' name='ACTION' value=' $Lang ::tr{'cancel'}' /></td>
2367 if ( $confighash { $cgiparams { 'KEY' }}[ 3 ] eq 'net' ) {
2368 print "<tr><td><input type='hidden' name='VHOST' value='off' /></td></tr>" ;
2369 } elsif ( $confighash { $cgiparams { 'KEY' }}[ 10 ]) {
2370 print "<tr><td colspan='5'><input type='checkbox' name='VHOST' $checked {'VHOST'} disabled='disabled' />" ;
2371 print " $Lang ::tr{'vpn vhost'}</td></tr>" ;
2373 print "<tr><td colspan='5'><input type='checkbox' name='VHOST' $checked {'VHOST'} />" ;
2374 print " $Lang ::tr{'vpn vhost'}</td></tr>" ;
2377 print "</table></form>" ;
2378 & Header
:: closebox
();
2379 & Header
:: closebigbox
();
2380 & Header
:: closepage
();
2387 ### Default status page
2392 & General
:: readhash
( "${General::swroot}/vpn/settings" , \
%cgiparams );
2393 & General
:: readhasharray
( "${General::swroot}/vpn/caconfig" , \
%cahash );
2394 & General
:: readhasharray
( "${General::swroot}/vpn/config" , \
%confighash );
2395 $cgiparams { 'CA_NAME' } = '' ;
2397 my @status = `/usr/local/bin/ipsecctrl I 2>/dev/null` ;
2399 # suggest a default name for this side
2400 if ( $cgiparams { 'VPN_IP' } eq '' && - e
"${General::swroot}/red/active" ) {
2401 if ( open ( IPADDR
, "${General::swroot}/red/local-ipaddress" )) {
2402 my $ipaddr = < IPADDR
>;
2405 $cgiparams { 'VPN_IP' } = ( gethostbyaddr ( pack ( "C4" , split ( /\./ , $ipaddr )), 2 ))[ 0 ];
2406 if ( $cgiparams { 'VPN_IP' } eq '' ) {
2407 $cgiparams { 'VPN_IP' } = $ipaddr ;
2411 # no IP found, use %defaultroute
2412 $cgiparams { 'VPN_IP' } = ' %defaultroute ' if ( $cgiparams { 'VPN_IP' } eq '' );
2414 $cgiparams { 'VPN_DELAYED_START' } = 0 if (! defined ( $cgiparams { 'VPN_DELAYED_START' }));
2415 $checked { 'ENABLED' } = $cgiparams { 'ENABLED' } eq 'on' ?
"checked='checked'" : '' ;
2417 & Header
:: showhttpheaders
();
2418 & Header
:: openpage
( $Lang :: tr
{ 'vpn configuration main' }, 1 , '' );
2419 & Header
:: openbigbox
( '100%' , 'left' , '' , $errormessage );
2421 if ( $errormessage ) {
2422 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'error messages' });
2423 print "<class name='base'> $errormessage \n " ;
2424 print " </class> \n " ;
2425 & Header
:: closebox
();
2428 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'global settings' });
2430 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2431 <table width='100%'>
2433 <td width='20%' class='base' nowrap='nowrap'> $Lang ::tr{'vpn red name'}:</td>
2434 <td width='20%'><input type='text' name='VPN_IP' value=' $cgiparams {'VPN_IP'}' /></td>
2435 <td width='20%' class='base'> $Lang ::tr{'enabled'}<input type='checkbox' name='ENABLED' $checked {'ENABLED'} /></td>
2441 <td class='base' nowrap='nowrap'> $Lang ::tr{'vpn delayed start'}: <img src='/blob.gif' alt='*' /><img src='/blob.gif' alt='*' /></td>
2442 <td ><input type='text' name='VPN_DELAYED_START' value=' $cgiparams {'VPN_DELAYED_START'}' /></td>
2445 <td class='base' nowrap='nowrap'> $Lang ::tr{'host to net vpn'}: <img src='/blob.gif' alt='*' /></td>
2446 <td ><input type='text' name='RW_NET' value=' $cgiparams {'RW_NET'}' /></td>
2450 <table width='100%'>
2452 <td class='base' valign='top'><img src='/blob.gif' alt='*' /></td>
2453 <td width='70%' class='base' valign='top'> $Lang ::tr{'this field may be blank'}</td>
2456 <td class='base' valign='top' nowrap='nowrap'><img src='/blob.gif' alt='*' /><img src='/blob.gif' alt='*' /> </td>
2457 <td class='base'> <font class='base'> $Lang ::tr{'vpn delayed start help'}</font></td>
2458 <td width='30%' align='center' class='base'><input type='submit' name='ACTION' value=' $Lang ::tr{'save'}' /></td>
2464 & Header
:: closebox
();
2466 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'connection status and controlc' });
2468 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2470 <td width='10%' class='boldbase' align='center'><b> $Lang ::tr{'name'}</b></td>
2471 <td width='22%' class='boldbase' align='center'><b> $Lang ::tr{'type'}</b></td>
2472 <td width='23%' class='boldbase' align='center'><b> $Lang ::tr{'common name'}</b></td>
2473 <td width='30%' class='boldbase' align='center'><b> $Lang ::tr{'remark'}</b></td>
2474 <td width='10%' class='boldbase' align='center'><b> $Lang ::tr{'status'}</b></td>
2475 <td class='boldbase' align='center' colspan='6'><b> $Lang ::tr{'action'}</b></td>
2481 foreach my $key ( keys %confighash ) {
2482 if ( $confighash { $key }[ 0 ] eq 'on' ) { $gif = 'on.gif' ; } else { $gif = 'off.gif' ; }
2485 print "<tr bgcolor=' $color {'color20'}'> \n " ;
2487 print "<tr bgcolor=' $color {'color22'}'> \n " ;
2489 print "<td align='center' nowrap='nowrap'> $confighash { $key }[1]</td>" ;
2490 print "<td align='center' nowrap='nowrap'>" . $Lang :: tr
{ " $confighash { $key }[3]" } . " (" . $Lang :: tr
{ " $confighash { $key }[4]" } . ") $confighash { $key }[29]</td>" ;
2491 if ( $confighash { $key }[ 2 ] eq ' %auth -dn' ) {
2492 print "<td align='left' nowrap='nowrap'> $confighash { $key }[9]</td>" ;
2493 } elsif ( $confighash { $key }[ 4 ] eq 'cert' ) {
2494 print "<td align='left' nowrap='nowrap'> $confighash { $key }[2]</td>" ;
2496 print "<td align='left'> </td>" ;
2498 print "<td align='center'> $confighash { $key }[25]</td>" ;
2500 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>" ;
2501 foreach my $line ( @status ) {
2502 if (( $line =~ /\"$confighash{$key}[1]\".*IPsec SA established/ ) ||
2503 ( $line =~ /$confighash{$key}[1]\{.*INSTALLED/ ))
2505 $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>" ;
2508 # move to blueif really down
2509 if ( $confighash { $key }[ 0 ] eq 'off' && $active =~ /${Header::colourred}/ ) {
2510 $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>" ;
2513 <td align='center'> $active </td>
2515 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2516 <input type='image' name=' $Lang ::tr{'restart'}' src='/images/reload.gif' alt=' $Lang ::tr{'restart'}' title=' $Lang ::tr{'restart'}' />
2517 <input type='hidden' name='ACTION' value=' $Lang ::tr{'restart'}' />
2518 <input type='hidden' name='KEY' value=' $key ' />
2523 if (( $confighash { $key }[ 4 ] eq 'cert' ) && ( $confighash { $key }[ 2 ] ne ' %auth -dn' )) {
2526 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2527 <input type='image' name=' $Lang ::tr{'show certificate'}' src='/images/info.gif' alt=' $Lang ::tr{'show certificate'}' title=' $Lang ::tr{'show certificate'}' />
2528 <input type='hidden' name='ACTION' value=' $Lang ::tr{'show certificate'}' />
2529 <input type='hidden' name='KEY' value=' $key ' />
2534 print "<td width='2%'> </td>" ;
2536 if ( $confighash { $key }[ 4 ] eq 'cert' && - f
"${General::swroot}/certs/ $confighash { $key }[1].p12" ) {
2539 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2540 <input type='image' name=' $Lang ::tr{'download pkcs12 file'}' src='/images/floppy.gif' alt=' $Lang ::tr{'download pkcs12 file'}' title=' $Lang ::tr{'download pkcs12 file'}' />
2541 <input type='hidden' name='ACTION' value=' $Lang ::tr{'download pkcs12 file'}' />
2542 <input type='hidden' name='KEY' value=' $key ' />
2546 ; } elsif (( $confighash { $key }[ 4 ] eq 'cert' ) && ( $confighash { $key }[ 2 ] ne ' %auth -dn' )) {
2549 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2550 <input type='image' name=' $Lang ::tr{'download certificate'}' src='/images/floppy.gif' alt=' $Lang ::tr{'download certificate'}' title=' $Lang ::tr{'download certificate'}' />
2551 <input type='hidden' name='ACTION' value=' $Lang ::tr{'download certificate'}' />
2552 <input type='hidden' name='KEY' value=' $key ' />
2557 print "<td width='2%'> </td>" ;
2561 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2562 <input type='image' name=' $Lang ::tr{'toggle enable disable'}' src='/images/ $gif ' alt=' $Lang ::tr{'toggle enable disable'}' title=' $Lang ::tr{'toggle enable disable'}' />
2563 <input type='hidden' name='ACTION' value=' $Lang ::tr{'toggle enable disable'}' />
2564 <input type='hidden' name='KEY' value=' $key ' />
2569 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2570 <input type='hidden' name='ACTION' value=' $Lang ::tr{'edit'}' />
2571 <input type='image' name=' $Lang ::tr{'edit'}' src='/images/edit.gif' alt=' $Lang ::tr{'edit'}' title=' $Lang ::tr{'edit'}' />
2572 <input type='hidden' name='KEY' value=' $key ' />
2575 <td align='center' >
2576 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2577 <input type='hidden' name='ACTION' value=' $Lang ::tr{'remove'}' />
2578 <input type='image' name=' $Lang ::tr{'remove'}' src='/images/delete.gif' alt=' $Lang ::tr{'remove'}' title=' $Lang ::tr{'remove'}' />
2579 <input type='hidden' name='KEY' value=' $key ' />
2589 # If the config file contains entries, print Key to action icons
2594 <td class='boldbase'> <b> $Lang ::tr{'legend'}:</b></td>
2595 <td> <img src='/images/on.gif' alt=' $Lang ::tr{'click to disable'}' /></td>
2596 <td class='base'> $Lang ::tr{'click to disable'}</td>
2597 <td> <img src='/images/info.gif' alt=' $Lang ::tr{'show certificate'}' /></td>
2598 <td class='base'> $Lang ::tr{'show certificate'}</td>
2599 <td> <img src='/images/edit.gif' alt=' $Lang ::tr{'edit'}' /></td>
2600 <td class='base'> $Lang ::tr{'edit'}</td>
2601 <td> <img src='/images/delete.gif' alt=' $Lang ::tr{'remove'}' /></td>
2602 <td class='base'> $Lang ::tr{'remove'}</td>
2606 <td> <img src='/images/off.gif' alt='?OFF' /></td>
2607 <td class='base'> $Lang ::tr{'click to enable'}</td>
2608 <td> <img src='/images/floppy.gif' alt='?FLOPPY' /></td>
2609 <td class='base'> $Lang ::tr{'download certificate'}</td>
2610 <td> <img src='/images/reload.gif' alt='?RELOAD'/></td>
2611 <td class='base'> $Lang ::tr{'restart'}</td>
2619 <table width='100%'>
2620 <tr><td align='center' colspan='9'>
2621 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2622 <input type='submit' name='ACTION' value=' $Lang ::tr{'add'}' />
2628 & Header
:: closebox
();
2630 & Header
:: openbox
( '100%' , 'left' , " $Lang ::tr{'certificate authorities'}:" );
2632 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2634 <td width='25%' class='boldbase' align='center'><b> $Lang ::tr{'name'}</b></td>
2635 <td width='65%' class='boldbase' align='center'><b> $Lang ::tr{'subject'}</b></td>
2636 <td width='10%' class='boldbase' colspan='3' align='center'><b> $Lang ::tr{'action'}</b></td>
2640 if (- f
"${General::swroot}/ca/cacert.pem" ) {
2641 my $casubject = & Header
:: cleanhtml
( getsubjectfromcert
( "${General::swroot}/ca/cacert.pem" ));
2644 <tr bgcolor=' $color {'color22'}'>
2645 <td class='base'> $Lang ::tr{'root certificate'}</td>
2646 <td class='base'> $casubject </td>
2647 <td width='3%' align='center'>
2648 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2649 <input type='hidden' name='ACTION' value=' $Lang ::tr{'show root certificate'}' />
2650 <input type='image' name=' $Lang ::tr{'edit'}' src='/images/info.gif' alt=' $Lang ::tr{'show root certificate'}' title=' $Lang ::tr{'show root certificate'}' />
2653 <td width='3%' align='center'>
2654 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2655 <input type='image' name=' $Lang ::tr{'download root certificate'}' src='/images/floppy.gif' alt=' $Lang ::tr{'download root certificate'}' title=' $Lang ::tr{'download root certificate'}' />
2656 <input type='hidden' name='ACTION' value=' $Lang ::tr{'download root certificate'}' />
2659 <td width='4%'> </td></tr>
2663 # display rootcert generation buttons
2665 <tr bgcolor=' $color {'color22'}'>
2666 <td class='base'> $Lang ::tr{'root certificate'}:</td>
2667 <td class='base'> $Lang ::tr{'not present'}</td>
2668 <td colspan='3'> </td></tr>
2673 if (- f
"${General::swroot}/certs/hostcert.pem" ) {
2674 my $hostsubject = & Header
:: cleanhtml
( getsubjectfromcert
( "${General::swroot}/certs/hostcert.pem" ));
2677 <tr bgcolor=' $color {'color20'}'>
2678 <td class='base'> $Lang ::tr{'host certificate'}</td>
2679 <td class='base'> $hostsubject </td>
2680 <td width='3%' align='center'>
2681 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2682 <input type='hidden' name='ACTION' value=' $Lang ::tr{'show host certificate'}' />
2683 <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'}' />
2686 <td width='3%' align='center'>
2687 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
2688 <input type='image' name=' $Lang ::tr{'download host certificate'}' src='/images/floppy.gif' alt=' $Lang ::tr{'download host certificate'}' title=' $Lang ::tr{'download host certificate'}' />
2689 <input type='hidden' name='ACTION' value=' $Lang ::tr{'download host certificate'}' />
2692 <td width='4%'> </td></tr>
2698 <tr bgcolor=' $color {'color20'}'>
2699 <td width='25%' class='base'> $Lang ::tr{'host certificate'}:</td>
2700 <td class='base'> $Lang ::tr{'not present'}</td>
2701 <td colspan='3'> </td></tr>
2707 if ( keys %cahash > 0 ) {
2708 foreach my $key ( keys %cahash ) {
2709 if ( $rowcolor ++ % 2 ) {
2710 print "<tr bgcolor=' $color {'color20'}'> \n " ;
2712 print "<tr bgcolor=' $color {'color22'}'> \n " ;
2714 print "<td class='base'> $cahash { $key }[0]</td> \n " ;
2715 print "<td class='base'> $cahash { $key }[1]</td> \n " ;
2718 <form method='post' name='cafrm${key}a' action=' $ENV {'SCRIPT_NAME'}'>
2719 <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'}' />
2720 <input type='hidden' name='ACTION' value=' $Lang ::tr{'show ca certificate'}' />
2721 <input type='hidden' name='KEY' value=' $key ' />
2725 <form method='post' name='cafrm${key}b' action=' $ENV {'SCRIPT_NAME'}'>
2726 <input type='image' name=' $Lang ::tr{'download ca certificate'}' src='/images/floppy.gif' alt=' $Lang ::tr{'download ca certificate'}' title=' $Lang ::tr{'download ca certificate'}' />
2727 <input type='hidden' name='ACTION' value=' $Lang ::tr{'download ca certificate'}' />
2728 <input type='hidden' name='KEY' value=' $key ' />
2732 <form method='post' name='cafrm${key}c' action=' $ENV {'SCRIPT_NAME'}'>
2733 <input type='hidden' name='ACTION' value=' $Lang ::tr{'remove ca certificate'}' />
2734 <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'}' />
2735 <input type='hidden' name='KEY' value=' $key ' />
2745 # If the file contains entries, print Key to action icons
2746 if ( - f
"${General::swroot}/ca/cacert.pem" ) {
2749 <td class='boldbase'> <b> $Lang ::tr{'legend'}:</b></td>
2750 <td> <img src='/images/info.gif' alt=' $Lang ::tr{'show certificate'}' /></td>
2751 <td class='base'> $Lang ::tr{'show certificate'}</td>
2752 <td> <img src='/images/floppy.gif' alt=' $Lang ::tr{'download certificate'}' /></td>
2753 <td class='base'> $Lang ::tr{'download certificate'}</td>
2758 my $createCA = - f
"${General::swroot}/ca/cacert.pem" ?
'' : "<tr><td colspan='3'></td><td><input type='submit' name='ACTION' value=' $Lang ::tr{'generate root/host certificates'}' /></td></tr>" ;
2761 <form method='post' enctype='multipart/form-data' action=' $ENV {'SCRIPT_NAME'}'>
2762 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2765 <td class='base' nowrap='nowrap'> $Lang ::tr{'ca name'}:</td>
2766 <td nowrap='nowrap'><input type='text' name='CA_NAME' value=' $cgiparams {'CA_NAME'}' size='15' /> </td>
2767 <td nowrap='nowrap'><input type='file' name='FH' size='30' /></td>
2768 <td nowrap='nowrap'><input type='submit' name='ACTION' value=' $Lang ::tr{'upload ca certificate'}' /></td>
2771 <td colspan='3'> $Lang ::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}:</td>
2772 <td><input type='submit' name='ACTION' value=' $Lang ::tr{'remove x509'}' /></td>
2778 & Header
:: closebox
();
2779 & Header
:: closebigbox
();
2780 & Header
:: closepage
();