]> git.ipfire.org Git - ipfire-2.x.git/blame - html/cgi-bin/vpnmain.cgi
vpnmain.cgi: Fix extra whitespace in exported pk12 file
[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 #
993724b4 5# Copyright (C) 2007-2020 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 21
205c3c17 22use Data::UUID;
26a0befd 23use MIME::Base64;
ac1cfefa
MT
24use Net::DNS;
25use File::Copy;
26use File::Temp qw/ tempfile tempdir /;
27use strict;
eff2dbf8 28use Sort::Naturally;
c7fe09c6 29use Sys::Hostname;
ac1cfefa 30# enable only the following on debugging purpose
cb5e9c6c
CS
31#use warnings;
32#use CGI::Carp 'fatalsToBrowser';
ac1cfefa 33
986e08d9 34require '/var/ipfire/general-functions.pl';
ac1cfefa
MT
35require "${General::swroot}/lang.pl";
36require "${General::swroot}/header.pl";
ac1cfefa
MT
37require "${General::swroot}/countries.pl";
38
39#workaround to suppress a warning when a variable is used only once
ed84e8b8 40my @dummy = ( ${Header::colourgreen}, ${Header::colourblue} );
ac1cfefa
MT
41undef (@dummy);
42
43###
44### Initialize variables
45###
624615ee 46my $sleepDelay = 4; # after a call to ipsecctrl S or R, wait this delay (seconds) before reading status (let the ipsec do its job)
ac1cfefa 47my %netsettings=();
ed84e8b8
MT
48our %cgiparams=();
49our %vpnsettings=();
ac1cfefa
MT
50my %checked=();
51my %confighash=();
52my %cahash=();
53my %selected=();
54my $warnmessage = '';
55my $errormessage = '';
ed84e8b8 56
f2fdd0c1
CS
57my %color = ();
58my %mainsettings = ();
59&General::readhash("${General::swroot}/main/settings", \%mainsettings);
8186b372 60&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
f2fdd0c1 61
ac1cfefa 62&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
e897bfeb 63
af183eeb
MT
64my %INACTIVITY_TIMEOUTS = (
65 300 => $Lang::tr{'five minutes'},
66 600 => $Lang::tr{'ten minutes'},
67 900 => $Lang::tr{'fifteen minutes'},
68 1800 => $Lang::tr{'thirty minutes'},
69 3600 => $Lang::tr{'one hour'},
70 43200 => $Lang::tr{'twelve hours'},
71 86400 => $Lang::tr{'24 hours'},
72 0 => "- $Lang::tr{'unlimited'} -",
73);
74
ae0d0698
MT
75# Load aliases
76my %aliases;
77&General::get_aliases(\%aliases);
78
e9850821
AM
79my $col="";
80
ac1cfefa 81$cgiparams{'ENABLED'} = 'off';
ac1cfefa 82$cgiparams{'EDIT_ADVANCED'} = 'off';
ac1cfefa
MT
83$cgiparams{'ACTION'} = '';
84$cgiparams{'CA_NAME'} = '';
ed84e8b8
MT
85$cgiparams{'KEY'} = '';
86$cgiparams{'TYPE'} = '';
87$cgiparams{'ADVANCED'} = '';
ed84e8b8
MT
88$cgiparams{'NAME'} = '';
89$cgiparams{'LOCAL_SUBNET'} = '';
90$cgiparams{'REMOTE_SUBNET'} = '';
ae0d0698 91$cgiparams{'LOCAL'} = '';
ed84e8b8
MT
92$cgiparams{'REMOTE'} = '';
93$cgiparams{'LOCAL_ID'} = '';
94$cgiparams{'REMOTE_ID'} = '';
95$cgiparams{'REMARK'} = '';
96$cgiparams{'PSK'} = '';
97$cgiparams{'CERT_NAME'} = '';
98$cgiparams{'CERT_EMAIL'} = '';
99$cgiparams{'CERT_OU'} = '';
100$cgiparams{'CERT_ORGANIZATION'} = '';
101$cgiparams{'CERT_CITY'} = '';
102$cgiparams{'CERT_STATE'} = '';
103$cgiparams{'CERT_COUNTRY'} = '';
104$cgiparams{'SUBJECTALTNAME'} = '';
105$cgiparams{'CERT_PASS1'} = '';
106$cgiparams{'CERT_PASS2'} = '';
107$cgiparams{'ROOTCERT_HOSTNAME'} = '';
108$cgiparams{'ROOTCERT_COUNTRY'} = '';
109$cgiparams{'P12_PASS'} = '';
110$cgiparams{'ROOTCERT_ORGANIZATION'} = '';
111$cgiparams{'ROOTCERT_HOSTNAME'} = '';
112$cgiparams{'ROOTCERT_EMAIL'} = '';
113$cgiparams{'ROOTCERT_OU'} = '';
114$cgiparams{'ROOTCERT_CITY'} = '';
115$cgiparams{'ROOTCERT_STATE'} = '';
c7fe09c6 116$cgiparams{'RW_ENDPOINT'} = '';
9d85ac3b 117$cgiparams{'RW_NET'} = '';
4e156911
AM
118$cgiparams{'DPD_DELAY'} = '30';
119$cgiparams{'DPD_TIMEOUT'} = '120';
f6529a04 120$cgiparams{'FORCE_MOBIKE'} = 'off';
1e9457ac 121$cgiparams{'START_ACTION'} = 'route';
8ebe7254 122$cgiparams{'INACTIVITY_TIMEOUT'} = 1800;
29f5e0e2 123$cgiparams{'MODE'} = "tunnel";
cae1f4a7 124$cgiparams{'INTERFACE_MODE'} = "";
74641317 125$cgiparams{'INTERFACE_ADDRESS'} = "";
55842dda 126$cgiparams{'INTERFACE_MTU'} = 1500;
dccd7e87 127$cgiparams{'DNS_SERVERS'} = "";
ac1cfefa
MT
128&Header::getcgihash(\%cgiparams, {'wantfile' => 1, 'filevar' => 'FH'});
129
2d7b3347
MT
130my %APPLE_CIPHERS = (
131 "aes256gcm128" => "AES-256-GCM",
132 "aes128gcm128" => "AES-128-GCM",
133 "aes256" => "AES-256",
134 "aes128" => "AES-128",
135 "3des" => "3DES",
136);
137
138my %APPLE_INTEGRITIES = (
139 "sha2_512" => "SHA2-512",
140 "sha2_384" => "SHA2-384",
141 "sha2_256" => "SHA2-256",
142 "sha1" => "SHA1-160",
143);
144
145my %APPLE_DH_GROUPS = (
146 "768" => 1,
147 "1024" => 2,
148 "1536" => 5,
149 "2048" => 14,
150 "3072" => 15,
151 "4096" => 16,
152 "6144" => 17,
153 "8192" => 18,
154 "e256" => 19,
155 "e384" => 20,
156 "e521" => 21,
157);
158
ac1cfefa
MT
159###
160### Useful functions
161###
162sub valid_dns_host {
163 my $hostname = $_[0];
164 unless ($hostname) { return "No hostname"};
165 my $res = new Net::DNS::Resolver;
166 my $query = $res->search("$hostname");
167 if ($query) {
168 foreach my $rr ($query->answer) {
169 ## Potential bug - we are only looking at A records:
170 return 0 if $rr->type eq "A";
171 }
172 } else {
173 return $res->errorstring;
174 }
175}
ed84e8b8
MT
176###
177### Just return true is one interface is vpn enabled
178###
179sub vpnenabled {
624615ee 180 return ($vpnsettings{'ENABLED'} eq 'on');
ed84e8b8
MT
181}
182###
624615ee
LS
183### old version: maintain serial number to one, without explication.
184### this: let the counter go, so that each cert is numbered.
ed84e8b8 185###
624615ee
LS
186sub cleanssldatabase {
187 if (open(FILE, ">${General::swroot}/certs/serial")) {
188 print FILE "01";
189 close FILE;
190 }
191 if (open(FILE, ">${General::swroot}/certs/index.txt")) {
192 print FILE "";
193 close FILE;
194 }
e6f7f8e7
EK
195 if (open(FILE, ">${General::swroot}/certs/index.txt.attr")) {
196 print FILE "";
197 close FILE;
198 }
624615ee 199 unlink ("${General::swroot}/certs/index.txt.old");
e6f7f8e7 200 unlink ("${General::swroot}/certs/index.txt.attr.old");
624615ee
LS
201 unlink ("${General::swroot}/certs/serial.old");
202 unlink ("${General::swroot}/certs/01.pem");
ac1cfefa 203}
624615ee
LS
204sub newcleanssldatabase {
205 if (! -s "${General::swroot}/certs/serial" ) {
206 open(FILE, ">${General::swroot}/certs/serial");
207 print FILE "01";
208 close FILE;
209 }
210 if (! -s ">${General::swroot}/certs/index.txt") {
a81cbf61
SS
211 open(FILE, ">${General::swroot}/certs/index.txt");
212 close(FILE);
624615ee 213 }
e6f7f8e7 214 if (! -s ">${General::swroot}/certs/index.txt.attr") {
a81cbf61
SS
215 open(FILE, ">${General::swroot}/certs/index.txt.attr");
216 close(FILE);
e6f7f8e7 217 }
624615ee 218 unlink ("${General::swroot}/certs/index.txt.old");
e6f7f8e7 219 unlink ("${General::swroot}/certs/index.txt.attr.old");
624615ee
LS
220 unlink ("${General::swroot}/certs/serial.old");
221# unlink ("${General::swroot}/certs/01.pem"); numbering evolves. Wrong place to delete
ac1cfefa 222}
ed84e8b8
MT
223
224###
225### Call openssl and return errormessage if any
226###
227sub callssl ($) {
624615ee 228 my $opt = shift;
b71a7fb9 229 my $retssl = `/usr/bin/openssl $opt 2>&1`; #redirect stderr
624615ee 230 my $ret = '';
b71a7fb9 231 foreach my $line (split (/\n/, $retssl)) {
624615ee
LS
232 &General::log("ipsec", "$line") if (0); # 1 for verbose logging
233 $ret .= '<br>'.$line if ( $line =~ /error|unknown/ );
234 }
235 if ($ret) {
236 $ret= &Header::cleanhtml($ret);
237 }
238 return $ret ? "$Lang::tr{'openssl produced an error'}: $ret" : '' ;
ed84e8b8
MT
239}
240###
241### Obtain a CN from given cert
242###
243sub getCNfromcert ($) {
624615ee 244 #&General::log("ipsec", "Extracting name from $_[0]...");
b71a7fb9
MT
245 my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
246 $temp =~ /Subject:.*CN = (.*)[\n]/;
247 $temp = $1;
248 $temp =~ s+/Email+, E+;
249 $temp =~ s/ ST = / S = /;
250 $temp =~ s/,//g;
251 $temp =~ s/\'//g;
624615ee 252 return $temp;
ed84e8b8
MT
253}
254###
255### Obtain Subject from given cert
256###
257sub getsubjectfromcert ($) {
624615ee 258 #&General::log("ipsec", "Extracting subject from $_[0]...");
b71a7fb9
MT
259 my $temp = `/usr/bin/openssl x509 -text -in $_[0]`;
260 $temp =~ /Subject: (.*)[\n]/;
261 $temp = $1;
262 $temp =~ s+/Email+, E+;
263 $temp =~ s/ ST = / S = /;
624615ee 264 return $temp;
ed84e8b8
MT
265}
266###
624615ee 267### Combine local subnet and connection name to make a unique name for each connection section
ed84e8b8
MT
268### (this sub is not used now)
269###
270sub makeconnname ($) {
624615ee
LS
271 my $conn = shift;
272 my $subnet = shift;
273
274 $subnet =~ /^(.*?)\/(.*?)$/; # $1=IP $2=mask
275 my $ip = unpack('N', &Socket::inet_aton($1));
276 if (length ($2) > 2) {
277 my $mm = unpack('N', &Socket::inet_aton($2));
278 while ( ($mm & 1)==0 ) {
279 $ip >>= 1;
280 $mm >>= 1;
281 };
282 } else {
283 $ip >>= (32 - $2);
284 }
285 return sprintf ("%s-%X", $conn, $ip);
ed84e8b8
MT
286}
287###
288### Write a config file.
289###
290###Type=Host : GUI can choose the interface used (RED,GREEN,BLUE) and
291### the side is always defined as 'left'.
ed84e8b8 292###
ed84e8b8 293
ac1cfefa 294sub writeipsecfiles {
624615ee
LS
295 my %lconfighash = ();
296 my %lvpnsettings = ();
297 &General::readhasharray("${General::swroot}/vpn/config", \%lconfighash);
298 &General::readhash("${General::swroot}/vpn/settings", \%lvpnsettings);
299
300 open(CONF, ">${General::swroot}/vpn/ipsec.conf") or die "Unable to open ${General::swroot}/vpn/ipsec.conf: $!";
301 open(SECRETS, ">${General::swroot}/vpn/ipsec.secrets") or die "Unable to open ${General::swroot}/vpn/ipsec.secrets: $!";
302 flock CONF, 2;
303 flock SECRETS, 2;
304 print CONF "version 2\n\n";
305 print CONF "conn %default\n";
306 print CONF "\tkeyingtries=%forever\n";
307 print CONF "\n";
308
309 # Add user includes to config file
310 if (-e "/etc/ipsec.user.conf") {
311 print CONF "include /etc/ipsec.user.conf\n";
312 print CONF "\n";
ed84e8b8 313 }
e8b3bb0e 314
624615ee 315 print SECRETS "include /etc/ipsec.user.secrets\n";
4b02b404 316
624615ee
LS
317 if (-f "${General::swroot}/certs/hostkey.pem") {
318 print SECRETS ": RSA ${General::swroot}/certs/hostkey.pem\n"
319 }
320 my $last_secrets = ''; # old the less specifics connections
321
322 foreach my $key (keys %lconfighash) {
323 next if ($lconfighash{$key}[0] ne 'on');
324
325 #remote peer is not set? => use '%any'
326 $lconfighash{$key}[10] = '%any' if ($lconfighash{$key}[10] eq '');
327
ae0d0698
MT
328 # Field 6 might be "off" on old installations
329 if ($lconfighash{$key}[6] eq "off") {
517683ee 330 $lconfighash{$key}[6] = $lvpnsettings{"VPN_IP"};
ae0d0698
MT
331 }
332
624615ee 333 my $localside;
ae0d0698
MT
334 if ($lconfighash{$key}[6]) {
335 $localside = $lconfighash{$key}[6];
ae0d0698
MT
336 } else {
337 $localside = "%defaultroute";
4b02b404 338 }
e8b3bb0e 339
b01c17e9
MT
340 my $interface_mode = $lconfighash{$key}[36];
341
624615ee
LS
342 print CONF "conn $lconfighash{$key}[1]\n";
343 print CONF "\tleft=$localside\n";
b01c17e9
MT
344
345 if ($interface_mode eq "gre") {
90aa4f10 346 print CONF "\tleftprotoport=gre\n";
b01c17e9
MT
347 } elsif ($interface_mode eq "vti") {
348 print CONF "\tleftsubnet=0.0.0.0/0\n";
349 } else {
f2d45a45 350 print CONF "\tleftsubnet=" . &make_subnets("left", $lconfighash{$key}[8]) . "\n";
b01c17e9
MT
351 }
352
624615ee
LS
353 print CONF "\tleftfirewall=yes\n";
354 print CONF "\tlefthostaccess=yes\n";
9f374222
MT
355
356 # Always send the host certificate
357 if ($lconfighash{$key}[3] eq 'host') {
358 print CONF "\tleftsendcert=always\n";
359 }
360
624615ee
LS
361 print CONF "\tright=$lconfighash{$key}[10]\n";
362
363 if ($lconfighash{$key}[3] eq 'net') {
b01c17e9 364 if ($interface_mode eq "gre") {
90aa4f10 365 print CONF "\trightprotoport=gre\n";
b01c17e9
MT
366 } elsif ($interface_mode eq "vti") {
367 print CONF "\trightsubnet=0.0.0.0/0\n";
368 } else {
f2d45a45 369 print CONF "\trightsubnet=" . &make_subnets("right", $lconfighash{$key}[11]) . "\n";
b01c17e9 370 }
624615ee 371 }
e8b3bb0e 372
624615ee
LS
373 # Local Cert and Remote Cert (unless auth is DN dn-auth)
374 if ($lconfighash{$key}[4] eq 'cert') {
375 print CONF "\tleftcert=${General::swroot}/certs/hostcert.pem\n";
376 print CONF "\trightcert=${General::swroot}/certs/$lconfighash{$key}[1]cert.pem\n" if ($lconfighash{$key}[2] ne '%auth-dn');
ed84e8b8 377 }
ed84e8b8 378
624615ee
LS
379 # Local and Remote IDs
380 print CONF "\tleftid=\"$lconfighash{$key}[7]\"\n" if ($lconfighash{$key}[7]);
381 print CONF "\trightid=\"$lconfighash{$key}[9]\"\n" if ($lconfighash{$key}[9]);
126246a8 382
326728d5
MT
383 # Set mode
384 if ($lconfighash{$key}[35] eq "transport") {
385 print CONF "\ttype=transport\n";
386 } else {
387 print CONF "\ttype=tunnel\n";
388 }
389
b01c17e9
MT
390 # Add mark for VTI
391 if ($interface_mode eq "vti") {
392 print CONF "\tmark=$key\n";
393 }
394
624615ee
LS
395 # Is PFS enabled?
396 my $pfs = $lconfighash{$key}[28] eq 'on' ? 'on' : 'off';
ed84e8b8 397
624615ee
LS
398 # Algorithms
399 if ($lconfighash{$key}[18] && $lconfighash{$key}[19] && $lconfighash{$key}[20]) {
400 my @encs = split('\|', $lconfighash{$key}[18]);
401 my @ints = split('\|', $lconfighash{$key}[19]);
402 my @groups = split('\|', $lconfighash{$key}[20]);
ed84e8b8 403
624615ee
LS
404 my @algos = &make_algos("ike", \@encs, \@ints, \@groups, 1);
405 print CONF "\tike=" . join(",", @algos);
406
407 if ($lconfighash{$key}[24] eq 'on') { #only proposed algorythms?
408 print CONF "!\n";
409 } else {
410 print CONF "\n";
411 }
412 }
413
414 if ($lconfighash{$key}[21] && $lconfighash{$key}[22]) {
415 my @encs = split('\|', $lconfighash{$key}[21]);
416 my @ints = split('\|', $lconfighash{$key}[22]);
417 my @groups = split('\|', $lconfighash{$key}[23]);
418
419 # Use IKE grouptype if no ESP group type has been selected
420 # (for backwards compatibility)
421 if ($lconfighash{$key}[23] eq "") {
422 @groups = split('\|', $lconfighash{$key}[20]);
423 }
f6529a04 424
624615ee
LS
425 my @algos = &make_algos("esp", \@encs, \@ints, \@groups, ($pfs eq "on"));
426 print CONF "\tesp=" . join(",", @algos);
afd5d8f7 427
624615ee
LS
428 if ($lconfighash{$key}[24] eq 'on') { #only proposed algorythms?
429 print CONF "!\n";
430 } else {
431 print CONF "\n";
432 }
afd5d8f7 433 }
ac1cfefa 434
624615ee
LS
435 # IKE V1 or V2
436 if (! $lconfighash{$key}[29]) {
437 $lconfighash{$key}[29] = "ikev1";
438 }
a4737620 439
624615ee 440 print CONF "\tkeyexchange=$lconfighash{$key}[29]\n";
a4737620 441
624615ee
LS
442 # Lifetimes
443 print CONF "\tikelifetime=$lconfighash{$key}[16]h\n" if ($lconfighash{$key}[16]);
444 print CONF "\tkeylife=$lconfighash{$key}[17]h\n" if ($lconfighash{$key}[17]);
445
446 # Compression
447 print CONF "\tcompress=yes\n" if ($lconfighash{$key}[13] eq 'on');
448
449 # Force MOBIKE?
450 if (($lconfighash{$key}[29] eq "ikev2") && ($lconfighash{$key}[32] eq 'on')) {
451 print CONF "\tmobike=yes\n";
452 }
453
454 # Dead Peer Detection
455 my $dpdaction = $lconfighash{$key}[27];
456 print CONF "\tdpdaction=$dpdaction\n";
457
458 # If the dead peer detection is disabled and IKEv2 is used,
459 # dpddelay must be set to zero, too.
460 if ($dpdaction eq "none") {
461 if ($lconfighash{$key}[29] eq "ikev2") {
462 print CONF "\tdpddelay=0\n";
463 }
464 } else {
465 my $dpddelay = $lconfighash{$key}[31];
466 if (!$dpddelay) {
467 $dpddelay = 30;
468 }
469 print CONF "\tdpddelay=$dpddelay\n";
470 my $dpdtimeout = $lconfighash{$key}[30];
471 if (!$dpdtimeout) {
472 $dpdtimeout = 120;
473 }
474 print CONF "\tdpdtimeout=$dpdtimeout\n";
475 }
476
477 # Build Authentication details: LEFTid RIGHTid : PSK psk
478 my $psk_line;
479 if ($lconfighash{$key}[4] eq 'psk') {
480 $psk_line = ($lconfighash{$key}[7] ? $lconfighash{$key}[7] : $localside) . " " ;
481 $psk_line .= $lconfighash{$key}[9] ? $lconfighash{$key}[9] : $lconfighash{$key}[10]; #remoteid or remote address?
482 $psk_line .= " : PSK '$lconfighash{$key}[5]'\n";
483 # if the line contains %any, it is less specific than two IP or ID, so move it at end of file.
484 if ($psk_line =~ /%any/) {
485 $last_secrets .= $psk_line;
486 } else {
487 print SECRETS $psk_line;
488 }
489 print CONF "\tauthby=secret\n";
490 } else {
491 print CONF "\tauthby=rsasig\n";
492 print CONF "\tleftrsasigkey=%cert\n";
493 print CONF "\trightrsasigkey=%cert\n";
494 }
495
dcb406cc
MT
496 my $start_action = $lconfighash{$key}[33];
497 if (!$start_action) {
498 $start_action = "start";
499 }
500
af183eeb
MT
501 my $inactivity_timeout = $lconfighash{$key}[34];
502 if ($inactivity_timeout eq "") {
503 $inactivity_timeout = 900;
504 }
505
624615ee
LS
506 # Automatically start only if a net-to-net connection
507 if ($lconfighash{$key}[3] eq 'host') {
508 print CONF "\tauto=add\n";
509 print CONF "\trightsourceip=$lvpnsettings{'RW_NET'}\n";
510 } else {
dcb406cc 511 print CONF "\tauto=$start_action\n";
1ee1666e
MT
512
513 # If in on-demand mode, we terminate the tunnel
514 # after 15 min of no traffic
af183eeb
MT
515 if ($start_action eq 'route' && $inactivity_timeout > 0) {
516 print CONF "\tinactivity=$inactivity_timeout\n";
1ee1666e 517 }
624615ee
LS
518 }
519
520 # Fragmentation
521 print CONF "\tfragmentation=yes\n";
522
dccd7e87
MT
523 # DNS Servers for RW
524 if ($lconfighash{$key}[3] eq 'host') {
525 my @servers = split(/\|/, $lconfighash{$key}[39]);
526
527 print CONF "\trightdns=" . join(",", @servers) . "\n";
528 }
529
624615ee
LS
530 print CONF "\n";
531 } #foreach key
532
533 # Add post user includes to config file
534 # After the GUI-connections allows to patch connections.
535 if (-e "/etc/ipsec.user-post.conf") {
536 print CONF "include /etc/ipsec.user-post.conf\n";
537 print CONF "\n";
538 }
539
540 print SECRETS $last_secrets if ($last_secrets);
541 close(CONF);
542 close(SECRETS);
ac1cfefa
MT
543}
544
ae2782ba
MT
545# Hook to regenerate the configuration files.
546if ($ENV{"REMOTE_ADDR"} eq "") {
26dfc86a 547 writeipsecfiles();
ae2782ba
MT
548 exit(0);
549}
550
ac1cfefa
MT
551###
552### Save main settings
553###
554if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq '' && $cgiparams{'KEY'} eq '') {
624615ee
LS
555 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
556
c7fe09c6
MT
557 if ($cgiparams{'RW_ENDPOINT'} ne '' && !&General::validip($cgiparams{'RW_ENDPOINT'}) && !&General::validfqdn($cgiparams{'RW_ENDPOINT'})) {
558 $errormessage = $Lang::tr{'ipsec invalid ip address or fqdn for rw endpoint'};
559 goto SAVE_ERROR;
560 }
561
624615ee
LS
562 if ( $cgiparams{'RW_NET'} ne '' and !&General::validipandmask($cgiparams{'RW_NET'}) ) {
563 $errormessage = $Lang::tr{'urlfilter invalid ip or mask error'};
564 goto SAVE_ERROR;
565 }
566
567 $vpnsettings{'ENABLED'} = $cgiparams{'ENABLED'};
c7fe09c6 568 $vpnsettings{'RW_ENDPOINT'} = $cgiparams{'RW_ENDPOINT'};
624615ee
LS
569 $vpnsettings{'RW_NET'} = $cgiparams{'RW_NET'};
570 &General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
571 &writeipsecfiles();
572 if (&vpnenabled) {
d22c7c10 573 &General::system('/usr/local/bin/ipsecctrl', 'S');
624615ee 574 } else {
d22c7c10 575 &General::system('/usr/local/bin/ipsecctrl', 'D');
624615ee
LS
576 }
577 sleep $sleepDelay;
578 SAVE_ERROR:
ac1cfefa
MT
579###
580### Reset all step 2
581###
ed84e8b8 582} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'} && $cgiparams{'AREUSURE'} eq 'yes') {
624615ee
LS
583 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
584
585 foreach my $key (keys %confighash) {
586 if ($confighash{$key}[4] eq 'cert') {
587 delete $confighash{$key};
588 }
589 }
590 while (my $file = glob("${General::swroot}/{ca,certs,crls,private}/*")) {
591 unlink $file
592 }
593 &cleanssldatabase();
594 if (open(FILE, ">${General::swroot}/vpn/caconfig")) {
595 print FILE "";
596 close FILE;
597 }
598 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
599 &writeipsecfiles();
a81cbf61 600 &General::system('/usr/local/bin/ipsecctrl', 'R');
624615ee 601 sleep $sleepDelay;
ac1cfefa
MT
602
603###
604### Reset all step 1
605###
ed84e8b8 606} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'}) {
624615ee
LS
607 &Header::showhttpheaders();
608 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
609 &Header::openbigbox('100%', 'left', '', '');
610 &Header::openbox('100%', 'left', $Lang::tr{'are you sure'});
611 print <<END
ed84e8b8 612 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
624615ee
LS
613 <table width='100%'>
614 <tr>
615 <td align='center'>
616 <input type='hidden' name='AREUSURE' value='yes' />
617 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:&nbsp;$Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}
618 </td>
619 </tr><tr>
620 <td align='center'>
621 <input type='submit' name='ACTION' value='$Lang::tr{'remove x509'}' />
ed84e8b8 622 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
624615ee
LS
623 </tr>
624 </table>
ed84e8b8 625 </form>
ac1cfefa 626END
624615ee
LS
627;
628 &Header::closebox();
629 &Header::closebigbox();
630 &Header::closepage();
631 exit (0);
ac1cfefa
MT
632
633###
634### Upload CA Certificate
635###
636} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload ca certificate'}) {
624615ee
LS
637 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
638
639 if ($cgiparams{'CA_NAME'} !~ /^[a-zA-Z0-9]+$/) {
640 $errormessage = $Lang::tr{'name must only contain characters'};
641 goto UPLOADCA_ERROR;
642 }
643
644 if (length($cgiparams{'CA_NAME'}) >60) {
645 $errormessage = $Lang::tr{'name too long'};
646 goto VPNCONF_ERROR;
647 }
648
649 if ($cgiparams{'CA_NAME'} eq 'ca') {
650 $errormessage = $Lang::tr{'name is invalid'};
651 goto UPLOAD_CA_ERROR;
652 }
653
654 # Check if there is no other entry with this name
655 foreach my $key (keys %cahash) {
656 if ($cahash{$key}[0] eq $cgiparams{'CA_NAME'}) {
657 $errormessage = $Lang::tr{'a ca certificate with this name already exists'};
658 goto UPLOADCA_ERROR;
659 }
660 }
661
2ad1b18b 662 unless (ref ($cgiparams{'FH'})) {
624615ee
LS
663 $errormessage = $Lang::tr{'there was no file upload'};
664 goto UPLOADCA_ERROR;
665 }
666 # Move uploaded ca to a temporary file
667 (my $fh, my $filename) = tempfile( );
668 if (copy ($cgiparams{'FH'}, $fh) != 1) {
669 $errormessage = $!;
670 goto UPLOADCA_ERROR;
671 }
b71a7fb9
MT
672 my $temp = `/usr/bin/openssl x509 -text -in $filename`;
673 if ($temp !~ /CA:TRUE/i) {
624615ee
LS
674 $errormessage = $Lang::tr{'not a valid ca certificate'};
675 unlink ($filename);
676 goto UPLOADCA_ERROR;
677 } else {
b5b19f37 678 unless(move($filename, "${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem")) {
624615ee
LS
679 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
680 unlink ($filename);
681 goto UPLOADCA_ERROR;
682 }
683 }
684
685 my $key = &General::findhasharraykey (\%cahash);
686 $cahash{$key}[0] = $cgiparams{'CA_NAME'};
687 $cahash{$key}[1] = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem"));
688 &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
689
a81cbf61 690 &General::system('/usr/local/bin/ipsecctrl', 'R');
624615ee
LS
691 sleep $sleepDelay;
692
693 UPLOADCA_ERROR:
ac1cfefa
MT
694
695###
696### Display ca certificate
697###
698} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show ca certificate'}) {
624615ee
LS
699 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
700
701 if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem") {
702 &Header::showhttpheaders();
703 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
704 &Header::openbigbox('100%', 'left', '', '');
705 &Header::openbox('100%', 'left', "$Lang::tr{'ca certificate'}:");
a81cbf61 706 my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
c64dc3be
MT
707 my $output = &Header::cleanhtml(join("", @output) ,"y");
708 print "<pre>$output</pre>\n";
624615ee
LS
709 &Header::closebox();
710 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
711 &Header::closebigbox();
712 &Header::closepage();
713 exit(0);
714 } else {
715 $errormessage = $Lang::tr{'invalid key'};
716 }
ac1cfefa
MT
717
718###
ed84e8b8 719### Export ca certificate to browser
ac1cfefa
MT
720###
721} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download ca certificate'}) {
624615ee
LS
722 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
723
724 if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
725 print "Content-Type: application/force-download\n";
726 print "Content-Type: application/octet-stream\r\n";
727 print "Content-Disposition: attachment; filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
a81cbf61
SS
728
729 my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
730 print "@cert";
624615ee
LS
731 exit(0);
732 } else {
733 $errormessage = $Lang::tr{'invalid key'};
734 }
ac1cfefa
MT
735
736###
737### Remove ca certificate (step 2)
738###
739} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'} && $cgiparams{'AREUSURE'} eq 'yes') {
624615ee
LS
740 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
741 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
742
743 if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
744 foreach my $key (keys %confighash) {
a81cbf61
SS
745 my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/certs/$confighash{$key}[1]cert.pem");
746 if (grep(/: OK/, @test)) {
624615ee 747 # Delete connection
624615ee
LS
748 unlink ("${General::swroot}/certs/$confighash{$key}[1]cert.pem");
749 unlink ("${General::swroot}/certs/$confighash{$key}[1].p12");
750 delete $confighash{$key};
751 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
752 &writeipsecfiles();
a81cbf61 753 &General::system('/usr/local/bin/ipsecctrl', 'D', $key) if (&vpnenabled);
624615ee
LS
754 }
755 }
756 unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
757 delete $cahash{$cgiparams{'KEY'}};
758 &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
a81cbf61 759 &General::system('/usr/local/bin/ipsecctrl', 'R');
624615ee
LS
760 sleep $sleepDelay;
761 } else {
762 $errormessage = $Lang::tr{'invalid key'};
ac1cfefa 763 }
ac1cfefa
MT
764###
765### Remove ca certificate (step 1)
766###
767} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'}) {
624615ee
LS
768 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
769 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
770
771 my $assignedcerts = 0;
772 if ( -f "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
773 foreach my $key (keys %confighash) {
a81cbf61
SS
774 my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/certs/$confighash{$key}[1]cert.pem");
775 if (grep(/: OK/, @test)) {
624615ee
LS
776 $assignedcerts++;
777 }
778 }
779 if ($assignedcerts) {
780 &Header::showhttpheaders();
781 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
782 &Header::openbigbox('100%', 'left', '', '');
783 &Header::openbox('100%', 'left', $Lang::tr{'are you sure'});
784 print <<END
785 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
786 <table width='100%'>
787 <tr>
788 <td align='center'>
789 <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
790 <input type='hidden' name='AREUSURE' value='yes' /></td>
791 </tr><tr>
792 <td align='center'>
793 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>&nbsp;$Lang::tr{'connections are associated with this ca. deleting the ca will delete these connections as well.'}</td>
794 </tr><tr>
795 <td align='center'>
796 <input type='submit' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
797 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
798 </tr>
799 </table>
800 </form>
ac1cfefa 801END
624615ee
LS
802;
803 &Header::closebox();
804 &Header::closebigbox();
805 &Header::closepage();
806 exit (0);
807 } else {
808 unlink ("${General::swroot}/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
809 delete $cahash{$cgiparams{'KEY'}};
810 &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
a81cbf61 811 &General::system('/usr/local/bin/ipsecctrl', 'R');
624615ee
LS
812 sleep $sleepDelay;
813 }
ac1cfefa 814 } else {
624615ee 815 $errormessage = $Lang::tr{'invalid key'};
ac1cfefa 816 }
ac1cfefa
MT
817
818###
819### Display root certificate
820###
821} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'} ||
822 $cgiparams{'ACTION'} eq $Lang::tr{'show host certificate'}) {
a81cbf61 823 my @output;
624615ee
LS
824 &Header::showhttpheaders();
825 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
826 &Header::openbigbox('100%', 'left', '', '');
827 if ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'}) {
828 &Header::openbox('100%', 'left', "$Lang::tr{'root certificate'}:");
a81cbf61 829 @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ca/cacert.pem");
624615ee
LS
830 } else {
831 &Header::openbox('100%', 'left', "$Lang::tr{'host certificate'}:");
a81cbf61 832 @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/certs/hostcert.pem");
624615ee 833 }
c64dc3be
MT
834 my $output = &Header::cleanhtml(join("", @output) ,"y");
835 print "<pre>$output</pre>\n";
624615ee
LS
836 &Header::closebox();
837 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
838 &Header::closebigbox();
839 &Header::closepage();
840 exit(0);
ac1cfefa
MT
841
842###
ed84e8b8 843### Export root certificate to browser
ac1cfefa
MT
844###
845} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download root certificate'}) {
624615ee
LS
846 if ( -f "${General::swroot}/ca/cacert.pem" ) {
847 print "Content-Type: application/force-download\n";
848 print "Content-Disposition: attachment; filename=cacert.pem\r\n\r\n";
a81cbf61
SS
849
850 my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ca/cacert.pem");
6688e0bc 851 print join("", @cert);
624615ee
LS
852 exit(0);
853 }
ac1cfefa 854###
ed84e8b8 855### Export host certificate to browser
ac1cfefa
MT
856###
857} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download host certificate'}) {
624615ee
LS
858 if ( -f "${General::swroot}/certs/hostcert.pem" ) {
859 print "Content-Type: application/force-download\n";
860 print "Content-Disposition: attachment; filename=hostcert.pem\r\n\r\n";
a81cbf61
SS
861
862 my @cert = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/certs/hostcert.pem");
6688e0bc 863 print join("", @cert);
624615ee
LS
864 exit(0);
865 }
ac1cfefa 866###
ed84e8b8 867### Form for generating/importing the caroot+host certificate
ac1cfefa
MT
868###
869} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate root/host certificates'} ||
624615ee
LS
870 $cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
871
872 if (-f "${General::swroot}/ca/cacert.pem") {
873 $errormessage = $Lang::tr{'valid root certificate already exists'};
874 goto ROOTCERT_SKIP;
875 }
876
877 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
878 # fill in initial values
879 if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
880 if (-e "${General::swroot}/red/active" && open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
881 my $ipaddr = <IPADDR>;
882 close IPADDR;
883 chomp ($ipaddr);
884 $cgiparams{'ROOTCERT_HOSTNAME'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
993724b4 885 $cgiparams{'SUBJECTALTNAME'} = "DNS:" . $cgiparams{'ROOTCERT_HOSTNAME'};
624615ee
LS
886 if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
887 $cgiparams{'ROOTCERT_HOSTNAME'} = $ipaddr;
993724b4 888 $cgiparams{'SUBJECTALTNAME'} = "IP:" . $cgiparams{'ROOTCERT_HOSTNAME'};
624615ee
LS
889 }
890 }
891 $cgiparams{'ROOTCERT_COUNTRY'} = $vpnsettings{'ROOTCERT_COUNTRY'} if (!$cgiparams{'ROOTCERT_COUNTRY'});
892 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
893 &General::log("ipsec", "Importing from p12...");
ac1cfefa 894
2ad1b18b 895 unless (ref ($cgiparams{'FH'})) {
624615ee
LS
896 $errormessage = $Lang::tr{'there was no file upload'};
897 goto ROOTCERT_ERROR;
898 }
ac1cfefa 899
624615ee
LS
900 # Move uploaded certificate request to a temporary file
901 (my $fh, my $filename) = tempfile( );
902 if (copy ($cgiparams{'FH'}, $fh) != 1) {
903 $errormessage = $!;
904 goto ROOTCERT_ERROR;
905 }
ac1cfefa 906
624615ee
LS
907 # Extract the CA certificate from the file
908 &General::log("ipsec", "Extracting caroot from p12...");
909 if (open(STDIN, "-|")) {
910 my $opt = " pkcs12 -cacerts -nokeys";
911 $opt .= " -in $filename";
912 $opt .= " -out /tmp/newcacert";
913 $errormessage = &callssl ($opt);
914 } else { #child
915 print "$cgiparams{'P12_PASS'}\n";
916 exit (0);
917 }
ac1cfefa 918
624615ee
LS
919 # Extract the Host certificate from the file
920 if (!$errormessage) {
921 &General::log("ipsec", "Extracting host cert from p12...");
922 if (open(STDIN, "-|")) {
923 my $opt = " pkcs12 -clcerts -nokeys";
924 $opt .= " -in $filename";
925 $opt .= " -out /tmp/newhostcert";
926 $errormessage = &callssl ($opt);
927 } else { #child
928 print "$cgiparams{'P12_PASS'}\n";
929 exit (0);
930 }
931 }
ed84e8b8 932
624615ee
LS
933 # Extract the Host key from the file
934 if (!$errormessage) {
935 &General::log("ipsec", "Extracting private key from p12...");
936 if (open(STDIN, "-|")) {
937 my $opt = " pkcs12 -nocerts -nodes";
938 $opt .= " -in $filename";
939 $opt .= " -out /tmp/newhostkey";
940 $errormessage = &callssl ($opt);
941 } else { #child
942 print "$cgiparams{'P12_PASS'}\n";
943 exit (0);
944 }
945 }
ac1cfefa 946
624615ee
LS
947 if (!$errormessage) {
948 &General::log("ipsec", "Moving cacert...");
b5b19f37
SS
949 unless(move("/tmp/newcacert", "${General::swroot}/ca/cacert.pem")) {
950 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
951 }
624615ee 952 }
ed84e8b8 953
624615ee
LS
954 if (!$errormessage) {
955 &General::log("ipsec", "Moving host cert...");
b5b19f37
SS
956 unless(move("/tmp/newhostcert", "${General::swroot}/certs/hostcert.pem")) {
957 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
958 }
624615ee 959 }
ed84e8b8 960
624615ee
LS
961 if (!$errormessage) {
962 &General::log("ipsec", "Moving private key...");
b5b19f37
SS
963 unless(move("/tmp/newhostkey", "${General::swroot}/certs/hostkey.pem")) {
964 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
965 }
624615ee
LS
966 }
967
968 #cleanup temp files
969 unlink ($filename);
970 unlink ('/tmp/newcacert');
971 unlink ('/tmp/newhostcert');
972 unlink ('/tmp/newhostkey');
973 if ($errormessage) {
974 unlink ("${General::swroot}/ca/cacert.pem");
975 unlink ("${General::swroot}/certs/hostcert.pem");
976 unlink ("${General::swroot}/certs/hostkey.pem");
977 goto ROOTCERT_ERROR;
978 }
979
980 # Create empty CRL cannot be done because we don't have
981 # the private key for this CAROOT
982 # IPFire can only import certificates
983
984 &General::log("ipsec", "p12 import completed!");
985 &cleanssldatabase();
986 goto ROOTCERT_SUCCESS;
987
988 } elsif ($cgiparams{'ROOTCERT_COUNTRY'} ne '') {
989
990 # Validate input since the form was submitted
991 if ($cgiparams{'ROOTCERT_ORGANIZATION'} eq ''){
992 $errormessage = $Lang::tr{'organization cant be empty'};
993 goto ROOTCERT_ERROR;
994 }
995 if (length($cgiparams{'ROOTCERT_ORGANIZATION'}) >60) {
996 $errormessage = $Lang::tr{'organization too long'};
997 goto ROOTCERT_ERROR;
998 }
999 if ($cgiparams{'ROOTCERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1000 $errormessage = $Lang::tr{'invalid input for organization'};
1001 goto ROOTCERT_ERROR;
1002 }
1003 if ($cgiparams{'ROOTCERT_HOSTNAME'} eq ''){
1004 $errormessage = $Lang::tr{'hostname cant be empty'};
1005 goto ROOTCERT_ERROR;
1006 }
1007 unless (&General::validfqdn($cgiparams{'ROOTCERT_HOSTNAME'}) || &General::validip($cgiparams{'ROOTCERT_HOSTNAME'})) {
1008 $errormessage = $Lang::tr{'invalid input for hostname'};
1009 goto ROOTCERT_ERROR;
1010 }
1011 if ($cgiparams{'ROOTCERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'ROOTCERT_EMAIL'}))) {
1012 $errormessage = $Lang::tr{'invalid input for e-mail address'};
1013 goto ROOTCERT_ERROR;
1014 }
1015 if (length($cgiparams{'ROOTCERT_EMAIL'}) > 40) {
1016 $errormessage = $Lang::tr{'e-mail address too long'};
1017 goto ROOTCERT_ERROR;
1018 }
1019 if ($cgiparams{'ROOTCERT_OU'} ne '' && $cgiparams{'ROOTCERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1020 $errormessage = $Lang::tr{'invalid input for department'};
1021 goto ROOTCERT_ERROR;
1022 }
1023 if ($cgiparams{'ROOTCERT_CITY'} ne '' && $cgiparams{'ROOTCERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1024 $errormessage = $Lang::tr{'invalid input for city'};
1025 goto ROOTCERT_ERROR;
1026 }
1027 if ($cgiparams{'ROOTCERT_STATE'} ne '' && $cgiparams{'ROOTCERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1028 $errormessage = $Lang::tr{'invalid input for state or province'};
1029 goto ROOTCERT_ERROR;
1030 }
1031 if ($cgiparams{'ROOTCERT_COUNTRY'} !~ /^[A-Z]*$/) {
1032 $errormessage = $Lang::tr{'invalid input for country'};
1033 goto ROOTCERT_ERROR;
1034 }
1035 #the exact syntax is a list comma separated of
1036 # email:any-validemail
1037 # URI: a uniform resource indicator
1038 # DNS: a DNS domain name
1039 # RID: a registered OBJECT IDENTIFIER
1040 # IP: an IP address
1041 # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
1042
993724b4
PM
1043 if ($cgiparams{'SUBJECTALTNAME'} eq '') {
1044 $errormessage = $Lang::tr{'vpn subjectaltname missing'};
1045 goto ROOTCERT_ERROR;
1046 }
1047
624615ee
LS
1048 if ($cgiparams{'SUBJECTALTNAME'} ne '' && $cgiparams{'SUBJECTALTNAME'} !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/,\.\-_@]*$/) {
1049 $errormessage = $Lang::tr{'vpn altname syntax'};
1050 goto VPNCONF_ERROR;
1051 }
1052
1053 # Copy the cgisettings to vpnsettings and save the configfile
1054 $vpnsettings{'ROOTCERT_ORGANIZATION'} = $cgiparams{'ROOTCERT_ORGANIZATION'};
1055 $vpnsettings{'ROOTCERT_HOSTNAME'} = $cgiparams{'ROOTCERT_HOSTNAME'};
1056 $vpnsettings{'ROOTCERT_EMAIL'} = $cgiparams{'ROOTCERT_EMAIL'};
1057 $vpnsettings{'ROOTCERT_OU'} = $cgiparams{'ROOTCERT_OU'};
1058 $vpnsettings{'ROOTCERT_CITY'} = $cgiparams{'ROOTCERT_CITY'};
1059 $vpnsettings{'ROOTCERT_STATE'} = $cgiparams{'ROOTCERT_STATE'};
1060 $vpnsettings{'ROOTCERT_COUNTRY'} = $cgiparams{'ROOTCERT_COUNTRY'};
1061 &General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
1062
1063 # Replace empty strings with a .
1064 (my $ou = $cgiparams{'ROOTCERT_OU'}) =~ s/^\s*$/\./;
1065 (my $city = $cgiparams{'ROOTCERT_CITY'}) =~ s/^\s*$/\./;
1066 (my $state = $cgiparams{'ROOTCERT_STATE'}) =~ s/^\s*$/\./;
1067
1068 # Create the CA certificate
1069 if (!$errormessage) {
1070 &General::log("ipsec", "Creating cacert...");
1071 if (open(STDIN, "-|")) {
1072 my $opt = " req -x509 -sha256 -nodes";
926e5519 1073 $opt .= " -days 3650";
624615ee
LS
1074 $opt .= " -newkey rsa:4096";
1075 $opt .= " -keyout ${General::swroot}/private/cakey.pem";
1076 $opt .= " -out ${General::swroot}/ca/cacert.pem";
1077
1078 $errormessage = &callssl ($opt);
1079 } else { #child
1080 print "$cgiparams{'ROOTCERT_COUNTRY'}\n";
1081 print "$state\n";
1082 print "$city\n";
1083 print "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
1084 print "$ou\n";
1085 print "$cgiparams{'ROOTCERT_ORGANIZATION'} CA\n";
1086 print "$cgiparams{'ROOTCERT_EMAIL'}\n";
1087 exit (0);
1088 }
1089 }
1090
1091 # Create the Host certificate request
1092 if (!$errormessage) {
1093 &General::log("ipsec", "Creating host cert...");
1094 if (open(STDIN, "-|")) {
1095 my $opt = " req -sha256 -nodes";
1096 $opt .= " -newkey rsa:2048";
1097 $opt .= " -keyout ${General::swroot}/certs/hostkey.pem";
1098 $opt .= " -out ${General::swroot}/certs/hostreq.pem";
1099 $errormessage = &callssl ($opt);
1100 } else { #child
1101 print "$cgiparams{'ROOTCERT_COUNTRY'}\n";
1102 print "$state\n";
1103 print "$city\n";
1104 print "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
1105 print "$ou\n";
1106 print "$cgiparams{'ROOTCERT_HOSTNAME'}\n";
1107 print "$cgiparams{'ROOTCERT_EMAIL'}\n";
1108 print ".\n";
1109 print ".\n";
1110 exit (0);
1111 }
1112 }
1113
1114 # Sign the host certificate request
1115 if (!$errormessage) {
1116 &General::log("ipsec", "Self signing host cert...");
1117
1118 #No easy way for specifying the contain of subjectAltName without writing a config file...
1119 my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
1120 print $fh <<END
1121 basicConstraints=CA:FALSE
1122 nsComment="OpenSSL Generated Certificate"
1123 subjectKeyIdentifier=hash
1124 authorityKeyIdentifier=keyid,issuer:always
1125 extendedKeyUsage = serverAuth
ed84e8b8
MT
1126END
1127;
624615ee
LS
1128 print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
1129 close ($fh);
1130
926e5519 1131 my $opt = " ca -md sha256 -days 825";
624615ee
LS
1132 $opt .= " -batch -notext";
1133 $opt .= " -in ${General::swroot}/certs/hostreq.pem";
1134 $opt .= " -out ${General::swroot}/certs/hostcert.pem";
1135 $opt .= " -extfile $v3extname";
1136 $errormessage = &callssl ($opt);
1137 unlink ("${General::swroot}/certs/hostreq.pem"); #no more needed
1138 unlink ($v3extname);
1139 }
1140
1141 # Create an empty CRL
1142 if (!$errormessage) {
1143 &General::log("ipsec", "Creating emptycrl...");
1144 my $opt = " ca -gencrl";
1145 $opt .= " -out ${General::swroot}/crls/cacrl.pem";
1146 $errormessage = &callssl ($opt);
1147 }
1148
1149 # Successfully build CA / CERT!
1150 if (!$errormessage) {
1151 &cleanssldatabase();
1152 goto ROOTCERT_SUCCESS;
1153 }
1154
1155 #Cleanup
1156 unlink ("${General::swroot}/ca/cacert.pem");
1157 unlink ("${General::swroot}/certs/hostkey.pem");
1158 unlink ("${General::swroot}/certs/hostcert.pem");
1159 unlink ("${General::swroot}/crls/cacrl.pem");
1160 &cleanssldatabase();
1161 }
1162
1163 ROOTCERT_ERROR:
1164 &Header::showhttpheaders();
1165 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
1166 &Header::openbigbox('100%', 'left', '', $errormessage);
1167 if ($errormessage) {
1168 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
1169 print "<class name='base'>$errormessage";
1170 print "&nbsp;</class>";
1171 &Header::closebox();
1172 }
1173 &Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
1174 print <<END
1175 <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
1176 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
1177 <tr><td width='40%' class='base'>$Lang::tr{'organization name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1178 <td width='60%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td></tr>
1179 <tr><td class='base'>$Lang::tr{'ipfires hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1180 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td></tr>
1181 <tr><td class='base'>$Lang::tr{'your e-mail'}:</td>
1182 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td></tr>
1183 <tr><td class='base'>$Lang::tr{'your department'}:</td>
1184 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td></tr>
1185 <tr><td class='base'>$Lang::tr{'city'}:</td>
1186 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td></tr>
1187 <tr><td class='base'>$Lang::tr{'state or province'}:</td>
1188 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td></tr>
1189 <tr><td class='base'>$Lang::tr{'country'}:</td>
1190 <td class='base'><select name='ROOTCERT_COUNTRY'>
ac1cfefa 1191END
624615ee
LS
1192;
1193 foreach my $country (sort keys %{Countries::countries}) {
1194 print "<option value='$Countries::countries{$country}'";
1195 if ( $Countries::countries{$country} eq $cgiparams{'ROOTCERT_COUNTRY'} ) {
1196 print " selected='selected'";
1197 }
1198 print ">$country</option>";
1199 }
1200 print <<END
1201 </select></td></tr>
993724b4 1202 <tr><td class='base'>$Lang::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*)&nbsp;<img src='/blob.gif' alt='*' /></td>
ed84e8b8 1203 <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value='$cgiparams{'SUBJECTALTNAME'}' size='32' /></td></tr>
624615ee
LS
1204 <tr><td>&nbsp;</td>
1205 <td><br /><input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' /><br /><br /></td></tr>
1206 <tr><td class='base' colspan='2' align='left'>
1207 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:
1208 $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'}
1209 </td></tr>
1210 <tr><td colspan='2'><hr></td></tr>
1211 <tr><td class='base' nowrap='nowrap'>$Lang::tr{'upload p12 file'}:</td>
1212 <td nowrap='nowrap'><input type='file' name='FH' size='32' /></td></tr>
1213 <tr><td class='base'>$Lang::tr{'pkcs12 file password'}:</td>
1214 <td class='base' nowrap='nowrap'><input type='password' name='P12_PASS' value='$cgiparams{'P12_PASS'}' size='32' /></td></tr>
1215 <tr><td>&nbsp;</td>
1216 <td><input type='submit' name='ACTION' value='$Lang::tr{'upload p12 file'}' /></td></tr>
1217 <tr><td class='base' colspan='2' align='left'>
1218 <img src='/blob.gif' alt='*' />&nbsp;$Lang::tr{'required field'}</td></tr>
1219 </table></form>
ed84e8b8 1220END
624615ee
LS
1221;
1222 &Header::closebox();
1223 &Header::closebigbox();
1224 &Header::closepage();
1225 exit(0);
1226
1227 ROOTCERT_SUCCESS:
1228 if (&vpnenabled) {
a81cbf61 1229 &General::system('/usr/local/bin/ipsecctrl', 'S');
624615ee
LS
1230 sleep $sleepDelay;
1231 }
1232 ROOTCERT_SKIP:
ac1cfefa 1233###
ed84e8b8 1234### Export PKCS12 file to browser
ac1cfefa
MT
1235###
1236} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download pkcs12 file'}) {
624615ee
LS
1237 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1238 print "Content-Type: application/force-download\n";
1239 print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . ".p12\r\n";
1240 print "Content-Type: application/octet-stream\r\n\r\n";
a81cbf61
SS
1241
1242 open(FILE, "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
1243 my @p12 = <FILE>;
1244 close(FILE);
f8384fbf 1245 print join("", @p12);
a81cbf61 1246
624615ee 1247 exit (0);
ac1cfefa 1248
26a0befd
MT
1249# Export Apple profile to browser
1250} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download apple profile'}) {
c7fe09c6
MT
1251 # Read global configuration
1252 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1253
1254 # Read connections
26a0befd
MT
1255 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1256 my $key = $cgiparams{'KEY'};
1257
205c3c17
MT
1258 # Create a UUID generator
1259 my $uuid = Data::UUID->new();
1260
1261 my $uuid1 = $uuid->create_str();
1262 my $uuid2 = $uuid->create_str();
26a0befd 1263
db33a122
MT
1264 my $ca = "";
1265 my $ca_uuid = $uuid->create_str();
1266
26a0befd 1267 my $cert = "";
205c3c17 1268 my $cert_uuid = $uuid->create_str();
26a0befd 1269
db33a122 1270 # Read and encode the CA & certificate
26a0befd 1271 if ($confighash{$key}[4] eq "cert") {
db33a122 1272 my $ca_path = "${General::swroot}/ca/cacert.pem";
26a0befd
MT
1273 my $cert_path = "${General::swroot}/certs/$confighash{$key}[1].p12";
1274
db33a122
MT
1275 # Read the CA and encode it into Base64
1276 open(CA, "<${ca_path}");
1277 local($/) = undef; # slurp
1278 $ca = MIME::Base64::encode_base64(<CA>);
1279 close(CA);
1280
26a0befd
MT
1281 # Read certificate and encode it into Base64
1282 open(CERT, "<${cert_path}");
1283 local($/) = undef; # slurp
1284 $cert = MIME::Base64::encode_base64(<CERT>);
1285 close(CERT);
1286 }
1287
1288 print "Content-Type: application/octet-stream\n";
1289 print "Content-Disposition: attachment; filename=" . $confighash{$key}[1] . ".mobileconfig\n";
1290 print "\n"; # end headers
1291
c7fe09c6
MT
1292 # Use our own FQDN if nothing else is configured
1293 my $endpoint = ($vpnsettings{'RW_ENDPOINT'} ne "") ? $vpnsettings{'RW_ENDPOINT'} : &hostname();
1294
26a0befd
MT
1295 print "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n";
1296 print "<plist version=\"1.0\">\n";
1297 print " <dict>\n";
1298 print " <key>PayloadDisplayName</key>\n";
1299 print " <string>$confighash{$key}[1]</string>\n";
1300 print " <key>PayloadIdentifier</key>\n";
1301 print " <string>$confighash{$key}[1]</string>\n";
1302 print " <key>PayloadUUID</key>\n";
1303 print " <string>${uuid1}</string>\n";
1304 print " <key>PayloadType</key>\n";
1305 print " <string>Configuration</string>\n";
1306 print " <key>PayloadVersion</key>\n";
1307 print " <integer>1</integer>\n";
1308 print " <key>PayloadContent</key>\n";
1309 print " <array>\n";
1310 print " <dict>\n";
1311 print " <key>PayloadIdentifier</key>\n";
1312 print " <string>org.example.vpn1.conf1</string>\n";
1313 print " <key>PayloadUUID</key>\n";
1314 print " <string>${uuid2}</string>\n";
1315 print " <key>PayloadType</key>\n";
1316 print " <string>com.apple.vpn.managed</string>\n";
1317 print " <key>PayloadVersion</key>\n";
1318 print " <integer>1</integer>\n";
1319 print " <key>UserDefinedName</key>\n";
1320 print " <string>$confighash{$key}[1]</string>\n";
1321 print " <key>VPNType</key>\n";
1322 print " <string>IKEv2</string>\n";
1323 print " <key>IKEv2</key>\n";
1324 print " <dict>\n";
1325 print " <key>RemoteAddress</key>\n";
c7fe09c6 1326 print " <string>$endpoint</string>\n";
26a0befd 1327
b75d9210
MT
1328 # PFS
1329 my $pfs = $confighash{$key}[28];
1330 if ($pfs eq "on") {
1331 print " <key>EnablePFS</key>\n";
1332 print " <true/>\n";
1333 }
1334
2d7b3347
MT
1335 # IKE Cipher Suite
1336 print " <key>IKESecurityAssociationParameters</key>\n";
1337 print " <dict>\n";
1338
1339 # Encryption
1340 foreach my $cipher (split(/\|/,$confighash{$key}[18])) {
1341 # Skip all unsupported ciphers
1342 next unless (exists $APPLE_CIPHERS{$cipher});
1343
1344 print " <key>EncryptionAlgorithm</key>\n";
1345 print " <string>$APPLE_CIPHERS{$cipher}</string>\n";
1346 last;
1347 }
1348
1349 # Integrity
1350 foreach my $integrity (split(/\|/,$confighash{$key}[19])) {
1351 # Skip all unsupported algorithms
1352 next unless (exists $APPLE_INTEGRITIES{$integrity});
1353
1354 print " <key>IntegrityAlgorithm</key>\n";
1355 print " <string>$APPLE_INTEGRITIES{$integrity}</string>\n";
1356 last;
1357 }
1358
1359 # Diffie Hellman Groups
1360 foreach my $group (split(/\|/,$confighash{$key}[20])) {
1361 # Skip all unsupported algorithms
1362 next unless (exists $APPLE_DH_GROUPS{$group});
1363
1364 print " <key>DiffieHellmanGroup</key>\n";
1365 print " <string>$APPLE_DH_GROUPS{$group}</string>\n";
1366 last;
1367 }
1368
1369 # Lifetime
1370 my $lifetime = $confighash{$key}[16] * 60;
1371 print " <key>LifeTimeInMinutes</key>\n";
1372 print " <integer>$lifetime</integer>\n";
1373 print " </dict>\n";
1374
1375 # ESP Cipher Suite
1376 print " <key>ChildSecurityAssociationParameters</key>\n";
1377 print " <dict>\n";
1378
1379 # Encryption
1380 foreach my $cipher (split(/\|/,$confighash{$key}[21])) {
1381 # Skip all unsupported ciphers
1382 next unless (exists $APPLE_CIPHERS{$cipher});
1383
1384 print " <key>EncryptionAlgorithm</key>\n";
1385 print " <string>$APPLE_CIPHERS{$cipher}</string>\n";
1386 last;
1387 }
1388
1389 # Integrity
1390 foreach my $integrity (split(/\|/,$confighash{$key}[22])) {
1391 # Skip all unsupported algorithms
1392 next unless (exists $APPLE_INTEGRITIES{$integrity});
1393
1394 print " <key>IntegrityAlgorithm</key>\n";
1395 print " <string>$APPLE_INTEGRITIES{$integrity}</string>\n";
1396 last;
1397 }
1398
1399 # Diffie Hellman Groups
1400 foreach my $group (split(/\|/,$confighash{$key}[23])) {
1401 # Skip all unsupported algorithms
1402 next unless (exists $APPLE_DH_GROUPS{$group});
1403
1404 print " <key>DiffieHellmanGroup</key>\n";
1405 print " <string>$APPLE_DH_GROUPS{$group}</string>\n";
1406 last;
1407 }
1408
1409 # Lifetime
1410 my $lifetime = $confighash{$key}[17] * 60;
1411 print " <key>LifeTimeInMinutes</key>\n";
1412 print " <integer>$lifetime</integer>\n";
1413 print " </dict>\n";
1414
1415
26a0befd
MT
1416 # Left ID
1417 if ($confighash{$key}[9]) {
1108156c
MT
1418 my $leftid = $confighash{$key}[9];
1419
1420 # Strip leading @ from FQDNs
1421 if ($leftid =~ m/^@(.*)$/) {
1422 $leftid = $1;
1423 }
1424
f3567364 1425 print " <key>LocalIdentifier</key>\n";
1108156c 1426 print " <string>$leftid</string>\n";
26a0befd
MT
1427 }
1428
1429 # Right ID
1430 if ($confighash{$key}[7]) {
1108156c
MT
1431 my $rightid = $confighash{$key}[7];
1432
1433 # Strip leading @ from FQDNs
1434 if ($rightid =~ m/^@(.*)$/) {
1435 $rightid = $1;
1436 }
1437
f3567364 1438 print " <key>RemoteIdentifier</key>\n";
1108156c 1439 print " <string>$rightid</string>\n";
26a0befd
MT
1440 }
1441
1442 if ($confighash{$key}[4] eq "cert") {
f3567364
MT
1443 print " <key>AuthenticationMethod</key>\n";
1444 print " <string>Certificate</string>\n";
26a0befd 1445
f3567364
MT
1446 print " <key>PayloadCertificateUUID</key>\n";
1447 print " <string>${cert_uuid}</string>\n";
26a0befd 1448 } else {
f3567364
MT
1449 print " <key>AuthenticationMethod</key>\n";
1450 print " <string>SharedSecret</string>\n";
1451 print " <key>SharedSecret</key>\n";
1452 print " <string>$confighash{$key}[5]</string>\n";
26a0befd
MT
1453 }
1454
1455 print " <key>ExtendedAuthEnabled</key>\n";
1456 print " <integer>0</integer>\n";
5b2e16dd 1457
08fa1272
MT
1458 # These are not needed, but we provide some default to stop iPhone asking for credentials
1459 print " <key>AuthName</key>\n";
1460 print " <string>$confighash{$key}[1]</string>\n";
1461 print " <key>AuthPassword</key>\n";
1462 print " <string></string>\n";
26a0befd
MT
1463 print " </dict>\n";
1464 print " </dict>\n";
1465
1466 if ($confighash{$key}[4] eq "cert") {
1467 print " <dict>\n";
1468 print " <key>PayloadIdentifier</key>\n";
1469 print " <string>org.example.vpn1.client</string>\n";
839183d8
MT
1470 print " <key>PayloadDisplayName</key>\n";
1471 print " <string>$confighash{$key}[1]</string>\n";
26a0befd
MT
1472 print " <key>PayloadUUID</key>\n";
1473 print " <string>${cert_uuid}</string>\n";
1474 print " <key>PayloadType</key>\n";
1475 print " <string>com.apple.security.pkcs12</string>\n";
1476 print " <key>PayloadVersion</key>\n";
1477 print " <integer>1</integer>\n";
1478 print " <key>PayloadContent</key>\n";
1479 print " <data>\n";
1480
1481 foreach (split /\n/,${cert}) {
1482 print " $_\n";
1483 }
1484
1485 print " </data>\n";
1486 print " </dict>\n";
db33a122
MT
1487
1488 print " <dict>\n";
1489 print " <key>PayloadIdentifier</key>\n";
1490 print " <string>org.example.ca</string>\n";
1491 print " <key>PayloadUUID</key>\n";
1492 print " <string>${ca_uuid}</string>\n";
1493 print " <key>PayloadType</key>\n";
1494 print " <string>com.apple.security.root</string>\n";
1495 print " <key>PayloadVersion</key>\n";
1496 print " <integer>1</integer>\n";
1497 print " <key>PayloadContent</key>\n";
1498 print " <data>\n";
1499
1500 foreach (split /\n/,${ca}) {
1501 print " $_\n";
1502 }
1503
1504 print " </data>\n";
1505 print " </dict>\n";
26a0befd
MT
1506 }
1507
1508 print " </array>\n";
1509 print " </dict>\n";
1510 print "</plist>\n";
1511
1512 # Done
1513 exit(0);
ac1cfefa
MT
1514###
1515### Display certificate
1516###
1517} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show certificate'}) {
624615ee
LS
1518 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1519
1520 if ( -f "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
1521 &Header::showhttpheaders();
1522 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
1523 &Header::openbigbox('100%', 'left', '', '');
1524 &Header::openbox('100%', 'left', "$Lang::tr{'cert'}:");
a81cbf61 1525 my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
c64dc3be
MT
1526 my $output = &Header::cleanhtml(join("", @output) ,"y");
1527 print "<pre>$output</pre>\n";
624615ee
LS
1528 &Header::closebox();
1529 print "<div align='center'><a href='/cgi-bin/vpnmain.cgi'>$Lang::tr{'back'}</a></div>";
1530 &Header::closebigbox();
1531 &Header::closepage();
1532 exit(0);
1533 }
ac1cfefa
MT
1534
1535###
ed84e8b8 1536### Export Certificate to browser
ac1cfefa
MT
1537###
1538} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download certificate'}) {
624615ee 1539 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
ac1cfefa 1540
624615ee
LS
1541 if ( -f "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
1542 print "Content-Type: application/force-download\n";
1543 print "Content-Disposition: attachment; filename=" . $confighash{$cgiparams{'KEY'}}[1] . "cert.pem\n\n";
a81cbf61
SS
1544
1545 open(FILE, "${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
1546 my @pem = <FILE>;
1547 close(FILE);
1548 print "@pem";
1549
624615ee
LS
1550 exit (0);
1551 }
ac1cfefa
MT
1552
1553###
1554### Enable/Disable connection
1555###
1556} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
624615ee
LS
1557
1558 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1559 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1560
1561 if ($confighash{$cgiparams{'KEY'}}) {
1562 if ($confighash{$cgiparams{'KEY'}}[0] eq 'off') {
1563 $confighash{$cgiparams{'KEY'}}[0] = 'on';
1564 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1565 &writeipsecfiles();
a81cbf61 1566 &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'}) if (&vpnenabled);
624615ee 1567 } else {
624615ee
LS
1568 $confighash{$cgiparams{'KEY'}}[0] = 'off';
1569 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1570 &writeipsecfiles();
a81cbf61 1571 &General::system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
624615ee
LS
1572 }
1573 sleep $sleepDelay;
ac1cfefa 1574 } else {
624615ee 1575 $errormessage = $Lang::tr{'invalid key'};
ac1cfefa 1576 }
ac1cfefa
MT
1577
1578###
1579### Restart connection
1580###
1581} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'restart'}) {
624615ee
LS
1582 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1583 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
ac1cfefa 1584
624615ee
LS
1585 if ($confighash{$cgiparams{'KEY'}}) {
1586 if (&vpnenabled) {
a81cbf61 1587 &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
624615ee
LS
1588 sleep $sleepDelay;
1589 }
1590 } else {
1591 $errormessage = $Lang::tr{'invalid key'};
ac1cfefa 1592 }
ac1cfefa
MT
1593
1594###
1595### Remove connection
1596###
1597} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove'}) {
624615ee
LS
1598 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1599 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
1600
1601 if ($confighash{$cgiparams{'KEY'}}) {
624615ee
LS
1602 unlink ("${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
1603 unlink ("${General::swroot}/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
1604 delete $confighash{$cgiparams{'KEY'}};
1605 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
1606 &writeipsecfiles();
a81cbf61 1607 &General::system('/usr/local/bin/ipsecctrl', 'D', $cgiparams{'KEY'}) if (&vpnenabled);
624615ee
LS
1608 } else {
1609 $errormessage = $Lang::tr{'invalid key'};
1610 }
c6df357f 1611 &General::firewall_reload();
ac1cfefa
MT
1612###
1613### Choose between adding a host-net or net-net connection
1614###
1615} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'add'} && $cgiparams{'TYPE'} eq '') {
ac1cfefa 1616 &Header::showhttpheaders();
7d44bfee 1617 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
ed84e8b8
MT
1618 &Header::openbigbox('100%', 'left', '', '');
1619 &Header::openbox('100%', 'left', $Lang::tr{'connection type'});
ac1cfefa 1620 print <<END
624615ee
LS
1621 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
1622 <b>$Lang::tr{'connection type'}:</b><br />
1623 <table>
1624 <tr><td><input type='radio' name='TYPE' value='host' checked='checked' /></td>
ed84e8b8 1625 <td class='base'>$Lang::tr{'host to net vpn'}</td>
624615ee 1626 </tr><tr>
ed84e8b8
MT
1627 <td><input type='radio' name='TYPE' value='net' /></td>
1628 <td class='base'>$Lang::tr{'net to net vpn'}</td>
624615ee 1629 </tr><tr>
ed84e8b8 1630 <td align='center' colspan='2'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>
624615ee
LS
1631 </tr>
1632 </table></form>
ac1cfefa 1633END
624615ee 1634;
ac1cfefa
MT
1635 &Header::closebox();
1636 &Header::closebigbox();
1637 &Header::closepage();
1638 exit (0);
1639###
ed1d0fbd 1640### Adding/Editing/Saving a connection
ac1cfefa
MT
1641###
1642} elsif (($cgiparams{'ACTION'} eq $Lang::tr{'add'}) ||
624615ee
LS
1643 ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) ||
1644 ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'ADVANCED'} eq '')) {
ac1cfefa 1645
624615ee
LS
1646 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
1647 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
1648 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
cbb3a8f9 1649
624615ee
LS
1650 if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}) {
1651 if (! $confighash{$cgiparams{'KEY'}}[0]) {
1652 $errormessage = $Lang::tr{'invalid key'};
1653 goto VPNCONF_END;
1654 }
1655 $cgiparams{'ENABLED'} = $confighash{$cgiparams{'KEY'}}[0];
1656 $cgiparams{'NAME'} = $confighash{$cgiparams{'KEY'}}[1];
1657 $cgiparams{'TYPE'} = $confighash{$cgiparams{'KEY'}}[3];
1658 $cgiparams{'AUTH'} = $confighash{$cgiparams{'KEY'}}[4];
1659 $cgiparams{'PSK'} = $confighash{$cgiparams{'KEY'}}[5];
ae0d0698 1660 $cgiparams{'LOCAL'} = $confighash{$cgiparams{'KEY'}}[6];
624615ee 1661 $cgiparams{'LOCAL_ID'} = $confighash{$cgiparams{'KEY'}}[7];
b1881251
MT
1662 my @local_subnets = split(",", $confighash{$cgiparams{'KEY'}}[8]);
1663 $cgiparams{'LOCAL_SUBNET'} = join(/\|/, @local_subnets);
624615ee
LS
1664 $cgiparams{'REMOTE_ID'} = $confighash{$cgiparams{'KEY'}}[9];
1665 $cgiparams{'REMOTE'} = $confighash{$cgiparams{'KEY'}}[10];
b1881251
MT
1666 my @remote_subnets = split(",", $confighash{$cgiparams{'KEY'}}[11]);
1667 $cgiparams{'REMOTE_SUBNET'} = join(/\|/, @remote_subnets);
624615ee
LS
1668 $cgiparams{'REMARK'} = $confighash{$cgiparams{'KEY'}}[25];
1669 $cgiparams{'DPD_ACTION'} = $confighash{$cgiparams{'KEY'}}[27];
1670 $cgiparams{'IKE_VERSION'} = $confighash{$cgiparams{'KEY'}}[29];
1671 $cgiparams{'IKE_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[18];
1672 $cgiparams{'IKE_INTEGRITY'} = $confighash{$cgiparams{'KEY'}}[19];
1673 $cgiparams{'IKE_GROUPTYPE'} = $confighash{$cgiparams{'KEY'}}[20];
1674 $cgiparams{'IKE_LIFETIME'} = $confighash{$cgiparams{'KEY'}}[16];
1675 $cgiparams{'ESP_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[21];
1676 $cgiparams{'ESP_INTEGRITY'} = $confighash{$cgiparams{'KEY'}}[22];
1677 $cgiparams{'ESP_GROUPTYPE'} = $confighash{$cgiparams{'KEY'}}[23];
1678 if ($cgiparams{'ESP_GROUPTYPE'} eq "") {
1679 $cgiparams{'ESP_GROUPTYPE'} = $cgiparams{'IKE_GROUPTYPE'};
1680 }
1681 $cgiparams{'ESP_KEYLIFE'} = $confighash{$cgiparams{'KEY'}}[17];
1682 $cgiparams{'COMPRESSION'} = $confighash{$cgiparams{'KEY'}}[13];
1683 $cgiparams{'ONLY_PROPOSED'} = $confighash{$cgiparams{'KEY'}}[24];
1684 $cgiparams{'PFS'} = $confighash{$cgiparams{'KEY'}}[28];
1685 $cgiparams{'DPD_TIMEOUT'} = $confighash{$cgiparams{'KEY'}}[30];
1686 $cgiparams{'DPD_DELAY'} = $confighash{$cgiparams{'KEY'}}[31];
1687 $cgiparams{'FORCE_MOBIKE'} = $confighash{$cgiparams{'KEY'}}[32];
eb09c90e 1688 $cgiparams{'START_ACTION'} = $confighash{$cgiparams{'KEY'}}[33];
af183eeb 1689 $cgiparams{'INACTIVITY_TIMEOUT'} = $confighash{$cgiparams{'KEY'}}[34];
29f5e0e2 1690 $cgiparams{'MODE'} = $confighash{$cgiparams{'KEY'}}[35];
cae1f4a7 1691 $cgiparams{'INTERFACE_MODE'} = $confighash{$cgiparams{'KEY'}}[36];
74641317 1692 $cgiparams{'INTERFACE_ADDRESS'} = $confighash{$cgiparams{'KEY'}}[37];
55842dda 1693 $cgiparams{'INTERFACE_MTU'} = $confighash{$cgiparams{'KEY'}}[38];
dccd7e87 1694 $cgiparams{'DNS_SERVERS'} = $confighash{$cgiparams{'KEY'}}[39];
624615ee
LS
1695
1696 if (!$cgiparams{'DPD_DELAY'}) {
1697 $cgiparams{'DPD_DELAY'} = 30;
1698 }
cbb3a8f9 1699
624615ee
LS
1700 if (!$cgiparams{'DPD_TIMEOUT'}) {
1701 $cgiparams{'DPD_TIMEOUT'} = 120;
1702 }
ac1cfefa 1703
af183eeb
MT
1704 if ($cgiparams{'INACTIVITY_TIMEOUT'} eq "") {
1705 $cgiparams{'INACTIVITY_TIMEOUT'} = 900;
1706 }
1707
29f5e0e2
MT
1708 if ($cgiparams{'MODE'} eq "") {
1709 $cgiparams{'MODE'} = "tunnel";
1710 }
1711
ab79dc43
MT
1712 if ($cgiparams{'INTERFACE_MTU'} eq "") {
1713 $cgiparams{'INTERFACE_MTU'} = 1500;
1714 }
1715
624615ee
LS
1716 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
1717 $cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
1718 if ($cgiparams{'TYPE'} !~ /^(host|net)$/) {
1719 $errormessage = $Lang::tr{'connection type is invalid'};
1720 goto VPNCONF_ERROR;
1721 }
ac1cfefa 1722
624615ee
LS
1723 if ($cgiparams{'NAME'} !~ /^[a-zA-Z0-9]+$/) {
1724 $errormessage = $Lang::tr{'name must only contain characters'};
1725 goto VPNCONF_ERROR;
1726 }
ac1cfefa 1727
624615ee
LS
1728 if ($cgiparams{'NAME'} =~ /^(host|01|block|private|clear|packetdefault)$/) {
1729 $errormessage = $Lang::tr{'name is invalid'};
1730 goto VPNCONF_ERROR;
1731 }
ac1cfefa 1732
624615ee
LS
1733 if (length($cgiparams{'NAME'}) >60) {
1734 $errormessage = $Lang::tr{'name too long'};
1735 goto VPNCONF_ERROR;
ac1cfefa 1736 }
ac1cfefa 1737
624615ee
LS
1738 # Check if there is no other entry with this name
1739 if (! $cgiparams{'KEY'}) { #only for add
1740 foreach my $key (keys %confighash) {
1741 if ($confighash{$key}[1] eq $cgiparams{'NAME'}) {
1742 $errormessage = $Lang::tr{'a connection with this name already exists'};
1743 goto VPNCONF_ERROR;
1744 }
1745 }
1746 }
ac1cfefa 1747
624615ee
LS
1748 if (($cgiparams{'TYPE'} eq 'net') && (! $cgiparams{'REMOTE'})) {
1749 $errormessage = $Lang::tr{'invalid input for remote host/ip'};
1750 goto VPNCONF_ERROR;
ac1cfefa 1751 }
ac1cfefa 1752
ae0d0698
MT
1753 if ($cgiparams{'LOCAL'}) {
1754 if (($cgiparams{'LOCAL'} ne "") && (!&General::validip($cgiparams{'LOCAL'}))) {
1755 $errormessage = $Lang::tr{'invalid input for local ip address'};
1756 goto VPNCONF_ERROR;
1757 }
1758 }
1759
624615ee
LS
1760 if ($cgiparams{'REMOTE'}) {
1761 if (($cgiparams{'REMOTE'} ne '%any') && (! &General::validip($cgiparams{'REMOTE'}))) {
1762 if (! &General::validfqdn ($cgiparams{'REMOTE'})) {
1763 $errormessage = $Lang::tr{'invalid input for remote host/ip'};
1764 goto VPNCONF_ERROR;
1765 } else {
1766 if (&valid_dns_host($cgiparams{'REMOTE'})) {
1767 $warnmessage = "$Lang::tr{'check vpn lr'} $cgiparams{'REMOTE'}. $Lang::tr{'dns check failed'}";
1768 }
1769 }
1770 }
1771 }
ac1cfefa 1772
b1881251
MT
1773 my @local_subnets = split(",", $cgiparams{'LOCAL_SUBNET'});
1774 foreach my $subnet (@local_subnets) {
8792caad 1775 unless (&Network::check_subnet($subnet)) {
b1881251 1776 $errormessage = $Lang::tr{'local subnet is invalid'};
8792caad
MT
1777 goto VPNCONF_ERROR;
1778 }
ac1cfefa 1779 }
ac1cfefa 1780
624615ee
LS
1781 # Allow only one roadwarrior/psk without remote IP-address
1782 if ($cgiparams{'REMOTE'} eq '' && $cgiparams{'AUTH'} eq 'psk') {
1783 foreach my $key (keys %confighash) {
1784 if ( ($cgiparams{'KEY'} ne $key) &&
1785 ($confighash{$key}[4] eq 'psk') &&
1786 ($confighash{$key}[10] eq '') ) {
1787 $errormessage = $Lang::tr{'you can only define one roadwarrior connection when using pre-shared key authentication'};
1788 goto VPNCONF_ERROR;
1789 }
1790 }
1791 }
ac1cfefa 1792
b1881251
MT
1793 if ($cgiparams{'TYPE'} eq 'net') {
1794 my @remote_subnets = split(",", $cgiparams{'REMOTE_SUBNET'});
1795 foreach my $subnet (@remote_subnets) {
1796 unless (&Network::check_subnet($subnet)) {
1797 $errormessage = $Lang::tr{'remote subnet is invalid'};
1798 goto VPNCONF_ERROR;
1799 }
1800 }
216bd9b3
MT
1801
1802 if ($cgiparams{'MODE'} !~ /^(tunnel|transport)$/) {
1803 $errormessage = $Lang::tr{'invalid input for mode'};
1804 goto VPNCONF_ERROR;
1805 }
1806
1807 if ($cgiparams{'INTERFACE_MODE'} !~ /^(|gre|vti)$/) {
1808 $errormessage = $Lang::tr{'invalid input for interface mode'};
1809 goto VPNCONF_ERROR;
1810 }
1811
7e25093d
MT
1812 if (($cgiparams{'INTERFACE_MODE'} eq "vti") && ($cgiparams{'MODE'} eq "transport")) {
1813 $errormessage = $Lang::tr{'transport mode does not support vti'};
1814 goto VPNCONF_ERROR;
1815 }
1816
216bd9b3
MT
1817 if (($cgiparams{'INTERFACE_MODE'} ne "") && !&Network::check_subnet($cgiparams{'INTERFACE_ADDRESS'})) {
1818 $errormessage = $Lang::tr{'invalid input for interface address'};
1819 goto VPNCONF_ERROR;
1820 }
1821
1822 if ($cgiparams{'INTERFACE_MTU'} !~ /^\d+$/) {
1823 $errormessage = $Lang::tr{'invalid input for interface mtu'};
1824 goto VPNCONF_ERROR;
1825 }
624615ee 1826 }
ac1cfefa 1827
dccd7e87
MT
1828 if ($cgiparams{'TYPE'} eq 'host') {
1829 my @servers = split(",", $cgiparams{'DNS_SERVERS'});
1830 foreach my $server (@servers) {
1831 unless (&Network::check_ip_address($server)) {
1832 $errormessage = $Lang::tr{'ipsec dns server address is invalid'};
1833 goto VPNCONF_ERROR;
1834 }
1835 }
1836 }
1837
624615ee
LS
1838 if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
1839 $errormessage = $Lang::tr{'invalid input'};
1840 goto VPNCONF_ERROR;
1841 }
1842 if ($cgiparams{'EDIT_ADVANCED'} !~ /^(on|off)$/) {
1843 $errormessage = $Lang::tr{'invalid input'};
1844 goto VPNCONF_ERROR;
1845 }
ed84e8b8 1846
624615ee
LS
1847 # Allow nothing or a string (DN,FDQN,) beginning with @
1848 # with no comma but slashes between RID eg @O=FR/C=Paris/OU=myhome/CN=franck
1849 if ( ($cgiparams{'LOCAL_ID'} !~ /^(|[\w.-]*@[\w. =*\/-]+|\d+\.\d+\.\d+\.\d+)$/) ||
1850 ($cgiparams{'REMOTE_ID'} !~ /^(|[\w.-]*@[\w. =*\/-]+|\d+\.\d+\.\d+\.\d+)$/) ||
1851 (($cgiparams{'REMOTE_ID'} eq $cgiparams{'LOCAL_ID'}) && ($cgiparams{'LOCAL_ID'} ne ''))
1852 ) {
1853 $errormessage = $Lang::tr{'invalid local-remote id'} . '<br />' .
1854 'DER_ASN1_DN: @c=FR/ou=Paris/ou=Home/cn=*<br />' .
1855 'FQDN: @ipfire.org<br />' .
1856 'USER_FQDN: info@ipfire.org<br />' .
1857 'IPV4_ADDR: 123.123.123.123';
1858 goto VPNCONF_ERROR;
1859 }
1860 # If Auth is DN, verify existance of Remote ID.
1861 if ( $cgiparams{'REMOTE_ID'} eq '' && (
1862 $cgiparams{'AUTH'} eq 'auth-dn'|| # while creation
1863 $confighash{$cgiparams{'KEY'}}[2] eq '%auth-dn')){ # while editing
1864 $errormessage = $Lang::tr{'vpn missing remote id'};
1865 goto VPNCONF_ERROR;
4d81e0f3 1866 }
4d81e0f3 1867
624615ee
LS
1868 if ($cgiparams{'TYPE'} eq 'net'){
1869 $warnmessage=&General::checksubnets('',$cgiparams{'REMOTE_SUBNET'},'ipsec');
1870 if ($warnmessage ne ''){
1871 $warnmessage=$Lang::tr{'remote subnet'}." ($cgiparams{'REMOTE_SUBNET'}) <br>".$warnmessage;
1872 }
1873 }
1874
1875 if ($cgiparams{'AUTH'} eq 'psk') {
1876 if (! length($cgiparams{'PSK'}) ) {
1877 $errormessage = $Lang::tr{'pre-shared key is too short'};
1878 goto VPNCONF_ERROR;
1879 }
1880 if ($cgiparams{'PSK'} =~ /'/) {
1881 $cgiparams{'PSK'} =~ tr/'/ /;
1882 $errormessage = $Lang::tr{'invalid characters found in pre-shared key'};
1883 goto VPNCONF_ERROR;
1884 }
ac1cfefa 1885 } elsif ($cgiparams{'AUTH'} eq 'certreq') {
624615ee
LS
1886 if ($cgiparams{'KEY'}) {
1887 $errormessage = $Lang::tr{'cant change certificates'};
1888 goto VPNCONF_ERROR;
1889 }
2ad1b18b 1890 unless (ref ($cgiparams{'FH'})) {
624615ee
LS
1891 $errormessage = $Lang::tr{'there was no file upload'};
1892 goto VPNCONF_ERROR;
1893 }
ac1cfefa 1894
624615ee
LS
1895 # Move uploaded certificate request to a temporary file
1896 (my $fh, my $filename) = tempfile( );
1897 if (copy ($cgiparams{'FH'}, $fh) != 1) {
1898 $errormessage = $!;
1899 goto VPNCONF_ERROR;
1900 }
ac1cfefa 1901
624615ee
LS
1902 # Sign the certificate request
1903 &General::log("ipsec", "Signing your cert $cgiparams{'NAME'}...");
926e5519 1904 my $opt = " ca -md sha256 -days 825";
ed84e8b8
MT
1905 $opt .= " -batch -notext";
1906 $opt .= " -in $filename";
1907 $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
1908
624615ee
LS
1909 if ( $errormessage = &callssl ($opt) ) {
1910 unlink ($filename);
1911 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1912 &cleanssldatabase();
1913 goto VPNCONF_ERROR;
1914 } else {
1915 unlink ($filename);
1916 &cleanssldatabase();
1917 }
1918
1919 $cgiparams{'CERT_NAME'} = getCNfromcert ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
1920 if ($cgiparams{'CERT_NAME'} eq '') {
1921 $errormessage = $Lang::tr{'could not retrieve common name from certificate'};
1922 goto VPNCONF_ERROR;
1923 }
ed84e8b8
MT
1924 } elsif ($cgiparams{'AUTH'} eq 'pkcs12') {
1925 &General::log("ipsec", "Importing from p12...");
1926
2ad1b18b 1927 unless (ref ($cgiparams{'FH'})) {
624615ee
LS
1928 $errormessage = $Lang::tr{'there was no file upload'};
1929 goto ROOTCERT_ERROR;
ed84e8b8
MT
1930 }
1931
1932 # Move uploaded certificate request to a temporary file
1933 (my $fh, my $filename) = tempfile( );
1934 if (copy ($cgiparams{'FH'}, $fh) != 1) {
624615ee
LS
1935 $errormessage = $!;
1936 goto ROOTCERT_ERROR;
ed84e8b8
MT
1937 }
1938
1939 # Extract the CA certificate from the file
1940 &General::log("ipsec", "Extracting caroot from p12...");
1941 if (open(STDIN, "-|")) {
624615ee 1942 my $opt = " pkcs12 -cacerts -nokeys";
ed84e8b8
MT
1943 $opt .= " -in $filename";
1944 $opt .= " -out /tmp/newcacert";
ed84e8b8 1945 $errormessage = &callssl ($opt);
624615ee 1946 } else { #child
ed84e8b8
MT
1947 print "$cgiparams{'P12_PASS'}\n";
1948 exit (0);
624615ee
LS
1949 }
1950
1951 # Extract the Host certificate from the file
1952 if (!$errormessage) {
1953 &General::log("ipsec", "Extracting host cert from p12...");
1954 if (open(STDIN, "-|")) {
1955 my $opt = " pkcs12 -clcerts -nokeys";
1956 $opt .= " -in $filename";
1957 $opt .= " -out /tmp/newhostcert";
1958 $errormessage = &callssl ($opt);
1959 } else { #child
1960 print "$cgiparams{'P12_PASS'}\n";
1961 exit (0);
1962 }
1963 }
1964
1965 if (!$errormessage) {
1966 &General::log("ipsec", "Moving cacert...");
1967 #If CA have new subject, add it to our list of CA
1968 my $casubject = &Header::cleanhtml(getsubjectfromcert ('/tmp/newcacert'));
1969 my @names;
1970 foreach my $x (keys %cahash) {
1971 $casubject='' if ($cahash{$x}[1] eq $casubject);
1972 unshift (@names,$cahash{$x}[0]);
1973 }
1974 if ($casubject) { # a new one!
a81cbf61
SS
1975 my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "/tmp/newcacert");
1976 if (! grep(/CA:TRUE/, @temp)) {
624615ee
LS
1977 $errormessage = $Lang::tr{'not a valid ca certificate'};
1978 } else {
1979 #compute a name for it
1980 my $idx=0;
1981 while (grep(/Imported-$idx/, @names) ) {$idx++};
1982 $cgiparams{'CA_NAME'}="Imported-$idx";
1983 $cgiparams{'CERT_NAME'}=&Header::cleanhtml(getCNfromcert ('/tmp/newhostcert'));
b5b19f37
SS
1984
1985 unless(move("/tmp/newcacert", "${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem")) {
1986 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1987 }
1988
624615ee
LS
1989 if (!$errormessage) {
1990 my $key = &General::findhasharraykey (\%cahash);
1991 $cahash{$key}[0] = $cgiparams{'CA_NAME'};
1992 $cahash{$key}[1] = $casubject;
1993 &General::writehasharray("${General::swroot}/vpn/caconfig", \%cahash);
a81cbf61 1994 &General::system('/usr/local/bin/ipsecctrl', 'R');
624615ee
LS
1995 }
1996 }
1997 }
ed84e8b8
MT
1998 }
1999 if (!$errormessage) {
624615ee 2000 &General::log("ipsec", "Moving host cert...");
b5b19f37
SS
2001 unless(move("/tmp/newhostcert", "${General::swroot}/certs/$cgiparams{'NAME'}cert.pem")) {
2002 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
2003 }
624615ee 2004 }
ed84e8b8
MT
2005
2006 #cleanup temp files
2007 unlink ($filename);
2008 unlink ('/tmp/newcacert');
2009 unlink ('/tmp/newhostcert');
2010 if ($errormessage) {
624615ee
LS
2011 unlink ("${General::swroot}/ca/$cgiparams{'CA_NAME'}cert.pem");
2012 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
2013 goto VPNCONF_ERROR;
ed84e8b8
MT
2014 }
2015 &General::log("ipsec", "p12 import completed!");
ac1cfefa 2016 } elsif ($cgiparams{'AUTH'} eq 'certfile') {
624615ee
LS
2017 if ($cgiparams{'KEY'}) {
2018 $errormessage = $Lang::tr{'cant change certificates'};
2019 goto VPNCONF_ERROR;
2020 }
2ad1b18b 2021 unless (ref ($cgiparams{'FH'})) {
624615ee
LS
2022 $errormessage = $Lang::tr{'there was no file upload'};
2023 goto VPNCONF_ERROR;
2024 }
2025 # Move uploaded certificate to a temporary file
2026 (my $fh, my $filename) = tempfile( );
2027 if (copy ($cgiparams{'FH'}, $fh) != 1) {
2028 $errormessage = $!;
2029 goto VPNCONF_ERROR;
ac1cfefa 2030 }
ac1cfefa 2031
624615ee
LS
2032 # Verify the certificate has a valid CA and move it
2033 &General::log("ipsec", "Validating imported cert against our known CA...");
2034 my $validca = 1; #assume ok
a81cbf61
SS
2035 my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/cacert.pem", "$filename");
2036 if (! grep(/: OK/, @test)) {
624615ee
LS
2037 my $validca = 0;
2038 foreach my $key (keys %cahash) {
a81cbf61
SS
2039 @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ca/$cahash{$key}[0]cert.pem", "$filename");
2040 if (grep(/: OK/, @test)) {
624615ee
LS
2041 $validca = 1;
2042 last;
2043 }
2044 }
2045 }
2046 if (! $validca) {
2047 $errormessage = $Lang::tr{'certificate does not have a valid ca associated with it'};
2048 unlink ($filename);
2049 goto VPNCONF_ERROR;
2050 } else {
aec1c53c
MT
2051 unless (move($filename, "${General::swroot}/certs/$cgiparams{'NAME'}cert.pem")) {
2052 $errormessage = "$Lang::tr{'certificate file move failed'} ($filename): $!";
624615ee
LS
2053 unlink ($filename);
2054 goto VPNCONF_ERROR;
2055 }
2056 }
2057
2058 $cgiparams{'CERT_NAME'} = getCNfromcert ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
2059 if ($cgiparams{'CERT_NAME'} eq '') {
2060 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
2061 $errormessage = $Lang::tr{'could not retrieve common name from certificate'};
2062 goto VPNCONF_ERROR;
2063 }
ac1cfefa 2064 } elsif ($cgiparams{'AUTH'} eq 'certgen') {
624615ee
LS
2065 if ($cgiparams{'KEY'}) {
2066 $errormessage = $Lang::tr{'cant change certificates'};
2067 goto VPNCONF_ERROR;
2068 }
2069 # Validate input since the form was submitted
2070 if (length($cgiparams{'CERT_NAME'}) >60) {
2071 $errormessage = $Lang::tr{'name too long'};
2072 goto VPNCONF_ERROR;
2073 }
2074 if ($cgiparams{'CERT_NAME'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
2075 $errormessage = $Lang::tr{'invalid input for name'};
2076 goto VPNCONF_ERROR;
2077 }
2078 if ($cgiparams{'CERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'CERT_EMAIL'}))) {
2079 $errormessage = $Lang::tr{'invalid input for e-mail address'};
2080 goto VPNCONF_ERROR;
2081 }
2082 if (length($cgiparams{'CERT_EMAIL'}) > 40) {
2083 $errormessage = $Lang::tr{'e-mail address too long'};
2084 goto VPNCONF_ERROR;
2085 }
2086 if ($cgiparams{'CERT_OU'} ne '' && $cgiparams{'CERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
2087 $errormessage = $Lang::tr{'invalid input for department'};
2088 goto VPNCONF_ERROR;
2089 }
2090 if (length($cgiparams{'CERT_ORGANIZATION'}) >60) {
2091 $errormessage = $Lang::tr{'organization too long'};
2092 goto VPNCONF_ERROR;
2093 }
2094 if ($cgiparams{'CERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]+$/) {
2095 $errormessage = $Lang::tr{'invalid input for organization'};
2096 goto VPNCONF_ERROR;
2097 }
2098 if ($cgiparams{'CERT_CITY'} ne '' && $cgiparams{'CERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
2099 $errormessage = $Lang::tr{'invalid input for city'};
2100 goto VPNCONF_ERROR;
2101 }
2102 if ($cgiparams{'CERT_STATE'} ne '' && $cgiparams{'CERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
2103 $errormessage = $Lang::tr{'invalid input for state or province'};
2104 goto VPNCONF_ERROR;
2105 }
2106 if ($cgiparams{'CERT_COUNTRY'} !~ /^[A-Z]*$/) {
2107 $errormessage = $Lang::tr{'invalid input for country'};
2108 goto VPNCONF_ERROR;
2109 }
2110 #the exact syntax is a list comma separated of
2111 # email:any-validemail
2112 # URI: a uniform resource indicator
2113 # DNS: a DNS domain name
2114 # RID: a registered OBJECT IDENTIFIER
2115 # IP: an IP address
2116 # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
2117
2118 if ($cgiparams{'SUBJECTALTNAME'} ne '' && $cgiparams{'SUBJECTALTNAME'} !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/,\.\-_@]*$/) {
2119 $errormessage = $Lang::tr{'vpn altname syntax'};
2120 goto VPNCONF_ERROR;
2121 }
ed84e8b8 2122
624615ee
LS
2123 if (length($cgiparams{'CERT_PASS1'}) < 5) {
2124 $errormessage = $Lang::tr{'password too short'};
2125 goto VPNCONF_ERROR;
2126 }
2127 if ($cgiparams{'CERT_PASS1'} ne $cgiparams{'CERT_PASS2'}) {
2128 $errormessage = $Lang::tr{'passwords do not match'};
2129 goto VPNCONF_ERROR;
2130 }
ac1cfefa 2131
624615ee
LS
2132 # Replace empty strings with a .
2133 (my $ou = $cgiparams{'CERT_OU'}) =~ s/^\s*$/\./;
2134 (my $city = $cgiparams{'CERT_CITY'}) =~ s/^\s*$/\./;
2135 (my $state = $cgiparams{'CERT_STATE'}) =~ s/^\s*$/\./;
ac1cfefa 2136
624615ee
LS
2137 # Create the Client certificate request
2138 &General::log("ipsec", "Creating a cert...");
ed84e8b8 2139
624615ee
LS
2140 if (open(STDIN, "-|")) {
2141 my $opt = " req -nodes -rand /proc/interrupts:/proc/net/rt_cache";
2142 $opt .= " -newkey rsa:2048";
2143 $opt .= " -keyout ${General::swroot}/certs/$cgiparams{'NAME'}key.pem";
2144 $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}req.pem";
2145
2146 if ( $errormessage = &callssl ($opt) ) {
2147 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
2148 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
2149 goto VPNCONF_ERROR;
2150 }
2151 } else { #child
2152 print "$cgiparams{'CERT_COUNTRY'}\n";
2153 print "$state\n";
2154 print "$city\n";
2155 print "$cgiparams{'CERT_ORGANIZATION'}\n";
2156 print "$ou\n";
2157 print "$cgiparams{'CERT_NAME'}\n";
2158 print "$cgiparams{'CERT_EMAIL'}\n";
2159 print ".\n";
2160 print ".\n";
2161 exit (0);
2162 }
ed84e8b8 2163
624615ee
LS
2164 # Sign the client certificate request
2165 &General::log("ipsec", "Signing the cert $cgiparams{'NAME'}...");
2166
2167 #No easy way for specifying the contain of subjectAltName without writing a config file...
2168 my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
2169 print $fh <<END
2170 basicConstraints=CA:FALSE
2171 nsComment="OpenSSL Generated Certificate"
2172 subjectKeyIdentifier=hash
2173 extendedKeyUsage=clientAuth
2174 authorityKeyIdentifier=keyid,issuer:always
ed84e8b8
MT
2175END
2176;
624615ee
LS
2177 print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
2178 close ($fh);
2179
926e5519 2180 my $opt = " ca -md sha256 -days 825 -batch -notext";
624615ee
LS
2181 $opt .= " -in ${General::swroot}/certs/$cgiparams{'NAME'}req.pem";
2182 $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
2183 $opt .= " -extfile $v3extname";
2184
2185 if ( $errormessage = &callssl ($opt) ) {
2186 unlink ($v3extname);
2187 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
2188 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
2189 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
2190 &cleanssldatabase();
2191 goto VPNCONF_ERROR;
2192 } else {
2193 unlink ($v3extname);
2194 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}req.pem");
2195 &cleanssldatabase();
2196 }
2197
2198 # Create the pkcs12 file
2199 &General::log("ipsec", "Packing a pkcs12 file...");
2200 $opt = " pkcs12 -export";
2201 $opt .= " -inkey ${General::swroot}/certs/$cgiparams{'NAME'}key.pem";
2202 $opt .= " -in ${General::swroot}/certs/$cgiparams{'NAME'}cert.pem";
2203 $opt .= " -name \"$cgiparams{'NAME'}\"";
2204 $opt .= " -passout pass:$cgiparams{'CERT_PASS1'}";
2205 $opt .= " -certfile ${General::swroot}/ca/cacert.pem";
2206 $opt .= " -caname \"$vpnsettings{'ROOTCERT_ORGANIZATION'} CA\"";
2207 $opt .= " -out ${General::swroot}/certs/$cgiparams{'NAME'}.p12";
2208
2209 if ( $errormessage = &callssl ($opt) ) {
2210 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
2211 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}cert.pem");
2212 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}.p12");
2213 goto VPNCONF_ERROR;
2214 } else {
2215 unlink ("${General::swroot}/certs/$cgiparams{'NAME'}key.pem");
2216 }
ac1cfefa 2217 } elsif ($cgiparams{'AUTH'} eq 'cert') {
624615ee 2218 ;# Nothing, just editing
ed84e8b8 2219 } elsif ($cgiparams{'AUTH'} eq 'auth-dn') {
624615ee 2220 $cgiparams{'CERT_NAME'} = '%auth-dn'; # a special value saying 'no cert file'
ac1cfefa 2221 } else {
624615ee
LS
2222 $errormessage = $Lang::tr{'invalid input for authentication method'};
2223 goto VPNCONF_ERROR;
ac1cfefa
MT
2224 }
2225
ed84e8b8
MT
2226 # 1)Error message here is not accurate.
2227 # 2)Test is superfluous, openswan can reference same cert multiple times
2228 # 3)Present since initial version (1.3.2.11), it isn't a bug correction
2229 # Check if there is no other entry with this certificate name
2230 #if ((! $cgiparams{'KEY'}) && ($cgiparams{'AUTH'} ne 'psk') && ($cgiparams{'AUTH'} ne 'auth-dn')) {
624615ee 2231 # foreach my $key (keys %confighash) {
ed84e8b8 2232 # if ($confighash{$key}[2] eq $cgiparams{'CERT_NAME'}) {
624615ee
LS
2233 # $errormessage = $Lang::tr{'a connection with this common name already exists'};
2234 # goto VPNCONF_ERROR;
2235 # }
ed84e8b8 2236 # }
ed84e8b8 2237 #}
624615ee 2238 # Save the config
ed84e8b8 2239
ac1cfefa
MT
2240 my $key = $cgiparams{'KEY'};
2241 if (! $key) {
624615ee 2242 $key = &General::findhasharraykey (\%confighash);
dccd7e87 2243 foreach my $i (0 .. 39) { $confighash{$key}[$i] = "";}
ac1cfefa
MT
2244 }
2245 $confighash{$key}[0] = $cgiparams{'ENABLED'};
2246 $confighash{$key}[1] = $cgiparams{'NAME'};
2247 if ((! $cgiparams{'KEY'}) && $cgiparams{'AUTH'} ne 'psk') {
624615ee 2248 $confighash{$key}[2] = $cgiparams{'CERT_NAME'};
ac1cfefa
MT
2249 }
2250 $confighash{$key}[3] = $cgiparams{'TYPE'};
2251 if ($cgiparams{'AUTH'} eq 'psk') {
624615ee
LS
2252 $confighash{$key}[4] = 'psk';
2253 $confighash{$key}[5] = $cgiparams{'PSK'};
ac1cfefa 2254 } else {
624615ee 2255 $confighash{$key}[4] = 'cert';
ac1cfefa
MT
2256 }
2257 if ($cgiparams{'TYPE'} eq 'net') {
b1881251
MT
2258 my @remote_subnets = split(",", $cgiparams{'REMOTE_SUBNET'});
2259 $confighash{$key}[11] = join('|', @remote_subnets);
ac1cfefa 2260 }
ae0d0698 2261 $confighash{$key}[6] = $cgiparams{'LOCAL'};
ac1cfefa 2262 $confighash{$key}[7] = $cgiparams{'LOCAL_ID'};
8792caad
MT
2263 my @local_subnets = split(",", $cgiparams{'LOCAL_SUBNET'});
2264 $confighash{$key}[8] = join('|', @local_subnets);
ac1cfefa
MT
2265 $confighash{$key}[9] = $cgiparams{'REMOTE_ID'};
2266 $confighash{$key}[10] = $cgiparams{'REMOTE'};
2267 $confighash{$key}[25] = $cgiparams{'REMARK'};
ae2782ba 2268 $confighash{$key}[26] = ""; # Formerly INTERFACE
ac1cfefa 2269 $confighash{$key}[27] = $cgiparams{'DPD_ACTION'};
e2e4ed01 2270 $confighash{$key}[29] = $cgiparams{'IKE_VERSION'};
ac1cfefa 2271
624615ee 2272 # don't forget advanced value
ed84e8b8
MT
2273 $confighash{$key}[18] = $cgiparams{'IKE_ENCRYPTION'};
2274 $confighash{$key}[19] = $cgiparams{'IKE_INTEGRITY'};
2275 $confighash{$key}[20] = $cgiparams{'IKE_GROUPTYPE'};
2276 $confighash{$key}[16] = $cgiparams{'IKE_LIFETIME'};
2277 $confighash{$key}[21] = $cgiparams{'ESP_ENCRYPTION'};
2278 $confighash{$key}[22] = $cgiparams{'ESP_INTEGRITY'};
2279 $confighash{$key}[23] = $cgiparams{'ESP_GROUPTYPE'};
2280 $confighash{$key}[17] = $cgiparams{'ESP_KEYLIFE'};
451a2f68 2281 $confighash{$key}[12] = 'off'; # $cgiparams{'AGGRMODE'};
ed84e8b8
MT
2282 $confighash{$key}[13] = $cgiparams{'COMPRESSION'};
2283 $confighash{$key}[24] = $cgiparams{'ONLY_PROPOSED'};
2284 $confighash{$key}[28] = $cgiparams{'PFS'};
4e156911
AM
2285 $confighash{$key}[30] = $cgiparams{'DPD_TIMEOUT'};
2286 $confighash{$key}[31] = $cgiparams{'DPD_DELAY'};
f6529a04 2287 $confighash{$key}[32] = $cgiparams{'FORCE_MOBIKE'};
eb09c90e 2288 $confighash{$key}[33] = $cgiparams{'START_ACTION'};
af183eeb 2289 $confighash{$key}[34] = $cgiparams{'INACTIVITY_TIMEOUT'};
29f5e0e2 2290 $confighash{$key}[35] = $cgiparams{'MODE'};
cae1f4a7 2291 $confighash{$key}[36] = $cgiparams{'INTERFACE_MODE'};
74641317 2292 $confighash{$key}[37] = $cgiparams{'INTERFACE_ADDRESS'};
55842dda 2293 $confighash{$key}[38] = $cgiparams{'INTERFACE_MTU'};
dccd7e87 2294 $confighash{$key}[39] = join("|", split(",", $cgiparams{'DNS_SERVERS'}));
ac1cfefa 2295
624615ee 2296 # free unused fields!
ed84e8b8 2297 $confighash{$key}[15] = 'off';
ac1cfefa
MT
2298
2299 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
2300 &writeipsecfiles();
ed84e8b8 2301 if (&vpnenabled) {
a81cbf61 2302 &General::system('/usr/local/bin/ipsecctrl', 'S', $key);
624615ee 2303 sleep $sleepDelay;
ac1cfefa
MT
2304 }
2305 if ($cgiparams{'EDIT_ADVANCED'} eq 'on') {
624615ee
LS
2306 $cgiparams{'KEY'} = $key;
2307 $cgiparams{'ACTION'} = $Lang::tr{'advanced'};
ac1cfefa
MT
2308 }
2309 goto VPNCONF_END;
624615ee
LS
2310} else { # add new connection
2311 $cgiparams{'ENABLED'} = 'on';
ac1cfefa 2312 if ( ! -f "${General::swroot}/private/cakey.pem" ) {
624615ee 2313 $cgiparams{'AUTH'} = 'psk';
ac1cfefa 2314 } elsif ( ! -f "${General::swroot}/ca/cacert.pem") {
624615ee 2315 $cgiparams{'AUTH'} = 'certfile';
ac1cfefa 2316 } else {
624615ee 2317 $cgiparams{'AUTH'} = 'certgen';
ac1cfefa 2318 }
605c391a
MT
2319
2320 if ($netsettings{"GREEN_NETADDRESS"} && $netsettings{"GREEN_NETMASK"}) {
2321 $cgiparams{"LOCAL_SUBNET"} = $netsettings{'GREEN_NETADDRESS'} . "/" . $netsettings{'GREEN_NETMASK'};
2322 } else {
2323 $cgiparams{"LOCAL_SUBNET"} = "";
2324 }
624615ee
LS
2325 $cgiparams{'CERT_EMAIL'} = $vpnsettings{'ROOTCERT_EMAIL'};
2326 $cgiparams{'CERT_OU'} = $vpnsettings{'ROOTCERT_OU'};
2327 $cgiparams{'CERT_ORGANIZATION'} = $vpnsettings{'ROOTCERT_ORGANIZATION'};
2328 $cgiparams{'CERT_CITY'} = $vpnsettings{'ROOTCERT_CITY'};
2329 $cgiparams{'CERT_STATE'} = $vpnsettings{'ROOTCERT_STATE'};
2330 $cgiparams{'CERT_COUNTRY'} = $vpnsettings{'ROOTCERT_COUNTRY'};
ac1cfefa 2331
624615ee 2332 # choose appropriate dpd action
ac1cfefa 2333 if ($cgiparams{'TYPE'} eq 'host') {
afd5d8f7 2334 $cgiparams{'DPD_ACTION'} = 'clear';
ac1cfefa 2335 } else {
afd5d8f7 2336 $cgiparams{'DPD_ACTION'} = 'restart';
ac1cfefa
MT
2337 }
2338
cbb3a8f9
MT
2339 if (!$cgiparams{'DPD_DELAY'}) {
2340 $cgiparams{'DPD_DELAY'} = 30;
2341 }
2342
2343 if (!$cgiparams{'DPD_TIMEOUT'}) {
2344 $cgiparams{'DPD_TIMEOUT'} = 120;
2345 }
2346
f6529a04
MT
2347 if (!$cgiparams{'FORCE_MOBIKE'}) {
2348 $cgiparams{'FORCE_MOBIKE'} = 'no';
2349 }
2350
ae2782ba
MT
2351 # Default IKE Version to v2
2352 if (!$cgiparams{'IKE_VERSION'}) {
624615ee 2353 $cgiparams{'IKE_VERSION'} = 'ikev2';
e2e4ed01
AF
2354 }
2355
ac1cfefa 2356 # ID are empty
624615ee 2357 $cgiparams{'LOCAL_ID'} = '';
ac1cfefa 2358 $cgiparams{'REMOTE_ID'} = '';
ed84e8b8
MT
2359
2360 #use default advanced value
05375f12 2361 $cgiparams{'IKE_ENCRYPTION'} = 'chacha20poly1305|aes256gcm128|aes256gcm96|aes256gcm64|aes256|aes192gcm128|aes192gcm96|aes192gcm64|aes192|aes128gcm128|aes128gcm96|aes128gcm64|aes128'; #[18];
570d54fd 2362 $cgiparams{'IKE_INTEGRITY'} = 'sha2_512|sha2_256'; #[19];
85d5f26f 2363 $cgiparams{'IKE_GROUPTYPE'} = 'curve448|curve448|4096|3072|2048'; #[20];
624615ee 2364 $cgiparams{'IKE_LIFETIME'} = '3'; #[16];
05375f12 2365 $cgiparams{'ESP_ENCRYPTION'} = 'chacha20poly1305|aes256gcm128|aes256gcm96|aes256gcm64|aes256|aes192gcm128|aes192gcm96|aes192gcm64|aes192|aes128gcm128|aes128gcm96|aes128gcm64|aes128'; #[21];
570d54fd 2366 $cgiparams{'ESP_INTEGRITY'} = 'sha2_512|sha2_256'; #[22];
85d5f26f 2367 $cgiparams{'ESP_GROUPTYPE'} = 'curve448|curve25519|4096|3072|2048'; #[23];
624615ee 2368 $cgiparams{'ESP_KEYLIFE'} = '1'; #[17];
120d77b3 2369 $cgiparams{'COMPRESSION'} = 'off'; #[13];
570d54fd 2370 $cgiparams{'ONLY_PROPOSED'} = 'on'; #[24];
624615ee 2371 $cgiparams{'PFS'} = 'on'; #[28];
af183eeb 2372 $cgiparams{'INACTIVITY_TIMEOUT'} = 900;
29f5e0e2 2373 $cgiparams{'MODE'} = "tunnel";
cae1f4a7 2374 $cgiparams{'INTERFACE_MODE'} = "";
74641317 2375 $cgiparams{'INTERFACE_ADDRESS'} = "";
55842dda 2376 $cgiparams{'INTERFACE_MTU'} = 1500;
dccd7e87 2377 $cgiparams{'DNS_SERVERS'} = "";
624615ee 2378}
ac1cfefa 2379
624615ee
LS
2380VPNCONF_ERROR:
2381 $checked{'ENABLED'}{'off'} = '';
2382 $checked{'ENABLED'}{'on'} = '';
2383 $checked{'ENABLED'}{$cgiparams{'ENABLED'}} = "checked='checked'";
2384
2385 $checked{'EDIT_ADVANCED'}{'off'} = '';
2386 $checked{'EDIT_ADVANCED'}{'on'} = '';
2387 $checked{'EDIT_ADVANCED'}{$cgiparams{'EDIT_ADVANCED'}} = "checked='checked'";
2388
2389 $checked{'AUTH'}{'psk'} = '';
2390 $checked{'AUTH'}{'certreq'} = '';
2391 $checked{'AUTH'}{'certgen'} = '';
2392 $checked{'AUTH'}{'certfile'} = '';
2393 $checked{'AUTH'}{'pkcs12'} = '';
2394 $checked{'AUTH'}{'auth-dn'} = '';
2395 $checked{'AUTH'}{$cgiparams{'AUTH'}} = "checked='checked'";
2396
216bd9b3
MT
2397 $selected{'MODE'}{'tunnel'} = '';
2398 $selected{'MODE'}{'transport'} = '';
2399 $selected{'MODE'}{$cgiparams{'MODE'}} = "selected='selected'";
2400
2401 $selected{'INTERFACE_MODE'}{''} = '';
2402 $selected{'INTERFACE_MODE'}{'gre'} = '';
2403 $selected{'INTERFACE_MODE'}{'vti'} = '';
2404 $selected{'INTERFACE_MODE'}{$cgiparams{'INTERFACE_MODE'}} = "selected='selected'";
2405
ae0d0698
MT
2406 $selected{'LOCAL'}{''} = '';
2407 foreach my $alias (sort keys %aliases) {
2408 my $address = $aliases{$alias}{'IPT'};
2409
2410 $selected{'LOCAL'}{$address} = '';
2411 }
2412 $selected{'LOCAL'}{$cgiparams{'LOCAL'}} = "selected='selected'";
2413
624615ee
LS
2414 &Header::showhttpheaders();
2415 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
2416 &Header::openbigbox('100%', 'left', '', $errormessage);
2417 if ($errormessage) {
2418 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
2419 print "<class name='base'>$errormessage";
2420 print "&nbsp;</class>";
2421 &Header::closebox();
2422 }
2423
2424 if ($warnmessage) {
2425 &Header::openbox('100%', 'left', "$Lang::tr{'warning messages'}:");
2426 print "<class name='base'>$warnmessage";
2427 print "&nbsp;</class>";
2428 &Header::closebox();
2429 }
ac1cfefa 2430
624615ee
LS
2431 print "<form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>";
2432 print<<END
ed84e8b8 2433 <input type='hidden' name='TYPE' value='$cgiparams{'TYPE'}' />
4ad0b5b6 2434 <input type='hidden' name='IKE_VERSION' value='$cgiparams{'IKE_VERSION'}' />
ed84e8b8
MT
2435 <input type='hidden' name='IKE_ENCRYPTION' value='$cgiparams{'IKE_ENCRYPTION'}' />
2436 <input type='hidden' name='IKE_INTEGRITY' value='$cgiparams{'IKE_INTEGRITY'}' />
2437 <input type='hidden' name='IKE_GROUPTYPE' value='$cgiparams{'IKE_GROUPTYPE'}' />
2438 <input type='hidden' name='IKE_LIFETIME' value='$cgiparams{'IKE_LIFETIME'}' />
2439 <input type='hidden' name='ESP_ENCRYPTION' value='$cgiparams{'ESP_ENCRYPTION'}' />
2440 <input type='hidden' name='ESP_INTEGRITY' value='$cgiparams{'ESP_INTEGRITY'}' />
2441 <input type='hidden' name='ESP_GROUPTYPE' value='$cgiparams{'ESP_GROUPTYPE'}' />
2442 <input type='hidden' name='ESP_KEYLIFE' value='$cgiparams{'ESP_KEYLIFE'}' />
ed84e8b8
MT
2443 <input type='hidden' name='COMPRESSION' value='$cgiparams{'COMPRESSION'}' />
2444 <input type='hidden' name='ONLY_PROPOSED' value='$cgiparams{'ONLY_PROPOSED'}' />
2445 <input type='hidden' name='PFS' value='$cgiparams{'PFS'}' />
cbb3a8f9
MT
2446 <input type='hidden' name='DPD_ACTION' value='$cgiparams{'DPD_ACTION'}' />
2447 <input type='hidden' name='DPD_DELAY' value='$cgiparams{'DPD_DELAY'}' />
2448 <input type='hidden' name='DPD_TIMEOUT' value='$cgiparams{'DPD_TIMEOUT'}' />
f6529a04 2449 <input type='hidden' name='FORCE_MOBIKE' value='$cgiparams{'FORCE_MOBIKE'}' />
eb09c90e 2450 <input type='hidden' name='START_ACTION' value='$cgiparams{'START_ACTION'}' />
5e6fa03e 2451 <input type='hidden' name='INACTIVITY_TIMEOUT' value='$cgiparams{'INACTIVITY_TIMEOUT'}' />
ed84e8b8 2452END
624615ee
LS
2453;
2454 if ($cgiparams{'KEY'}) {
2455 print "<input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />";
2456 print "<input type='hidden' name='NAME' value='$cgiparams{'NAME'}' />";
2457 print "<input type='hidden' name='AUTH' value='$cgiparams{'AUTH'}' />";
2458 }
2459
2460 &Header::openbox('100%', 'left', "$Lang::tr{'connection'}: $cgiparams{'NAME'}");
2461 print "<table width='100%'>";
2462 if (!$cgiparams{'KEY'}) {
2463 print <<EOF;
2464 <tr>
2465 <td width='20%'>$Lang::tr{'name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2466 <td width='30%'>
2467 <input type='text' name='NAME' value='$cgiparams{'NAME'}' size='25' />
2468 </td>
2469 <td colspan="2"></td>
2470 </tr>
d2d87f2c 2471EOF
624615ee 2472 }
ac1cfefa 2473
dccd7e87
MT
2474 my $blob = "";
2475 if ($cgiparams{'TYPE'} eq 'net') {
e3edceeb 2476 $blob = "<img src='/blob.gif' alt='*' />";
624615ee 2477 };
5fd30232 2478
b1881251
MT
2479 my @local_subnets = split(/\|/, $cgiparams{'LOCAL_SUBNET'});
2480 my $local_subnets = join(",", @local_subnets);
8792caad 2481
b1881251
MT
2482 my @remote_subnets = split(/\|/, $cgiparams{'REMOTE_SUBNET'});
2483 my $remote_subnets = join(",", @remote_subnets);
8792caad 2484
dccd7e87
MT
2485 my @dns_servers = split(/\|/, $cgiparams{'DNS_SERVERS'});
2486 my $dns_servers = join(",", @dns_servers);
2487
ae0d0698 2488 print <<END;
ae2782ba 2489 <tr>
d2d87f2c
MT
2490 <td width='20%'>$Lang::tr{'enabled'}</td>
2491 <td width='30%'>
2492 <input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} />
2493 </td>
455fdcb1 2494 <td colspan="2"></td>
d2d87f2c
MT
2495 </tr>
2496 <tr>
ae0d0698
MT
2497 <td class='boldbase' width='20%'>$Lang::tr{'local ip address'}:</td>
2498 <td width='30%'>
2499 <select name="LOCAL">
2500 <option value="" $selected{'LOCAL'}{''}>- $Lang::tr{'default IP address'} -</option>
2501END
2502
2503 foreach my $alias (sort keys %aliases) {
2504 my $address = $aliases{$alias}{'IPT'};
2505 print <<END;
2506 <option value="$address" $selected{'LOCAL'}{$address}>$alias ($address)</option>
2507END
2508 }
2509
2510 print <<END;
2511 </select>
2512 </td>
624615ee
LS
2513 <td class='boldbase' width='20%'>$Lang::tr{'remote host/ip'}:&nbsp;$blob</td>
2514 <td width='30%'>
2515 <input type='text' name='REMOTE' value='$cgiparams{'REMOTE'}' size="25" />
2516 </td>
455fdcb1
MT
2517 </tr>
2518 <tr>
2519 <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'local subnet'}&nbsp;<img src='/blob.gif' alt='*' /></td>
2520 <td width='30%'>
2521 <input type='text' name='LOCAL_SUBNET' value='$local_subnets' size="25" />
2522 </td>
dccd7e87
MT
2523END
2524
2525 if ($cgiparams{'TYPE'} eq "net") {
2526 print <<END;
2527 <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'remote subnet'}&nbsp;<img src='/blob.gif' alt='*' /></td>
624615ee 2528 <td width='30%'>
dccd7e87 2529 <input type='text' name='REMOTE_SUBNET' value='$remote_subnets' size="25" />
624615ee 2530 </td>
dccd7e87
MT
2531END
2532
2533 } elsif ($cgiparams{'TYPE'} eq "host") {
2534 print <<END;
2535 <td class='boldbase' nowrap='nowrap' width='20%'>$Lang::tr{'dns servers'}:</td>
2536 <td width='30%'>
2537 <input type='text' name='DNS_SERVERS' value='$dns_servers' size="25" />
2538 </td>
2539END
2540 }
2541
2542 print <<END;
ae2782ba
MT
2543 </tr>
2544 <tr>
624615ee
LS
2545 <td class='boldbase' width='20%'>$Lang::tr{'vpn local id'}:</td>
2546 <td width='30%'>
2547 <input type='text' name='LOCAL_ID' value='$cgiparams{'LOCAL_ID'}' size="25" />
2548 </td>
2549 <td class='boldbase' width='20%'>$Lang::tr{'vpn remote id'}:</td>
2550 <td width='30%'>
2551 <input type='text' name='REMOTE_ID' value='$cgiparams{'REMOTE_ID'}' size="25" />
2552 </td>
ae2782ba 2553 </tr>
d2d87f2c 2554 <tr><td colspan="4"><br /></td></tr>
ae2782ba 2555 <tr>
624615ee
LS
2556 <td class='boldbase' width='20%'>$Lang::tr{'remark title'}</td>
2557 <td colspan='3'>
2558 <input type='text' name='REMARK' value='$cgiparams{'REMARK'}' maxlength='50' size="73" />
2559 </td>
ed84e8b8 2560 </tr>
ac1cfefa 2561END
624615ee
LS
2562;
2563 if (!$cgiparams{'KEY'}) {
2564 print "<tr><td colspan='3'><input type='checkbox' name='EDIT_ADVANCED' $checked{'EDIT_ADVANCED'}{'on'} /> $Lang::tr{'edit advanced settings when done'}</td></tr>";
2565 }
2566 print "</table>";
ed84e8b8 2567 &Header::closebox();
ed84e8b8 2568
216bd9b3
MT
2569 if ($cgiparams{'TYPE'} eq 'net') {
2570 &Header::openbox('100%', 'left', $Lang::tr{'ipsec settings'});
2571 print <<EOF;
2572 <table width='100%'>
2573 <tbody>
2574 <tr>
2575 <td class='boldbase' width='20%'>$Lang::tr{'mode'}:</td>
2576 <td width='30%'>
2577 <select name='MODE'>
2578 <option value='tunnel' $selected{'MODE'}{'tunnel'}>$Lang::tr{'ipsec mode tunnel'}</option>
2579 <option value='transport' $selected{'MODE'}{'transport'}>$Lang::tr{'ipsec mode transport'}</option>
2580 </select>
2581 </td>
2582 <td colspan='2'></td>
2583 </tr>
2584
2585 <tr>
2586 <td class='boldbase' width='20%'>$Lang::tr{'interface mode'}:</td>
2587 <td width='30%'>
2588 <select name='INTERFACE_MODE'>
2589 <option value='' $selected{'INTERFACE_MODE'}{''}>$Lang::tr{'ipsec interface mode none'}</option>
2590 <option value='gre' $selected{'INTERFACE_MODE'}{'gre'}>$Lang::tr{'ipsec interface mode gre'}</option>
2591 <option value='vti' $selected{'INTERFACE_MODE'}{'vti'}>$Lang::tr{'ipsec interface mode vti'}</option>
2592 </select>
2593 </td>
2594
2595 <td class='boldbase' width='20%'>$Lang::tr{'ip address'}/$Lang::tr{'subnet mask'}:</td>
2596 <td width='30%'>
2597 <input type="text" name="INTERFACE_ADDRESS" value="$cgiparams{'INTERFACE_ADDRESS'}">
2598 </td>
2599 </tr>
2600
2601 <tr>
2602 <td class='boldbase' width='20%'>$Lang::tr{'mtu'}:</td>
2603 <td width='30%'>
2604 <input type="number" name="INTERFACE_MTU" value="$cgiparams{'INTERFACE_MTU'}" min="576" max="9000">
2605 </td>
2606 <td colspan='2'></td>
2607 </tr>
2608 </tbody>
2609 </table>
2610EOF
2611 &Header::closebox();
2612 }
2613
624615ee
LS
2614 if ($cgiparams{'KEY'} && $cgiparams{'AUTH'} eq 'psk') {
2615 &Header::openbox('100%', 'left', $Lang::tr{'authentication'});
2616 print <<END
2617 <table width='100%' cellpadding='0' cellspacing='5' border='0'>
2618 <tr><td class='base' width='50%'>$Lang::tr{'use a pre-shared key'}</td>
2619 <td class='base' width='50%'><input type='password' name='PSK' size='30' value='$cgiparams{'PSK'}' /></td>
2620 </tr>
2621 </table>
ac1cfefa 2622END
624615ee
LS
2623;
2624 &Header::closebox();
2625 } elsif (! $cgiparams{'KEY'}) {
2626 my $cakeydisabled = ( ! -f "${General::swroot}/private/cakey.pem" ) ? "disabled='disabled'" : '';
2627 $cgiparams{'CERT_NAME'} = $Lang::tr{'vpn no full pki'} if ($cakeydisabled);
2628 my $cacrtdisabled = ( ! -f "${General::swroot}/ca/cacert.pem" ) ? "disabled='disabled'" : '';
2629
2630 &Header::openbox('100%', 'left', $Lang::tr{'authentication'});
2631 print <<END
2632 <table width='100%' cellpadding='0' cellspacing='5' border='0'>
2633 <tr><td width='5%'><input type='radio' name='AUTH' value='psk' $checked{'AUTH'}{'psk'} /></td>
2634 <td class='base' width='55%'>$Lang::tr{'use a pre-shared key'}</td>
2635 <td class='base' width='40%'><input type='password' name='PSK' size='30' value='$cgiparams{'PSK'}' /></td></tr>
2636 <tr><td colspan='3' bgcolor='#000000'></td></tr>
2637 <tr><td><input type='radio' name='AUTH' value='certreq' $checked{'AUTH'}{'certreq'} $cakeydisabled /></td>
2638 <td class='base'><hr />$Lang::tr{'upload a certificate request'}</td>
2639 <td class='base' rowspan='3' valign='middle'><input type='file' name='FH' size='30' $cacrtdisabled /></td></tr>
2640 <tr><td><input type='radio' name='AUTH' value='certfile' $checked{'AUTH'}{'certfile'} $cacrtdisabled /></td>
2641 <td class='base'>$Lang::tr{'upload a certificate'}</td></tr>
2642 <tr><td><input type='radio' name='AUTH' value='pkcs12' $cacrtdisabled /></td>
2643 <td class='base'>$Lang::tr{'upload p12 file'} $Lang::tr{'pkcs12 file password'}:<input type='password' name='P12_PASS'/></td></tr>
2644 <tr><td><input type='radio' name='AUTH' value='auth-dn' $checked{'AUTH'}{'auth-dn'} $cacrtdisabled /></td>
2645 <td class='base'><hr />$Lang::tr{'vpn auth-dn'}</td></tr>
2646 <tr><td colspan='3' bgcolor='#000000'></td></tr>
2647 <tr><td><input type='radio' name='AUTH' value='certgen' $checked{'AUTH'}{'certgen'} $cakeydisabled /></td>
2648 <td class='base'><hr />$Lang::tr{'generate a certificate'}</td><td>&nbsp;</td></tr>
2649 <tr><td>&nbsp;</td>
2650 <td class='base'>$Lang::tr{'users fullname or system hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2651 <td class='base' nowrap='nowrap'><input type='text' name='CERT_NAME' value='$cgiparams{'CERT_NAME'}' size='32' $cakeydisabled /></td></tr>
2652 <tr><td>&nbsp;</td>
2653 <td class='base'>$Lang::tr{'users email'}:</td>
2654 <td class='base' nowrap='nowrap'><input type='text' name='CERT_EMAIL' value='$cgiparams{'CERT_EMAIL'}' size='32' $cakeydisabled /></td></tr>
2655 <tr><td>&nbsp;</td>
2656 <td class='base'>$Lang::tr{'users department'}:</td>
2657 <td class='base' nowrap='nowrap'><input type='text' name='CERT_OU' value='$cgiparams{'CERT_OU'}' size='32' $cakeydisabled /></td></tr>
2658 <tr><td>&nbsp;</td>
2158e11b 2659 <td class='base'>$Lang::tr{'organization name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
624615ee
LS
2660 <td class='base' nowrap='nowrap'><input type='text' name='CERT_ORGANIZATION' value='$cgiparams{'CERT_ORGANIZATION'}' size='32' $cakeydisabled /></td></tr>
2661 <tr><td>&nbsp;</td>
2662 <td class='base'>$Lang::tr{'city'}:</td>
2663 <td class='base' nowrap='nowrap'><input type='text' name='CERT_CITY' value='$cgiparams{'CERT_CITY'}' size='32' $cakeydisabled /></td></tr>
2664 <tr><td>&nbsp;</td>
2665 <td class='base'>$Lang::tr{'state or province'}:</td>
2666 <td class='base' nowrap='nowrap'><input type='text' name='CERT_STATE' value='$cgiparams{'CERT_STATE'}' size='32' $cakeydisabled /></td></tr>
2667 <tr><td>&nbsp;</td>
2668 <td class='base'>$Lang::tr{'country'}:</td>
2669 <td class='base'><select name='CERT_COUNTRY' $cakeydisabled>
2670END
2671;
2672 foreach my $country (sort keys %{Countries::countries}) {
2673 print "\t\t\t<option value='$Countries::countries{$country}'";
2674 if ( $Countries::countries{$country} eq $cgiparams{'CERT_COUNTRY'} ) {
2675 print " selected='selected'";
2676 }
2677 print ">$country</option>\n";
2678 }
2679 print <<END
2680 </select></td></tr>
2681
2682 <tr><td>&nbsp;</td><td class='base'>$Lang::tr{'vpn subjectaltname'} (subjectAltName=email:*,URI:*,DNS:*,RID:*)</td>
2683 <td class='base' nowrap='nowrap'><input type='text' name='SUBJECTALTNAME' value='$cgiparams{'SUBJECTALTNAME'}' size='32' $cakeydisabled /></td></tr>
2684 <tr><td>&nbsp;</td>
2685 <td class='base'>$Lang::tr{'pkcs12 file password'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
2686 <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS1' value='$cgiparams{'CERT_PASS1'}' size='32' $cakeydisabled /></td></tr>
2687 <tr><td>&nbsp;</td><td class='base'>$Lang::tr{'pkcs12 file password'}&nbsp;($Lang::tr{'confirmation'}):&nbsp;<img src='/blob.gif' alt='*' /></td>
2688 <td class='base' nowrap='nowrap'><input type='password' name='CERT_PASS2' value='$cgiparams{'CERT_PASS2'}' size='32' $cakeydisabled /></td></tr>
2689 </table>
2690END
2691;
2692 &Header::closebox();
ac1cfefa
MT
2693 }
2694
624615ee
LS
2695 print "<div align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' />";
2696 if ($cgiparams{'KEY'}) {
2697 print "<input type='submit' name='ACTION' value='$Lang::tr{'advanced'}' />";
2698 }
2699 print "<input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></div></form>";
2700 &Header::closebigbox();
2701 &Header::closepage();
2702 exit (0);
2703
2704 VPNCONF_END:
ac1cfefa
MT
2705}
2706
2707###
2708### Advanced settings
2709###
2710if(($cgiparams{'ACTION'} eq $Lang::tr{'advanced'}) ||
2711 ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'ADVANCED'} eq 'yes')) {
624615ee
LS
2712 &General::readhash("${General::swroot}/vpn/settings", \%vpnsettings);
2713 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
2714 if (! $confighash{$cgiparams{'KEY'}}) {
2715 $errormessage = $Lang::tr{'invalid key'};
2716 goto ADVANCED_END;
2717 }
2718
2719 if ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
2720 my @temp = split('\|', $cgiparams{'IKE_ENCRYPTION'});
2721 if ($#temp < 0) {
2722 $errormessage = $Lang::tr{'invalid input'};
2723 goto ADVANCED_ERROR;
2724 }
2725 foreach my $val (@temp) {
05375f12 2726 if ($val !~ /^(aes(256|192|128)(gcm(128|96|64))?|3des|chacha20poly1305|camellia(256|192|128))$/) {
624615ee
LS
2727 $errormessage = $Lang::tr{'invalid input'};
2728 goto ADVANCED_ERROR;
2729 }
2730 }
2731 @temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
2732 if ($#temp < 0) {
2733 $errormessage = $Lang::tr{'invalid input'};
2734 goto ADVANCED_ERROR;
2735 }
2736 foreach my $val (@temp) {
2737 if ($val !~ /^(sha2_(512|384|256)|sha|md5|aesxcbc)$/) {
2738 $errormessage = $Lang::tr{'invalid input'};
2739 goto ADVANCED_ERROR;
2740 }
2741 }
2742 @temp = split('\|', $cgiparams{'IKE_GROUPTYPE'});
2743 if ($#temp < 0) {
2744 $errormessage = $Lang::tr{'invalid input'};
2745 goto ADVANCED_ERROR;
2746 }
2747 foreach my $val (@temp) {
7f662098 2748 if ($val !~ /^(curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192)$/) {
624615ee
LS
2749 $errormessage = $Lang::tr{'invalid input'};
2750 goto ADVANCED_ERROR;
2751 }
2752 }
2753 if ($cgiparams{'IKE_LIFETIME'} !~ /^\d+$/) {
2754 $errormessage = $Lang::tr{'invalid input for ike lifetime'};
2755 goto ADVANCED_ERROR;
2756 }
610108ff 2757 if ($cgiparams{'IKE_LIFETIME'} < 1 || $cgiparams{'IKE_LIFETIME'} > 24) {
81ebfac7 2758 $errormessage = $Lang::tr{'ike lifetime should be between 1 and 24 hours'};
624615ee
LS
2759 goto ADVANCED_ERROR;
2760 }
2761 @temp = split('\|', $cgiparams{'ESP_ENCRYPTION'});
2762 if ($#temp < 0) {
2763 $errormessage = $Lang::tr{'invalid input'};
2764 goto ADVANCED_ERROR;
2765 }
2766 foreach my $val (@temp) {
05375f12 2767 if ($val !~ /^(aes(256|192|128)(gcm(128|96|64))?|3des|chacha20poly1305|camellia(256|192|128))$/) {
624615ee
LS
2768 $errormessage = $Lang::tr{'invalid input'};
2769 goto ADVANCED_ERROR;
2770 }
2771 }
2772 @temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
2773 if ($#temp < 0) {
2774 $errormessage = $Lang::tr{'invalid input'};
2775 goto ADVANCED_ERROR;
2776 }
2777 foreach my $val (@temp) {
2778 if ($val !~ /^(sha2_(512|384|256)|sha1|md5|aesxcbc)$/) {
2779 $errormessage = $Lang::tr{'invalid input'};
2780 goto ADVANCED_ERROR;
2781 }
2782 }
2783 @temp = split('\|', $cgiparams{'ESP_GROUPTYPE'});
2784 if ($#temp < 0) {
2785 $errormessage = $Lang::tr{'invalid input'};
2786 goto ADVANCED_ERROR;
2787 }
2788 foreach my $val (@temp) {
7f662098 2789 if ($val !~ /^(curve448|curve25519|e521|e384|e256|e224|e192|e512bp|e384bp|e256bp|e224bp|768|1024|1536|2048|3072|4096|6144|8192|none)$/) {
624615ee
LS
2790 $errormessage = $Lang::tr{'invalid input'};
2791 goto ADVANCED_ERROR;
2792 }
2793 }
2794 if ($cgiparams{'ESP_KEYLIFE'} !~ /^\d+$/) {
2795 $errormessage = $Lang::tr{'invalid input for esp keylife'};
2796 goto ADVANCED_ERROR;
2797 }
2798 if ($cgiparams{'ESP_KEYLIFE'} < 1 || $cgiparams{'ESP_KEYLIFE'} > 24) {
2799 $errormessage = $Lang::tr{'esp keylife should be between 1 and 24 hours'};
2800 goto ADVANCED_ERROR;
2801 }
2802
2803 if (($cgiparams{'COMPRESSION'} !~ /^(|on|off)$/) ||
2804 ($cgiparams{'FORCE_MOBIKE'} !~ /^(|on|off)$/) ||
2805 ($cgiparams{'ONLY_PROPOSED'} !~ /^(|on|off)$/) ||
2806 ($cgiparams{'PFS'} !~ /^(|on|off)$/)) {
2807 $errormessage = $Lang::tr{'invalid input'};
2808 goto ADVANCED_ERROR;
2809 }
2810
2811 if ($cgiparams{'DPD_DELAY'} !~ /^\d+$/) {
2812 $errormessage = $Lang::tr{'invalid input for dpd delay'};
2813 goto ADVANCED_ERROR;
2814 }
2815
2816 if ($cgiparams{'DPD_TIMEOUT'} !~ /^\d+$/) {
2817 $errormessage = $Lang::tr{'invalid input for dpd timeout'};
2818 goto ADVANCED_ERROR;
2819 }
2820
af183eeb
MT
2821 if ($cgiparams{'INACTIVITY_TIMEOUT'} !~ /^\d+$/) {
2822 $errormessage = $Lang::tr{'invalid input for inactivity timeout'};
2823 goto ADVANCED_ERROR;
2824 }
2825
624615ee
LS
2826 $confighash{$cgiparams{'KEY'}}[29] = $cgiparams{'IKE_VERSION'};
2827 $confighash{$cgiparams{'KEY'}}[18] = $cgiparams{'IKE_ENCRYPTION'};
2828 $confighash{$cgiparams{'KEY'}}[19] = $cgiparams{'IKE_INTEGRITY'};
2829 $confighash{$cgiparams{'KEY'}}[20] = $cgiparams{'IKE_GROUPTYPE'};
2830 $confighash{$cgiparams{'KEY'}}[16] = $cgiparams{'IKE_LIFETIME'};
2831 $confighash{$cgiparams{'KEY'}}[21] = $cgiparams{'ESP_ENCRYPTION'};
2832 $confighash{$cgiparams{'KEY'}}[22] = $cgiparams{'ESP_INTEGRITY'};
2833 $confighash{$cgiparams{'KEY'}}[23] = $cgiparams{'ESP_GROUPTYPE'};
2834 $confighash{$cgiparams{'KEY'}}[17] = $cgiparams{'ESP_KEYLIFE'};
2835 $confighash{$cgiparams{'KEY'}}[12] = 'off'; #$cgiparams{'AGGRMODE'};
2836 $confighash{$cgiparams{'KEY'}}[13] = $cgiparams{'COMPRESSION'};
2837 $confighash{$cgiparams{'KEY'}}[24] = $cgiparams{'ONLY_PROPOSED'};
2838 $confighash{$cgiparams{'KEY'}}[28] = $cgiparams{'PFS'};
2839 $confighash{$cgiparams{'KEY'}}[27] = $cgiparams{'DPD_ACTION'};
2840 $confighash{$cgiparams{'KEY'}}[30] = $cgiparams{'DPD_TIMEOUT'};
2841 $confighash{$cgiparams{'KEY'}}[31] = $cgiparams{'DPD_DELAY'};
2842 $confighash{$cgiparams{'KEY'}}[32] = $cgiparams{'FORCE_MOBIKE'};
dcb406cc 2843 $confighash{$cgiparams{'KEY'}}[33] = $cgiparams{'START_ACTION'};
af183eeb 2844 $confighash{$cgiparams{'KEY'}}[34] = $cgiparams{'INACTIVITY_TIMEOUT'};
624615ee
LS
2845 &General::writehasharray("${General::swroot}/vpn/config", \%confighash);
2846 &writeipsecfiles();
2847 if (&vpnenabled) {
a81cbf61 2848 &General::system('/usr/local/bin/ipsecctrl', 'S', $cgiparams{'KEY'});
624615ee
LS
2849 sleep $sleepDelay;
2850 }
2851 goto ADVANCED_END;
2852 } else {
2853 $cgiparams{'IKE_VERSION'} = $confighash{$cgiparams{'KEY'}}[29];
2854 $cgiparams{'IKE_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[18];
2855 $cgiparams{'IKE_INTEGRITY'} = $confighash{$cgiparams{'KEY'}}[19];
2856 $cgiparams{'IKE_GROUPTYPE'} = $confighash{$cgiparams{'KEY'}}[20];
2857 $cgiparams{'IKE_LIFETIME'} = $confighash{$cgiparams{'KEY'}}[16];
2858 $cgiparams{'ESP_ENCRYPTION'} = $confighash{$cgiparams{'KEY'}}[21];
2859 $cgiparams{'ESP_INTEGRITY'} = $confighash{$cgiparams{'KEY'}}[22];
2860 $cgiparams{'ESP_GROUPTYPE'} = $confighash{$cgiparams{'KEY'}}[23];
2861 if ($cgiparams{'ESP_GROUPTYPE'} eq "") {
2862 $cgiparams{'ESP_GROUPTYPE'} = $cgiparams{'IKE_GROUPTYPE'};
2863 }
2864 $cgiparams{'ESP_KEYLIFE'} = $confighash{$cgiparams{'KEY'}}[17];
2865 $cgiparams{'COMPRESSION'} = $confighash{$cgiparams{'KEY'}}[13];
2866 $cgiparams{'ONLY_PROPOSED'} = $confighash{$cgiparams{'KEY'}}[24];
2867 $cgiparams{'PFS'} = $confighash{$cgiparams{'KEY'}}[28];
2868 $cgiparams{'DPD_ACTION'} = $confighash{$cgiparams{'KEY'}}[27];
2869 $cgiparams{'DPD_TIMEOUT'} = $confighash{$cgiparams{'KEY'}}[30];
2870 $cgiparams{'DPD_DELAY'} = $confighash{$cgiparams{'KEY'}}[31];
2871 $cgiparams{'FORCE_MOBIKE'} = $confighash{$cgiparams{'KEY'}}[32];
dcb406cc 2872 $cgiparams{'START_ACTION'} = $confighash{$cgiparams{'KEY'}}[33];
af183eeb 2873 $cgiparams{'INACTIVITY_TIMEOUT'} = $confighash{$cgiparams{'KEY'}}[34];
29f5e0e2 2874 $cgiparams{'MODE'} = $confighash{$cgiparams{'KEY'}}[35];
cae1f4a7 2875 $cgiparams{'INTERFACE_MODE'} = $confighash{$cgiparams{'KEY'}}[36];
74641317 2876 $cgiparams{'INTERFACE_ADDRESS'} = $confighash{$cgiparams{'KEY'}}[37];
55842dda 2877 $cgiparams{'INTERFACE_MTU'} = $confighash{$cgiparams{'KEY'}}[38];
dccd7e87 2878 $cgiparams{'DNS_SERVERS'} = $confighash{$cgiparams{'KEY'}}[39];
624615ee
LS
2879
2880 if (!$cgiparams{'DPD_DELAY'}) {
2881 $cgiparams{'DPD_DELAY'} = 30;
2882 }
2883
2884 if (!$cgiparams{'DPD_TIMEOUT'}) {
2885 $cgiparams{'DPD_TIMEOUT'} = 120;
2886 }
dcb406cc
MT
2887
2888 if (!$cgiparams{'START_ACTION'}) {
2889 $cgiparams{'START_ACTION'} = "start";
2890 }
af183eeb
MT
2891
2892 if ($cgiparams{'INACTIVITY_TIMEOUT'} eq "") {
2893 $cgiparams{'INACTIVITY_TIMEOUT'} = 900; # 15 min
2894 }
29f5e0e2
MT
2895
2896 if ($cgiparams{'MODE'} eq "") {
2897 $cgiparams{'MODE'} = "tunnel";
2898 }
ac1cfefa 2899 }
624615ee
LS
2900
2901 ADVANCED_ERROR:
05375f12 2902 $checked{'IKE_ENCRYPTION'}{'chacha20poly1305'} = '';
624615ee
LS
2903 $checked{'IKE_ENCRYPTION'}{'aes256'} = '';
2904 $checked{'IKE_ENCRYPTION'}{'aes192'} = '';
2905 $checked{'IKE_ENCRYPTION'}{'aes128'} = '';
2906 $checked{'IKE_ENCRYPTION'}{'aes256gcm128'} = '';
2907 $checked{'IKE_ENCRYPTION'}{'aes192gcm128'} = '';
2908 $checked{'IKE_ENCRYPTION'}{'aes128gcm128'} = '';
2909 $checked{'IKE_ENCRYPTION'}{'aes256gcm96'} = '';
2910 $checked{'IKE_ENCRYPTION'}{'aes192gcm96'} = '';
2911 $checked{'IKE_ENCRYPTION'}{'aes128gcm96'} = '';
2912 $checked{'IKE_ENCRYPTION'}{'aes256gcm64'} = '';
2913 $checked{'IKE_ENCRYPTION'}{'aes192gcm64'} = '';
2914 $checked{'IKE_ENCRYPTION'}{'aes128gcm64'} = '';
2915 $checked{'IKE_ENCRYPTION'}{'3des'} = '';
2916 $checked{'IKE_ENCRYPTION'}{'camellia256'} = '';
2917 $checked{'IKE_ENCRYPTION'}{'camellia192'} = '';
2918 $checked{'IKE_ENCRYPTION'}{'camellia128'} = '';
2919 my @temp = split('\|', $cgiparams{'IKE_ENCRYPTION'});
2920 foreach my $key (@temp) {$checked{'IKE_ENCRYPTION'}{$key} = "selected='selected'"; }
2921 $checked{'IKE_INTEGRITY'}{'sha2_512'} = '';
2922 $checked{'IKE_INTEGRITY'}{'sha2_384'} = '';
2923 $checked{'IKE_INTEGRITY'}{'sha2_256'} = '';
2924 $checked{'IKE_INTEGRITY'}{'sha'} = '';
2925 $checked{'IKE_INTEGRITY'}{'md5'} = '';
2926 $checked{'IKE_INTEGRITY'}{'aesxcbc'} = '';
ac1cfefa 2927 @temp = split('\|', $cgiparams{'IKE_INTEGRITY'});
624615ee 2928 foreach my $key (@temp) {$checked{'IKE_INTEGRITY'}{$key} = "selected='selected'"; }
d47b2cc2 2929 $checked{'IKE_GROUPTYPE'}{'curve448'} = '';
7f662098 2930 $checked{'IKE_GROUPTYPE'}{'curve25519'} = '';
624615ee
LS
2931 $checked{'IKE_GROUPTYPE'}{'768'} = '';
2932 $checked{'IKE_GROUPTYPE'}{'1024'} = '';
2933 $checked{'IKE_GROUPTYPE'}{'1536'} = '';
2934 $checked{'IKE_GROUPTYPE'}{'2048'} = '';
2935 $checked{'IKE_GROUPTYPE'}{'3072'} = '';
2936 $checked{'IKE_GROUPTYPE'}{'4096'} = '';
2937 $checked{'IKE_GROUPTYPE'}{'6144'} = '';
2938 $checked{'IKE_GROUPTYPE'}{'8192'} = '';
ac1cfefa 2939 @temp = split('\|', $cgiparams{'IKE_GROUPTYPE'});
624615ee
LS
2940 foreach my $key (@temp) {$checked{'IKE_GROUPTYPE'}{$key} = "selected='selected'"; }
2941
05375f12 2942 $checked{'ESP_ENCRYPTION'}{'chacha20poly1305'} = '';
624615ee
LS
2943 $checked{'ESP_ENCRYPTION'}{'aes256'} = '';
2944 $checked{'ESP_ENCRYPTION'}{'aes192'} = '';
2945 $checked{'ESP_ENCRYPTION'}{'aes128'} = '';
2946 $checked{'ESP_ENCRYPTION'}{'aes256gcm128'} = '';
2947 $checked{'ESP_ENCRYPTION'}{'aes192gcm128'} = '';
2948 $checked{'ESP_ENCRYPTION'}{'aes128gcm128'} = '';
2949 $checked{'ESP_ENCRYPTION'}{'aes256gcm96'} = '';
2950 $checked{'ESP_ENCRYPTION'}{'aes192gcm96'} = '';
2951 $checked{'ESP_ENCRYPTION'}{'aes128gcm96'} = '';
2952 $checked{'ESP_ENCRYPTION'}{'aes256gcm64'} = '';
2953 $checked{'ESP_ENCRYPTION'}{'aes192gcm64'} = '';
2954 $checked{'ESP_ENCRYPTION'}{'aes128gcm64'} = '';
2955 $checked{'ESP_ENCRYPTION'}{'3des'} = '';
2956 $checked{'ESP_ENCRYPTION'}{'camellia256'} = '';
2957 $checked{'ESP_ENCRYPTION'}{'camellia192'} = '';
2958 $checked{'ESP_ENCRYPTION'}{'camellia128'} = '';
ac1cfefa 2959 @temp = split('\|', $cgiparams{'ESP_ENCRYPTION'});
624615ee
LS
2960 foreach my $key (@temp) {$checked{'ESP_ENCRYPTION'}{$key} = "selected='selected'"; }
2961 $checked{'ESP_INTEGRITY'}{'sha2_512'} = '';
2962 $checked{'ESP_INTEGRITY'}{'sha2_384'} = '';
2963 $checked{'ESP_INTEGRITY'}{'sha2_256'} = '';
2964 $checked{'ESP_INTEGRITY'}{'sha1'} = '';
2965 $checked{'ESP_INTEGRITY'}{'md5'} = '';
2966 $checked{'ESP_INTEGRITY'}{'aesxcbc'} = '';
ac1cfefa 2967 @temp = split('\|', $cgiparams{'ESP_INTEGRITY'});
624615ee 2968 foreach my $key (@temp) {$checked{'ESP_INTEGRITY'}{$key} = "selected='selected'"; }
d47b2cc2 2969 $checked{'ESP_GROUPTYPE'}{'curve448'} = '';
7f662098 2970 $checked{'ESP_GROUPTYPE'}{'curve25519'} = '';
624615ee
LS
2971 $checked{'ESP_GROUPTYPE'}{'768'} = '';
2972 $checked{'ESP_GROUPTYPE'}{'1024'} = '';
2973 $checked{'ESP_GROUPTYPE'}{'1536'} = '';
2974 $checked{'ESP_GROUPTYPE'}{'2048'} = '';
2975 $checked{'ESP_GROUPTYPE'}{'3072'} = '';
2976 $checked{'ESP_GROUPTYPE'}{'4096'} = '';
2977 $checked{'ESP_GROUPTYPE'}{'6144'} = '';
2978 $checked{'ESP_GROUPTYPE'}{'8192'} = '';
2979 $checked{'ESP_GROUPTYPE'}{'none'} = '';
4b02b404 2980 @temp = split('\|', $cgiparams{'ESP_GROUPTYPE'});
624615ee 2981 foreach my $key (@temp) {$checked{'ESP_GROUPTYPE'}{$key} = "selected='selected'"; }
ed84e8b8 2982
624615ee
LS
2983 $checked{'COMPRESSION'} = $cgiparams{'COMPRESSION'} eq 'on' ? "checked='checked'" : '' ;
2984 $checked{'FORCE_MOBIKE'} = $cgiparams{'FORCE_MOBIKE'} eq 'on' ? "checked='checked'" : '' ;
2985 $checked{'ONLY_PROPOSED'} = $cgiparams{'ONLY_PROPOSED'} eq 'on' ? "checked='checked'" : '' ;
2986 $checked{'PFS'} = $cgiparams{'PFS'} eq 'on' ? "checked='checked'" : '' ;
cbb3a8f9 2987
624615ee
LS
2988 $selected{'IKE_VERSION'}{'ikev1'} = '';
2989 $selected{'IKE_VERSION'}{'ikev2'} = '';
2990 $selected{'IKE_VERSION'}{$cgiparams{'IKE_VERSION'}} = "selected='selected'";
cbb3a8f9 2991
624615ee
LS
2992 $selected{'DPD_ACTION'}{'clear'} = '';
2993 $selected{'DPD_ACTION'}{'hold'} = '';
2994 $selected{'DPD_ACTION'}{'restart'} = '';
2995 $selected{'DPD_ACTION'}{'none'} = '';
2996 $selected{'DPD_ACTION'}{$cgiparams{'DPD_ACTION'}} = "selected='selected'";
ac1cfefa 2997
237f3ab7 2998 $selected{'START_ACTION'}{'add'} = '';
dcb406cc
MT
2999 $selected{'START_ACTION'}{'route'} = '';
3000 $selected{'START_ACTION'}{'start'} = '';
3001 $selected{'START_ACTION'}{$cgiparams{'START_ACTION'}} = "selected='selected'";
3002
af183eeb
MT
3003 $selected{'INACTIVITY_TIMEOUT'} = ();
3004 foreach my $timeout (keys %INACTIVITY_TIMEOUTS) {
3005 $selected{'INACTIVITY_TIMEOUT'}{$timeout} = "";
3006 }
3007 $selected{'INACTIVITY_TIMEOUT'}{$cgiparams{'INACTIVITY_TIMEOUT'}} = "selected";
3008
624615ee
LS
3009 &Header::showhttpheaders();
3010 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
3011 &Header::openbigbox('100%', 'left', '', $errormessage);
3012
3013 if ($errormessage) {
3014 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
3015 print "<class name='base'>$errormessage";
3016 print "&nbsp;</class>";
3017 &Header::closebox();
3018 }
3019
3020 if ($warnmessage) {
3021 &Header::openbox('100%', 'left', $Lang::tr{'warning messages'});
3022 print "<class name='base'>$warnmessage";
3023 print "&nbsp;</class>";
3024 &Header::closebox();
3025 }
ac1cfefa 3026
624615ee 3027 &Header::openbox('100%', 'left', "$Lang::tr{'advanced'}:");
dcb406cc 3028 print <<EOF;
624615ee
LS
3029 <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
3030 <input type='hidden' name='ADVANCED' value='yes' />
3031 <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
ac1cfefa 3032
624615ee 3033 <table width='100%'>
63e3da59
MT
3034 <thead>
3035 <tr>
cbb3a8f9 3036 <th width="15%"></th>
63e3da59
MT
3037 <th>IKE</th>
3038 <th>ESP</th>
3039 </tr>
3040 </thead>
3041 <tbody>
4ad0b5b6
MT
3042 <tr>
3043 <td>$Lang::tr{'vpn keyexchange'}:</td>
3044 <td>
3045 <select name='IKE_VERSION'>
3046 <option value='ikev2' $selected{'IKE_VERSION'}{'ikev2'}>IKEv2</option>
3047 <option value='ikev1' $selected{'IKE_VERSION'}{'ikev1'}>IKEv1</option>
3048 </select>
3049 </td>
3050 <td></td>
3051 </tr>
63e3da59 3052 <tr>
cbb3a8f9 3053 <td class='boldbase' width="15%">$Lang::tr{'encryption'}</td>
63e3da59
MT
3054 <td class='boldbase'>
3055 <select name='IKE_ENCRYPTION' multiple='multiple' size='6' style='width: 100%'>
05375f12 3056 <option value='chacha20poly1305' $checked{'IKE_ENCRYPTION'}{'chacha20poly1305'}>256 bit ChaCha20-Poly1305/128 bit ICV</option>
dfea4f86 3057 <option value='aes256gcm128' $checked{'IKE_ENCRYPTION'}{'aes256gcm128'}>256 bit AES-GCM/128 bit ICV</option>
dfea4f86 3058 <option value='aes256gcm96' $checked{'IKE_ENCRYPTION'}{'aes256gcm96'}>256 bit AES-GCM/96 bit ICV</option>
dfea4f86 3059 <option value='aes256gcm64' $checked{'IKE_ENCRYPTION'}{'aes256gcm64'}>256 bit AES-GCM/64 bit ICV</option>
a4d24f90 3060 <option value='aes256' $checked{'IKE_ENCRYPTION'}{'aes256'}>256 bit AES-CBC</option>
dfea4f86 3061 <option value='camellia256' $checked{'IKE_ENCRYPTION'}{'camellia256'}>256 bit Camellia-CBC</option>
a4d24f90
MT
3062 <option value='aes192gcm128' $checked{'IKE_ENCRYPTION'}{'aes192gcm128'}>192 bit AES-GCM/128 bit ICV</option>
3063 <option value='aes192gcm96' $checked{'IKE_ENCRYPTION'}{'aes192gcm96'}>192 bit AES-GCM/96 bit ICV</option>
3064 <option value='aes192gcm64' $checked{'IKE_ENCRYPTION'}{'aes192gcm64'}>192 bit AES-GCM/64 bit ICV</option>
3065 <option value='aes192' $checked{'IKE_ENCRYPTION'}{'aes192'}>192 bit AES-CBC</option>
dfea4f86 3066 <option value='camellia192' $checked{'IKE_ENCRYPTION'}{'camellia192'}>192 bit Camellia-CBC</option>
a4d24f90
MT
3067 <option value='aes128gcm128' $checked{'IKE_ENCRYPTION'}{'aes128gcm128'}>128 bit AES-GCM/128 bit ICV</option>
3068 <option value='aes128gcm96' $checked{'IKE_ENCRYPTION'}{'aes128gcm96'}>128 bit AES-GCM/96 bit ICV</option>
3069 <option value='aes128gcm64' $checked{'IKE_ENCRYPTION'}{'aes128gcm64'}>128 bit AES-GCM/64 bit ICV</option>
3070 <option value='aes128' $checked{'IKE_ENCRYPTION'}{'aes128'}>128 bit AES-CBC</option>
dfea4f86 3071 <option value='camellia128' $checked{'IKE_ENCRYPTION'}{'camellia128'}>128 bit Camellia-CBC</option>
6fc0f5eb 3072 <option value='3des' $checked{'IKE_ENCRYPTION'}{'3des'}>168 bit 3DES-EDE-CBC ($Lang::tr{'vpn weak'})</option>
63e3da59
MT
3073 </select>
3074 </td>
3075 <td class='boldbase'>
3076 <select name='ESP_ENCRYPTION' multiple='multiple' size='6' style='width: 100%'>
05375f12 3077 <option value='chacha20poly1305' $checked{'ESP_ENCRYPTION'}{'chacha20poly1305'}>256 bit ChaCha20-Poly1305/128 bit ICV</option>
dfea4f86 3078 <option value='aes256gcm128' $checked{'ESP_ENCRYPTION'}{'aes256gcm128'}>256 bit AES-GCM/128 bit ICV</option>
dfea4f86 3079 <option value='aes256gcm96' $checked{'ESP_ENCRYPTION'}{'aes256gcm96'}>256 bit AES-GCM/96 bit ICV</option>
dfea4f86 3080 <option value='aes256gcm64' $checked{'ESP_ENCRYPTION'}{'aes256gcm64'}>256 bit AES-GCM/64 bit ICV</option>
a4d24f90 3081 <option value='aes256' $checked{'ESP_ENCRYPTION'}{'aes256'}>256 bit AES-CBC</option>
dfea4f86 3082 <option value='camellia256' $checked{'ESP_ENCRYPTION'}{'camellia256'}>256 bit Camellia-CBC</option>
a4d24f90
MT
3083 <option value='aes192gcm128' $checked{'ESP_ENCRYPTION'}{'aes192gcm128'}>192 bit AES-GCM/128 bit ICV</option>
3084 <option value='aes192gcm96' $checked{'ESP_ENCRYPTION'}{'aes192gcm96'}>192 bit AES-GCM/96 bit ICV</option>
3085 <option value='aes192gcm64' $checked{'ESP_ENCRYPTION'}{'aes192gcm64'}>192 bit AES-GCM/64 bit ICV</option>
3086 <option value='aes192' $checked{'ESP_ENCRYPTION'}{'aes192'}>192 bit AES-CBC</option>
dfea4f86 3087 <option value='camellia192' $checked{'ESP_ENCRYPTION'}{'camellia192'}>192 bit Camellia-CBC</option>
a4d24f90
MT
3088 <option value='aes128gcm128' $checked{'ESP_ENCRYPTION'}{'aes128gcm128'}>128 bit AES-GCM/128 bit ICV</option>
3089 <option value='aes128gcm96' $checked{'ESP_ENCRYPTION'}{'aes128gcm96'}>128 bit AES-GCM/96 bit ICV</option>
3090 <option value='aes128gcm64' $checked{'ESP_ENCRYPTION'}{'aes128gcm64'}>128 bit AES-GCM/64 bit ICV</option>
3091 <option value='aes128' $checked{'ESP_ENCRYPTION'}{'aes128'}>128 bit AES-CBC</option>
dfea4f86 3092 <option value='camellia128' $checked{'ESP_ENCRYPTION'}{'camellia128'}>128 bit Camellia-CBC</option>
6fc0f5eb 3093 <option value='3des' $checked{'ESP_ENCRYPTION'}{'3des'}>168 bit 3DES-EDE-CBC ($Lang::tr{'vpn weak'})</option>
63e3da59
MT
3094 </select>
3095 </td>
3096 </tr>
ed84e8b8 3097
63e3da59 3098 <tr>
cbb3a8f9 3099 <td class='boldbase' width="15%">$Lang::tr{'integrity'}</td>
63e3da59
MT
3100 <td class='boldbase'>
3101 <select name='IKE_INTEGRITY' multiple='multiple' size='6' style='width: 100%'>
3102 <option value='sha2_512' $checked{'IKE_INTEGRITY'}{'sha2_512'}>SHA2 512 bit</option>
3103 <option value='sha2_384' $checked{'IKE_INTEGRITY'}{'sha2_384'}>SHA2 384 bit</option>
3104 <option value='sha2_256' $checked{'IKE_INTEGRITY'}{'sha2_256'}>SHA2 256 bit</option>
a4d24f90 3105 <option value='aesxcbc' $checked{'IKE_INTEGRITY'}{'aesxcbc'}>AES XCBC</option>
c94d1976 3106 <option value='sha' $checked{'IKE_INTEGRITY'}{'sha'}>SHA1 ($Lang::tr{'vpn weak'})</option>
86282bdc 3107 <option value='md5' $checked{'IKE_INTEGRITY'}{'md5'}>MD5 ($Lang::tr{'vpn broken'})</option>
63e3da59
MT
3108 </select>
3109 </td>
3110 <td class='boldbase'>
3111 <select name='ESP_INTEGRITY' multiple='multiple' size='6' style='width: 100%'>
3112 <option value='sha2_512' $checked{'ESP_INTEGRITY'}{'sha2_512'}>SHA2 512 bit</option>
3113 <option value='sha2_384' $checked{'ESP_INTEGRITY'}{'sha2_384'}>SHA2 384 bit</option>
3114 <option value='sha2_256' $checked{'ESP_INTEGRITY'}{'sha2_256'}>SHA2 256 bit</option>
a4d24f90 3115 <option value='aesxcbc' $checked{'ESP_INTEGRITY'}{'aesxcbc'}>AES XCBC</option>
c94d1976
MT
3116 <option value='sha1' $checked{'ESP_INTEGRITY'}{'sha1'}>SHA1 ($Lang::tr{'vpn weak'})</option>
3117 <option value='md5' $checked{'ESP_INTEGRITY'}{'md5'}>MD5 ($Lang::tr{'vpn broken'})</option>
63e3da59
MT
3118 </select>
3119 </td>
3120 </tr>
3121 <tr>
e3edceeb 3122 <td class='boldbase' width="15%">$Lang::tr{'lifetime'}&nbsp;<img src='/blob.gif' alt='*' /></td>
63e3da59
MT
3123 <td class='boldbase'>
3124 <input type='text' name='IKE_LIFETIME' value='$cgiparams{'IKE_LIFETIME'}' size='5' /> $Lang::tr{'hours'}
3125 </td>
3126 <td class='boldbase'>
3127 <input type='text' name='ESP_KEYLIFE' value='$cgiparams{'ESP_KEYLIFE'}' size='5' /> $Lang::tr{'hours'}
3128 </td>
3129 </tr>
3130 <tr>
cbb3a8f9 3131 <td class='boldbase' width="15%">$Lang::tr{'grouptype'}</td>
63e3da59
MT
3132 <td class='boldbase'>
3133 <select name='IKE_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
d47b2cc2 3134 <option value='curve448' $checked{'IKE_GROUPTYPE'}{'curve448'}>Curve 448 (224 bit)</option>
7f662098 3135 <option value='curve25519' $checked{'IKE_GROUPTYPE'}{'curve25519'}>Curve 25519 (128 bit)</option>
63e3da59 3136 <option value='e521' $checked{'IKE_GROUPTYPE'}{'e521'}>ECP-521 (NIST)</option>
63e3da59 3137 <option value='e512bp' $checked{'IKE_GROUPTYPE'}{'e512bp'}>ECP-512 (Brainpool)</option>
a4d24f90 3138 <option value='e384' $checked{'IKE_GROUPTYPE'}{'e384'}>ECP-384 (NIST)</option>
63e3da59 3139 <option value='e384bp' $checked{'IKE_GROUPTYPE'}{'e384bp'}>ECP-384 (Brainpool)</option>
a4d24f90 3140 <option value='e256' $checked{'IKE_GROUPTYPE'}{'e256'}>ECP-256 (NIST)</option>
63e3da59 3141 <option value='e256bp' $checked{'IKE_GROUPTYPE'}{'e256bp'}>ECP-256 (Brainpool)</option>
a4d24f90 3142 <option value='e224' $checked{'IKE_GROUPTYPE'}{'e224'}>ECP-224 (NIST)</option>
63e3da59 3143 <option value='e224bp' $checked{'IKE_GROUPTYPE'}{'e224bp'}>ECP-224 (Brainpool)</option>
a4d24f90 3144 <option value='e192' $checked{'IKE_GROUPTYPE'}{'e192'}>ECP-192 (NIST)</option>
63e3da59
MT
3145 <option value='8192' $checked{'IKE_GROUPTYPE'}{'8192'}>MODP-8192</option>
3146 <option value='6144' $checked{'IKE_GROUPTYPE'}{'6144'}>MODP-6144</option>
3147 <option value='4096' $checked{'IKE_GROUPTYPE'}{'4096'}>MODP-4096</option>
3148 <option value='3072' $checked{'IKE_GROUPTYPE'}{'3072'}>MODP-3072</option>
63e3da59
MT
3149 <option value='2048' $checked{'IKE_GROUPTYPE'}{'2048'}>MODP-2048</option>
3150 <option value='1536' $checked{'IKE_GROUPTYPE'}{'1536'}>MODP-1536</option>
c94d1976
MT
3151 <option value='1024' $checked{'IKE_GROUPTYPE'}{'1024'}>MODP-1024 ($Lang::tr{'vpn broken'})</option>
3152 <option value='768' $checked{'IKE_GROUPTYPE'}{'768'}>MODP-768 ($Lang::tr{'vpn broken'})</option>
63e3da59
MT
3153 </select>
3154 </td>
4b02b404
MT
3155 <td class='boldbase'>
3156 <select name='ESP_GROUPTYPE' multiple='multiple' size='6' style='width: 100%'>
d47b2cc2 3157 <option value='curve448' $checked{'ESP_GROUPTYPE'}{'curve448'}>Curve 448 (224 bit)</option>
7f662098 3158 <option value='curve25519' $checked{'ESP_GROUPTYPE'}{'curve25519'}>Curve 25519 (128 bit)</option>
4b02b404
MT
3159 <option value='e521' $checked{'ESP_GROUPTYPE'}{'e521'}>ECP-521 (NIST)</option>
3160 <option value='e512bp' $checked{'ESP_GROUPTYPE'}{'e512bp'}>ECP-512 (Brainpool)</option>
3161 <option value='e384' $checked{'ESP_GROUPTYPE'}{'e384'}>ECP-384 (NIST)</option>
3162 <option value='e384bp' $checked{'ESP_GROUPTYPE'}{'e384bp'}>ECP-384 (Brainpool)</option>
3163 <option value='e256' $checked{'ESP_GROUPTYPE'}{'e256'}>ECP-256 (NIST)</option>
3164 <option value='e256bp' $checked{'ESP_GROUPTYPE'}{'e256bp'}>ECP-256 (Brainpool)</option>
3165 <option value='e224' $checked{'ESP_GROUPTYPE'}{'e224'}>ECP-224 (NIST)</option>
3166 <option value='e224bp' $checked{'ESP_GROUPTYPE'}{'e224bp'}>ECP-224 (Brainpool)</option>
3167 <option value='e192' $checked{'ESP_GROUPTYPE'}{'e192'}>ECP-192 (NIST)</option>
3168 <option value='8192' $checked{'ESP_GROUPTYPE'}{'8192'}>MODP-8192</option>
3169 <option value='6144' $checked{'ESP_GROUPTYPE'}{'6144'}>MODP-6144</option>
3170 <option value='4096' $checked{'ESP_GROUPTYPE'}{'4096'}>MODP-4096</option>
3171 <option value='3072' $checked{'ESP_GROUPTYPE'}{'3072'}>MODP-3072</option>
4b02b404
MT
3172 <option value='2048' $checked{'ESP_GROUPTYPE'}{'2048'}>MODP-2048</option>
3173 <option value='1536' $checked{'ESP_GROUPTYPE'}{'1536'}>MODP-1536</option>
c94d1976
MT
3174 <option value='1024' $checked{'ESP_GROUPTYPE'}{'1024'}>MODP-1024 ($Lang::tr{'vpn broken'})</option>
3175 <option value='768' $checked{'ESP_GROUPTYPE'}{'768'}>MODP-768 ($Lang::tr{'vpn broken'})</option>
4b02b404
MT
3176 <option value='none' $checked{'ESP_GROUPTYPE'}{'none'}>- $Lang::tr{'none'} -</option>
3177 </select>
3178 </td>
63e3da59
MT
3179 </tr>
3180 </tbody>
624615ee 3181 </table>
63e3da59 3182
cbb3a8f9
MT
3183 <br><br>
3184
3185 <h2>$Lang::tr{'dead peer detection'}</h2>
3186
624615ee
LS
3187 <table width="100%">
3188 <tr>
cbb3a8f9
MT
3189 <td width="15%">$Lang::tr{'dpd action'}:</td>
3190 <td>
3191 <select name='DPD_ACTION'>
afd5d8f7 3192 <option value='none' $selected{'DPD_ACTION'}{'none'}>- $Lang::tr{'disabled'} -</option>
cbb3a8f9
MT
3193 <option value='clear' $selected{'DPD_ACTION'}{'clear'}>clear</option>
3194 <option value='hold' $selected{'DPD_ACTION'}{'hold'}>hold</option>
3195 <option value='restart' $selected{'DPD_ACTION'}{'restart'}>restart</option>
3196 </select>
3197 </td>
3198 </tr>
3199 <tr>
e3edceeb 3200 <td width="15%">$Lang::tr{'dpd timeout'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
cbb3a8f9
MT
3201 <td>
3202 <input type='text' name='DPD_TIMEOUT' size='5' value='$cgiparams{'DPD_TIMEOUT'}' />
3203 </td>
3204 </tr>
3205 <tr>
e3edceeb 3206 <td width="15%">$Lang::tr{'dpd delay'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
cbb3a8f9
MT
3207 <td>
3208 <input type='text' name='DPD_DELAY' size='5' value='$cgiparams{'DPD_DELAY'}' />
3209 </td>
3210 </tr>
624615ee 3211 </table>
cbb3a8f9 3212
624615ee 3213 <hr>
63e3da59 3214
624615ee 3215 <table width="100%">
63e3da59 3216 <tr>
cbb3a8f9 3217 <td>
63e3da59
MT
3218 <label>
3219 <input type='checkbox' name='ONLY_PROPOSED' $checked{'ONLY_PROPOSED'} />
cbb88df1 3220 IKE+ESP: $Lang::tr{'use only proposed settings'}
63e3da59
MT
3221 </label>
3222 </td>
dcb406cc
MT
3223 <td>
3224 <label>$Lang::tr{'vpn start action'}</label>
3225 <select name="START_ACTION">
3226 <option value="route" $selected{'START_ACTION'}{'route'}>$Lang::tr{'vpn start action route'}</option>
3227 <option value="start" $selected{'START_ACTION'}{'start'}>$Lang::tr{'vpn start action start'}</option>
237f3ab7 3228 <option value="add" $selected{'START_ACTION'}{'add'} >$Lang::tr{'vpn start action add'}</option>
dcb406cc
MT
3229 </select>
3230 </td>
63e3da59
MT
3231 </tr>
3232 <tr>
af183eeb 3233 <td>
63e3da59
MT
3234 <label>
3235 <input type='checkbox' name='PFS' $checked{'PFS'} />
3236 $Lang::tr{'pfs yes no'}
3237 </label>
3238 </td>
af183eeb
MT
3239 <td>
3240 <label>$Lang::tr{'vpn inactivity timeout'}</label>
3241 <select name="INACTIVITY_TIMEOUT">
3242EOF
3243 foreach my $t (sort { $a <=> $b } keys %INACTIVITY_TIMEOUTS) {
3244 print "<option value=\"$t\" $selected{'INACTIVITY_TIMEOUT'}{$t}>$INACTIVITY_TIMEOUTS{$t}</option>\n";
3245 }
3246
3247 print <<EOF;
3248
3249 </select>
3250 </td>
63e3da59
MT
3251 </tr>
3252 <tr>
dcb406cc 3253 <td colspan="2">
63e3da59
MT
3254 <label>
3255 <input type='checkbox' name='COMPRESSION' $checked{'COMPRESSION'} />
3256 $Lang::tr{'vpn payload compression'}
3257 </label>
3258 </td>
ed84e8b8 3259 </tr>
f6529a04 3260 <tr>
dcb406cc 3261 <td colspan="2">
f6529a04
MT
3262 <label>
3263 <input type='checkbox' name='FORCE_MOBIKE' $checked{'FORCE_MOBIKE'} />
3264 $Lang::tr{'vpn force mobike'}
3265 </label>
3266 </td>
3267 </tr>
63e3da59 3268 <tr>
dcb406cc
MT
3269 <td align='left'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'required field'}</td>
3270 <td align='right'>
63e3da59
MT
3271 <input type='submit' name='ACTION' value='$Lang::tr{'save'}' />
3272 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' />
3273 </td>
3274 </tr>
624615ee 3275 </table></form>
63e3da59
MT
3276EOF
3277
624615ee
LS
3278 &Header::closebox();
3279 &Header::closebigbox();
3280 &Header::closepage();
3281 exit(0);
ac1cfefa 3282
624615ee 3283 ADVANCED_END:
ac1cfefa
MT
3284}
3285
3286###
3287### Default status page
3288###
624615ee
LS
3289 %cgiparams = ();
3290 %cahash = ();
3291 %confighash = ();
3292 &General::readhash("${General::swroot}/vpn/settings", \%cgiparams);
3293 &General::readhasharray("${General::swroot}/vpn/caconfig", \%cahash);
3294 &General::readhasharray("${General::swroot}/vpn/config", \%confighash);
3295 $cgiparams{'CA_NAME'} = '';
3296
a81cbf61 3297 my @status = &General::system_output("/usr/local/bin/ipsecctrl", "I");
624615ee 3298
624615ee
LS
3299 $checked{'ENABLED'} = $cgiparams{'ENABLED'} eq 'on' ? "checked='checked'" : '';
3300
3301 &Header::showhttpheaders();
3302 &Header::openpage($Lang::tr{'ipsec'}, 1, '');
3303 &Header::openbigbox('100%', 'left', '', $errormessage);
3304
3305 if ($errormessage) {
3306 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
3307 print "<class name='base'>$errormessage\n";
3308 print "&nbsp;</class>\n";
3309 &Header::closebox();
3310 }
ac1cfefa 3311
4d81e0f3
AM
3312 if ($warnmessage) {
3313 &Header::openbox('100%', 'left', $Lang::tr{'warning messages'});
3314 print "$warnmessage<br>";
3315 print "$Lang::tr{'fwdfw warn1'}<br>";
3316 &Header::closebox();
03b08c08 3317 print"<center><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'ok'}' style='width: 5em;'></form>";
4d81e0f3
AM
3318 &Header::closepage();
3319 exit 0;
3320 }
3321
624615ee
LS
3322 &Header::openbox('100%', 'left', $Lang::tr{'global settings'});
3323 print <<END
3324 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3325 <table width='100%'>
38f6bdb7
MT
3326 <tr>
3327 <td width='60%' class='base'>
3328 $Lang::tr{'enabled'}
3329 </td>
3330 <td width="40%">
3331 <input type='checkbox' name='ENABLED' $checked{'ENABLED'} />
3332 </td>
3333 </tr>
c7fe09c6
MT
3334 <tr>
3335 <td class='base' nowrap='nowrap' width="60%">$Lang::tr{'ipsec roadwarrior endpoint'}:</td>
3336 <td width="40%"><input type='text' name='RW_ENDPOINT' value='$cgiparams{'RW_ENDPOINT'}' /></td>
3337 </tr>
38f6bdb7
MT
3338 <tr>
3339 <td class='base' nowrap='nowrap' width="60%">$Lang::tr{'host to net vpn'}:</td>
3340 <td width="40%"><input type='text' name='RW_NET' value='$cgiparams{'RW_NET'}' /></td>
3341 </tr>
3342 <tr>
3343 <td width='100%' colspan="2" align='right' class='base'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
3344 </tr>
ac1cfefa
MT
3345</table>
3346END
624615ee
LS
3347;
3348 print "</form>";
3349 &Header::closebox();
3350
3351 &Header::openbox('100%', 'left', $Lang::tr{'connection status and controlc'});
3352 print <<END
3353 <table width='100%' cellspacing='1' cellpadding='0' class='tbl'>
3354 <tr>
e9850821
AM
3355 <th width='10%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></th>
3356 <th width='22%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></th>
3357 <th width='23%' class='boldbase' align='center'><b>$Lang::tr{'common name'}</b></th>
3358 <th width='30%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></th>
3359 <th width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></th>
26a0befd 3360 <th class='boldbase' align='center' colspan='7'><b>$Lang::tr{'action'}</b></th>
624615ee 3361 </tr>
ac1cfefa 3362END
624615ee
LS
3363;
3364 my $id = 0;
3365 my $gif;
3366 foreach my $key (sort { ncmp ($confighash{$a}[1],$confighash{$b}[1]) } keys %confighash) {
ac1cfefa
MT
3367 if ($confighash{$key}[0] eq 'on') { $gif = 'on.gif'; } else { $gif = 'off.gif'; }
3368
3369 if ($id % 2) {
e9850821
AM
3370 print "<tr>";
3371 $col="bgcolor='$color{'color20'}'";
ac1cfefa 3372 } else {
e9850821
AM
3373 print "<tr>";
3374 $col="bgcolor='$color{'color22'}'";
ac1cfefa 3375 }
e9850821
AM
3376 print "<td align='center' nowrap='nowrap' $col>$confighash{$key}[1]</td>";
3377 print "<td align='center' nowrap='nowrap' $col>" . $Lang::tr{"$confighash{$key}[3]"} . " (" . $Lang::tr{"$confighash{$key}[4]"} . ") $confighash{$key}[29]</td>";
ed84e8b8 3378 if ($confighash{$key}[2] eq '%auth-dn') {
624615ee 3379 print "<td align='left' nowrap='nowrap' $col>$confighash{$key}[9]</td>";
ed84e8b8 3380 } elsif ($confighash{$key}[4] eq 'cert') {
624615ee 3381 print "<td align='left' nowrap='nowrap' $col>$confighash{$key}[2]</td>";
ac1cfefa 3382 } else {
624615ee 3383 print "<td align='left' $col>&nbsp;</td>";
ac1cfefa 3384 }
e9850821 3385 print "<td align='center' $col>$confighash{$key}[25]</td>";
0afd8493 3386 my $col1="bgcolor='${Header::colourred}'";
0afd8493 3387 my $active = "<b><font color='#FFFFFF'>$Lang::tr{'capsclosed'}</font></b>";
aec1925b
MT
3388 if ($confighash{$key}[33] eq "add") {
3389 $col1="bgcolor='${Header::colourorange}'";
3390 $active = "<b><font color='#FFFFFF'>$Lang::tr{'vpn wait'}</font></b>";
3391 }
5fd30232 3392 foreach my $line (@status) {
624615ee
LS
3393 if (($line =~ /\"$confighash{$key}[1]\".*IPsec SA established/) ||
3394 ($line =~ /$confighash{$key}[1]\{.*INSTALLED/)) {
3395 $col1="bgcolor='${Header::colourgreen}'";
3396 $active = "<b><font color='#FFFFFF'>$Lang::tr{'capsopen'}</font></b>";
1f3f2d67 3397 last;
1fab4edf
MT
3398 } elsif ($line =~ /$confighash{$key}[1]\[.*CONNECTING/) {
3399 $col1="bgcolor='${Header::colourorange}'";
3400 $active = "<b><font color='#FFFFFF'>$Lang::tr{'vpn connecting'}</font></b>";
8057ab15
MT
3401 } elsif ($line =~ /$confighash{$key}[1]\{.*ROUTED/) {
3402 $col1="bgcolor='${Header::colourorange}'";
3403 $active = "<b><font color='#FFFFFF'>$Lang::tr{'vpn on-demand'}</font></b>";
624615ee
LS
3404 }
3405 }
3406 # move to blue if really down
0afd8493
AM
3407 if ($confighash{$key}[0] eq 'off' && $col1 =~ /${Header::colourred}/ ) {
3408 $col1="bgcolor='${Header::colourblue}'";
624615ee 3409 $active = "<b><font color='#FFFFFF'>$Lang::tr{'capsclosed'}</font></b>";
5fd30232 3410 }
ac1cfefa 3411 print <<END
0afd8493 3412 <td align='center' $col1>$active</td>
e9850821 3413 <td align='center' $col>
624615ee
LS
3414 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3415 <input type='image' name='$Lang::tr{'restart'}' src='/images/reload.gif' alt='$Lang::tr{'restart'}' title='$Lang::tr{'restart'}' />
3416 <input type='hidden' name='ACTION' value='$Lang::tr{'restart'}' />
3417 <input type='hidden' name='KEY' value='$key' />
3418 </form>
ed84e8b8 3419 </td>
ac1cfefa 3420END
624615ee 3421;
ed84e8b8 3422 if (($confighash{$key}[4] eq 'cert') && ($confighash{$key}[2] ne '%auth-dn')) {
624615ee
LS
3423 print <<END
3424 <td align='center' $col>
3425 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
ed84e8b8 3426 <input type='image' name='$Lang::tr{'show certificate'}' src='/images/info.gif' alt='$Lang::tr{'show certificate'}' title='$Lang::tr{'show certificate'}' />
ac1cfefa
MT
3427 <input type='hidden' name='ACTION' value='$Lang::tr{'show certificate'}' />
3428 <input type='hidden' name='KEY' value='$key' />
624615ee
LS
3429 </form>
3430 </td>
ac1cfefa 3431END
624615ee
LS
3432;
3433 } else {
3434 print "<td width='2%' $col>&nbsp;</td>";
ac1cfefa 3435 }
624615ee
LS
3436 if ($confighash{$key}[4] eq 'cert' && -f "${General::swroot}/certs/$confighash{$key}[1].p12") {
3437 print <<END
3438 <td align='center' $col>
3439 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
ed84e8b8 3440 <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
3441 <input type='hidden' name='ACTION' value='$Lang::tr{'download pkcs12 file'}' />
3442 <input type='hidden' name='KEY' value='$key' />
624615ee 3443 </form>
ed84e8b8 3444 </td>
ac1cfefa 3445END
624615ee
LS
3446;
3447 } elsif (($confighash{$key}[4] eq 'cert') && ($confighash{$key}[2] ne '%auth-dn')) {
3448 print <<END
3449 <td align='center' $col>
3450 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
ed84e8b8 3451 <input type='image' name='$Lang::tr{'download certificate'}' src='/images/floppy.gif' alt='$Lang::tr{'download certificate'}' title='$Lang::tr{'download certificate'}' />
ac1cfefa
MT
3452 <input type='hidden' name='ACTION' value='$Lang::tr{'download certificate'}' />
3453 <input type='hidden' name='KEY' value='$key' />
624615ee 3454 </form>
ed84e8b8 3455 </td>
ac1cfefa 3456END
624615ee
LS
3457;
3458 } else {
3459 print "<td width='2%' $col>&nbsp;</td>";
ac1cfefa 3460 }
26a0befd
MT
3461
3462 # Apple Profile
3463 if ($confighash{$key}[3] eq 'host') {
3464 print <<END;
3465 <td align='center' $col>
3466 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3467 <input type='image' name='$Lang::tr{'download apple profile'}' src='/images/apple.png' alt='$Lang::tr{'download apple profile'}' title='$Lang::tr{'download apple profile'}' />
3468 <input type='hidden' name='ACTION' value='$Lang::tr{'download apple profile'}' />
3469 <input type='hidden' name='KEY' value='$key' />
3470 </form>
3471 </td>
3472END
3473 } else {
3474 print "<td width='2%' $col>&nbsp;</td>";
3475 }
3476
ac1cfefa 3477 print <<END
e9850821 3478 <td align='center' $col>
624615ee
LS
3479 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3480 <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' />
3481 <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
3482 <input type='hidden' name='KEY' value='$key' />
3483 </form>
ed84e8b8 3484 </td>
ac1cfefa 3485
e9850821 3486 <td align='center' $col>
624615ee
LS
3487 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3488 <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
3489 <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
3490 <input type='hidden' name='KEY' value='$key' />
3491 </form>
ed84e8b8 3492 </td>
e9850821 3493 <td align='center' $col>
624615ee
LS
3494 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3495 <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
3496 <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
3497 <input type='hidden' name='KEY' value='$key' />
3498 </form>
ed84e8b8 3499 </td>
ac1cfefa
MT
3500 </tr>
3501END
624615ee 3502;
ac1cfefa 3503 $id++;
624615ee
LS
3504 }
3505 print "</table>";
3506
3507 # If the config file contains entries, print Key to action icons
3508 if ( $id ) {
3509 print <<END
3510 <table>
3511 <tr>
3512 <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
3513 <td>&nbsp; <img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
3514 <td class='base'>$Lang::tr{'click to disable'}</td>
3515 <td>&nbsp; &nbsp; <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
3516 <td class='base'>$Lang::tr{'show certificate'}</td>
3517 <td>&nbsp; &nbsp; <img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
3518 <td class='base'>$Lang::tr{'edit'}</td>
3519 <td>&nbsp; &nbsp; <img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
3520 <td class='base'>$Lang::tr{'remove'}</td>
3521 </tr>
3522 <tr>
3523 <td>&nbsp; </td>
3524 <td>&nbsp; <img src='/images/off.gif' alt='?OFF' /></td>
3525 <td class='base'>$Lang::tr{'click to enable'}</td>
3526 <td>&nbsp; &nbsp; <img src='/images/floppy.gif' alt='?FLOPPY' /></td>
3527 <td class='base'>$Lang::tr{'download certificate'}</td>
3528 <td>&nbsp; &nbsp; <img src='/images/reload.gif' alt='?RELOAD'/></td>
3529 <td class='base'>$Lang::tr{'restart'}</td>
3530 </tr>
3531 </table>
ac1cfefa 3532END
624615ee
LS
3533;
3534 }
ac1cfefa 3535
624615ee
LS
3536 print <<END
3537 <table width='100%'>
3538 <tr><td align='right' colspan='9'>
ed84e8b8
MT
3539 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3540 <input type='submit' name='ACTION' value='$Lang::tr{'add'}' />
3541 </form>
624615ee
LS
3542 </td></tr>
3543 </table>
ac1cfefa 3544END
624615ee
LS
3545;
3546 &Header::closebox();
ac1cfefa 3547
624615ee
LS
3548 &Header::openbox('100%', 'left', "$Lang::tr{'certificate authorities'}");
3549 print <<EOF
3550 <table width='100%' cellspacing='1' cellpadding='0' class='tbl'>
3551 <tr>
e9850821
AM
3552 <th width='25%' class='boldbase' align='center'><b>$Lang::tr{'name'}</b></th>
3553 <th width='65%' class='boldbase' align='center'><b>$Lang::tr{'subject'}</b></th>
3554 <th width='10%' class='boldbase' colspan='3' align='center'><b>$Lang::tr{'action'}</b></th>
624615ee 3555 </tr>
ac1cfefa 3556EOF
624615ee
LS
3557;
3558 my $col1="bgcolor='$color{'color22'}'";
e9850821 3559 my $col2="bgcolor='$color{'color20'}'";
624615ee
LS
3560 if (-f "${General::swroot}/ca/cacert.pem") {
3561 my $casubject = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/ca/cacert.pem"));
3562 print <<END
3563 <tr>
3564 <td class='base' $col1>$Lang::tr{'root certificate'}</td>
3565 <td class='base' $col1>$casubject</td>
3566 <td width='3%' align='center' $col1>
3567 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3568 <input type='hidden' name='ACTION' value='$Lang::tr{'show root certificate'}' />
3569 <input type='image' name='$Lang::tr{'edit'}' src='/images/info.gif' alt='$Lang::tr{'show root certificate'}' title='$Lang::tr{'show root certificate'}' />
3570 </form>
3571 </td>
3572 <td width='3%' align='center' $col1>
3573 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3574 <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'}' />
3575 <input type='hidden' name='ACTION' value='$Lang::tr{'download root certificate'}' />
3576 </form>
3577 </td>
3578 <td width='4%' $col1>&nbsp;</td></tr>
ac1cfefa 3579END
624615ee
LS
3580;
3581 } else {
3582 # display rootcert generation buttons
3583 print <<END
3584 <tr>
3585 <td class='base' $col1>$Lang::tr{'root certificate'}:</td>
3586 <td class='base' $col1>$Lang::tr{'not present'}</td>
3587 <td colspan='3' $col1>&nbsp;</td></tr>
ac1cfefa 3588END
624615ee
LS
3589;
3590 }
ac1cfefa 3591
624615ee
LS
3592 if (-f "${General::swroot}/certs/hostcert.pem") {
3593 my $hostsubject = &Header::cleanhtml(getsubjectfromcert ("${General::swroot}/certs/hostcert.pem"));
ac1cfefa 3594
624615ee
LS
3595 print <<END
3596 <tr>
3597 <td class='base' $col2>$Lang::tr{'host certificate'}</td>
3598 <td class='base' $col2>$hostsubject</td>
3599 <td width='3%' align='center' $col2>
3600 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3601 <input type='hidden' name='ACTION' value='$Lang::tr{'show host certificate'}' />
3602 <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'}' />
3603 </form>
3604 </td>
3605 <td width='3%' align='center' $col2>
3606 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
3607 <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'}" />
3608 <input type='hidden' name='ACTION' value="$Lang::tr{'download host certificate'}" />
3609 </form>
3610 </td>
3611 <td width='4%' $col2>&nbsp;</td></tr>
ac1cfefa 3612END
624615ee
LS
3613;
3614 } else {
3615 # Nothing
3616 print <<END
3617 <tr>
3618 <td width='25%' class='base' $col2>$Lang::tr{'host certificate'}:</td>
3619 <td class='base' $col2>$Lang::tr{'not present'}</td>
3620 <td colspan='3' $col2>&nbsp;</td></tr>
ac1cfefa 3621END
624615ee
LS
3622;
3623 }
3624
e9850821
AM
3625 my $rowcolor = 0;
3626 if (keys %cahash > 0) {
3627 foreach my $key (keys %cahash) {
624615ee
LS
3628 if ($rowcolor++ % 2) {
3629 print "<tr>";
3630 $col="bgcolor='$color{'color20'}'";
3631 } else {
3632 print "<tr>";
3633 $col="bgcolor='$color{'color22'}'";
3634 }
3635 print "<td class='base' $col>$cahash{$key}[0]</td>\n";
3636 print "<td class='base' $col>$cahash{$key}[1]</td>\n";
3637 print <<END
3638 <td align='center' $col>
3639 <form method='post' name='cafrm${key}a' action='$ENV{'SCRIPT_NAME'}'>
3640 <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'}' />
3641 <input type='hidden' name='ACTION' value='$Lang::tr{'show ca certificate'}' />
3642 <input type='hidden' name='KEY' value='$key' />
3643 </form>
3644 </td>
3645 <td align='center' $col>
3646 <form method='post' name='cafrm${key}b' action='$ENV{'SCRIPT_NAME'}'>
3647 <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'}' />
3648 <input type='hidden' name='ACTION' value='$Lang::tr{'download ca certificate'}' />
3649 <input type='hidden' name='KEY' value='$key' />
3650 </form>
3651 </td>
3652 <td align='center' $col>
3653 <form method='post' name='cafrm${key}c' action='$ENV{'SCRIPT_NAME'}'>
3654 <input type='hidden' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
3655 <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'}' />
3656 <input type='hidden' name='KEY' value='$key' />
3657 </form>
3658 </td>
3659 </tr>
3660END
3661;
3662 }
3663 }
3664 print "</table>";
3665
3666 # If the file contains entries, print Key to action icons
3667 if ( -f "${General::swroot}/ca/cacert.pem") {
3668 print <<END
3669 <table><tr>
3670 <td class='boldbase'>&nbsp; <b>$Lang::tr{'legend'}:</b></td>
3671 <td>&nbsp; &nbsp; <img src='/images/info.gif' alt='$Lang::tr{'show certificate'}' /></td>
3672 <td class='base'>$Lang::tr{'show certificate'}</td>
3673 <td>&nbsp; &nbsp; <img src='/images/floppy.gif' alt='$Lang::tr{'download certificate'}' /></td>
3674 <td class='base'>$Lang::tr{'download certificate'}</td>
3675 </tr></table>
ac1cfefa 3676END
624615ee 3677;
ac1cfefa 3678 }
624615ee 3679 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>";
ed84e8b8 3680 print <<END
624615ee
LS
3681 <br>
3682 <hr />
3683 <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
3684 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
3685 $createCA
3686 <tr>
e3edceeb 3687 <td class='base' nowrap='nowrap'>$Lang::tr{'ca name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
ed84e8b8
MT
3688 <td nowrap='nowrap'><input type='text' name='CA_NAME' value='$cgiparams{'CA_NAME'}' size='15' /> </td>
3689 <td nowrap='nowrap'><input type='file' name='FH' size='30' /></td>
3690 <td nowrap='nowrap'><input type='submit' name='ACTION' value='$Lang::tr{'upload ca certificate'}' /></td>
624615ee
LS
3691 </tr>
3692 <tr>
ed84e8b8 3693 <td colspan='3'>$Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}:</td>
0afd8493 3694 <td align='right'><input type='submit' name='ACTION' value='$Lang::tr{'remove x509'}' /></td>
624615ee
LS
3695 </tr>
3696 </table>
3697 </form>
ac1cfefa 3698END
624615ee
LS
3699;
3700 &Header::closebox();
3701 &Header::closebigbox();
3702 &Header::closepage();
e8b3bb0e
MT
3703
3704sub array_unique($) {
3705 my $array = shift;
3706 my @unique = ();
3707
3708 my %seen = ();
3709 foreach my $e (@$array) {
3710 next if $seen{$e}++;
3711 push(@unique, $e);
3712 }
3713
3714 return @unique;
3715}
3716
3717sub make_algos($$$$$) {
3718 my ($mode, $encs, $ints, $grps, $pfs) = @_;
3719 my @algos = ();
3720
3721 foreach my $enc (@$encs) {
3722 foreach my $int (@$ints) {
3723 foreach my $grp (@$grps) {
3724 my @algo = ($enc);
3725
78039c15 3726 if ($mode eq "ike") {
e8b3bb0e 3727 push(@algo, $int);
e8b3bb0e 3728
2c531c21 3729 if ($grp =~ m/^e(.*)$/) {
e8b3bb0e 3730 push(@algo, "ecp$1");
7f662098 3731 } elsif ($grp =~ m/curve(448|25519)/) {
e34e72b6 3732 push(@algo, "$grp");
e8b3bb0e
MT
3733 } else {
3734 push(@algo, "modp$grp");
3735 }
e8b3bb0e 3736
745915d8 3737 } elsif ($mode eq "esp") {
78039c15
MT
3738 my $is_aead = ($enc =~ m/[cg]cm/);
3739
3740 if (!$is_aead) {
3741 push(@algo, $int);
3742 }
4b02b404 3743
0dd16f40 3744 if (!$pfs || $grp eq "none") {
4b02b404
MT
3745 # noop
3746 } elsif ($grp =~ m/^e(.*)$/) {
3747 push(@algo, "ecp$1");
7f662098 3748 } elsif ($grp =~ m/curve(448|25519)/) {
e34e72b6 3749 push(@algo, "$grp");
4b02b404
MT
3750 } else {
3751 push(@algo, "modp$grp");
3752 }
e8b3bb0e
MT
3753 }
3754
3755 push(@algos, join("-", @algo));
3756 }
3757 }
3758 }
3759
3760 return &array_unique(\@algos);
3761}
8792caad 3762
f2d45a45
MT
3763sub make_subnets($$) {
3764 my $direction = shift;
8792caad
MT
3765 my $subnets = shift;
3766
3767 my @nets = split(/\|/, $subnets);
3768 my @cidr_nets = ();
3769 foreach my $net (@nets) {
3770 my $cidr_net = &General::ipcidr($net);
f2d45a45
MT
3771
3772 # Skip 0.0.0.0/0 for remote because this renders the
3773 # while system inaccessible
3774 next if (($direction eq "right") && ($cidr_net eq "0.0.0.0/0"));
3775
8792caad
MT
3776 push(@cidr_nets, $cidr_net);
3777 }
3778
3779 return join(",", @cidr_nets);
3780}