3d5a360f132330f3a84981a021295db95e88418f
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / vpnmain.cgi
1 #!/usr/bin/perl
2 ###############################################################################
3 #                                                                             #
4 # IPFire.org - A linux based firewall                                         #
5 # Copyright (C) 2007-2011  IPFire Team  info@ipfire.org                       #
6 #                                                                             #
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.                                         #
11 #                                                                             #
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.                                #
16 #                                                                             #
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/>.       #
19 #                                                                             #
20 ###############################################################################
21
22 use Net::DNS;
23 use File::Copy;
24 use File::Temp qw/ tempfile tempdir /;
25 use strict;
26
27 # enable only the following on debugging purpose
28 #use warnings;
29 #use CGI::Carp 'fatalsToBrowser';
30
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";
35
36 #workaround to suppress a warning when a variable is used only once
37 my @dummy = ( ${Header::colourgreen}, ${Header::colourblue} );
38 undef (@dummy);
39
40 ###
41 ### Initialize variables
42 ###
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)
45 my %netsettings=();
46 our %cgiparams=();
47 our %vpnsettings=();
48 my %checked=();
49 my %confighash=();
50 my %cahash=();
51 my %selected=();
52 my $warnmessage = '';
53 my $errormessage = '';
54
55 my %color = ();
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);
59
60 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
61
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'}");
66 }
67 my $orange_cidr = "# Orange not defined";
68 if ($netsettings{'ORANGE_DEV'}) {
69         $orange_cidr = &General::ipcidr("$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}");
70 }
71
72 $cgiparams{'ENABLED'} = 'off';
73 $cgiparams{'EDIT_ADVANCED'} = 'off';
74 $cgiparams{'ACTION'} = '';
75 $cgiparams{'CA_NAME'} = '';
76 $cgiparams{'DBG_CRYPT'} = '';
77 $cgiparams{'DBG_PARSING'} = '';
78 $cgiparams{'DBG_EMITTING'} = '';
79 $cgiparams{'DBG_CONTROL'} = '';
80 $cgiparams{'DBG_KLIPS'} = '';
81 $cgiparams{'DBG_DNS'} = '';
82 $cgiparams{'DBG_NAT_T'} = '';
83 $cgiparams{'KEY'} = '';
84 $cgiparams{'TYPE'} = '';
85 $cgiparams{'ADVANCED'} = '';
86 $cgiparams{'INTERFACE'} = '';
87 $cgiparams{'NAME'} = '';
88 $cgiparams{'LOCAL_SUBNET'} = '';
89 $cgiparams{'REMOTE_SUBNET'} = '';
90 $cgiparams{'REMOTE'} = '';
91 $cgiparams{'LOCAL_ID'} = '';
92 $cgiparams{'REMOTE_ID'} = '';
93 $cgiparams{'REMARK'} = '';
94 $cgiparams{'PSK'} = '';
95 $cgiparams{'CERT_NAME'} = '';
96 $cgiparams{'CERT_EMAIL'} = '';
97 $cgiparams{'CERT_OU'} = '';
98 $cgiparams{'CERT_ORGANIZATION'} = '';
99 $cgiparams{'CERT_CITY'} = '';
100 $cgiparams{'CERT_STATE'} = '';
101 $cgiparams{'CERT_COUNTRY'} = '';
102 $cgiparams{'SUBJECTALTNAME'} = '';
103 $cgiparams{'CERT_PASS1'} = '';
104 $cgiparams{'CERT_PASS2'} = '';
105 $cgiparams{'ROOTCERT_HOSTNAME'} = '';
106 $cgiparams{'ROOTCERT_COUNTRY'} = '';
107 $cgiparams{'P12_PASS'} = '';
108 $cgiparams{'ROOTCERT_ORGANIZATION'} = '';
109 $cgiparams{'ROOTCERT_HOSTNAME'} = '';
110 $cgiparams{'ROOTCERT_EMAIL'} = '';
111 $cgiparams{'ROOTCERT_OU'} = '';
112 $cgiparams{'ROOTCERT_CITY'} = '';
113 $cgiparams{'ROOTCERT_STATE'} = '';
114
115 &Header::getcgihash(\%cgiparams, {'wantfile' => 1, 'filevar' => 'FH'});
116
117 ###
118 ### Useful functions
119 ###
120 sub valid_dns_host {
121         my $hostname = $_[0];
122         unless ($hostname) { return "No hostname"};
123         my $res = new Net::DNS::Resolver;
124         my $query = $res->search("$hostname");
125         if ($query) {
126                 foreach my $rr ($query->answer) {
127                         ## Potential bug - we are only looking at A records:
128                         return 0 if $rr->type eq "A";
129                 }
130         } else {
131                 return $res->errorstring;
132         }
133 }
134 ###
135 ### Just return true is one interface is vpn enabled
136 ###
137 sub vpnenabled {
138     return ($vpnsettings{'ENABLED'} eq 'on');
139 }
140 ###
141 ### old version: maintain serial number to one, without explication. 
142 ### this             : let the counter go, so that each cert is numbered.
143 ###
144 sub cleanssldatabase
145 {
146     if (open(FILE, ">${General::swroot}/certs/serial")) {
147         print FILE "01";
148         close FILE;
149     }
150     if (open(FILE, ">${General::swroot}/certs/index.txt")) {
151         print FILE "";
152         close FILE;
153     }
154     unlink ("${General::swroot}/certs/index.txt.old");
155     unlink ("${General::swroot}/certs/serial.old");
156     unlink ("${General::swroot}/certs/01.pem");
157 }
158 sub newcleanssldatabase
159 {
160     if (! -s "${General::swroot}/certs/serial" )  {
161         open(FILE, ">${General::swroot}/certs/serial");
162         print FILE "01";
163         close FILE;
164     }
165     if (! -s ">${General::swroot}/certs/index.txt") {
166         system ("touch ${General::swroot}/certs/index.txt");
167     }
168     unlink ("${General::swroot}/certs/index.txt.old");
169     unlink ("${General::swroot}/certs/serial.old");
170 #   unlink ("${General::swroot}/certs/01.pem");         numbering evolves. Wrong place to delete
171 }
172
173 ###
174 ### Call openssl and return errormessage if any
175 ###
176 sub callssl ($) {
177     my $opt = shift;
178     my $retssl =  `/usr/bin/openssl $opt 2>&1`; #redirect stderr
179     my $ret = '';
180     foreach my $line (split (/\n/, $retssl)) {
181         &General::log("ipsec", "$line") if (0);         # 1 for verbose logging
182         $ret .= '<br>'.$line if ( $line =~ /error|unknown/ );
183     }
184     if ($ret) {
185         $ret= &Header::cleanhtml($ret);
186     }
187     return $ret ? "$Lang::tr{'openssl produced an error'}: $ret" : '' ;
188 }
189 ###
190 ### Obtain a CN from given cert
191 ###
192 sub getCNfromcert ($) {
193     #&General::log("ipsec", "Extracting name from $_[0]...");
194     my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
195     $temp =~ /Subject:.*CN=(.*)[\n]/;
196     $temp = $1;
197     $temp =~ s+/Email+, E+;
198     $temp =~ s/ ST=/ S=/;
199     $temp =~ s/,//g;
200     $temp =~ s/\'//g;
201     return $temp;
202 }
203 ###
204 ### Obtain Subject from given cert
205 ###
206 sub getsubjectfromcert ($) {
207     #&General::log("ipsec", "Extracting subject from $_[0]...");
208     my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
209     $temp =~ /Subject: (.*)[\n]/;
210     $temp = $1;
211     $temp =~ s+/Email+, E+;
212     $temp =~ s/ ST=/ S=/;
213     return $temp;
214 }
215 ###
216 ### Combine local subnet and connection name to make a unique name for each connection section 
217 ### (this sub is not used now)
218 ###
219 sub makeconnname ($) {
220     my $conn = shift;
221     my $subnet = shift;
222
223     $subnet =~ /^(.*?)\/(.*?)$/;        # $1=IP $2=mask
224     my $ip = unpack('N', &Socket::inet_aton($1));
225     if (length ($2) > 2) {
226         my $mm =  unpack('N', &Socket::inet_aton($2));
227         while ( ($mm & 1)==0 ) {
228             $ip >>= 1; 
229             $mm >>= 1;
230         };
231     } else {
232         $ip >>=  (32 - $2);
233     }
234     return sprintf ("%s-%X", $conn, $ip);
235 }
236 ###
237 ### Write a config file.
238 ###
239 ###Type=Host : GUI can choose the interface used (RED,GREEN,BLUE) and
240 ###             the side is always defined as 'left'.
241 ###             configihash[14]: 'VHOST' is allowed
242 ###
243
244 sub writeipsecfiles {
245     my %lconfighash = ();
246     my %lvpnsettings = ();
247     &General::readhasharray("${General::swroot}/vpn/config", \%lconfighash);
248     &General::readhash("${General::swroot}/vpn/settings", \%lvpnsettings);
249
250     open(CONF,    ">${General::swroot}/vpn/ipsec.conf") or die "Unable to open ${General::swroot}/vpn/ipsec.conf: $!";
251     open(SECRETS, ">${General::swroot}/vpn/ipsec.secrets") or die "Unable to open ${General::swroot}/vpn/ipsec.secrets: $!";
252     flock CONF, 2;
253     flock SECRETS, 2;
254     print CONF "version 2\n\n";
255     print CONF "config setup\n";
256     #create an ipsec Interface for each 'enabled' ones
257     #loop trought configuration and add physical interfaces to the list
258     my $interfaces = "\tinterfaces=\"";
259     foreach my $key (keys %lconfighash) {
260         next if ($lconfighash{$key}[0] ne 'on');
261         $interfaces .= "%defaultroute "                     if ($interfaces !~ /defaultroute/ && $lconfighash{$key}[26] eq 'RED');
262         $interfaces .= "$netsettings{'GREEN_DEV'} "  if ($interfaces !~ /ipsec1/              && $lconfighash{$key}[26] eq 'GREEN');
263         $interfaces .= "$netsettings{'BLUE_DEV'} "   if ($interfaces !~ /ipsec2/              && $lconfighash{$key}[26] eq 'BLUE');
264         $interfaces .= "$netsettings{'ORANGE_DEV'} " if ($interfaces !~ /ipsec3/              && $lconfighash{$key}[26] eq 'ORANGE');
265     }
266     print CONF $interfaces . "\"\n";
267
268     my $plutodebug = '';                        # build debug list
269     map ($plutodebug .= $lvpnsettings{$_} eq 'on' ? lc (substr($_,4)).' ' : '',
270         ('DBG_CRYPT','DBG_PARSING','DBG_EMITTING','DBG_CONTROL',
271          'DBG_DNS'));
272     $plutodebug = 'none' if $plutodebug eq '';  # if nothing selected, use 'none'.
273     #print CONF "\tklipsdebug=\"none\"\n";
274     print CONF "\tplutodebug=\"$plutodebug\"\n";
275     # deprecated in ipsec.conf version 2
276     #print CONF "\tplutoload=%search\n";
277     #print CONF "\tplutostart=%search\n";
278     print CONF "\tuniqueids=yes\n";
279     print CONF "\tnat_traversal=yes\n";
280     print CONF "\toverridemtu=$lvpnsettings{'VPN_OVERRIDE_MTU'}\n" if ($lvpnsettings{'VPN_OVERRIDE_MTU'} ne '');
281     print CONF "\tvirtual_private=%v4:10.0.0.0/8,%v4:172.16.0.0/12,%v4:192.168.0.0/16";
282     print CONF ",%v4:!$green_cidr";
283     if (length($netsettings{'ORANGE_DEV'}) > 2) {
284         print CONF ",%v4:!$orange_cidr";
285     }
286     if (length($netsettings{'BLUE_DEV'}) > 2) {
287         print CONF ",%v4:!$blue_cidr";
288     }
289     foreach my $key (keys %lconfighash) {
290         if ($lconfighash{$key}[3] eq 'net') {
291             print CONF ",%v4:!$lconfighash{$key}[11]";
292         }
293     }
294     print CONF "\n\n";
295     print CONF "conn %default\n";
296     print CONF "\tkeyingtries=0\n";
297     #strongswan doesn't know this
298     #print CONF "\tdisablearrivalcheck=no\n";
299     print CONF "\n";
300
301     # Add user includes to config file
302     print CONF "include /etc/ipsec.user.conf\n";
303     print CONF "\n";
304
305     print SECRETS "include /etc/ipsec.user.secrets\n";
306
307     if (-f "${General::swroot}/certs/hostkey.pem") {
308         print SECRETS ": RSA ${General::swroot}/certs/hostkey.pem\n"
309     }
310     my $last_secrets = ''; # old the less specifics connections
311     
312     foreach my $key (keys %lconfighash) {
313         next if ($lconfighash{$key}[0] ne 'on');
314
315         #remote peer is not set? => use '%any'
316         $lconfighash{$key}[10] = '%any' if ($lconfighash{$key}[10] eq '');
317
318         my $localside;
319         if ($lconfighash{$key}[26] eq 'BLUE') {
320                 $localside = $netsettings{'BLUE_ADDRESS'};
321         } elsif ($lconfighash{$key}[26] eq 'GREEN') {
322                 $localside = $netsettings{'GREEN_ADDRESS'};
323         } elsif ($lconfighash{$key}[26] eq 'ORANGE') {
324                 $localside = $netsettings{'ORANGE_ADDRESS'};
325         } else {        # it is RED
326                 $localside = $lvpnsettings{'VPN_IP'};
327         }
328
329         print CONF "conn $lconfighash{$key}[1]\n";
330         print CONF "\tleft=$localside\n";
331         print CONF "\tleftnexthop=%defaultroute\n" if ($lconfighash{$key}[26] eq 'RED' && $lvpnsettings{'VPN_IP'} ne '%defaultroute');
332         my $cidr_net=&General::ipcidr($lconfighash{$key}[8]);
333         print CONF "\tleftsubnet=$cidr_net\n";
334         print CONF "\tleftfirewall=yes\n";
335         print CONF "\tlefthostaccess=yes\n";
336
337         print CONF "\tright=$lconfighash{$key}[10]\n";
338         if ($lconfighash{$key}[3] eq 'net') {
339             my $cidr_net=&General::ipcidr($lconfighash{$key}[11]);
340             print CONF "\trightsubnet=$cidr_net\n";
341             print CONF "\trightnexthop=%defaultroute\n";
342         } elsif ($lconfighash{$key}[10] eq '%any' && $lconfighash{$key}[14] eq 'on') { #vhost allowed for roadwarriors?
343             print CONF "\trightsubnet=vhost:%no,%priv\n";
344         }
345
346         # Local Cert and Remote Cert (unless auth is DN dn-auth)
347         if ($lconfighash{$key}[4] eq 'cert') {
348             print CONF "\tleftcert=${General::swroot}/certs/hostcert.pem\n";
349             print CONF "\trightcert=${General::swroot}/certs/$lconfighash{$key}[1]cert.pem\n" if ($lconfighash{$key}[2] ne '%auth-dn');
350         }
351
352         # Local and Remote IDs
353         print CONF "\tleftid=\"$lconfighash{$key}[7]\"\n" if ($lconfighash{$key}[7]);
354         print CONF "\trightid=\"$lconfighash{$key}[9]\"\n" if ($lconfighash{$key}[9]);
355
356         # Algorithms
357         if ($lconfighash{$key}[18] && $lconfighash{$key}[19] && $lconfighash{$key}[20]) {
358             print CONF "\tike=";
359             my @encs   = split('\|', $lconfighash{$key}[18]);
360             my @ints   = split('\|', $lconfighash{$key}[19]);
361             my @groups = split('\|', $lconfighash{$key}[20]);
362             my $comma = 0;
363             foreach my $i (@encs) {
364                 foreach my $j (@ints) {
365                     foreach my $k (@groups) {
366                         if ($comma != 0) { print CONF ","; } else { $comma = 1; }
367                     print CONF "$i-$j-modp$k";
368                 }
369                     }
370             }
371             if ($lconfighash{$key}[24] eq 'on') {       #only proposed algorythms?
372                 print CONF "!\n";
373             } else {
374                 print CONF "\n";
375             }
376         }
377         if ($lconfighash{$key}[21] && $lconfighash{$key}[22]) {
378             print CONF "\tesp=";
379             my @encs   = split('\|', $lconfighash{$key}[21]);
380             my @ints   = split('\|', $lconfighash{$key}[22]);
381             my $comma = 0;
382             foreach my $i (@encs) {
383                 foreach my $j (@ints) {
384                     if ($comma != 0) { print CONF ","; } else { $comma = 1; }
385                     print CONF "$i-$j";
386                 }
387             }
388             if ($lconfighash{$key}[24] eq 'on') {       #only proposed algorythms?
389                 print CONF "!\n";
390             } else {
391                 print CONF "\n";
392             }
393         }
394         if ($lconfighash{$key}[23]) {
395             print CONF "\tpfsgroup=$lconfighash{$key}[23]\n";
396         }
397
398         # IKE V1 or V2
399         if (! $lconfighash{$key}[29]) {
400            $lconfighash{$key}[29] = "ikev1";
401         }
402         print CONF "\tkeyexchange=$lconfighash{$key}[29]\n";
403
404         # Lifetimes
405         print CONF "\tikelifetime=$lconfighash{$key}[16]h\n" if ($lconfighash{$key}[16]);
406         print CONF "\tkeylife=$lconfighash{$key}[17]h\n" if ($lconfighash{$key}[17]);
407
408         # Compression
409         print CONF "\tcompress=yes\n" if ($lconfighash{$key}[13] eq 'on');
410
411         # Dead Peer Detection
412         print CONF "\tdpddelay=30\n";
413         print CONF "\tdpdtimeout=120\n";
414         print CONF "\tdpdaction=$lconfighash{$key}[27]\n";
415
416         # Disable pfs ?
417         print CONF "\tpfs=". ($lconfighash{$key}[28] eq 'on' ? "yes\n" : "no\n");
418
419         # Build Authentication details:  LEFTid RIGHTid : PSK psk
420         my $psk_line;
421         if ($lconfighash{$key}[4] eq 'psk') {
422             $psk_line = ($lconfighash{$key}[7] ? $lconfighash{$key}[7] : $localside) . " " ;
423             $psk_line .= $lconfighash{$key}[9] ? $lconfighash{$key}[9] : $lconfighash{$key}[10];  #remoteid or remote address?
424             $psk_line .= " : PSK '$lconfighash{$key}[5]'\n";
425             # if the line contains %any, it is less specific than two IP or ID, so move it at end of file.
426             if ($psk_line =~ /%any/) {
427                 $last_secrets .= $psk_line;
428             } else {
429                 print SECRETS $psk_line;
430             }
431             print CONF "\tauthby=secret\n";
432         } else {
433             print CONF "\tauthby=rsasig\n";
434             print CONF "\tleftrsasigkey=%cert\n";
435             print CONF "\trightrsasigkey=%cert\n";
436         }
437
438         # Automatically start only if a net-to-net connection
439         if ($lconfighash{$key}[3] eq 'host') {
440             print CONF "\tauto=add\n";
441         } else {
442             print CONF "\tauto=start\n";
443         }
444         print CONF "\n";
445     }#foreach key
446     print SECRETS $last_secrets if ($last_secrets);
447     close(CONF);
448     close(SECRETS);
449 }
450
451 ###
452 ### Save main settings
453 ###
454 if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq '' && $cgiparams{'KEY'} eq '') {
455     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
456     unless (&General::validfqdn($cgiparams{'VPN_IP'}) || &General::validip($cgiparams{'VPN_IP'})
457             || $cgiparams{'VPN_IP'} eq '%defaultroute' ) {
458         $errormessage = $Lang::tr{'invalid input for hostname'};
459         goto SAVE_ERROR;
460     }
461
462     unless ($cgiparams{'VPN_DELAYED_START'} =~ /^[0-9]{1,3}$/ ) { #allow 0-999 seconds !
463         $errormessage = $Lang::tr{'invalid time period'};
464         goto SAVE_ERROR;
465     }
466
467     unless ($cgiparams{'VPN_OVERRIDE_MTU'} =~ /^(|[0-9]{1,5})$/ ) { #allow 0-99999
468         $errormessage = $Lang::tr{'vpn mtu invalid'};
469         goto SAVE_ERROR;
470     }
471
472     unless ($cgiparams{'VPN_WATCH'} =~ /^(|off|on)$/ ) {
473         $errormessage = $Lang::tr{'invalid input'};
474         goto SAVE_ERROR;
475     }
476
477     map ($vpnsettings{$_} = $cgiparams{$_},
478         ('ENABLED','DBG_CRYPT','DBG_PARSING','DBG_EMITTING','DBG_CONTROL',
479          'DBG_DNS'));
480
481     $vpnsettings{'VPN_IP'} = $cgiparams{'VPN_IP'};
482     $vpnsettings{'VPN_DELAYED_START'} = $cgiparams{'VPN_DELAYED_START'};
483     $vpnsettings{'VPN_OVERRIDE_MTU'} = $cgiparams{'VPN_OVERRIDE_MTU'};
484     $vpnsettings{'VPN_WATCH'} = $cgiparams{'VPN_WATCH'};
485     &General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
486     &writeipsecfiles();
487     if (&vpnenabled) {
488         system('/usr/local/bin/ipsecctrl', 'S');
489     } else {
490         system('/usr/local/bin/ipsecctrl', 'D');
491     }
492     sleep $sleepDelay;
493     SAVE_ERROR:
494 ###
495 ### Reset all step 2
496 ###
497 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'} && $cgiparams{'AREUSURE'} eq 'yes') {
498     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
499
500     foreach my $key (keys %confighash) {
501         if ($confighash{$key}[4] eq 'cert') {
502             delete $confighash{$key};
503         }
504     }
505     while (my $file = glob("${General::swroot}/{ca,certs,crls,private}/*")) {
506         unlink $file
507     }
508     &cleanssldatabase();
509     if (open(FILE, ">${General::swroot}/vpn/caconfig")) {
510         print FILE "";
511         close FILE;
512     }
513     &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
514     &writeipsecfiles();
515     system('/usr/local/bin/ipsecctrl', 'R');
516     sleep $sleepDelay;
517
518 ###
519 ### Reset all step 1
520 ###
521 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'}) {
522     &Header::showhttpheaders();
523     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
524     &Header::openbigbox('100%', 'left', '', '');
525     &Header::openbox('100%', 'left', $Lang::tr{'are you sure'});
526     print <<END
527         <form method='post' action='$ENV{'SCRIPT_NAME'}'>
528         <table width='100%'>
529             <tr>
530                 <td align='center'>
531                 <input type='hidden' name='AREUSURE' value='yes' />
532                 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:
533                 $Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}</td>
534             </tr><tr>
535                 <td align='center'>
536                 <input type='submit' name='ACTION' value='$Lang::tr{'remove x509'}' />
537                 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
538             </tr>
539         </table>
540         </form>
541 END
542     ;
543     &Header::closebox();
544     &Header::closebigbox();
545     &Header::closepage();
546     exit (0);
547
548 ###
549 ### Upload CA Certificate
550 ###
551 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload ca certificate'}) {
552     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
553
554     if ($cgiparams{'CA_NAME'} !~ /^[a-zA-Z0-9]+$/) {
555         $errormessage = $Lang::tr{'name must only contain characters'};
556         goto UPLOADCA_ERROR;
557     }
558
559     if (length($cgiparams{'CA_NAME'}) >60) {
560         $errormessage = $Lang::tr{'name too long'};
561         goto VPNCONF_ERROR;
562     }
563
564     if ($cgiparams{'CA_NAME'} eq 'ca') {
565         $errormessage = $Lang::tr{'name is invalid'};
566         goto UPLOAD_CA_ERROR;
567     }
568
569     # Check if there is no other entry with this name
570     foreach my $key (keys %cahash) {
571         if ($cahash{$key}[0] eq $cgiparams{'CA_NAME'}) {
572             $errormessage = $Lang::tr{'a ca certificate with this name already exists'};
573             goto UPLOADCA_ERROR;
574         }
575     }
576
577     if (ref ($cgiparams{'FH'}) ne 'Fh') {
578         $errormessage = $Lang::tr{'there was no file upload'};
579         goto UPLOADCA_ERROR;
580     }
581     # Move uploaded ca to a temporary file
582     (my $fh, my $filename) = tempfile( );
583     if (copy ($cgiparams{'FH'}, $fh) != 1) {
584         $errormessage = $!;
585         goto UPLOADCA_ERROR;
586     }
587     my $temp = `/usr/bin/openssl x509 -text -in $filename`;
588     if ($temp !~ /CA:TRUE/i) {
589         $errormessage = $Lang::tr{'not a valid ca certificate'};
590         unlink ($filename);
591         goto UPLOADCA_ERROR;
592     } else {
593         move($filename, "${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem");
594         if ($? ne 0) {
595             $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
596             unlink ($filename);
597             goto UPLOADCA_ERROR;
598         }
599     }
600
601     my $key = &General::findhasharraykey (\%cahash);
602     $cahash{$key}[0] = $cgiparams{'CA_NAME'};
603     $cahash{$key}[1] = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem"));
604     &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
605
606     system('/usr/local/bin/ipsecctrl', 'R');
607     sleep $sleepDelay;
608
609     UPLOADCA_ERROR:
610
611 ###
612 ### Display ca certificate
613 ###
614 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show ca certificate'}) {
615     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
616
617     if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem") {
618         &Header::showhttpheaders();
619         &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
620         &Header::openbigbox('100%', 'left', '', '');
621         &Header::openbox('100%', 'left', "$Lang::tr{'ca certificate'}:");
622         my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem`;
623         $output = &Header::cleanhtml($output,"y");
624         print "<pre>$output</pre>\n";
625         &Header::closebox();
626         print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
627         &Header::closebigbox();
628         &Header::closepage();
629         exit(0);
630     } else {
631         $errormessage = $Lang::tr{'invalid key'};
632     }
633
634 ###
635 ### Export ca certificate to browser
636 ###
637 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download ca certificate'}) {
638     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
639
640     if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
641         print "Content-Type: application/force-download\n";
642         print "Content-Type: application/octet-stream\r\n";
643         print "Content-Disposition: attachment; filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
644         print `/usr/bin/openssl x509 -in ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem`;
645         exit(0);
646     } else {
647         $errormessage = $Lang::tr{'invalid key'};
648     }
649
650 ###
651 ### Remove ca certificate (step 2)
652 ###
653 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'} && $cgiparams{'AREUSURE'} eq 'yes') {
654     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
655     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
656
657     if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
658         foreach my $key (keys %confighash) {
659             my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/certs/$confighash{$key}[1]cert.pem`;
660             if ($test =~ /: OK/) {
661                 # Delete connection
662                 system('/usr/local/bin/ipsecctrl', 'D', $key) if (&vpnenabled);
663                 unlink ("${General::swroot}/certs/$confighash{$key}[1]cert.pem");
664                 unlink ("${General::swroot}/certs/$confighash{$key}[1].p12");
665                 delete $confighash{$key};
666                 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
667                 &writeipsecfiles();
668             }
669         }
670         unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
671         delete $cahash{$cgiparams{'KEY'}};
672         &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
673         system('/usr/local/bin/ipsecctrl', 'R');
674         sleep $sleepDelay;
675     } else {
676         $errormessage = $Lang::tr{'invalid key'};
677     }
678 ###
679 ### Remove ca certificate (step 1)
680 ###
681 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'}) {
682     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
683     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
684
685     my $assignedcerts = 0;
686     if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
687         foreach my $key (keys %confighash) {
688             my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem ${General::swroot}/certs/$confighash{$key}[1]cert.pem`;
689             if ($test =~ /: OK/) {
690                 $assignedcerts++;
691             }
692         }
693         if ($assignedcerts) {
694             &Header::showhttpheaders();
695             &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
696             &Header::openbigbox('100%', 'left', '', '');
697             &Header::openbox('100%', 'left', $Lang::tr{'are you sure'});
698             print <<END
699             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
700             <table width='100%'>
701                 <tr>
702                     <td align='center'>
703                     <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
704                     <input type='hidden' name='AREUSURE' value='yes' /></td>
705                 </tr><tr>
706                     <td align='center'>
707                     <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>
708                     $Lang::tr{'connections are associated with this ca.  deleting the ca will delete these connections as well.'}</td>
709                 </tr><tr>
710                     <td align='center'>
711                     <input type='submit' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
712                     <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
713                 </tr>
714             </table>
715             </form>
716 END
717             ;
718             &Header::closebox();
719             &Header::closebigbox();
720             &Header::closepage();
721             exit (0);
722         } else {
723             unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
724             delete $cahash{$cgiparams{'KEY'}};
725             &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
726             system('/usr/local/bin/ipsecctrl', 'R');
727             sleep $sleepDelay;
728         }
729     } else {
730         $errormessage = $Lang::tr{'invalid key'};
731     }
732
733 ###
734 ### Display root certificate
735 ###
736 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'} ||
737         $cgiparams{'ACTION'} eq $Lang::tr{'show host certificate'}) {
738     my $output;
739     &Header::showhttpheaders();
740     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
741     &Header::openbigbox('100%', 'left', '', '');
742     if ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'}) {
743         &Header::openbox('100%', 'left', "$Lang::tr{'root certificate'}:");
744         $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ca/cacert.pem`;
745     } else {
746         &Header::openbox('100%', 'left', "$Lang::tr{'host certificate'}:");
747         $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/hostcert.pem`;
748     }
749     $output = &Header::cleanhtml($output,"y");
750     print "<pre>$output</pre>\n";
751     &Header::closebox();
752     print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
753     &Header::closebigbox();
754     &Header::closepage();
755     exit(0);
756
757 ###
758 ### Export root certificate to browser
759 ###
760 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download root certificate'}) {
761     if ( -f "${General::swroot}/ca/cacert.pem" ) {
762         print "Content-Type: application/force-download\n";
763         print "Content-Disposition: attachment; filename=cacert.pem\r\n\r\n";
764         print `/usr/bin/openssl x509 -in ${General::swroot}/ca/cacert.pem`;
765         exit(0);
766     }
767 ###
768 ### Export host certificate to browser
769 ###
770 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download host certificate'}) {
771     if ( -f "${General::swroot}/certs/hostcert.pem" ) {
772         print "Content-Type: application/force-download\n";
773         print "Content-Disposition: attachment; filename=hostcert.pem\r\n\r\n";
774         print `/usr/bin/openssl x509 -in ${General::swroot}/certs/hostcert.pem`;
775         exit(0);
776     }
777 ###
778 ### Form for generating/importing the caroot+host certificate
779 ###
780 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate root/host certificates'} ||
781          $cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
782
783     if (-f "${General::swroot}/ca/cacert.pem") {
784         $errormessage = $Lang::tr{'valid root certificate already exists'};
785         goto ROOTCERT_SKIP;
786     }
787
788     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
789     # fill in initial values
790     if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
791         if (-e "${General::swroot}/red/active" && open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
792             my $ipaddr = <IPADDR>;
793             close IPADDR;
794             chomp ($ipaddr);
795             $cgiparams{'ROOTCERT_HOSTNAME'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
796             if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
797                 $cgiparams{'ROOTCERT_HOSTNAME'} = $ipaddr;
798             }
799         }
800         $cgiparams{'ROOTCERT_COUNTRY'} = $vpnsettings{'ROOTCERT_COUNTRY'} if (!$cgiparams{'ROOTCERT_COUNTRY'});
801     } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
802         &General::log("ipsec", "Importing from p12...");
803
804         if (ref ($cgiparams{'FH'}) ne 'Fh') {
805             $errormessage = $Lang::tr{'there was no file upload'};
806             goto ROOTCERT_ERROR;
807         }
808
809         # Move uploaded certificate request to a temporary file
810         (my $fh, my $filename) = tempfile( );
811         if (copy ($cgiparams{'FH'}, $fh) != 1) {
812             $errormessage = $!;
813             goto ROOTCERT_ERROR;
814         }
815
816         # Extract the CA certificate from the file
817         &General::log("ipsec", "Extracting caroot from p12...");
818         if (open(STDIN, "-|")) {
819             my  $opt  = " pkcs12 -cacerts -nokeys";
820                 $opt .= " -in $filename";
821                 $opt .= " -out /tmp/newcacert";
822             $errormessage = &callssl ($opt);
823         } else {        #child
824             print "$cgiparams{'P12_PASS'}\n";
825             exit (0);
826         }
827
828         # Extract the Host certificate from the file
829         if (!$errormessage) {
830             &General::log("ipsec", "Extracting host cert from p12...");
831             if (open(STDIN, "-|")) {
832                 my  $opt  = " pkcs12 -clcerts -nokeys";
833                     $opt .= " -in $filename";
834                     $opt .= " -out /tmp/newhostcert";
835                 $errormessage = &callssl ($opt);
836             } else {    #child
837                 print "$cgiparams{'P12_PASS'}\n";
838                 exit (0);
839             }
840         }
841
842         # Extract the Host key from the file
843         if (!$errormessage) {
844             &General::log("ipsec", "Extracting private key from p12...");
845             if (open(STDIN, "-|")) {
846                 my  $opt  = " pkcs12 -nocerts -nodes";
847                     $opt .= " -in $filename";
848                     $opt .= " -out /tmp/newhostkey";
849                 $errormessage = &callssl ($opt);
850             } else {    #child
851                 print "$cgiparams{'P12_PASS'}\n";
852                 exit (0);
853             }
854         }
855
856         if (!$errormessage) {
857             &General::log("ipsec", "Moving cacert...");
858             move("/tmp/newcacert", "${General::swroot}/ca/cacert.pem");
859             $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
860         }
861
862         if (!$errormessage) {
863             &General::log("ipsec", "Moving host cert...");
864             move("/tmp/newhostcert", "${General::swroot}/certs/hostcert.pem");
865             $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
866         }
867
868         if (!$errormessage) {
869             &General::log("ipsec", "Moving private key...");
870             move("/tmp/newhostkey", "${General::swroot}/certs/hostkey.pem");
871             $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
872         }
873         
874         #cleanup temp files
875         unlink ($filename);
876         unlink ('/tmp/newcacert');
877         unlink ('/tmp/newhostcert');
878         unlink ('/tmp/newhostkey');
879         if ($errormessage) {
880             unlink ("${General::swroot}/ca/cacert.pem");
881             unlink ("${General::swroot}/certs/hostcert.pem");
882             unlink ("${General::swroot}/certs/hostkey.pem");
883             goto ROOTCERT_ERROR;
884         }
885
886         # Create empty CRL cannot be done because we don't have
887         # the private key for this CAROOT
888         # IPFire can only import certificates
889
890         &General::log("ipsec", "p12 import completed!");
891         &cleanssldatabase();
892         goto ROOTCERT_SUCCESS;
893
894     } elsif ($cgiparams{'ROOTCERT_COUNTRY'} ne '') {
895
896         # Validate input since the form was submitted
897         if ($cgiparams{'ROOTCERT_ORGANIZATION'} eq ''){
898             $errormessage = $Lang::tr{'organization cant be empty'};
899             goto ROOTCERT_ERROR;
900         }
901         if (length($cgiparams{'ROOTCERT_ORGANIZATION'}) >60) {
902             $errormessage = $Lang::tr{'organization too long'};
903             goto ROOTCERT_ERROR;
904         }
905         if ($cgiparams{'ROOTCERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
906             $errormessage = $Lang::tr{'invalid input for organization'};
907             goto ROOTCERT_ERROR;
908         }
909         if ($cgiparams{'ROOTCERT_HOSTNAME'} eq ''){
910             $errormessage = $Lang::tr{'hostname cant be empty'};
911             goto ROOTCERT_ERROR;
912         }
913         unless (&General::validfqdn($cgiparams{'ROOTCERT_HOSTNAME'}) || &General::validip($cgiparams{'ROOTCERT_HOSTNAME'})) {
914             $errormessage = $Lang::tr{'invalid input for hostname'};
915             goto ROOTCERT_ERROR;
916         }
917         if ($cgiparams{'ROOTCERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'ROOTCERT_EMAIL'}))) {
918             $errormessage = $Lang::tr{'invalid input for e-mail address'};
919             goto ROOTCERT_ERROR;
920         }
921         if (length($cgiparams{'ROOTCERT_EMAIL'}) > 40) {
922             $errormessage = $Lang::tr{'e-mail address too long'};
923             goto ROOTCERT_ERROR;
924         }
925         if ($cgiparams{'ROOTCERT_OU'} ne '' && $cgiparams{'ROOTCERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
926             $errormessage = $Lang::tr{'invalid input for department'};
927             goto ROOTCERT_ERROR;
928         }
929         if ($cgiparams{'ROOTCERT_CITY'} ne '' && $cgiparams{'ROOTCERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
930             $errormessage = $Lang::tr{'invalid input for city'};
931             goto ROOTCERT_ERROR;
932         }
933         if ($cgiparams{'ROOTCERT_STATE'} ne '' && $cgiparams{'ROOTCERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
934             $errormessage = $Lang::tr{'invalid input for state or province'};
935             goto ROOTCERT_ERROR;
936         }
937         if ($cgiparams{'ROOTCERT_COUNTRY'} !~ /^[A-Z]*$/) {
938             $errormessage = $Lang::tr{'invalid input for country'};
939             goto ROOTCERT_ERROR;
940         }
941         #the exact syntax is a list comma separated of 
942         #  email:any-validemail
943         #       URI: a uniform resource indicator
944         #   DNS: a DNS domain name
945         #   RID: a registered OBJECT IDENTIFIER
946         #   IP: an IP address
947         # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
948
949         if ($cgiparams{'SUBJECTALTNAME'} ne '' && $cgiparams{'SUBJECTALTNAME'} !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/,\.\-_@]*$/) {
950             $errormessage = $Lang::tr{'vpn altname syntax'};
951             goto VPNCONF_ERROR;
952         }
953
954         # Copy the cgisettings to vpnsettings and save the configfile
955         $vpnsettings{'ROOTCERT_ORGANIZATION'}   = $cgiparams{'ROOTCERT_ORGANIZATION'};
956         $vpnsettings{'ROOTCERT_HOSTNAME'}       = $cgiparams{'ROOTCERT_HOSTNAME'};
957         $vpnsettings{'ROOTCERT_EMAIL'}          = $cgiparams{'ROOTCERT_EMAIL'};
958         $vpnsettings{'ROOTCERT_OU'}             = $cgiparams{'ROOTCERT_OU'};
959         $vpnsettings{'ROOTCERT_CITY'}           = $cgiparams{'ROOTCERT_CITY'};
960         $vpnsettings{'ROOTCERT_STATE'}          = $cgiparams{'ROOTCERT_STATE'};
961         $vpnsettings{'ROOTCERT_COUNTRY'}        = $cgiparams{'ROOTCERT_COUNTRY'};
962         &General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
963
964         # Replace empty strings with a .
965         (my $ou = $cgiparams{'ROOTCERT_OU'}) =~ s/^\s*$/\./;
966         (my $city = $cgiparams{'ROOTCERT_CITY'}) =~ s/^\s*$/\./;
967         (my $state = $cgiparams{'ROOTCERT_STATE'}) =~ s/^\s*$/\./;
968
969         # Create the CA certificate
970         if (!$errormessage) {
971             &General::log("ipsec", "Creating cacert...");
972             if (open(STDIN, "-|")) {
973                 my $opt  = " req -x509 -nodes -rand /proc/interrupts:/proc/net/rt_cache";
974                    $opt .= " -days 999999";
975                    $opt .= " -newkey rsa:2048";
976                    $opt .= " -keyout ${General::swroot}/private/cakey.pem";
977                    $opt .= " -out ${General::swroot}/ca/cacert.pem";
978
979                 $errormessage = &callssl ($opt);
980             } else {    #child
981                 print  "$cgiparams{'ROOTCERT_COUNTRY'}\n";
982                 print  "$state\n";
983                 print  "$city\n";
984                 print  "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
985                 print  "$ou\n";
986                 print  "$cgiparams{'ROOTCERT_ORGANIZATION'} CA\n";
987                 print  "$cgiparams{'ROOTCERT_EMAIL'}\n";
988                 exit (0);
989             }
990         }
991
992         # Create the Host certificate request
993         if (!$errormessage) {
994             &General::log("ipsec", "Creating host cert...");
995             if (open(STDIN, "-|")) {
996                 my $opt  = " req -nodes -rand /proc/interrupts:/proc/net/rt_cache";
997                    $opt .= " -newkey rsa:1024";
998                    $opt .= " -keyout ${General::swroot}/certs/hostkey.pem";
999                    $opt .= " -out ${General::swroot}/certs/hostreq.pem";
1000                 $errormessage = &callssl ($opt);
1001             } else {    #child
1002                 print  "$cgiparams{'ROOTCERT_COUNTRY'}\n";
1003                 print  "$state\n";
1004                 print  "$city\n";
1005                 print  "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
1006                 print  "$ou\n";
1007                 print  "$cgiparams{'ROOTCERT_HOSTNAME'}\n";
1008                 print  "$cgiparams{'ROOTCERT_EMAIL'}\n";
1009                 print  ".\n";
1010                 print  ".\n";
1011                 exit (0);
1012             }
1013         }
1014
1015         # Sign the host certificate request
1016         if (!$errormessage) {
1017             &General::log("ipsec", "Self signing host cert...");
1018
1019             #No easy way for specifying the contain of subjectAltName without writing a config file...
1020             my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
1021             print $fh <<END
1022             basicConstraints=CA:FALSE
1023             nsComment="OpenSSL Generated Certificate"
1024             subjectKeyIdentifier=hash
1025             authorityKeyIdentifier=keyid,issuer:always
1026 END
1027 ;
1028             print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
1029             close ($fh);
1030             
1031             my  $opt  = " ca -days 999999";
1032                 $opt .= " -batch -notext";
1033                 $opt .= " -in ${General::swroot}/certs/hostreq.pem";
1034                 $opt .= " -out ${General::swroot}/certs/hostcert.pem";
1035                 $opt .= " -extfile $v3extname";
1036             $errormessage = &callssl ($opt);
1037             unlink ("${General::swroot}/certs/hostreq.pem"); #no more needed
1038             unlink ($v3extname);
1039         }
1040
1041         # Create an empty CRL
1042         if (!$errormessage) {
1043             &General::log("ipsec", "Creating emptycrl...");
1044             my  $opt  = " ca -gencrl";
1045                 $opt .= " -out ${General::swroot}/crls/cacrl.pem";
1046             $errormessage = &callssl ($opt);
1047         }
1048         
1049         # Successfully build CA / CERT!
1050         if (!$errormessage) {
1051             &cleanssldatabase();
1052             goto ROOTCERT_SUCCESS;
1053         }
1054         
1055         #Cleanup
1056         unlink ("${General::swroot}/ca/cacert.pem");
1057         unlink ("${General::swroot}/certs/hostkey.pem");
1058         unlink ("${General::swroot}/certs/hostcert.pem");
1059         unlink ("${General::swroot}/crls/cacrl.pem");
1060         &cleanssldatabase();
1061     }
1062
1063     ROOTCERT_ERROR:
1064     &Header::showhttpheaders();
1065     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
1066     &Header::openbigbox('100%', 'left', '', $errormessage);
1067     if ($errormessage) {
1068         &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
1069         print "<class name='base'>$errormessage";
1070         print "&nbsp;</class>";
1071         &Header::closebox();
1072     }
1073     &Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
1074     print <<END
1075     <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
1076     <table width='100%' border='0' cellspacing='1' cellpadding='0'>
1077     <tr><td width='40%' class='base'>$Lang::tr{'organization name'}:</td>
1078         <td width='60%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td></tr>
1079     <tr><td class='base'>$Lang::tr{'ipfires hostname'}:</td>
1080         <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td></tr>
1081     <tr><td class='base'>$Lang::tr{'your e-mail'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1082         <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td></tr>
1083     <tr><td class='base'>$Lang::tr{'your department'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1084         <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td></tr>
1085     <tr><td class='base'>$Lang::tr{'city'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1086         <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td></tr>
1087     <tr><td class='base'>$Lang::tr{'state or province'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1088         <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td></tr>
1089     <tr><td class='base'>$Lang::tr{'country'}:</td>
1090         <td class='base'><select name='ROOTCERT_COUNTRY'>
1091 END
1092     ;
1093     foreach my $country (sort keys %{Countries::countries}) {
1094         print "<option value='$Countries::countries{$country}'";
1095         if ( $Countries::countries{$country} eq $cgiparams{'ROOTCERT_COUNTRY'} ) {
1096             print " selected='selected'";
1097         }
1098         print ">$country</option>";
1099     }
1100     print <<END
1101         </select></td></tr>
1102     <tr><td class='base'>$Lang::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*) <img src='/blob.gif' alt='*' /></td>
1103         <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value='$cgiparams{'SUBJECTALTNAME'}' size='32' /></td></tr>
1104     <tr><td>&nbsp;</td>
1105         <td><br /><input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' /><br /><br /></td></tr>
1106     <tr><td class='base' colspan='2' align='left'>
1107         <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>: 
1108         $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'}
1109     </td></tr>
1110     <tr><td colspan='2'><hr /></td></tr>
1111     <tr><td class='base' nowrap='nowrap'>$Lang::tr{'upload p12 file'}:</td>
1112         <td nowrap='nowrap'><input type='file' name='FH' size='32' /></td></tr>
1113     <tr><td class='base'>$Lang::tr{'pkcs12 file password'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1114         <td class='base' nowrap='nowrap'><input type='password' name='P12_PASS' value='$cgiparams{'P12_PASS'}' size='32' /></td></tr>
1115     <tr><td>&nbsp;</td>
1116         <td><input type='submit' name='ACTION' value='$Lang::tr{'upload p12 file'}' /></td></tr>
1117     <tr><td class='base' colspan='2' align='left'>
1118         <img src='/blob.gif' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td></tr>
1119     </table></form>
1120 END
1121     ;
1122     &Header::closebox();
1123     &Header::closebigbox();
1124     &Header::closepage();
1125     exit(0);
1126
1127     ROOTCERT_SUCCESS:
1128     if (&vpnenabled) {
1129         system('/usr/local/bin/ipsecctrl', 'S');
1130         sleep $sleepDelay;
1131     }
1132     ROOTCERT_SKIP:
1133 ###
1134 ### Export PKCS12 file to browser
1135 ###
1136 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download pkcs12 file'}) {
1137     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1138     print "Content-Type: application/force-download\n";
1139     print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . ".p12\r\n";
1140     print "Content-Type: application/octet-stream\r\n\r\n";
1141     print `/bin/cat ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12`;
1142     exit (0);
1143
1144 ###
1145 ### Display certificate
1146 ###
1147 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show certificate'}) {
1148     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1149
1150     if ( -f "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
1151         &Header::showhttpheaders();
1152         &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
1153         &Header::openbigbox('100%', 'left', '', '');
1154         &Header::openbox('100%', 'left', "$Lang::tr{'cert'}:");
1155         my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem`;
1156         $output = &Header::cleanhtml($output,"y");
1157         print "<pre>$output</pre>\n";
1158         &Header::closebox();
1159         print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
1160         &Header::closebigbox();
1161         &Header::closepage();
1162         exit(0);
1163     }
1164
1165 ###
1166 ### Export Certificate to browser
1167 ###
1168 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download certificate'}) {
1169     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1170
1171     if ( -f "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
1172         print "Content-Type: application/force-download\n";
1173         print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . "cert.pem\n\n";
1174         print `/bin/cat ${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem`;
1175         exit (0);
1176     }
1177
1178 ###
1179 ### Enable/Disable connection
1180 ###
1181 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
1182     
1183     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1184     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1185
1186     if ($confighash{$cgiparams{'KEY'}}) {
1187         if ($confighash{$cgiparams{'KEY'}}[0] eq 'off') {
1188             $confighash{$cgiparams{'KEY'}}[0] = 'on';
1189             &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1190             &writeipsecfiles();
1191             system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'}) if (&vpnenabled);
1192         } else {
1193             system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
1194             $confighash{$cgiparams{'KEY'}}[0] = 'off';
1195             &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1196             &writeipsecfiles();
1197         }
1198         sleep $sleepDelay;
1199     } else {
1200         $errormessage = $Lang::tr{'invalid key'};
1201     }
1202
1203 ###
1204 ### Restart connection
1205 ###
1206 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'restart'}) {
1207     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1208     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1209
1210     if ($confighash{$cgiparams{'KEY'}}) {
1211         if (&vpnenabled) {
1212             system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
1213             sleep $sleepDelay;
1214         }
1215     } else {
1216         $errormessage = $Lang::tr{'invalid key'};
1217     }
1218
1219 ###
1220 ### Remove connection
1221 ###
1222 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove'}) {
1223     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1224     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1225
1226     if ($confighash{$cgiparams{'KEY'}}) {
1227         system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
1228         unlink ("${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
1229         unlink ("${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
1230         delete $confighash{$cgiparams{'KEY'}};
1231         &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1232         &writeipsecfiles();
1233     } else {
1234         $errormessage = $Lang::tr{'invalid key'};
1235     }
1236
1237 ###
1238 ### Choose between adding a host-net or net-net connection
1239 ###
1240 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'add'} && $cgiparams{'TYPE'} eq '') {
1241         &Header::showhttpheaders();
1242         &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
1243         &Header::openbigbox('100%', 'left', '', '');
1244         &Header::openbox('100%', 'left', $Lang::tr{'connection type'});
1245         print <<END
1246             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
1247             <b>$Lang::tr{'connection type'}:</b><br />
1248             <table>
1249             <tr><td><input type='radio' name='TYPE' value='host' checked='checked' /></td>
1250                 <td class='base'>$Lang::tr{'host to net vpn'}</td>
1251             </tr><tr>
1252                 <td><input type='radio' name='TYPE' value='net' /></td>
1253                 <td class='base'>$Lang::tr{'net to net vpn'}</td>
1254             </tr><tr>
1255                 <td align='center' colspan='2'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>
1256             </tr>
1257             </table></form>
1258 END
1259         ;
1260         &Header::closebox();
1261         &Header::closebigbox();
1262         &Header::closepage();
1263         exit (0);
1264 ###
1265 ### Adding/Editing/Saving a  connection
1266 ###
1267 } elsif (($cgiparams{'ACTION'} eq $Lang::tr{'add'}) ||
1268          ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) ||
1269          ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'ADVANCED'} eq '')) {
1270
1271     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1272     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
1273     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1274
1275     if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) {
1276         if (! $confighash{$cgiparams{'KEY'}}[0]) {
1277             $errormessage = $Lang::tr{'invalid key'};
1278             goto VPNCONF_END;
1279         }
1280         $cgiparams{'ENABLED'}           = $confighash{$cgiparams{'KEY'}}[0];
1281         $cgiparams{'NAME'}              = $confighash{$cgiparams{'KEY'}}[1];
1282         $cgiparams{'TYPE'}              = $confighash{$cgiparams{'KEY'}}[3];
1283         $cgiparams{'AUTH'}              = $confighash{$cgiparams{'KEY'}}[4];
1284         $cgiparams{'PSK'}               = $confighash{$cgiparams{'KEY'}}[5];
1285         #$cgiparams{'free'}             = $confighash{$cgiparams{'KEY'}}[6];
1286         $cgiparams{'LOCAL_ID'}          = $confighash{$cgiparams{'KEY'}}[7];
1287         $cgiparams{'LOCAL_SUBNET'}      = $confighash{$cgiparams{'KEY'}}[8];
1288         $cgiparams{'REMOTE_ID'}         = $confighash{$cgiparams{'KEY'}}[9];
1289         $cgiparams{'REMOTE'}            = $confighash{$cgiparams{'KEY'}}[10];
1290         $cgiparams{'REMOTE_SUBNET'}     = $confighash{$cgiparams{'KEY'}}[11];
1291         $cgiparams{'REMARK'}            = $confighash{$cgiparams{'KEY'}}[25];
1292         $cgiparams{'INTERFACE'}         = $confighash{$cgiparams{'KEY'}}[26];
1293         $cgiparams{'DPD_ACTION'}        = $confighash{$cgiparams{'KEY'}}[27];
1294         $cgiparams{'IKE_VERSION'}       = $confighash{$cgiparams{'KEY'}}[29];
1295         $cgiparams{'IKE_ENCRYPTION'}    = $confighash{$cgiparams{'KEY'}}[18];
1296         $cgiparams{'IKE_INTEGRITY'}     = $confighash{$cgiparams{'KEY'}}[19];
1297         $cgiparams{'IKE_GROUPTYPE'}     = $confighash{$cgiparams{'KEY'}}[20];
1298         $cgiparams{'IKE_LIFETIME'}      = $confighash{$cgiparams{'KEY'}}[16];
1299         $cgiparams{'ESP_ENCRYPTION'}    = $confighash{$cgiparams{'KEY'}}[21];
1300         $cgiparams{'ESP_INTEGRITY'}     = $confighash{$cgiparams{'KEY'}}[22];
1301         $cgiparams{'ESP_GROUPTYPE'}     = $confighash{$cgiparams{'KEY'}}[23];
1302         $cgiparams{'ESP_KEYLIFE'}       = $confighash{$cgiparams{'KEY'}}[17];
1303         $cgiparams{'COMPRESSION'}       = $confighash{$cgiparams{'KEY'}}[13];
1304         $cgiparams{'ONLY_PROPOSED'}     = $confighash{$cgiparams{'KEY'}}[24];
1305         $cgiparams{'PFS'}               = $confighash{$cgiparams{'KEY'}}[28];
1306         $cgiparams{'VHOST'}             = $confighash{$cgiparams{'KEY'}}[14];
1307
1308     } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
1309         $cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
1310         if ($cgiparams{'TYPE'} !~ /^(host|net)$/) {
1311             $errormessage = $Lang::tr{'connection type is invalid'};
1312             goto VPNCONF_ERROR;
1313         }
1314
1315         if ($cgiparams{'NAME'} !~ /^[a-zA-Z0-9]+$/) {
1316             $errormessage = $Lang::tr{'name must only contain characters'};
1317             goto VPNCONF_ERROR;
1318         }
1319
1320         if ($cgiparams{'NAME'} =~ /^(host|01|block|private|clear|packetdefault)$/) {
1321             $errormessage = $Lang::tr{'name is invalid'};
1322             goto VPNCONF_ERROR;
1323         }
1324
1325         if (length($cgiparams{'NAME'}) >60) {
1326             $errormessage = $Lang::tr{'name too long'};
1327             goto VPNCONF_ERROR;
1328         }
1329
1330         # Check if there is no other entry with this name
1331         if (! $cgiparams{'KEY'}) {  #only for add
1332             foreach my $key (keys %confighash) {
1333                 if ($confighash{$key}[1] eq $cgiparams{'NAME'}) {
1334                     $errormessage = $Lang::tr{'a connection with this name already exists'};
1335                     goto VPNCONF_ERROR;
1336                 }
1337             }
1338         }
1339
1340         if (($cgiparams{'TYPE'} eq 'net') && (! $cgiparams{'REMOTE'})) {
1341             $errormessage = $Lang::tr{'invalid input for remote host/ip'};
1342             goto VPNCONF_ERROR;
1343         }
1344
1345         if ($cgiparams{'REMOTE'}) {
1346             if (! &General::validip($cgiparams{'REMOTE'})) {
1347                 if (! &General::validfqdn ($cgiparams{'REMOTE'}))  {
1348                     $errormessage = $Lang::tr{'invalid input for remote host/ip'};
1349                     goto VPNCONF_ERROR;
1350                 } else {
1351                     if (&valid_dns_host($cgiparams{'REMOTE'})) {
1352                         $warnmessage = "$Lang::tr{'check vpn lr'} $cgiparams{'REMOTE'}. $Lang::tr{'dns check failed'}";
1353                     }
1354                 }
1355             }
1356         }
1357
1358         unless (&General::validipandmask($cgiparams{'LOCAL_SUBNET'})) {
1359             $errormessage = $Lang::tr{'local subnet is invalid'};
1360             goto VPNCONF_ERROR;
1361         }
1362
1363         # Allow only one roadwarrior/psk without remote IP-address
1364         if ($cgiparams{'REMOTE'} eq '' && $cgiparams{'AUTH'} eq 'psk') {
1365             foreach my $key (keys %confighash) {
1366                 if ( ($cgiparams{'KEY'} ne $key) && 
1367                       ($confighash{$key}[4] eq 'psk') && 
1368                       ($confighash{$key}[10] eq '') ) {
1369                         $errormessage = $Lang::tr{'you can only define one roadwarrior connection when using pre-shared key authentication'};
1370                         goto VPNCONF_ERROR;
1371                 }
1372             }
1373         }
1374         if (($cgiparams{'TYPE'} eq 'net') && (! &General::validipandmask($cgiparams{'REMOTE_SUBNET'}))) {
1375             $errormessage = $Lang::tr{'remote subnet is invalid'};
1376             goto VPNCONF_ERROR;
1377         }
1378
1379         if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
1380             $errormessage = $Lang::tr{'invalid input'};
1381             goto VPNCONF_ERROR;
1382         }
1383         if ($cgiparams{'EDIT_ADVANCED'} !~ /^(on|off)$/) {
1384             $errormessage = $Lang::tr{'invalid input'};
1385             goto VPNCONF_ERROR;
1386         }
1387
1388         # Allow nothing or a string (DN,FDQN,) beginning with @
1389         # with no comma but slashes between RID eg @O=FR/C=Paris/OU=myhome/CN=franck
1390         if ( ($cgiparams{'LOCAL_ID'} !~ /^(|[\w.-]*@[\w. =*\/-]+|\d+\.\d+\.\d+\.\d+)$/) ||
1391             ($cgiparams{'REMOTE_ID'} !~ /^(|[\w.-]*@[\w. =*\/-]+|\d+\.\d+\.\d+\.\d+)$/) ||
1392             (($cgiparams{'REMOTE_ID'} eq $cgiparams{'LOCAL_ID'}) && ($cgiparams{'LOCAL_ID'} ne ''))
1393            ) {
1394             $errormessage = $Lang::tr{'invalid local-remote id'} . '<br />' .
1395             'DER_ASN1_DN: @c=FR/ou=Paris/ou=Home/cn=*<br />' .
1396             'FQDN: @ipfire.org<br />' .
1397             'USER_FQDN: info@ipfire.org<br />' .
1398             'IPV4_ADDR: 123.123.123.123';
1399             goto VPNCONF_ERROR;
1400         }
1401         # If Auth is DN, verify existance of Remote ID.
1402         if ( $cgiparams{'REMOTE_ID'} eq '' && (
1403                 $cgiparams{'AUTH'} eq 'auth-dn'||                  # while creation
1404                 $confighash{$cgiparams{'KEY'}}[2] eq '%auth-dn')){ # while editing
1405             $errormessage = $Lang::tr{'vpn missing remote id'};
1406             goto VPNCONF_ERROR;
1407         }
1408
1409         if ($cgiparams{'AUTH'} eq 'psk') {
1410             if (! length($cgiparams{'PSK'}) ) {
1411                 $errormessage = $Lang::tr{'pre-shared key is too short'};
1412                 goto VPNCONF_ERROR;
1413             }
1414             if ($cgiparams{'PSK'} =~ /'/) {
1415                 $cgiparams{'PSK'} =~ tr/'/ /;
1416                 $errormessage = $Lang::tr{'invalid characters found in pre-shared key'};
1417                 goto VPNCONF_ERROR;
1418             }
1419         } elsif ($cgiparams{'AUTH'} eq 'certreq') {
1420             if ($cgiparams{'KEY'}) {
1421                 $errormessage = $Lang::tr{'cant change certificates'};
1422                 goto VPNCONF_ERROR;
1423             }
1424             if (ref ($cgiparams{'FH'}) ne 'Fh') {
1425                 $errormessage = $Lang::tr{'there was no file upload'};
1426                 goto VPNCONF_ERROR;
1427             }
1428
1429             # Move uploaded certificate request to a temporary file
1430             (my $fh, my $filename) = tempfile( );
1431             if (copy ($cgiparams{'FH'}, $fh) != 1) {
1432                 $errormessage = $!;
1433                 goto VPNCONF_ERROR;
1434             }
1435
1436             # Sign the certificate request
1437             &General::log("ipsec", "Signing your cert $cgiparams{'NAME'}...");
1438             my  $opt  = " ca -days 999999";
1439                 $opt .= " -batch -notext";
1440                 $opt .= " -in $filename";
1441                 $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
1442
1443             if ( $errormessage = &callssl ($opt) ) {
1444                 unlink ($filename);
1445                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1446                 &cleanssldatabase();
1447                 goto VPNCONF_ERROR;
1448             } else {
1449                 unlink ($filename);
1450                 &cleanssldatabase();
1451             }
1452
1453             $cgiparams{'CERT_NAME'} = getCNfromcert ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1454             if ($cgiparams{'CERT_NAME'} eq '') {
1455                 $errormessage = $Lang::tr{'could not retrieve common name from certificate'};
1456                 goto VPNCONF_ERROR;
1457             }
1458         } elsif ($cgiparams{'AUTH'} eq 'pkcs12') {
1459                 &General::log("ipsec", "Importing from p12...");
1460
1461                 if (ref ($cgiparams{'FH'}) ne 'Fh') {
1462                     $errormessage = $Lang::tr{'there was no file upload'};
1463                     goto ROOTCERT_ERROR;
1464                 }
1465
1466                 # Move uploaded certificate request to a temporary file
1467                 (my $fh, my $filename) = tempfile( );
1468                 if (copy ($cgiparams{'FH'}, $fh) != 1) {
1469                     $errormessage = $!;
1470                     goto ROOTCERT_ERROR;
1471                 }
1472
1473                 # Extract the CA certificate from the file
1474                 &General::log("ipsec", "Extracting caroot from p12...");
1475                 if (open(STDIN, "-|")) {
1476                     my  $opt  = " pkcs12 -cacerts -nokeys";
1477                         $opt .= " -in $filename";
1478                         $opt .= " -out /tmp/newcacert";
1479                     $errormessage = &callssl ($opt);
1480                 } else {        #child
1481                     print "$cgiparams{'P12_PASS'}\n";
1482                     exit (0);
1483                 }
1484
1485                 # Extract the Host certificate from the file
1486                 if (!$errormessage) {
1487                     &General::log("ipsec", "Extracting host cert from p12...");
1488                     if (open(STDIN, "-|")) {
1489                         my  $opt  = " pkcs12 -clcerts -nokeys";
1490                         $opt .= " -in $filename";
1491                         $opt .= " -out /tmp/newhostcert";
1492                         $errormessage = &callssl ($opt);
1493                     } else {    #child
1494                         print "$cgiparams{'P12_PASS'}\n";
1495                         exit (0);
1496                     }
1497                 }
1498
1499                 if (!$errormessage) {           
1500                     &General::log("ipsec", "Moving cacert...");
1501                     #If CA have new subject, add it to our list of CA
1502                     my $casubject = &Header::cleanhtml(getsubjectfromcert ('/tmp/newcacert'));
1503                     my @names;
1504                     foreach my $x (keys %cahash) {
1505                         $casubject='' if ($cahash{$x}[1] eq $casubject);
1506                         unshift (@names,$cahash{$x}[0]);
1507                     }
1508                     if ($casubject) { # a new one!
1509                         my $temp = `/usr/bin/openssl x509 -text -in /tmp/newcacert`;
1510                         if ($temp !~ /CA:TRUE/i) {
1511                             $errormessage = $Lang::tr{'not a valid ca certificate'};
1512                         } else {
1513                             #compute a name for it
1514                             my $idx=0;
1515                             while (grep(/Imported-$idx/, @names) ) {$idx++};
1516                             $cgiparams{'CA_NAME'}="Imported-$idx";
1517                             $cgiparams{'CERT_NAME'}=&Header::cleanhtml(getCNfromcert ('/tmp/newhostcert'));
1518                             move("/tmp/newcacert", "${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem");
1519                             $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
1520                             if (!$errormessage) {
1521                                 my $key = &General::findhasharraykey (\%cahash);
1522                                 $cahash{$key}[0] = $cgiparams{'CA_NAME'};
1523                                 $cahash{$key}[1] = $casubject;
1524                                 &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
1525                                 system('/usr/local/bin/ipsecctrl', 'R');
1526                             }
1527                         }
1528                     }   
1529                 }
1530                 if (!$errormessage) {
1531                     &General::log("ipsec", "Moving host cert...");
1532                     move("/tmp/newhostcert", "${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1533                     $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
1534                 }
1535
1536                 #cleanup temp files
1537                 unlink ($filename);
1538                 unlink ('/tmp/newcacert');
1539                 unlink ('/tmp/newhostcert');
1540                 if ($errormessage) {
1541                     unlink ("${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem");
1542                     unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1543                     goto VPNCONF_ERROR;
1544                 }
1545                 &General::log("ipsec", "p12 import completed!");
1546         } elsif ($cgiparams{'AUTH'} eq 'certfile') {
1547             if ($cgiparams{'KEY'}) {
1548                 $errormessage = $Lang::tr{'cant change certificates'};
1549                 goto VPNCONF_ERROR;
1550             }
1551             if (ref ($cgiparams{'FH'}) ne 'Fh') {
1552                 $errormessage = $Lang::tr{'there was no file upload'};
1553                 goto VPNCONF_ERROR;
1554             }
1555             # Move uploaded certificate to a temporary file
1556             (my $fh, my $filename) = tempfile( );
1557             if (copy ($cgiparams{'FH'}, $fh) != 1) {
1558                 $errormessage = $!;
1559                 goto VPNCONF_ERROR;
1560             }
1561
1562             # Verify the certificate has a valid CA and move it
1563             &General::log("ipsec", "Validating imported cert against our known CA...");
1564             my $validca = 1;  #assume ok
1565             my $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/cacert.pem $filename`;
1566             if ($test !~ /: OK/) {
1567                 my $validca = 0;
1568                 foreach my $key (keys %cahash) {
1569                     $test = `/usr/bin/openssl verify -CAfile ${General::swroot}/ca/$cahash{$key}[0]cert.pem $filename`;
1570                     if ($test =~ /: OK/) {
1571                         $validca = 1;
1572                         last;
1573                     }
1574                 }
1575             }
1576             if (! $validca) {
1577                 $errormessage = $Lang::tr{'certificate does not have a valid ca associated with it'};
1578                 unlink ($filename);
1579                 goto VPNCONF_ERROR;
1580             } else {
1581                 move($filename, "${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1582                 if ($? ne 0) {
1583                     $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1584                     unlink ($filename);
1585                     goto VPNCONF_ERROR;
1586                 }
1587             }
1588
1589             $cgiparams{'CERT_NAME'} = getCNfromcert ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1590             if ($cgiparams{'CERT_NAME'} eq '') {
1591                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1592                 $errormessage = $Lang::tr{'could not retrieve common name from certificate'};
1593                 goto VPNCONF_ERROR;
1594             }
1595         } elsif ($cgiparams{'AUTH'} eq 'certgen') {
1596             if ($cgiparams{'KEY'}) {
1597                 $errormessage = $Lang::tr{'cant change certificates'};
1598                 goto VPNCONF_ERROR;
1599             }
1600             # Validate input since the form was submitted
1601             if (length($cgiparams{'CERT_NAME'}) >60) {
1602                 $errormessage = $Lang::tr{'name too long'};
1603                 goto VPNCONF_ERROR;
1604             }
1605             if ($cgiparams{'CERT_NAME'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
1606                 $errormessage = $Lang::tr{'invalid input for name'};
1607                 goto VPNCONF_ERROR;
1608             }
1609             if ($cgiparams{'CERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'CERT_EMAIL'}))) {
1610                 $errormessage = $Lang::tr{'invalid input for e-mail address'};
1611                 goto VPNCONF_ERROR;
1612             }
1613             if (length($cgiparams{'CERT_EMAIL'}) > 40) {
1614                 $errormessage = $Lang::tr{'e-mail address too long'};
1615                 goto VPNCONF_ERROR;
1616             }
1617             if ($cgiparams{'CERT_OU'} ne '' && $cgiparams{'CERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1618                 $errormessage = $Lang::tr{'invalid input for department'};
1619                 goto VPNCONF_ERROR;
1620             }
1621             if (length($cgiparams{'CERT_ORGANIZATION'}) >60) {
1622                 $errormessage = $Lang::tr{'organization too long'};
1623                 goto VPNCONF_ERROR;
1624             }
1625             if ($cgiparams{'CERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
1626                 $errormessage = $Lang::tr{'invalid input for organization'};
1627                 goto VPNCONF_ERROR;
1628             }
1629             if ($cgiparams{'CERT_CITY'} ne '' && $cgiparams{'CERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1630                 $errormessage = $Lang::tr{'invalid input for city'};
1631                 goto VPNCONF_ERROR;
1632             }
1633             if ($cgiparams{'CERT_STATE'} ne '' && $cgiparams{'CERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1634                 $errormessage = $Lang::tr{'invalid input for state or province'};
1635                 goto VPNCONF_ERROR;
1636             }
1637             if ($cgiparams{'CERT_COUNTRY'} !~ /^[A-Z]*$/) {
1638                 $errormessage = $Lang::tr{'invalid input for country'};
1639                 goto VPNCONF_ERROR;
1640             }
1641             #the exact syntax is a list comma separated of 
1642             #  email:any-validemail
1643             #   URI: a uniform resource indicator
1644             #   DNS: a DNS domain name
1645             #   RID: a registered OBJECT IDENTIFIER
1646             #   IP: an IP address
1647             # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
1648
1649             if ($cgiparams{'SUBJECTALTNAME'} ne '' && $cgiparams{'SUBJECTALTNAME'} !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/,\.\-_@]*$/) {
1650                 $errormessage = $Lang::tr{'vpn altname syntax'};
1651                 goto VPNCONF_ERROR;
1652             }
1653
1654             if (length($cgiparams{'CERT_PASS1'}) < 5) {
1655                 $errormessage = $Lang::tr{'password too short'};
1656                 goto VPNCONF_ERROR;
1657             }
1658             if ($cgiparams{'CERT_PASS1'} ne $cgiparams{'CERT_PASS2'}) {
1659                 $errormessage = $Lang::tr{'passwords do not match'};
1660                 goto VPNCONF_ERROR;
1661             }
1662
1663             # Replace empty strings with a .
1664             (my $ou = $cgiparams{'CERT_OU'}) =~ s/^\s*$/\./;
1665             (my $city = $cgiparams{'CERT_CITY'}) =~ s/^\s*$/\./;
1666             (my $state = $cgiparams{'CERT_STATE'}) =~ s/^\s*$/\./;
1667
1668             # Create the Host certificate request
1669             &General::log("ipsec", "Creating a cert...");
1670
1671             if (open(STDIN, "-|")) {
1672                 my $opt  = " req -nodes -rand /proc/interrupts:/proc/net/rt_cache";
1673                    $opt .= " -newkey rsa:1024";
1674                    $opt .= " -keyout ${General::swroot}/certs/$cgiparams{'NAME'}key.pem";
1675                    $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}req.pem";
1676
1677                 if ( $errormessage = &callssl ($opt) ) {
1678                     unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
1679                     unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
1680                     goto VPNCONF_ERROR;
1681                 }
1682             } else {    #child
1683                 print  "$cgiparams{'CERT_COUNTRY'}\n";
1684                 print  "$state\n";
1685                 print  "$city\n";
1686                 print  "$cgiparams{'CERT_ORGANIZATION'}\n";
1687                 print  "$ou\n";
1688                 print  "$cgiparams{'CERT_NAME'}\n";
1689                 print  "$cgiparams{'CERT_EMAIL'}\n";
1690                 print  ".\n";
1691                 print  ".\n";
1692                 exit (0);
1693             }
1694             
1695             # Sign the host certificate request
1696             &General::log("ipsec", "Signing the cert $cgiparams{'NAME'}...");
1697
1698             #No easy way for specifying the contain of subjectAltName without writing a config file...
1699             my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
1700             print $fh <<END
1701             basicConstraints=CA:FALSE
1702             nsComment="OpenSSL Generated Certificate"
1703             subjectKeyIdentifier=hash
1704             authorityKeyIdentifier=keyid,issuer:always
1705 END
1706 ;
1707             print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
1708             close ($fh);
1709
1710             my $opt  = " ca -days 999999 -batch -notext";
1711                $opt .= " -in ${General::swroot}/certs/$cgiparams{'NAME'}req.pem";
1712                $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
1713                $opt .= " -extfile $v3extname";
1714
1715             if ( $errormessage = &callssl ($opt) ) {
1716                 unlink ($v3extname);
1717                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
1718                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
1719                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1720                 &cleanssldatabase();
1721                 goto VPNCONF_ERROR;
1722             } else {
1723                 unlink ($v3extname);
1724                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
1725                 &cleanssldatabase();
1726             }
1727
1728             # Create the pkcs12 file
1729             &General::log("ipsec", "Packing a pkcs12 file...");
1730                $opt  = " pkcs12 -export"; 
1731                $opt .= " -inkey ${General::swroot}/certs/$cgiparams{'NAME'}key.pem";
1732                $opt .= " -in ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
1733                $opt .= " -name \"$cgiparams{'NAME'}\"";
1734                $opt .= " -passout pass:$cgiparams{'CERT_PASS1'}";
1735                $opt .= " -certfile ${General::swroot}/ca/cacert.pem";
1736                $opt .= " -caname \"$vpnsettings{'ROOTCERT_ORGANIZATION'} CA\"";
1737                $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}.p12";
1738
1739             if ( $errormessage = &callssl ($opt) ) {
1740                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
1741                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1742                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}.p12");
1743                 goto VPNCONF_ERROR;
1744             } else {
1745                 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
1746             }
1747         } elsif ($cgiparams{'AUTH'} eq 'cert') {
1748             ;# Nothing, just editing
1749         } elsif ($cgiparams{'AUTH'} eq 'auth-dn') {
1750             $cgiparams{'CERT_NAME'} = '%auth-dn';       # a special value saying 'no cert file'     
1751         } else {
1752             $errormessage = $Lang::tr{'invalid input for authentication method'};
1753             goto VPNCONF_ERROR;
1754         }
1755
1756         # 1)Error message here is not accurate.
1757         # 2)Test is superfluous, openswan can reference same cert multiple times
1758         # 3)Present since initial version (1.3.2.11), it isn't a bug correction
1759         # Check if there is no other entry with this certificate name
1760         #if ((! $cgiparams{'KEY'}) && ($cgiparams{'AUTH'} ne 'psk') && ($cgiparams{'AUTH'} ne 'auth-dn')) {
1761         #    foreach my $key (keys %confighash) {
1762         #       if ($confighash{$key}[2] eq $cgiparams{'CERT_NAME'}) {
1763         #           $errormessage = $Lang::tr{'a connection with this common name already exists'};
1764         #           goto VPNCONF_ERROR;
1765         #       }
1766         #    }
1767         #}
1768         # Save the config
1769
1770         my $key = $cgiparams{'KEY'};
1771         if (! $key) {
1772             $key = &General::findhasharraykey (\%confighash);
1773             foreach my $i (0 .. 28) { $confighash{$key}[$i] = "";}
1774         }
1775         $confighash{$key}[0] = $cgiparams{'ENABLED'};
1776         $confighash{$key}[1] = $cgiparams{'NAME'};
1777         if ((! $cgiparams{'KEY'}) && $cgiparams{'AUTH'} ne 'psk') {
1778             $confighash{$key}[2] = $cgiparams{'CERT_NAME'};
1779         }
1780         $confighash{$key}[3] = $cgiparams{'TYPE'};
1781         if ($cgiparams{'AUTH'} eq 'psk') {
1782             $confighash{$key}[4] = 'psk';
1783             $confighash{$key}[5] = $cgiparams{'PSK'};
1784         } else {
1785             $confighash{$key}[4] = 'cert';
1786         }
1787         if ($cgiparams{'TYPE'} eq 'net') {
1788             $confighash{$key}[11] = $cgiparams{'REMOTE_SUBNET'};
1789         }
1790         $confighash{$key}[7] = $cgiparams{'LOCAL_ID'};
1791         $confighash{$key}[8] = $cgiparams{'LOCAL_SUBNET'};
1792         $confighash{$key}[9] = $cgiparams{'REMOTE_ID'};
1793         $confighash{$key}[10] = $cgiparams{'REMOTE'};
1794         $confighash{$key}[25] = $cgiparams{'REMARK'};
1795         $confighash{$key}[26] = $cgiparams{'INTERFACE'};
1796         $confighash{$key}[27] = $cgiparams{'DPD_ACTION'};
1797         $confighash{$key}[29] = $cgiparams{'IKE_VERSION'};
1798
1799         #dont forget advanced value
1800         $confighash{$key}[18] = $cgiparams{'IKE_ENCRYPTION'};
1801         $confighash{$key}[19] = $cgiparams{'IKE_INTEGRITY'};
1802         $confighash{$key}[20] = $cgiparams{'IKE_GROUPTYPE'};
1803         $confighash{$key}[16] = $cgiparams{'IKE_LIFETIME'};
1804         $confighash{$key}[21] = $cgiparams{'ESP_ENCRYPTION'};
1805         $confighash{$key}[22] = $cgiparams{'ESP_INTEGRITY'};
1806         $confighash{$key}[23] = $cgiparams{'ESP_GROUPTYPE'};
1807         $confighash{$key}[17] = $cgiparams{'ESP_KEYLIFE'};
1808         $confighash{$key}[12] = 'off'; # $cgiparams{'AGGRMODE'};
1809         $confighash{$key}[13] = $cgiparams{'COMPRESSION'};
1810         $confighash{$key}[24] = $cgiparams{'ONLY_PROPOSED'};
1811         $confighash{$key}[28] = $cgiparams{'PFS'};
1812         $confighash{$key}[14] = $cgiparams{'VHOST'};
1813
1814         #free unused fields!
1815         $confighash{$key}[6] = 'off';
1816         $confighash{$key}[15] = 'off';
1817
1818         &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1819         &writeipsecfiles();
1820         if (&vpnenabled) {
1821             system('/usr/local/bin/ipsecctrl', 'S', $key);
1822             sleep $sleepDelay;
1823         }
1824         if ($cgiparams{'EDIT_ADVANCED'} eq 'on') {
1825             $cgiparams{'KEY'} = $key;
1826             $cgiparams{'ACTION'} = $Lang::tr{'advanced'};
1827         }
1828         goto VPNCONF_END;
1829     } else { # add new connection
1830         $cgiparams{'ENABLED'} = 'on';
1831         if ( ! -f "${General::swroot}/private/cakey.pem" ) {
1832             $cgiparams{'AUTH'} = 'psk';
1833         } elsif ( ! -f "${General::swroot}/ca/cacert.pem") {
1834             $cgiparams{'AUTH'} = 'certfile';
1835         } else {
1836             $cgiparams{'AUTH'} = 'certgen';
1837         }
1838         $cgiparams{'LOCAL_SUBNET'}      ="$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}";
1839         $cgiparams{'CERT_EMAIL'}        = $vpnsettings{'ROOTCERT_EMAIL'};
1840         $cgiparams{'CERT_OU'}           = $vpnsettings{'ROOTCERT_OU'};
1841         $cgiparams{'CERT_ORGANIZATION'} = $vpnsettings{'ROOTCERT_ORGANIZATION'};
1842         $cgiparams{'CERT_CITY'}         = $vpnsettings{'ROOTCERT_CITY'};
1843         $cgiparams{'CERT_STATE'}        = $vpnsettings{'ROOTCERT_STATE'};
1844         $cgiparams{'CERT_COUNTRY'}      = $vpnsettings{'ROOTCERT_COUNTRY'};
1845
1846         # choose appropriate dpd action 
1847         if ($cgiparams{'TYPE'} eq 'host') {
1848             $cgiparams{'DPD_ACTION'} = 'clear';
1849         } else {
1850             $cgiparams{'DPD_ACTION'} = 'restart';
1851         }
1852
1853         # Default IKE Version to V1
1854         if (! $cgiparams{'IKE_VERSION'}) {
1855             $cgiparams{'IKE_VERSION'} = 'ikev1';
1856         }
1857
1858         # Default is yes for 'pfs'
1859         $cgiparams{'PFS'}     = 'on';
1860         
1861         # ID are empty
1862         $cgiparams{'LOCAL_ID'}  = '';
1863         $cgiparams{'REMOTE_ID'} = '';
1864
1865         #use default advanced value
1866         $cgiparams{'IKE_ENCRYPTION'} = 'aes128|3des';   #[18];
1867         $cgiparams{'IKE_INTEGRITY'}  = 'sha|md5';       #[19];
1868         $cgiparams{'IKE_GROUPTYPE'}  = '1536|1024';     #[20];
1869         $cgiparams{'IKE_LIFETIME'}   = '1';             #[16];
1870         $cgiparams{'ESP_ENCRYPTION'} = 'aes128|3des';   #[21];
1871         $cgiparams{'ESP_INTEGRITY'}  = 'sha1|md5';      #[22];
1872         $cgiparams{'ESP_GROUPTYPE'}  = '';              #[23];
1873         $cgiparams{'ESP_KEYLIFE'}    = '8';             #[17];
1874         $cgiparams{'COMPRESSION'}    = 'off';           #[13];
1875         $cgiparams{'ONLY_PROPOSED'}  = 'off';           #[24];
1876         $cgiparams{'PFS'}            = 'on';            #[28];
1877         $cgiparams{'VHOST'}          = 'on';            #[14];
1878     }
1879
1880     VPNCONF_ERROR:
1881     $checked{'ENABLED'}{'off'} = '';
1882     $checked{'ENABLED'}{'on'} = '';
1883     $checked{'ENABLED'}{$cgiparams{'ENABLED'}} = "checked='checked'";
1884
1885     $checked{'EDIT_ADVANCED'}{'off'} = '';
1886     $checked{'EDIT_ADVANCED'}{'on'} = '';
1887     $checked{'EDIT_ADVANCED'}{$cgiparams{'EDIT_ADVANCED'}} = "checked='checked'";
1888
1889     $checked{'AUTH'}{'psk'} = '';
1890     $checked{'AUTH'}{'certreq'} = '';
1891     $checked{'AUTH'}{'certgen'} = '';
1892     $checked{'AUTH'}{'certfile'} = '';
1893     $checked{'AUTH'}{'pkcs12'} = '';
1894     $checked{'AUTH'}{'auth-dn'} = '';
1895     $checked{'AUTH'}{$cgiparams{'AUTH'}} = "checked='checked'";
1896
1897     $selected{'INTERFACE'}{'RED'} = '';
1898     $selected{'INTERFACE'}{'ORANGE'} = '';
1899     $selected{'INTERFACE'}{'GREEN'} = '';
1900     $selected{'INTERFACE'}{'BLUE'} = '';
1901     $selected{'INTERFACE'}{$cgiparams{'INTERFACE'}} = "selected='selected'";
1902
1903     $selected{'DPD_ACTION'}{'clear'} = '';
1904     $selected{'DPD_ACTION'}{'hold'} = '';
1905     $selected{'DPD_ACTION'}{'restart'} = '';
1906     $selected{'DPD_ACTION'}{$cgiparams{'DPD_ACTION'}} = "selected='selected'";
1907
1908     $selected{'IKE_VERSION'}{'ikev1'} = '';
1909     $selected{'IKE_VERSION'}{'ikev2'} = '';
1910     $selected{'IKE_VERSION'}{$cgiparams{'IKE_VERSION'}} = "selected='selected'";
1911
1912     &Header::showhttpheaders();
1913     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
1914     &Header::openbigbox('100%', 'left', '', $errormessage);
1915     if ($errormessage) {
1916         &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
1917         print "<class name='base'>$errormessage";
1918         print "&nbsp;</class>";
1919         &Header::closebox();
1920     }
1921
1922     if ($warnmessage) {
1923         &Header::openbox('100%', 'left', "$Lang::tr{'warning messages'}:");
1924         print "<class name='base'>$warnmessage";
1925         print "&nbsp;</class>";
1926         &Header::closebox();
1927     }
1928
1929     print "<form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>";
1930     print<<END
1931         <input type='hidden' name='TYPE' value='$cgiparams{'TYPE'}' />
1932         <input type='hidden' name='IKE_ENCRYPTION' value='$cgiparams{'IKE_ENCRYPTION'}' />
1933         <input type='hidden' name='IKE_INTEGRITY' value='$cgiparams{'IKE_INTEGRITY'}' />
1934         <input type='hidden' name='IKE_GROUPTYPE' value='$cgiparams{'IKE_GROUPTYPE'}' />
1935         <input type='hidden' name='IKE_LIFETIME' value='$cgiparams{'IKE_LIFETIME'}' />
1936         <input type='hidden' name='ESP_ENCRYPTION' value='$cgiparams{'ESP_ENCRYPTION'}' />
1937         <input type='hidden' name='ESP_INTEGRITY' value='$cgiparams{'ESP_INTEGRITY'}' />
1938         <input type='hidden' name='ESP_GROUPTYPE' value='$cgiparams{'ESP_GROUPTYPE'}' />
1939         <input type='hidden' name='ESP_KEYLIFE' value='$cgiparams{'ESP_KEYLIFE'}' />
1940         <input type='hidden' name='COMPRESSION' value='$cgiparams{'COMPRESSION'}' />
1941         <input type='hidden' name='ONLY_PROPOSED' value='$cgiparams{'ONLY_PROPOSED'}' />
1942         <input type='hidden' name='PFS' value='$cgiparams{'PFS'}' />
1943         <input type='hidden' name='VHOST' value='$cgiparams{'VHOST'}' />
1944 END
1945     ;
1946     if ($cgiparams{'KEY'}) {
1947         print "<input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />";
1948         print "<input type='hidden' name='AUTH' value='$cgiparams{'AUTH'}' />";
1949     }
1950
1951     &Header::openbox('100%', 'left', "$Lang::tr{'connection'}:");
1952     print "<table width='100%'>";
1953     print "<tr><td width='25%' class='boldbase'>$Lang::tr{'name'}:</td>";
1954     if ($cgiparams{'KEY'}) {
1955         print "<td width='25%' class='base'><input type='hidden' name='NAME' value='$cgiparams{'NAME'}' /><b>$cgiparams{'NAME'}</b></td>";
1956     } else {
1957         print "<td width='25%'><input type='text' name='NAME' value='$cgiparams{'NAME'}' size='30' /></td>";
1958     }
1959     print "<td>$Lang::tr{'enabled'}</td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td></tr>";
1960     print '</tr><td><br /></td><tr>';
1961
1962     my $disabled;
1963     my $blob;
1964     if ($cgiparams{'TYPE'} eq 'host') {
1965         $disabled = "disabled='disabled'";
1966         $blob = "<img src='/blob.gif' alt='*' />";
1967     };
1968
1969     print "<tr><td>$Lang::tr{'host ip'}:</td>";
1970     print "<td><select name='INTERFACE'>";
1971     print "<option value='RED' $selected{'INTERFACE'}{'RED'}>RED ($vpnsettings{'VPN_IP'})</option>";
1972     print "<option value='GREEN' $selected{'INTERFACE'}{'GREEN'}>GREEN ($netsettings{'GREEN_ADDRESS'})</option>";
1973     print "<option value='BLUE' $selected{'INTERFACE'}{'BLUE'}>BLUE ($netsettings{'BLUE_ADDRESS'})</option>" if ($netsettings{'BLUE_DEV'} ne '');
1974     print "<option value='ORANGE' $selected{'INTERFACE'}{'ORANGE'}>ORANGE ($netsettings{'ORANGE_ADDRESS'})</option>" if ($netsettings{'ORANGE_DEV'} ne '');
1975     print "</select></td>";
1976     print <<END
1977             <td class='boldbase'>$Lang::tr{'remote host/ip'}:&nbsp;$blob</td>
1978             <td><input type='text' name='REMOTE' value='$cgiparams{'REMOTE'}' size='30' /></td>
1979         </tr><tr>
1980             <td class='boldbase' nowrap='nowrap'>$Lang::tr{'local subnet'}</td>
1981             <td><input type='text' name='LOCAL_SUBNET' value='$cgiparams{'LOCAL_SUBNET'}' size='30' /></td>
1982             <td class='boldbase' nowrap='nowrap'>$Lang::tr{'remote subnet'}</td>
1983             <td><input $disabled type='text' name='REMOTE_SUBNET' value='$cgiparams{'REMOTE_SUBNET'}' size='30' /></td>
1984         </tr><tr>
1985             <td class='boldbase'>$Lang::tr{'vpn local id'}:<br />($Lang::tr{'eg'} <tt>&#64;xy.example.com</tt>)</td>
1986             <td><input type='text' name='LOCAL_ID' value='$cgiparams{'LOCAL_ID'}' /></td>
1987             <td class='boldbase'>$Lang::tr{'vpn remote id'}:</td>
1988             <td><input type='text' name='REMOTE_ID' value='$cgiparams{'REMOTE_ID'}' /></td>
1989         </tr><tr>
1990         </tr><td><br /></td><tr>
1991             <td>$Lang::tr{'vpn keyexchange'}:</td>
1992             <td><select name='IKE_VERSION'>
1993                 <option value='ikev1' $selected{'IKE_VERSION'}{'ikev1'}>IKEv1</option>
1994                 <option value='ikev2' $selected{'IKE_VERSION'}{'ikev2'}>IKEv2</option>
1995                 </select></a>
1996             </td>
1997             <td>$Lang::tr{'dpd action'}:</td>
1998             <td><select name='DPD_ACTION'>
1999                 <option value='clear' $selected{'DPD_ACTION'}{'clear'}>clear</option>
2000                 <option value='hold' $selected{'DPD_ACTION'}{'hold'}>hold</option>
2001                 <option value='restart' $selected{'DPD_ACTION'}{'restart'}>restart</option>
2002                 </select>&nbsp; <a href='http://www.openswan.com/docs/local/README.DPD'>?</a>
2003             </td>
2004         </tr><tr>
2005 <!--http://www.openswan.com/docs/local/README.DPD
2006     http://bugs.xelerance.com/view.php?id=156
2007     restart = clear + reinitiate connection
2008 -->
2009             <td class='boldbase'>$Lang::tr{'remark title'}&nbsp;<img src='/blob.gif' alt='*' /></td>
2010             <td colspan='3'><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td>
2011         </tr>
2012 END
2013     ;
2014     if (!$cgiparams{'KEY'}) {
2015         print "<tr><td colspan='3'><input type='checkbox' name='EDIT_ADVANCED' $checked{'EDIT_ADVANCED'}{'on'} /> $Lang::tr{'edit advanced settings when done'}</td></tr>";
2016     }
2017     print "</table>";
2018     &Header::closebox();
2019         
2020     if ($cgiparams{'KEY'} && $cgiparams{'AUTH'} eq 'psk') {
2021         &Header::openbox('100%', 'left', $Lang::tr{'authentication'});
2022         print <<END
2023         <table width='100%' cellpadding='0' cellspacing='5' border='0'>
2024         <tr><td class='base' width='50%'>$Lang::tr{'use a pre-shared key'}</td>
2025             <td class='base' width='50%'><input type='password' name='PSK' size='30' value='$cgiparams{'PSK'}' /></td>
2026         </tr>
2027         </table>
2028 END
2029         ;
2030         &Header::closebox();
2031     } elsif (! $cgiparams{'KEY'}) {
2032         my $pskdisabled = ($vpnsettings{'VPN_IP'} eq '%defaultroute') ? "disabled='disabled'" : '' ;
2033         $cgiparams{'PSK'} =  $Lang::tr{'vpn incompatible use of defaultroute'} if ($pskdisabled);
2034         my $cakeydisabled = ( ! -f "${General::swroot}/private/cakey.pem" ) ? "disabled='disabled'" : '';
2035         $cgiparams{'CERT_NAME'} = $Lang::tr{'vpn no full pki'} if ($cakeydisabled);
2036         my $cacrtdisabled = ( ! -f "${General::swroot}/ca/cacert.pem" ) ? "disabled='disabled'" : '';
2037
2038         &Header::openbox('100%', 'left', $Lang::tr{'authentication'});
2039         print <<END
2040         <table width='100%' cellpadding='0' cellspacing='5' border='0'>
2041         <tr><td width='5%'><input type='radio' name='AUTH' value='psk' $checked{'AUTH'}{'psk'} $pskdisabled/></td>
2042             <td class='base' width='55%'>$Lang::tr{'use a pre-shared key'}</td>
2043             <td class='base' width='40%'><input type='password' name='PSK' size='30' value='$cgiparams{'PSK'}' $pskdisabled/></td></tr>
2044         <tr><td colspan='3' bgcolor='#000000'></td></tr>
2045         <tr><td><input type='radio' name='AUTH' value='certreq' $checked{'AUTH'}{'certreq'} $cakeydisabled /></td>
2046             <td class='base'><hr />$Lang::tr{'upload a certificate request'}</td>
2047             <td class='base' rowspan='3' valign='middle'><input type='file' name='FH' size='30' $cacrtdisabled /></td></tr>
2048         <tr><td><input type='radio' name='AUTH' value='certfile' $checked{'AUTH'}{'certfile'} $cacrtdisabled /></td>
2049             <td class='base'>$Lang::tr{'upload a certificate'}</td></tr>
2050         <tr><td><input type='radio' name='AUTH' value='pkcs12' $cacrtdisabled /></td>
2051             <td class='base'>$Lang::tr{'upload p12 file'} $Lang::tr{'pkcs12 file password'}:<input type='password' name='P12_PASS'/></td></tr>
2052         <tr><td><input type='radio' name='AUTH' value='auth-dn' $checked{'AUTH'}{'auth-dn'} $cacrtdisabled /></td>
2053             <td class='base'><hr />$Lang::tr{'vpn auth-dn'}</td></tr>
2054         <tr><td colspan='3' bgcolor='#000000'></td></tr>
2055         <tr><td><input type='radio' name='AUTH' value='certgen' $checked{'AUTH'}{'certgen'} $cakeydisabled /></td>
2056             <td class='base'><hr />$Lang::tr{'generate a certificate'}</td><td>&nbsp;</td></tr>
2057         <tr><td>&nbsp;</td>
2058             <td class='base'>$Lang::tr{'users fullname or system hostname'}:</td>
2059             <td class='base' nowrap='nowrap'><input type='text' name='CERT_NAME' value='$cgiparams{'CERT_NAME'}' size='32' $cakeydisabled /></td></tr>
2060         <tr><td>&nbsp;</td>
2061             <td class='base'>$Lang::tr{'users email'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2062             <td class='base' nowrap='nowrap'><input type='text' name='CERT_EMAIL' value='$cgiparams{'CERT_EMAIL'}' size='32' $cakeydisabled /></td></tr>
2063         <tr><td>&nbsp;</td>
2064             <td class='base'>$Lang::tr{'users department'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2065             <td class='base' nowrap='nowrap'><input type='text' name='CERT_OU' value='$cgiparams{'CERT_OU'}' size='32' $cakeydisabled /></td></tr>
2066         <tr><td>&nbsp;</td>
2067             <td class='base'>$Lang::tr{'organization name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2068             <td class='base' nowrap='nowrap'><input type='text' name='CERT_ORGANIZATION' value='$cgiparams{'CERT_ORGANIZATION'}' size='32' $cakeydisabled /></td></tr>
2069         <tr><td>&nbsp;</td>
2070             <td class='base'>$Lang::tr{'city'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2071             <td class='base' nowrap='nowrap'><input type='text' name='CERT_CITY' value='$cgiparams{'CERT_CITY'}' size='32' $cakeydisabled /></td></tr>
2072         <tr><td>&nbsp;</td>
2073             <td class='base'>$Lang::tr{'state or province'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2074             <td class='base' nowrap='nowrap'><input type='text' name='CERT_STATE' value='$cgiparams{'CERT_STATE'}' size='32' $cakeydisabled /></td></tr>
2075         <tr><td>&nbsp;</td>
2076             <td class='base'>$Lang::tr{'country'}:</td>
2077             <td class='base'><select name='CERT_COUNTRY' $cakeydisabled>
2078 END
2079         ;
2080         foreach my $country (sort keys %{Countries::countries}) {
2081             print "\t\t\t<option value='$Countries::countries{$country}'";
2082             if ( $Countries::countries{$country} eq $cgiparams{'CERT_COUNTRY'} ) {
2083                 print " selected='selected'";
2084             }
2085             print ">$country</option>\n";
2086         }
2087         print <<END
2088             </select></td></tr>
2089
2090         <tr><td>&nbsp;</td><td class='base'>$Lang::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*)<img src='/blob.gif' alt='*' /></td>
2091             <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value='$cgiparams{'SUBJECTALTNAME'}' size='32' $cakeydisabled /></td></tr>
2092         <tr><td>&nbsp;</td>
2093             <td class='base'>$Lang::tr{'pkcs12 file password'}:</td>
2094             <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS1' value='$cgiparams{'CERT_PASS1'}' size='32' $cakeydisabled /></td></tr>
2095         <tr><td>&nbsp;</td><td class='base'>$Lang::tr{'pkcs12 file password'}:($Lang::tr{'confirmation'})</td>
2096             <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS2' value='$cgiparams{'CERT_PASS2'}' size='32' $cakeydisabled /></td></tr>
2097         </table>
2098 END
2099         ;
2100         &Header::closebox();
2101     }
2102
2103     print "<div align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' />";
2104     if ($cgiparams{'KEY'}) {
2105         print "<input type='submit' name='ACTION' value='$Lang::tr{'advanced'}' />";
2106     }
2107     print "<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></div></form>";
2108     &Header::closebigbox();
2109     &Header::closepage();
2110     exit (0);
2111     
2112     VPNCONF_END:
2113 }
2114
2115 ###
2116 ### Advanced settings
2117 ###
2118 if(($cgiparams{'ACTION'} eq $Lang::tr{'advanced'}) ||
2119         ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'ADVANCED'} eq 'yes')) {
2120     &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
2121     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
2122     if (! $confighash{$cgiparams{'KEY'}}) {
2123         $errormessage = $Lang::tr{'invalid key'};
2124         goto ADVANCED_END;
2125     }
2126
2127     if ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
2128         # I didn't read any incompatibilities here....
2129         #if ($cgiparams{'VHOST'} eq 'on' && $cgiparams{'COMPRESSION'} eq 'on') {
2130         #    $errormessage = $Lang::tr{'cannot enable both nat traversal and compression'};
2131         #    goto ADVANCED_ERROR;
2132         #}
2133         my @temp = split('\|', $cgiparams{'IKE_ENCRYPTION'});
2134         if ($#temp < 0) {
2135             $errormessage = $Lang::tr{'invalid input'};
2136             goto ADVANCED_ERROR;
2137         }
2138         foreach my $val (@temp) {
2139             if ($val !~ /^(aes256|aes128|3des)$/) {
2140                 $errormessage = $Lang::tr{'invalid input'};
2141                 goto ADVANCED_ERROR;
2142             }
2143         }
2144         @temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
2145         if ($#temp < 0) {
2146             $errormessage = $Lang::tr{'invalid input'};
2147             goto ADVANCED_ERROR;
2148         }
2149         foreach my $val (@temp) {
2150             if ($val !~ /^(sha2_512|sha2_256|sha|md5)$/) {
2151                 $errormessage = $Lang::tr{'invalid input'};
2152                 goto ADVANCED_ERROR;
2153             }
2154         }
2155         @temp = split('\|', $cgiparams{'IKE_GROUPTYPE'});
2156         if ($#temp < 0) {
2157             $errormessage = $Lang::tr{'invalid input'};
2158             goto ADVANCED_ERROR;
2159         }
2160         foreach my $val (@temp) {
2161             if ($val !~ /^(1024|1536|2048|3072|4096|6144|8192)$/) {
2162                 $errormessage = $Lang::tr{'invalid input'};
2163                 goto ADVANCED_ERROR;
2164             }
2165         }
2166         if ($cgiparams{'IKE_LIFETIME'} !~ /^\d+$/) {
2167             $errormessage = $Lang::tr{'invalid input for ike lifetime'};
2168             goto ADVANCED_ERROR;
2169         }
2170         if ($cgiparams{'IKE_LIFETIME'} < 1 || $cgiparams{'IKE_LIFETIME'} > 8) {
2171             $errormessage = $Lang::tr{'ike lifetime should be between 1 and 8 hours'};
2172             goto ADVANCED_ERROR;
2173         }
2174         @temp = split('\|', $cgiparams{'ESP_ENCRYPTION'});
2175         if ($#temp < 0) {
2176             $errormessage = $Lang::tr{'invalid input'};
2177             goto ADVANCED_ERROR;
2178         }
2179         foreach my $val (@temp) {
2180             if ($val !~ /^(aes256|aes128|3des)$/) {
2181                 $errormessage = $Lang::tr{'invalid input'};
2182                 goto ADVANCED_ERROR;
2183             }
2184         }
2185         @temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
2186         if ($#temp < 0) {
2187             $errormessage = $Lang::tr{'invalid input'};
2188             goto ADVANCED_ERROR;
2189         }
2190         foreach my $val (@temp) {
2191             if ($val !~ /^(sha2_512|sha2_256|sha1|md5)$/) {
2192                 $errormessage = $Lang::tr{'invalid input'};
2193                 goto ADVANCED_ERROR;
2194             }
2195         }
2196         if ($cgiparams{'ESP_GROUPTYPE'} ne '' &&
2197             $cgiparams{'ESP_GROUPTYPE'} !~  /^modp(1024|1536|2048|3072|4096)$/) {
2198             $errormessage = $Lang::tr{'invalid input'};
2199             goto ADVANCED_ERROR;
2200         }
2201
2202         if ($cgiparams{'ESP_KEYLIFE'} !~ /^\d+$/) {
2203             $errormessage = $Lang::tr{'invalid input for esp keylife'};
2204             goto ADVANCED_ERROR;
2205         }
2206         if ($cgiparams{'ESP_KEYLIFE'} < 1 || $cgiparams{'ESP_KEYLIFE'} > 24) {
2207             $errormessage = $Lang::tr{'esp keylife should be between 1 and 24 hours'};
2208             goto ADVANCED_ERROR;
2209         }
2210
2211         if (
2212             ($cgiparams{'COMPRESSION'} !~ /^(|on|off)$/) ||
2213             ($cgiparams{'ONLY_PROPOSED'} !~ /^(|on|off)$/) ||
2214             ($cgiparams{'PFS'} !~ /^(|on|off)$/) ||
2215             ($cgiparams{'VHOST'} !~ /^(|on|off)$/)
2216         ){
2217             $errormessage = $Lang::tr{'invalid input'};
2218             goto ADVANCED_ERROR;
2219         }
2220
2221         $confighash{$cgiparams{'KEY'}}[18] = $cgiparams{'IKE_ENCRYPTION'};
2222         $confighash{$cgiparams{'KEY'}}[19] = $cgiparams{'IKE_INTEGRITY'};
2223         $confighash{$cgiparams{'KEY'}}[20] = $cgiparams{'IKE_GROUPTYPE'};
2224         $confighash{$cgiparams{'KEY'}}[16] = $cgiparams{'IKE_LIFETIME'};
2225         $confighash{$cgiparams{'KEY'}}[21] = $cgiparams{'ESP_ENCRYPTION'};
2226         $confighash{$cgiparams{'KEY'}}[22] = $cgiparams{'ESP_INTEGRITY'};
2227         $confighash{$cgiparams{'KEY'}}[23] = $cgiparams{'ESP_GROUPTYPE'};
2228         $confighash{$cgiparams{'KEY'}}[17] = $cgiparams{'ESP_KEYLIFE'};
2229         $confighash{$cgiparams{'KEY'}}[12] = 'off'; #$cgiparams{'AGGRMODE'};
2230         $confighash{$cgiparams{'KEY'}}[13] = $cgiparams{'COMPRESSION'};
2231         $confighash{$cgiparams{'KEY'}}[24] = $cgiparams{'ONLY_PROPOSED'};
2232         $confighash{$cgiparams{'KEY'}}[28] = $cgiparams{'PFS'};
2233         $confighash{$cgiparams{'KEY'}}[14] = $cgiparams{'VHOST'};
2234         &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
2235         &writeipsecfiles();
2236         if (&vpnenabled) {
2237             system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
2238             sleep $sleepDelay;
2239         }
2240         goto ADVANCED_END;
2241     } else {
2242         $cgiparams{'IKE_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[18];
2243         $cgiparams{'IKE_INTEGRITY'}  = $confighash{$cgiparams{'KEY'}}[19];
2244         $cgiparams{'IKE_GROUPTYPE'}  = $confighash{$cgiparams{'KEY'}}[20];
2245         $cgiparams{'IKE_LIFETIME'}   = $confighash{$cgiparams{'KEY'}}[16];
2246         $cgiparams{'ESP_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[21];
2247         $cgiparams{'ESP_INTEGRITY'}  = $confighash{$cgiparams{'KEY'}}[22];
2248         $cgiparams{'ESP_GROUPTYPE'}  = $confighash{$cgiparams{'KEY'}}[23];
2249         $cgiparams{'ESP_KEYLIFE'}    = $confighash{$cgiparams{'KEY'}}[17];
2250         $cgiparams{'COMPRESSION'}    = $confighash{$cgiparams{'KEY'}}[13];
2251         $cgiparams{'ONLY_PROPOSED'}  = $confighash{$cgiparams{'KEY'}}[24];
2252         $cgiparams{'PFS'}            = $confighash{$cgiparams{'KEY'}}[28];
2253         $cgiparams{'VHOST'}          = $confighash{$cgiparams{'KEY'}}[14];
2254
2255         if ($confighash{$cgiparams{'KEY'}}[3] eq 'net' || $confighash{$cgiparams{'KEY'}}[10]) {
2256             $cgiparams{'VHOST'}            = 'off';
2257         }
2258     }
2259
2260     ADVANCED_ERROR:
2261     $checked{'IKE_ENCRYPTION'}{'aes256'} = '';
2262     $checked{'IKE_ENCRYPTION'}{'aes128'} = '';
2263     $checked{'IKE_ENCRYPTION'}{'3des'} = '';
2264     my @temp = split('\|', $cgiparams{'IKE_ENCRYPTION'});
2265     foreach my $key (@temp) {$checked{'IKE_ENCRYPTION'}{$key} = "selected='selected'"; }
2266     $checked{'IKE_INTEGRITY'}{'sha2_512'} = '';
2267     $checked{'IKE_INTEGRITY'}{'sha2_256'} = '';
2268     $checked{'IKE_INTEGRITY'}{'sha'} = '';
2269     $checked{'IKE_INTEGRITY'}{'md5'} = '';
2270     @temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
2271     foreach my $key (@temp) {$checked{'IKE_INTEGRITY'}{$key} = "selected='selected'"; }
2272     $checked{'IKE_GROUPTYPE'}{'768'} = '';
2273     $checked{'IKE_GROUPTYPE'}{'1024'} = '';
2274     $checked{'IKE_GROUPTYPE'}{'1536'} = '';
2275     $checked{'IKE_GROUPTYPE'}{'2048'} = '';
2276     $checked{'IKE_GROUPTYPE'}{'3072'} = '';
2277     $checked{'IKE_GROUPTYPE'}{'4096'} = '';
2278     $checked{'IKE_GROUPTYPE'}{'6144'} = '';
2279     $checked{'IKE_GROUPTYPE'}{'8192'} = '';
2280     @temp = split('\|', $cgiparams{'IKE_GROUPTYPE'});
2281     foreach my $key (@temp) {$checked{'IKE_GROUPTYPE'}{$key} = "selected='selected'"; }
2282
2283     # 768 is not supported by strongswan
2284     $checked{'IKE_GROUPTYPE'}{'768'} = '';
2285
2286
2287     $checked{'ESP_ENCRYPTION'}{'aes256'} = '';
2288     $checked{'ESP_ENCRYPTION'}{'aes128'} = '';
2289     $checked{'ESP_ENCRYPTION'}{'3des'} = '';
2290     @temp = split('\|', $cgiparams{'ESP_ENCRYPTION'});
2291     foreach my $key (@temp) {$checked{'ESP_ENCRYPTION'}{$key} = "selected='selected'"; }
2292     $checked{'ESP_INTEGRITY'}{'sha2_512'} = '';
2293     $checked{'ESP_INTEGRITY'}{'sha2_256'} = '';
2294     $checked{'ESP_INTEGRITY'}{'sha1'} = '';
2295     $checked{'ESP_INTEGRITY'}{'md5'} = '';
2296     @temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
2297     foreach my $key (@temp) {$checked{'ESP_INTEGRITY'}{$key} = "selected='selected'"; }
2298     $checked{'ESP_GROUPTYPE'}{$cgiparams{'ESP_GROUPTYPE'}} = "selected='selected'";
2299
2300     $checked{'COMPRESSION'} = $cgiparams{'COMPRESSION'} eq 'on' ? "checked='checked'" : '' ;
2301     $checked{'ONLY_PROPOSED'} = $cgiparams{'ONLY_PROPOSED'} eq 'on' ? "checked='checked'" : '' ;
2302     $checked{'PFS'} = $cgiparams{'PFS'} eq 'on' ? "checked='checked'" : '' ;
2303     $checked{'VHOST'} = $cgiparams{'VHOST'} eq 'on' ? "checked='checked'" : '' ;
2304
2305     &Header::showhttpheaders();
2306     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
2307     &Header::openbigbox('100%', 'left', '', $errormessage);
2308
2309     if ($errormessage) {
2310         &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
2311         print "<class name='base'>$errormessage";
2312         print "&nbsp;</class>";
2313         &Header::closebox();
2314     }
2315
2316     if ($warnmessage) {
2317         &Header::openbox('100%', 'left', $Lang::tr{'warning messages'});
2318         print "<class name='base'>$warnmessage";
2319         print "&nbsp;</class>";
2320         &Header::closebox();
2321     }
2322
2323     &Header::openbox('100%', 'left', "$Lang::tr{'advanced'}:");
2324     print <<EOF
2325     <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
2326     <input type='hidden' name='ADVANCED' value='yes' />
2327     <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
2328
2329     <table width='100%'>
2330         <tr><td class='boldbase' align='right' valign='top'>$Lang::tr{'ike encryption'}</td><td class='boldbase' valign='top'>
2331                 <select name='IKE_ENCRYPTION' multiple='multiple' size='4'>
2332                 <option value='aes256' $checked{'IKE_ENCRYPTION'}{'aes256'}>AES (256 bit)</option>
2333                 <option value='aes128' $checked{'IKE_ENCRYPTION'}{'aes128'}>AES (128 bit)</option>
2334                 <option value='3des' $checked{'IKE_ENCRYPTION'}{'3des'}>3DES</option>
2335                 </select></td>
2336
2337             <td class='boldbase' align='right' valign='top'>$Lang::tr{'ike integrity'}</td><td class='boldbase' valign='top'>
2338                 <select name='IKE_INTEGRITY' multiple='multiple' size='4'>
2339                 <option value='sha' $checked{'IKE_INTEGRITY'}{'sha'}>SHA</option>
2340                 <option value='md5' $checked{'IKE_INTEGRITY'}{'md5'}>MD5</option>
2341                 </select></td>
2342         
2343             <td class='boldbase' align='right' valign='top'>$Lang::tr{'ike grouptype'}</td><td class='boldbase' valign='top'>
2344                 <select name='IKE_GROUPTYPE' multiple='multiple' size='4'>
2345                 <option value='8192' $checked{'IKE_GROUPTYPE'}{'8192'}>MODP-8192</option>
2346                 <option value='6144' $checked{'IKE_GROUPTYPE'}{'6144'}>MODP-6144</option>
2347                 <option value='4096' $checked{'IKE_GROUPTYPE'}{'4096'}>MODP-4096</option>
2348                 <option value='3072' $checked{'IKE_GROUPTYPE'}{'3072'}>MODP-3072</option>
2349                 <option value='2048' $checked{'IKE_GROUPTYPE'}{'2048'}>MODP-2048</option>
2350                 <option value='1536' $checked{'IKE_GROUPTYPE'}{'1536'}>MODP-1536</option>
2351                 <option value='1024' $checked{'IKE_GROUPTYPE'}{'1024'}>MODP-1024</option>
2352                 </select></td>
2353         </tr><tr>
2354             <td class='boldbase' align='right' valign='top'>$Lang::tr{'ike lifetime'}</td><td class='boldbase' valign='top'>
2355             <input type='text' name='IKE_LIFETIME' value='$cgiparams{'IKE_LIFETIME'}' size='5' /> $Lang::tr{'hours'}</td>
2356
2357         </tr><tr>
2358             <td colspan='1'><hr /></td>
2359         </tr><tr>
2360             <td class='boldbase' align='right' valign='top'>$Lang::tr{'esp encryption'}</td><td class='boldbase' valign='top'>
2361                 <select name='ESP_ENCRYPTION' multiple='multiple' size='4'>
2362                 <option value='aes256' $checked{'ESP_ENCRYPTION'}{'aes256'}>AES (256 bit)</option>
2363                 <option value='aes128' $checked{'ESP_ENCRYPTION'}{'aes128'}>AES (128 bit)</option>
2364                 <option value='3des' $checked{'ESP_ENCRYPTION'}{'3des'}>3DES</option>
2365
2366             <td class='boldbase' align='right' valign='top'>$Lang::tr{'esp integrity'}</td><td class='boldbase' valign='top'>
2367                 <select name='ESP_INTEGRITY' multiple='multiple' size='4'>
2368                 <option value='sha1' $checked{'ESP_INTEGRITY'}{'sha1'}>SHA1</option>
2369                 <option value='md5' $checked{'ESP_INTEGRITY'}{'md5'}>MD5</option></select></td>
2370
2371             <td class='boldbase' align='right' valign='top'>$Lang::tr{'esp grouptype'}</td><td class='boldbase' valign='top'>
2372                 <select name='ESP_GROUPTYPE'>
2373                 <option value=''>$Lang::tr{'phase1 group'}</option></select></td>
2374         </tr><tr>
2375             <td class='boldbase' align='right' valign='top'>$Lang::tr{'esp keylife'}</td><td class='boldbase' valign='top'>
2376                 <input type='text' name='ESP_KEYLIFE' value='$cgiparams{'ESP_KEYLIFE'}' size='5' /> $Lang::tr{'hours'}</td>
2377         </tr><tr>
2378             <td colspan='1'><hr /></td>
2379         </tr><tr>
2380             <td colspan='5'><input type='checkbox' name='ONLY_PROPOSED' $checked{'ONLY_PROPOSED'} />
2381                 IKE+ESP: $Lang::tr{'use only proposed settings'}</td>
2382         </tr><tr>
2383             <td colspan='5'><input type='checkbox' name='PFS' $checked{'PFS'} />
2384                 $Lang::tr{'pfs yes no'}</td>
2385                 <td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
2386         </tr><tr>
2387             <td colspan='5'><input type='checkbox' name='COMPRESSION' $checked{'COMPRESSION'} />
2388                 $Lang::tr{'vpn payload compression'}</td>
2389                 <td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
2390         </tr>
2391 EOF
2392     ;
2393     if ($confighash{$cgiparams{'KEY'}}[3] eq 'net') {
2394         print "<tr><td><input type='hidden' name='VHOST' value='off' /></td></tr>";
2395     } elsif ($confighash{$cgiparams{'KEY'}}[10]) {
2396         print "<tr><td colspan='5'><input type='checkbox' name='VHOST' $checked{'VHOST'} disabled='disabled' />";
2397         print " $Lang::tr{'vpn vhost'}</td></tr>";
2398     } else {
2399         print "<tr><td colspan='5'><input type='checkbox' name='VHOST' $checked{'VHOST'} />";
2400         print " $Lang::tr{'vpn vhost'}</td></tr>";
2401     }
2402
2403     print "</table></form>";
2404     &Header::closebox();
2405     &Header::closebigbox();
2406     &Header::closepage();
2407     exit(0);
2408
2409     ADVANCED_END:
2410 }
2411
2412 ###
2413 ### Default status page
2414 ###
2415     %cgiparams = ();
2416     %cahash = ();
2417     %confighash = ();
2418     &General::readhash("${General::swroot}/vpn/settings", \%cgiparams);
2419     &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
2420     &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
2421     $cgiparams{'CA_NAME'} = '';
2422
2423     my @status = `/usr/local/bin/ipsecctrl I 2>/dev/null`;
2424
2425     # suggest a default name for this side
2426     if ($cgiparams{'VPN_IP'} eq '' && -e "${General::swroot}/red/active") {
2427         if (open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
2428             my $ipaddr = <IPADDR>;
2429             close IPADDR;
2430             chomp ($ipaddr);
2431             $cgiparams{'VPN_IP'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
2432             if ($cgiparams{'VPN_IP'} eq '') {
2433                 $cgiparams{'VPN_IP'} = $ipaddr;
2434             }
2435         }
2436     }
2437     # no IP found, use %defaultroute
2438     $cgiparams{'VPN_IP'} ='%defaultroute' if ($cgiparams{'VPN_IP'} eq '');
2439     
2440     $cgiparams{'VPN_DELAYED_START'} = 0 if (! defined ($cgiparams{'VPN_DELAYED_START'}));
2441     $checked{'VPN_WATCH'} = $cgiparams{'VPN_WATCH'} eq 'on' ? "checked='checked'" : '' ;
2442     map ($checked{$_} = $cgiparams{$_} eq 'on' ? "checked='checked'" : '',
2443         ('ENABLED','DBG_CRYPT','DBG_PARSING','DBG_EMITTING','DBG_CONTROL',
2444          'DBG_DNS'));
2445
2446
2447     &Header::showhttpheaders();
2448     &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
2449     &Header::openbigbox('100%', 'left', '', $errormessage);
2450
2451     if ($errormessage) {
2452         &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
2453         print "<class name='base'>$errormessage\n";
2454         print "&nbsp;</class>\n";
2455         &Header::closebox();
2456     }
2457
2458     &Header::openbox('100%', 'left', $Lang::tr{'global settings'});
2459     print <<END
2460     <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2461     <table width='100%'>
2462     <tr>
2463         <td width='20%' class='base' nowrap='nowrap'>$Lang::tr{'vpn red name'}:</td>
2464         <td width='20%'><input type='text' name='VPN_IP' value='$cgiparams{'VPN_IP'}' /></td>
2465         <td width='20%' class='base'>$Lang::tr{'enabled'}<input type='checkbox' name='ENABLED' $checked{'ENABLED'} /></td>
2466     </tr>
2467 END
2468     ;
2469     print <<END
2470     <tr>
2471         <td class='base' nowrap='nowrap'>$Lang::tr{'override mtu'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2472         <td ><input type='text' name='VPN_OVERRIDE_MTU' value='$cgiparams{'VPN_OVERRIDE_MTU'}' /></td>
2473     </tr>
2474 END
2475     ;
2476 print <<END
2477     <tr>
2478         <td  class='base' nowrap='nowrap'>$Lang::tr{'vpn delayed start'}:&nbsp;<img src='/blob.gif' alt='*' /><img src='/blob.gif' alt='*' /></td>
2479         <td ><input type='text' name='VPN_DELAYED_START' value='$cgiparams{'VPN_DELAYED_START'}' /></td>
2480     </tr>
2481  </table>
2482 <p>$Lang::tr{'vpn watch'}:<input type='checkbox' name='VPN_WATCH' $checked{'VPN_WATCH'} /></p>
2483 <p>PLUTO DEBUG&nbsp;=
2484 crypt:<input type='checkbox' name='DBG_CRYPT' $checked{'DBG_CRYPT'} />,&nbsp;
2485 parsing:<input type='checkbox' name='DBG_PARSING' $checked{'DBG_PARSING'} />,&nbsp;
2486 emitting:<input type='checkbox' name='DBG_EMITTING' $checked{'DBG_EMITTING'} />,&nbsp;
2487 control:<input type='checkbox' name='DBG_CONTROL' $checked{'DBG_CONTROL'} />,&nbsp;
2488 dns:<input type='checkbox' name='DBG_DNS' $checked{'DBG_DNS'} />&nbsp;
2489 <hr />
2490 <table width='100%'>
2491 <tr>
2492     <td class='base' valign='top'><img src='/blob.gif' alt='*' /></td>
2493     <td width='70%' class='base' valign='top'>$Lang::tr{'this field may be blank'}</td>
2494 </tr>
2495 <tr>
2496     <td class='base' valign='top' nowrap='nowrap'><img src='/blob.gif' alt='*' /><img src='/blob.gif' alt='*' />&nbsp;</td>
2497     <td class='base'>   <font class='base'>$Lang::tr{'vpn delayed start help'}</font></td>
2498     <td width='30%' align='center' class='base'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
2499 </tr>
2500 </table>
2501 END
2502 ;               
2503     print "</form>";
2504     &Header::closebox();
2505
2506     &Header::openbox('100%', 'left', $Lang::tr{'connection status and controlc'});
2507     print <<END
2508     <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2509     <tr>
2510         <td width='10%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></td>
2511         <td width='22%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></td>
2512         <td width='23%' class='boldbase' align='center'><b>$Lang::tr{'common name'}</b></td>
2513         <td width='30%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td>
2514         <td width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></td>
2515         <td class='boldbase' align='center' colspan='6'><b>$Lang::tr{'action'}</b></td>
2516     </tr>
2517 END
2518     ;
2519     my $id = 0;
2520     my $gif;
2521     foreach my $key (keys %confighash) {
2522         if ($confighash{$key}[0] eq 'on') { $gif = 'on.gif'; } else { $gif = 'off.gif'; }
2523
2524         if ($id % 2) {
2525             print "<tr bgcolor='$color{'color20'}'>\n";
2526         } else {
2527             print "<tr bgcolor='$color{'color22'}'>\n";
2528         }
2529         print "<td align='center' nowrap='nowrap'>$confighash{$key}[1]</td>";
2530         print "<td align='center' nowrap='nowrap'>" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ")</td>";
2531         if ($confighash{$key}[2] eq '%auth-dn') {
2532             print "<td align='left' nowrap='nowrap'>$confighash{$key}[9]</td>";
2533         } elsif ($confighash{$key}[4] eq 'cert') {
2534             print "<td align='left' nowrap='nowrap'>$confighash{$key}[2]</td>";
2535         } else {
2536             print "<td align='left'>&nbsp;</td>";
2537         }
2538         print "<td align='center'>$confighash{$key}[25]</td>";
2539         # get real state
2540         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>";
2541         foreach my $line (@status) {
2542             if (($line =~ /\"$confighash{$key}[1]\".*IPsec SA established/) ||
2543                ($line =~ / $confighash{$key}[1]\[.*ESTABLISHED/))
2544             {
2545                 $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>";
2546             }
2547         }
2548         # move to blueif really down
2549         if ($confighash{$key}[0] eq 'off' && $active =~ /${Header::colourred}/ ) {
2550             $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>";
2551         }
2552         print <<END
2553         <td align='center'>$active</td>
2554         <td align='center'>
2555             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2556             <input type='image'  name='$Lang::tr{'restart'}' src='/images/reload.gif' alt='$Lang::tr{'restart'}' title='$Lang::tr{'restart'}' />
2557             <input type='hidden' name='ACTION' value='$Lang::tr{'restart'}' />
2558             <input type='hidden' name='KEY' value='$key' />
2559             </form>
2560         </td>
2561 END
2562         ;
2563         if (($confighash{$key}[4] eq 'cert') && ($confighash{$key}[2] ne '%auth-dn')) {
2564             print <<END
2565             <td align='center'>
2566             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2567                 <input type='image' name='$Lang::tr{'show certificate'}' src='/images/info.gif' alt='$Lang::tr{'show certificate'}' title='$Lang::tr{'show certificate'}' />
2568                 <input type='hidden' name='ACTION' value='$Lang::tr{'show certificate'}' />
2569                 <input type='hidden' name='KEY' value='$key' />
2570             </form>
2571             </td>
2572 END
2573         ; } else {
2574             print "<td width='2%'>&nbsp;</td>";
2575         }
2576         if ($confighash{$key}[4] eq 'cert' && -f "${General::swroot}/certs/$confighash{$key}[1].p12") { 
2577             print <<END
2578             <td align='center'>
2579             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2580                 <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'}' />
2581                 <input type='hidden' name='ACTION' value='$Lang::tr{'download pkcs12 file'}' />
2582                 <input type='hidden' name='KEY' value='$key' />
2583             </form>
2584         </td>
2585 END
2586         ; } elsif (($confighash{$key}[4] eq 'cert') && ($confighash{$key}[2] ne '%auth-dn')) {
2587             print <<END
2588             <td align='center'>
2589             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2590                 <input type='image' name='$Lang::tr{'download certificate'}' src='/images/floppy.gif' alt='$Lang::tr{'download certificate'}' title='$Lang::tr{'download certificate'}' />
2591                 <input type='hidden' name='ACTION' value='$Lang::tr{'download certificate'}' />
2592                 <input type='hidden' name='KEY' value='$key' />
2593             </form>
2594         </td>
2595 END
2596         ; } else {
2597             print "<td width='2%'>&nbsp;</td>";
2598         }
2599         print <<END
2600         <td align='center'>
2601             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2602             <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' />
2603             <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
2604             <input type='hidden' name='KEY' value='$key' />
2605             </form>
2606         </td>
2607
2608         <td align='center'>
2609             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2610             <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
2611             <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
2612             <input type='hidden' name='KEY' value='$key' />
2613             </form>
2614         </td>
2615         <td align='center' >
2616             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2617             <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
2618             <input type='image'  name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
2619             <input type='hidden' name='KEY' value='$key' />
2620             </form>
2621         </td>
2622         </tr>
2623 END
2624         ;
2625         $id++;
2626     }
2627     print "</table>";
2628
2629     # If the config file contains entries, print Key to action icons
2630     if ( $id ) {
2631     print <<END
2632     <table>
2633     <tr>
2634         <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
2635         <td>&nbsp; <img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
2636         <td class='base'>$Lang::tr{'click to disable'}</td>
2637         <td>&nbsp; &nbsp; <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
2638         <td class='base'>$Lang::tr{'show certificate'}</td>
2639         <td>&nbsp; &nbsp; <img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
2640         <td class='base'>$Lang::tr{'edit'}</td>
2641         <td>&nbsp; &nbsp; <img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
2642         <td class='base'>$Lang::tr{'remove'}</td>
2643     </tr>
2644     <tr>
2645         <td>&nbsp; </td>
2646         <td>&nbsp; <img src='/images/off.gif' alt='?OFF' /></td>
2647         <td class='base'>$Lang::tr{'click to enable'}</td>
2648         <td>&nbsp; &nbsp; <img src='/images/floppy.gif' alt='?FLOPPY' /></td>
2649         <td class='base'>$Lang::tr{'download certificate'}</td>
2650         <td>&nbsp; &nbsp; <img src='/images/reload.gif' alt='?RELOAD'/></td>
2651         <td class='base'>$Lang::tr{'restart'}</td>
2652     </tr>
2653     </table>
2654 END
2655     ;
2656     }
2657
2658     print <<END
2659     <table width='100%'>
2660     <tr><td align='center' colspan='9'>
2661         <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2662         <input type='submit' name='ACTION' value='$Lang::tr{'add'}' />
2663         </form>
2664     </td></tr>
2665     </table>
2666 END
2667     ;
2668     &Header::closebox();
2669
2670     &Header::openbox('100%', 'left', "$Lang::tr{'certificate authorities'}:");
2671     print <<EOF
2672     <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2673     <tr>
2674         <td width='25%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></td>
2675         <td width='65%' class='boldbase' align='center'><b>$Lang::tr{'subject'}</b></td>
2676         <td width='10%' class='boldbase' colspan='3' align='center'><b>$Lang::tr{'action'}</b></td>
2677     </tr>
2678 EOF
2679     ;
2680     if (-f "${General::swroot}/ca/cacert.pem") {
2681         my $casubject = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/ca/cacert.pem"));
2682
2683         print <<END
2684         <tr bgcolor='$color{'color22'}'>
2685         <td class='base'>$Lang::tr{'root certificate'}</td>
2686         <td class='base'>$casubject</td>
2687         <td width='3%' align='center'>
2688             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2689             <input type='hidden' name='ACTION' value='$Lang::tr{'show root certificate'}' />
2690             <input type='image' name='$Lang::tr{'edit'}' src='/images/info.gif' alt='$Lang::tr{'show root certificate'}' title='$Lang::tr{'show root certificate'}' />
2691             </form>
2692         </td>
2693         <td width='3%' align='center'>
2694             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2695             <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'}' />
2696             <input type='hidden' name='ACTION' value='$Lang::tr{'download root certificate'}' />
2697             </form>
2698         </td>
2699         <td width='4%'>&nbsp;</td></tr>
2700 END
2701         ;
2702     } else {
2703         # display rootcert generation buttons
2704         print <<END
2705         <tr bgcolor='$color{'color22'}'>
2706         <td class='base'>$Lang::tr{'root certificate'}:</td>
2707         <td class='base'>$Lang::tr{'not present'}</td>
2708         <td colspan='3'>&nbsp;</td></tr>
2709 END
2710         ;
2711     }
2712
2713     if (-f "${General::swroot}/certs/hostcert.pem") {
2714         my $hostsubject = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/certs/hostcert.pem"));
2715
2716         print <<END
2717         <tr bgcolor='$color{'color20'}'>
2718         <td class='base'>$Lang::tr{'host certificate'}</td>
2719         <td class='base'>$hostsubject</td>
2720         <td width='3%' align='center'>
2721             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2722             <input type='hidden' name='ACTION' value='$Lang::tr{'show host certificate'}' />
2723             <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'}' />
2724             </form>
2725         </td>
2726         <td width='3%' align='center'>
2727             <form method='post' action='$ENV{'SCRIPT_NAME'}'>
2728             <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'}' />
2729             <input type='hidden' name='ACTION' value='$Lang::tr{'download host certificate'}' />
2730             </form>
2731         </td>
2732         <td width='4%'>&nbsp;</td></tr>
2733 END
2734         ;
2735     } else {
2736         # Nothing
2737         print <<END
2738         <tr bgcolor='$color{'color20'}'>
2739         <td width='25%' class='base'>$Lang::tr{'host certificate'}:</td>
2740         <td class='base'>$Lang::tr{'not present'}</td>
2741         <td colspan='3'>&nbsp;</td></tr>
2742 END
2743         ;
2744     }
2745  
2746     my $rowcolor = 0;
2747     if (keys %cahash > 0) {
2748    foreach my $key (keys %cahash) {
2749        if ($rowcolor++ % 2) {
2750       print "<tr bgcolor='$color{'color20'}'>\n";
2751        } else {
2752       print "<tr bgcolor='$color{'color22'}'>\n";
2753        }
2754             print "<td class='base'>$cahash{$key}[0]</td>\n";
2755             print "<td class='base'>$cahash{$key}[1]</td>\n";
2756             print <<END
2757             <td align='center'>
2758                 <form method='post' name='cafrm${key}a' action='$ENV{'SCRIPT_NAME'}'>
2759                 <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'}' />
2760                 <input type='hidden' name='ACTION' value='$Lang::tr{'show ca certificate'}' />
2761                 <input type='hidden' name='KEY' value='$key' />
2762                 </form>
2763             </td>
2764             <td align='center'>
2765                 <form method='post' name='cafrm${key}b' action='$ENV{'SCRIPT_NAME'}'>
2766                 <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'}' />
2767                 <input type='hidden' name='ACTION' value='$Lang::tr{'download ca certificate'}' />
2768                 <input type='hidden' name='KEY' value='$key' />
2769                 </form>
2770             </td>
2771             <td align='center'>
2772                 <form method='post' name='cafrm${key}c' action='$ENV{'SCRIPT_NAME'}'>
2773                 <input type='hidden' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
2774                 <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'}' />
2775                 <input type='hidden' name='KEY' value='$key' />
2776                 </form>
2777             </td>
2778             </tr>
2779 END
2780             ;
2781         }
2782     }
2783     print "</table>";
2784
2785     # If the file contains entries, print Key to action icons
2786     if ( -f "${General::swroot}/ca/cacert.pem") {
2787         print <<END
2788         <table><tr>
2789         <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
2790         <td>&nbsp; &nbsp; <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
2791         <td class='base'>$Lang::tr{'show certificate'}</td>
2792         <td>&nbsp; &nbsp; <img src='/images/floppy.gif' alt='$Lang::tr{'download certificate'}' /></td>
2793         <td class='base'>$Lang::tr{'download certificate'}</td>
2794         </tr></table>
2795 END
2796         ;
2797     }
2798     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>";
2799     print <<END
2800     <hr />
2801     <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
2802     <table width='100%' border='0' cellspacing='1' cellpadding='0'>
2803     $createCA
2804     <tr>
2805         <td class='base' nowrap='nowrap'>$Lang::tr{'ca name'}:</td>
2806         <td nowrap='nowrap'><input type='text' name='CA_NAME' value='$cgiparams{'CA_NAME'}' size='15' /> </td>
2807         <td nowrap='nowrap'><input type='file' name='FH' size='30' /></td>
2808         <td nowrap='nowrap'><input type='submit' name='ACTION' value='$Lang::tr{'upload ca certificate'}' /></td>
2809     </tr>
2810     <tr>
2811         <td colspan='3'>$Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}:</td>
2812         <td><input type='submit' name='ACTION' value='$Lang::tr{'remove x509'}' /></td>
2813     </tr>
2814     </table>
2815     </form>
2816 END
2817     ;
2818     &Header::closebox();
2819     &Header::closebigbox();
2820     &Header::closepage();