]>
Commit | Line | Data |
---|---|---|
6e13d0a5 MT |
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 | } |