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