captive: Get MAC address of a device without calling arp
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / captive / index.cgi
CommitLineData
8b920789
AM
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
22use strict;
23use CGI ':standard';
24use URI::Escape;
25use HTML::Entities();
a2c26388 26use HTML::Template;
e01c5ab7 27
8b920789
AM
28# enable only the following on debugging purpose
29#use warnings;
30#use CGI::Carp 'fatalsToBrowser';
31
32require '/var/ipfire/general-functions.pl';
33require "${General::swroot}/lang.pl";
34
35#Set Variables
36my %voucherhash=();
37my %clientshash=();
38my %cgiparams=();
39my %settings=();
40my $voucherout="${General::swroot}/captive/voucher_out";
41my $clients="${General::swroot}/captive/clients";
42my $settingsfile="${General::swroot}/captive/settings";
43my $redir=0;
44my $errormessage;
45my $url=param('redirect');
e01c5ab7 46
8b920789
AM
47#Create /var/ipfire/captive/clients if not exist
48unless (-f $clients){ system("touch $clients"); }
49
50#Get GUI variables
51&getcgihash(\%cgiparams);
52
53#Read settings
54&General::readhash("$settingsfile", \%settings) if(-f $settingsfile);
55
966971e5
MT
56# Actions
57if ($cgiparams{'ACTION'} eq "SUBMIT") {
8b920789
AM
58 #Get Clients IP-Address
59 my $ip_address = $ENV{X_FORWARDED_FOR} || $ENV{REMOTE_ADDR} ||"";
60
dbfd2622
MT
61 # Retrieve the MAC address from the ARP table
62 my $mac_address = &Network::get_hardware_address($ip_address);
8b920789
AM
63
64 &General::readhasharray("$clients", \%clientshash);
11fc9575 65 my $key = &General::findhasharraykey(\%clientshash);
8b920789
AM
66
67 if (!$errormessage){
e01c5ab7
AM
68 foreach my $i (0 .. 5) { $clientshash{$key}[$i] = "";}
69
70 $clientshash{$key}[0] = $mac_address; #mac address of actual client
71 $clientshash{$key}[1] = $ip_address; #ip address of actual client
72 $clientshash{$key}[2] = time(); #actual time in unix seconds (timestamp of first conenction)
73 $clientshash{$key}[3] = $settings{'EXPIRE'}; #Expire time in seconds (1day, 1 week ....)
74 $clientshash{$key}[4] = $Lang::tr{'Captive auth_lic'}; #Type of license (license or voucher)
75 $clientshash{$key}[5] = '';
76
8b920789
AM
77 &General::writehasharray("$clients", \%clientshash);
78 system("/usr/local/bin/captivectrl");
79 &General::log("Captive", "Internet Access granted via license-agreement for $ip_address until $clientshash{$key}[3]");
80 $redir=1;
81 }
82}
83
966971e5 84if ($cgiparams{'ACTION'} eq "SUBMIT") {
8b920789 85 my $ip_address;
5dc32e58 86 my $granted=0;
8b920789
AM
87 #Convert voucherinput to uppercase
88 $cgiparams{'VOUCHER'} = uc $cgiparams{'VOUCHER'};
89 #Get Clients IP-Address
90 $ip_address = $ENV{X_FORWARDED_FOR} || $ENV{REMOTE_ADDR} ||"";
91 #Ask arp to give the corresponding MAC-Address
dbfd2622 92 my $mac_address = &Network::get_hardware_address($ip_address);
8b920789
AM
93 #Check if voucher is valid and write client to clients file, delete voucher from voucherout
94 &General::readhasharray("$voucherout", \%voucherhash);
95 &General::readhasharray("$clients", \%clientshash);
96 foreach my $key (keys %voucherhash) {
97 if($voucherhash{$key}[1] eq $cgiparams{'VOUCHER'}){
98 #Voucher valid, write to clients, then delete from voucherout
8b920789 99 my $key1 = &General::findhasharraykey(\%clientshash);
e01c5ab7
AM
100 foreach my $i (0 .. 5) { $clientshash{$key1}[$i] = "";}
101
8b920789
AM
102 $clientshash{$key1}[0] = $mac_address;
103 $clientshash{$key1}[1] = $ip_address;
e01c5ab7 104 $clientshash{$key1}[2] = time();
c7e78cc6 105 $clientshash{$key1}[3] = $voucherhash{$key}[2];
8b920789 106 $clientshash{$key1}[4] = $cgiparams{'VOUCHER'};
c7e78cc6 107 $clientshash{$key1}[5] = HTML::Entities::decode_entities($voucherhash{$key}[3]);
e01c5ab7 108
8b920789 109 &General::writehasharray("$clients", \%clientshash);
8b920789
AM
110 &General::log("Captive", "Internet Access granted via voucher no. $clientshash{$key1}[4] for $ip_address until $clientshash{$key}[3] Remark: $clientshash{$key1}[7]");
111
112 delete $voucherhash{$key};
113 &General::writehasharray("$voucherout", \%voucherhash);
5dc32e58 114 $granted=1;
8b920789
AM
115 last;
116 }
117 }
5dc32e58
AM
118 if($granted==1){
119 system("/usr/local/bin/captivectrl");
120 $redir=1;
121 }else{
122 $errormessage="$Lang::tr{'Captive invalid_voucher'}";
123 }
8b920789
AM
124}
125
126if($redir == 1){
127 print "Status: 302 Moved Temporarily\n";
128 print "Location: $url\n";
129 print "Connection: close\n";
130 print "\n";
131 exit 0;
132}
8b920789
AM
133
134#Open HTML Page, load header and css
a2c26388
MT
135my $tmpl = HTML::Template->new(
136 filename => "/srv/web/ipfire/html/captive/template.html",
137 die_on_bad_params => 0
138);
8b920789 139
a2c26388 140$tmpl->param(REDIRECT_URL => $url);
8b920789 141
48fb1d3b
MT
142# Voucher
143if ($settings{'AUTH'} eq "VOUCHER") {
144 $tmpl->param(VOUCHER => 1);
145}
146
a2c26388
MT
147$tmpl->param(TITLE => $settings{'TITLE'});
148$tmpl->param(ERROR => $errormessage);
e01c5ab7 149
48fb1d3b
MT
150$tmpl->param(TAC => &gettac());
151
152# Some translated strings
153$tmpl->param(L_ACTIVATE => $Lang::tr{'Captive ACTIVATE'});
154$tmpl->param(L_GAIN_ACCESS => $Lang::tr{'Captive GAIN ACCESS'});
155$tmpl->param(L_HEADING_TAC => $Lang::tr{'Captive heading tac'});
156$tmpl->param(L_HEADING_VOUCHER => $Lang::tr{'Captive heading voucher'});
157$tmpl->param(L_AGREE_TAC => $Lang::tr{'Captive agree tac'});
158
a2c26388
MT
159# Print header
160print "Pragma: no-cache\n";
161print "Cache-control: no-cache\n";
162print "Connection: close\n";
163print "Content-type: text/html\n\n";
8b920789 164
a2c26388 165# Print rendered template
48fb1d3b 166print $tmpl->output();
8b920789
AM
167
168sub getcgihash {
169 my ($hash, $params) = @_;
170 my $cgi = CGI->new ();
171 $hash->{'__CGI__'} = $cgi;
172 return if ($ENV{'REQUEST_METHOD'} ne 'POST');
173 if (!$params->{'wantfile'}) {
174 $CGI::DISABLE_UPLOADS = 1;
175 $CGI::POST_MAX = 1024 * 1024;
176 } else {
177 $CGI::POST_MAX = 10 * 1024 * 1024;
178 }
179 $cgi->referer() =~ m/^http?\:\/\/([^\/]+)/;
180 my $referer = $1;
181 $cgi->url() =~ m/^http?\:\/\/([^\/]+)/;
182 my $servername = $1;
183 return if ($referer ne $servername);
184
185 ### Modified for getting multi-vars, split by |
186 my %temp = $cgi->Vars();
187 foreach my $key (keys %temp) {
188 $hash->{$key} = $temp{$key};
189 $hash->{$key} =~ s/\0/|/g;
190 $hash->{$key} =~ s/^\s*(.*?)\s*$/$1/;
191 }
192
193 if (($params->{'wantfile'})&&($params->{'filevar'})) {
194 $hash->{$params->{'filevar'}} = $cgi->upload
195 ($params->{'filevar'});
196 }
197 return;
198}
199
48fb1d3b
MT
200sub gettac() {
201 my @tac = ();
202
203 open(my $handle, "<:utf8", "/var/ipfire/captive/agb.txt" ) or die("$!");
204 while(<$handle>) {
205 $_ = HTML::Entities::decode_entities($_);
206 push(@tac, $_);
207 }
208 close($handle);
209
210 my $tac = join("\n", @tac);
211
212 # Format paragraphs
213 $tac =~ s/\n\n/<\/p>\n<p>/g;
214
215 return $tac;
8b920789 216}