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