/root/.bash_history
/var/ipfire/ethernet/aliases
/var/ipfire/ethernet/wireless
+/var/ipfire/captive/*
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;
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;
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 (<FILE>) {
+ 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
# 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
--- /dev/null
+Listen 1013
+
+<VirtualHost *: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
+
+ <Directory /srv/web/ipfire/cgi-bin/captive>
+ Options ExecCGI
+ Require all granted
+ </Directory>
+
+ <Directory /srv/web/ipfire/html/captive>
+ Options +FollowSymlinks
+ Require all granted
+ </Directory>
+</VirtualHost>
'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',
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
#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
#usr/share/man/man8/rotatelogs.8
#usr/share/man/man8/suexec.8
var/log/httpd
+var/log/httpd/captive
--- /dev/null
+#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
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
#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
#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
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
#sbin
#srv
#usr/bin
+usr/bin/captive-cleanup
#usr/bin/perl
#usr/include
#usr/lib
--- /dev/null
+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
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
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
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
#sbin
#srv
#usr/bin
+usr/bin/captive-cleanup
#usr/bin/perl
#usr/include
#usr/lib
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
# Checking cgi-bin translations for language: en #
############################################################################
< addon
+< Captive clients
+< Captive genvoucher
+< Captive logo_upload
+< Captive logo_upload1
< ccd maxclients
< ovpn_fragment
############################################################################
< 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
< drop action2
< drop forward
< drop outgoing
+< eight hours
< email config
< email empty field
< email error
< 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
< drop action2
< drop forward
< drop outgoing
+< eight hours
< email config
< email empty field
< email error
< 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
< drop action2
< drop forward
< drop outgoing
+< eight hours
< email config
< email empty field
< email error
< 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
< drop forward
< drop outgoing
< Edit an existing route
+< eight hours
< email config
< email empty field
< email error
--- /dev/null
+#!/usr/bin/perl
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2016 IPFire Team <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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+#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 <<END
+ <form method='post' action='$ENV{'SCRIPT_NAME'}' enctype="multipart/form-data">\n
+ <table width='100%' border="0">
+ <tr>
+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 "<td width='30%'>$Lang::tr{'Captive active on'} <font color='$Header::colourgreen'>Green</font></td><td><input type='checkbox' name='ENABLE_GREEN' $checked{'ENABLE_GREEN'}{'on'} /></td></tr>";
+}
+if ($netsettings{'BLUE_DEV'}){
+ print "<td width='30%'>$Lang::tr{'Captive active on'} <font color='$Header::colourblue'>Blue</font></td><td><input type='checkbox' name='ENABLE_BLUE' $checked{'ENABLE_BLUE'}{'on'} /></td></tr>";
+}
+
+print<<END
+ </tr>
+ <tr>
+ <td>
+ $Lang::tr{'Captive authentication'}
+ </td>
+ <td>
+ <select name='AUTH'>
+ <option value="TERMS" $selected{'AUTH'}{'TERMS'} >$Lang::tr{'Captive terms'}</option>
+ <option value="COUPON" $selected{'AUTH'}{'COUPON'}>$Lang::tr{'Captive coupon'}</option>
+ </select>
+ </td>
+ </tr>
+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;
+ <tr>
+ <td></td>
+ <td>
+ <textarea cols="50" rows="10" name="TERMS">$terms</textarea>
+ </td>
+ </tr>
+
+ <tr>
+ <td>$Lang::tr{'Captive client session expiry time'}</td>
+ <td>
+ <select name="SESSION_TIME">
+ <option value="0" $selected{'SESSION_TIME'}{'0'}>- $Lang::tr{'unlimited'} -</option>
+ <option value="3600" $selected{'SESSION_TIME'}{'3600'}>$Lang::tr{'one hour'}</option>
+ <option value="28800" $selected{'SESSION_TIME'}{'28800'}>$Lang::tr{'eight hours'}</option>
+ <option value="86400" $selected{'SESSION_TIME'}{'86400'}>$Lang::tr{'24 hours'}</option>
+ <option value="604800" $selected{'SESSION_TIME'}{'604800'}>$Lang::tr{'one week'}</option>
+ <option value="18144000" $selected{'SESSION_TIME'}{'18144000'}>$Lang::tr{'one month'}</option>
+ </select>
+ </td>
+ </tr>
+END
+}
+
+print<<END;
+ <tr>
+ <td colspan="2">
+ <br>
+ <strong>$Lang::tr{'Captive branding'}</strong>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ $Lang::tr{'Captive title'}
+ </td>
+ <td>
+ <input type='text' name='TITLE' value="$settings{'TITLE'}" size='40'>
+ </td>
+ </tr>
+ <tr>
+ <td>$Lang::tr{'Captive brand color'}</td>
+ <td>
+ <input type="color" name="COLOR" value="$settings{'COLOR'}">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ $Lang::tr{'Captive upload logo'}
+ </td>
+ <td>
+ <input type="file" name="logo">
+ <br>$Lang::tr{'Captive upload logo recommendations'}
+ </td>
+ </tr>
+END
+
+if (-e $logo) {
+ print <<END;
+ <tr>
+ <td>$Lang::tr{'Captive logo uploaded'}</td>
+ <td>$Lang::tr{'yes'}</td>
+ </tr>
+END
+}
+
+print <<END;
+ <tr>
+ <td></td>
+ <td align='right'>
+ <input type='submit' name='ACTION' value="$Lang::tr{'save'}"/>
+ </td>
+ </tr>
+ </table></form>
+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(<FILE>) {
+ 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 <<END;
+ <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+ <table border='0' width='100%'>
+ <tr>
+ <td width='30%'>
+ $Lang::tr{'Captive vouchervalid'}
+ </td>
+ <td width='70%'>
+ <table class='tbl' border='0' width='100%'>
+ <tr>
+ <th>$Lang::tr{'hours'}</th>
+ <th>$Lang::tr{'days'}</th>
+ <th>$Lang::tr{'weeks'}</th>
+ <th>$Lang::tr{'months'}</th>
+ <th></th>
+ </tr>
+END
+
+ #print hour-dropdownbox
+ my $hrs=3600;
+ print "<tr height='40px'><td><select name='EXP_HOUR' style='width:8em;'>";
+ print "<option value='0' ";
+ print " selected='selected'" if ($settings{'EXP_HOUR'} eq '0');
+ print ">--</option>";
+ for (my $i = 1; $i<25; $i++){
+ my $exp_sec = $i * $hrs;
+ print "<option value='$exp_sec' ";
+ print " selected='selected'" if ($settings{'EXP_HOUR'} eq $exp_sec);
+ print ">$i</option>";
+ }
+ print "</td><td>";
+
+ #print day-dropdownbox
+ my $days=3600*24;
+ print "<select name='EXP_DAY' style='width:8em;'>";
+ print "<option value='0' ";
+ print " selected='selected'" if ($settings{'EXP_DAY'} eq '0');
+ print ">--</option>";
+ for (my $i = 1; $i<8; $i++){
+ my $exp_sec = $i * $days;
+ print "<option value='$exp_sec' ";
+ print " selected='selected'" if ($settings{'EXP_DAY'} eq $exp_sec);
+ print ">$i</option>";
+ }
+ print "</td><td>";
+
+ #print week-dropdownbox
+ my $week=3600*24*7;
+ print "<select name='EXP_WEEK' style='width:8em;'>";
+ print "<option value='0' ";
+ print " selected='selected'" if ($settings{'EXP_WEEK'} eq '0');
+ print ">--</option>";
+ for (my $i = 1; $i<5; $i++){
+ my $exp_sec = $i * $week;
+ print "<option value='$exp_sec' ";
+ print " selected='selected'" if ($settings{'EXP_WEEK'} eq $exp_sec);
+ print ">$i</option>";
+ }
+ print "</td><td>";
+
+ #print month-dropdownbox
+ my $month=3600*24*30;
+ print "<select name='EXP_MONTH' style='width:8em;'>";
+ print "<option value='0' ";
+ print " selected='selected'" if ($settings{'EXP_MONTH'} eq '0');
+ print ">--</option>";
+ for (my $i = 1; $i<13; $i++){
+ my $exp_sec = $i * $month;
+ print "<option value='$exp_sec' ";
+ print " selected='selected'" if ($settings{'EXP_MONTH'} eq $exp_sec);
+ print ">$i</option>";
+ }
+ print <<END;
+ </td>
+ <td>
+ <label>
+ <input type='checkbox' name='UNLIMITED' $checked{'UNLIMITED'}{'on'} />
+ $Lang::tr{'Captive nolimit'}
+ </label>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>$Lang::tr{'remark'}</td>
+ <td>
+ <input type='text' style='width: 98%;' name='REMARK' align='left'>
+ </td>
+ </tr>
+ </table>
+
+ <div align="right">
+ <select name="COUNT">
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="20">20</option>
+ <option value="50">50</option>
+ <option value="100">100</option>
+ </select>
+
+ <input type="submit" name="ACTION" value="$Lang::tr{'Captive generate coupon'}">
+ </div>
+ </form>
+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 <<END;
+ <table class='tbl' border='0'>
+ <tr>
+ <th align='center' width='15%'>
+ $Lang::tr{'Captive coupon'}
+ </th>
+ <th align='center' width='15%'>$Lang::tr{'Captive expiry time'}</th>
+ <th align='center' width='65%'>$Lang::tr{'remark'}</th>
+ <th align='center' width='5%'>$Lang::tr{'delete'}</th>
+ </tr>
+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 <<END;
+ <tr>
+ <td $col align="center">
+ <b>$couponhash{$key}[1]</b>
+ </td>
+ <td $col align="center">
+ $expirytime
+ </td>
+ <td $col align="center">
+ $couponhash{$key}[3]
+ </td>
+ <td $col align="center">
+ <form method='post'>
+ <input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />
+ <input type='hidden' name='ACTION' value='delete-coupon' />
+ <input type='hidden' name='key' value='$couponhash{$key}[0]' />
+ </form>
+ </td>
+ </tr>
+END
+ }
+
+ print "</table>";
+
+ &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 <<END;
+ <table class='tbl' width='100%'>
+ <tr>
+ <th align='center' width='15%'>$Lang::tr{'Captive coupon'}</th>
+ <th align='center' width='15%'>$Lang::tr{'Captive activated'}</th>
+ <th align='center' width='15%'>$Lang::tr{'Captive expiry time'}</th>
+ <th align='center' width='10%'>$Lang::tr{'Captive mac'}</th>
+ <th align='center' width='43%'>$Lang::tr{'remark'}</th>
+ <th align='center' width='5%'>$Lang::tr{'delete'}</th>
+ </tr>
+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 <<END;
+ <tr>
+ <td $col align="center"><b>$coupon</b></td>
+ <td $col align="center">$starttime</td>
+ <td $col align="center">$endtime</td>
+ <td $col align="center">$clientshash{$key}[0]</td>
+ <td $col align="center">$clientshash{$key}[5]</td>
+ <td $col align="center">
+ <form method='post'>
+ <input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />
+ <input type='hidden' name='ACTION' value='delete-client' />
+ <input type='hidden' name='key' value='$clientshash{$key}[0]' />
+ </form>
+ </td>
+ </tr>
+END
+ }
+
+ print "</table>";
+
+ &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();
--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+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<p>/g;
+
+ return $terms;
+}
--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+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);
--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+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";
my %sections = (
'auth' => '(\w+\(pam_unix\)\[.*\]: )',
'wio' => '(wio|wio\[.*\])',
+ 'captive' => '(Captive:)',
'clamav' => '(clamd\[.*\]: |freshclam\[.*\]: )',
'collectd' => '(collectd\[.*\]: )',
'cron' => '(fcron\[.*\]: )',
my %trsections = (
'auth' => "$Lang::tr{'loginlogout'}",
'wio' => 'Who Is Online?',
+ 'captive' => $Lang::tr{'captive'},
'clamav' => 'ClamAV',
'collectd' => 'Collectd',
'cron' => 'Cron',
--- /dev/null
+@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;
+}
--- /dev/null
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title><TMPL_VAR NAME="TITLE"></title>
+
+ <link rel="stylesheet" href="../assets/bootstrap-reboot.min.css">
+ <link rel="stylesheet" href="../assets/bootstrap-grid.min.css">
+ <link rel="stylesheet" href="../assets/captive.css">
+
+ <TMPL_IF NAME="COLOR">
+ <style>
+ .box-block {
+ background-color: <TMPL_VAR NAME="COLOR">;
+ }
+ </style>
+ </TMPL_IF>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ </head>
+
+ <body>
+ <div class="container content">
+ <div class="row">
+ <div class="col-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2">
+ <div class="box">
+ <div class="box-header">
+ <h1><TMPL_VAR NAME="TITLE"></h1>
+ </div>
+
+ <div class="box-block">
+ <h4><TMPL_VAR NAME="L_HEADING"></h4>
+
+ <form action="" method="POST">
+ <input type="hidden" name="ACTION" value="SUBMIT">
+ <input type="hidden" name="redirect" value="<TMPL_VAR NAME="REDIRECT">">
+
+ <TMPL_IF NAME="COUPON">
+ <input class="form-text <TMPL_IF NAME="ERROR">form-error</TMPL_IF>" type="text" name="COUPON">
+ <input class="form-submit" type="submit"
+ value="<TMPL_VAR NAME="L_ACTIVATE">">
+ <TMPL_ELSE>
+ <div class="checkbox">
+ <label>
+ <input class="form-checkbox <TMPL_IF NAME="ERROR">error</TMPL_IF>" type="checkbox" name="TERMS">
+ <TMPL_VAR NAME="L_AGREE_TERMS">
+ </label>
+ </div>
+
+ <input class="form-submit" type="submit"
+ value="<TMPL_VAR NAME="L_GAIN_ACCESS">">
+ </TMPL_IF>
+
+ <TMPL_IF NAME="ERROR">
+ <div class="text-error">
+ <TMPL_VAR NAME="ERROR">
+ </div>
+ </TMPL_IF>
+ </form>
+ </div>
+
+ <TMPL_IF NAME="TERMS">
+ <TMPL_VAR NAME="TERMS">
+ </TMPL_IF>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <footer>
+ <div class="container">
+ <div class="footer">
+ <img class="logo" src="../assets/ipfire.png" alt="IPFire Logo">
+ Powered by IPFire
+ </div>
+ </div>
+ </footer>
+ </body>
+</html>
'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 <u>eine</u> der untenstehenden Regeln aus.',
'Class' => 'Klasse',
'Class was deleted' => 'wurde mit eventuell vorhandenen Unterklassen gelöscht',
'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',
%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 <u>one</u> of the following rules.',
'Class' => 'Class',
'Class was deleted' => 'with potential subclasses was deleted',
'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',
'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',
'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.',
'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',
'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.',
'unix password sync' => 'Unix Password Sync',
'unix shell' => 'UNIX Shell',
'unknown' => 'UNKNOWN',
+'unlimited' => 'Unlimited',
'unnamed' => 'Unnamed',
'update' => 'Update',
'update accelerator' => 'Update Accelerator',
'week' => 'Week',
'week-graph' => 'Week',
'weekly firewallhits' => 'weekly firewallhits',
-'weeks' => 'weeks',
+'weeks' => 'Weeks',
'wildcards' => 'Wildcards',
'wins server' => 'Wins Server',
'wins support' => 'Wins Support',
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)
--- /dev/null
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2007-2016 IPFire Team <info@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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+###############################################################################
+# 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)
@$(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 \
# 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 \
# 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
--- /dev/null
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2007-2017 IPFire Team <info@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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+###############################################################################
+# 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)
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)
lfsmake2 web-user-interface
lfsmake2 flag-icons
lfsmake2 jquery
+ lfsmake2 bootstrap
lfsmake2 arping
lfsmake2 beep
lfsmake2 dvdrtools
lfsmake2 openssh
lfsmake2 fontconfig
lfsmake2 dejavu-fonts-ttf
+ lfsmake2 ubuntu-font-family
lfsmake2 freefont
lfsmake2 pixman
lfsmake2 cairo
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
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
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))
--- /dev/null
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#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;
+}
char buffer[STRING_SIZE];
char *index, *ipaddress, *macaddress, *enabled;
struct keyvalue *kv = NULL;
+ struct keyvalue* captive_settings = NULL;
if (!(initsetuid()))
exit(1);
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)) {
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;
--- /dev/null
+#!/usr/bin/perl
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2016 IPFire Team <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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+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);
+}