]> git.ipfire.org Git - ipfire-2.x.git/blob - html/cgi-bin/ovpnmain.cgi
core180: Ship suricata
[ipfire-2.x.git] / html / cgi-bin / ovpnmain.cgi
1 #!/usr/bin/perl
2 ###############################################################################
3 # #
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
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 ###############################################################################
21
22 use CGI;
23 use CGI qw/:standard/;
24 use Imager::QRCode;
25 use MIME::Base32;
26 use MIME::Base64;
27 use URI::Encode qw(uri_encode uri_decode);;
28 use Net::DNS;
29 use Net::Ping;
30 use Net::Telnet;
31 use File::Copy;
32 use File::Temp qw/ tempfile tempdir /;
33 use strict;
34 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
35 use Sort::Naturally;
36 use Date::Parse;
37 require '/var/ipfire/general-functions.pl';
38 require "${General::swroot}/lang.pl";
39 require "${General::swroot}/header.pl";
40 require "${General::swroot}/countries.pl";
41 require "${General::swroot}/location-functions.pl";
42
43 # enable only the following on debugging purpose
44 #use warnings;
45 #use CGI::Carp 'fatalsToBrowser';
46
47 #workaround to suppress a warning when a variable is used only once
48 my @dummy = ( ${Header::colourgreen}, ${Header::colourblue} );
49 undef (@dummy);
50
51 my %color = ();
52 my %mainsettings = ();
53 &General::readhash("${General::swroot}/main/settings", \%mainsettings);
54 &General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
55
56 ###
57 ### Initialize variables
58 ###
59 my %ccdconfhash=();
60 my %ccdroutehash=();
61 my %ccdroute2hash=();
62 my %netsettings=();
63 my %cgiparams=();
64 my %vpnsettings=();
65 my %checked=();
66 my %confighash=();
67 my %cahash=();
68 my %selected=();
69 my $warnmessage = '';
70 my $errormessage = '';
71 my $cryptoerror = '';
72 my $cryptowarning = '';
73 my %settings=();
74 my $routes_push_file = '';
75 my $confighost="${General::swroot}/fwhosts/customhosts";
76 my $configgrp="${General::swroot}/fwhosts/customgroups";
77 my $customnet="${General::swroot}/fwhosts/customnetworks";
78 my $name;
79 my $col="";
80 my $local_serverconf = "${General::swroot}/ovpn/scripts/server.conf.local";
81 my $local_clientconf = "${General::swroot}/ovpn/scripts/client.conf.local";
82 my $dhparameter = "/etc/ssl/ffdhe4096.pem";
83
84 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
85 $cgiparams{'ENABLED'} = 'off';
86 $cgiparams{'ENABLED_BLUE'} = 'off';
87 $cgiparams{'ENABLED_ORANGE'} = 'off';
88 $cgiparams{'EDIT_ADVANCED'} = 'off';
89 $cgiparams{'NAT'} = 'off';
90 $cgiparams{'COMPRESSION'} = 'off';
91 $cgiparams{'ONLY_PROPOSED'} = 'off';
92 $cgiparams{'ACTION'} = '';
93 $cgiparams{'CA_NAME'} = '';
94 $cgiparams{'DHCP_DOMAIN'} = '';
95 $cgiparams{'DHCP_DNS'} = '';
96 $cgiparams{'DHCP_WINS'} = '';
97 $cgiparams{'ROUTES_PUSH'} = '';
98 $cgiparams{'DCOMPLZO'} = 'off';
99 $cgiparams{'MSSFIX'} = '';
100 $cgiparams{'number'} = '';
101 $cgiparams{'DCIPHER'} = '';
102 $cgiparams{'DAUTH'} = '';
103 $cgiparams{'TLSAUTH'} = '';
104 $routes_push_file = "${General::swroot}/ovpn/routes_push";
105 # Perform crypto and configration test
106 &pkiconfigcheck;
107
108 # Add CCD files if not already presant
109 unless (-e $routes_push_file) {
110 open(RPF, ">$routes_push_file");
111 close(RPF);
112 }
113 unless (-e "${General::swroot}/ovpn/ccd.conf") {
114 open(CCDC, ">${General::swroot}/ovpn/ccd.conf");
115 close (CCDC);
116 }
117 unless (-e "${General::swroot}/ovpn/ccdroute") {
118 open(CCDR, ">${General::swroot}/ovpn/ccdroute");
119 close (CCDR);
120 }
121 unless (-e "${General::swroot}/ovpn/ccdroute2") {
122 open(CCDRT, ">${General::swroot}/ovpn/ccdroute2");
123 close (CCDRT);
124 }
125 # Add additional configs if not already presant
126 unless (-e "$local_serverconf") {
127 open(LSC, ">$local_serverconf");
128 close (LSC);
129 }
130 unless (-e "$local_clientconf") {
131 open(LCC, ">$local_clientconf");
132 close (LCC);
133 }
134
135 &Header::getcgihash(\%cgiparams, {'wantfile' => 1, 'filevar' => 'FH'});
136
137 # prepare openvpn config file
138 ###
139 ### Useful functions
140 ###
141 sub haveOrangeNet
142 {
143 if ($netsettings{'CONFIG_TYPE'} == 2) {return 1;}
144 if ($netsettings{'CONFIG_TYPE'} == 4) {return 1;}
145 return 0;
146 }
147
148 sub haveBlueNet
149 {
150 if ($netsettings{'CONFIG_TYPE'} == 3) {return 1;}
151 if ($netsettings{'CONFIG_TYPE'} == 4) {return 1;}
152 return 0;
153 }
154
155 sub sizeformat{
156 my $bytesize = shift;
157 my $i = 0;
158
159 while(abs($bytesize) >= 1024){
160 $bytesize=$bytesize/1024;
161 $i++;
162 last if($i==6);
163 }
164
165 my @units = ("Bytes","KB","MB","GB","TB","PB","EB");
166 my $newsize=(int($bytesize*100 +0.5))/100;
167 return("$newsize $units[$i]");
168 }
169
170 sub cleanssldatabase
171 {
172 if (open(FILE, ">${General::swroot}/ovpn/certs/serial")) {
173 print FILE "01";
174 close FILE;
175 }
176 if (open(FILE, ">${General::swroot}/ovpn/certs/index.txt")) {
177 print FILE "";
178 close FILE;
179 }
180 if (open(FILE, ">${General::swroot}/ovpn/certs/index.txt.attr")) {
181 print FILE "";
182 close FILE;
183 }
184 unlink ("${General::swroot}/ovpn/certs/index.txt.old");
185 unlink ("${General::swroot}/ovpn/certs/index.txt.attr.old");
186 unlink ("${General::swroot}/ovpn/certs/serial.old");
187 unlink ("${General::swroot}/ovpn/certs/01.pem");
188 }
189
190 sub newcleanssldatabase
191 {
192 if (! -s "${General::swroot}/ovpn/certs/serial" ) {
193 open(FILE, ">${General::swroot}(ovpn/certs/serial");
194 print FILE "01";
195 close FILE;
196 }
197 if (! -s ">${General::swroot}/ovpn/certs/index.txt") {
198 &General::system("touch", "${General::swroot}/ovpn/certs/index.txt");
199 }
200 if (! -s ">${General::swroot}/ovpn/certs/index.txt.attr") {
201 &General::system("touch", "${General::swroot}/ovpn/certs/index.txt.attr");
202 }
203 unlink ("${General::swroot}/ovpn/certs/index.txt.old");
204 unlink ("${General::swroot}/ovpn/certs/index.txt.attr.old");
205 unlink ("${General::swroot}/ovpn/certs/serial.old");
206 }
207
208 sub deletebackupcert
209 {
210 if (open(FILE, "${General::swroot}/ovpn/certs/serial.old")) {
211 my $hexvalue = <FILE>;
212 chomp $hexvalue;
213 close FILE;
214 unlink ("${General::swroot}/ovpn/certs/$hexvalue.pem");
215 }
216 }
217
218 ###
219 ### Check for PKI and configure problems
220 ###
221
222 sub pkiconfigcheck
223 {
224 # Warning if md5 is in usage
225 if (-f "${General::swroot}/ovpn/certs/servercert.pem") {
226 my @signature = &General::system_output("/usr/bin/openssl", "x509", "-noout", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
227 if (grep(/md5WithRSAEncryption/, @signature) ) {
228 $cryptoerror = "$Lang::tr{'ovpn error md5'}";
229 goto CRYPTO_ERROR;
230 }
231 }
232
233 CRYPTO_ERROR:
234
235 # Warning if certificate is not compliant to RFC3280 TLS rules
236 if (-f "${General::swroot}/ovpn/certs/servercert.pem") {
237 my @extendkeyusage = &General::system_output("/usr/bin/openssl", "x509", "-noout", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
238 if ( ! grep(/TLS Web Server Authentication/, @extendkeyusage)) {
239 $cryptowarning = "$Lang::tr{'ovpn warning rfc3280'}";
240 goto CRYPTO_WARNING;
241 }
242 }
243
244 CRYPTO_WARNING:
245 }
246
247 sub writeserverconf {
248 my %sovpnsettings = ();
249 my @temp = ();
250 &General::readhash("${General::swroot}/ovpn/settings", \%sovpnsettings);
251 &read_routepushfile;
252
253 open(CONF, ">${General::swroot}/ovpn/server.conf") or die "Unable to open ${General::swroot}/ovpn/server.conf: $!";
254 flock CONF, 2;
255 print CONF "#OpenVPN Server conf\n";
256 print CONF "\n";
257 print CONF "daemon openvpnserver\n";
258 print CONF "writepid /var/run/openvpn.pid\n";
259 print CONF "#DAN prepare OpenVPN for listening on blue and orange\n";
260 print CONF ";local $sovpnsettings{'VPN_IP'}\n";
261 print CONF "dev tun\n";
262 print CONF "proto $sovpnsettings{'DPROTOCOL'}\n";
263 print CONF "port $sovpnsettings{'DDEST_PORT'}\n";
264 print CONF "script-security 3\n";
265 print CONF "ifconfig-pool-persist /var/ipfire/ovpn/ovpn-leases.db 3600\n";
266 print CONF "client-config-dir /var/ipfire/ovpn/ccd\n";
267 print CONF "tls-server\n";
268 print CONF "ca ${General::swroot}/ovpn/ca/cacert.pem\n";
269 print CONF "cert ${General::swroot}/ovpn/certs/servercert.pem\n";
270 print CONF "key ${General::swroot}/ovpn/certs/serverkey.pem\n";
271 print CONF "dh $dhparameter\n";
272 my @tempovpnsubnet = split("\/",$sovpnsettings{'DOVPN_SUBNET'});
273 print CONF "server $tempovpnsubnet[0] $tempovpnsubnet[1]\n";
274 #print CONF "push \"route $netsettings{'GREEN_NETADDRESS'} $netsettings{'GREEN_NETMASK'}\"\n";
275
276 print CONF "tun-mtu $sovpnsettings{'DMTU'}\n";
277
278 if ($vpnsettings{'ROUTES_PUSH'} ne '') {
279 @temp = split(/\n/,$vpnsettings{'ROUTES_PUSH'});
280 foreach (@temp)
281 {
282 @tempovpnsubnet = split("\/",&General::ipcidr2msk($_));
283 print CONF "push \"route " . $tempovpnsubnet[0]. " " . $tempovpnsubnet[1] . "\"\n";
284 }
285 }
286 # a.marx ccd
287 my %ccdconfhash=();
288 &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
289 foreach my $key (keys %ccdconfhash) {
290 my $a=$ccdconfhash{$key}[1];
291 my ($b,$c) = split (/\//, $a);
292 print CONF "route $b ".&General::cidrtosub($c)."\n";
293 }
294 my %ccdroutehash=();
295 &General::readhasharray("${General::swroot}/ovpn/ccdroute", \%ccdroutehash);
296 foreach my $key (keys %ccdroutehash) {
297 foreach my $i ( 1 .. $#{$ccdroutehash{$key}}){
298 my ($a,$b)=split (/\//,$ccdroutehash{$key}[$i]);
299 print CONF "route $a $b\n";
300 }
301 }
302 # ccd end
303
304 if ($sovpnsettings{CLIENT2CLIENT} eq 'on') {
305 print CONF "client-to-client\n";
306 }
307 if ($sovpnsettings{MSSFIX} eq 'on') {
308 print CONF "mssfix\n";
309 } else {
310 print CONF "mssfix 0\n";
311 }
312 if ($sovpnsettings{FRAGMENT} ne '' && $sovpnsettings{'DPROTOCOL'} ne 'tcp') {
313 print CONF "fragment $sovpnsettings{'FRAGMENT'}\n";
314 }
315
316 if ($sovpnsettings{KEEPALIVE_1} > 0 && $sovpnsettings{KEEPALIVE_2} > 0) {
317 print CONF "keepalive $sovpnsettings{'KEEPALIVE_1'} $sovpnsettings{'KEEPALIVE_2'}\n";
318 }
319 print CONF "status-version 1\n";
320 print CONF "status /var/run/ovpnserver.log 30\n";
321 print CONF "ncp-disable\n";
322 print CONF "cipher $sovpnsettings{DCIPHER}\n";
323 print CONF "auth $sovpnsettings{'DAUTH'}\n";
324 # Set TLSv2 as minimum
325 print CONF "tls-version-min 1.2\n";
326
327 if ($sovpnsettings{'TLSAUTH'} eq 'on') {
328 print CONF "tls-auth ${General::swroot}/ovpn/certs/ta.key\n";
329 }
330 if ($sovpnsettings{DCOMPLZO} eq 'on') {
331 print CONF "comp-lzo\n";
332 }
333 if ($sovpnsettings{REDIRECT_GW_DEF1} eq 'on') {
334 print CONF "push \"redirect-gateway def1\"\n";
335 }
336 if ($sovpnsettings{DHCP_DOMAIN} ne '') {
337 print CONF "push \"dhcp-option DOMAIN $sovpnsettings{DHCP_DOMAIN}\"\n";
338 }
339
340 if ($sovpnsettings{DHCP_DNS} ne '') {
341 print CONF "push \"dhcp-option DNS $sovpnsettings{DHCP_DNS}\"\n";
342 }
343
344 if ($sovpnsettings{DHCP_WINS} ne '') {
345 print CONF "push \"dhcp-option WINS $sovpnsettings{DHCP_WINS}\"\n";
346 }
347
348 if ($sovpnsettings{MAX_CLIENTS} eq '') {
349 print CONF "max-clients 100\n";
350 }
351 if ($sovpnsettings{MAX_CLIENTS} ne '') {
352 print CONF "max-clients $sovpnsettings{MAX_CLIENTS}\n";
353 }
354 print CONF "tls-verify /usr/lib/openvpn/verify\n";
355 print CONF "crl-verify /var/ipfire/ovpn/crls/cacrl.pem\n";
356 print CONF "auth-user-pass-optional\n";
357 print CONF "reneg-sec 86400\n";
358 print CONF "user nobody\n";
359 print CONF "group nobody\n";
360 print CONF "persist-key\n";
361 print CONF "persist-tun\n";
362 if ($sovpnsettings{LOG_VERB} ne '') {
363 print CONF "verb $sovpnsettings{LOG_VERB}\n";
364 } else {
365 print CONF "verb 3\n";
366 }
367
368 print CONF "# Log clients connecting/disconnecting\n";
369 print CONF "client-connect \"/usr/sbin/openvpn-metrics client-connect\"\n";
370 print CONF "client-disconnect \"/usr/sbin/openvpn-metrics client-disconnect\"\n";
371 print CONF "\n";
372
373 print CONF "# Enable Management Socket\n";
374 print CONF "management /var/run/openvpn.sock unix\n";
375 print CONF "management-client-auth\n";
376
377 # Print server.conf.local if entries exist to server.conf
378 if ( !-z $local_serverconf && $sovpnsettings{'ADDITIONAL_CONFIGS'} eq 'on') {
379 open (LSC, "$local_serverconf");
380 print CONF "\n#---------------------------\n";
381 print CONF "# Start of custom directives\n";
382 print CONF "# from server.conf.local\n";
383 print CONF "#---------------------------\n\n";
384 while (<LSC>) {
385 print CONF $_;
386 }
387 print CONF "\n#-----------------------------\n";
388 print CONF "# End of custom directives\n";
389 print CONF "#-----------------------------\n";
390 close (LSC);
391 }
392 print CONF "\n";
393
394 close(CONF);
395 }
396
397 sub emptyserverlog{
398 if (open(FILE, ">/var/run/ovpnserver.log")) {
399 flock FILE, 2;
400 print FILE "";
401 close FILE;
402 }
403
404 }
405
406 sub delccdnet
407 {
408 my %ccdconfhash = ();
409 my %ccdhash = ();
410 my $ccdnetname=$_[0];
411 if (-f "${General::swroot}/ovpn/ovpnconfig"){
412 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
413 foreach my $key (keys %ccdhash) {
414 if ($ccdhash{$key}[32] eq $ccdnetname) {
415 $errormessage=$Lang::tr{'ccd err hostinnet'};
416 return;
417 }
418 }
419 }
420 &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
421 foreach my $key (keys %ccdconfhash) {
422 if ($ccdconfhash{$key}[0] eq $ccdnetname){
423 delete $ccdconfhash{$key};
424 }
425 }
426 &General::writehasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
427
428 &writeserverconf;
429 return 0;
430 }
431
432 sub addccdnet
433 {
434 my %ccdconfhash=();
435 my @ccdconf=();
436 my $ccdname=$_[0];
437 my $ccdnet=$_[1];
438 my $subcidr;
439 my @ip2=();
440 my $checkup;
441 my $ccdip;
442 my $baseaddress;
443
444
445 #check name
446 if ($ccdname eq '')
447 {
448 $errormessage=$errormessage.$Lang::tr{'ccd err name'}."<br>";
449 return
450 }
451
452 if(!&General::validccdname($ccdname))
453 {
454 $errormessage=$Lang::tr{'ccd err invalidname'};
455 return;
456 }
457
458 ($ccdip,$subcidr) = split (/\//,$ccdnet);
459 $subcidr=&General::iporsubtocidr($subcidr);
460 #check subnet
461 if ($subcidr > 30)
462 {
463 $errormessage=$Lang::tr{'ccd err invalidnet'};
464 return;
465 }
466 #check ip
467 if (!&General::validipandmask($ccdnet)){
468 $errormessage=$Lang::tr{'ccd err invalidnet'};
469 return;
470 }
471
472 if (!$errormessage) {
473 my %ccdconfhash=();
474 $baseaddress=&General::getnetworkip($ccdip,$subcidr);
475 &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
476 my $key = &General::findhasharraykey (\%ccdconfhash);
477 foreach my $i (0 .. 1) { $ccdconfhash{$key}[$i] = "";}
478 $ccdconfhash{$key}[0] = $ccdname;
479 $ccdconfhash{$key}[1] = $baseaddress."/".$subcidr;
480 &General::writehasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
481 &writeserverconf;
482 $cgiparams{'ccdname'}='';
483 $cgiparams{'ccdsubnet'}='';
484 return 1;
485 }
486 }
487
488 sub modccdnet
489 {
490
491 my $newname=$_[0];
492 my $oldname=$_[1];
493 my %ccdconfhash=();
494 my %ccdhash=();
495
496 # Check if the new name is valid.
497 if(!&General::validhostname($newname)) {
498 $errormessage=$Lang::tr{'ccd err invalidname'};
499 return;
500 }
501
502 &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
503 foreach my $key (keys %ccdconfhash) {
504 if ($ccdconfhash{$key}[0] eq $oldname) {
505 foreach my $key1 (keys %ccdconfhash) {
506 if ($ccdconfhash{$key1}[0] eq $newname){
507 $errormessage=$errormessage.$Lang::tr{'ccd err netadrexist'};
508 return;
509 }else{
510 $ccdconfhash{$key}[0]= $newname;
511 &General::writehasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
512 last;
513 }
514 }
515 }
516 }
517
518 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
519 foreach my $key (keys %ccdhash) {
520 if ($ccdhash{$key}[32] eq $oldname) {
521 $ccdhash{$key}[32]=$newname;
522 &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
523 last;
524 }
525 }
526
527 return 0;
528 }
529 sub ccdmaxclients
530 {
531 my $ccdnetwork=$_[0];
532 my @octets=();
533 my @subnet=();
534 @octets=split("\/",$ccdnetwork);
535 @subnet= split /\./, &General::cidrtosub($octets[1]);
536 my ($a,$b,$c,$d,$e);
537 $a=256-$subnet[0];
538 $b=256-$subnet[1];
539 $c=256-$subnet[2];
540 $d=256-$subnet[3];
541 $e=($a*$b*$c*$d)/4;
542 return $e-1;
543 }
544
545 sub getccdadresses
546 {
547 my $ipin=$_[0];
548 my ($ip1,$ip2,$ip3,$ip4)=split /\./, $ipin;
549 my $cidr=$_[1];
550 chomp($cidr);
551 my $count=$_[2];
552 my $hasip=$_[3];
553 chomp($hasip);
554 my @iprange=();
555 my %ccdhash=();
556 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
557 $iprange[0]=$ip1.".".$ip2.".".$ip3.".".($ip4+2);
558 for (my $i=1;$i<=$count;$i++) {
559 my $tmpip=$iprange[$i-1];
560 my $stepper=$i*4;
561 $iprange[$i]= &General::getnextip($tmpip,4);
562 }
563 my $r=0;
564 foreach my $key (keys %ccdhash) {
565 $r=0;
566 foreach my $tmp (@iprange){
567 my ($net,$sub) = split (/\//,$ccdhash{$key}[33]);
568 if ($net eq $tmp) {
569 if ( $hasip ne $ccdhash{$key}[33] ){
570 splice (@iprange,$r,1);
571 }
572 }
573 $r++;
574 }
575 }
576 return @iprange;
577 }
578
579 sub fillselectbox
580 {
581 my $boxname=$_[1];
582 my ($ccdip,$subcidr) = split("/",$_[0]);
583 my $tz=$_[2];
584 my @allccdips=&getccdadresses($ccdip,$subcidr,&ccdmaxclients($ccdip."/".$subcidr),$tz);
585 print"<select name='$boxname' STYLE='font-family : arial; font-size : 9pt; width:130px;' >";
586 foreach (@allccdips) {
587 my $ip=$_."/30";
588 chomp($ip);
589 print "<option value='$ip' ";
590 if ( $ip eq $cgiparams{$boxname} ){
591 print"selected";
592 }
593 print ">$ip</option>";
594 }
595 print "</select>";
596 }
597
598 sub hostsinnet
599 {
600 my $name=$_[0];
601 my %ccdhash=();
602 my $i=0;
603 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
604 foreach my $key (keys %ccdhash) {
605 if ($ccdhash{$key}[32] eq $name){ $i++;}
606 }
607 return $i;
608 }
609
610 sub check_routes_push
611 {
612 my $val=$_[0];
613 my ($ip,$cidr) = split (/\//, $val);
614 ##check for existing routes in routes_push
615 if (-e "${General::swroot}/ovpn/routes_push") {
616 open(FILE,"${General::swroot}/ovpn/routes_push");
617 while (<FILE>) {
618 $_=~s/\s*$//g;
619
620 my ($ip2,$cidr2) = split (/\//,"$_");
621 my $val2=$ip2."/".&General::iporsubtodec($cidr2);
622
623 if($val eq $val2){
624 return 0;
625 }
626 #subnetcheck
627 if (&General::IpInSubnet ($ip,$ip2,&General::iporsubtodec($cidr2))){
628 return 0;
629 }
630 };
631 close(FILE);
632 }
633 return 1;
634 }
635
636 sub check_ccdroute
637 {
638 my %ccdroutehash=();
639 my $val=$_[0];
640 my ($ip,$cidr) = split (/\//, $val);
641 #check for existing routes in ccdroute
642 &General::readhasharray("${General::swroot}/ovpn/ccdroute", \%ccdroutehash);
643 foreach my $key (keys %ccdroutehash) {
644 foreach my $i (1 .. $#{$ccdroutehash{$key}}) {
645 if (&General::iporsubtodec($val) eq $ccdroutehash{$key}[$i] && $ccdroutehash{$key}[0] ne $cgiparams{'NAME'}){
646 return 0;
647 }
648 my ($ip2,$cidr2) = split (/\//,$ccdroutehash{$key}[$i]);
649 #subnetcheck
650 if (&General::IpInSubnet ($ip,$ip2,$cidr2)&& $ccdroutehash{$key}[0] ne $cgiparams{'NAME'} ){
651 return 0;
652 }
653 }
654 }
655 return 1;
656 }
657 sub check_ccdconf
658 {
659 my %ccdconfhash=();
660 my $val=$_[0];
661 my ($ip,$cidr) = split (/\//, $val);
662 #check for existing routes in ccdroute
663 &General::readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
664 foreach my $key (keys %ccdconfhash) {
665 if (&General::iporsubtocidr($val) eq $ccdconfhash{$key}[1]){
666 return 0;
667 }
668 my ($ip2,$cidr2) = split (/\//,$ccdconfhash{$key}[1]);
669 #subnetcheck
670 if (&General::IpInSubnet ($ip,$ip2,&General::cidrtosub($cidr2))){
671 return 0;
672 }
673
674 }
675 return 1;
676 }
677
678 ###
679 # m.a.d net2net
680 ###
681
682 sub validdotmask
683 {
684 my $ipdotmask = $_[0];
685 if (&General::validip($ipdotmask)) { return 0; }
686 if (!($ipdotmask =~ /^(.*?)\/(.*?)$/)) { }
687 my $mask = $2;
688 if (($mask =~ /\./ )) { return 0; }
689 return 1;
690 }
691
692 # -------------------------------------------------------------------
693
694 sub write_routepushfile
695 {
696 open(FILE, ">$routes_push_file");
697 flock(FILE, 2);
698 if ($vpnsettings{'ROUTES_PUSH'} ne '') {
699 print FILE $vpnsettings{'ROUTES_PUSH'};
700 }
701 close(FILE);
702 }
703
704 sub read_routepushfile
705 {
706 if (-e "$routes_push_file") {
707 open(FILE,"$routes_push_file");
708 delete $vpnsettings{'ROUTES_PUSH'};
709 while (<FILE>) { $vpnsettings{'ROUTES_PUSH'} .= $_ };
710 close(FILE);
711 $cgiparams{'ROUTES_PUSH'} = $vpnsettings{'ROUTES_PUSH'};
712
713 }
714 }
715
716 sub writecollectdconf {
717 my $vpncollectd;
718 my %ccdhash=();
719
720 open(COLLECTDVPN, ">${General::swroot}/ovpn/collectd.vpn") or die "Unable to open collectd.vpn: $!";
721 print COLLECTDVPN "Loadplugin openvpn\n";
722 print COLLECTDVPN "\n";
723 print COLLECTDVPN "<Plugin openvpn>\n";
724 print COLLECTDVPN "Statusfile \"/var/run/ovpnserver.log\"\n";
725
726 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ccdhash);
727 foreach my $key (keys %ccdhash) {
728 if ($ccdhash{$key}[0] eq 'on' && $ccdhash{$key}[3] eq 'net') {
729 print COLLECTDVPN "Statusfile \"/var/run/openvpn/$ccdhash{$key}[1]-n2n\"\n";
730 }
731 }
732
733 print COLLECTDVPN "</Plugin>\n";
734 close(COLLECTDVPN);
735
736 # Reload collectd afterwards
737 &General::system("/usr/local/bin/collectdctrl", "restart");
738 }
739
740 #hier die refresh page
741 if ( -e "${General::swroot}/ovpn/gencanow") {
742 my $refresh = '';
743 $refresh = "<meta http-equiv='refresh' content='15;' />";
744 &Header::showhttpheaders();
745 &Header::openpage($Lang::tr{'OVPN'}, 1, $refresh);
746 &Header::openbigbox('100%', 'center');
747 &Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
748 print "<tr>\n<td align='center'><img src='/images/clock.gif' alt='' /></td>\n";
749 print "<td colspan='2'><font color='red'>Please be patient this realy can take some time on older hardware...</font></td></tr>\n";
750 &Header::closebox();
751 &Header::closebigbox();
752 &Header::closepage();
753 exit (0);
754 }
755 ##hier die refresh page
756
757
758 ###
759 ### OpenVPN Server Control
760 ###
761 if ($cgiparams{'ACTION'} eq $Lang::tr{'start ovpn server'} ||
762 $cgiparams{'ACTION'} eq $Lang::tr{'stop ovpn server'} ||
763 $cgiparams{'ACTION'} eq $Lang::tr{'restart ovpn server'}) {
764 #start openvpn server
765 if ($cgiparams{'ACTION'} eq $Lang::tr{'start ovpn server'}){
766 &emptyserverlog();
767 &General::system("/usr/local/bin/openvpnctrl", "-s");
768 }
769 #stop openvpn server
770 if ($cgiparams{'ACTION'} eq $Lang::tr{'stop ovpn server'}){
771 &General::system("/usr/local/bin/openvpnctrl", "-k");
772 &emptyserverlog();
773 }
774 # #restart openvpn server
775 # if ($cgiparams{'ACTION'} eq $Lang::tr{'restart ovpn server'}){
776 #workarund, till SIGHUP also works when running as nobody
777 # system('/usr/local/bin/openvpnctrl', '-r');
778 # &emptyserverlog();
779 # }
780 }
781
782 ###
783 ### Save Advanced options
784 ###
785
786 if ($cgiparams{'ACTION'} eq $Lang::tr{'save-adv-options'}) {
787 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
788 #DAN do we really need (to to check) this value? Besides if we listen on blue and orange too,
789 #DAN this value has to leave.
790 #new settings for daemon
791 $vpnsettings{'LOG_VERB'} = $cgiparams{'LOG_VERB'};
792 $vpnsettings{'KEEPALIVE_1'} = $cgiparams{'KEEPALIVE_1'};
793 $vpnsettings{'KEEPALIVE_2'} = $cgiparams{'KEEPALIVE_2'};
794 $vpnsettings{'MAX_CLIENTS'} = $cgiparams{'MAX_CLIENTS'};
795 $vpnsettings{'REDIRECT_GW_DEF1'} = $cgiparams{'REDIRECT_GW_DEF1'};
796 $vpnsettings{'CLIENT2CLIENT'} = $cgiparams{'CLIENT2CLIENT'};
797 $vpnsettings{'DCOMPLZO'} = $cgiparams{'DCOMPLZO'};
798 $vpnsettings{'ADDITIONAL_CONFIGS'} = $cgiparams{'ADDITIONAL_CONFIGS'};
799 $vpnsettings{'DHCP_DOMAIN'} = $cgiparams{'DHCP_DOMAIN'};
800 $vpnsettings{'DHCP_DNS'} = $cgiparams{'DHCP_DNS'};
801 $vpnsettings{'DHCP_WINS'} = $cgiparams{'DHCP_WINS'};
802 $vpnsettings{'ROUTES_PUSH'} = $cgiparams{'ROUTES_PUSH'};
803 my @temp=();
804
805 if ($cgiparams{'FRAGMENT'} eq '') {
806 delete $vpnsettings{'FRAGMENT'};
807 } else {
808 if ($cgiparams{'FRAGMENT'} !~ /^[0-9]+$/) {
809 $errormessage = "Incorrect value, please insert only numbers.";
810 goto ADV_ERROR;
811 } else {
812 $vpnsettings{'FRAGMENT'} = $cgiparams{'FRAGMENT'};
813 }
814 }
815
816 if ($cgiparams{'MSSFIX'} ne 'on') {
817 delete $vpnsettings{'MSSFIX'};
818 } else {
819 $vpnsettings{'MSSFIX'} = $cgiparams{'MSSFIX'};
820 }
821
822 if ($cgiparams{'DHCP_DOMAIN'} ne ''){
823 unless (&General::validdomainname($cgiparams{'DHCP_DOMAIN'}) || &General::validip($cgiparams{'DHCP_DOMAIN'})) {
824 $errormessage = $Lang::tr{'invalid input for dhcp domain'};
825 goto ADV_ERROR;
826 }
827 }
828 if ($cgiparams{'DHCP_DNS'} ne ''){
829 unless (&General::validfqdn($cgiparams{'DHCP_DNS'}) || &General::validip($cgiparams{'DHCP_DNS'})) {
830 $errormessage = $Lang::tr{'invalid input for dhcp dns'};
831 goto ADV_ERROR;
832 }
833 }
834 if ($cgiparams{'DHCP_WINS'} ne ''){
835 unless (&General::validfqdn($cgiparams{'DHCP_WINS'}) || &General::validip($cgiparams{'DHCP_WINS'})) {
836 $errormessage = $Lang::tr{'invalid input for dhcp wins'};
837 goto ADV_ERROR;
838 }
839 }
840 if ($cgiparams{'ROUTES_PUSH'} ne ''){
841 @temp = split(/\n/,$cgiparams{'ROUTES_PUSH'});
842 undef $vpnsettings{'ROUTES_PUSH'};
843
844 foreach my $tmpip (@temp)
845 {
846 s/^\s+//g; s/\s+$//g;
847
848 if ($tmpip)
849 {
850 $tmpip=~s/\s*$//g;
851 unless (&General::validipandmask($tmpip)) {
852 $errormessage = "$tmpip ".$Lang::tr{'ovpn errmsg invalid ip or mask'};
853 goto ADV_ERROR;
854 }
855 my ($ip, $cidr) = split("\/",&General::ipcidr2msk($tmpip));
856
857 if ($ip eq $netsettings{'GREEN_NETADDRESS'} && $cidr eq $netsettings{'GREEN_NETMASK'}) {
858 $errormessage = $Lang::tr{'ovpn errmsg green already pushed'};
859 goto ADV_ERROR;
860 }
861 # a.marx ccd
862 my %ccdroutehash=();
863 &General::readhasharray("${General::swroot}/ovpn/ccdroute", \%ccdroutehash);
864 foreach my $key (keys %ccdroutehash) {
865 foreach my $i (1 .. $#{$ccdroutehash{$key}}) {
866 if ( $ip."/".$cidr eq $ccdroutehash{$key}[$i] ){
867 $errormessage="Route $ip\/$cidr ".$Lang::tr{'ccd err inuse'}." $ccdroutehash{$key}[0]" ;
868 goto ADV_ERROR;
869 }
870 my ($ip2,$cidr2) = split(/\//,$ccdroutehash{$key}[$i]);
871 if (&General::IpInSubnet ($ip,$ip2,$cidr2)){
872 $errormessage="Route $ip\/$cidr ".$Lang::tr{'ccd err inuse'}." $ccdroutehash{$key}[0]" ;
873 goto ADV_ERROR;
874 }
875 }
876 }
877
878 # ccd end
879
880 $vpnsettings{'ROUTES_PUSH'} .= $tmpip."\n";
881 }
882 }
883 &write_routepushfile;
884 undef $vpnsettings{'ROUTES_PUSH'};
885 }
886 else {
887 undef $vpnsettings{'ROUTES_PUSH'};
888 &write_routepushfile;
889 }
890 if ((length($cgiparams{'MAX_CLIENTS'}) == 0) || (($cgiparams{'MAX_CLIENTS'}) < 1 ) || (($cgiparams{'MAX_CLIENTS'}) > 1024 )) {
891 $errormessage = $Lang::tr{'invalid input for max clients'};
892 goto ADV_ERROR;
893 }
894 if ($cgiparams{'KEEPALIVE_1'} ne '') {
895 if ($cgiparams{'KEEPALIVE_1'} !~ /^[0-9]+$/) {
896 $errormessage = $Lang::tr{'invalid input for keepalive 1'};
897 goto ADV_ERROR;
898 }
899 }
900 if ($cgiparams{'KEEPALIVE_2'} ne ''){
901 if ($cgiparams{'KEEPALIVE_2'} !~ /^[0-9]+$/) {
902 $errormessage = $Lang::tr{'invalid input for keepalive 2'};
903 goto ADV_ERROR;
904 }
905 }
906 if ($cgiparams{'KEEPALIVE_2'} < ($cgiparams{'KEEPALIVE_1'} * 2)){
907 $errormessage = $Lang::tr{'invalid input for keepalive 1:2'};
908 goto ADV_ERROR;
909 }
910 &General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
911 &writeserverconf();#hier ok
912 }
913
914 ###
915 # m.a.d net2net
916 ###
917
918 if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && $cgiparams{'SIDE'} eq 'server')
919 {
920
921 my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'});
922 my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'});
923 my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
924 my $tunmtu = '';
925
926 unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";}
927 unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}", 0770 or die "Unable to create dir $!";}
928
929 open(SERVERCONF, ">${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Unable to open ${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf: $!";
930
931 flock SERVERCONF, 2;
932 print SERVERCONF "# IPFire n2n Open VPN Server Config by ummeegge und m.a.d\n";
933 print SERVERCONF "\n";
934 print SERVERCONF "# User Security\n";
935 print SERVERCONF "user nobody\n";
936 print SERVERCONF "group nobody\n";
937 print SERVERCONF "persist-tun\n";
938 print SERVERCONF "persist-key\n";
939 print SERVERCONF "script-security 2\n";
940 print SERVERCONF "# IP/DNS for remote Server Gateway\n";
941
942 if ($cgiparams{'REMOTE'} ne '') {
943 print SERVERCONF "remote $cgiparams{'REMOTE'}\n";
944 }
945
946 print SERVERCONF "float\n";
947 print SERVERCONF "# IP adresses of the VPN Subnet\n";
948 print SERVERCONF "ifconfig $ovsubnet.1 $ovsubnet.2\n";
949 print SERVERCONF "# Client Gateway Network\n";
950 print SERVERCONF "route $remsubnet[0] $remsubnet[1]\n";
951 print SERVERCONF "up \"/etc/init.d/static-routes start\"\n";
952 print SERVERCONF "# tun Device\n";
953 print SERVERCONF "dev tun\n";
954 print SERVERCONF "#Logfile for statistics\n";
955 print SERVERCONF "status-version 1\n";
956 print SERVERCONF "status /var/run/openvpn/$cgiparams{'NAME'}-n2n 10\n";
957 print SERVERCONF "# Port and Protokol\n";
958 print SERVERCONF "port $cgiparams{'DEST_PORT'}\n";
959
960 if ($cgiparams{'PROTOCOL'} eq 'tcp') {
961 print SERVERCONF "proto tcp4-server\n";
962 print SERVERCONF "# Packet size\n";
963 if ($cgiparams{'MTU'} eq '') {$tunmtu = '1400'} else {$tunmtu = $cgiparams{'MTU'}};
964 print SERVERCONF "tun-mtu $tunmtu\n";
965 }
966
967 if ($cgiparams{'PROTOCOL'} eq 'udp') {
968 print SERVERCONF "proto udp4\n";
969 print SERVERCONF "# Paketsize\n";
970 if ($cgiparams{'MTU'} eq '') {$tunmtu = '1500'} else {$tunmtu = $cgiparams{'MTU'}};
971 print SERVERCONF "tun-mtu $tunmtu\n";
972 if ($cgiparams{'FRAGMENT'} ne '') {print SERVERCONF "fragment $cgiparams{'FRAGMENT'}\n";}
973 if ($cgiparams{'MSSFIX'} eq 'on') {print SERVERCONF "mssfix\n"; } else { print SERVERCONF "mssfix 0\n" };
974 }
975
976 print SERVERCONF "# Auth. Server\n";
977 print SERVERCONF "tls-server\n";
978 print SERVERCONF "ca ${General::swroot}/ovpn/ca/cacert.pem\n";
979 print SERVERCONF "cert ${General::swroot}/ovpn/certs/servercert.pem\n";
980 print SERVERCONF "key ${General::swroot}/ovpn/certs/serverkey.pem\n";
981 print SERVERCONF "dh $dhparameter\n";
982 print SERVERCONF "# Cipher\n";
983 print SERVERCONF "cipher $cgiparams{'DCIPHER'}\n";
984
985 # If GCM cipher is used, do not use --auth
986 if (($cgiparams{'DCIPHER'} eq 'AES-256-GCM') ||
987 ($cgiparams{'DCIPHER'} eq 'AES-192-GCM') ||
988 ($cgiparams{'DCIPHER'} eq 'AES-128-GCM')) {
989 print SERVERCONF unless "# HMAC algorithm\n";
990 print SERVERCONF unless "auth $cgiparams{'DAUTH'}\n";
991 } else {
992 print SERVERCONF "# HMAC algorithm\n";
993 print SERVERCONF "auth $cgiparams{'DAUTH'}\n";
994 }
995
996 # Set TLSv1.2 as minimum
997 print SERVERCONF "tls-version-min 1.2\n";
998
999 if ($cgiparams{'COMPLZO'} eq 'on') {
1000 print SERVERCONF "# Enable Compression\n";
1001 print SERVERCONF "comp-lzo\n";
1002 }
1003 print SERVERCONF "# Debug Level\n";
1004 print SERVERCONF "verb 3\n";
1005 print SERVERCONF "# Tunnel check\n";
1006 print SERVERCONF "keepalive 10 60\n";
1007 print SERVERCONF "# Start as daemon\n";
1008 print SERVERCONF "daemon $cgiparams{'NAME'}n2n\n";
1009 print SERVERCONF "writepid /var/run/$cgiparams{'NAME'}n2n.pid\n";
1010 print SERVERCONF "# Activate Management Interface and Port\n";
1011 if ($cgiparams{'OVPN_MGMT'} eq '') {print SERVERCONF "management localhost $cgiparams{'DEST_PORT'}\n"}
1012 else {print SERVERCONF "management localhost $cgiparams{'OVPN_MGMT'}\n"};
1013 close(SERVERCONF);
1014
1015 }
1016
1017 ###
1018 # m.a.d net2net
1019 ###
1020
1021 if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq 'net' && $cgiparams{'SIDE'} eq 'client')
1022 {
1023
1024 my @ovsubnettemp = split(/\./,$cgiparams{'OVPN_SUBNET'});
1025 my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
1026 my @remsubnet = split(/\//,$cgiparams{'REMOTE_SUBNET'});
1027 my $tunmtu = '';
1028
1029 unless(-d "${General::swroot}/ovpn/n2nconf/"){mkdir "${General::swroot}/ovpn/n2nconf", 0755 or die "Unable to create dir $!";}
1030 unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}", 0770 or die "Unable to create dir $!";}
1031
1032 open(CLIENTCONF, ">${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf") or die "Unable to open ${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}/$cgiparams{'NAME'}.conf: $!";
1033
1034 flock CLIENTCONF, 2;
1035 print CLIENTCONF "# IPFire rewritten n2n Open VPN Client Config by ummeegge und m.a.d\n";
1036 print CLIENTCONF "#\n";
1037 print CLIENTCONF "# User Security\n";
1038 print CLIENTCONF "user nobody\n";
1039 print CLIENTCONF "group nobody\n";
1040 print CLIENTCONF "persist-tun\n";
1041 print CLIENTCONF "persist-key\n";
1042 print CLIENTCONF "script-security 2\n";
1043 print CLIENTCONF "# IP/DNS for remote Server Gateway\n";
1044 print CLIENTCONF "remote $cgiparams{'REMOTE'}\n";
1045 print CLIENTCONF "float\n";
1046 print CLIENTCONF "# IP adresses of the VPN Subnet\n";
1047 print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n";
1048 print CLIENTCONF "# Server Gateway Network\n";
1049 print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n";
1050 print CLIENTCONF "up \"/etc/init.d/static-routes start\"\n";
1051 print CLIENTCONF "# tun Device\n";
1052 print CLIENTCONF "dev tun\n";
1053 print CLIENTCONF "#Logfile for statistics\n";
1054 print CLIENTCONF "status-version 1\n";
1055 print CLIENTCONF "status /var/run/openvpn/$cgiparams{'NAME'}-n2n 10\n";
1056 print CLIENTCONF "# Port and Protokol\n";
1057 print CLIENTCONF "port $cgiparams{'DEST_PORT'}\n";
1058
1059 if ($cgiparams{'PROTOCOL'} eq 'tcp') {
1060 print CLIENTCONF "proto tcp4-client\n";
1061 print CLIENTCONF "# Packet size\n";
1062 if ($cgiparams{'MTU'} eq '') {$tunmtu = '1400'} else {$tunmtu = $cgiparams{'MTU'}};
1063 print CLIENTCONF "tun-mtu $tunmtu\n";
1064 }
1065
1066 if ($cgiparams{'PROTOCOL'} eq 'udp') {
1067 print CLIENTCONF "proto udp4\n";
1068 print CLIENTCONF "# Paketsize\n";
1069 if ($cgiparams{'MTU'} eq '') {$tunmtu = '1500'} else {$tunmtu = $cgiparams{'MTU'}};
1070 print CLIENTCONF "tun-mtu $tunmtu\n";
1071 if ($cgiparams{'FRAGMENT'} ne '') {print CLIENTCONF "fragment $cgiparams{'FRAGMENT'}\n";}
1072 if ($cgiparams{'MSSFIX'} eq 'on') {print CLIENTCONF "mssfix\n"; } else { print CLIENTCONF "mssfix 0\n" };
1073 }
1074
1075 # Check host certificate if X509 is RFC3280 compliant.
1076 # If not, old --ns-cert-type directive will be used.
1077 # If appropriate key usage extension exists, new --remote-cert-tls directive will be used.
1078 my @hostcert = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
1079 if ( ! grep(/TLS Web Server Authentication/, @hostcert)) {
1080 print CLIENTCONF "ns-cert-type server\n";
1081 } else {
1082 print CLIENTCONF "remote-cert-tls server\n";
1083 }
1084 print CLIENTCONF "# Auth. Client\n";
1085 print CLIENTCONF "tls-client\n";
1086 print CLIENTCONF "# Cipher\n";
1087 print CLIENTCONF "cipher $cgiparams{'DCIPHER'}\n";
1088 print CLIENTCONF "pkcs12 ${General::swroot}/ovpn/certs/$cgiparams{'NAME'}.p12\r\n";
1089
1090 # If GCM cipher is used, do not use --auth
1091 if (($cgiparams{'DCIPHER'} eq 'AES-256-GCM') ||
1092 ($cgiparams{'DCIPHER'} eq 'AES-192-GCM') ||
1093 ($cgiparams{'DCIPHER'} eq 'AES-128-GCM')) {
1094 print CLIENTCONF unless "# HMAC algorithm\n";
1095 print CLIENTCONF unless "auth $cgiparams{'DAUTH'}\n";
1096 } else {
1097 print CLIENTCONF "# HMAC algorithm\n";
1098 print CLIENTCONF "auth $cgiparams{'DAUTH'}\n";
1099 }
1100
1101 # Set TLSv1.2 as minimum
1102 print CLIENTCONF "tls-version-min 1.2\n";
1103
1104 if ($cgiparams{'COMPLZO'} eq 'on') {
1105 print CLIENTCONF "# Enable Compression\n";
1106 print CLIENTCONF "comp-lzo\n";
1107 }
1108 print CLIENTCONF "# Debug Level\n";
1109 print CLIENTCONF "verb 3\n";
1110 print CLIENTCONF "# Tunnel check\n";
1111 print CLIENTCONF "keepalive 10 60\n";
1112 print CLIENTCONF "# Start as daemon\n";
1113 print CLIENTCONF "daemon $cgiparams{'NAME'}n2n\n";
1114 print CLIENTCONF "writepid /var/run/$cgiparams{'NAME'}n2n.pid\n";
1115 print CLIENTCONF "# Activate Management Interface and Port\n";
1116 if ($cgiparams{'OVPN_MGMT'} eq '') {print CLIENTCONF "management localhost $cgiparams{'DEST_PORT'}\n"}
1117 else {print CLIENTCONF "management localhost $cgiparams{'OVPN_MGMT'}\n"};
1118 close(CLIENTCONF);
1119
1120 }
1121
1122 ###
1123 ### Save main settings
1124 ###
1125
1126 if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} && $cgiparams{'TYPE'} eq '' && $cgiparams{'KEY'} eq '') {
1127 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
1128 #DAN do we really need (to to check) this value? Besides if we listen on blue and orange too,
1129 #DAN this value has to leave.
1130 if ($cgiparams{'ENABLED'} eq 'on'){
1131 unless (&General::validfqdn($cgiparams{'VPN_IP'}) || &General::validip($cgiparams{'VPN_IP'})) {
1132 $errormessage = $Lang::tr{'invalid input for hostname'};
1133 goto SETTINGS_ERROR;
1134 }
1135 }
1136
1137 if (! &General::validipandmask($cgiparams{'DOVPN_SUBNET'})) {
1138 $errormessage = $Lang::tr{'ovpn subnet is invalid'};
1139 goto SETTINGS_ERROR;
1140 }
1141 my @tmpovpnsubnet = split("\/",$cgiparams{'DOVPN_SUBNET'});
1142
1143 if (&General::IpInSubnet ( $netsettings{'RED_ADDRESS'},
1144 $tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
1145 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire RED Network $netsettings{'RED_ADDRESS'}";
1146 goto SETTINGS_ERROR;
1147 }
1148
1149 if (&General::IpInSubnet ( $netsettings{'GREEN_ADDRESS'},
1150 $tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
1151 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Green Network $netsettings{'GREEN_ADDRESS'}";
1152 goto SETTINGS_ERROR;
1153 }
1154
1155 if (&General::IpInSubnet ( $netsettings{'BLUE_ADDRESS'},
1156 $tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
1157 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Blue Network $netsettings{'BLUE_ADDRESS'}";
1158 goto SETTINGS_ERROR;
1159 }
1160
1161 if (&General::IpInSubnet ( $netsettings{'ORANGE_ADDRESS'},
1162 $tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
1163 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Orange Network $netsettings{'ORANGE_ADDRESS'}";
1164 goto SETTINGS_ERROR;
1165 }
1166 open(ALIASES, "${General::swroot}/ethernet/aliases") or die 'Unable to open aliases file.';
1167 while (<ALIASES>)
1168 {
1169 chomp($_);
1170 my @tempalias = split(/\,/,$_);
1171 if ($tempalias[1] eq 'on') {
1172 if (&General::IpInSubnet ($tempalias[0] ,
1173 $tmpovpnsubnet[0], $tmpovpnsubnet[1])) {
1174 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire alias entry $tempalias[0]";
1175 }
1176 }
1177 }
1178 close(ALIASES);
1179 if ($errormessage ne ''){
1180 goto SETTINGS_ERROR;
1181 }
1182 if ($cgiparams{'ENABLED'} !~ /^(on|off)$/) {
1183 $errormessage = $Lang::tr{'invalid input'};
1184 goto SETTINGS_ERROR;
1185 }
1186 if ((length($cgiparams{'DMTU'})==0) || (($cgiparams{'DMTU'}) < 1000 )) {
1187 $errormessage = $Lang::tr{'invalid mtu input'};
1188 goto SETTINGS_ERROR;
1189 }
1190
1191 unless (&General::validport($cgiparams{'DDEST_PORT'})) {
1192 $errormessage = $Lang::tr{'invalid port'};
1193 goto SETTINGS_ERROR;
1194 }
1195
1196 # Create ta.key for tls-auth if not presant
1197 if ($cgiparams{'TLSAUTH'} eq 'on') {
1198 if ( ! -e "${General::swroot}/ovpn/certs/ta.key") {
1199 # This system call is safe, because all arguements are passed as an array.
1200 system("/usr/sbin/openvpn", "--genkey", "secret", "${General::swroot}/ovpn/certs/ta.key");
1201 if ($?) {
1202 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1203 goto SETTINGS_ERROR;
1204 }
1205 }
1206 }
1207
1208 $vpnsettings{'ENABLED_BLUE'} = $cgiparams{'ENABLED_BLUE'};
1209 $vpnsettings{'ENABLED_ORANGE'} =$cgiparams{'ENABLED_ORANGE'};
1210 $vpnsettings{'ENABLED'} = $cgiparams{'ENABLED'};
1211 $vpnsettings{'VPN_IP'} = $cgiparams{'VPN_IP'};
1212 #new settings for daemon
1213 $vpnsettings{'DOVPN_SUBNET'} = $cgiparams{'DOVPN_SUBNET'};
1214 $vpnsettings{'DPROTOCOL'} = $cgiparams{'DPROTOCOL'};
1215 $vpnsettings{'DDEST_PORT'} = $cgiparams{'DDEST_PORT'};
1216 $vpnsettings{'DMTU'} = $cgiparams{'DMTU'};
1217 $vpnsettings{'DCOMPLZO'} = $cgiparams{'DCOMPLZO'};
1218 $vpnsettings{'DCIPHER'} = $cgiparams{'DCIPHER'};
1219 $vpnsettings{'DAUTH'} = $cgiparams{'DAUTH'};
1220 $vpnsettings{'TLSAUTH'} = $cgiparams{'TLSAUTH'};
1221 #wrtie enable
1222
1223 if ( $vpnsettings{'ENABLED_BLUE'} eq 'on' ) {
1224 &General::system("touch", "${General::swroot}/ovpn/enable_blue");
1225 } else {
1226 unlink("${General::swroot}/ovpn/enable_blue");
1227 }
1228
1229 if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' ) {
1230 &General::system("touch", "${General::swroot}/ovpn/enable_orange");
1231 } else {
1232 unlink("${General::swroot}/ovpn/enable_orange");
1233 }
1234
1235 if ( $vpnsettings{'ENABLED'} eq 'on' ) {
1236 &General::system("touch", "${General::swroot}/ovpn/enable");
1237 } else {
1238 unlink("${General::swroot}/ovpn/enable");
1239 }
1240
1241 #new settings for daemon
1242 &General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
1243 &writeserverconf();#hier ok
1244 SETTINGS_ERROR:
1245 ###
1246 ### Reset all step 2
1247 ###
1248 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'} && $cgiparams{'AREUSURE'} eq 'yes') {
1249 my $file = '';
1250 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
1251
1252 # Kill all N2N connections
1253 &General::system("/usr/local/bin/openvpnctrl", "-kn2n");
1254
1255 foreach my $key (keys %confighash) {
1256 my $name = $confighash{$cgiparams{'$key'}}[1];
1257
1258 if ($confighash{$key}[4] eq 'cert') {
1259 delete $confighash{$cgiparams{'$key'}};
1260 }
1261
1262 &General::system("/usr/local/bin/openvpnctrl", "-drrd", "$name");
1263 }
1264 while ($file = glob("${General::swroot}/ovpn/ca/*")) {
1265 unlink $file;
1266 }
1267 while ($file = glob("${General::swroot}/ovpn/certs/*")) {
1268 unlink $file;
1269 }
1270 while ($file = glob("${General::swroot}/ovpn/crls/*")) {
1271 unlink $file;
1272 }
1273 &cleanssldatabase();
1274 if (open(FILE, ">${General::swroot}/ovpn/caconfig")) {
1275 print FILE "";
1276 close FILE;
1277 }
1278 if (open(FILE, ">${General::swroot}/ovpn/ccdroute")) {
1279 print FILE "";
1280 close FILE;
1281 }
1282 if (open(FILE, ">${General::swroot}/ovpn/ccdroute2")) {
1283 print FILE "";
1284 close FILE;
1285 }
1286 while ($file = glob("${General::swroot}/ovpn/ccd/*")) {
1287 unlink $file
1288 }
1289 while ($file = glob("${General::swroot}/ovpn/ccd/*")) {
1290 unlink $file
1291 }
1292 if (open(FILE, ">${General::swroot}/ovpn/ovpn-leases.db")) {
1293 print FILE "";
1294 close FILE;
1295 }
1296 if (open(FILE, ">${General::swroot}/ovpn/ovpnconfig")) {
1297 print FILE "";
1298 close FILE;
1299 }
1300 while ($file = glob("${General::swroot}/ovpn/n2nconf/*")) {
1301 unlink($file);
1302 }
1303
1304 # Remove everything from the collectd configuration
1305 &writecollectdconf();
1306
1307 #&writeserverconf();
1308 ###
1309 ### Reset all step 1
1310 ###
1311 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove x509'}) {
1312 &Header::showhttpheaders();
1313 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
1314 &Header::openbigbox('100%', 'left', '', '');
1315 &Header::openbox('100%', 'left', $Lang::tr{'are you sure'});
1316 print <<END;
1317 <form method='post'>
1318 <table width='100%'>
1319 <tr>
1320 <td align='center'>
1321 <input type='hidden' name='AREUSURE' value='yes' />
1322 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>:
1323 $Lang::tr{'resetting the vpn configuration will remove the root ca, the host certificate and all certificate based connections'}</td>
1324 </tr>
1325 <tr>
1326 <td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'remove x509'}' />
1327 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td>
1328 </tr>
1329 </table>
1330 </form>
1331 END
1332 ;
1333 &Header::closebox();
1334 &Header::closebigbox();
1335 &Header::closepage();
1336 exit (0);
1337
1338 ###
1339 ### Upload CA Certificate
1340 ###
1341 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload ca certificate'}) {
1342 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1343
1344 if ($cgiparams{'CA_NAME'} !~ /^[a-zA-Z0-9]+$/) {
1345 $errormessage = $Lang::tr{'name must only contain characters'};
1346 goto UPLOADCA_ERROR;
1347 }
1348
1349 if (length($cgiparams{'CA_NAME'}) >60) {
1350 $errormessage = $Lang::tr{'name too long'};
1351 goto VPNCONF_ERROR;
1352 }
1353
1354 if ($cgiparams{'CA_NAME'} eq 'ca') {
1355 $errormessage = $Lang::tr{'name is invalid'};
1356 goto UPLOADCA_ERROR;
1357 }
1358
1359 # Check if there is no other entry with this name
1360 foreach my $key (keys %cahash) {
1361 if ($cahash{$key}[0] eq $cgiparams{'CA_NAME'}) {
1362 $errormessage = $Lang::tr{'a ca certificate with this name already exists'};
1363 goto UPLOADCA_ERROR;
1364 }
1365 }
1366
1367 unless (ref ($cgiparams{'FH'})) {
1368 $errormessage = $Lang::tr{'there was no file upload'};
1369 goto UPLOADCA_ERROR;
1370 }
1371 # Move uploaded ca to a temporary file
1372 (my $fh, my $filename) = tempfile( );
1373 if (copy ($cgiparams{'FH'}, $fh) != 1) {
1374 $errormessage = $!;
1375 goto UPLOADCA_ERROR;
1376 }
1377 my @temp = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "$filename");
1378 if ( ! grep(/CA:TRUE/i, @temp )) {
1379 $errormessage = $Lang::tr{'not a valid ca certificate'};
1380 unlink ($filename);
1381 goto UPLOADCA_ERROR;
1382 } else {
1383 unless(move($filename, "${General::swroot}/ovpn/ca/$cgiparams{'CA_NAME'}cert.pem")) {
1384 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1385 unlink ($filename);
1386 goto UPLOADCA_ERROR;
1387 }
1388 }
1389
1390 my @casubject = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/ca/$cgiparams{'CA_NAME'}cert.pem");
1391 my $casubject;
1392
1393 foreach my $line (@casubject) {
1394 if ($line =~ /Subject: (.*)[\n]/) {
1395 $casubject = $1;
1396 $casubject =~ s+/Email+, E+;
1397 $casubject =~ s/ ST=/ S=/;
1398
1399 last;
1400 }
1401 }
1402
1403 $casubject = &Header::cleanhtml($casubject);
1404
1405 my $key = &General::findhasharraykey (\%cahash);
1406 $cahash{$key}[0] = $cgiparams{'CA_NAME'};
1407 $cahash{$key}[1] = $casubject;
1408 &General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1409 # system('/usr/local/bin/ipsecctrl', 'R');
1410
1411 UPLOADCA_ERROR:
1412
1413 ###
1414 ### Display ca certificate
1415 ###
1416 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show ca certificate'}) {
1417 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1418
1419 if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem") {
1420 &Header::showhttpheaders();
1421 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
1422 &Header::openbigbox('100%', 'LEFT', '', $errormessage);
1423 &Header::openbox('100%', 'LEFT', "$Lang::tr{'ca certificate'}:");
1424 my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
1425 my $output = &Header::cleanhtml(join("", @output),"y");
1426 print "<pre>$output</pre>\n";
1427 &Header::closebox();
1428 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
1429 &Header::closebigbox();
1430 &Header::closepage();
1431 exit(0);
1432 } else {
1433 $errormessage = $Lang::tr{'invalid key'};
1434 }
1435
1436 ###
1437 ### Download ca certificate
1438 ###
1439 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download ca certificate'}) {
1440 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1441
1442 if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
1443 print "Content-Type: application/octet-stream\r\n";
1444 print "Content-Disposition: filename=$cahash{$cgiparams{'KEY'}}[0]cert.pem\r\n\r\n";
1445
1446 my @tmp = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
1447 print @tmp;
1448
1449 exit(0);
1450 } else {
1451 $errormessage = $Lang::tr{'invalid key'};
1452 }
1453
1454 ###
1455 ### Remove ca certificate (step 2)
1456 ###
1457 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'} && $cgiparams{'AREUSURE'} eq 'yes') {
1458 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
1459 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1460
1461 if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
1462 foreach my $key (keys %confighash) {
1463 my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem");
1464 if (grep(/: OK/, @test)) {
1465 # Delete connection
1466 # if ($vpnsettings{'ENABLED'} eq 'on' ||
1467 # $vpnsettings{'ENABLED_BLUE'} eq 'on') {
1468 # system('/usr/local/bin/ipsecctrl', 'D', $key);
1469 # }
1470 unlink ("${General::swroot}/ovpn//certs/$confighash{$key}[1]cert.pem");
1471 unlink ("${General::swroot}/ovpn/certs/$confighash{$key}[1].p12");
1472 delete $confighash{$key};
1473 &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
1474 # &writeipsecfiles();
1475 }
1476 }
1477 unlink ("${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
1478 delete $cahash{$cgiparams{'KEY'}};
1479 &General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1480 # system('/usr/local/bin/ipsecctrl', 'R');
1481 } else {
1482 $errormessage = $Lang::tr{'invalid key'};
1483 }
1484 ###
1485 ### Remove ca certificate (step 1)
1486 ###
1487 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove ca certificate'}) {
1488 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
1489 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1490
1491 my $assignedcerts = 0;
1492 if ( -f "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem" ) {
1493 foreach my $key (keys %confighash) {
1494 my @test = &General::system_output("/usr/bin/openssl", "verify", "-CAfile", "${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem", "${General::swroot}/ovpn/certs/$confighash{$key}[1]cert.pem");
1495 if (grep(/: OK/, @test)) {
1496 $assignedcerts++;
1497 }
1498 }
1499 if ($assignedcerts) {
1500 &Header::showhttpheaders();
1501 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
1502 &Header::openbigbox('100%', 'LEFT', '', $errormessage);
1503 &Header::openbox('100%', 'LEFT', $Lang::tr{'are you sure'});
1504 print <<END;
1505 <table><form method='post'><input type='hidden' name='AREUSURE' value='yes' />
1506 <input type='hidden' name='KEY' value='$cgiparams{'KEY'}' />
1507 <tr><td align='center'>
1508 <b><font color='${Header::colourred}'>$Lang::tr{'capswarning'}</font></b>: $assignedcerts
1509 $Lang::tr{'connections are associated with this ca. deleting the ca will delete these connections as well.'}
1510 <tr><td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'remove ca certificate'}' />
1511 <input type='submit' name='ACTION' value='$Lang::tr{'cancel'}' /></td></tr>
1512 </form></table>
1513 END
1514 ;
1515 &Header::closebox();
1516 &Header::closebigbox();
1517 &Header::closepage();
1518 exit (0);
1519 } else {
1520 unlink ("${General::swroot}/ovpn/ca/$cahash{$cgiparams{'KEY'}}[0]cert.pem");
1521 delete $cahash{$cgiparams{'KEY'}};
1522 &General::writehasharray("${General::swroot}/ovpn/caconfig", \%cahash);
1523 # system('/usr/local/bin/ipsecctrl', 'R');
1524 }
1525 } else {
1526 $errormessage = $Lang::tr{'invalid key'};
1527 }
1528
1529 ###
1530 ### Display root certificate
1531 ###
1532 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'} ||
1533 $cgiparams{'ACTION'} eq $Lang::tr{'show host certificate'}) {
1534 my @output;
1535 &Header::showhttpheaders();
1536 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
1537 &Header::openbigbox('100%', 'LEFT', '', '');
1538 if ($cgiparams{'ACTION'} eq $Lang::tr{'show root certificate'}) {
1539 &Header::openbox('100%', 'LEFT', "$Lang::tr{'root certificate'}:");
1540 @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/ca/cacert.pem");
1541 } else {
1542 &Header::openbox('100%', 'LEFT', "$Lang::tr{'host certificate'}:");
1543 @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
1544 }
1545 my $output = &Header::cleanhtml(join("", @output), "y");
1546 print "<pre>$output</pre>\n";
1547 &Header::closebox();
1548 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
1549 &Header::closebigbox();
1550 &Header::closepage();
1551 exit(0);
1552
1553 ###
1554 ### Download root certificate
1555 ###
1556 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download root certificate'}) {
1557 if ( -f "${General::swroot}/ovpn/ca/cacert.pem" ) {
1558 print "Content-Type: application/octet-stream\r\n";
1559 print "Content-Disposition: filename=cacert.pem\r\n\r\n";
1560
1561 my @tmp = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/ca/cacert.pem");
1562 print @tmp;
1563
1564 exit(0);
1565 }
1566
1567 ###
1568 ### Download host certificate
1569 ###
1570 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download host certificate'}) {
1571 if ( -f "${General::swroot}/ovpn/certs/servercert.pem" ) {
1572 print "Content-Type: application/octet-stream\r\n";
1573 print "Content-Disposition: filename=servercert.pem\r\n\r\n";
1574
1575 my @tmp = &General::system_output("/usr/bin/openssl", "x509", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
1576 print @tmp;
1577
1578 exit(0);
1579 }
1580
1581 ###
1582 ### Download tls-auth key
1583 ###
1584 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download tls-auth key'}) {
1585 if ( -f "${General::swroot}/ovpn/certs/ta.key" ) {
1586 print "Content-Type: application/octet-stream\r\n";
1587 print "Content-Disposition: filename=ta.key\r\n\r\n";
1588
1589 open(FILE, "${General::swroot}/ovpn/certs/ta.key");
1590 my @tmp = <FILE>;
1591 close(FILE);
1592
1593 print @tmp;
1594
1595 exit(0);
1596 }
1597
1598 ###
1599 ### Form for generating a root certificate
1600 ###
1601 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'generate root/host certificates'} ||
1602 $cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
1603
1604 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
1605 if (-f "${General::swroot}/ovpn/ca/cacert.pem") {
1606 $errormessage = $Lang::tr{'valid root certificate already exists'};
1607 $cgiparams{'ACTION'} = '';
1608 goto ROOTCERT_ERROR;
1609 }
1610
1611 if (($cgiparams{'ROOTCERT_HOSTNAME'} eq '') && -e "${General::swroot}/red/active") {
1612 if (open(IPADDR, "${General::swroot}/red/local-ipaddress")) {
1613 my $ipaddr = <IPADDR>;
1614 close IPADDR;
1615 chomp ($ipaddr);
1616 $cgiparams{'ROOTCERT_HOSTNAME'} = (gethostbyaddr(pack("C4", split(/\./, $ipaddr)), 2))[0];
1617 if ($cgiparams{'ROOTCERT_HOSTNAME'} eq '') {
1618 $cgiparams{'ROOTCERT_HOSTNAME'} = $ipaddr;
1619 }
1620 }
1621 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'upload p12 file'}) {
1622 unless (ref ($cgiparams{'FH'})) {
1623 $errormessage = $Lang::tr{'there was no file upload'};
1624 goto ROOTCERT_ERROR;
1625 }
1626
1627 # Move uploaded certificate request to a temporary file
1628 (my $fh, my $filename) = tempfile( );
1629 if (copy ($cgiparams{'FH'}, $fh) != 1) {
1630 $errormessage = $!;
1631 goto ROOTCERT_ERROR;
1632 }
1633
1634 # Create a temporary dirctory
1635 my $tempdir = tempdir( CLEANUP => 1 );
1636
1637 # Extract the CA certificate from the file
1638 my $pid = open(OPENSSL, "|-");
1639 $SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
1640 if ($pid) { # parent
1641 if ($cgiparams{'P12_PASS'} ne '') {
1642 print OPENSSL "$cgiparams{'P12_PASS'}\n";
1643 }
1644 close (OPENSSL);
1645 if ($?) {
1646 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1647 unlink ($filename);
1648 goto ROOTCERT_ERROR;
1649 }
1650 } else { # child
1651 unless (exec ('/usr/bin/openssl', 'pkcs12', '-cacerts', '-nokeys',
1652 '-in', $filename,
1653 '-out', "$tempdir/cacert.pem")) {
1654 $errormessage = "$Lang::tr{'cant start openssl'}: $!";
1655 unlink ($filename);
1656 goto ROOTCERT_ERROR;
1657 }
1658 }
1659
1660 # Extract the Host certificate from the file
1661 $pid = open(OPENSSL, "|-");
1662 $SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
1663 if ($pid) { # parent
1664 if ($cgiparams{'P12_PASS'} ne '') {
1665 print OPENSSL "$cgiparams{'P12_PASS'}\n";
1666 }
1667 close (OPENSSL);
1668 if ($?) {
1669 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1670 unlink ($filename);
1671 goto ROOTCERT_ERROR;
1672 }
1673 } else { # child
1674 unless (exec ('/usr/bin/openssl', 'pkcs12', '-clcerts', '-nokeys',
1675 '-in', $filename,
1676 '-out', "$tempdir/hostcert.pem")) {
1677 $errormessage = "$Lang::tr{'cant start openssl'}: $!";
1678 unlink ($filename);
1679 goto ROOTCERT_ERROR;
1680 }
1681 }
1682
1683 # Extract the Host key from the file
1684 $pid = open(OPENSSL, "|-");
1685 $SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
1686 if ($pid) { # parent
1687 if ($cgiparams{'P12_PASS'} ne '') {
1688 print OPENSSL "$cgiparams{'P12_PASS'}\n";
1689 }
1690 close (OPENSSL);
1691 if ($?) {
1692 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1693 unlink ($filename);
1694 goto ROOTCERT_ERROR;
1695 }
1696 } else { # child
1697 unless (exec ('/usr/bin/openssl', 'pkcs12', '-nocerts',
1698 '-nodes',
1699 '-in', $filename,
1700 '-out', "$tempdir/serverkey.pem")) {
1701 $errormessage = "$Lang::tr{'cant start openssl'}: $!";
1702 unlink ($filename);
1703 goto ROOTCERT_ERROR;
1704 }
1705 }
1706
1707 unless(move("$tempdir/cacert.pem", "${General::swroot}/ovpn/ca/cacert.pem")) {
1708 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1709 unlink ($filename);
1710 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1711 unlink ("${General::swroot}/ovpn/certs/servercert.pem");
1712 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1713 goto ROOTCERT_ERROR;
1714 }
1715
1716 unless(move("$tempdir/hostcert.pem", "${General::swroot}/ovpn/certs/servercert.pem")) {
1717 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1718 unlink ($filename);
1719 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1720 unlink ("${General::swroot}/ovpn/certs/servercert.pem");
1721 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1722 goto ROOTCERT_ERROR;
1723 }
1724
1725 unless(move("$tempdir/serverkey.pem", "${General::swroot}/ovpn/certs/serverkey.pem")) {
1726 $errormessage = "$Lang::tr{'certificate file move failed'}: $!";
1727 unlink ($filename);
1728 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1729 unlink ("${General::swroot}/ovpn/certs/servercert.pem");
1730 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1731 goto ROOTCERT_ERROR;
1732 }
1733
1734 goto ROOTCERT_SUCCESS;
1735
1736 } elsif ($cgiparams{'ROOTCERT_COUNTRY'} ne '') {
1737
1738 # Validate input since the form was submitted
1739 if ($cgiparams{'ROOTCERT_ORGANIZATION'} eq ''){
1740 $errormessage = $Lang::tr{'organization cant be empty'};
1741 goto ROOTCERT_ERROR;
1742 }
1743 if (length($cgiparams{'ROOTCERT_ORGANIZATION'}) >60) {
1744 $errormessage = $Lang::tr{'organization too long'};
1745 goto ROOTCERT_ERROR;
1746 }
1747 if ($cgiparams{'ROOTCERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1748 $errormessage = $Lang::tr{'invalid input for organization'};
1749 goto ROOTCERT_ERROR;
1750 }
1751 if ($cgiparams{'ROOTCERT_HOSTNAME'} eq ''){
1752 $errormessage = $Lang::tr{'hostname cant be empty'};
1753 goto ROOTCERT_ERROR;
1754 }
1755 unless (&General::validfqdn($cgiparams{'ROOTCERT_HOSTNAME'}) || &General::validip($cgiparams{'ROOTCERT_HOSTNAME'})) {
1756 $errormessage = $Lang::tr{'invalid input for hostname'};
1757 goto ROOTCERT_ERROR;
1758 }
1759 if ($cgiparams{'ROOTCERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'ROOTCERT_EMAIL'}))) {
1760 $errormessage = $Lang::tr{'invalid input for e-mail address'};
1761 goto ROOTCERT_ERROR;
1762 }
1763 if (length($cgiparams{'ROOTCERT_EMAIL'}) > 40) {
1764 $errormessage = $Lang::tr{'e-mail address too long'};
1765 goto ROOTCERT_ERROR;
1766 }
1767 if ($cgiparams{'ROOTCERT_OU'} ne '' && $cgiparams{'ROOTCERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1768 $errormessage = $Lang::tr{'invalid input for department'};
1769 goto ROOTCERT_ERROR;
1770 }
1771 if ($cgiparams{'ROOTCERT_CITY'} ne '' && $cgiparams{'ROOTCERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1772 $errormessage = $Lang::tr{'invalid input for city'};
1773 goto ROOTCERT_ERROR;
1774 }
1775 if ($cgiparams{'ROOTCERT_STATE'} ne '' && $cgiparams{'ROOTCERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
1776 $errormessage = $Lang::tr{'invalid input for state or province'};
1777 goto ROOTCERT_ERROR;
1778 }
1779 if ($cgiparams{'ROOTCERT_COUNTRY'} !~ /^[A-Z]*$/) {
1780 $errormessage = $Lang::tr{'invalid input for country'};
1781 goto ROOTCERT_ERROR;
1782 }
1783
1784 # Copy the cgisettings to vpnsettings and save the configfile
1785 $vpnsettings{'ROOTCERT_ORGANIZATION'} = $cgiparams{'ROOTCERT_ORGANIZATION'};
1786 $vpnsettings{'ROOTCERT_HOSTNAME'} = $cgiparams{'ROOTCERT_HOSTNAME'};
1787 $vpnsettings{'ROOTCERT_EMAIL'} = $cgiparams{'ROOTCERT_EMAIL'};
1788 $vpnsettings{'ROOTCERT_OU'} = $cgiparams{'ROOTCERT_OU'};
1789 $vpnsettings{'ROOTCERT_CITY'} = $cgiparams{'ROOTCERT_CITY'};
1790 $vpnsettings{'ROOTCERT_STATE'} = $cgiparams{'ROOTCERT_STATE'};
1791 $vpnsettings{'ROOTCERT_COUNTRY'} = $cgiparams{'ROOTCERT_COUNTRY'};
1792 &General::writehash("${General::swroot}/ovpn/settings", \%vpnsettings);
1793
1794 # Replace empty strings with a .
1795 (my $ou = $cgiparams{'ROOTCERT_OU'}) =~ s/^\s*$/\./;
1796 (my $city = $cgiparams{'ROOTCERT_CITY'}) =~ s/^\s*$/\./;
1797 (my $state = $cgiparams{'ROOTCERT_STATE'}) =~ s/^\s*$/\./;
1798
1799 # refresh
1800 #system ('/bin/touch', "${General::swroot}/ovpn/gencanow");
1801
1802 # Create the CA certificate
1803 my $pid = open(OPENSSL, "|-");
1804 $SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
1805 if ($pid) { # parent
1806 print OPENSSL "$cgiparams{'ROOTCERT_COUNTRY'}\n";
1807 print OPENSSL "$state\n";
1808 print OPENSSL "$city\n";
1809 print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
1810 print OPENSSL "$ou\n";
1811 print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'} CA\n";
1812 print OPENSSL "$cgiparams{'ROOTCERT_EMAIL'}\n";
1813 close (OPENSSL);
1814 if ($?) {
1815 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1816 unlink ("${General::swroot}/ovpn/ca/cakey.pem");
1817 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1818 goto ROOTCERT_ERROR;
1819 }
1820 } else { # child
1821 unless (exec ('/usr/bin/openssl', 'req', '-x509', '-nodes',
1822 '-days', '999999', '-newkey', 'rsa:4096', '-sha512',
1823 '-keyout', "${General::swroot}/ovpn/ca/cakey.pem",
1824 '-out', "${General::swroot}/ovpn/ca/cacert.pem",
1825 '-config',"${General::swroot}/ovpn/openssl/ovpn.cnf")) {
1826 $errormessage = "$Lang::tr{'cant start openssl'}: $!";
1827 goto ROOTCERT_ERROR;
1828 }
1829 }
1830
1831 # Create the Host certificate request
1832 $pid = open(OPENSSL, "|-");
1833 $SIG{ALRM} = sub { $errormessage = $Lang::tr{'broken pipe'}; goto ROOTCERT_ERROR;};
1834 if ($pid) { # parent
1835 print OPENSSL "$cgiparams{'ROOTCERT_COUNTRY'}\n";
1836 print OPENSSL "$state\n";
1837 print OPENSSL "$city\n";
1838 print OPENSSL "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
1839 print OPENSSL "$ou\n";
1840 print OPENSSL "$cgiparams{'ROOTCERT_HOSTNAME'}\n";
1841 print OPENSSL "$cgiparams{'ROOTCERT_EMAIL'}\n";
1842 print OPENSSL ".\n";
1843 print OPENSSL ".\n";
1844 close (OPENSSL);
1845 if ($?) {
1846 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1847 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1848 unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
1849 goto ROOTCERT_ERROR;
1850 }
1851 } else { # child
1852 unless (exec ('/usr/bin/openssl', 'req', '-nodes',
1853 '-newkey', 'rsa:4096',
1854 '-keyout', "${General::swroot}/ovpn/certs/serverkey.pem",
1855 '-out', "${General::swroot}/ovpn/certs/serverreq.pem",
1856 '-extensions', 'server',
1857 '-config', "${General::swroot}/ovpn/openssl/ovpn.cnf" )) {
1858 $errormessage = "$Lang::tr{'cant start openssl'}: $!";
1859 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1860 unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
1861 unlink ("${General::swroot}/ovpn/ca/cakey.pem");
1862 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1863 goto ROOTCERT_ERROR;
1864 }
1865 }
1866
1867 # Sign the host certificate request
1868 # This system call is safe, because all argeuments are passed as an array.
1869 system('/usr/bin/openssl', 'ca', '-days', '999999',
1870 '-batch', '-notext',
1871 '-in', "${General::swroot}/ovpn/certs/serverreq.pem",
1872 '-out', "${General::swroot}/ovpn/certs/servercert.pem",
1873 '-extensions', 'server',
1874 '-config', "${General::swroot}/ovpn/openssl/ovpn.cnf");
1875 if ($?) {
1876 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1877 unlink ("${General::swroot}/ovpn/ca/cakey.pem");
1878 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1879 unlink ("${General::swroot}/ovpn/serverkey.pem");
1880 unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
1881 unlink ("${General::swroot}/ovpn/certs/servercert.pem");
1882 &newcleanssldatabase();
1883 goto ROOTCERT_ERROR;
1884 } else {
1885 unlink ("${General::swroot}/ovpn/certs/serverreq.pem");
1886 &deletebackupcert();
1887 }
1888
1889 # Create an empty CRL
1890 # System call is safe, because all arguments are passed as array.
1891 system('/usr/bin/openssl', 'ca', '-gencrl',
1892 '-out', "${General::swroot}/ovpn/crls/cacrl.pem",
1893 '-config', "${General::swroot}/ovpn/openssl/ovpn.cnf" );
1894 if ($?) {
1895 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1896 unlink ("${General::swroot}/ovpn/certs/serverkey.pem");
1897 unlink ("${General::swroot}/ovpn/certs/servercert.pem");
1898 unlink ("${General::swroot}/ovpn/ca/cacert.pem");
1899 unlink ("${General::swroot}/ovpn/crls/cacrl.pem");
1900 &cleanssldatabase();
1901 goto ROOTCERT_ERROR;
1902 # } else {
1903 # &cleanssldatabase();
1904 }
1905 # Create ta.key for tls-auth
1906 # This system call is safe, because all arguments are passed as an array.
1907 system('/usr/sbin/openvpn', '--genkey', 'secret', "${General::swroot}/ovpn/certs/ta.key");
1908 if ($?) {
1909 $errormessage = "$Lang::tr{'openssl produced an error'}: $?";
1910 &cleanssldatabase();
1911 goto ROOTCERT_ERROR;
1912 }
1913 goto ROOTCERT_SUCCESS;
1914 }
1915 ROOTCERT_ERROR:
1916 if ($cgiparams{'ACTION'} ne '') {
1917 &Header::showhttpheaders();
1918 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
1919 &Header::openbigbox('100%', 'LEFT', '', '');
1920 if ($errormessage) {
1921 &Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
1922 print "<class name='base'>$errormessage";
1923 print "&nbsp;</class>";
1924 &Header::closebox();
1925 }
1926 &Header::openbox('100%', 'LEFT', "$Lang::tr{'generate root/host certificates'}:");
1927 print <<END;
1928 <form method='post' enctype='multipart/form-data'>
1929 <table width='100%' border='0' cellspacing='1' cellpadding='0'>
1930 <tr><td width='30%' class='base'>$Lang::tr{'organization name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1931 <td width='35%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td>
1932 <td width='35%' colspan='2'>&nbsp;</td></tr>
1933 <tr><td class='base'>$Lang::tr{'ipfires hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1934 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td>
1935 <td colspan='2'>&nbsp;</td></tr>
1936 <tr><td class='base'>$Lang::tr{'your e-mail'}:</td>
1937 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td>
1938 <td colspan='2'>&nbsp;</td></tr>
1939 <tr><td class='base'>$Lang::tr{'your department'}:</td>
1940 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td>
1941 <td colspan='2'>&nbsp;</td></tr>
1942 <tr><td class='base'>$Lang::tr{'city'}:</td>
1943 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td>
1944 <td colspan='2'>&nbsp;</td></tr>
1945 <tr><td class='base'>$Lang::tr{'state or province'}:</td>
1946 <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td>
1947 <td colspan='2'>&nbsp;</td></tr>
1948 <tr><td class='base'>$Lang::tr{'country'}:</td>
1949 <td class='base'><select name='ROOTCERT_COUNTRY'>
1950
1951 END
1952 ;
1953 foreach my $country (sort keys %{Countries::countries}) {
1954 print "<option value='$Countries::countries{$country}'";
1955 if ( $Countries::countries{$country} eq $cgiparams{'ROOTCERT_COUNTRY'} ) {
1956 print " selected='selected'";
1957 }
1958 print ">$country</option>";
1959 }
1960 print <<END;
1961 </select></td>
1962
1963 <tr><td>&nbsp;</td>
1964 <td><input type='submit' name='ACTION' value='$Lang::tr{'generate root/host certificates'}' /></td>
1965 <td>&nbsp;</td><td>&nbsp;</td></tr>
1966 <tr><td class='base' colspan='4' align='left'>
1967 <img src='/blob.gif' valign='top' alt='*' />&nbsp;$Lang::tr{'required field'}</td></tr>
1968 <tr><td colspan='2'><br></td></tr>
1969 </table>
1970
1971 <table width='100%'>
1972 <tr><td colspan='4'><hr></td></tr>
1973 <tr><td class='base' nowrap='nowrap'>$Lang::tr{'upload p12 file'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
1974 <td nowrap='nowrap'><input type='file' name='FH' size='32'></td>
1975 <td colspan='2'>&nbsp;</td></tr>
1976 <tr><td class='base'>$Lang::tr{'pkcs12 file password'}:</td>
1977 <td class='base' nowrap='nowrap'><input type='password' name='P12_PASS' value='$cgiparams{'P12_PASS'}' size='32' /></td>
1978 <td colspan='2'>&nbsp;</td></tr>
1979 <tr><td>&nbsp;</td>
1980 <td><input type='submit' name='ACTION' value='$Lang::tr{'upload p12 file'}' /></td>
1981 <td colspan='2'>&nbsp;</td></tr>
1982 <tr><td class='base' colspan='4' align='left'>
1983 <img src='/blob.gif' valign='top' alt='*' >&nbsp;$Lang::tr{'required field'}</td>
1984 </tr>
1985 </form></table>
1986 END
1987 ;
1988 &Header::closebox();
1989 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
1990 &Header::closebigbox();
1991 &Header::closepage();
1992 exit(0)
1993 }
1994
1995 ROOTCERT_SUCCESS:
1996 &General::system("chmod", "600", "${General::swroot}/ovpn/certs/serverkey.pem");
1997 # if ($vpnsettings{'ENABLED'} eq 'on' ||
1998 # $vpnsettings{'ENABLE_BLUE'} eq 'on') {
1999 # system('/usr/local/bin/ipsecctrl', 'S');
2000 # }
2001
2002 ###
2003 ### Enable/Disable connection
2004 ###
2005
2006 ###
2007 # m.a.d net2net
2008 ###
2009
2010 }elsif ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
2011
2012 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
2013 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2014 my $n2nactive = '';
2015 my @ps = &General::system_output("/bin/ps", "ax");
2016
2017 if(grep(/$confighash{$cgiparams{'KEY'}}[1]/, @ps)) {
2018 $n2nactive = "1";
2019 }
2020
2021 if ($confighash{$cgiparams{'KEY'}}) {
2022 if ($confighash{$cgiparams{'KEY'}}[0] eq 'off') {
2023 $confighash{$cgiparams{'KEY'}}[0] = 'on';
2024 &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2025
2026 if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
2027 &General::system("/usr/local/bin/openvpnctrl", "-sn2n", "$confighash{$cgiparams{'KEY'}}[1]");
2028 &writecollectdconf();
2029 }
2030 } else {
2031
2032 $confighash{$cgiparams{'KEY'}}[0] = 'off';
2033 &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2034
2035 if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
2036 if ($n2nactive ne '') {
2037 &General::system("/usr/local/bin/openvpnctrl", "-kn2n", "$confighash{$cgiparams{'KEY'}}[1]");
2038 &writecollectdconf();
2039 }
2040 }
2041 }
2042 }
2043
2044 ###
2045 ### Download OpenVPN client package
2046 ###
2047
2048
2049 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'dl client arch'}) {
2050 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
2051 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2052 my $file = '';
2053 my $clientovpn = '';
2054 my @fileholder;
2055 my $tempdir = tempdir( CLEANUP => 1 );
2056 my $zippath = "$tempdir/";
2057
2058 ###
2059 # m.a.d net2net
2060 ###
2061
2062 if ($confighash{$cgiparams{'KEY'}}[3] eq 'net'){
2063
2064 my $zipname = "$confighash{$cgiparams{'KEY'}}[1]-Client.zip";
2065 my $zippathname = "$zippath$zipname";
2066 $clientovpn = "$confighash{$cgiparams{'KEY'}}[1].conf";
2067 my @ovsubnettemp = split(/\./,$confighash{$cgiparams{'KEY'}}[27]);
2068 my $ovsubnet = "$ovsubnettemp[0].$ovsubnettemp[1].$ovsubnettemp[2]";
2069 my $tunmtu = '';
2070 my @remsubnet = split(/\//,$confighash{$cgiparams{'KEY'}}[8]);
2071 my $n2nfragment = '';
2072
2073 open(CLIENTCONF, ">$tempdir/$clientovpn") or die "Unable to open tempfile: $!";
2074 flock CLIENTCONF, 2;
2075
2076 my $zip = Archive::Zip->new();
2077 print CLIENTCONF "# IPFire n2n Open VPN Client Config by ummeegge und m.a.d\n";
2078 print CLIENTCONF "# \n";
2079 print CLIENTCONF "# User Security\n";
2080 print CLIENTCONF "user nobody\n";
2081 print CLIENTCONF "group nobody\n";
2082 print CLIENTCONF "persist-tun\n";
2083 print CLIENTCONF "persist-key\n";
2084 print CLIENTCONF "script-security 2\n";
2085 print CLIENTCONF "# IP/DNS for remote Server Gateway\n";
2086 print CLIENTCONF "remote $vpnsettings{'VPN_IP'}\n";
2087 print CLIENTCONF "float\n";
2088 print CLIENTCONF "# IP adresses of the VPN Subnet\n";
2089 print CLIENTCONF "ifconfig $ovsubnet.2 $ovsubnet.1\n";
2090 print CLIENTCONF "# Server Gateway Network\n";
2091 print CLIENTCONF "route $remsubnet[0] $remsubnet[1]\n";
2092 print CLIENTCONF "# tun Device\n";
2093 print CLIENTCONF "dev tun\n";
2094 print CLIENTCONF "#Logfile for statistics\n";
2095 print CLIENTCONF "status-version 1\n";
2096 print CLIENTCONF "status /var/run/openvpn/$cgiparams{'NAME'}-n2n 10\n";
2097 print CLIENTCONF "# Port and Protokoll\n";
2098 print CLIENTCONF "port $confighash{$cgiparams{'KEY'}}[29]\n";
2099
2100 if ($confighash{$cgiparams{'KEY'}}[28] eq 'tcp') {
2101 print CLIENTCONF "proto tcp4-client\n";
2102 print CLIENTCONF "# Packet size\n";
2103 if ($confighash{$cgiparams{'KEY'}}[31] eq '') {$tunmtu = '1400'} else {$tunmtu = $confighash{$cgiparams{'KEY'}}[31]};
2104 print CLIENTCONF "tun-mtu $tunmtu\n";
2105 }
2106
2107 if ($confighash{$cgiparams{'KEY'}}[28] eq 'udp') {
2108 print CLIENTCONF "proto udp4\n";
2109 print CLIENTCONF "# Paketsize\n";
2110 if ($confighash{$cgiparams{'KEY'}}[31] eq '') {$tunmtu = '1500'} else {$tunmtu = $confighash{$cgiparams{'KEY'}}[31]};
2111 print CLIENTCONF "tun-mtu $tunmtu\n";
2112 if ($confighash{$cgiparams{'KEY'}}[24] ne '') {print CLIENTCONF "fragment $confighash{$cgiparams{'KEY'}}[24]\n";}
2113 if ($confighash{$cgiparams{'KEY'}}[23] eq 'on') {print CLIENTCONF "mssfix\n";} else { print CLIENTCONF "mssfix 0\n"; }
2114 }
2115 # Check host certificate if X509 is RFC3280 compliant.
2116 # If not, old --ns-cert-type directive will be used.
2117 # If appropriate key usage extension exists, new --remote-cert-tls directive will be used.
2118 my @hostcert = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
2119 if (! grep(/TLS Web Server Authentication/, @hostcert)) {
2120 print CLIENTCONF "ns-cert-type server\n";
2121 } else {
2122 print CLIENTCONF "remote-cert-tls server\n";
2123 }
2124 print CLIENTCONF "# Auth. Client\n";
2125 print CLIENTCONF "tls-client\n";
2126 print CLIENTCONF "# Cipher\n";
2127 print CLIENTCONF "cipher $confighash{$cgiparams{'KEY'}}[40]\n";
2128 if ($confighash{$cgiparams{'KEY'}}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12") {
2129 print CLIENTCONF "pkcs12 ${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12\r\n";
2130 $zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12", "$confighash{$cgiparams{'KEY'}}[1].p12") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1].p12\n";
2131 }
2132
2133 # If GCM cipher is used, do not use --auth
2134 if (($confighash{$cgiparams{'KEY'}}[40] eq 'AES-256-GCM') ||
2135 ($confighash{$cgiparams{'KEY'}}[40] eq 'AES-192-GCM') ||
2136 ($confighash{$cgiparams{'KEY'}}[40] eq 'AES-128-GCM')) {
2137 print CLIENTCONF unless "# HMAC algorithm\n";
2138 print CLIENTCONF unless "auth $confighash{$cgiparams{'KEY'}}[39]\n";
2139 } else {
2140 print CLIENTCONF "# HMAC algorithm\n";
2141 print CLIENTCONF "auth $confighash{$cgiparams{'KEY'}}[39]\n";
2142 }
2143
2144 if ($confighash{$cgiparams{'KEY'}}[30] eq 'on') {
2145 print CLIENTCONF "# Enable Compression\n";
2146 print CLIENTCONF "comp-lzo\n";
2147 }
2148 print CLIENTCONF "# Debug Level\n";
2149 print CLIENTCONF "verb 3\n";
2150 print CLIENTCONF "# Tunnel check\n";
2151 print CLIENTCONF "keepalive 10 60\n";
2152 print CLIENTCONF "# Start as daemon\n";
2153 print CLIENTCONF "daemon $confighash{$cgiparams{'KEY'}}[1]n2n\n";
2154 print CLIENTCONF "writepid /var/run/$confighash{$cgiparams{'KEY'}}[1]n2n.pid\n";
2155 print CLIENTCONF "# Activate Management Interface and Port\n";
2156 if ($confighash{$cgiparams{'KEY'}}[22] eq '') {print CLIENTCONF "management localhost $confighash{$cgiparams{'KEY'}}[29]\n"}
2157 else {print CLIENTCONF "management localhost $confighash{$cgiparams{'KEY'}}[22]\n"};
2158 print CLIENTCONF "# remsub $confighash{$cgiparams{'KEY'}}[11]\n";
2159
2160
2161 close(CLIENTCONF);
2162
2163 $zip->addFile( "$tempdir/$clientovpn", $clientovpn) or die "Can't add file $clientovpn\n";
2164 my $status = $zip->writeToFileNamed($zippathname);
2165
2166 open(DLFILE, "<$zippathname") or die "Unable to open $zippathname: $!";
2167 @fileholder = <DLFILE>;
2168 print "Content-Type:application/x-download\n";
2169 print "Content-Disposition:attachment;filename=$zipname\n\n";
2170 print @fileholder;
2171 exit (0);
2172 }
2173 else
2174 {
2175 my $zipname = "$confighash{$cgiparams{'KEY'}}[1]-TO-IPFire.zip";
2176 my $zippathname = "$zippath$zipname";
2177 $clientovpn = "$confighash{$cgiparams{'KEY'}}[1]-TO-IPFire.ovpn";
2178
2179 ###
2180 # m.a.d net2net
2181 ###
2182
2183 open(CLIENTCONF, ">$tempdir/$clientovpn") or die "Unable to open tempfile: $!";
2184 flock CLIENTCONF, 2;
2185
2186 my $zip = Archive::Zip->new();
2187
2188 print CLIENTCONF "#OpenVPN Client conf\r\n";
2189 print CLIENTCONF "tls-client\r\n";
2190 print CLIENTCONF "client\r\n";
2191 print CLIENTCONF "nobind\r\n";
2192 print CLIENTCONF "dev tun\r\n";
2193 print CLIENTCONF "proto $vpnsettings{'DPROTOCOL'}\r\n";
2194 print CLIENTCONF "tun-mtu $vpnsettings{'DMTU'}\r\n";
2195
2196 if ( $vpnsettings{'ENABLED'} eq 'on'){
2197 print CLIENTCONF "remote $vpnsettings{'VPN_IP'} $vpnsettings{'DDEST_PORT'}\r\n";
2198 if ( $vpnsettings{'ENABLED_BLUE'} eq 'on' && (&haveBlueNet())){
2199 print CLIENTCONF "#comment the above line and uncomment the next line, if you want to connect on the Blue interface\r\n";
2200 print CLIENTCONF ";remote $netsettings{'BLUE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
2201 }
2202 if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
2203 print CLIENTCONF "#comment the above line and uncomment the next line, if you want to connect on the Orange interface\r\n";
2204 print CLIENTCONF ";remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
2205 }
2206 } elsif ( $vpnsettings{'ENABLED_BLUE'} eq 'on' && (&haveBlueNet())){
2207 print CLIENTCONF "remote $netsettings{'BLUE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
2208 if ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
2209 print CLIENTCONF "#comment the above line and uncomment the next line, if you want to connect on the Orange interface\r\n";
2210 print CLIENTCONF ";remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
2211 }
2212 } elsif ( $vpnsettings{'ENABLED_ORANGE'} eq 'on' && (&haveOrangeNet())){
2213 print CLIENTCONF "remote $netsettings{'ORANGE_ADDRESS'} $vpnsettings{'DDEST_PORT'}\r\n";
2214 }
2215
2216 my $file_crt = new File::Temp( UNLINK => 1 );
2217 my $file_key = new File::Temp( UNLINK => 1 );
2218 my $include_certs = 0;
2219
2220 if ($confighash{$cgiparams{'KEY'}}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12") {
2221 if ($cgiparams{'MODE'} eq 'insecure') {
2222 $include_certs = 1;
2223
2224 # Add the CA
2225 print CLIENTCONF ";ca cacert.pem\r\n";
2226 $zip->addFile("${General::swroot}/ovpn/ca/cacert.pem", "cacert.pem") or die "Can't add file cacert.pem\n";
2227
2228 # Extract the certificate
2229 # This system call is safe, because all arguments are passed as an array.
2230 system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
2231 '-clcerts', '-nokeys', '-nodes', '-out', "$file_crt" , '-passin', 'pass:');
2232 if ($?) {
2233 die "openssl error: $?";
2234 }
2235
2236 $zip->addFile("$file_crt", "$confighash{$cgiparams{'KEY'}}[1].pem") or die;
2237 print CLIENTCONF ";cert $confighash{$cgiparams{'KEY'}}[1].pem\r\n";
2238
2239 # Extract the key
2240 # This system call is safe, because all arguments are passed as an array.
2241 system('/usr/bin/openssl', 'pkcs12', '-in', "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12",
2242 '-nocerts', '-nodes', '-out', "$file_key", '-passin', 'pass:');
2243 if ($?) {
2244 die "openssl error: $?";
2245 }
2246
2247 $zip->addFile("$file_key", "$confighash{$cgiparams{'KEY'}}[1].key") or die;
2248 print CLIENTCONF ";key $confighash{$cgiparams{'KEY'}}[1].key\r\n";
2249 } else {
2250 print CLIENTCONF "pkcs12 $confighash{$cgiparams{'KEY'}}[1].p12\r\n";
2251 $zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12", "$confighash{$cgiparams{'KEY'}}[1].p12") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1].p12\n";
2252 }
2253 } else {
2254 print CLIENTCONF "ca cacert.pem\r\n";
2255 print CLIENTCONF "cert $confighash{$cgiparams{'KEY'}}[1]cert.pem\r\n";
2256 print CLIENTCONF "key $confighash{$cgiparams{'KEY'}}[1].key\r\n";
2257 $zip->addFile( "${General::swroot}/ovpn/ca/cacert.pem", "cacert.pem") or die "Can't add file cacert.pem\n";
2258 $zip->addFile( "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem", "$confighash{$cgiparams{'KEY'}}[1]cert.pem") or die "Can't add file $confighash{$cgiparams{'KEY'}}[1]cert.pem\n";
2259 }
2260 print CLIENTCONF "cipher $vpnsettings{DCIPHER}\r\n";
2261 print CLIENTCONF "auth $vpnsettings{'DAUTH'}\r\n";
2262
2263 if ($vpnsettings{'TLSAUTH'} eq 'on') {
2264 if ($cgiparams{'MODE'} eq 'insecure') {
2265 print CLIENTCONF ";";
2266 }
2267 print CLIENTCONF "tls-auth ta.key\r\n";
2268 $zip->addFile( "${General::swroot}/ovpn/certs/ta.key", "ta.key") or die "Can't add file ta.key\n";
2269 }
2270 if ($vpnsettings{DCOMPLZO} eq 'on') {
2271 print CLIENTCONF "comp-lzo\r\n";
2272 }
2273 print CLIENTCONF "verb 3\r\n";
2274 # Check host certificate if X509 is RFC3280 compliant.
2275 # If not, old --ns-cert-type directive will be used.
2276 # If appropriate key usage extension exists, new --remote-cert-tls directive will be used.
2277 my @hostcert = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/servercert.pem");
2278 if (! grep(/TLS Web Server Authentication/, @hostcert)) {
2279 print CLIENTCONF "ns-cert-type server\r\n";
2280 } else {
2281 print CLIENTCONF "remote-cert-tls server\r\n";
2282 }
2283 print CLIENTCONF "verify-x509-name $vpnsettings{ROOTCERT_HOSTNAME} name\r\n";
2284 if ($vpnsettings{MSSFIX} eq 'on') {
2285 print CLIENTCONF "mssfix\r\n";
2286 } else {
2287 print CLIENTCONF "mssfix 0\r\n";
2288 }
2289 if ($vpnsettings{FRAGMENT} ne '' && $vpnsettings{DPROTOCOL} ne 'tcp' ) {
2290 print CLIENTCONF "fragment $vpnsettings{'FRAGMENT'}\r\n";
2291 }
2292
2293 # Disable storing any credentials in memory
2294 print CLIENTCONF "auth-nocache\r\n";
2295
2296 # Set a fake user name for authentication
2297 print CLIENTCONF "auth-token-user USER\r\n";
2298 print CLIENTCONF "auth-token TOTP\r\n";
2299
2300 # If the server is asking for TOTP this needs to happen interactively
2301 print CLIENTCONF "auth-retry interact\r\n";
2302
2303 if ($include_certs) {
2304 print CLIENTCONF "\r\n";
2305
2306 # CA
2307 open(FILE, "<${General::swroot}/ovpn/ca/cacert.pem");
2308 print CLIENTCONF "<ca>\r\n";
2309 while (<FILE>) {
2310 chomp($_);
2311 print CLIENTCONF "$_\r\n";
2312 }
2313 print CLIENTCONF "</ca>\r\n\r\n";
2314 close(FILE);
2315
2316 # Cert
2317 open(FILE, "<$file_crt");
2318 print CLIENTCONF "<cert>\r\n";
2319 while (<FILE>) {
2320 chomp($_);
2321 print CLIENTCONF "$_\r\n";
2322 }
2323 print CLIENTCONF "</cert>\r\n\r\n";
2324 close(FILE);
2325
2326 # Key
2327 open(FILE, "<$file_key");
2328 print CLIENTCONF "<key>\r\n";
2329 while (<FILE>) {
2330 chomp($_);
2331 print CLIENTCONF "$_\r\n";
2332 }
2333 print CLIENTCONF "</key>\r\n\r\n";
2334 close(FILE);
2335
2336 # TLS auth
2337 if ($vpnsettings{'TLSAUTH'} eq 'on') {
2338 open(FILE, "<${General::swroot}/ovpn/certs/ta.key");
2339 print CLIENTCONF "<tls-auth>\r\n";
2340 while (<FILE>) {
2341 chomp($_);
2342 print CLIENTCONF "$_\r\n";
2343 }
2344 print CLIENTCONF "</tls-auth>\r\n\r\n";
2345 close(FILE);
2346 }
2347 }
2348
2349 # Print client.conf.local if entries exist to client.ovpn
2350 if (!-z $local_clientconf && $vpnsettings{'ADDITIONAL_CONFIGS'} eq 'on') {
2351 open (LCC, "$local_clientconf");
2352 print CLIENTCONF "\n#---------------------------\n";
2353 print CLIENTCONF "# Start of custom directives\n";
2354 print CLIENTCONF "# from client.conf.local\n";
2355 print CLIENTCONF "#---------------------------\n\n";
2356 while (<LCC>) {
2357 print CLIENTCONF $_;
2358 }
2359 print CLIENTCONF "\n#---------------------------\n";
2360 print CLIENTCONF "# End of custom directives\n";
2361 print CLIENTCONF "#---------------------------\n\n";
2362 close (LCC);
2363 }
2364 close(CLIENTCONF);
2365
2366 $zip->addFile( "$tempdir/$clientovpn", $clientovpn) or die "Can't add file $clientovpn\n";
2367 my $status = $zip->writeToFileNamed($zippathname);
2368
2369 open(DLFILE, "<$zippathname") or die "Unable to open $zippathname: $!";
2370 @fileholder = <DLFILE>;
2371 print "Content-Type:application/x-download\n";
2372 print "Content-Disposition:attachment;filename=$zipname\n\n";
2373 print @fileholder;
2374 exit (0);
2375 }
2376
2377
2378
2379 ###
2380 ### Remove connection
2381 ###
2382
2383
2384 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'remove'}) {
2385 &General::readhash("${General::swroot}/ovpn/settings", \%vpnsettings);
2386 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2387
2388 if ($confighash{$cgiparams{'KEY'}}) {
2389 # Revoke certificate if certificate was deleted and rewrite the CRL
2390 &General::system("/usr/bin/openssl", "ca", "-revoke", "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem", "-config", "${General::swroot}/ovpn/openssl/ovpn.cnf");
2391 &General::system("/usr/bin/openssl", "ca", "-gencrl", "-out", "${General::swroot}/ovpn/crls/cacrl.pem", "-config", "${General::swroot}/ovpn/openssl/ovpn.cnf");
2392
2393 ###
2394 # m.a.d net2net
2395 ###
2396
2397 if ($confighash{$cgiparams{'KEY'}}[3] eq 'net') {
2398 # Stop the N2N connection before it is removed
2399 &General::system("/usr/local/bin/openvpnctrl", "-kn2n", "$confighash{$cgiparams{'KEY'}}[1]");
2400
2401 my $conffile = glob("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]/$confighash{$cgiparams{'KEY'}}[1].conf");
2402 my $certfile = glob("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
2403 unlink ($certfile);
2404 unlink ($conffile);
2405
2406 if (-e "${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]") {
2407 rmdir ("${General::swroot}/ovpn/n2nconf/$confighash{$cgiparams{'KEY'}}[1]") || die "Kann Verzeichnis nicht loeschen: $!";
2408 }
2409 }
2410
2411 unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
2412 unlink ("${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
2413
2414 # A.Marx CCD delete ccd files and routes
2415
2416 if (-f "${General::swroot}/ovpn/ccd/$confighash{$cgiparams{'KEY'}}[2]")
2417 {
2418 unlink "${General::swroot}/ovpn/ccd/$confighash{$cgiparams{'KEY'}}[2]";
2419 }
2420
2421 &General::readhasharray("${General::swroot}/ovpn/ccdroute", \%ccdroutehash);
2422 foreach my $key (keys %ccdroutehash) {
2423 if ($ccdroutehash{$key}[0] eq $confighash{$cgiparams{'KEY'}}[1]){
2424 delete $ccdroutehash{$key};
2425 }
2426 }
2427 &General::writehasharray("${General::swroot}/ovpn/ccdroute", \%ccdroutehash);
2428
2429 &General::readhasharray("${General::swroot}/ovpn/ccdroute2", \%ccdroute2hash);
2430 foreach my $key (keys %ccdroute2hash) {
2431 if ($ccdroute2hash{$key}[0] eq $confighash{$cgiparams{'KEY'}}[1]){
2432 delete $ccdroute2hash{$key};
2433 }
2434 }
2435 &General::writehasharray("${General::swroot}/ovpn/ccdroute2", \%ccdroute2hash);
2436 &writeserverconf;
2437
2438 # CCD end
2439 # Update collectd configuration and delete all RRD files of the removed connection
2440 &writecollectdconf();
2441 &General::system("/usr/local/bin/openvpnctrl", "-drrd", "$confighash{$cgiparams{'KEY'}}[1]");
2442
2443 delete $confighash{$cgiparams{'KEY'}};
2444 &General::system("/usr/bin/openssl", "ca", "-gencrl", "-out", "${General::swroot}/ovpn/crls/cacrl.pem", "-config", "${General::swroot}/ovpn/openssl/ovpn.cnf");
2445 &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2446
2447 } else {
2448 $errormessage = $Lang::tr{'invalid key'};
2449 }
2450 &General::firewall_reload();
2451
2452 ###
2453 ### Download PKCS12 file
2454 ###
2455 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'download pkcs12 file'}) {
2456 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2457
2458 print "Content-Disposition: filename=" . $confighash{$cgiparams{'KEY'}}[1] . ".p12\r\n";
2459 print "Content-Type: application/octet-stream\r\n\r\n";
2460
2461 open(FILE, "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1].p12");
2462 my @tmp = <FILE>;
2463 close(FILE);
2464
2465 print @tmp;
2466 exit (0);
2467
2468 ###
2469 ### Display certificate
2470 ###
2471 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show certificate'}) {
2472 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2473
2474 if ( -f "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem") {
2475 &Header::showhttpheaders();
2476 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
2477 &Header::openbigbox('100%', 'LEFT', '', '');
2478 &Header::openbox('100%', 'LEFT', "$Lang::tr{'certificate'}:");
2479 my @output = &General::system_output("/usr/bin/openssl", "x509", "-text", "-in", "${General::swroot}/ovpn/certs/$confighash{$cgiparams{'KEY'}}[1]cert.pem");
2480 my $output = &Header::cleanhtml(join("", @output), "y");
2481 print "<pre>$output</pre>\n";
2482 &Header::closebox();
2483 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2484 &Header::closebigbox();
2485 &Header::closepage();
2486 exit(0);
2487 }
2488
2489 ###
2490 ### Display OTP QRCode
2491 ###
2492 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show otp qrcode'}) {
2493 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2494
2495 my $qrcode = Imager::QRCode->new(
2496 size => 6,
2497 margin => 0,
2498 version => 0,
2499 level => 'M',
2500 mode => '8-bit',
2501 casesensitive => 1,
2502 lightcolor => Imager::Color->new(255, 255, 255),
2503 darkcolor => Imager::Color->new(0, 0, 0),
2504 );
2505 my $cn = uri_encode($confighash{$cgiparams{'KEY'}}[2]);
2506 my $secret = encode_base32(pack('H*', $confighash{$cgiparams{'KEY'}}[44]));
2507 my $issuer = uri_encode("$mainsettings{'HOSTNAME'}.$mainsettings{'DOMAINNAME'}");
2508 my $qrcodeimg = $qrcode->plot("otpauth://totp/$cn?secret=$secret&issuer=$issuer");
2509 my $qrcodeimgdata;
2510 $qrcodeimg->write(data => \$qrcodeimgdata, type=> 'png')
2511 or die $qrcodeimg->errstr;
2512 $qrcodeimgdata = encode_base64($qrcodeimgdata, '');
2513
2514 &Header::showhttpheaders();
2515 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
2516 &Header::openbigbox('100%', 'LEFT', '', '');
2517 &Header::openbox('100%', 'LEFT', "$Lang::tr{'otp qrcode'}:");
2518 print <<END;
2519 $Lang::tr{'secret'}:&nbsp;$secret</br></br>
2520 <img alt="$Lang::tr{'otp qrcode'}" src="data:image/png;base64,$qrcodeimgdata">
2521 END
2522 &Header::closebox();
2523 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2524 &Header::closebigbox();
2525 &Header::closepage();
2526 exit(0);
2527
2528 ###
2529 ### Display Diffie-Hellman key
2530 ###
2531 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show dh'}) {
2532
2533 if (! -e "$dhparameter") {
2534 $errormessage = $Lang::tr{'not present'};
2535 } else {
2536 &Header::showhttpheaders();
2537 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
2538 &Header::openbigbox('100%', 'LEFT', '', '');
2539 &Header::openbox('100%', 'LEFT', "$Lang::tr{'dh'}:");
2540 my @output = &General::system_output("/usr/bin/openssl", "dhparam", "-text", "-in", "$dhparameter");
2541 my $output = &Header::cleanhtml(join("", @output) ,"y");
2542 print "<pre>$output</pre>\n";
2543 &Header::closebox();
2544 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2545 &Header::closebigbox();
2546 &Header::closepage();
2547 exit(0);
2548 }
2549
2550 ###
2551 ### Display tls-auth key
2552 ###
2553 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show tls-auth key'}) {
2554
2555 if (! -e "${General::swroot}/ovpn/certs/ta.key") {
2556 $errormessage = $Lang::tr{'not present'};
2557 } else {
2558 &Header::showhttpheaders();
2559 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
2560 &Header::openbigbox('100%', 'LEFT', '', '');
2561 &Header::openbox('100%', 'LEFT', "$Lang::tr{'ta key'}:");
2562
2563 open(FILE, "${General::swroot}/ovpn/certs/ta.key");
2564 my @output = <FILE>;
2565 close(FILE);
2566
2567 my $output = &Header::cleanhtml(join("", @output),"y");
2568 print "<pre>$output</pre>\n";
2569 &Header::closebox();
2570 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2571 &Header::closebigbox();
2572 &Header::closepage();
2573 exit(0);
2574 }
2575
2576 ###
2577 ### Display Certificate Revoke List
2578 ###
2579 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show crl'}) {
2580 # &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
2581
2582 if (! -e "${General::swroot}/ovpn/crls/cacrl.pem") {
2583 $errormessage = $Lang::tr{'not present'};
2584 } else {
2585 &Header::showhttpheaders();
2586 &Header::openpage($Lang::tr{'ovpn'}, 1, '');
2587 &Header::openbigbox('100%', 'LEFT', '', '');
2588 &Header::openbox('100%', 'LEFT', "$Lang::tr{'crl'}:");
2589 my @output = &General::system_output("/usr/bin/openssl", "crl", "-text", "-noout", "-in", "${General::swroot}/ovpn/crls/cacrl.pem");
2590 my $output = &Header::cleanhtml(join("", @output), "y");
2591 print "<pre>$output</pre>\n";
2592 &Header::closebox();
2593 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2594 &Header::closebigbox();
2595 &Header::closepage();
2596 exit(0);
2597 }
2598
2599 ###
2600 ### Advanced Server Settings
2601 ###
2602
2603 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'advanced server'}) {
2604 %cgiparams = ();
2605 %cahash = ();
2606 %confighash = ();
2607 my $disabled;
2608 &General::readhash("${General::swroot}/ovpn/settings", \%cgiparams);
2609 read_routepushfile;
2610
2611
2612 # if ($cgiparams{'CLIENT2CLIENT'} eq '') {
2613 # $cgiparams{'CLIENT2CLIENT'} = 'on';
2614 # }
2615 ADV_ERROR:
2616 if ($cgiparams{'MAX_CLIENTS'} eq '') {
2617 $cgiparams{'MAX_CLIENTS'} = '100';
2618 }
2619 if ($cgiparams{'KEEPALIVE_1'} eq '') {
2620 $cgiparams{'KEEPALIVE_1'} = '10';
2621 }
2622 if ($cgiparams{'KEEPALIVE_2'} eq '') {
2623 $cgiparams{'KEEPALIVE_2'} = '60';
2624 }
2625 if ($cgiparams{'LOG_VERB'} eq '') {
2626 $cgiparams{'LOG_VERB'} = '3';
2627 }
2628 if ($cgiparams{'TLSAUTH'} eq '') {
2629 $cgiparams{'TLSAUTH'} = 'off';
2630 }
2631 $checked{'CLIENT2CLIENT'}{'off'} = '';
2632 $checked{'CLIENT2CLIENT'}{'on'} = '';
2633 $checked{'CLIENT2CLIENT'}{$cgiparams{'CLIENT2CLIENT'}} = 'CHECKED';
2634 $checked{'REDIRECT_GW_DEF1'}{'off'} = '';
2635 $checked{'REDIRECT_GW_DEF1'}{'on'} = '';
2636 $checked{'REDIRECT_GW_DEF1'}{$cgiparams{'REDIRECT_GW_DEF1'}} = 'CHECKED';
2637 $checked{'DCOMPLZO'}{'off'} = '';
2638 $checked{'DCOMPLZO'}{'on'} = '';
2639 $checked{'DCOMPLZO'}{$cgiparams{'DCOMPLZO'}} = 'CHECKED';
2640 $checked{'ADDITIONAL_CONFIGS'}{'off'} = '';
2641 $checked{'ADDITIONAL_CONFIGS'}{'on'} = '';
2642 $checked{'ADDITIONAL_CONFIGS'}{$cgiparams{'ADDITIONAL_CONFIGS'}} = 'CHECKED';
2643 $checked{'MSSFIX'}{'off'} = '';
2644 $checked{'MSSFIX'}{'on'} = '';
2645 $checked{'MSSFIX'}{$cgiparams{'MSSFIX'}} = 'CHECKED';
2646 $selected{'LOG_VERB'}{'0'} = '';
2647 $selected{'LOG_VERB'}{'1'} = '';
2648 $selected{'LOG_VERB'}{'2'} = '';
2649 $selected{'LOG_VERB'}{'3'} = '';
2650 $selected{'LOG_VERB'}{'4'} = '';
2651 $selected{'LOG_VERB'}{'5'} = '';
2652 $selected{'LOG_VERB'}{'6'} = '';
2653 $selected{'LOG_VERB'}{'7'} = '';
2654 $selected{'LOG_VERB'}{'8'} = '';
2655 $selected{'LOG_VERB'}{'9'} = '';
2656 $selected{'LOG_VERB'}{'10'} = '';
2657 $selected{'LOG_VERB'}{'11'} = '';
2658 $selected{'LOG_VERB'}{$cgiparams{'LOG_VERB'}} = 'SELECTED';
2659
2660 &Header::showhttpheaders();
2661 &Header::openpage($Lang::tr{'status ovpn'}, 1, '');
2662 &Header::openbigbox('100%', 'LEFT', '', $errormessage);
2663 if ($errormessage) {
2664 &Header::openbox('100%', 'LEFT', $Lang::tr{'error messages'});
2665 print "<class name='base'>$errormessage\n";
2666 print "&nbsp;</class>\n";
2667 &Header::closebox();
2668 }
2669 &Header::openbox('100%', 'LEFT', $Lang::tr{'advanced server'});
2670 print <<END;
2671 <form method='post' enctype='multipart/form-data'>
2672 <table width='100%' border=0>
2673 <tr>
2674 <td colspan='4'><b>$Lang::tr{'dhcp-options'}</b></td>
2675 </tr>
2676 <tr>
2677 <td width='25%'></td> <td width='20%'> </td><td width='25%'> </td><td width='30%'></td>
2678 </tr>
2679 <tr>
2680 <td class='base'>Domain</td>
2681 <td><input type='TEXT' name='DHCP_DOMAIN' value='$cgiparams{'DHCP_DOMAIN'}' size='30' /></td>
2682 </tr>
2683 <tr>
2684 <td class='base'>DNS</td>
2685 <td><input type='TEXT' name='DHCP_DNS' value='$cgiparams{'DHCP_DNS'}' size='30' /></td>
2686 </tr>
2687 <tr>
2688 <td class='base'>WINS</td>
2689 <td><input type='TEXT' name='DHCP_WINS' value='$cgiparams{'DHCP_WINS'}' size='30' /></td>
2690 </tr>
2691 <tr>
2692 <td colspan='4'><b>$Lang::tr{'ovpn routes push options'}</b></td>
2693 </tr>
2694 <tr>
2695 <td class='base'>$Lang::tr{'ovpn routes push'}</td>
2696 <td colspan='2'>
2697 <textarea name='ROUTES_PUSH' cols='26' rows='6' wrap='off'>
2698 END
2699 ;
2700
2701 if ($cgiparams{'ROUTES_PUSH'} ne '')
2702 {
2703 print $cgiparams{'ROUTES_PUSH'};
2704 }
2705
2706 print <<END;
2707 </textarea></td>
2708 </tr>
2709 </tr>
2710 </table>
2711 <hr size='1'>
2712 <table width='100%'>
2713 <tr>
2714 <td class='base'><b>$Lang::tr{'misc-options'}</b></td>
2715 </tr>
2716
2717 <tr>
2718 <td width='20%'></td> <td width='15%'> </td><td width='35%'> </td><td width='20%'></td><td width='35%'></td>
2719 </tr>
2720
2721 <tr>
2722 <td class='base'>Client-To-Client</td>
2723 <td><input type='checkbox' name='CLIENT2CLIENT' $checked{'CLIENT2CLIENT'}{'on'} /></td>
2724 </tr>
2725
2726 <tr>
2727 <td class='base'>Redirect-Gateway def1</td>
2728 <td><input type='checkbox' name='REDIRECT_GW_DEF1' $checked{'REDIRECT_GW_DEF1'}{'on'} /></td>
2729 </tr>
2730
2731 <tr><td class='boldbase' nowrap='nowrap'>$Lang::tr{'comp-lzo'}</td>
2732 <td><input type='checkbox' name='DCOMPLZO' $checked{'DCOMPLZO'}{'on'} /></td>
2733 <td>$Lang::tr{'openvpn default'}: off <font color='red'>($Lang::tr{'attention'} exploitable via Voracle)</font></td>
2734 </tr>
2735
2736 <tr>
2737 <td class='base'>$Lang::tr{'ovpn add conf'}</td>
2738 <td><input type='checkbox' name='ADDITIONAL_CONFIGS' $checked{'ADDITIONAL_CONFIGS'}{'on'} /></td>
2739 <td>$Lang::tr{'openvpn default'}: off</td>
2740 </tr>
2741
2742 <tr>
2743 <td class='base'>mssfix</td>
2744 <td><input type='checkbox' name='MSSFIX' $checked{'MSSFIX'}{'on'} /></td>
2745 <td>$Lang::tr{'openvpn default'}: off</td>
2746 </tr>
2747
2748 <tr>
2749 <td class='base'>fragment <br></td>
2750 <td><input type='TEXT' name='FRAGMENT' value='$cgiparams{'FRAGMENT'}' size='10' /></td>
2751 </tr>
2752
2753
2754 <tr>
2755 <td class='base'>Max-Clients</td>
2756 <td><input type='text' name='MAX_CLIENTS' value='$cgiparams{'MAX_CLIENTS'}' size='10' /></td>
2757 </tr>
2758 <tr>
2759 <td class='base'>Keepalive <br />
2760 (ping/ping-restart)</td>
2761 <td><input type='TEXT' name='KEEPALIVE_1' value='$cgiparams{'KEEPALIVE_1'}' size='10' /></td>
2762 <td><input type='TEXT' name='KEEPALIVE_2' value='$cgiparams{'KEEPALIVE_2'}' size='10' /></td>
2763 </tr>
2764 </table>
2765
2766 <hr size='1'>
2767 <table width='100%'>
2768 <tr>
2769 <td class='base'><b>$Lang::tr{'log-options'}</b></td>
2770 </tr>
2771 <tr>
2772 <td width='20%'></td> <td width='30%'> </td><td width='25%'> </td><td width='25%'></td>
2773 </tr>
2774
2775 <tr><td class='base'>VERB</td>
2776 <td><select name='LOG_VERB'>
2777 <option value='0' $selected{'LOG_VERB'}{'0'}>0</option>
2778 <option value='1' $selected{'LOG_VERB'}{'1'}>1</option>
2779 <option value='2' $selected{'LOG_VERB'}{'2'}>2</option>
2780 <option value='3' $selected{'LOG_VERB'}{'3'}>3</option>
2781 <option value='4' $selected{'LOG_VERB'}{'4'}>4</option>
2782 <option value='5' $selected{'LOG_VERB'}{'5'}>5</option>
2783 <option value='6' $selected{'LOG_VERB'}{'6'}>6</option>
2784 <option value='7' $selected{'LOG_VERB'}{'7'}>7</option>
2785 <option value='8' $selected{'LOG_VERB'}{'8'}>8</option>
2786 <option value='9' $selected{'LOG_VERB'}{'9'}>9</option>
2787 <option value='10' $selected{'LOG_VERB'}{'10'}>10</option>
2788 <option value='11' $selected{'LOG_VERB'}{'11'}>11</option>
2789 </td></select>
2790 </table>
2791
2792 <hr size='1'>
2793 END
2794
2795 if ( -e "/var/run/openvpn.pid"){
2796 print" <br><b><font color='#990000'>$Lang::tr{'attention'}:</b></font><br>
2797 $Lang::tr{'server restart'}<br><br>
2798 <hr>";
2799 print<<END;
2800 <table width='100%'>
2801 <tr>
2802 <td>&nbsp;</td>
2803 <td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'save-adv-options'}' disabled='disabled' /></td>
2804 <td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'cancel-adv-options'}' /></td>
2805 <td>&nbsp;</td>
2806 </tr>
2807 </table>
2808 </form>
2809 END
2810 ;
2811
2812
2813 }else{
2814
2815 print<<END;
2816 <table width='100%'>
2817 <tr>
2818 <td>&nbsp;</td>
2819 <td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'save-adv-options'}' /></td>
2820 <td allign='center'><input type='submit' name='ACTION' value='$Lang::tr{'cancel-adv-options'}' /></td>
2821 <td>&nbsp;</td>
2822 </tr>
2823 </table>
2824 </form>
2825 END
2826 ;
2827 }
2828 &Header::closebox();
2829 # print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
2830 &Header::closebigbox();
2831 &Header::closepage();
2832 exit(0);
2833
2834
2835 # A.Marx CCD Add,delete or edit CCD net
2836
2837 } elsif ($cgiparams{'ACTION'} eq $Lang::tr{'ccd net'} ||
2838 $cgiparams{'ACTION'} eq $Lang::tr{'ccd add'} ||
2839 $cgiparams{'ACTION'} eq "kill" ||
2840 $cgiparams{'ACTION'} eq "edit" ||
2841 $cgiparams{'ACTION'} eq 'editsave'){
2842 &Header::showhttpheaders();
2843 &Header::openpage($Lang::tr{'ccd net'}, 1, '');
2844 &Header::openbigbox('100%', 'LEFT', '', '');
2845
2846 if ($cgiparams{'ACTION'} eq "kill"){
2847 &delccdnet($cgiparams{'net'});
2848 }
2849
2850 if ($cgiparams{'ACTION'} eq 'editsave'){
2851 my ($a,$b) =split (/\|/,$cgiparams{'ccdname'});
2852 if ( $a ne $b){ &modccdnet($a,$b);}
2853 $cgiparams{'ccdname'}='';
2854 $cgiparams{'ccdsubnet'}='';
2855 }
2856
2857 if ($cgiparams{'ACTION'} eq $Lang::tr{'ccd add'}) {
2858 &addccdnet($cgiparams{'ccdname'},$cgiparams{'ccdsubnet'});
2859 }
2860 if ($errormessage) {
2861 &Header::openbox('100%', 'LEFT', $Lang::tr{