captive: Refactor the access page
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / captive / index.cgi
1 #!/usr/bin/perl
2 ###############################################################################
3 #                                                                             #
4 # IPFire.org - A linux based firewall                                         #
5 # Copyright (C) 2016  Alexander Marx alexander.marx@ipfire.org                #
6 #                                                                             #
7 # This program is free software you can redistribute it and/or modify         #
8 # it under the terms of the GNU General Public License as published by        #
9 # the Free Software Foundation, either version 3 of the License, or           #
10 # (at your option) any later version.                                         #
11 #                                                                             #
12 # This program is distributed in the hope that it will be useful,             #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of              #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
15 # GNU General Public License for more details.                                #
16 #                                                                             #
17 # You should have received a copy of the GNU General Public License           #
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
19 #                                                                             #
20 ###############################################################################
21
22 use strict;
23 use CGI ':standard';
24 use URI::Escape;
25 use HTML::Entities();
26 use HTML::Template;
27
28 # enable only the following on debugging purpose
29 #use warnings;
30 #use CGI::Carp 'fatalsToBrowser';
31
32 require '/var/ipfire/general-functions.pl';
33 require "${General::swroot}/lang.pl";
34
35 #Set Variables
36 my %voucherhash=();
37 my %clientshash=();
38 my %cgiparams=();
39 my %settings=();
40 my $voucherout="${General::swroot}/captive/voucher_out";
41 my $clients="${General::swroot}/captive/clients";
42 my $settingsfile="${General::swroot}/captive/settings";
43 my $errormessage;
44 my $url=param('redirect');
45
46 #Create /var/ipfire/captive/clients if not exist
47 unless (-f $clients){ system("touch $clients"); }
48
49 #Get GUI variables
50 &getcgihash(\%cgiparams);
51
52 #Read settings
53 &General::readhash("$settingsfile", \%settings) if(-f $settingsfile);
54
55 # Actions
56 if ($cgiparams{'ACTION'} eq "SUBMIT") {
57         # Get client IP address
58         my $ip_address = $ENV{X_FORWARDED_FOR} || $ENV{REMOTE_ADDR};
59
60         # Retrieve the MAC address from the ARP table
61         my $mac_address = &Network::get_hardware_address($ip_address);
62
63         &General::readhasharray("$clients", \%clientshash);
64         my $key = &General::findhasharraykey(\%clientshash);
65
66         # Create a new client line
67         foreach my $i (0 .. 5) { $clientshash{$key}[$i] = ""; }
68
69         # MAC address of the client
70         $clientshash{$key}[0] = $mac_address;
71
72         # IP address of the client
73         $clientshash{$key}[1] = $ip_address;
74
75         # Current time
76         $clientshash{$key}[2] = time();
77
78         if ($settings{"AUTH"} eq "VOUCHER") {
79                 &General::readhasharray("$voucherout", \%voucherhash);
80
81                 # Convert voucher input to uppercase
82                 $cgiparams{'VOUCHER'} = uc $cgiparams{'VOUCHER'};
83
84                 # Walk through all valid vouchers and find the right one
85                 my $found = 0;
86                 foreach my $voucher (keys %voucherhash) {
87                         if ($voucherhash{$voucher}[1] eq $cgiparams{'VOUCHER'}) {
88                                 $found = 1;
89
90                                 # Copy expiry time
91                                 $clientshash{$key}[3] = $voucherhash{$voucher}[2];
92
93                                 # Save voucher code
94                                 $clientshash{$key}[4] = $cgiparams{'VOUCHER'};
95
96                                 # Copy voucher remark
97                                 $clientshash{$key}[5] = $voucherhash{$voucher}[3];
98
99                                 # Delete used voucher
100                                 delete $voucherhash{$voucher};
101                                 &General::writehasharray("$voucherout", \%voucherhash);
102
103                                 last;
104                         }
105                 }
106
107                 if ($found == 1) {
108                         &General::log("Captive", "Internet access granted via voucher ($clientshash{$key}[4]) for $ip_address until $clientshash{$key}[3]");
109                 } else {
110                         $errormessage = $Lang::tr{"Captive invalid_voucher"};
111                 }
112
113         # License
114         } else {
115                 # Copy expiry time
116                 $clientshash{$key}[3] = $settings{'EXPIRE'};
117
118                 # No voucher code
119                 $clientshash{$key}[4] = "LICENSE";
120
121                 &General::log("Captive", "Internet access granted via license agreement for $ip_address until $clientshash{$key}[3]");
122         }
123
124         # If no errors were found, save configruation and reload
125         if (!$errormessage) {
126                 &General::writehasharray("$clients", \%clientshash);
127
128                 system("/usr/local/bin/captivectrl");
129
130                 # Redirect client to the original URL
131                 print "Status: 302 Moved Temporarily\n";
132                 print "Location: $url\n";
133                 print "Connection: close\n\n";
134                 exit 0;
135         }
136 }
137
138 my $tmpl = HTML::Template->new(
139         filename => "/srv/web/ipfire/html/captive/template.html",
140         die_on_bad_params => 0
141 );
142
143 $tmpl->param(REDIRECT_URL => $url);
144
145 # Voucher
146 if ($settings{'AUTH'} eq "VOUCHER") {
147         $tmpl->param(VOUCHER  => 1);
148 }
149
150 $tmpl->param(TITLE => $settings{'TITLE'});
151 $tmpl->param(ERROR => $errormessage);
152
153 $tmpl->param(TAC => &gettac());
154
155 # Some translated strings
156 $tmpl->param(L_ACTIVATE        => $Lang::tr{'Captive ACTIVATE'});
157 $tmpl->param(L_GAIN_ACCESS     => $Lang::tr{'Captive GAIN ACCESS'});
158 $tmpl->param(L_HEADING_TAC     => $Lang::tr{'Captive heading tac'});
159 $tmpl->param(L_HEADING_VOUCHER => $Lang::tr{'Captive heading voucher'});
160 $tmpl->param(L_AGREE_TAC       => $Lang::tr{'Captive agree tac'});
161
162 # Print header
163 print "Pragma: no-cache\n";
164 print "Cache-control: no-cache\n";
165 print "Connection: close\n";
166 print "Content-type: text/html\n\n";
167
168 # Print rendered template
169 print $tmpl->output();
170
171 sub getcgihash {
172         my ($hash, $params) = @_;
173         my $cgi = CGI->new ();
174         $hash->{'__CGI__'} = $cgi;
175         return if ($ENV{'REQUEST_METHOD'} ne 'POST');
176         if (!$params->{'wantfile'}) {
177                 $CGI::DISABLE_UPLOADS = 1;
178                 $CGI::POST_MAX        = 1024 * 1024;
179         } else {
180                 $CGI::POST_MAX = 10 * 1024 * 1024;
181         }
182         $cgi->referer() =~ m/^http?\:\/\/([^\/]+)/;
183         my $referer = $1;
184         $cgi->url() =~ m/^http?\:\/\/([^\/]+)/;
185         my $servername = $1;
186         return if ($referer ne $servername);
187
188         ### Modified for getting multi-vars, split by |
189         my %temp = $cgi->Vars();
190         foreach my $key (keys %temp) {
191                 $hash->{$key} = $temp{$key};
192                 $hash->{$key} =~ s/\0/|/g;
193                 $hash->{$key} =~ s/^\s*(.*?)\s*$/$1/;
194         }
195
196         if (($params->{'wantfile'})&&($params->{'filevar'})) {
197                 $hash->{$params->{'filevar'}} = $cgi->upload
198                                                 ($params->{'filevar'});
199         }
200         return;
201 }
202
203 sub gettac() {
204         my @tac = ();
205
206         open(my $handle, "<:utf8", "/var/ipfire/captive/agb.txt" ) or die("$!");
207         while(<$handle>) {
208                 $_ = HTML::Entities::decode_entities($_);
209                 push(@tac, $_);
210         }
211         close($handle);
212
213         my $tac = join("\n", @tac);
214
215         # Format paragraphs
216         $tac =~ s/\n\n/<\/p>\n<p>/g;
217
218         return $tac;
219 }