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