cleaned up iptables binary handling

This commit is contained in:
Nathan Freitas 2012-01-12 20:58:21 -05:00
parent 4bbca2927d
commit b8af143d5f
7 changed files with 183 additions and 1097 deletions

View File

@ -43,5 +43,6 @@ public interface TorConstants {
public final static String PREF_HAS_ROOT = "has_root";
public final static int RESULT_CLOSE_ALL = 0;
public final static String PREF_USE_SYSTEM_IPTABLES = "pref_use_sys_iptables";
}

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,12 @@
package org.torproject.android.service;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -22,6 +24,7 @@ import org.torproject.android.TorConstants;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
public class TorBinaryInstaller implements TorServiceConstants {
@ -29,6 +32,8 @@ public class TorBinaryInstaller implements TorServiceConstants {
File installFolder;
Context context;
private static int isARMv6 = -1;
public TorBinaryInstaller (Context context, File installFolder)
{
this.installFolder = installFolder;
@ -151,4 +156,97 @@ public class TorBinaryInstaller implements TorServiceConstants {
/**
* Check if this is an ARMv6 device
* @return true if this is ARMv6
*/
private static boolean isARMv6() {
if (isARMv6 == -1) {
BufferedReader r = null;
try {
isARMv6 = 0;
r = new BufferedReader(new FileReader("/proc/cpuinfo"));
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (line.startsWith("Processor") && line.contains("ARMv6")) {
isARMv6 = 1;
break;
} else if (line.startsWith("CPU architecture") && (line.contains("6TE") || line.contains("5TE"))) {
isARMv6 = 1;
break;
}
}
} catch (Exception ex) {
} finally {
if (r != null) try {r.close();} catch (Exception ex) {}
}
}
return (isARMv6 == 1);
}
/**
* Copies a raw resource file, given its ID to the given location
* @param ctx context
* @param resid resource id
* @param file destination file
* @param mode file permissions (E.g.: "755")
* @throws IOException on error
* @throws InterruptedException when interrupted
*/
private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
{
final String abspath = file.getAbsolutePath();
// Write the iptables binary
final FileOutputStream out = new FileOutputStream(file);
final InputStream is = ctx.getResources().openRawResource(resid);
byte buf[] = new byte[1024];
int len;
while ((len = is.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
is.close();
// Change the permissions
Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
}
/**
* Asserts that the binary files are installed in the cache directory.
* @param ctx context
* @param showErrors indicates if errors should be alerted
* @return false if the binary files could not be installed
*/
public static boolean assertIpTablesBinaries(Context ctx, boolean showErrors) throws Exception {
boolean changed = false;
// Check iptables_g1
File file = new File(ctx.getDir("bin",0), "iptables");
if ((!file.exists()) && isARMv6()) {
copyRawFile(ctx, R.raw.iptables_g1, file, "755");
changed = true;
}
// Check iptables_n1
file = new File(ctx.getDir("bin",0), "iptables");
if ((!file.exists()) && (!isARMv6())) {
copyRawFile(ctx, R.raw.iptables_n1, file, "755");
changed = true;
}
// Check busybox
/*
file = new File(ctx.getDir("bin",0), "busybox_g1");
if (!file.exists()) {
copyRawFile(ctx, R.raw.busybox_g1, file, "755");
changed = true;
}
*/
if (changed) {
Toast.makeText(ctx, R.string.status_install_success, Toast.LENGTH_LONG).show();
}
return true;
}
}

View File

@ -1,11 +1,20 @@
/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
/*
* Code for iptables binary management taken from DroidWall GPLv3
* Copyright (C) 2009-2010 Rodrigo Zechin Rosauro
*/
package org.torproject.android.service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
@ -39,6 +48,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
{
@ -414,8 +424,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private boolean checkTorBinaries () throws Exception
{
//check and install iptables
IptablesManager.assertBinaries(this, true);
TorBinaryInstaller.assertIpTablesBinaries(this, true);
appBinHome = getDir("bin",0);
appDataHome = getCacheDir();
@ -520,6 +529,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
TorTransProxy ttProxy = new TorTransProxy();
if (hasRoot && enableTransparentProxy)
{
@ -544,7 +555,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
int status = code;
while (st.hasMoreTokens())
{
status = TorTransProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
status = ttProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
if(status != 0)
code = status;
}
@ -554,12 +565,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if(transProxyAll)
{
showAlert(getString(R.string.status), getString(R.string.setting_up_full_transparent_proxying_));
code = TorTransProxy.setTransparentProxyingAll(this);
code = ttProxy.setTransparentProxyingAll(this);
}
else
{
showAlert(getString(R.string.status), getString(R.string.setting_up_app_based_transparent_proxying_));
code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
code = ttProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
}
}
@ -576,7 +587,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{
showAlert(getString(R.string.status), getString(R.string.transproxy_enabled_for_tethering_));
TorTransProxy.enableTetheringRules(this);
ttProxy.enableTetheringRules(this);
}
}
@ -604,12 +615,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
if (hasRoot && enableTransparentProxy)
{
TorService.logMessage ("Clearing TransProxy rules");
TorTransProxy.flushIptables(this);
new TorTransProxy().flushIptables(this);
showAlert(getString(R.string.status), getString(R.string.transproxy_rules_cleared));

View File

@ -6,17 +6,59 @@ import org.torproject.android.TorConstants;
import org.torproject.android.settings.TorifiedApp;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class TorTransProxy implements TorServiceConstants {
private final static String TAG = TorConstants.TAG;
private String ipTablesPath;
public String getIpTablesPath (Context context)
{
public static int flushIptables(Context context) throws Exception {
if (ipTablesPath == null)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean(TorConstants.PREF_USE_SYSTEM_IPTABLES, false))
{
//if the user wants us to use the built-in iptables, then we have to find it
File fileIpt = new File("/system/bin/iptables");
if (fileIpt.exists())
ipTablesPath = fileIpt.getAbsolutePath();
else
{
fileIpt = new File("/system/xbin/iptables");
if (fileIpt.exists())
return (ipTablesPath = fileIpt.getAbsolutePath());
else
{
//use the bundled version
ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
}
}
}
else
{
//use the bundled version
ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
}
}
return ipTablesPath;
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
}
public int flushIptables(Context context) throws Exception {
String ipTablesPath = getIpTablesPath(context);
final StringBuilder script = new StringBuilder();
StringBuilder res = new StringBuilder();
@ -124,16 +166,17 @@ public class TorTransProxy implements TorServiceConstants {
}
*/
public static int testOwnerModule(Context context) throws Exception
public int testOwnerModule(Context context) throws Exception
{
TorBinaryInstaller.assertIpTablesBinaries(context, false);
boolean runRoot = true;
boolean waitFor = true;
//redirectDNSResolvConf(); //not working yet
int torUid = context.getApplicationInfo().uid;
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@ -161,7 +204,7 @@ public class TorTransProxy implements TorServiceConstants {
public static int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
public int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
{
boolean runRoot = true;
@ -169,7 +212,7 @@ public class TorTransProxy implements TorServiceConstants {
//redirectDNSResolvConf(); //not working yet
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@ -261,7 +304,7 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
public static int setTransparentProxyingByPort(Context context, int port) throws Exception
public int setTransparentProxyingByPort(Context context, int port) throws Exception
{
//android.os.Debug.waitForDebugger();
@ -269,7 +312,7 @@ public class TorTransProxy implements TorServiceConstants {
//redirectDNSResolvConf(); //not working yet
//String baseDir = context.getDir("bin",0).getAbsolutePath() + '/';
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@ -318,13 +361,13 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
public static int enableTetheringRules (Context context) throws Exception
public int enableTetheringRules (Context context) throws Exception
{
boolean runRoot = true;
boolean waitFor = true;
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@ -360,14 +403,14 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
public static int setTransparentProxyingAll(Context context) throws Exception
public int setTransparentProxyingAll(Context context) throws Exception
{
boolean runRoot = true;
boolean waitFor = true;
//redirectDNSResolvConf(); //not working yet
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();

View File

@ -164,7 +164,7 @@ public class Permissions extends Activity implements TorConstants {
if (hasRoot)
{
try {
int resp = TorTransProxy.testOwnerModule(context);
int resp = new TorTransProxy().testOwnerModule(context);
if (resp < 0)
{

View File

@ -93,17 +93,16 @@ public class WizardHelper implements TorConstants {
@Override
public void onClick(View view) {
boolean iCanHazRoot = TorServiceUtils.isRootPossible();
boolean isRootPossible = TorServiceUtils.isRootPossible();
if (isRootPossible)
if (iCanHazRoot)
{
try {
int resp = TorTransProxy.testOwnerModule(context);
int resp = new TorTransProxy().testOwnerModule(context);
if (resp < 0)
{
isRootPossible = false;
iCanHazRoot = false;
Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show();
Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available");
@ -111,21 +110,12 @@ public class WizardHelper implements TorConstants {
} catch (Exception e) {
isRootPossible = false;
iCanHazRoot = false;
Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e);
}
}
/*
* we shouldn't store root here, as this step is just chekcing to see if root is possible
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Editor pEdit = prefs.edit();
pEdit.putBoolean("has_root",hasRoot);
pEdit.commit();
*/
if (isRootPossible)
if (iCanHazRoot)
{
currentDialog.dismiss();
showWizardStep2Root();