#!/usr/bin/perl ############################################################################### # # # IPFire.org - A linux based firewall # # Copyright (C) 2012 IPFire Team # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # # # ############################################################################### # DEVICE,ENABLED,MODE,WPA_MODE,SSID,PSK,PRIO,AUTH,ANONYMOUS,IDENTITY,PASSWORD # wlan0,on,WPA2,,Use This One Mum,ThisIsTheKey,2,TTLS,anonymous,username,password use strict; # 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"; #workaround to suppress a warning when a variable is used only once my @dummy = ( ${Header::colouryellow} ); undef (@dummy); # Files used my $setting = "${General::swroot}/main/settings"; our $datafile = "${General::swroot}/ethernet/wireless"; my %color = (); my %mainsettings = (); &General::readhash("${General::swroot}/main/settings", \%mainsettings); &General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); our %settings = (); our %netsettings = (); $settings{'ID'} = ''; $settings{'INTERFACE'} = ''; $settings{'ENABLED'} = ''; $settings{'ENCRYPTION'} = ''; $settings{'WPA_MODE'} = ''; $settings{'SSID'} = ''; $settings{'PSK'} = ''; $settings{'PRIO'} = ''; $settings{'ACTION'} = ''; # add/edit/remove $settings{'ID'} = ''; # point record for ACTION my $errormessage = ''; my $warnmessage = ''; &Header::showhttpheaders(); #Get GUI values &Header::getcgihash(\%settings); # Load multiline data our @configs = (); if (open(FILE, "$datafile")) { @configs = ; close (FILE); } &General::readhash("${General::swroot}/main/settings", \%settings); &General::readhash("${General::swroot}/ethernet/settings", \%netsettings); # Toggle enable/disable field. if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) { my @update; foreach my $line (@configs) { chomp($line); my @config = split(/\,/, $line); # Update the entry with the matching ID. if ($config[0] eq $settings{'ID'}) { # Toggle enabled/disabled status. if ($config[2] eq 'on') { $config[2] = 'off'; } else { $config[2] = 'on'; } $line = join(',', @config); } push(@update, $line."\n"); } # Save updated configuration settings. open(FILE, ">$datafile") or die 'wlan client datafile error'; print FILE @update; close(FILE); @configs = @update; # Update configuration files. &BuildConfiguration(); # Reset ACTION. $settings{'ACTION'} = ''; } if ($settings{'ACTION'} eq $Lang::tr{'add'}) { # Validate input data. $errormessage = ValidateInput("add"); unless ($errormessage) { # Search for the next free id. my $next_id = NextID(); my @config = ($next_id); push(@config, $settings{'INTERFACE'}); push(@config, $settings{'ENABLED'}); push(@config, $settings{'ENCRYPTION'}); push(@config, $settings{'WPA_MODE'}); push(@config, $settings{'SSID'}); push(@config, $settings{'PSK'}); push(@config, $settings{'PRIO'}); push(@config, $settings{'AUTH'}); push(@config, $settings{'ANONYMOUS'}); push(@config, $settings{'IDENTITY'}); push(@config, $settings{'PASSWORD'}); # Add the new configuration and write all the stuff to the configuration file. my $line = join(',', @config) . "\n"; push(@configs, $line); # Save updated configuration settings. open(FILE, ">$datafile") or die 'wlan client datafile error'; print FILE @configs; close(FILE); # Update configuration files. &BuildConfiguration(); # Reset ACTION. $settings{'ACTION'} = ''; } } if ($settings{'ACTION'} eq $Lang::tr{'edit'}) { foreach my $line (@configs) { chomp($line); my @config = split(/\,/, $line); if ($config[0] eq $settings{'ID'}) { $settings{'ID'} = $config[0]; $settings{'INTERFACE'} = $config[1]; $settings{'ENABLED'} = $config[2]; $settings{'ENCRYPTION'} = $config[3]; $settings{'WPA_MODE'} = $config[4]; $settings{'SSID'} = $config[5]; $settings{'PSK'} = $config[6]; $settings{'PRIO'} = $config[7]; $settings{'AUTH'} = $config[8]; $settings{'ANONYMOUS'} = $config[9]; $settings{'IDENTITY'} = $config[10]; $settings{'PASSWORD'} = $config[11]; } } } if ($settings{'ACTION'} eq $Lang::tr{'update'}) { $errormessage = ValidateInput("update"); unless ($errormessage) { my @update; foreach my $line (@configs) { chomp($line); my @config = split(/\,/, $line); # Update the entry with the matching ID. if ($config[0] eq $settings{'ID'}) { # Update all configuration settings. # ID and INTERFACE cannot be changed. $config[2] = $settings{'ENABLED'}; $config[3] = $settings{'ENCRYPTION'}; $config[4] = $settings{'WPA_MODE'}; $config[5] = $settings{'SSID'}; $config[6] = $settings{'PSK'}; $config[7] = $settings{'PRIO'}; $config[8] = $settings{'AUTH'}; $config[9] = $settings{'ANONYMOUS'}; $config[10] = $settings{'IDENTITY'}; $config[11] = $settings{'PASSWORD'}; $line = join(',', @config); } push(@update, $line."\n"); } # Save updated configuration settings. open(FILE, ">$datafile") or die 'wlan client datafile error'; print FILE @update; close(FILE); @configs = @update; # Update configuration files. &BuildConfiguration(); # Reset ACTION. $settings{'ACTION'} = ''; } } if ($settings{'ACTION'} eq $Lang::tr{'remove'}) { my @update; foreach my $line (@configs) { chomp($line); my @config = split(/\,/, $line); # Skip the to be removed entry. if ($config[0] eq $settings{'ID'}) { next; } push(@update, $line."\n"); } # Save updated configuration settings. open(FILE, ">$datafile") or die 'wlan client datafile error'; print FILE @update; close(FILE); @configs = @update; # Update configuration files. &BuildConfiguration(); # Reset ACTION. $settings{'ACTION'} = ''; } if ($settings{'ACTION'} eq '') { # First launch from GUI &showMainBox(); } else { # Action has been set, so show the edit box. &showEditBox(); } sub showMainBox() { &Header::openpage($Lang::tr{'wlan client configuration'}, 1, ''); &Header::openbigbox('100%', 'left', '', $errormessage); &Header::openbox('100%', 'left', $Lang::tr{'wlan client configuration'}); print <


END # # Print each line of @configs list # my $key = 0; my $col=""; foreach my $line (@configs) { # Skip commented lines. my $firstchar = substr($line, 0, 1); next if ($firstchar eq "#"); chomp($line); my @config = split(/\,/,$line); #Choose icon for checkbox my $gif = ''; my $gdesc = ''; if ($config[2] eq 'on' ) { $gif = 'on.gif'; $gdesc = $Lang::tr{'click to disable'}; } else { $gif = 'off.gif'; $gdesc = $Lang::tr{'click to enable'}; } # Colorize each line if ($key % 2) { print ""; $col="bgcolor='$color{'color20'}'"; } else { print ""; $col="bgcolor='$color{'color22'}'"; } my $encryption_mode = $Lang::tr{'unknown'}; if ($config[3] eq "NONE") { $encryption_mode = $Lang::tr{'wlan client encryption none'}; } elsif ($config[3] eq "WEP") { $encryption_mode = $Lang::tr{'wlan client encryption wep'}; } elsif ($config[3] eq "WPA") { $encryption_mode = $Lang::tr{'wlan client encryption wpa'}; } elsif ($config[3] eq "WPA2") { $encryption_mode = $Lang::tr{'wlan client encryption wpa2'}; } elsif ($config[3] eq "EAP") { $encryption_mode = $Lang::tr{'wlan client encryption eap'}; } if ($config[3] eq "EAP") { if ($config[8] eq "PEAP") { $encryption_mode .= " ($Lang::tr{'wlan client auth peap'})"; } elsif ($config[8] eq "TTLS") { $encryption_mode .= " ($Lang::tr{'wlan client auth ttls'})"; } else { $encryption_mode .= " ($Lang::tr{'wlan client auth auto'})"; } $encryption_mode .= "
"; if ($config[10]) { $encryption_mode .= "$Lang::tr{'wlan client identity'}: "; $encryption_mode .= $config[10]; } # Anonymous identity if ($config[9]) { $encryption_mode .= "
"; $encryption_mode .= "$Lang::tr{'wlan client anonymous identity'}: "; $encryption_mode .= $config[9]; } } elsif (($config[3] eq "WPA") || ($config[3] eq "WPA2")) { my $wpa_pairwise = "$Lang::tr{'wlan client ccmp'} $Lang::tr{'wlan client and'} $Lang::tr{'wlan client tkip'}"; my $wpa_group = "$Lang::tr{'wlan client ccmp'} $Lang::tr{'wlan client and'} $Lang::tr{'wlan client tkip'}"; if ($config[4] eq "CCMP-CCMP") { $wpa_pairwise = $Lang::tr{'wlan client ccmp'}; $wpa_group = $Lang::tr{'wlan client ccmp'}; } elsif ($config[4] eq "CCMP-TKIP") { $wpa_pairwise = $Lang::tr{'wlan client ccmp'}; $wpa_group = $Lang::tr{'wlan client tkip'}; } elsif ($config[4] eq "TKIP-TKIP") { $wpa_pairwise = $Lang::tr{'wlan client tkip'}; $wpa_group = $Lang::tr{'wlan client tkip'}; } $encryption_mode .= "
"; $encryption_mode .= "$Lang::tr{'wlan client pairwise key algorithm'}: "; $encryption_mode .= $wpa_pairwise; $encryption_mode .= "
"; $encryption_mode .= "$Lang::tr{'wlan client group key algorithm'}: "; $encryption_mode .= $wpa_group; } print <$config[5] END $key++; } print "
$Lang::tr{'wlan client ssid'} $Lang::tr{'wlan client encryption'} $Lang::tr{'priority'}
$encryption_mode $config[7]
"; # If table contains entries, print 'Key to action icons' if ($key) { print <  $Lang::tr{'legend'}:  $Lang::tr{ $Lang::tr{'click to disable'}    $Lang::tr{ $Lang::tr{'click to enable'}    $Lang::tr{ $Lang::tr{'edit'}    $Lang::tr{ $Lang::tr{'remove'} END } &Header::closebox(); # Show status box. &ShowStatus(); &Header::closebigbox(); &Header::closepage(); } sub showEditBox() { &Header::openpage($Lang::tr{'wlan client configuration'}, 1, ''); &Header::openbigbox('100%', 'left', '', $errormessage); if ($errormessage) { &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); print "$errormessage "; &Header::closebox(); } my $buttontext = $Lang::tr{'add'}; if ($settings{'ID'} ne '') { $buttontext = $Lang::tr{'update'}; &Header::openbox('100%', 'left', $Lang::tr{'wlan client edit entry'}); } else { &Header::openbox('100%', 'left', $Lang::tr{'wlan client new entry'}); $settings{'ENABLED'} = 'on'; } my $action = $buttontext; my %checked = (); $checked{'ENABLED'} = ($settings{'ENABLED'} ne 'on' ) ? '' : "checked='checked'"; my %selected = (); $selected{'ENCRYPTION'} = (); $selected{'ENCRYPTION'}{'NONE'} = ''; $selected{'ENCRYPTION'}{'WPA2'} = ''; $selected{'ENCRYPTION'}{'WPA'} = ''; $selected{'ENCRYPTION'}{'WEP'} = ''; $selected{'ENCRYPTION'}{$settings{'ENCRYPTION'}} = "selected='selected'"; $selected{'WPA_MODE'} = (); $selected{'WPA_MODE'}{''} = ''; $selected{'WPA_MODE'}{'CCMP-CCMP'} = ''; $selected{'WPA_MODE'}{'CCMP-TKIP'} = ''; $selected{'WPA_MODE'}{'TKIP-TKIP'} = ''; $selected{'WPA_MODE'}{$settings{'WPA_MODE'}} = "selected='selected'"; $selected{'AUTH'} = (); $selected{'AUTH'}{''} = ''; $selected{'AUTH'}{'PEAP'} = ''; $selected{'AUTH'}{'TTLS'} = ''; $selected{'AUTH'}{$settings{'AUTH'}} = "selected='selected'"; $selected{'PRIO'} = (); $selected{'PRIO'}{'0'} = ''; $selected{'PRIO'}{'1'} = ''; $selected{'PRIO'}{'2'} = ''; $selected{'PRIO'}{'3'} = ''; $selected{'PRIO'}{'4'} = ''; $selected{'PRIO'}{$settings{'PRIO'}} = "selected='selected'"; print <
$Lang::tr{'wlan client ssid'}: $Lang::tr{'enabled'}
$Lang::tr{'wlan client encryption'}:
$Lang::tr{'wlan client psk'}: 


$Lang::tr{'wlan client authentication settings'}:
$Lang::tr{'wlan client eap authentication method'}:
$Lang::tr{'wlan client anonymous identity'}:
$Lang::tr{'wlan client identity'}:
$Lang::tr{'wlan client password'}:


$Lang::tr{'wlan client advanced settings'}:
$Lang::tr{'wlan client wpa mode'}: ($Lang::tr{'wlan client pairwise key group key'})
$Lang::tr{'priority'}:


END &Header::closebox(); &Header::closebigbox(); &Header::closepage(); } sub ShowStatus() { my $device = $netsettings{'RED_DEV'}; # Exit if no device is configured. return if ($device eq ""); # Exit if wpa_supplicant is not running on this interface. #return if (! -e "/var/run/wpa_supplicant/$device"); open(FILE, "/usr/local/bin/wirelessclient status |"); my %status = (); while () { chomp($_); my ($key, $value) = split("=", $_); $status{$key} = $value; } close(FILE); # End here, if no there is no input. return if (!keys %status); &Header::openbox('100%', 'left', $Lang::tr{'status'}); if ($status{'ssid'} eq "") { print "

$Lang::tr{'wlan client disconnected'}

"; } else { print < $Lang::tr{'wlan client ssid'} $status{'ssid'} $Lang::tr{'wlan client bssid'} $status{'bssid'} END if ($status{'EAP state'}) { my $selected_method = $status{'selectedMethod'}; $selected_method =~ s/\d+ \((.*)\)/$1/e; print < $Lang::tr{'wlan client encryption eap'} $Lang::tr{'wlan client eap state'} $status{'EAP state'} $Lang::tr{'wlan client method'} $selected_method $Lang::tr{'wlan client tls version'} $status{'eap_tls_version'} $Lang::tr{'wlan client tls cipher'} $status{'EAP TLS cipher'} $Lang::tr{'wlan client eap phase2 method'} $status{"${selected_method}v0 Phase2 method"} END } if (($status{'pairwise_cipher'} ne "NONE") || ($status{'group_cipher'} ne "NONE")) { print < $Lang::tr{'wlan client encryption wpa'} $Lang::tr{'wlan client pairwise cipher'} $status{'pairwise_cipher'} $Lang::tr{'wlan client group cipher'} $status{'group_cipher'} END } print ""; } &Header::closebox(); } sub BuildConfiguration() { system("/usr/local/bin/wirelessclient restart"); } sub NextID() { my $highest_id = 0; foreach my $line (@configs) { # Skip commented lines. my $firstchar = substr($line, 0, 1); next if ($firstchar eq "#"); my @config = split(/\,/, $line); if ($config[0] > $highest_id) { $highest_id = $config[0]; } } return $highest_id + 1; } sub DuplicateSSID($) { my $ssid = shift; foreach my $line (@configs) { # Skip commented lines. my $firstchar = substr($line, 0, 1); next if ($firstchar eq "#"); my @config = split(/\,/, $line); if ($config[5] eq $ssid) { return 1; } } return 0; } sub ValidKeyLength($$) { my $algo = shift; my $key = shift; my $key_length = length($key); if ($algo eq "WEP") { # Key must be 13 or 26 characters. if (($key_length == 13) || ($key_length == 26)) { return 0; } return 1; } elsif (($algo eq "WPA2") || ($algo eq "WPA")) { # Key must be between 8 and 63 chars. if (($key_length >= 8) && ($key_length <= 63)) { return 0; } return 1; } # Say okay for all other algorithms. return 0; } sub ValidateInput($) { my $mode = shift; # Check for duplicate SSIDs. if (($mode eq "add") && (DuplicateSSID($settings{'SSID'}))) { return "$Lang::tr{'wlan client duplicate ssid'}: $settings{'SSID'}"; # Check for invalid key length. } elsif (ValidKeyLength($settings{'ENCRYPTION'}, $settings{'PSK'})) { return "$Lang::tr{'wlan client invalid key length'}"; } # Reset WPA mode, if WPA(2) is not selected. if (($settings{'ENCRYPTION'} ne "WPA") && ($settings{'ENCRYPTION'} ne "WPA2")) { $settings{'WPA_MODE'} = ''; } if ($settings{'ENABLED'} ne "") { $settings{'ENABLED'} = 'on'; } else { $settings{'ENABLED'} = 'off'; } return; }