#!/usr/bin/perl
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2016 Alexander Marx alexander.marx@ipfire.org #
# #
# This program is free software you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see . #
# #
###############################################################################
use strict;
use CGI ':standard';
use URI::Escape;
use HTML::Entities();
use HTML::Template;
# enable only the following on debugging purpose
#use warnings;
#use CGI::Carp 'fatalsToBrowser';
require '/var/ipfire/general-functions.pl';
require "${General::swroot}/lang.pl";
#Set Variables
my %voucherhash=();
my %clientshash=();
my %cgiparams=();
my %settings=();
my $voucherout="${General::swroot}/captive/voucher_out";
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 "VOUCHER") {
&General::readhasharray("$voucherout", \%voucherhash);
# Convert voucher input to uppercase
$cgiparams{'VOUCHER'} = uc $cgiparams{'VOUCHER'};
# Walk through all valid vouchers and find the right one
my $found = 0;
foreach my $voucher (keys %voucherhash) {
if ($voucherhash{$voucher}[1] eq $cgiparams{'VOUCHER'}) {
$found = 1;
# Copy expiry time
$clientshash{$key}[3] = $voucherhash{$voucher}[2];
# Save voucher code
$clientshash{$key}[4] = $cgiparams{'VOUCHER'};
# Copy voucher remark
$clientshash{$key}[5] = $voucherhash{$voucher}[3];
# Delete used voucher
delete $voucherhash{$voucher};
&General::writehasharray("$voucherout", \%voucherhash);
last;
}
}
if ($found == 1) {
&General::log("Captive", "Internet access granted via voucher ($clientshash{$key}[4]) for $ip_address until $clientshash{$key}[3]");
} else {
$errormessage = $Lang::tr{"Captive invalid_voucher"};
}
# License
} else {
# Copy expiry time
$clientshash{$key}[3] = $settings{'EXPIRE'};
# No voucher code
$clientshash{$key}[4] = "LICENSE";
&General::log("Captive", "Internet access granted via license agreement for $ip_address until $clientshash{$key}[3]");
}
# 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 => $url);
# Voucher
if ($settings{'AUTH'} eq "VOUCHER") {
$tmpl->param(VOUCHER => 1);
}
$tmpl->param(TITLE => $settings{'TITLE'});
$tmpl->param(ERROR => $errormessage);
$tmpl->param(TAC => &gettac());
# Some translated strings
$tmpl->param(L_ACTIVATE => $Lang::tr{'Captive ACTIVATE'});
$tmpl->param(L_GAIN_ACCESS => $Lang::tr{'Captive GAIN ACCESS'});
$tmpl->param(L_HEADING_TAC => $Lang::tr{'Captive heading tac'});
$tmpl->param(L_HEADING_VOUCHER => $Lang::tr{'Captive heading voucher'});
$tmpl->param(L_AGREE_TAC => $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 gettac() {
my @tac = ();
open(my $handle, "<:utf8", "/var/ipfire/captive/agb.txt" ) or die("$!");
while(<$handle>) {
$_ = HTML::Entities::decode_entities($_);
push(@tac, $_);
}
close($handle);
my $tac = join("\n", @tac);
# Format paragraphs
$tac =~ s/\n\n/<\/p>\n
/g;
return $tac;
}