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