diff --git a/config/backup/include b/config/backup/include index e1edeff6a..ba78c69f5 100644 --- a/config/backup/include +++ b/config/backup/include @@ -41,3 +41,4 @@ /root/.bash_history /var/ipfire/ethernet/aliases /var/ipfire/ethernet/wireless +/var/ipfire/captive/* diff --git a/config/cfgroot/general-functions.pl b/config/cfgroot/general-functions.pl index f448c34be..0577afe28 100644 --- a/config/cfgroot/general-functions.pl +++ b/config/cfgroot/general-functions.pl @@ -235,7 +235,13 @@ sub writehashpart sub age { my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat $_[0]; - my $totalsecs = time() - $mtime; + my $t = time() - $mtime; + + return &format_time($t); +} + +sub format_time($) { + my $totalsecs = shift; my @s = (); my $secs = $totalsecs % 60; diff --git a/config/cfgroot/lang.pl b/config/cfgroot/lang.pl index c77e0a066..2b09c4a9f 100644 --- a/config/cfgroot/lang.pl +++ b/config/cfgroot/lang.pl @@ -179,4 +179,18 @@ sub FindWebLanguage() { return undef; } +sub DetectBrowserLanguages() { + my $langs = $ENV{"HTTP_ACCEPT_LANGUAGE"}; + my @results = (); + + foreach my $lang (split /[,;]/, $langs) { + # Drop all q= arguments + next if ($lang =~ m/^q=/); + + push(@results, $lang); + } + + return @results; +} + 1; diff --git a/config/cfgroot/network-functions.pl b/config/cfgroot/network-functions.pl index 66f1ed554..93b819030 100644 --- a/config/cfgroot/network-functions.pl +++ b/config/cfgroot/network-functions.pl @@ -374,6 +374,26 @@ sub wifi_get_signal_level($) { return $signal_level; } + +sub get_hardware_address($) { + my $ip_address = shift; + my $ret; + + open(FILE, "/proc/net/arp") or die("Could not read ARP table"); + + while () { + my ($ip_addr, $hwtype, $flags, $hwaddr, $mask, $device) = split(/\s+/, $_); + if ($ip_addr eq $ip_address) { + $ret = $hwaddr; + last; + } + } + + close(FILE); + + return $ret; +} + 1; # Remove the next line to enable the testsuite diff --git a/config/cron/crontab b/config/cron/crontab index c6d8a725c..4561f4a24 100644 --- a/config/cron/crontab +++ b/config/cron/crontab @@ -65,6 +65,12 @@ HOME=/ # Retry sending spooled mails regularly %hourly * /usr/sbin/dma -q +# Cleanup captive clients +%hourly * /usr/bin/captive-cleanup + +# Reload captive firewall rules +%nightly * 23-1 /usr/local/bin/captivectrl >/dev/null + # Cleanup the mail spool directory %weekly * * /usr/sbin/dma-cleanup-spool diff --git a/config/httpd/vhosts.d/captive.conf b/config/httpd/vhosts.d/captive.conf new file mode 100644 index 000000000..e4e1d78f1 --- /dev/null +++ b/config/httpd/vhosts.d/captive.conf @@ -0,0 +1,30 @@ +Listen 1013 + + + DocumentRoot /srv/web/ipfire/html/captive + + # Close all connections as soon as a reply has been sent. + # Most browsers open loads of connections which then causes + # the access page being loaded again after a correct coupon + # code was entered. + KeepAlive Off + + ScriptAlias /cgi-bin/ /srv/web/ipfire/cgi-bin/captive/ + Alias /assets/ /srv/web/ipfire/html/captive/assets/ + + Alias /favicon.ico /srv/web/ipfire/html/captive/assets/favicon.ico + + # All unknown URIs will be redirected to the first + # redirector script. + ScriptAliasMatch .* /srv/web/ipfire/cgi-bin/captive/redirect.cgi + + + Options ExecCGI + Require all granted + + + + Options +FollowSymlinks + Require all granted + + diff --git a/config/menu/30-network.menu b/config/menu/30-network.menu index 8e1336a3b..137fd686c 100644 --- a/config/menu/30-network.menu +++ b/config/menu/30-network.menu @@ -23,6 +23,11 @@ 'title' => "$Lang::tr{'dhcp server'}", 'enabled' => 1, }; + $subnetwork->{'32.captive'} = {'caption' => $Lang::tr{'Captive menu'}, + 'uri' => '/cgi-bin/captive.cgi', + 'title' => $Lang::tr{'Captive menu'}, + 'enabled' => 1, + }; $subnetwork->{'40.scheduler'} = { 'caption' => $Lang::tr{'connscheduler'}, 'uri' => '/cgi-bin/connscheduler.cgi', diff --git a/config/rootfiles/common/apache2 b/config/rootfiles/common/apache2 index 233301a71..040b48214 100644 --- a/config/rootfiles/common/apache2 +++ b/config/rootfiles/common/apache2 @@ -43,6 +43,7 @@ etc/httpd/conf/server-tuning.conf etc/httpd/conf/ssl-global.conf etc/httpd/conf/uid.conf #etc/httpd/conf/vhosts.d +etc/httpd/conf/vhosts.d/captive.conf etc/httpd/conf/vhosts.d/ipfire-interface-ssl.conf etc/httpd/conf/vhosts.d/ipfire-interface.conf #etc/httpd/conf/vhosts.d/nagios.conf @@ -91,6 +92,8 @@ etc/httpd/conf/vhosts.d/ipfire-interface.conf #srv/web/ipfire/error/include/top.html #srv/web/ipfire/htdocs #srv/web/ipfire/htdocs/index.html +#srv/web/ipfire/html +srv/web/ipfire/html/captive #srv/web/ipfire/icons #srv/web/ipfire/icons/README #srv/web/ipfire/icons/README.html @@ -1662,3 +1665,4 @@ usr/sbin/httpd #usr/share/man/man8/rotatelogs.8 #usr/share/man/man8/suexec.8 var/log/httpd +var/log/httpd/captive diff --git a/config/rootfiles/common/bootstrap b/config/rootfiles/common/bootstrap new file mode 100644 index 000000000..cc5566a87 --- /dev/null +++ b/config/rootfiles/common/bootstrap @@ -0,0 +1,17 @@ +#usr/share/bootstrap +#usr/share/bootstrap/css +usr/share/bootstrap/css/bootstrap.css +usr/share/bootstrap/css/bootstrap.css.map +usr/share/bootstrap/css/bootstrap-grid.css +usr/share/bootstrap/css/bootstrap-grid.css.map +usr/share/bootstrap/css/bootstrap-grid.min.css +usr/share/bootstrap/css/bootstrap-grid.min.css.map +usr/share/bootstrap/css/bootstrap.min.css +usr/share/bootstrap/css/bootstrap.min.css.map +usr/share/bootstrap/css/bootstrap-reboot.css +usr/share/bootstrap/css/bootstrap-reboot.css.map +usr/share/bootstrap/css/bootstrap-reboot.min.css +usr/share/bootstrap/css/bootstrap-reboot.min.css.map +#usr/share/bootstrap/js +usr/share/bootstrap/js/bootstrap.js +usr/share/bootstrap/js/bootstrap.min.js diff --git a/config/rootfiles/common/configroot b/config/rootfiles/common/configroot index 911a780ec..58424ed2b 100644 --- a/config/rootfiles/common/configroot +++ b/config/rootfiles/common/configroot @@ -11,6 +11,11 @@ var/ipfire/auth var/ipfire/backup/exclude.user var/ipfire/backup/include.user var/ipfire/ca +var/ipfire/captive +var/ipfire/captive/agb.txt +var/ipfire/captive/clients +var/ipfire/captive/settings +var/ipfire/captive/voucher_out var/ipfire/certs #var/ipfire/certs/index.txt #var/ipfire/certs/serial @@ -51,16 +56,14 @@ var/ipfire/extrahd #var/ipfire/extrahd/settings var/ipfire/firewall #var/ipfire/firewall/config -#var/ipfire/firewall/dmz #var/ipfire/firewall/geoipblock #var/ipfire/firewall/input -#var/ipfire/firewall/nat #var/ipfire/firewall/outgoing #var/ipfire/firewall/p2protocols #var/ipfire/firewall/settings var/ipfire/fwhosts -#var/ipfire/fwhosts/customgroups #var/ipfire/fwhosts/customgeoipgrp +#var/ipfire/fwhosts/customgroups #var/ipfire/fwhosts/customhosts #var/ipfire/fwhosts/customnetworks #var/ipfire/fwhosts/customservicegrp @@ -116,6 +119,7 @@ var/ipfire/menu.d/70-log.menu #var/ipfire/menu.d/EX-tor.menu #var/ipfire/menu.d/EX-wlanap.menu var/ipfire/modem +var/ipfire/modem-lib.pl #var/ipfire/modem/defaults #var/ipfire/modem/settings var/ipfire/modem-lib.pl diff --git a/config/rootfiles/common/misc-progs b/config/rootfiles/common/misc-progs index f94f3195d..789179513 100644 --- a/config/rootfiles/common/misc-progs +++ b/config/rootfiles/common/misc-progs @@ -1,6 +1,7 @@ usr/local/bin/addonctrl #usr/local/bin/applejuicectrl usr/local/bin/backupctrl +usr/local/bin/captivectrl #usr/local/bin/clamavctrl usr/local/bin/collectdctrl usr/local/bin/ddnsctrl diff --git a/config/rootfiles/common/stage2 b/config/rootfiles/common/stage2 index ec36774b3..8c6dd40af 100644 --- a/config/rootfiles/common/stage2 +++ b/config/rootfiles/common/stage2 @@ -69,6 +69,7 @@ run #sbin #srv #usr/bin +usr/bin/captive-cleanup #usr/bin/perl #usr/include #usr/lib diff --git a/config/rootfiles/common/ubuntu-font-family b/config/rootfiles/common/ubuntu-font-family new file mode 100644 index 000000000..b9f7c0b1d --- /dev/null +++ b/config/rootfiles/common/ubuntu-font-family @@ -0,0 +1,13 @@ +usr/share/fonts/Ubuntu-B.ttf +usr/share/fonts/Ubuntu-BI.ttf +usr/share/fonts/Ubuntu-C.ttf +usr/share/fonts/Ubuntu-L.ttf +usr/share/fonts/Ubuntu-LI.ttf +usr/share/fonts/Ubuntu-M.ttf +usr/share/fonts/Ubuntu-MI.ttf +usr/share/fonts/Ubuntu-R.ttf +usr/share/fonts/Ubuntu-RI.ttf +usr/share/fonts/UbuntuMono-B.ttf +usr/share/fonts/UbuntuMono-BI.ttf +usr/share/fonts/UbuntuMono-R.ttf +usr/share/fonts/UbuntuMono-RI.ttf diff --git a/config/rootfiles/common/web-user-interface b/config/rootfiles/common/web-user-interface index f204f1657..531f8bdad 100644 --- a/config/rootfiles/common/web-user-interface +++ b/config/rootfiles/common/web-user-interface @@ -8,6 +8,11 @@ srv/web/ipfire/cgi-bin/aliases.cgi srv/web/ipfire/cgi-bin/atm-status.cgi srv/web/ipfire/cgi-bin/backup.cgi srv/web/ipfire/cgi-bin/bluetooth.cgi +#srv/web/ipfire/cgi-bin/captive +srv/web/ipfire/cgi-bin/captive.cgi +srv/web/ipfire/cgi-bin/captive/index.cgi +srv/web/ipfire/cgi-bin/captive/logo.cgi +srv/web/ipfire/cgi-bin/captive/redirect.cgi srv/web/ipfire/cgi-bin/chpasswd.cgi srv/web/ipfire/cgi-bin/connections.cgi srv/web/ipfire/cgi-bin/connscheduler.cgi @@ -23,8 +28,8 @@ srv/web/ipfire/cgi-bin/fireinfo.cgi srv/web/ipfire/cgi-bin/firewall.cgi srv/web/ipfire/cgi-bin/fwhosts.cgi srv/web/ipfire/cgi-bin/geoip-block.cgi -#srv/web/ipfire/cgi-bin/guardian.cgi srv/web/ipfire/cgi-bin/gpl.cgi +#srv/web/ipfire/cgi-bin/guardian.cgi srv/web/ipfire/cgi-bin/gui.cgi srv/web/ipfire/cgi-bin/hardwaregraphs.cgi srv/web/ipfire/cgi-bin/hosts.cgi @@ -89,6 +94,19 @@ srv/web/ipfire/cgi-bin/wirelessclient.cgi srv/web/ipfire/cgi-bin/wlanap.cgi #srv/web/ipfire/html srv/web/ipfire/html/blob.gif +#srv/web/ipfire/html/captive +#srv/web/ipfire/html/captive/assets +srv/web/ipfire/html/captive/assets/Ubuntu-L.ttf +srv/web/ipfire/html/captive/assets/Ubuntu-M.ttf +srv/web/ipfire/html/captive/assets/Ubuntu-R.ttf +srv/web/ipfire/html/captive/assets/bootstrap-grid.min.css +srv/web/ipfire/html/captive/assets/bootstrap-grid.min.css.map +srv/web/ipfire/html/captive/assets/bootstrap-reboot.min.css +srv/web/ipfire/html/captive/assets/bootstrap-reboot.min.css.map +srv/web/ipfire/html/captive/assets/captive.css +srv/web/ipfire/html/captive/assets/favicon.ico +srv/web/ipfire/html/captive/assets/ipfire.png +srv/web/ipfire/html/captive/template.html srv/web/ipfire/html/clwarn.cgi srv/web/ipfire/html/dial.cgi srv/web/ipfire/html/favicon.ico diff --git a/config/rootfiles/common/x86_64/stage2 b/config/rootfiles/common/x86_64/stage2 index 95eff3696..2897adc5e 100644 --- a/config/rootfiles/common/x86_64/stage2 +++ b/config/rootfiles/common/x86_64/stage2 @@ -70,6 +70,7 @@ run #sbin #srv #usr/bin +usr/bin/captive-cleanup #usr/bin/perl #usr/include #usr/lib diff --git a/doc/language_issues.de b/doc/language_issues.de index b9f774758..f5d6d3675 100644 --- a/doc/language_issues.de +++ b/doc/language_issues.de @@ -1,4 +1,24 @@ WARNING: translation string unused: Async logging enabled +WARNING: translation string unused: Captive 1day +WARNING: translation string unused: Captive 1month +WARNING: translation string unused: Captive 1week +WARNING: translation string unused: Captive activate +WARNING: translation string unused: Captive auth_lic +WARNING: translation string unused: Captive auth_vou +WARNING: translation string unused: Captive err doublevoucher +WARNING: translation string unused: Captive expire +WARNING: translation string unused: Captive genvoucher +WARNING: translation string unused: Captive invalid logosize +WARNING: translation string unused: Captive invalid_voucher +WARNING: translation string unused: Captive ip +WARNING: translation string unused: Captive logo_set +WARNING: translation string unused: Captive logo_upload +WARNING: translation string unused: Captive logo_upload1 +WARNING: translation string unused: Captive nr +WARNING: translation string unused: Captive time +WARNING: translation string unused: Captive voactive +WARNING: translation string unused: Captive voucher +WARNING: translation string unused: Captive vout WARNING: translation string unused: ConnSched scheduler WARNING: translation string unused: ConnSched select profile WARNING: translation string unused: HDD temperature @@ -665,9 +685,11 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours WARNING: untranslated string: Scan for Songs WARNING: untranslated string: addons WARNING: untranslated string: bytes +WARNING: untranslated string: captive WARNING: untranslated string: community rules WARNING: untranslated string: dead peer detection WARNING: untranslated string: emerging rules @@ -714,11 +736,15 @@ WARNING: untranslated string: ike lifetime should be between 1 and 8 hours WARNING: untranslated string: info messages WARNING: untranslated string: no data WARNING: untranslated string: none +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: qos add subclass WARNING: untranslated string: route config changed WARNING: untranslated string: routing config added WARNING: untranslated string: routing config changed WARNING: untranslated string: routing table WARNING: untranslated string: show tls-auth key +WARNING: untranslated string: unlimited WARNING: untranslated string: vpn force mobike WARNING: untranslated string: vpn statistics n2n diff --git a/doc/language_issues.en b/doc/language_issues.en index f2f6ab7d3..1a22e2836 100644 --- a/doc/language_issues.en +++ b/doc/language_issues.en @@ -1,4 +1,25 @@ WARNING: translation string unused: Async logging enabled +WARNING: translation string unused: Captive 1day +WARNING: translation string unused: Captive 1month +WARNING: translation string unused: Captive 1week +WARNING: translation string unused: Captive activate +WARNING: translation string unused: Captive auth_lic +WARNING: translation string unused: Captive auth_vou +WARNING: translation string unused: Captive err doublevoucher +WARNING: translation string unused: Captive expire +WARNING: translation string unused: Captive heading terms +WARNING: translation string unused: Captive heading voucher +WARNING: translation string unused: Captive invalid coupon +WARNING: translation string unused: Captive invalid logosize +WARNING: translation string unused: Captive invalid_voucher +WARNING: translation string unused: Captive ip +WARNING: translation string unused: Captive logo_set +WARNING: translation string unused: Captive nr +WARNING: translation string unused: Captive please enter a coupon code +WARNING: translation string unused: Captive time +WARNING: translation string unused: Captive voactive +WARNING: translation string unused: Captive voucher +WARNING: translation string unused: Captive vout WARNING: translation string unused: ConnSched scheduler WARNING: translation string unused: ConnSched select profile WARNING: translation string unused: HDD temperature @@ -701,8 +722,10 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: Captive clients WARNING: untranslated string: Scan for Songs WARNING: untranslated string: bytes +WARNING: untranslated string: captive WARNING: untranslated string: fwhost cust geoipgrp WARNING: untranslated string: fwhost err hostip WARNING: untranslated string: guardian block a host diff --git a/doc/language_issues.es b/doc/language_issues.es index d34d63f59..a7010105b 100644 --- a/doc/language_issues.es +++ b/doc/language_issues.es @@ -618,6 +618,35 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: ConnSched dial WARNING: untranslated string: ConnSched hangup WARNING: untranslated string: ConnSched reboot @@ -649,6 +678,7 @@ WARNING: untranslated string: bit WARNING: untranslated string: block WARNING: untranslated string: bytes WARNING: untranslated string: capabilities +WARNING: untranslated string: captive WARNING: untranslated string: ccd add WARNING: untranslated string: ccd choose net WARNING: untranslated string: ccd client options @@ -729,6 +759,7 @@ WARNING: untranslated string: drop action1 WARNING: untranslated string: drop action2 WARNING: untranslated string: drop forward WARNING: untranslated string: drop outgoing +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -1019,6 +1050,9 @@ WARNING: untranslated string: no hardware random number generator WARNING: untranslated string: none WARNING: untranslated string: not a valid dh key WARNING: untranslated string: notice +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: openvpn default WARNING: untranslated string: openvpn destination port used WARNING: untranslated string: openvpn fragment allowed with udp @@ -1143,6 +1177,7 @@ WARNING: untranslated string: tor use exit nodes WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink WARNING: untranslated string: uplink bit rate WARNING: untranslated string: upload dh key diff --git a/doc/language_issues.fr b/doc/language_issues.fr index 4a916761b..1389cbbe7 100644 --- a/doc/language_issues.fr +++ b/doc/language_issues.fr @@ -628,6 +628,35 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: ConnSched dial WARNING: untranslated string: ConnSched hangup WARNING: untranslated string: ConnSched reboot @@ -658,6 +687,7 @@ WARNING: untranslated string: bit WARNING: untranslated string: block WARNING: untranslated string: bytes WARNING: untranslated string: capabilities +WARNING: untranslated string: captive WARNING: untranslated string: ccd add WARNING: untranslated string: ccd choose net WARNING: untranslated string: ccd client options @@ -739,6 +769,7 @@ WARNING: untranslated string: drop action1 WARNING: untranslated string: drop action2 WARNING: untranslated string: drop forward WARNING: untranslated string: drop outgoing +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -1038,6 +1069,9 @@ WARNING: untranslated string: not a valid dh key WARNING: untranslated string: notice WARNING: untranslated string: ntp common settings WARNING: untranslated string: ntp sync +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: openvpn default WARNING: untranslated string: openvpn destination port used WARNING: untranslated string: openvpn fragment allowed with udp @@ -1157,6 +1191,7 @@ WARNING: untranslated string: tor use exit nodes WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink WARNING: untranslated string: uplink bit rate WARNING: untranslated string: upload dh key diff --git a/doc/language_issues.it b/doc/language_issues.it index 0baf40086..5b921a84a 100644 --- a/doc/language_issues.it +++ b/doc/language_issues.it @@ -695,6 +695,35 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: MTU settings WARNING: untranslated string: Number of Countries for the pie chart WARNING: untranslated string: Scan for Songs @@ -707,6 +736,7 @@ WARNING: untranslated string: advproxy group required WARNING: untranslated string: application layer gateways WARNING: untranslated string: block WARNING: untranslated string: bytes +WARNING: untranslated string: captive WARNING: untranslated string: check all WARNING: untranslated string: dhcp dns enable update WARNING: untranslated string: dhcp dns key name @@ -715,6 +745,7 @@ WARNING: untranslated string: dhcp dns update algo WARNING: untranslated string: dhcp dns update secret WARNING: untranslated string: dl client arch insecure WARNING: untranslated string: dnssec disabled warning +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -808,6 +839,9 @@ WARNING: untranslated string: masquerading enabled WARNING: untranslated string: messages WARNING: untranslated string: no data WARNING: untranslated string: none +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: outgoing compression in bytes per second WARNING: untranslated string: outgoing overhead in bytes per second WARNING: untranslated string: ovpn add conf @@ -825,6 +859,7 @@ WARNING: untranslated string: search WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink bit rate WARNING: untranslated string: vpn broken WARNING: untranslated string: vpn connecting diff --git a/doc/language_issues.nl b/doc/language_issues.nl index 4f64b5d68..16f6c0d89 100644 --- a/doc/language_issues.nl +++ b/doc/language_issues.nl @@ -691,6 +691,35 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: MTU settings WARNING: untranslated string: Number of Countries for the pie chart WARNING: untranslated string: Scan for Songs @@ -706,6 +735,7 @@ WARNING: untranslated string: atm device WARNING: untranslated string: block WARNING: untranslated string: bytes WARNING: untranslated string: capabilities +WARNING: untranslated string: captive WARNING: untranslated string: check all WARNING: untranslated string: default WARNING: untranslated string: dh @@ -727,6 +757,7 @@ WARNING: untranslated string: dnssec not supported WARNING: untranslated string: dnssec validating WARNING: untranslated string: download tls-auth key WARNING: untranslated string: drop outgoing +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -840,6 +871,9 @@ WARNING: untranslated string: nameserver WARNING: untranslated string: no data WARNING: untranslated string: none WARNING: untranslated string: not a valid dh key +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: outgoing compression in bytes per second WARNING: untranslated string: outgoing overhead in bytes per second WARNING: untranslated string: ovpn add conf @@ -871,6 +905,7 @@ WARNING: untranslated string: ta key WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink bit rate WARNING: untranslated string: upload dh key WARNING: untranslated string: vendor diff --git a/doc/language_issues.pl b/doc/language_issues.pl index d34d63f59..a7010105b 100644 --- a/doc/language_issues.pl +++ b/doc/language_issues.pl @@ -618,6 +618,35 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: ConnSched dial WARNING: untranslated string: ConnSched hangup WARNING: untranslated string: ConnSched reboot @@ -649,6 +678,7 @@ WARNING: untranslated string: bit WARNING: untranslated string: block WARNING: untranslated string: bytes WARNING: untranslated string: capabilities +WARNING: untranslated string: captive WARNING: untranslated string: ccd add WARNING: untranslated string: ccd choose net WARNING: untranslated string: ccd client options @@ -729,6 +759,7 @@ WARNING: untranslated string: drop action1 WARNING: untranslated string: drop action2 WARNING: untranslated string: drop forward WARNING: untranslated string: drop outgoing +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -1019,6 +1050,9 @@ WARNING: untranslated string: no hardware random number generator WARNING: untranslated string: none WARNING: untranslated string: not a valid dh key WARNING: untranslated string: notice +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: openvpn default WARNING: untranslated string: openvpn destination port used WARNING: untranslated string: openvpn fragment allowed with udp @@ -1143,6 +1177,7 @@ WARNING: untranslated string: tor use exit nodes WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink WARNING: untranslated string: uplink bit rate WARNING: untranslated string: upload dh key diff --git a/doc/language_issues.ru b/doc/language_issues.ru index d07c421eb..a2a771ece 100644 --- a/doc/language_issues.ru +++ b/doc/language_issues.ru @@ -619,7 +619,36 @@ WARNING: translation string unused: wlanap wlan services WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours WARNING: untranslated string: Add a route +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: ConnSched dial WARNING: untranslated string: ConnSched hangup WARNING: untranslated string: ConnSched reboot @@ -651,6 +680,7 @@ WARNING: untranslated string: bit WARNING: untranslated string: block WARNING: untranslated string: bytes WARNING: untranslated string: capabilities +WARNING: untranslated string: captive WARNING: untranslated string: ccd add WARNING: untranslated string: ccd choose net WARNING: untranslated string: ccd client options @@ -733,6 +763,7 @@ WARNING: untranslated string: drop action1 WARNING: untranslated string: drop action2 WARNING: untranslated string: drop forward WARNING: untranslated string: drop outgoing +WARNING: untranslated string: eight hours WARNING: untranslated string: email config WARNING: untranslated string: email empty field WARNING: untranslated string: email invalid @@ -1021,6 +1052,9 @@ WARNING: untranslated string: no hardware random number generator WARNING: untranslated string: none WARNING: untranslated string: not a valid dh key WARNING: untranslated string: notice +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: openvpn default WARNING: untranslated string: openvpn destination port used WARNING: untranslated string: openvpn fragment allowed with udp @@ -1138,6 +1172,7 @@ WARNING: untranslated string: tor use exit nodes WARNING: untranslated string: unblock WARNING: untranslated string: unblock all WARNING: untranslated string: uncheck all +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink WARNING: untranslated string: uplink bit rate WARNING: untranslated string: upload dh key diff --git a/doc/language_issues.tr b/doc/language_issues.tr index 034dd2a7b..96849cd69 100644 --- a/doc/language_issues.tr +++ b/doc/language_issues.tr @@ -703,10 +703,41 @@ WARNING: translation string unused: xtaccess all error WARNING: translation string unused: xtaccess bad transfert WARNING: translation string unused: year-graph WARNING: translation string unused: yearly firewallhits +WARNING: untranslated string: 24 hours +WARNING: untranslated string: Captive ACTIVATE +WARNING: untranslated string: Captive GAIN ACCESS +WARNING: untranslated string: Captive activated +WARNING: untranslated string: Captive active on +WARNING: untranslated string: Captive agree tac +WARNING: untranslated string: Captive authentication +WARNING: untranslated string: Captive brand color +WARNING: untranslated string: Captive branding +WARNING: untranslated string: Captive client session expiry time +WARNING: untranslated string: Captive clients +WARNING: untranslated string: Captive config +WARNING: untranslated string: Captive coupon +WARNING: untranslated string: Captive expiry time +WARNING: untranslated string: Captive generate coupon +WARNING: untranslated string: Captive issued coupons +WARNING: untranslated string: Captive logo uploaded +WARNING: untranslated string: Captive mac +WARNING: untranslated string: Captive menu +WARNING: untranslated string: Captive noexpiretime +WARNING: untranslated string: Captive nolimit +WARNING: untranslated string: Captive please accept the terms and conditions +WARNING: untranslated string: Captive terms +WARNING: untranslated string: Captive terms short +WARNING: untranslated string: Captive title +WARNING: untranslated string: Captive upload logo +WARNING: untranslated string: Captive upload logo recommendations +WARNING: untranslated string: Captive vouchervalid +WARNING: untranslated string: Captive wrong ext WARNING: untranslated string: Scan for Songs WARNING: untranslated string: application layer gateways WARNING: untranslated string: bytes +WARNING: untranslated string: captive WARNING: untranslated string: dnssec disabled warning +WARNING: untranslated string: eight hours WARNING: untranslated string: firewall graph country WARNING: untranslated string: firewall graph ip WARNING: untranslated string: firewall graph port @@ -755,10 +786,14 @@ WARNING: untranslated string: guardian watch snort alertfile WARNING: untranslated string: ike lifetime should be between 1 and 8 hours WARNING: untranslated string: info messages WARNING: untranslated string: no data +WARNING: untranslated string: one hour +WARNING: untranslated string: one month +WARNING: untranslated string: one week WARNING: untranslated string: route config changed WARNING: untranslated string: routing config added WARNING: untranslated string: routing config changed WARNING: untranslated string: routing table +WARNING: untranslated string: unlimited WARNING: untranslated string: uplink bit rate WARNING: untranslated string: vpn broken WARNING: untranslated string: vpn connecting diff --git a/doc/language_missings b/doc/language_missings index fd372c15f..46f6d694d 100644 --- a/doc/language_missings +++ b/doc/language_missings @@ -2,6 +2,10 @@ # Checking cgi-bin translations for language: en # ############################################################################ < addon +< Captive clients +< Captive genvoucher +< Captive logo_upload +< Captive logo_upload1 < ccd maxclients < ovpn_fragment ############################################################################ @@ -32,6 +36,54 @@ < bit < block < capabilities +< Captive 1day +< Captive 1month +< Captive 1week +< Captive activate +< Captive ACTIVATE +< Captive activated +< Captive active on +< Captive agree tac +< Captive authentication +< Captive auth_lic +< Captive auth_vou +< Captive brand color +< Captive branding +< Captive clients +< Captive client session expiry time +< Captive config +< Captive coupon +< Captive err doublevoucher +< Captive expire +< Captive expiry time +< Captive GAIN ACCESS +< Captive generate coupon +< Captive genvoucher +< Captive invalid logosize +< Captive invalid_voucher +< Captive ip +< Captive issued coupons +< Captive logo_set +< Captive logo_upload +< Captive logo_upload1 +< Captive logo uploaded +< Captive mac +< Captive menu +< Captive noexpiretime +< Captive nolimit +< Captive nr +< Captive please accept the terms and conditions +< Captive terms +< Captive terms short +< Captive time +< Captive title +< Captive upload logo +< Captive upload logo recommendations +< Captive voactive +< Captive voucher +< Captive vouchervalid +< Captive vout +< Captive wrong ext < ccd add < ccd choose net < ccd clientip @@ -121,6 +173,7 @@ < drop action2 < drop forward < drop outgoing +< eight hours < email config < email empty field < email error @@ -674,6 +727,54 @@ < bit < block < capabilities +< Captive 1day +< Captive 1month +< Captive 1week +< Captive activate +< Captive ACTIVATE +< Captive activated +< Captive active on +< Captive agree tac +< Captive authentication +< Captive auth_lic +< Captive auth_vou +< Captive brand color +< Captive branding +< Captive clients +< Captive client session expiry time +< Captive config +< Captive coupon +< Captive err doublevoucher +< Captive expire +< Captive expiry time +< Captive GAIN ACCESS +< Captive generate coupon +< Captive genvoucher +< Captive invalid logosize +< Captive invalid_voucher +< Captive ip +< Captive issued coupons +< Captive logo_set +< Captive logo_upload +< Captive logo_upload1 +< Captive logo uploaded +< Captive mac +< Captive menu +< Captive noexpiretime +< Captive nolimit +< Captive nr +< Captive please accept the terms and conditions +< Captive terms +< Captive terms short +< Captive time +< Captive title +< Captive upload logo +< Captive upload logo recommendations +< Captive voactive +< Captive voucher +< Captive vouchervalid +< Captive vout +< Captive wrong ext < ccd add < ccd choose net < ccd clientip @@ -762,6 +863,7 @@ < drop action2 < drop forward < drop outgoing +< eight hours < email config < email empty field < email error @@ -1297,6 +1399,54 @@ < bit < block < capabilities +< Captive 1day +< Captive 1month +< Captive 1week +< Captive activate +< Captive ACTIVATE +< Captive activated +< Captive active on +< Captive agree tac +< Captive authentication +< Captive auth_lic +< Captive auth_vou +< Captive brand color +< Captive branding +< Captive clients +< Captive client session expiry time +< Captive config +< Captive coupon +< Captive err doublevoucher +< Captive expire +< Captive expiry time +< Captive GAIN ACCESS +< Captive generate coupon +< Captive genvoucher +< Captive invalid logosize +< Captive invalid_voucher +< Captive ip +< Captive issued coupons +< Captive logo_set +< Captive logo_upload +< Captive logo_upload1 +< Captive logo uploaded +< Captive mac +< Captive menu +< Captive noexpiretime +< Captive nolimit +< Captive nr +< Captive please accept the terms and conditions +< Captive terms +< Captive terms short +< Captive time +< Captive title +< Captive upload logo +< Captive upload logo recommendations +< Captive voactive +< Captive voucher +< Captive vouchervalid +< Captive vout +< Captive wrong ext < ccd add < ccd choose net < ccd clientip @@ -1385,6 +1535,7 @@ < drop action2 < drop forward < drop outgoing +< eight hours < email config < email empty field < email error @@ -1907,6 +2058,54 @@ < bit < block < capabilities +< Captive 1day +< Captive 1month +< Captive 1week +< Captive activate +< Captive ACTIVATE +< Captive activated +< Captive active on +< Captive agree tac +< Captive authentication +< Captive auth_lic +< Captive auth_vou +< Captive brand color +< Captive branding +< Captive clients +< Captive client session expiry time +< Captive config +< Captive coupon +< Captive err doublevoucher +< Captive expire +< Captive expiry time +< Captive GAIN ACCESS +< Captive generate coupon +< Captive genvoucher +< Captive invalid logosize +< Captive invalid_voucher +< Captive ip +< Captive issued coupons +< Captive logo_set +< Captive logo_upload +< Captive logo_upload1 +< Captive logo uploaded +< Captive mac +< Captive menu +< Captive noexpiretime +< Captive nolimit +< Captive nr +< Captive please accept the terms and conditions +< Captive terms +< Captive terms short +< Captive time +< Captive title +< Captive upload logo +< Captive upload logo recommendations +< Captive voactive +< Captive voucher +< Captive vouchervalid +< Captive vout +< Captive wrong ext < ccd add < ccd choose net < ccd clientip @@ -1998,6 +2197,7 @@ < drop forward < drop outgoing < Edit an existing route +< eight hours < email config < email empty field < email error diff --git a/html/cgi-bin/captive.cgi b/html/cgi-bin/captive.cgi new file mode 100755 index 000000000..2f85b17c2 --- /dev/null +++ b/html/cgi-bin/captive.cgi @@ -0,0 +1,666 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2016 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +#use strict; +use HTML::Entities(); +use File::Basename; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +my %selected = (); + +my $coupons = "${General::swroot}/captive/coupons"; +my %couponhash = (); + +my $logo = "${General::swroot}/captive/logo.dat"; + +my %settings=(); +my %mainsettings; +my %color; +my %cgiparams=(); +my %netsettings=(); +my %checked=(); +my $errormessage=''; +my $clients="${General::swroot}/captive/clients"; +my %clientshash=(); +my $settingsfile="${General::swroot}/captive/settings"; +unless (-e $settingsfile) { system("touch $settingsfile"); } + +&Header::getcgihash(\%cgiparams); + +&General::readhash("${General::swroot}/main/settings", \%mainsettings); +&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); +&General::readhash("$settingsfile", \%settings) if(-f $settingsfile); +&General::readhash("${General::swroot}/ethernet/settings", \%netsettings); + +&Header::showhttpheaders(); + +if ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) { + my $file = $cgiparams{'logo'}; + if ($file) { + # Check if the file extension is PNG/JPEG + chomp $file; + + my ($name, $path, $ext) = fileparse($file, qr/\.[^.]*$/); + if ($ext ne ".png" && $ext ne ".jpg" && $ext ne ".jpeg") { + $errormessage = $Lang::tr{'Captive wrong ext'}; + } + } + + $settings{'ENABLE_GREEN'} = $cgiparams{'ENABLE_GREEN'}; + $settings{'ENABLE_BLUE'} = $cgiparams{'ENABLE_BLUE'}; + $settings{'AUTH'} = $cgiparams{'AUTH'}; + $settings{'TITLE'} = $cgiparams{'TITLE'}; + $settings{'COLOR'} = $cgiparams{'COLOR'}; + $settings{'SESSION_TIME'} = $cgiparams{'SESSION_TIME'}; + + if (!$errormessage){ + #Check if we need to upload a new logo + if ($file) { + # Save logo + my ($filehandle) = CGI::upload("logo"); + + # XXX check filesize + + open(FILE, ">$logo"); + binmode $filehandle; + while (<$filehandle>) { + print FILE; + } + close(FILE); + } + + &General::writehash("$settingsfile", \%settings); + + # Save terms + if ($cgiparams{'TERMS'}){ + $cgiparams{'TERMS'} = &Header::escape($cgiparams{'TERMS'}); + open(FH, ">:utf8", "/var/ipfire/captive/terms.txt") or die("$!"); + print FH $cgiparams{'TERMS'}; + close(FH); + $cgiparams{'TERMS'} = ""; + } + + #execute binary to reload firewall rules + system("/usr/local/bin/captivectrl"); + + if ($cgiparams{'ENABLE_BLUE'} eq 'on'){ + system("/usr/local/bin/wirelessctrl"); + } + } +} + +if ($cgiparams{'ACTION'} eq "$Lang::tr{'Captive generate coupon'}") { + # Check expiry time + if ($cgiparams{'EXP_HOUR'} + $cgiparams{'EXP_DAY'} + $cgiparams{'EXP_WEEK'} + $cgiparams{'EXP_MONTH'} == 0 && $cgiparams{'UNLIMITED'} == '') { + $errormessage = $Lang::tr{'Captive noexpiretime'}; + } + + #check valid remark + if ($cgiparams{'REMARK'} ne '' && !&validremark($cgiparams{'REMARK'})){ + $errormessage=$Lang::tr{'fwhost err remark'}; + } + + if (!$errormessage) { + # Remember selected values + foreach my $val (("UNLIMITED", "EXP_HOUR", "EXP_DAY", "EXP_WEEK", "EXP_MONTH")) { + $settings{$val} = $cgiparams{$val}; + } + &General::writehash($settingsfile, \%settings); + + &General::readhasharray($coupons, \%couponhash) if (-e $coupons); + my $now = time(); + + # Calculate expiry time in seconds + my $expires = 0; + + if ($settings{'UNLIMITED'} ne 'on') { + $expires += $settings{'EXP_HOUR'}; + $expires += $settings{'EXP_DAY'}; + $expires += $settings{'EXP_WEEK'}; + $expires += $settings{'EXP_MONTH'}; + } + + my $count = $cgiparams{'COUNT'} || 1; + while($count-- > 0) { + # Generate a new code + my $code = &gencode(); + + # Check if the coupon code already exists + foreach my $key (keys %couponhash) { + if($couponhash{$key}[1] eq $code) { + # Code already exists, so try again + $code = ""; + $count++; + last; + } + } + + next if ($code eq ""); + + # Get a new key from hash + my $key = &General::findhasharraykey(\%couponhash); + + # Initialize all fields + foreach my $i (0 .. 3) { $couponhash{$key}[$i] = ""; } + + $couponhash{$key}[0] = $now; + $couponhash{$key}[1] = $code; + $couponhash{$key}[2] = $expires; + $couponhash{$key}[3] = $cgiparams{'REMARK'}; + } + + # Save everything to disk + &General::writehasharray($coupons, \%couponhash); + } +} + +if ($cgiparams{'ACTION'} eq 'delete-coupon') { + #deletes an already generated but unused voucher + + #read all generated vouchers + &General::readhasharray($coupons, \%couponhash) if (-e $coupons); + foreach my $key (keys %couponhash) { + if($cgiparams{'key'} eq $couponhash{$key}[0]){ + #write logenty with decoded remark + my $rem=HTML::Entities::decode_entities($couponhash{$key}[4]); + &General::log("Captive", "Delete unused coupon $couponhash{$key}[1] $couponhash{$key}[2] hours valid expires on $couponhash{$key}[3] remark $rem"); + #delete line from hash + delete $couponhash{$key}; + last; + } + } + #write back hash + &General::writehasharray($coupons, \%couponhash); +} + +if ($cgiparams{'ACTION'} eq 'delete-client') { + #delete voucher and connection in use + + #read all active clients + &General::readhasharray($clients, \%clientshash) if (-e $clients); + foreach my $key (keys %clientshash) { + if($cgiparams{'key'} eq $clientshash{$key}[0]){ + #prepare log entry with decoded remark + my $rem=HTML::Entities::decode_entities($clientshash{$key}[7]); + #write logentry + &General::log("Captive", "Deleted client in use $clientshash{$key}[1] $clientshash{$key}[2] hours valid expires on $clientshash{$key}[3] remark $rem - Connection will be terminated"); + #delete line from hash + delete $clientshash{$key}; + last; + } + } + #write back hash + &General::writehasharray("$clients", \%clientshash); + #reload firewallrules to kill connection of client + system("/usr/local/bin/captivectrl"); +} + +#open webpage, print header and open box +&Header::openpage($Lang::tr{'Captive menu'}, 1, ''); +&Header::openbigbox(); + +# If an error message exists, show a box with the error message +if ($errormessage) { + &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + print $errormessage; + &Header::closebox(); +} + +# Prints the config box on the website +&Header::openbox('100%', 'left', $Lang::tr{'Captive config'}); +print <\n + + +END +; + +#check which parameters have to be enabled (from settings file) +$checked{'ENABLE_GREEN'}{'off'} = ''; +$checked{'ENABLE_GREEN'}{'on'} = ''; +$checked{'ENABLE_GREEN'}{$settings{'ENABLE_GREEN'}} = "checked='checked'"; + +$checked{'ENABLE_BLUE'}{'off'} = ''; +$checked{'ENABLE_BLUE'}{'on'} = ''; +$checked{'ENABLE_BLUE'}{$settings{'ENABLE_BLUE'}} = "checked='checked'"; + +$checked{'UNLIMITED'}{'off'} = ''; +$checked{'UNLIMITED'}{'on'} = ''; +$checked{'UNLIMITED'}{$settings{'UNLIMITED'}} = "checked='checked'"; + +$selected{'AUTH'} = (); +$selected{'AUTH'}{'COUPON'} = ""; +$selected{'AUTH'}{'TERMS'} = ""; +$selected{'AUTH'}{$settings{'AUTH'}} = "selected"; + +if ($netsettings{'GREEN_DEV'}){ + print ""; +} +if ($netsettings{'BLUE_DEV'}){ + print ""; +} + +print< + + + + +END +; + +if ($settings{'AUTH'} eq 'TERMS') { + $selected{'SESSION_TIME'} = (); + $selected{'SESSION_TIME'}{'0'} = ""; + $selected{'SESSION_TIME'}{'3600'} = ""; + $selected{'SESSION_TIME'}{'86400'} = ""; + $selected{'SESSION_TIME'}{'604800'} = ""; + $selected{'SESSION_TIME'}{'18144000'} = ""; + $selected{'SESSION_TIME'}{$settings{'SESSION_TIME'}} = "selected"; + + my $terms = &getterms(); + print < + + + + + + + + +END +} + +print< + + + + + + + + + + + + + + +END + +if (-e $logo) { + print < + + + +END +} + +print < + + + +
$Lang::tr{'Captive active on'} Green
$Lang::tr{'Captive active on'} Blue
+ $Lang::tr{'Captive authentication'} + + +
+ +
$Lang::tr{'Captive client session expiry time'} + +
+
+ $Lang::tr{'Captive branding'} +
+ $Lang::tr{'Captive title'} + + +
$Lang::tr{'Captive brand color'} + +
+ $Lang::tr{'Captive upload logo'} + + +
$Lang::tr{'Captive upload logo recommendations'} +
$Lang::tr{'Captive logo uploaded'}$Lang::tr{'yes'}
+ +
+END + +&Header::closebox(); + +#if settings is set to use coupons, the coupon part has to be displayed +if ($settings{'AUTH'} eq 'COUPON') { + &coupons(); +} + +# Show active clients +&show_clients(); + +sub getterms() { + my @ret; + + open(FILE, "<:utf8", "/var/ipfire/captive/terms.txt"); + while() { + push(@ret, HTML::Entities::decode_entities($_)); + } + close(FILE); + + return join(/\n/, @ret); +} + +sub gencode(){ + #generate a random code only letters from A-Z except 'O' and 0-9 + my @chars = ("A".."N", "P".."Z", "0".."9"); + my $randomstring; + $randomstring .= $chars[rand @chars] for 1..8; + return $randomstring; +} + +sub coupons() { + &Header::openbox('100%', 'left', $Lang::tr{'Captive generate coupon'}); + print < + + + + + + + + + +
+ $Lang::tr{'Captive vouchervalid'} + + + + + + + + + +END + + #print hour-dropdownbox + my $hrs=3600; + print " + +
$Lang::tr{'hours'}$Lang::tr{'days'}$Lang::tr{'weeks'}$Lang::tr{'months'}
"; + + #print day-dropdownbox + my $days=3600*24; + print ""; + + #print week-dropdownbox + my $week=3600*24*7; + print ""; + + #print month-dropdownbox + my $month=3600*24*30; + print " + +
+
$Lang::tr{'remark'} + +
+ +
+ + + +
+ +END + + &Header::closebox(); + + # Show all coupons if exist + if (! -z $coupons) { + &show_coupons(); + } +} + +sub show_coupons() { + &General::readhasharray($coupons, \%couponhash) if (-e $coupons); + + #if there are already generated but unsused coupons, print a table + &Header::openbox('100%', 'left', $Lang::tr{'Captive issued coupons'}); + + print < + + + $Lang::tr{'Captive coupon'} + + $Lang::tr{'Captive expiry time'} + $Lang::tr{'remark'} + $Lang::tr{'delete'} + +END + + foreach my $key (keys %couponhash) { + my $expirytime = $Lang::tr{'Captive nolimit'}; + if ($couponhash{$key}[2] > 0) { + $expirytime = &General::format_time($couponhash{$key}[2]); + } + + if ($count++ % 2) { + $col="bgcolor='$color{'color20'}'"; + } else { + $col="bgcolor='$color{'color22'}'"; + } + + print < + + $couponhash{$key}[1] + + + $expirytime + + + $couponhash{$key}[3] + + +
+ + + +
+ + +END + } + + print ""; + + &Header::closebox(); +} + +sub show_clients() { + # if there are active clients which use coupons show table + return if ( -z $clients || ! -f $clients ); + + my $count=0; + my $col; + + &Header::openbox('100%', 'left', $Lang::tr{'Captive clients'}); + + print < + + $Lang::tr{'Captive coupon'} + $Lang::tr{'Captive activated'} + $Lang::tr{'Captive expiry time'} + $Lang::tr{'Captive mac'} + $Lang::tr{'remark'} + $Lang::tr{'delete'} + +END + + &General::readhasharray($clients, \%clientshash) if (-e $clients); + foreach my $key (keys %clientshash) { + #calculate time from clientshash (starttime) + my $starttime = sub{sprintf '%02d.%02d.%04d %02d:%02d', $_[3], $_[4]+1, $_[5]+1900, $_[2], $_[1] }->(localtime($clientshash{$key}[2])); + + #calculate endtime from clientshash + my $endtime; + if ($clientshash{$key}[3] eq '0'){ + $endtime=$Lang::tr{'Captive nolimit'}; + } else { + $endtime = sub{sprintf '%02d.%02d.%04d %02d:%02d', $_[3], $_[4]+1, $_[5]+1900, $_[2], $_[1] }->(localtime($clientshash{$key}[2]+$clientshash{$key}[3])); + } + + if ($count++ % 2) { + $col="bgcolor='$color{'color20'}'"; + } else { + $col="bgcolor='$color{'color22'}'"; + } + + my $coupon = ($clientshash{$key}[4] eq "LICENSE") ? $Lang::tr{'Captive terms short'} : $clientshash{$key}[4]; + + print < + $coupon + $starttime + $endtime + $clientshash{$key}[0] + $clientshash{$key}[5] + +
+ + + +
+ + +END + } + + print ""; + + &Header::closebox(); +} + +sub validremark +{ + # Checks a hostname against RFC1035 + my $remark = $_[0]; + # Each part should be at least two characters in length + # but no more than 63 characters + if (length ($remark) < 1 || length ($remark) > 255) { + return 0;} + # Only valid characters are a-z, A-Z, 0-9 and - + if ($remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/\s]*$/) { + return 0;} + # First character can only be a letter or a digit + if (substr ($remark, 0, 1) !~ /^[a-zäöüA-ZÖÄÜ0-9]*$/) { + return 0;} + # Last character can only be a letter or a digit + if (substr ($remark, -1, 1) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/) { + return 0;} + return 1; +} + +&Header::closebigbox(); +&Header::closepage(); diff --git a/html/cgi-bin/captive/index.cgi b/html/cgi-bin/captive/index.cgi new file mode 100755 index 000000000..e9606b1bf --- /dev/null +++ b/html/cgi-bin/captive/index.cgi @@ -0,0 +1,238 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2016 Alexander Marx alexander.marx@ipfire.org # +# # +# This program is free software you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; +use CGI ':standard'; +use URI::Escape; +use HTML::Entities(); +use HTML::Template; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; + +# Load the most appropriate language from the browser configuration +my @langs = &Lang::DetectBrowserLanguages(); +&Lang::reload(@langs); + +my $coupons = "${General::swroot}/captive/coupons"; +my %couponhash = (); + +my %clientshash=(); +my %cgiparams=(); +my %settings=(); +my $clients="${General::swroot}/captive/clients"; +my $settingsfile="${General::swroot}/captive/settings"; +my $errormessage; +my $url=param('redirect'); + +#Create /var/ipfire/captive/clients if not exist +unless (-f $clients){ system("touch $clients"); } + +#Get GUI variables +&getcgihash(\%cgiparams); + +#Read settings +&General::readhash("$settingsfile", \%settings) if(-f $settingsfile); + +# Actions +if ($cgiparams{'ACTION'} eq "SUBMIT") { + # Get client IP address + my $ip_address = $ENV{X_FORWARDED_FOR} || $ENV{REMOTE_ADDR}; + + # Retrieve the MAC address from the ARP table + my $mac_address = &Network::get_hardware_address($ip_address); + + &General::readhasharray("$clients", \%clientshash); + my $key = &General::findhasharraykey(\%clientshash); + + # Create a new client line + foreach my $i (0 .. 5) { $clientshash{$key}[$i] = ""; } + + # MAC address of the client + $clientshash{$key}[0] = $mac_address; + + # IP address of the client + $clientshash{$key}[1] = $ip_address; + + # Current time + $clientshash{$key}[2] = time(); + + if ($settings{"AUTH"} eq "COUPON") { + &General::readhasharray($coupons, \%couponhash); + + if ($cgiparams{'COUPON'}) { + # Convert coupon input to uppercase + $cgiparams{'COUPON'} = uc $cgiparams{'COUPON'}; + + # Walk through all valid coupons and find the right one + my $found = 0; + foreach my $coupon (keys %couponhash) { + if ($couponhash{$coupon}[1] eq $cgiparams{'COUPON'}) { + $found = 1; + + # Copy expiry time + $clientshash{$key}[3] = $couponhash{$coupon}[2]; + + # Save coupon code + $clientshash{$key}[4] = $cgiparams{'COUPON'}; + + # Copy coupon remark + $clientshash{$key}[5] = $couponhash{$coupon}[3]; + + # Delete used coupon + delete $couponhash{$coupon}; + &General::writehasharray($coupons, \%couponhash); + + last; + } + } + + if ($found == 1) { + &General::log("Captive", "Internet access granted via coupon ($clientshash{$key}[4]) for $ip_address until $clientshash{$key}[3]"); + } else { + $errormessage = $Lang::tr{"Captive invalid coupon"}; + } + + # No coupon given + } else { + $errormessage = $Lang::tr{"Captive please enter a coupon code"}; + } + + # Terms + } else { + # Make sure that they have been accepted + if ($cgiparams{'TERMS'} eq "on") { + # Copy session expiry time + $clientshash{$key}[3] = $settings{'SESSION_TIME'} || "0"; + + # No coupon code + $clientshash{$key}[4] = "TERMS"; + + &General::log("Captive", "Internet access granted via license agreement for $ip_address until $clientshash{$key}[3]"); + + # The terms have not been accepted + } else { + $errormessage = $Lang::tr{'Captive please accept the terms and conditions'}; + } + } + + # If no errors were found, save configruation and reload + if (!$errormessage) { + &General::writehasharray("$clients", \%clientshash); + + system("/usr/local/bin/captivectrl"); + + # Redirect client to the original URL + print "Status: 302 Moved Temporarily\n"; + print "Location: $url\n"; + print "Connection: close\n\n"; + exit 0; + } +} + +my $tmpl = HTML::Template->new( + filename => "/srv/web/ipfire/html/captive/template.html", + die_on_bad_params => 0 +); + +$tmpl->param(REDIRECT => $url); + +# Coupon +if ($settings{'AUTH'} eq "COUPON") { + $tmpl->param(COUPON => 1); + $tmpl->param(L_HEADING => $Lang::tr{'Captive coupon'}); +} else { + $tmpl->param(L_HEADING => $Lang::tr{'Captive terms'}); +} + +$tmpl->param(TITLE => $settings{'TITLE'}); +$tmpl->param(COLOR => $settings{'COLOR'}); +$tmpl->param(ERROR => $errormessage); + +$tmpl->param(TERMS => &getterms()); + +# Some translated strings +$tmpl->param(L_ACTIVATE => $Lang::tr{'Captive ACTIVATE'}); +$tmpl->param(L_GAIN_ACCESS => $Lang::tr{'Captive GAIN ACCESS'}); +$tmpl->param(L_AGREE_TERMS => $Lang::tr{'Captive agree tac'}); + +# Print header +print "Pragma: no-cache\n"; +print "Cache-control: no-cache\n"; +print "Connection: close\n"; +print "Content-type: text/html\n\n"; + +# Print rendered template +print $tmpl->output(); + +sub getcgihash { + my ($hash, $params) = @_; + my $cgi = CGI->new (); + $hash->{'__CGI__'} = $cgi; + return if ($ENV{'REQUEST_METHOD'} ne 'POST'); + if (!$params->{'wantfile'}) { + $CGI::DISABLE_UPLOADS = 1; + $CGI::POST_MAX = 1024 * 1024; + } else { + $CGI::POST_MAX = 10 * 1024 * 1024; + } + $cgi->referer() =~ m/^http?\:\/\/([^\/]+)/; + my $referer = $1; + $cgi->url() =~ m/^http?\:\/\/([^\/]+)/; + my $servername = $1; + return if ($referer ne $servername); + + ### Modified for getting multi-vars, split by | + my %temp = $cgi->Vars(); + foreach my $key (keys %temp) { + $hash->{$key} = $temp{$key}; + $hash->{$key} =~ s/\0/|/g; + $hash->{$key} =~ s/^\s*(.*?)\s*$/$1/; + } + + if (($params->{'wantfile'})&&($params->{'filevar'})) { + $hash->{$params->{'filevar'}} = $cgi->upload + ($params->{'filevar'}); + } + return; +} + +sub getterms() { + my @terms = (); + + open(my $handle, "<:utf8", "/var/ipfire/captive/terms.txt"); + while(<$handle>) { + $_ = HTML::Entities::decode_entities($_); + push(@terms, $_); + } + close($handle); + + my $terms = join("\n", @terms); + + # Format paragraphs + $terms =~ s/\n\n/<\/p>\n

/g; + + return $terms; +} diff --git a/html/cgi-bin/captive/logo.cgi b/html/cgi-bin/captive/logo.cgi new file mode 100644 index 000000000..8f292b171 --- /dev/null +++ b/html/cgi-bin/captive/logo.cgi @@ -0,0 +1,44 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2016 Alexander Marx alexander.marx@ipfire.org # +# # +# This program is free software you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; +use CGI; +use File::Copy; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; + +my $logo = "${General::swroot}/captive/logo.dat"; + +# Send 404 if logo was not uploaded and exit +if (!-e $logo) { + print CGI::header(status => 404); + exit(0); +} + +print "Content-Type: application/octet-stream\n\n"; + +# Send image data +File::Copy::copy $logo, \*STDOUT; +exit(0); diff --git a/html/cgi-bin/captive/redirect.cgi b/html/cgi-bin/captive/redirect.cgi new file mode 100755 index 000000000..7c5b5e7c9 --- /dev/null +++ b/html/cgi-bin/captive/redirect.cgi @@ -0,0 +1,58 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2016 Alexander Marx alexander.marx@ipfire.org # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; +use URI::Escape; +use CGI::Carp qw(fatalsToBrowser); + +require '/var/ipfire/general-functions.pl'; + +my $url = "http://$ENV{'SERVER_NAME'}$ENV{'REQUEST_URI'}"; +my $safe_url = uri_escape($url); + +my %settingshash = (); +my %ethernethash = (); +my $target; + +# Read settings +&General::readhash("${General::swroot}/captive/settings", \%settingshash); +&General::readhash("${General::swroot}/ethernet/settings", \%ethernethash); + +# Get the client's IP address +my $client_address = $ENV{X_FORWARDED_FOR} || $ENV{REMOTE_ADDR} || ""; + +if ($settingshash{'ENABLE_GREEN'} eq "on" && $ethernethash{'GREEN_ADDRESS'} ne '') { + if (&General::IpInSubnet($client_address, $ethernethash{'GREEN_ADDRESS'}, $ethernethash{'GREEN_NETMASK'})) { + $target = $ethernethash{'GREEN_ADDRESS'}; + } + +} elsif($settingshash{'ENABLE_BLUE'} eq "on" && $ethernethash{'BLUE_ADDRESS'} ne '') { + if (&General::IpInSubnet($client_address, $ethernethash{'BLUE_ADDRESS'}, $ethernethash{'BLUE_NETMASK'})) { + $target = $ethernethash{'BLUE_ADDRESS'}; + } + +} else { + exit 0; +} + +print "Status: 302 Moved Temporarily\n"; +print "Location: http://$target:1013/cgi-bin/index.cgi?redirect=$safe_url\n"; +print "Connection: close\n\n"; diff --git a/html/cgi-bin/logs.cgi/log.dat b/html/cgi-bin/logs.cgi/log.dat index 5734fed18..f241365a1 100644 --- a/html/cgi-bin/logs.cgi/log.dat +++ b/html/cgi-bin/logs.cgi/log.dat @@ -51,6 +51,7 @@ $cgiparams{'SECTION'} = 'ipfire'; my %sections = ( 'auth' => '(\w+\(pam_unix\)\[.*\]: )', 'wio' => '(wio|wio\[.*\])', + 'captive' => '(Captive:)', 'clamav' => '(clamd\[.*\]: |freshclam\[.*\]: )', 'collectd' => '(collectd\[.*\]: )', 'cron' => '(fcron\[.*\]: )', @@ -77,6 +78,7 @@ my %sections = ( my %trsections = ( 'auth' => "$Lang::tr{'loginlogout'}", 'wio' => 'Who Is Online?', + 'captive' => $Lang::tr{'captive'}, 'clamav' => 'ClamAV', 'collectd' => 'Collectd', 'cron' => 'Cron', diff --git a/html/html/captive/assets/captive.css b/html/html/captive/assets/captive.css new file mode 100644 index 000000000..6f231bc47 --- /dev/null +++ b/html/html/captive/assets/captive.css @@ -0,0 +1,194 @@ +@font-face { + font-family: "Ubuntu"; + font-weight: 300; + src: local("Ubuntu Light"), local("Ubuntu-Light"), url("Ubuntu-L.ttf") format("truetype"); +} + +@font-face { + font-family: "Ubuntu"; + font-weight: 400; + src: local("Ubuntu Regular"), local("Ubuntu-Regular"), url("Ubuntu-R.ttf") format("truetype"); +} + +@font-face { + font-family: "Ubuntu"; + font-weight: 500; + src: local("Ubuntu Medium"), local("Ubuntu-Medium"), url("Ubuntu-M.ttf") format("truetype"); +} + +body { + background-image: url("../cgi-bin/logo.cgi"); + background-size: 100%; + background-repeat: no-repeat; + + background-color: #eceff1; + color: #263238; + + display: flex; + min-height: 100vh; + flex-direction: column; +} + +body, input { + font-family: "Ubuntu", sans-serif; + font-size: 14px; +} + +.content { + flex: 1; +} + +.box { + margin: 272px 0 48px 0; + padding: 0 30px 48px 30px; + + position: relative; + display: flex; + flex-direction: column; + background-color: white; + + border: none; + border-radius: 4px; + box-shadow: + 0 19px 38px 0 rgba(0, 0, 0, 0.3), + 0 15px 12px 0 rgba(0, 0, 0, 0.22); +} + +.box-header { + display: flex; + align-items: center; + justify-content: center; + min-height: 128px; +} + +.box-header h1 { + font-size: 40px; +} + +@media (min-width: 1200px) { + .box-header { + min-height: none; + } + + .box-header h1 { + margin-top: 24px; + margin-bottom: 20px; + } +} + +.box-block { + padding: 24px 16px 24px 16px; + margin: 0 -8px 40px -8px; + + text-align: center; + background-color: #b71c1c; + color: white; + border-radius: 4px; +} + +@media (min-width: 1200px) { + .box-block { + padding: 18px 16px 18px 16px; + margin: 0 0 48px 0; + } +} + +.box-block h4 { + font-size: 20px; +} + +footer { + height: 64px; + background-color: rgba(84, 110, 122, 0.06); /* #546e7a */ +} + +.footer { + display: flex; + align-items: center; +} + +.footer .logo { + width: 64px; + height: 64px; + padding: 8px; +} + +.form-text { + display: inline-block; + height: 36px; + + color: #263238; + background-color: rgba(38, 49, 56, 0,08); + + border: 0; + border-radius: 2px; + box-shadow: inset 0 -2px 0 0 #546e7a; +} + +.form-error { + box-shadow: inset 0 -2px 0 0 #ff3d00; +} + +.form-submit { + display: inline-block; + + font-weight: 500; + text-transform: uppercase; + + height: 36px; + padding: 0 16px 0 16px; + margin: 0 8px 0 8px; + + color: #263238; + background-color: white; + + border: none; + border-radius: 2px; + box-shadow: + 0 2px 4px 0 rgba(0, 0, 0, 0.16), + 0 1px 2px 0 rgba(0, 0, 0, 0.23); +} + +.form-submit:hover { + box-shadow: + 0 3px 6px 0 rgba(0, 0, 0, 0.16), + 0 3px 6px 0 rgba(0, 0, 0, 0.23); +} + +.form-submit:active { + background-color: black; + opacity: 0.16; + box-shadow: none; +} + +.checkbox { + position: relative; + display: block; + + margin-top: 20px; +} + +.checkbox .form-checkbox { + position: absolute; + margin-top: 1px; + margin-left: -24px; + + width: 20px; + height: 20px; + + background-color: rgba(38, 49, 56, 0.08); + + border: 2px solid #546e7a; + border-radius: 2px; +} + +.text-error { + position: block; + margin-top: 6px; + min-height: 23px; + + color: white; + background-color: #ff3d00; + + border-radius: 2px; +} diff --git a/html/html/captive/assets/favicon.ico b/html/html/captive/assets/favicon.ico new file mode 100644 index 000000000..52da262f7 Binary files /dev/null and b/html/html/captive/assets/favicon.ico differ diff --git a/html/html/captive/assets/ipfire.png b/html/html/captive/assets/ipfire.png new file mode 100644 index 000000000..cd84ad53d Binary files /dev/null and b/html/html/captive/assets/ipfire.png differ diff --git a/html/html/captive/template.html b/html/html/captive/template.html new file mode 100644 index 000000000..04be2b144 --- /dev/null +++ b/html/html/captive/template.html @@ -0,0 +1,79 @@ + + + + + <TMPL_VAR NAME="TITLE"> + + + + + + + + + + + + + +

+
+
+
+
+

+
+ +
+

+ +
+ + "> + + + form-error" type="text" name="COUPON"> + "> + +
+ +
+ + "> + + + +
+ +
+
+ +
+ + + + +
+
+
+
+ +
+
+ +
+
+ + diff --git a/langs/de/cgi-bin/de.pl b/langs/de/cgi-bin/de.pl index 7bc1c495d..af96a6445 100644 --- a/langs/de/cgi-bin/de.pl +++ b/langs/de/cgi-bin/de.pl @@ -7,6 +7,54 @@ 'Add Rule' => 'Regel hinzufügen', 'Add a route' => 'Eine Route hinzufügen', 'Async logging enabled' => 'Aktiviere asynchrones Schreiben des Syslogs', +'Captive 1day' => '1 Tag', +'Captive 1month' => '1 Monat', +'Captive 1week' => '1 Woche', +'Captive ACTIVATE' => 'AKTIVIEREN', +'Captive GAIN ACCESS' => 'ZUGANG', +'Captive activate' => 'Aktivieren', +'Captive activated' => 'Aktiviert', +'Captive active on' => 'Aktiviert auf', +'Captive agree tac' => 'Bedingungen akzeptieren', +'Captive auth_lic' => 'Lizenz', +'Captive auth_vou' => 'Gutschein', +'Captive authentication' => 'Art der Anmeldung', +'Captive brand color' => 'Highlight-Farbe', +'Captive branding' => 'Branding', +'Captive client session expiry time' => 'Ablaufzeit', +'Captive clients' => 'Clients', +'Captive config' => 'Konfiguration', +'Captive coupon' => 'Coupon', +'Captive err doublevoucher' => 'Ein Gutschein mit diesem Code ist bereits im Umlauf', +'Captive expire' => 'Ablauf', +'Captive expiry time' => 'Ablaufzeit', +'Captive generate coupon' => 'Coupon generieren', +'Captive genvoucher' => 'Gutschein generieren', +'Captive invalid logosize' => 'Die hochgeladene Datei entspricht nicht der vorgegeben Auflösung von mindestens 1280x400 und maximal 1920x800 Pixeln', +'Captive invalid_voucher' => 'Dieser Code ist ungültig. Bitte versuchen Sie es erneut', +'Captive ip' => 'IP-Addresse', +'Captive issued coupons' => 'Ausgestellte Coupons', +'Captive logo uploaded' => 'Logo hochgeladen', +'Captive logo_set' => 'Aktuelles Logo', +'Captive logo_upload' => 'Logo hochladen', +'Captive logo_upload1' => '(PNG, min. 1280x400, max. 1920x800)', +'Captive mac' => 'MAC-Adresse', +'Captive menu' => 'Captive-Portal', +'Captive noexpiretime' => 'Es wurde kein gültiger Verbindungszeitraum angegeben', +'Captive nolimit' => 'Unbegrenzt', +'Captive nr' => 'Nummer', +'Captive please accept the terms and conditions' => 'Bitte akzeptieren Sie die Bedingungen', +'Captive terms' => 'Bedingungen', +'Captive terms short' => 'Bedingungen', +'Captive time' => 'Erlaubter Nutzungszeitraum nach Aktivierung (Stunden)', +'Captive title' => 'Titel der Anmeldeseite', +'Captive upload logo' => 'Logo hochladen', +'Captive upload logo recommendations' => '(PNG oder JPEG, 1280x720 Pixel empfohlen)', +'Captive voactive' => 'Aktive Gutscheine', +'Captive voucher' => 'Gutschein', +'Captive vouchervalid' => 'Erlaubter Zeitraum für Gutschein', +'Captive vout' => 'Ausgegebene Gutscheine', +'Captive wrong ext' => 'Die hochgeladene Datei hat den falschen Dateityp', 'Choose Rule' => 'Wählen Sie eine der untenstehenden Regeln aus.', 'Class' => 'Klasse', 'Class was deleted' => 'wurde mit eventuell vorhandenen Unterklassen gelöscht', @@ -841,6 +889,7 @@ 'edit share' => 'Freigabe bearbeiten', 'editor' => 'Editor', 'eg' => 'z.B.:', +'eight hours' => '8 Stunden', 'email config' => 'Konfiguration', 'email empty field' => 'Leeres Feld', 'email error' => 'FEHLER: Test-E-Mail konnte nicht versendet werden', diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index ab1f40180..7e4f95ccf 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -1,12 +1,61 @@ %tr = ( %tr, +'24 hours' => '24 Hours', 'Act as' => 'Act as:', 'Add Level7 rule' => 'Add Level7 rule', 'Add Port Rule' => 'Add port rule', 'Add Rule' => 'Add rule', 'Add a route' => 'Add a route', 'Async logging enabled' => 'Enable asynchronous writing of the syslog file', +'Captive 1day' => '1 day', +'Captive 1month' => '1 month', +'Captive 1week' => '1 week', +'Captive ACTIVATE' => 'ACTIVATE', +'Captive GAIN ACCESS' => 'GAIN ACCESS', +'Captive activate' => 'Activate', +'Captive activated' => 'Activated', +'Captive active on' => 'Activated on', +'Captive agree tac' => 'I agree with the terms & conditions below.', +'Captive auth_lic' => 'License', +'Captive auth_vou' => 'Voucher', +'Captive authentication' => 'Type of Access', +'Captive brand color' => 'Brand Color', +'Captive branding' => 'Branding', +'Captive client session expiry time' => 'Session Expiry Time', +'Captive config' => 'Settings', +'Captive coupon' => 'Coupon', +'Captive err doublevoucher' => 'A voucher with this code already exists', +'Captive expire' => 'Expire', +'Captive expiry time' => 'Expiry Time', +'Captive generate coupon' => 'Generate Coupon', +'Captive heading terms' => 'Terms & Conditions', +'Captive heading voucher' => 'Voucher or Access Code', +'Captive invalid coupon' => 'You entered an invalid coupon code. Please try again.', +'Captive invalid logosize' => 'The uploaded image file does not meet the required resolution of at least 1280x400 but not larger than 1920x800 pixels', +'Captive invalid_voucher' => 'Invalid code. Please try again', +'Captive ip' => 'IP Address', +'Captive issued coupons' => 'Issued Coupons', +'Captive logo uploaded' => 'Logo uploaded', +'Captive logo_set' => 'Current Logo', +'Captive mac' => 'MAC Address', +'Captive menu' => 'Captive Portal', +'Captive noexpiretime' => 'No valid connection time range given', +'Captive nolimit' => 'unlimited', +'Captive nr' => 'Number', +'Captive please accept the terms and conditions' => 'Please accept the terms & conditions', +'Captive please enter a coupon code' => 'Please enter a coupon code', +'Captive terms' => 'Terms & Conditions', +'Captive terms short' => 'T&Cs', +'Captive time' => 'Access time post activation (hours)', +'Captive title' => 'Title of Login Page', +'Captive upload logo' => 'Upload Logo', +'Captive upload logo recommendations' => '(PNG or JPEG, recommended 1280x720 pixels)', +'Captive voactive' => 'Active Vouchers', +'Captive voucher' => 'Voucher', +'Captive vouchervalid' => 'Allowed time for this voucher', +'Captive vout' => 'Issued Vouchers', +'Captive wrong ext' => 'Uploaded file has wrong filetype', 'Choose Rule' => 'Choose one of the following rules.', 'Class' => 'Class', 'Class was deleted' => 'with potential subclasses was deleted', @@ -650,7 +699,7 @@ 'day after' => 'Day after', 'day before' => 'Day before', 'day-graph' => 'Day', -'days' => 'days.', +'days' => 'Days', 'dbfile' => 'Dbfile', 'ddns help dnsmadeeasy' => 'In the field for hostname enter your ID (or a list of IDs seperated by;)', 'ddns help freedns' => 'In the fied username enter your connect string', @@ -867,6 +916,7 @@ 'edit share' => 'Edit share', 'editor' => 'Editor', 'eg' => 'e.g.:', +'eight hours' => '8 Hours', 'email config' => 'Configuration', 'email empty field' => 'Empty field', 'email error' => 'ERROR: Test mail could not be sent', @@ -1282,7 +1332,7 @@ 'hosts config changed' => 'Hosts config changed', 'hour' => 'Hour', 'hour-graph' => 'Hour', -'hours' => 'hours', +'hours' => 'Hours', 'hours2' => 'Hours', 'ibod for dual isdn only' => 'iBOD can only be used with Dual ISDN.', 'icmp selected but no type' => 'ICMP selected for protocol, but no ICMP type specified.', @@ -1606,7 +1656,7 @@ 'monthly volume' => 'Monthly volume', 'monthly volume start day' => 'First day of monthly period', 'monthly volume start day short' => 'First day', -'months' => 'months', +'months' => 'Months', 'more' => 'more', 'most preferred' => 'most preferred', 'mount' => 'Mount', @@ -1701,6 +1751,9 @@ 'ok' => 'OK', 'older' => 'Older', 'on' => 'on', +'one hour' => 'One Hour', +'one month' => 'One Month', +'one week' => 'One Week', 'online help en' => 'Online help (in english)', 'only digits allowed in holdoff field' => 'Only digits allowed in holdoff field', 'only digits allowed in max retries field' => 'Only digits allowed in max retries field.', @@ -2314,6 +2367,7 @@ 'unix password sync' => 'Unix Password Sync', 'unix shell' => 'UNIX Shell', 'unknown' => 'UNKNOWN', +'unlimited' => 'Unlimited', 'unnamed' => 'Unnamed', 'update' => 'Update', 'update accelerator' => 'Update Accelerator', @@ -2694,7 +2748,7 @@ 'week' => 'Week', 'week-graph' => 'Week', 'weekly firewallhits' => 'weekly firewallhits', -'weeks' => 'weeks', +'weeks' => 'Weeks', 'wildcards' => 'Wildcards', 'wins server' => 'Wins Server', 'wins support' => 'Wins Support', diff --git a/lfs/apache2 b/lfs/apache2 index b7a741614..138ede8de 100644 --- a/lfs/apache2 +++ b/lfs/apache2 @@ -117,5 +117,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) cp -rf $(DIR_CONF)/httpd/* /etc/httpd/conf ln -sf $(CONFIG_ROOT)/main/hostname.conf /etc/httpd/conf/ + # Create captive logging directory + -mkdir -pv /var/log/httpd/captive + @rm -rf $(DIR_APP) @$(POSTBUILD) diff --git a/lfs/bootstrap b/lfs/bootstrap new file mode 100644 index 000000000..15e882e8a --- /dev/null +++ b/lfs/bootstrap @@ -0,0 +1,79 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2016 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VER = 4.0.0-alpha.6 + +THISAPP = bootstrap-$(VER) +DL_FILE = $(THISAPP)-dist.zip +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP)-dist +TARGET = $(DIR_INFO)/$(THISAPP) + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_MD5 = 7fed4691d4d7ca19820009dad86e1aef + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +md5 : $(subst %,%_MD5,$(objects)) + +############################################################################### +# Downloading, checking, md5sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_MD5,$(objects)) : + @$(MD5) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && unzip $(DIR_DL)/$(DL_FILE) + + -mkdir -pv /usr/share/bootstrap/{css,js} + cd $(DIR_APP) && cp -vf css/* /usr/share/bootstrap/css + cd $(DIR_APP) && cp -vf js/* /usr/share/bootstrap/js + + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/lfs/configroot b/lfs/configroot index 760505e2c..ad02996cf 100644 --- a/lfs/configroot +++ b/lfs/configroot @@ -50,7 +50,7 @@ $(TARGET) : @$(PREBUILD) # Create all directories - for i in addon-lang auth backup ca certs connscheduler crls ddns dhcp dhcpc dns dnsforward \ + for i in addon-lang auth backup ca captive certs connscheduler crls ddns dhcp dhcpc dns dnsforward \ ethernet extrahd/bin fwlogs fwhosts firewall isdn key langs logging mac main \ menu.d modem nfs optionsfw \ ovpn patches pakfire portfw ppp private proxy/advanced/cre \ @@ -62,7 +62,7 @@ $(TARGET) : # Touch empty files for i in auth/users backup/include.user backup/exclude.user \ - certs/index.txt ddns/config ddns/noipsettings ddns/settings ddns/ipcache dhcp/settings \ + captive/settings captive/agb.txt captive/clients captive/voucher_out certs/index.txt ddns/config ddns/noipsettings ddns/settings ddns/ipcache dhcp/settings \ dhcp/fixleases dhcp/advoptions dhcp/dhcpd.conf.local dns/settings dnsforward/config ethernet/aliases ethernet/settings ethernet/known_nics ethernet/scanned_nics \ ethernet/wireless extrahd/scan extrahd/devices extrahd/partitions extrahd/settings firewall/settings firewall/config firewall/geoipblock firewall/input firewall/outgoing \ fwhosts/customnetworks fwhosts/customhosts fwhosts/customgroups fwhosts/customservicegrp fwhosts/customgeoipgrp fwlogs/ipsettings fwlogs/portsettings \ diff --git a/lfs/stage2 b/lfs/stage2 index b70bde78a..0a5ac65c0 100644 --- a/lfs/stage2 +++ b/lfs/stage2 @@ -107,6 +107,7 @@ endif # Move script to correct place. mv -vf /usr/local/bin/ovpn-ccd-convert /usr/sbin/ mv -vf /usr/local/bin/ovpn-collectd-convert /usr/sbin/ + mv -vf /usr/local/bin/captive-cleanup /usr/bin/ # Install firewall scripts. mkdir -pv /usr/lib/firewall diff --git a/lfs/ubuntu-font-family b/lfs/ubuntu-font-family new file mode 100644 index 000000000..f817b856b --- /dev/null +++ b/lfs/ubuntu-font-family @@ -0,0 +1,78 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2017 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VER = 0.83 + +THISAPP = ubuntu-font-family-$(VER) +DL_FILE = $(THISAPP).zip +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) +TARGET = $(DIR_INFO)/$(THISAPP) + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_MD5 = a24b8136b8f3bb93f166baf97d9328de + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +md5 : $(subst %,%_MD5,$(objects)) + +############################################################################### +# Downloading, checking, md5sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_MD5,$(objects)) : + @$(MD5) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && unzip $(DIR_DL)/$(DL_FILE) + + -mkdir -pv /usr/share/fonts + cd $(DIR_APP) && cp -vf *.ttf /usr/share/fonts/ + + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/lfs/web-user-interface b/lfs/web-user-interface index 919acbe76..3e9eb9aba 100644 --- a/lfs/web-user-interface +++ b/lfs/web-user-interface @@ -68,5 +68,24 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) ln -svf ipfire /srv/web/ipfire/html/themes/ipfire-rounded # Reset permissions of redirect templates and theme directories - find /srv/web/ipfire/html/{redirect-templates,themes} -type d | xargs chmod -v 755 + find /srv/web/ipfire/html/{captive,redirect-templates,themes} -type d | xargs chmod -v 755 + + # Captive Portal CSS + ln -svf --relative /usr/share/bootstrap/css/bootstrap-grid.min.css \ + /srv/web/ipfire/html/captive/assets/bootstrap-grid.min.css + ln -svf --relative /usr/share/bootstrap/css/bootstrap-grid.min.css.map \ + /srv/web/ipfire/html/captive/assets/bootstrap-grid.min.css.map + ln -svf --relative /usr/share/bootstrap/css/bootstrap-reboot.min.css \ + /srv/web/ipfire/html/captive/assets/bootstrap-reboot.min.css + ln -svf --relative /usr/share/bootstrap/css/bootstrap-reboot.min.css.map \ + /srv/web/ipfire/html/captive/assets/bootstrap-reboot.min.css.map + + # Captive Portal Fonts + ln -svf --relative /usr/share/fonts/Ubuntu-L.ttf \ + /srv/web/ipfire/html/captive/assets/Ubuntu-L.ttf + ln -svf --relative /usr/share/fonts/Ubuntu-M.ttf \ + /srv/web/ipfire/html/captive/assets/Ubuntu-M.ttf + ln -svf --relative /usr/share/fonts/Ubuntu-R.ttf \ + /srv/web/ipfire/html/captive/assets/Ubuntu-R.ttf + @$(POSTBUILD) diff --git a/make.sh b/make.sh index 815b25aca..790c6b81f 100755 --- a/make.sh +++ b/make.sh @@ -548,6 +548,7 @@ buildipfire() { lfsmake2 web-user-interface lfsmake2 flag-icons lfsmake2 jquery + lfsmake2 bootstrap lfsmake2 arping lfsmake2 beep lfsmake2 dvdrtools @@ -626,6 +627,7 @@ buildipfire() { lfsmake2 openssh lfsmake2 fontconfig lfsmake2 dejavu-fonts-ttf + lfsmake2 ubuntu-font-family lfsmake2 freefont lfsmake2 pixman lfsmake2 cairo diff --git a/src/initscripts/system/firewall b/src/initscripts/system/firewall index 7bdb292f7..c4d2fefe4 100644 --- a/src/initscripts/system/firewall +++ b/src/initscripts/system/firewall @@ -224,6 +224,13 @@ iptables_init() { iptables -A ${i} -j LOOPBACK done + # Captive portal + iptables -N CAPTIVE_PORTAL + iptables -N CAPTIVE_PORTAL_CLIENTS + for i in INPUT FORWARD; do + iptables -A ${i} -j CAPTIVE_PORTAL + done + # Accept everything connected for i in INPUT FORWARD OUTPUT; do iptables -A ${i} -j CONNTRACK @@ -337,6 +344,10 @@ iptables_init() { iptables -N UPNPFW iptables -A FORWARD -m conntrack --ctstate NEW -j UPNPFW + # Captive Portal + iptables -t nat -N CAPTIVE_PORTAL + iptables -t nat -A PREROUTING -j CAPTIVE_PORTAL + # RED chain, used for the red interface iptables -N REDINPUT iptables -A INPUT -j REDINPUT diff --git a/src/misc-progs/Makefile b/src/misc-progs/Makefile index 7cc70b482..c3329b130 100644 --- a/src/misc-progs/Makefile +++ b/src/misc-progs/Makefile @@ -31,7 +31,8 @@ SUID_PROGS = squidctrl sshctrl ipfirereboot \ redctrl syslogdctrl extrahdctrl sambactrl upnpctrl \ smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \ setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes \ - getconntracktable wirelessclient torctrl ddnsctrl unboundctrl + getconntracktable wirelessclient torctrl ddnsctrl unboundctrl \ + captivectrl SUID_UPDX = updxsetperms OBJS = $(patsubst %,%.o,$(PROGS) $(SUID_PROGS)) diff --git a/src/misc-progs/captivectrl.c b/src/misc-progs/captivectrl.c new file mode 100644 index 000000000..6b68f97b3 --- /dev/null +++ b/src/misc-progs/captivectrl.c @@ -0,0 +1,369 @@ +/* This file is part of the IPFire Firewall. +* +* This program is distributed under the terms of the GNU General Public +* Licence. See the file COPYING for details. */ + +#define _BSD_SOURCE +#define _XOPEN_SOURCE + +#include +#include +#include +#include + +#include "libsmooth.h" +#include "setuid.h" + +#define CAPTIVE_PORTAL_SETTINGS CONFIG_ROOT "/captive/settings" +#define ETHERNET_SETTINGS CONFIG_ROOT "/ethernet/settings" + +#define CLIENTS CONFIG_ROOT "/captive/clients" +#define IPTABLES "/sbin/iptables --wait" +#define HTTP_PORT 80 +#define REDIRECT_PORT 1013 + +typedef struct client { + char etheraddr[STRING_SIZE]; + char ipaddr[STRING_SIZE]; + time_t time_start; + int expires; + + struct client* next; +} client_t; + +static time_t parse_time(const char* s) { + int t = 0; + + if (sscanf(s, "%d", &t) == 1) { + return (time_t)t; + } + + return -1; +} + +static char* format_time(const time_t* t) { + char buffer[STRING_SIZE]; + + struct tm* tm = gmtime(t); + if (tm == NULL) + return NULL; + + strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M", tm); + + return strdup(buffer); +} + +static client_t* read_clients(char* filename) { + FILE* f = NULL; + + if (!(f = fopen(filename, "r"))) { + fprintf(stderr, "Could not open configuration file: %s\n", filename); + return NULL;; + } + + char line[STRING_SIZE]; + + client_t* client_first = NULL; + client_t* client_last = NULL; + client_t* client_curr; + + while ((fgets(line, STRING_SIZE, f) != NULL)) { + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + // Skip all commented lines + if (*line == '#') + continue; + + client_curr = (client_t*)malloc(sizeof(client_t)); + memset(client_curr, 0, sizeof(client_t)); + + if (client_first == NULL) + client_first = client_curr; + else + client_last->next = client_curr; + client_last = client_curr; + + unsigned int count = 0; + char* lineptr = line; + while (1) { + if (!*lineptr) + break; + + char* word = lineptr; + while (*lineptr != '\0') { + if (*lineptr == ',') { + *lineptr = '\0'; + lineptr++; + break; + } + lineptr++; + } + + switch (count++) { + // Ethernet address + case 1: + strcpy(client_curr->etheraddr, word); + break; + + // IP address + case 2: + strcpy(client_curr->ipaddr, word); + break; + + // Start time + case 3: + client_curr->time_start = parse_time(word); + break; + + // Expire duration + case 4: + client_curr->expires = atoi(word); + break; + + default: + break; + } + } + } + + if (f) + fclose(f); + + return client_first; +} + +static void flush_chains() { + // filter + safe_system(IPTABLES " -F CAPTIVE_PORTAL"); + safe_system(IPTABLES " -F CAPTIVE_PORTAL_CLIENTS"); + + // nat + safe_system(IPTABLES " -t nat -F CAPTIVE_PORTAL"); +} + +static int setup_dns_filters() { + const char* protos[] = { "udp", "tcp", NULL }; + + // Limits the number of DNS requests to 3 kByte/s + // A burst of 1MB is permitted at the start + const char* limiter = "-m hashlimit --hashlimit-name dns-filter" + " --hashlimit-mode srcip --hashlimit-upto 3kb/sec --hashlimit-burst 1024kb"; + + char command[STRING_SIZE]; + + const char** proto = protos; + while (*proto) { + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS -p %s" + " --dport 53 %s -j RETURN", *proto, limiter); + + int r = safe_system(command); + if (r) + return r; + + proto++; + } + + return 0; +} + +static int add_client_rules(const client_t* clients) { + char command[STRING_SIZE]; + char match[STRING_SIZE]; + + while (clients) { + size_t len = 0; + + if (*clients->ipaddr && clients->expires > 0) { + len += snprintf(match + len, sizeof(match) - len, + "-s %s", clients->ipaddr); + } + + len += snprintf(match + len, sizeof(match) - len, + " -m mac --mac-source %s", clients->etheraddr); + + if (clients->expires > 0) { + time_t expires = clients->time_start + clients->expires; + + char* time_start = format_time(&clients->time_start); + char* time_end = format_time(&expires); + + len += snprintf(match + len, sizeof(match) - len, + " -m time --datestart %s --datestop %s", + time_start, time_end); + + free(time_start); + free(time_end); + } + + // filter + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS" + " %s -j RETURN", match); + safe_system(command); + + // nat + snprintf(command, sizeof(command), IPTABLES " -t nat -A CAPTIVE_PORTAL" + " %s -j RETURN", match); + safe_system(command); + + // Move on to the next client + clients = clients->next; + } + + return 0; +} + +static char* get_key(struct keyvalue* settings, char* key) { + char value[STRING_SIZE]; + + if (!findkey(settings, key, value)) + return NULL; + + return strdup(value); +} + +static int add_interface_rule(const char* intf, int allow_webif_access) { + int r; + char command[STRING_SIZE]; + + if ((intf == NULL) || (strlen(intf) == 0)) { + fprintf(stderr, "Empty interface given\n"); + return -1; + } + + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL -i %s" + " -j CAPTIVE_PORTAL_CLIENTS", intf); + r = safe_system(command); + if (r) + return r; + +#if 0 + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL -o %s" + " -j CAPTIVE_PORTAL_CLIENTS", intf); + r = safe_system(command); + if (r) + return r; +#endif + + if (allow_webif_access) { + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS" + " -i %s -p tcp --dport 444 -j RETURN", intf); + r = safe_system(command); + if (r) + return r; + } + + // Redirect all unauthenticated clients + snprintf(command, sizeof(command), IPTABLES " -t nat -A CAPTIVE_PORTAL -i %s" + " -p tcp --dport %d -j REDIRECT --to-ports %d", intf, HTTP_PORT, REDIRECT_PORT); + r = safe_system(command); + if (r) + return r; + + // Allow access to captive portal site + snprintf(command, sizeof(command), IPTABLES " -A CAPTIVE_PORTAL_CLIENTS" + " -i %s -p tcp --dport %d -j RETURN", intf, REDIRECT_PORT); + r = safe_system(command); + if (r) + return r; + + return 0; +} + +static int add_interface_rules(struct keyvalue* captive_portal_settings, struct keyvalue* ethernet_settings) { + const char* intf; + char* setting; + int r = 0; + + setting = get_key(captive_portal_settings, "ENABLE_GREEN"); + if (setting && (strcmp(setting, "on") == 0)) { + free(setting); + + intf = get_key(ethernet_settings, "GREEN_DEV"); + r = add_interface_rule(intf, /* allow webif access from green */ 1); + if (r) + return r; + } + + setting = get_key(captive_portal_settings, "ENABLE_BLUE"); + if (setting && (strcmp(setting, "on") == 0)) { + free(setting); + + intf = get_key(ethernet_settings, "BLUE_DEV"); + r = add_interface_rule(intf, /* do not allow webif access */ 0); + if (r) + return r; + } + + // Always pass DNS packets through all firewall rules + r = setup_dns_filters(); + if (r) + return r; + + // Add the last rule + r = safe_system(IPTABLES " -A CAPTIVE_PORTAL_CLIENTS -j DROP"); + if (r) + return r; + + return r; +} + +int main(int argc, char** argv) { + int r = 0; + char* intf = NULL; + client_t* clients = NULL; + + struct keyvalue* captive_portal_settings = NULL; + struct keyvalue* ethernet_settings = NULL; + + if (!(initsetuid())) + exit(2); + + ethernet_settings = initkeyvalues(); + if (!readkeyvalues(ethernet_settings, ETHERNET_SETTINGS)) { + fprintf(stderr, "Could not read %s\n", ETHERNET_SETTINGS); + r = 1; + goto END; + } + + captive_portal_settings = initkeyvalues(); + if (!readkeyvalues(captive_portal_settings, CAPTIVE_PORTAL_SETTINGS)) { + fprintf(stderr, "Could not read %s\n", CAPTIVE_PORTAL_SETTINGS); + r = 1; + goto END; + } + + clients = read_clients(CLIENTS); + + // Clean up all old rules + flush_chains(); + + // Add all client rules + r = add_client_rules(clients); + if (r) + goto END; + + // Add all interface rules + r = add_interface_rules(captive_portal_settings, ethernet_settings); + if (r) + goto END; + +END: + while (clients) { + client_t* head = clients; + clients = clients->next; + + free(head); + } + + if (ethernet_settings) + freekeyvalues(ethernet_settings); + + if (captive_portal_settings) + freekeyvalues(captive_portal_settings); + + if (intf) + free(intf); + + return r; +} diff --git a/src/misc-progs/wirelessctrl.c b/src/misc-progs/wirelessctrl.c index 1e166eb3d..7cffc89df 100644 --- a/src/misc-progs/wirelessctrl.c +++ b/src/misc-progs/wirelessctrl.c @@ -42,6 +42,7 @@ int main(void) { char buffer[STRING_SIZE]; char *index, *ipaddress, *macaddress, *enabled; struct keyvalue *kv = NULL; + struct keyvalue* captive_settings = NULL; if (!(initsetuid())) exit(1); @@ -67,6 +68,13 @@ int main(void) { exit(1); } + // Read captive portal settings + captive_settings = initkeyvalues(); + if (!readkeyvalues(captive_settings, CONFIG_ROOT "/captive/settings")) { + fprintf(stderr, "Could not read captive portal settings\n"); + exit(1); + } + /* Get the BLUE interface details */ if (findkey(kv, "BLUE_DEV", blue_dev) > 0) { if ((strlen(blue_dev) > 0) && !VALID_DEVICE(blue_dev)) { @@ -79,6 +87,15 @@ int main(void) { exit(0); } + // Check if the captive portal is enabled on blue. If so, we will + // just keep the chains flushed and do not add any rules. + char captive_enabled[STRING_SIZE]; + if (findkey(captive_settings, "ENABLE_BLUE", captive_enabled) > 0) { + if (strcmp(captive_enabled, "on") == 0) { + return 0; + } + } + if ((fd = fopen(CONFIG_ROOT "/wireless/nodrop", "r"))) return 0; diff --git a/src/scripts/captive-cleanup b/src/scripts/captive-cleanup new file mode 100755 index 000000000..c39e4883a --- /dev/null +++ b/src/scripts/captive-cleanup @@ -0,0 +1,46 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2016 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; + +require '/var/ipfire/general-functions.pl'; + +my %settings=(); +my %clientshash=(); +my $settingsfile="${General::swroot}/captive/settings"; +my $clients="${General::swroot}/captive/clients"; +my $time; +my $expiretime; + +if (-f $settingsfile && -f $clients && ! -z $clients){ + &General::readhash("$settingsfile", \%settings) if(-f $settingsfile); + &General::readhasharray("$clients", \%clientshash); + $time = time(); + foreach my $key (keys %clientshash) { + $expiretime=($clientshash{$key}[2])+$clientshash{$key}[3]; + if ($expiretime < $time){ + delete $clientshash{$key}; + my $exp = gmtime($expiretime); + &General::log("Captive", "Delete expired voucher $clientshash{$key}[4] expired on $exp. Remark: $clientshash{$key}[5]"); + } + } + &General::writehasharray("$clients", \%clientshash); +}