diff options
author | Fil <fil.bergamo@riseup.net> | 2017-03-07 23:07:50 +0100 |
---|---|---|
committer | Fil <fil.bergamo@riseup.net> | 2017-03-07 23:07:50 +0100 |
commit | 6cd05512a7bca3becff60ae470f43793744c7f86 (patch) | |
tree | b05dd0d004f10f9c5255d1732893593b286d0b1e /app/src/fil/libre/repwifiapp/helpers | |
parent | 8b111e0799432fc5a6ead191e1029cc1446a8c91 (diff) | |
download | packages_apps_repwifi-6cd05512a7bca3becff60ae470f43793744c7f86.tar.gz packages_apps_repwifi-6cd05512a7bca3becff60ae470f43793744c7f86.tar.bz2 packages_apps_repwifi-6cd05512a7bca3becff60ae470f43793744c7f86.zip |
Removed bin directory, renamed root directory
Diffstat (limited to 'app/src/fil/libre/repwifiapp/helpers')
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java | 196 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java | 106 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/Engine.java | 397 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/Engine4p2.java | 131 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/Engine6p0.java | 360 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/IEngine.java | 41 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/NetworkButton.java | 41 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/NetworkManager.java | 288 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/RootCommand.java | 109 | ||||
-rw-r--r-- | app/src/fil/libre/repwifiapp/helpers/Utils.java | 205 |
10 files changed, 1874 insertions, 0 deletions
diff --git a/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java b/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java new file mode 100644 index 0000000..65c8b24 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java @@ -0,0 +1,196 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import fil.libre.repwifiapp.Commons; + + +public class AccessPointInfo implements Serializable{ + + private static final long serialVersionUID = 1L; + + private String _ssid; + private String _bssid; + private String _auth; + private String _level; + private String _freq; + private String _password; + private long _lastTimeUsed; + + public AccessPointInfo(String ssid, String bssid, String authType, String level, String freq){ + + this._ssid = ssid; + this._bssid = bssid; + this._auth = authType; + this._level = level; + this._freq = freq; + + } + + public String getSSID(){ + return this._ssid; + } + + public String getBSSID(){ + return this._bssid; + } + + public String getAuthType(){ + return this._auth; + } + + public String getSignlalStrength(){ + return this._level; + } + + public String getFrequency(){ + return this._freq; + } + + public long getLastTimeUsed(){ + return this._lastTimeUsed; + } + + public void setLastTimeUsed(long timeStampInMillis){ + this._lastTimeUsed = timeStampInMillis; + } + + public boolean isOlderThan(int days){ + + if (this._lastTimeUsed == 0){ + return false; + } + + long timeDiff = System.currentTimeMillis() - this._lastTimeUsed; + long spanMillis = Utils.daysToMilliseconds(days); + + if (timeDiff > spanMillis){ + return true; + }else{ + return false; + } + + + } + + public String getPassword(){ + return this._password; + } + + public void setPassword(String password){ + this._password = password; + } + + public boolean needsPassword(){ + + if ( (this._auth == null) || (this._auth.equals("")) ){ + //TODO + //check if default behavior should be with or without password, + //when no auth info is available. + return false; + } + + if (this._auth.contains("WPA2") || this._auth.contains("WPA")){ + return true; + } + else { + return false; + } + + } + + protected static AccessPointInfo parseLine(String line){ + + try{ + + String[] params = line.split("\t"); + if (params.length != 5){ + return null; + } + + String bssid = params[0]; + String freq = params[1]; + String level = params[2]; + String auth = params[3]; + String ssid = params [4]; + + AccessPointInfo info = new AccessPointInfo(ssid, bssid, auth, level, freq); + return info; + + }catch (Exception e){ + Utils.logError("Error while parsing line: " + line, e); + return null; + } + + } + + public static AccessPointInfo[] parseScanResult(String scanResultFile){ + + try { + + File f = new File(scanResultFile); + if (! f.exists()){ + Utils.logError("AccessPointInfo.parseScanResult(): The provided scan result file doesn't exist"); + return null; + } + + String[] lines = Utils.readFileLines(Commons.getScanFile()); + List<AccessPointInfo> nets = new ArrayList<AccessPointInfo>(); + + for(String l : lines){ + if (l.startsWith(Commons.SCAN_FILE_HDR)){ + //strip off the header + continue; + } + + if (l.trim().equals("")){ + //empty line, skip. + continue; + } + + //try to parse line into network info + AccessPointInfo info = AccessPointInfo.parseLine(l); + if (info == null){ + Utils.logError("Failed to parse line into AccessPointInfo: " + l); + continue; + } + + nets.add(info); + + } + + AccessPointInfo[] a = new AccessPointInfo[nets.size()]; + a = nets.toArray(a); + return a; + + } catch (Exception e) { + Utils.logError("Error while parsing scan results in class AccessPointInfo",e); + return null; + } + + } + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java b/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java new file mode 100644 index 0000000..f7cb8d7 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java @@ -0,0 +1,106 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import java.io.Serializable; + +public class ConnectionStatus implements Serializable{ + + /** + * + */ + private static final long serialVersionUID = 1L; + public static final String STATUS_CONNECTED = "COMPLETED"; + public static final String STATUS_INACTIVE = "INACTIVE"; + public static final String STATUS_DISCONNECTED = "DISCONNECTED"; + public static final String STATUS_UNDEFINED = "UNDEFINED"; + + public String status; + public String SSID; + public String BSSID; + public String IP; + + private static final String F_SEP = "="; + private static final String KeyStatus = "wpa_state"; + private static final String KeySSID = "ssid"; + private static final String KeyBSSID = "bssid"; + private static final String KeyIP = "ip_address"; + + public static ConnectionStatus parseWpaCliOutput(String wpaCliOutput){ + + if (wpaCliOutput == null){ + return null; + } + + if (wpaCliOutput.trim().length() == 0){ + return null; + } + + String[] lines = wpaCliOutput.split("\n"); + + ConnectionStatus s = new ConnectionStatus(); + for(String line : lines){ + + if (line.trim().equals("")){ + continue; + } + + String[] fields = line.split(F_SEP); + if(fields.length < 2){ + continue; + } + + String key = fields[0]; + String val = fields[1]; + + if (key.equals(KeyBSSID)){ + s.BSSID = val; + } + else if (key.equals(KeySSID)){ + s.SSID = val; + } + else if (key.equals(KeyStatus)){ + s.status = val; + } + else if (key.equals(KeyIP)){ + s.IP = val; + } + + } + + return s; + + } + + public boolean isConnected(){ + + if (this.status == null){ + return false; + } + + if (this.status.equals(STATUS_CONNECTED)){ + return true; + }else{ + return false; + } + } + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/Engine.java b/app/src/fil/libre/repwifiapp/helpers/Engine.java new file mode 100644 index 0000000..cdddb0b --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/Engine.java @@ -0,0 +1,397 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import fil.libre.repwifiapp.Commons; + + +public abstract class Engine implements IEngine{ + + protected String getCmdWpaSup(){ + return "wpa_supplicant -B -dd -i" + Commons.INTERFACE_NAME + " -C\"" +Commons.SOCKET_DIR + "\" -P\"" + Commons.PID_FILE + "\""; + } + + protected String getCmdWpaCli() { + return "wpa_cli -p" + Commons.SOCKET_DIR + " -P" + Commons.PID_FILE + " -i" + Commons.INTERFACE_NAME; + } + + protected abstract String getCmdWpaStart(); + + public static final String DNS1 = "193.183.98.154"; + public static final String DNS2 = "87.98.175.85"; + + public boolean deleteFileIfExists(String filePath){ + + if (filePath == null){ + return false; + } + + if (filePath.contains("*")){ + //it's safer to reject bulk rm'ing + return false; + } + + if (filePath.contains(" -r ")){ + //only file rm'ing acceppted + return false; + } + + return executeRootCmd("if [ -e \""+ filePath + "\" ]; then rm \"" + filePath + "\"; fi"); + } + + public boolean chmodFile(String filePath, String mod){ + return executeRootCmd("chmod " + mod + " \"" + filePath + "\""); + } + + @Override + public boolean killPreviousConnections() { + + Utils.logDebug("killing wpa_supplicant..:"); + if (executeRootCmd("killall -SIGINT wpa_supplicant")){ + Utils.logDebug("Killed wpa_supplicant"); + }else{ + Utils.logDebug("Wpa_supplicant NOT killed."); + } + + Utils.logDebug("killing dhcpcd.."); + if (executeRootCmd("killall -SIGINT dhcpcd")){ + Utils.logDebug("Killed dhcpcd"); + }else{ + Utils.logDebug("dhcpcd NOT killed."); + } + + + return true; + + } + + @Override + public boolean clearWorkingDir(){ + + Utils.logDebug("clearWorkingDir():"); + + if (executeRootCmd("rm -r " + Commons.SOCKET_DIR)){ + Utils.logDebug("removed socket dir"); + } + + if (executeRootCmd("rm " + Commons.ENTROPY_FILE)){ + Utils.logDebug("removed entropy file"); + } + + if (executeRootCmd("rm " + Commons.PID_FILE)){ + Utils.logDebug("removed pidfile"); + } + + if (executeRootCmd("rm " + Commons.SOFTAP_FILE)){ + Utils.logDebug("removed softap file"); + } + + if (executeRootCmd("rm " + Commons.WPA_CONF)){ + Utils.logDebug("removed wpa conf file"); + } + + if (executeRootCmd("rm " + Commons.P2P_CONF)){ + Utils.logDebug("removed p2p conf file"); + } + + + return true; + + } + + @Override + public boolean startWpaSupplicant(){ + + Utils.logDebug("startWpaSupplicant():"); + + if (executeRootCmd(getCmdWpaSup())){ + return true; + }else{ + Utils.logDebug("Failed to start wpa"); + return false; + } + + } + + @Override + public AccessPointInfo[] getAvailableNetworks(){ + + Utils.logDebug("getAvailableNetworks():"); + + killPreviousConnections(); + + if (! clearWorkingDir()){ + Utils.logError("Failed clearing dir"); + return null; + } + + if (! startWpaSupplicant()){ + Utils.logError("Failed starting wpa_supplicant"); + return null; + } + + if (! createScanScripts()){ + Utils.logError("Failed creating scripts"); + return null; + } + + if (! scanNetworks()){ + Utils.logError("failed scanning networks"); + return null; + } + + if (!getScanResults()){ + Utils.logError("failed getting scan results"); + return null; + } + + //chmod 666 scan_file to make it readable + if (!chmodFile(Commons.getScanFile(), "666")){ + Utils.logError("failed chmodding scan_file"); + return null; + } + + AccessPointInfo[] a = AccessPointInfo.parseScanResult(Commons.getScanFile()); + if (a == null){ + Utils.logError("Unable to parse scan file into AccessPointInfo array"); + } + + + return a; + + } + + @Override + public abstract boolean connect(AccessPointInfo info); + + @Override + public boolean disconnect(){ + + if (! isWpaSupplicantRunning()){ + return true; + } + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " disconnect"); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while enabling network", e); + return false; + } + } + + /*** + * returns null if unable to determine connection status for any reason. + */ + @Override + public ConnectionStatus getConnectionStatus(){ + + Utils.logDebug("called getConnecitonStatus()"); + if (! isWpaSupplicantRunning()){ + //wpa_supplicant is not running. + //unable to determin status. + Utils.logDebug("wpa not running, cannot get connection status."); + return null; + + } + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " status"); + if(su.execute() == 0){ + String out = su.getOutput(); + if (out == null || out.trim().equals("")){ + return null; + } + else { + return ConnectionStatus.parseWpaCliOutput(out); + } + } + else { + return null; + } + + } catch (Exception e) { + Utils.logError("Error while executing wpa_cli status", e); + return null; + } + + } + + public boolean runDhcpcd(){ + + return executeRootCmd("dhcpcd " + Commons.INTERFACE_NAME); + + } + + public boolean interfaceUp(){ + return executeRootCmd("ifconfig " + Commons.INTERFACE_NAME + " up"); + } + + protected boolean executeRootCmd(String cmd){ + + try { + + RootCommand c = new RootCommand(cmd); + if ( c.execute() == 0){ + return true; + }else { + return false; + } + + } catch (Exception e) { + Utils.logError("Error executing \"" + cmd + "\"",e); + return false; + } + } + + protected boolean isWpaSupplicantRunning(){ + + boolean retval = false; + + try { + + RootCommand su = new RootCommand("pidof wpa_supplicant"); + if (su.execute() == 0){ + + if (su.getOutput().trim().equals("")){ + retval = false; + }else{ + retval = true; + } + + }else { + retval = false; + } + + + } catch (Exception e) { + Utils.logError("Exception during isWpaSupplicantRunning()",e); + retval = false; + } + + return retval; + + } + + protected boolean scanNetworks(){ + + return executeRootCmd("bash " + Commons.getScriptScan()); + + } + + protected boolean getScanResults(){ + + return executeRootCmd("bash " + Commons.getScriptScanRes()); + + } + + protected boolean createScanScripts(){ + + try { + + String scan = getCmdWpaCli() + " scan\n" + + "if [ $? -ne 0 ]; then\n" + + "exit 1\n" + + "fi\n" + + "sleep 2s\n"; + + String scanRes = "if [ -e \"" + Commons.getScanFile() + "\" ]; then\n" + + " rm \"" + Commons.getScanFile() + "\"\n" + + "fi\n" + + getCmdWpaCli() + " scan_results > \""+ Commons.getScanFile() + "\"\n" + + "if [ $? -ne 0 ]; then\n" + + " exit 1\n" + + "fi\n" + + "sleep 1s\n"; + + + //Try to create and chmod script scan + /* executeRootCmd("echo > " + Commons.getSCRIPT_SCAN()); + chmodFile(Commons.getSCRIPT_SCAN(), "666");*/ + + + if (! Utils.writeFile(Commons.getScriptScan(),scan,true) ){ + + Exception e = Utils.getLastException(); + if (e != null){ + Utils.logError("Error while writing scan script.",e); + } + + return false; + } + + //Try to create and chmod script scanres + /*executeRootCmd("echo > " + Commons.getSCRIPT_SCANRES()); + chmodFile(Commons.getSCRIPT_SCANRES(), "666");*/ + + if (! Utils.writeFile(Commons.getScriptScanRes(),scanRes,true) ){ + + Exception e = Utils.getLastException(); + if (e != null){ + Utils.logError("Error while writing getScanResults script.",e); + } + + return false; + } + + + return true; + + } catch (Exception e) { + + Utils.logError("Error while creating the scanning script.",e); + return false; + } + + } + + /*protected boolean createDhcpcdScritp(){ + + String scriptDhcp = "dhcpcd "+ Commons.INTERFACE_NAME + "\n" + + "sleep 3s\n"; + + if (! Utils.writeFile(Commons.getScriptDhcpcd(),scriptDhcp,true) ){ + + Exception e = Utils.getLastException(); + if (e != null){ + Utils.logError("Error while writing dhcpcd script.",e); + } + + return false; + } + + return true; + + }*/ +} diff --git a/app/src/fil/libre/repwifiapp/helpers/Engine4p2.java b/app/src/fil/libre/repwifiapp/helpers/Engine4p2.java new file mode 100644 index 0000000..12d8da8 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/Engine4p2.java @@ -0,0 +1,131 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import fil.libre.repwifiapp.Commons; + + +public class Engine4p2 extends Engine{ + + @Override + protected String getCmdWpaStart(){ + return "wpa_supplicant -B -dd -i" + Commons.INTERFACE_NAME + " -C\"" + Commons.SOCKET_DIR + "\" -c\"" + Commons.WPA_CONF + "\" -P\"" + Commons.PID_FILE + "\""; + } + + public boolean loadModules(){ + try { + //TODO + //implement kernel modules loading + return true; + } catch (Exception e) { + Utils.logError("Error while loading kernel modules",e); + return false; + } + } + + @Override + public boolean connect(AccessPointInfo info){ + + killPreviousConnections(); + + if (info == null){ + Utils.logDebug("Engine's connect() received a null AccessPointInfo"); + return false; + } + + if (! createConfigFile(info)){ + return false; + } + + //launch wpa_supplicant specifying our custom configuration and the socket file + if (! executeRootCmd(getCmdWpaStart())){ + Utils.logError("wpa_supplicant connection command failed."); + return false; + } + + //negotiate DHCP lease + if (!runDhcpcd()){ + return false; + } + + //set DNS's + if (! executeRootCmd("setprop net.dns1 " + DNS1)){ + Utils.logError("setting dns1 failed"); + return false; + } + + if (! executeRootCmd("setprop net.dns2 " + DNS2)){ + Utils.logError("setting dns2 failed"); + return false; + } + + //TODO + //implement wpa_cli command to query wpa_supplicant's state + //in order to confirm that connection was successful. + + return true; + + } + + private boolean createConfigFile(AccessPointInfo info){ + + try { + + if (! deleteFileIfExists(Commons.WPA_CONF)){ + Utils.logError("Unable to remove wpa_supplicant.conf before writing it."); + return false; + } + + String configText = "ctrl_interface=DIR=" + Commons.SOCKET_DIR + "\n" + + "update_config=1\n" + + "network={\n"+ + " ssid=\"" + info.getSSID() + "\"\n"; + + if (info.needsPassword()){ + configText += " psk=\""+ info.getPassword() + "\"\n"; + }else { + configText += " key_mgmt=NONE\n"; + } + + configText += "}\n"; + + if ( ! Utils.writeFile(Commons.WPA_CONF, configText, true) ){ + Utils.logError("Unable to write wpa_supplicant.conf file!"); + return false; + } + + //chmod wpa_supplicant.conf, in order to make it accessible + if(chmodFile(Commons.WPA_CONF, "666")){ + return true; + }else { + Utils.logError("Unable to chmod wpa_supplicant.conf"); + return false; + } + + } catch (Exception e) { + Utils.logError("Error while creating wpa_supplicant.conf",e); + return false; + } + + } + + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java b/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java new file mode 100644 index 0000000..24096d2 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java @@ -0,0 +1,360 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import fil.libre.repwifiapp.Commons; + + +public class Engine6p0 extends Engine{ + + @Override + protected String getCmdWpaStart(){ + return "wpa_supplicant -B -dd -i" + Commons.INTERFACE_NAME + " -C" + Commons.SOCKET_DIR + " -P" + Commons.PID_FILE + " -I" + Commons.OVERLAY_FILE + " -e" + Commons.ENTROPY_FILE; + } + + @Override + public boolean connect(AccessPointInfo info){ + + killPreviousConnections(); + + if (info == null){ + Utils.logDebug("Engine's connect() received a null AccessPointInfo"); + return false; + } + + //clear any previously set network + if (! destroyNetwork()){ + Utils.logDebug("Unable to ndc destroy network"); + return false; + } + + //clear interface's ip + if (! clearAddrs()){ + Utils.logDebug("Unable to ndc clearaddrs"); + return false; + } + + //bring up interface + if(! interfaceUp()){ + Utils.logDebug("Unable to bring up interface."); + return false; + } + + //launch wpa_supplicant specifying our custom configuration and the socket file + if (! executeRootCmd(getCmdWpaStart())){ + Utils.logDebug("Unable to run wpa start"); + return false; + } + + //create new network and get network id + String netID = createNetworkGetId(); + if (netID == null){ + Utils.logDebug("Unable to fetch network id"); + return false; + } + + //set network SSID + if (! setNetworkSSID(info.getSSID(), netID)){ + Utils.logDebug("Failed to set network ssid"); + return false; + } + + //set password (if any) + if(! setNetworkPSK(info, netID)){ + Utils.logDebug("Failed to set network psk"); + return false; + } + + // select the network we just created + if (! selectNetwork(netID)){ + Utils.logDebug("Unable to wpa_cli select network"); + return false; + } + + //enable the newtork + if (! enableNetwork(netID)){ + Utils.logDebug("Unable to wpa_cli enable_newtork"); + return false; + } + + //try to reassociate to Access Point + if (! reassociate()){ + Utils.logDebug("Unable to wpa_cli reassociate"); + return false; + } + + //get DHCP + Utils.logDebug("Attempt to run dhcpcd.."); + if (!runDhcpcd()){ + Utils.logDebug("Failed to run dhcpcd"); + return false; + } + + //try to fetch gateway + String gw = getGateway(); + if (gw == null || gw.trim().length() < 7){ + //failed to get gateway + Utils.logDebug("Failed to get gateway"); + return false; + } + + if (! executeRootCmd("ndc network create 1")){ + Utils.logDebug("Failed to wpa_cli network create 1 "); + return false; + } + + if (! executeRootCmd("ndc network interface add 1 " + Commons.INTERFACE_NAME)){ + Utils.logDebug("Failed to add interface."); + return false; + } + + // set route to gateway for all traffic + if (! executeRootCmd("ndc network route add 1 " + Commons.INTERFACE_NAME + " 0.0.0.0/0 " + gw)){ + Utils.logDebug("Failed to add route to gateway"); + return false; + } + + //set DNS + if (! executeRootCmd("ndc resolver setnetdns 1 " + " " + DNS1 + " " + DNS2)){ + Utils.logDebug("Failed to set DNS"); + return false; + } + + //use network + if (! executeRootCmd("ndc network default set 1")){ + Utils.logDebug("Failed to set network as default"); + return false; + } + + //TODO + //implement wpa_cli query for status + //in order to be sure that connection is extablished + + return true; + + + + } + + private String createNetworkGetId(){ + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " add_network"); + if(su.execute() == 0){ + String out = su.getOutput(); + if (out == null || out.trim().equals("")){ + return null; + } + else { + return out.replace("\n", ""); + } + } + else { + return null; + } + + } catch (Exception e) { + Utils.logError("Error while creating network", e); + return null; + } + + } + + private boolean destroyNetwork(){ + return executeRootCmd("ndc network destroy 1"); + } + + private boolean setNetworkSSID(String ssid, String networkID){ + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " set_network " + networkID + " ssid '\"" + ssid + "\"'" ); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while setting network SSID", e); + return false; + } + + } + + private boolean setNetworkPSK(AccessPointInfo info, String networkID){ + + try { + + String cmdSetPass = null; + if (info.needsPassword()){ + cmdSetPass = getCmdWpaCli() + " set_network " + networkID + " psk '\"" + info.getPassword() + "\"'"; + } + else{ + cmdSetPass = getCmdWpaCli() + " set_network " + networkID + " key_mgmt NONE"; + } + + RootCommand su = new RootCommand(cmdSetPass); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while setting network PSK", e); + return false; + } + + + } + + private boolean selectNetwork(String networkID){ + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " select_network " + networkID); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while selecting network", e); + return false; + } + + } + + private boolean enableNetwork(String networkID){ + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " enable_network " + networkID); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while enabling network", e); + return false; + } + + } + + private boolean reassociate(){ + + try { + + RootCommand su = new RootCommand(getCmdWpaCli() + " reassociate"); + if (su.execute() == 0){ + String out = su.getOutput(); + if (out != null && out.trim().replace("\n", "").equals("OK")){ + return true; + }else { + return false; + } + } + else{ + return false; + } + + } catch (Exception e) { + Utils.logError("Error while reassociating network", e); + return false; + } + + } + + private String getGateway(){ + + try { + + RootCommand su = new RootCommand("ip route show dev " + Commons.INTERFACE_NAME); + if (su.execute() != 0){ + Utils.logDebug("command failed show route"); + return null; + } + + //read command output + String out = su.getOutput(); + if (out == null){ + return null; + } + + String[] lines = out.split("\n"); + + for (String l : lines){ + + if (l.contains("default via")){ + + String[] f = l.split(" "); + if (f.length > 2){ + + //found route's address: + return f[2]; + + } + } + } + + return null; + + } catch (Exception e) { + Utils.logError("Error while trying to fetch route",e); + return null; + } + + } + + private boolean clearAddrs(){ + return executeRootCmd("ndc interface clearaddrs " + Commons.INTERFACE_NAME); + } + +}
\ No newline at end of file diff --git a/app/src/fil/libre/repwifiapp/helpers/IEngine.java b/app/src/fil/libre/repwifiapp/helpers/IEngine.java new file mode 100644 index 0000000..67ffb86 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/IEngine.java @@ -0,0 +1,41 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + + +public interface IEngine { + + public boolean startWpaSupplicant(); + + public boolean killPreviousConnections(); + + public boolean clearWorkingDir(); + + public AccessPointInfo[] getAvailableNetworks(); + + public boolean connect(AccessPointInfo info); + + public boolean disconnect(); + + public ConnectionStatus getConnectionStatus(); + + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/NetworkButton.java b/app/src/fil/libre/repwifiapp/helpers/NetworkButton.java new file mode 100644 index 0000000..9a7c523 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/NetworkButton.java @@ -0,0 +1,41 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import android.content.Context; +import android.widget.Button; + +public class NetworkButton extends Button{ + + private String _bssid = ""; + + public NetworkButton(Context context, String networkBSSID){ + super(context); + this._bssid = networkBSSID; + } + + public String getNetworkBSSID(){ + return this._bssid; + } + + + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java b/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java new file mode 100644 index 0000000..bc59862 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java @@ -0,0 +1,288 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import java.io.File; +import java.util.ArrayList; + +public class NetworkManager { + + private static final String F_SEP = "\t"; + private static final int NET_MAX_AGE = 365; //Expressed in days + + private String _knownNetworksFile = null; + + public NetworkManager(String networksFilePath){ + this._knownNetworksFile = networksFilePath; + } + + private AccessPointInfo searchInFile(AccessPointInfo i){ + + if (i == null){ + return null; + } + + String bssid = i.getBSSID(); + String ssid = i.getSSID(); + + if (bssid == null || ssid == null || bssid.trim().equals("") || ssid.trim().equals("")){ + return null; + } + + AccessPointInfo ret = null; + AccessPointInfo[] list = getKnownNetworks(); + + if (list == null){ + return null; + } + + for(AccessPointInfo toTest : list){ + + // try to match both bssid and ssid. + // if bssid doesn't match, but ssid does, + // then the network is a candidate. + // if no bssid equality is found, + // then return the best match (only ssid), if any + if (toTest.getSSID().equals(ssid)){ + + if (toTest.getBSSID().equals(bssid)){ + i.setPassword(toTest.getPassword()); + return i; + + }else{ + i.setPassword(toTest.getPassword()); + ret = i; + } + + } + + } + + return ret; + + } + + private boolean saveOrRemove(AccessPointInfo info, boolean save){ + + String iText = InfoToString(info); + if (iText == null){ + return false; + } + + AccessPointInfo[] existingNets = getKnownNetworks(); + + ArrayList<AccessPointInfo> newlist = new ArrayList<AccessPointInfo>(); + + if (existingNets == null || existingNets.length == 0){ + //no existing storage yet, create it + + if (save){ + //set timestamp + info.setLastTimeUsed(System.currentTimeMillis()); + newlist.add(info); + AccessPointInfo[] newContents = new AccessPointInfo[newlist.size()]; + newContents = newlist.toArray(newContents); + + return saveList(newContents); + + }else{ + //nothing to do, return + return true; + } + + } + + for(AccessPointInfo old : existingNets){ + + if (old == null){ + continue; + } + + if (old.getBSSID().equals(info.getBSSID()) && old.getSSID().equals(info.getSSID())){ + + //found previous entry for this network, + //if the call is for saving, overwrite the entry with the new one, + //else omit the line, to remove network from the saved list. + if (save){ + info.setLastTimeUsed(System.currentTimeMillis()); + newlist.add(info); + } + + }else{ + //other network, keep it in the file + // only if it's not older than the max age for a network + if (! info.isOlderThan(NET_MAX_AGE)){ + newlist.add(old); + } + } + + } + + AccessPointInfo[] newContents = new AccessPointInfo[newlist.size()]; + newContents = newlist.toArray(newContents); + + return saveList(newContents); + + } + + private AccessPointInfo getFromString(String savedString){ + + if (savedString == null || savedString.trim().equals("")) { + return null; + } + + String[] fields = savedString.split(F_SEP); + + if (fields.length != 4 ){ + return null; + } + + String bssid = fields[0]; + String ssid = fields[1]; + String pass = fields[2]; + String lastUsed = fields[3]; + + long lastusedmillis = 0; + try { + lastusedmillis = Long.parseLong(lastUsed); + } catch (NumberFormatException e) { + //invalid format + Utils.logError("Invalid time format in network manager \""+lastUsed +"\". Network BSSID: " + bssid, e); + } + + if (bssid.trim().equals("") || ssid.trim().equals("") || pass.trim().equals("")){ + return null; + } + + AccessPointInfo i = new AccessPointInfo(ssid, bssid, null, null, null); + i.setPassword(pass); + i.setLastTimeUsed(lastusedmillis); + + return i; + + } + + private String InfoToString(AccessPointInfo info){ + + if (info == null){ + return null; + } + + String bssid = info.getBSSID(); + String ssid = info.getSSID(); + String pass = info.getPassword(); + String tsLastUsed = "" + info.getLastTimeUsed(); + + if (bssid == null || bssid.trim().equals("")){ + return null; + } + + if (ssid == null || ssid.trim().equals("")){ + return null; + } + + if (pass == null || pass.trim().equals("")){ + return null; + } + + String iText = info.getBSSID() + F_SEP + info.getSSID() + F_SEP + info.getPassword() + F_SEP + tsLastUsed; + return iText; + + } + + private boolean saveList(AccessPointInfo[] list){ + + if (list == null){ + return false; + } + + String[] lines = new String[list.length]; + + for (int i = 0; i<list.length; i++){ + + String storeString = InfoToString(list[i]); + if (storeString == null){ + return false; + } + lines[i] = storeString; + + } + + return Utils.writeFileLines(this._knownNetworksFile,lines, true); + + } + + public AccessPointInfo[] getKnownNetworks(){ + + ArrayList<AccessPointInfo> list = new ArrayList<AccessPointInfo>(); + + File f = new File(this._knownNetworksFile); + if (! f.exists()){ + return null; + } + + String[] lines = Utils.readFileLines(_knownNetworksFile); + if (lines.length == 0){ + return null; + } + + for(String l : lines){ + + AccessPointInfo info = getFromString(l); + if (info != null){ + list.add(info); + } + + } + + AccessPointInfo[] ret = new AccessPointInfo[list.size()]; + ret = list.toArray(ret); + + return ret; + + } + + public boolean isKnown(AccessPointInfo info){ + + AccessPointInfo i = searchInFile(info); + if (i == null){ + return false; + }else { + return true; + } + + } + + public boolean save(AccessPointInfo info){ + return saveOrRemove(info, true); + } + + public boolean remove(AccessPointInfo info){ + return saveOrRemove(info, false); + } + + public AccessPointInfo getSavedNetwork(AccessPointInfo i){ + return searchInFile(i); + } + + + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/RootCommand.java b/app/src/fil/libre/repwifiapp/helpers/RootCommand.java new file mode 100644 index 0000000..3da4ae0 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/RootCommand.java @@ -0,0 +1,109 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +import fil.libre.repwifiapp.Commons; + +public class RootCommand { + + private String _cmdOut = ""; + private String _cmdTxt = ""; + + public RootCommand(String commandText){ + this._cmdTxt = commandText; + } + + public int execute() throws Exception{ + return execute(0); + } + + public int execute(int sleepSecsAfterCmd) throws Exception{ + + Process su = Runtime.getRuntime().exec("su"); + + DataOutputStream stdin = new DataOutputStream(su.getOutputStream()); + InputStream os = su.getInputStream(); + BufferedReader stdOut = new BufferedReader(new InputStreamReader(os)); + InputStream es = su.getErrorStream(); + BufferedReader stdError = new BufferedReader(new InputStreamReader(es)); + + if ( this._cmdTxt != null ){ + + Utils.logDebug("EXEC: " + this._cmdTxt); + + this._cmdTxt += " > " + Commons.getTempOutFile(); + + stdin.writeBytes(this._cmdTxt + "\n"); + stdin.flush(); + } + + /* if (sleepSecsAfterCmd > 0){ + Thread.sleep(sleepSecsAfterCmd * 1000); + }*/ + + StringBuilder sb = new StringBuilder(); + String s = null; + + while ( (es.available() > 0) && (s = stdError.readLine()) != null) { + sb.append(s + "\n"); + } + + while ( (os.available() > 0) && (s = stdOut.readLine()) != null) { + sb.append(s + "\n"); + } + + this._cmdOut = sb.toString(); + + stdin.writeBytes("exit\n"); + stdin.flush(); + + int res = su.waitFor(); + + Utils.logDebug("OUT: " + getOutput()); + + return res; + + } + + public String getOutput(){ + + String[] lastOut = Utils.readFileLines(Commons.getTempOutFile()); + if (lastOut == null){ + return this._cmdOut; + } + + String fout = ""; + + for (String s : lastOut){ + fout += s + "\n"; + } + + return fout; + + } + + + +} diff --git a/app/src/fil/libre/repwifiapp/helpers/Utils.java b/app/src/fil/libre/repwifiapp/helpers/Utils.java new file mode 100644 index 0000000..2e5fa27 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/helpers/Utils.java @@ -0,0 +1,205 @@ +// +// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp 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. +// +// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.helpers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import android.util.Log; + +public class Utils { + + private static final long MILLIS_IN_DAY = 86400000; + + public static final int logLevel = 1; + + public static final String APP_NAME = "RepWifi"; + + private static Exception _lastException = null; + + public static Exception getLastException(){ + return _lastException; + } + + public static void logError(String msg, Exception e){ + Log.e(APP_NAME,msg,e); + } + + public static void logError(String msg){ + Log.e(APP_NAME,msg); + } + + public static void logDebug(String msg){ + logDebug(msg,0); + } + + public static void logDebug(String msg, int level){ + + if (level < logLevel){ + return; + } + + Log.d(APP_NAME,msg); + } + + public static boolean writeFile(String filePath, String text, boolean overwrite){ + + + FileWriter writer = null; + boolean retval = false; + try { + + writer = new FileWriter(filePath, (! overwrite)); + writer.write(text); + + retval = true; + + } catch (Exception e) { + _lastException = e; + retval = false; + } + finally{ + + if (writer != null){ + try { + writer.close(); + } catch (IOException e) { + //suppress + } + } + + } + + return retval; + + } + + public static boolean writeFileLines(String filePath, String[] lines, boolean overwrite){ + + if (lines == null){ + return false; + } + + FileWriter writer = null; + boolean retval = false; + try { + + writer = new FileWriter(filePath, (! overwrite)); + + if (lines.length == 0){ + writer.write(""); + } + + for(String l : lines){ + writer.write(l + "\n"); + } + + retval = true; + + } catch (Exception e) { + _lastException = e; + retval = false; + } + finally{ + + if (writer != null){ + try { + writer.close(); + } catch (IOException e) { + //suppress + } + } + + } + + return retval; + + } + + public static String[] readFileLines(String filePath){ + + if (filePath == null){ + return null; + } + + File f = new File(filePath); + if (! f.exists()){ + logError("File doesn't exist: " + filePath); + return null; + } + + FileReader fr = null; + BufferedReader bufr = null; + + List<String> lines = new ArrayList<String>(); + String[] ret = null; + + try { + + fr = new FileReader(filePath); + bufr = new BufferedReader(fr); + String line =""; + while((line = bufr.readLine()) != null){ + lines.add(line); + } + + String[] ar = new String[lines.size()]; + ret = lines.toArray(ar); + + } catch (Exception e) { + logError("Error while reading file " + filePath,e); + ret = null; + } + finally{ + try { + if (bufr != null){ + bufr.close(); + } + } catch (IOException ex) { + //suppress + } + try { + if (fr != null){ + fr.close(); + } + }catch(IOException exc){ + //suppress + } + } + + return ret; + + } + + public static long daysToMilliseconds(int days){ + return (days * MILLIS_IN_DAY); + } + + public static long millisecondsToDays(long milliseconds){ + return (milliseconds / MILLIS_IN_DAY); + } + +} |