]> git.ipfire.org Git - ipfire-2.x.git/blob - html/cgi-bin/ovpnfunc.pl
HinzugefĆ¼gt:
[ipfire-2.x.git] / html / cgi-bin / ovpnfunc.pl
1 #!/usr/bin/perl -w
2 package Ovpnfunc;
3 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
4 use Net::DNS;
5 use File::Copy;
6 use File::Temp qw/ tempfile tempdir /;
7 use strict;
8 require '/var/ipfire/general-functions.pl';
9 my %netsettings=();
10 my $errormessage = '';
11 my $errormessage2 = '';
12 my @subnets; # array of anonymous hashes {cn, from, to}
13 my @subnets2; # array of anonymous hashes {cn, from, to}
14 my %overlaps; # hash {cn} of anonymous arrays of subnets
15 my ($subnet, $from, $to, $i, $j);
16 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
17 sub haveOrangeNet
18 {
19 if ($netsettings{'CONFIG_TYPE'} == 1) {return 1;}
20 if ($netsettings{'CONFIG_TYPE'} == 3) {return 1;}
21 if ($netsettings{'CONFIG_TYPE'} == 5) {return 1;}
22 if ($netsettings{'CONFIG_TYPE'} == 7) {return 1;}
23 return 0;
24 }
25
26 sub haveBlueNet
27 {
28 if ($netsettings{'CONFIG_TYPE'} == 4) {return 1;}
29 if ($netsettings{'CONFIG_TYPE'} == 5) {return 1;}
30 if ($netsettings{'CONFIG_TYPE'} == 6) {return 1;}
31 if ($netsettings{'CONFIG_TYPE'} == 7) {return 1;}
32 return 0;
33 }
34
35 sub sizeformat{
36 my $bytesize = $_[0];
37 my $i = 0;
38
39 while(abs($bytesize) >= 1024){
40 $bytesize=$bytesize/1024;
41 $i++;
42 last if($i==6);
43 }
44
45 my @units = ("Bytes","KB","MB","GB","TB","PB","EB");
46 my $newsize=(int($bytesize*100 +0.5))/100;
47 return("$newsize $units[$i]");
48 }
49
50 sub valid_dns_host {
51 my $hostname = $_[0];
52 unless ($hostname) { return "No hostname"};
53 my $res = new Net::DNS::Resolver;
54 my $query = $res->search("$hostname");
55 if ($query) {
56 foreach my $rr ($query->answer) {
57 ## Potential bug - we are only looking at A records:
58 return 0 if $rr->type eq "A";
59 }
60 } else {
61 return $res->errorstring;
62 }
63 }
64
65 sub cleanssldatabase
66 {
67 if (open(FILE, ">${General::swroot}/ovpn/certs/serial")) {
68 print FILE "01";
69 close FILE;
70 }
71 if (open(FILE, ">${General::swroot}/ovpn/certs/index.txt")) {
72 print FILE "";
73 close FILE;
74 }
75 unlink ("${General::swroot}/ovpn/certs/index.txt.old");
76 unlink ("${General::swroot}/ovpn/certs/serial.old");
77 unlink ("${General::swroot}/ovpn/certs/01.pem");
78 }
79
80 sub newcleanssldatabase
81 {
82 if (! -s "${General::swroot}/ovpn/certs/serial" ) {
83 open(FILE, ">${General::swroot}(ovpn/certs/serial");
84 print FILE "01";
85 close FILE;
86 }
87 if (! -s ">${General::swroot}/ovpn/certs/index.txt") {
88 system ("touch ${General::swroot}/ovpn/certs/index.txt");
89 }
90 unlink ("${General::swroot}/ovpn/certs/index.txt.old");
91 unlink ("${General::swroot}/ovpn/certs/serial.old");
92 }
93
94 sub deletebackupcert
95 {
96 if (open(FILE, "${General::swroot}/ovpn/certs/serial.old")) {
97 my $hexvalue = <FILE>;
98 chomp $hexvalue;
99 close FILE;
100 unlink ("${General::swroot}/ovpn/certs/$hexvalue.pem");
101 }
102 }
103
104 sub checkportfw {
105 my $KEY2 = $_[0]; # key2
106 my $SRC_PORT = $_[1]; # src_port
107 my $PROTOCOL = $_[2]; # protocol
108 my $SRC_IP = $_[3]; # sourceip
109 my $pfwfilename = "${General::swroot}/portfw/config";
110 open(FILE, $pfwfilename) or die 'Unable to open config file.';
111 my @pfwcurrent = <FILE>;
112 close(FILE);
113 my $pfwkey1 = 0; # used for finding last sequence number used
114 foreach my $pfwline (@pfwcurrent)
115 {
116 my @pfwtemp = split(/\,/,$pfwline);
117
118 chomp ($pfwtemp[8]);
119 if ($KEY2 eq "0"){ # if key2 is 0 then it is a portfw addition
120 if ( $SRC_PORT eq $pfwtemp[3] &&
121 $PROTOCOL eq $pfwtemp[2] &&
122 $SRC_IP eq $pfwtemp[7])
123 {
124 $errormessage = "$Lang::tr{'source port in use'} $SRC_PORT";
125 }
126 # Check if key2 = 0, if it is then it is a port forward entry and we want the sequence number
127 if ( $pfwtemp[1] eq "0") {
128 $pfwkey1=$pfwtemp[0];
129 }
130 # Darren Critchley - Duplicate or overlapping Port range check
131 if ($pfwtemp[1] eq "0" &&
132 $PROTOCOL eq $pfwtemp[2] &&
133 $SRC_IP eq $pfwtemp[7] &&
134 $errormessage eq '')
135 {
136 &portchecks($SRC_PORT, $pfwtemp[5]);
137 # &portchecks($pfwtemp[3], $pfwtemp[5]);
138 # &portchecks($pfwtemp[3], $SRC_IP);
139 }
140 }
141 }
142 # $errormessage="$KEY2 $SRC_PORT $PROTOCOL $SRC_IP";
143
144 return $errormessage;
145 }
146
147 sub checkportoverlap
148 {
149 my $portrange1 = $_[0]; # New port range
150 my $portrange2 = $_[1]; # existing port range
151 my @tempr1 = split(/\:/,$portrange1);
152 my @tempr2 = split(/\:/,$portrange2);
153
154 unless (&checkportinc($tempr1[0], $portrange2)){ return 0;}
155 unless (&checkportinc($tempr1[1], $portrange2)){ return 0;}
156
157 unless (&checkportinc($tempr2[0], $portrange1)){ return 0;}
158 unless (&checkportinc($tempr2[1], $portrange1)){ return 0;}
159
160 return 1; # Everything checks out!
161 }
162
163 # Darren Critchley - we want to make sure that a port entry is not within an already existing range
164 sub checkportinc
165 {
166 my $port1 = $_[0]; # Port
167 my $portrange2 = $_[1]; # Port range
168 my @tempr1 = split(/\:/,$portrange2);
169
170 if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) {
171 return 1;
172 } else {
173 return 0;
174 }
175 }
176 # Darren Critchley - Duplicate or overlapping Port range check
177 sub portchecks
178 {
179 my $p1 = $_[0]; # New port range
180 my $p2 = $_[1]; # existing port range
181 # $_ = $_[0];
182 our ($prtrange1, $prtrange2);
183 $prtrange1 = 0;
184 # if (m/:/ && $prtrange1 == 1) { # comparing two port ranges
185 # unless (&checkportoverlap($p1,$p2)) {
186 # $errormessage = "$Lang::tr{'source port overlaps'} $p1";
187 # }
188 # }
189 if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range
190 unless (&checkportinc($p2,$p1)) {
191 $errormessage = "$Lang::tr{'srcprt within existing'} $p1";
192 }
193 }
194 $prtrange1 = 1;
195 if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range
196 unless (&checkportinc($p1,$p2)) {
197 $errormessage = "$Lang::tr{'srcprt range overlaps'} $p2";
198 }
199 }
200 return;
201 }
202
203 # Darren Critchley - certain ports are reserved for ipfire
204 # TCP 67,68,81,222,445
205 # UDP 67,68
206 # Params passed in -> port, rangeyn, protocol
207 sub disallowreserved
208 {
209 # port 67 and 68 same for tcp and udp, don't bother putting in an array
210 my $msg = "";
211 my @tcp_reserved = (81,222,445);
212 my $prt = $_[0]; # the port or range
213 my $ryn = $_[1]; # tells us whether or not it is a port range
214 my $prot = $_[2]; # protocol
215 my $srcdst = $_[3]; # source or destination
216 if ($ryn) { # disect port range
217 if ($srcdst eq "src") {
218 $msg = "$Lang::tr{'rsvd src port overlap'}";
219 } else {
220 $msg = "$Lang::tr{'rsvd dst port overlap'}";
221 }
222 my @tmprng = split(/\:/,$prt);
223 unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; }
224 unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; }
225 if ($prot eq "tcp") {
226 foreach my $prange (@tcp_reserved) {
227 unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; }
228 }
229 }
230 } else {
231 if ($srcdst eq "src") {
232 $msg = "$Lang::tr{'reserved src port'}";
233 } else {
234 $msg = "$Lang::tr{'reserved dst port'}";
235 }
236 if ($prt == 67) { $errormessage="$msg 67"; return; }
237 if ($prt == 68) { $errormessage="$msg 68"; return; }
238 if ($prot eq "tcp") {
239 foreach my $prange (@tcp_reserved) {
240 if ($prange == $prt) {
241 $errormessage = "$msg $prange";
242 return $errormessage; }
243 }
244 }
245 }
246 return $errormessage;
247 }
248
249 sub writeserverconf {
250 my %sovpnsettings = ();
251 &General::readhash("${General::swroot}/ovpn/settings", \%sovpnsettings);
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 ZERINA for listening on blue and orange\n";
260 print CONF ";local $sovpnsettings{'VPN_IP'}\n";
261 print CONF "dev $sovpnsettings{'DDEVICE'}\n";
262 print CONF "$sovpnsettings{'DDEVICE'}-mtu $sovpnsettings{'DMTU'}\n";
263 print CONF "proto $sovpnsettings{'DPROTOCOL'}\n";
264 print CONF "port $sovpnsettings{'DDEST_PORT'}\n";
265 print CONF "tls-server\n";
266 print CONF "ca /var/ipfire/ovpn/ca/cacert.pem\n";
267 print CONF "cert /var/ipfire/ovpn/certs/servercert.pem\n";
268 print CONF "key /var/ipfire/ovpn/certs/serverkey.pem\n";
269 print CONF "dh /var/ipfire/ovpn/ca/dh1024.pem\n";
270 my @tempovpnsubnet = split("\/",$sovpnsettings{'DOVPN_SUBNET'});
271 print CONF "server $tempovpnsubnet[0] $tempovpnsubnet[1]\n";
272 print CONF "push \"route $netsettings{'GREEN_NETADDRESS'} $netsettings{'GREEN_NETMASK'}\"\n";
273 if ($sovpnsettings{AD_ROUTE1} ne '') {
274 my @tempovpnsubnet = split("\/",$sovpnsettings{'AD_ROUTE1'});
275 print CONF "push \"route $tempovpnsubnet[0] $tempovpnsubnet[1]\"\n";
276 }
277 if ($sovpnsettings{AD_ROUTE2} ne '') {
278 my @tempovpnsubnet = split("\/",$sovpnsettings{'AD_ROUTE2'});
279 print CONF "push \"route $tempovpnsubnet[0] $tempovpnsubnet[1]\"\n";
280 }
281 if ($sovpnsettings{AD_ROUTE3} ne '') {
282 my @tempovpnsubnet = split("\/",$sovpnsettings{'AD_ROUTE3'});
283 print CONF "push \"route $tempovpnsubnet[0] $tempovpnsubnet[1]\"\n";
284 }
285 if ($sovpnsettings{CLIENT2CLIENT} eq 'on') {
286 print CONF "client-to-client\n";
287 }
288 if ($sovpnsettings{KEEPALIVE_1} > 0 && $sovpnsettings{KEEPALIVE_2} > 0) {
289 print CONF "keepalive $sovpnsettings{'KEEPALIVE_1'} $sovpnsettings{'KEEPALIVE_2'}\n";
290 }
291 print CONF "status-version 1\n";
292 print CONF "status /var/log/ovpnserver.log 30\n";
293 print CONF "cipher $sovpnsettings{DCIPHER}\n";
294 if ($sovpnsettings{DCOMPLZO} eq 'on') {
295 print CONF "comp-lzo\n";
296 }
297 if ($sovpnsettings{REDIRECT_GW_DEF1} eq 'on') {
298 print CONF "push \"redirect-gateway def1\"\n";
299 }
300 if ($sovpnsettings{DHCP_DOMAIN} ne '') {
301 print CONF "push \"dhcp-option DOMAIN $sovpnsettings{DHCP_DOMAIN}\"\n";
302 }
303
304 if ($sovpnsettings{DHCP_DNS} ne '') {
305 print CONF "push \"dhcp-option DNS $sovpnsettings{DHCP_DNS}\"\n";
306 }
307
308 if ($sovpnsettings{DHCP_WINS} ne '') {
309 print CONF "push \"dhcp-option WINS $sovpnsettings{DHCP_WINS}\"\n";
310 }
311
312 if ($sovpnsettings{DHCP_WINS} eq '') {
313 print CONF "max-clients 100\n";
314 }
315
316 if ($sovpnsettings{DHCP_WINS} ne '') {
317 print CONF "max-clients $sovpnsettings{MAX_CLIENTS}\n";
318 }
319
320 #################################################################################
321 # Added by Philipp Jenni #
322 # #
323 # Contact: philipp.jenni-at-gmx.ch #
324 # Date: 2006-04-22 #
325 # Description: Add the FAST-IO Parameter from OpenVPN to der Server.Config. #
326 # Add the NICE Parameter from OpenVPN to der Server.Config. #
327 # Add the MTU-DISC Parameter from OpenVPN to der Server.Config. #
328 # Add the MSSFIX Parameter from OpenVPN to der Server.Config. #
329 # Add the FRAMGMENT Parameter from OpenVPN to der Server.Config. #
330 #################################################################################
331 if ($sovpnsettings{EXTENDED_FASTIO} eq 'on') {
332 print CONF "fast-io\n";
333 }
334 if ($sovpnsettings{EXTENDED_NICE} != 0) {
335 print CONF "nice $sovpnsettings{EXTENDED_NICE}\n";
336 }
337 if ($sovpnsettings{EXTENDED_MTUDISC} eq 'on') {
338 print CONF "mtu-disc yes\n";
339 }
340 if ($sovpnsettings{EXTENDED_MSSFIX} ne '') {
341 print CONF "mssfix $sovpnsettings{EXTENDED_MSSFIX}\n";
342 }
343 if ($sovpnsettings{EXTENDED_FRAGMENT} ne '') {
344 print CONF "fragment $sovpnsettings{EXTENDED_FRAGMENT}\n";
345 }
346 #################################################################################
347 # End of Inserted Data #
348 #################################################################################
349
350 print CONF "tls-verify /var/ipfire/ovpn/verify\n";
351 print CONF "crl-verify /var/ipfire/ovpn/crls/cacrl.pem\n";
352 print CONF "user nobody\n";
353 print CONF "group nobody\n";
354 print CONF "persist-key\n";
355 print CONF "persist-tun\n";
356 if ($sovpnsettings{LOG_VERB} ne '') {
357 print CONF "verb $sovpnsettings{LOG_VERB}\n";
358 } else {
359 print CONF "verb 3\n";
360 }
361 print CONF "\n";
362
363 close(CONF);
364 }
365
366 sub writenet2netconf {
367 my $n2nkey = $_[0];
368 my $zerinaclient = $_[1];
369 my %n2nconfighash = ();
370 my $file = '';
371 # my $file = '';
372 my $clientovpn = '';
373 my @fileholder;
374 my $tempdir = tempdir( CLEANUP => 1 );
375 my $zippath = "$tempdir/";
376 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%n2nconfighash);
377 if (! $n2nkey) {
378 $n2nkey = &General::findhasharraykey (\%n2nconfighash);
379 foreach my $i (0 .. 25) { $n2nconfighash{$n2nkey}[$i] = "";}
380 }
381 my $zipname = "$n2nconfighash{$n2nkey}[1].zip";
382 my $zippathname = "$zippath$zipname";
383 if ($n2nconfighash{$n2nkey}[3] eq 'net') {
384 if ($zerinaclient eq '') {
385 if ( -d "${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]"){
386 while ($file = glob("${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]/*.conf")) {
387 unlink $file
388 }
389 } else {
390 mkdir("${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]", 0770);
391 }
392 open(CONF, ">${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]/$n2nconfighash{$n2nkey}[1].conf") or die "Unable to open ${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]/$n2nconfighash{$n2nkey}[1].conf: $!";
393 } else {
394 $clientovpn = "$n2nconfighash{$n2nkey}[1].conf";
395 open(CONF, ">$tempdir/$clientovpn") or die "Unable to open $tempdir/$clientovpn: $!";
396 }
397 flock CONF, 2;
398 print CONF "dev tun\n";
399 print CONF "tun-mtu $n2nconfighash{$n2nkey}[17]\n";
400 print CONF "proto $n2nconfighash{$n2nkey}[14]\n";
401 print CONF "port $n2nconfighash{$n2nkey}[15]\n";
402 my @tempovpnsubnet = split("\/",$n2nconfighash{$n2nkey}[13]);
403 my @ovpnip = split /\./,$tempovpnsubnet[0];
404 # if ((($zerinaclient eq '') && ($n2nconfighash{$n2nkey}[19] eq 'no'))) {
405 if ((($zerinaclient eq '') && ($n2nconfighash{$n2nkey}[6] eq 'server'))) {
406 print CONF "ifconfig $ovpnip[0].$ovpnip[1].$ovpnip[2].1 $ovpnip[0].$ovpnip[1].$ovpnip[2].2\n";
407 print CONF "remote $n2nconfighash{$n2nkey}[10]\n";
408 print CONF "tls-server\n";
409 print CONF "ca /var/ipfire/ovpn/ca/cacert.pem\n";
410 print CONF "cert /var/ipfire/ovpn/certs/servercert.pem\n";
411 print CONF "key /var/ipfire/ovpn/certs/serverkey.pem\n";
412 print CONF "dh /var/ipfire/ovpn/ca/dh1024.pem\n";
413 my @tempremotesubnet = split("\/",$n2nconfighash{$n2nkey}[11]);
414 print CONF "route $tempremotesubnet[0] $tempremotesubnet[1]\n";
415 } else {
416 print CONF "ifconfig $ovpnip[0].$ovpnip[1].$ovpnip[2].2 $ovpnip[0].$ovpnip[1].$ovpnip[2].1\n";
417 #print CONF "$zerinaclient ufuk 10=$n2nconfighash{$n2nkey}[10] 18=$n2nconfighash{$n2nkey}[18] 19=$n2nconfighash{$n2nkey}[19] \n";
418 if ($zerinaclient ne 'true'){
419 if ($n2nconfighash{$n2nkey}[19] eq 'no'){
420 print CONF "remote $n2nconfighash{$n2nkey}[10]\n";
421 } else {
422 print CONF "remote $n2nconfighash{$n2nkey}[10]\n";
423 }
424 } else {
425 print CONF "remote $n2nconfighash{$n2nkey}[18]\n";
426 }
427 print CONF "tls-client\n";
428 if ($zerinaclient ne 'true'){
429 print CONF "pkcs12 ${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]/$n2nconfighash{$n2nkey}[1].p12\n";
430 } else {
431 print CONF "pkcs12 $n2nconfighash{$n2nkey}[1].p12\n";
432 }
433 if ($n2nconfighash{$n2nkey}[19] eq 'no'){
434 my @tempremotesubnet = split("\/",$n2nconfighash{$n2nkey}[8]);
435 print CONF "route $tempremotesubnet[0] $tempremotesubnet[1]\n";
436 } else {
437 my @tempremotesubnet = split("\/",$n2nconfighash{$n2nkey}[11]);
438 print CONF "route $tempremotesubnet[0] $tempremotesubnet[1]\n";
439 }
440 }
441 if ($n2nconfighash{$n2nkey}[26] > 0 && $n2nconfighash{$n2nkey}[27] > 0) {
442 print CONF "keepalive $n2nconfighash{$n2nkey}[26] $n2nconfighash{$n2nkey}[27]\n";
443 } else {
444 print CONF "keepalive 10 60\n";
445 }
446 print CONF "cipher $n2nconfighash{$n2nkey}[20]\n";
447 if ($n2nconfighash{$n2nkey}[16] eq 'on') {
448 print CONF "comp-lzo\n";
449 }
450 if ($n2nconfighash{$n2nkey}[42] ne '') {
451 print CONF "verb $n2nconfighash{$n2nkey}[42]\n";
452 } else {
453 print CONF "verb 3\n";
454 }
455 if ($n2nconfighash{$n2nkey}[19] eq 'no'){
456 print CONF "#$n2nconfighash{$n2nkey}[11]\n";
457 } else {
458 print CONF "#$n2nconfighash{$n2nkey}[8]\n";
459 }
460 if ($zerinaclient ne 'true') {
461 print CONF "daemon OVPN_$n2nconfighash{$n2nkey}[1]\n";
462 print CONF "#status ${General::swroot}/ovpn/n2nconf/$n2nconfighash{$n2nkey}[1]/$n2nconfighash{$n2nkey}[1].log 2\n";
463 }
464 close(CONF);
465 if ($zerinaclient eq 'true') {
466 my $zip = Archive::Zip->new();
467 $zip->addFile( "${General::swroot}/ovpn/certs/$n2nconfighash{$n2nkey}[1].p12", "$n2nconfighash{$n2nkey}[1].p12") or die "Can't add file ${General::swroot}/ovpn/certs/$n2nconfighash{$n2nkey}[1].p12\n";
468 $zip->addFile( "$tempdir/$clientovpn", $clientovpn) or die "Can't add file $clientovpn\n";
469 my $status = $zip->writeToFileNamed($zippathname);
470 open(DLFILE, "<$zippathname") or die "Unable to open $zippathname: $!";
471 @fileholder = <DLFILE>;
472 print "Content-Type:application/x-download\n";
473 print "Content-Disposition:attachment;filename=$zipname\n\n";
474 print @fileholder;
475 exit (0);
476 }
477 }
478 }
479
480 sub removenet2netconf {
481 my %n2nconfighash = ();
482 my $key = $_[0];
483 my $file = '';
484 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%n2nconfighash);
485 if ($n2nconfighash{$key}[3] eq 'net') {
486 if ( -d "${General::swroot}/ovpn/n2nconf/$n2nconfighash{$key}[1]"){
487 while ($file = glob("${General::swroot}/ovpn/n2nconf/$n2nconfighash{$key}[1]/*")) {
488 unlink $file
489 }
490 rmdir("${General::swroot}/ovpn/n2nconf/$n2nconfighash{$key}[1]");
491 }
492 }
493 }
494
495 sub emptyserverlog{
496 if (open(FILE, ">/var/log/ovpnserver.log")) {
497 flock FILE, 2;
498 print FILE "";
499 close FILE;
500 }
501 }
502
503 sub displayca {
504 my $key = $_[0];
505 my %cahash = ();
506 &General::readhasharray("${General::swroot}/ovpn/caconfig", \%cahash);
507 if ( -f "${General::swroot}/ovpn/ca/$cahash{$key}[0]cert.pem") {
508 &Header::showhttpheaders();
509 &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
510 &Header::openbigbox('100%', 'LEFT', '', $errormessage);
511 &Header::openbox('100%', 'LEFT', "$Lang::tr{'ca certificate'}:");
512 my $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/ca/$cahash{$key}[0]cert.pem`;
513 $output = &Header::cleanhtml($output,"y");
514 print "<pre>$output</pre>\n";
515 &Header::closebox();
516 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
517 &Header::closebigbox();
518 &Header::closepage();
519 exit(0);
520 } else {
521 $errormessage = $Lang::tr{'invalid key'};
522 }
523 }
524 sub displayroothost {
525 my $roothost = $_[0];
526 my $output;
527 &Header::showhttpheaders();
528 &Header::openpage($Lang::tr{'vpn configuration main'}, 1, '');
529 &Header::openbigbox('100%', 'LEFT', '', '');
530 if ($roothost eq $Lang::tr{'show root certificate'}) {
531 &Header::openbox('100%', 'LEFT', "$Lang::tr{'root certificate'}:");
532 $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/ca/cacert.pem`;
533 } else {
534 &Header::openbox('100%', 'LEFT', "$Lang::tr{'host certificate'}:");
535 $output = `/usr/bin/openssl x509 -text -in ${General::swroot}/ovpn/certs/servercert.pem`;
536 }
537 $output = &Header::cleanhtml($output,"y");
538 print "<pre>$output</pre>\n";
539 &Header::closebox();
540 print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
541 &Header::closebigbox();
542 &Header::closepage();
543 exit(0);
544 }
545
546 sub killconnection {
547 my $key = $_[0];
548 my %n2nconfighash = ();
549 &General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%n2nconfighash);
550 my $n2nactive = `/bin/ps ax|grep $n2nconfighash{$key}[1].conf|grep -v grep|awk \'{print \$1}\'`;
551 if ($n2nactive ne ''){
552 system('/usr/local/bin/openvpnctrl', '-kn2n', $n2nactive);
553 }
554 }
555
556 sub cidrormask {
557 my $cidrmask = $_[0];
558 my $cidrmask2 = $cidrmask;
559 if ("/$cidrmask" =~ /^\/(\d+)/){#cidr
560 if ($cidrmask2 = &cidr2mask("/$cidrmask")) {
561 return $cidrmask2;
562 } else {
563 if ($cidrmask =~ /^\d+\.\d+\.\d+\.\d+/){#mask
564 return $cidrmask;
565 }
566 }
567 } else {
568 if ($cidrmask =~ /^\d+\.\d+\.\d+\.\d+/){#mask
569 return $cidrmask;
570 }
571 }
572 }
573 sub cidr2mask {
574 my( $cidr ) = @_;
575 my( $one32 ) = 0xffffffff;
576 my( @d, $n, $bits );
577
578 if ( $cidr eq "/0" ) {
579 return "0.0.0.0";
580 }
581
582 if ( $cidr !~ /\/(\d+)/ ) {
583 return undef;
584 }
585 $bits = $1;
586
587 if ( $bits > 32 ) {
588 return undef;
589 }
590
591 #-- convert to subnet-style mask
592 $n = $one32 << (32 - $bits);
593 $d[3] = $n % 256; $n = int( $n / 256);
594 $d[2] = $n % 256; $n = int( $n / 256);
595 $d[1] = $n % 256; $n = int( $n / 256);
596 $d[0] = $n;
597 return join '.', @d;
598 }
599
600
601 # ----------------------------------------------------------------------------
602 # $cidr = &mask2cidr( $mask )
603 # ----------------------------------------------------------------------------
604
605 sub mask2cidr {
606 my( $mask ) = @_;
607 my( @d, $n, $bits );
608
609 if ( $mask eq "0.0.0.0" ) {
610 return "/0";
611 }
612
613 if ( ! &validMask( $mask ) ) {
614 return undef;
615 }
616
617 @d = split /\./, $mask;
618 $n = ((((($d[0] * 256) + $d[1]) * 256) + $d[2]) * 256) + $d[3];
619 $bits = 32;
620 while ( ($n % 2) == 0 ) {
621 $n >>= 1;
622 $bits -= 1;
623 }
624 return "/$bits";
625 }
626
627
628 # ----------------------------------------------------------------------------
629 # $yesno = &validMask( $mask )
630 # ----------------------------------------------------------------------------
631
632 sub validMask {
633 my( $mask ) = @_;
634 my( @d, $n, $str );
635
636 @d = split /\./, $mask;
637 $n = ((((($d[0] * 256) + $d[1]) * 256) + $d[2]) * 256) + $d[3];
638 $str = sprintf "%b", $n;
639 return ( $str =~ /^1+0*$/ );
640 }
641
642 sub overlapping {
643 # read all subnets from AD, convert to integer range, and sort.
644 foreach $subnet (@subnets2) {
645 ($from, $to) = &subnet2range ($subnet);
646 push @subnets, { cn => $subnet, from => $from, to => $to };
647 }
648 @subnets = sort { $a->{from} <=> $b->{from} } @subnets;
649
650 # compare all possible subnets for overlap; depend on sort order.
651 for ($i=0; $i<=$#subnets; $i++) {
652 for ($j=$i+1; $j<=$#subnets; $j++) {
653 last if $subnets[$i]->{to} < $subnets[$j]->{from}; # no possible overlap anymore;
654 push @{$overlaps{$subnets[$i]->{cn}}}, $subnets[$j]->{cn} if $subnets[$i]->{to} >= $subnets[$j]->{from};
655 }
656 }
657
658 if (scalar (keys %overlaps)) {
659 foreach $subnet (sort keys %overlaps) {
660 #$errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire IPSEC : %s\n", $subnet, join (", ", sort @{$overlaps{$subnet}});
661 $errormessage = "$subnet : $overlaps{$subnet}[0]";
662 last;
663 }
664 }
665 return $errormessage;
666 }
667
668 # &subnet2range ($subnet)
669 # convert subnets to integers in order to compare them later.
670 # A subnet looks like this: 10.1.2.0/24
671 # returns beginning and end of subnet as integer
672 #
673 sub subnet2range {
674 my $subnet = shift (@_);
675 my ($from, $to);
676
677 $subnet =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)$/ || die "bad subnet $subnet\n";
678 $from = $1*2**24 + $2*2**16 + $3*2**8 + $4;
679 $to = $from + 2**(32-$5) - 1;
680 return ($from, $to);
681 }
682
683 sub ovelapplausi {
684 my $tmpovpnsubnet0 = $_[0];
685 my $tmpovpnsubnet1 = $_[1];
686 my %vpnconfighash = ();
687 my $tmpcidr = '';
688 my @tmpremotevpnsubnet;
689 &General::readhasharray("${General::swroot}/vpn/config", \%vpnconfighash);
690
691 if (&General::IpInSubnet ( $netsettings{'GREEN_ADDRESS'},
692 $tmpovpnsubnet0, $tmpovpnsubnet1)) {
693 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Green Network $netsettings{'GREEN_ADDRESS'}";
694 return $errormessage;
695 }
696
697 if (&haveBlueNet()) {
698 if (&General::IpInSubnet ( $netsettings{'BLUE_ADDRESS'},
699 $tmpovpnsubnet0, $tmpovpnsubnet1)) {
700 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Blue Network $netsettings{'BLUE_ADDRESS'}";
701 return $errormessage;
702 }
703 }
704 if (&haveOrangeNet()) {
705 if (&General::IpInSubnet ( $netsettings{'ORANGE_ADDRESS'},
706 $tmpovpnsubnet0, $tmpovpnsubnet1)) {
707 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire Orange Network $netsettings{'ORANGE_ADDRESS'}";
708 return $errormessage;
709 }
710 }
711 open(ALIASES, "${General::swroot}/ethernet/aliases") or die 'Unable to open aliases file.';
712 while (<ALIASES>)
713 {
714 chomp($_);
715 my @tempalias = split(/\,/,$_);
716 if ($tempalias[1] eq 'on') {
717 if (&General::IpInSubnet ($tempalias[0] ,
718 $tmpovpnsubnet0, $tmpovpnsubnet1)) {
719 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire alias entry $tempalias[0]";
720 exit $errormessage;
721 }
722 }
723 }
724 close(ALIASES);
725
726 #check against ipsec connections
727 foreach my $key (keys %vpnconfighash) {
728 #$confighash{$key}[8] = $cgiparams{'LOCAL_SUBNET'};
729 #$confighash{$key}[3]#host or net
730 #$confighash{$key}[11] = $cgiparams{'REMOTE_SUBNET'};
731 #$confighash{$key}[10] = $cgiparams{'REMOTE'};
732 &emptyarray();
733 $tmpcidr = &mask2cidr($tmpovpnsubnet1);
734 push @subnets2, "$tmpovpnsubnet0$tmpcidr";
735 @tmpremotevpnsubnet = split("\/",$vpnconfighash{$key}[8]);
736 $tmpcidr = &mask2cidr($tmpremotevpnsubnet[1]);
737 push @subnets2, "$tmpremotevpnsubnet[0]$tmpcidr";
738 $errormessage2 = &overlapping();
739 if ($errormessage2 ne '') {
740 $errormessage = "$Lang::tr{'ovpn subnet overlap'}IPSCEC Connection=$vpnconfighash{$key}[1] $Lang::tr{'local subnet'} $errormessage2 ";
741 last;
742 }
743 &emptyarray();
744 if ($vpnconfighash{$key}[3] eq 'net'){
745 if (&General::IpInSubnet ($vpnconfighash{$key}[10],$tmpovpnsubnet0, $tmpovpnsubnet1)) {
746 $errormessage = "$Lang::tr{'ovpn subnet overlap'} IPFire IPSEC Connection/IP: $vpnconfighash{$key}[1]/$vpnconfighash{$key}[10]";
747 last;
748 }
749 #check agains ipsec local subent
750 push @subnets2, "$tmpovpnsubnet0$tmpcidr";
751 @tmpremotevpnsubnet = split("\/",$vpnconfighash{$key}[11]);
752 $tmpcidr = &mask2cidr($tmpremotevpnsubnet[1]);
753 push @subnets2, "$tmpremotevpnsubnet[0]$tmpcidr";
754 $errormessage2 = &overlapping();
755 if ($errormessage2 ne '') {
756 $errormessage = "$Lang::tr{'ovpn subnet overlap'}IPSCEC Connection=$vpnconfighash{$key}[1] $Lang::tr{'remote subnet'} $errormessage2 ";
757 last;
758 }
759 &emptyarray();
760 push @subnets2, "$tmpovpnsubnet0$tmpcidr";
761 @tmpremotevpnsubnet = split("\/",$vpnconfighash{$key}[8]);
762 $tmpcidr = &mask2cidr($tmpremotevpnsubnet[1]);
763 push @subnets2, "$tmpremotevpnsubnet[0]$tmpcidr";
764 $errormessage2 = &overlapping();
765 if ($errormessage2 ne '') {
766 $errormessage = "$Lang::tr{'ovpn subnet overlap'}IPSCEC Connection=$vpnconfighash{$key}[1] $Lang::tr{'local subnet'} $errormessage2 ";
767 last;
768 }
769 &emptyarray();
770 }
771 }
772 #check against OpenVPN Connections (aware check against itself)
773 return $errormessage;
774 }
775 sub emptyarray {
776 @subnets2 = ();
777 @subnets = ();
778 }