big refactor for multiple reasons
- implement LICENSE display in About dialog - remove root transproxy features - general crufty stuff cleanup
This commit is contained in:
		
							parent
							
								
									70693bfc6a
								
							
						
					
					
						commit
						01176b1d38
					
				|  | @ -5,6 +5,7 @@ package org.torproject.android; | ||||||
| 
 | 
 | ||||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||||
| import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||||
| import java.net.URLDecoder; | import java.net.URLDecoder; | ||||||
|  | @ -64,6 +65,7 @@ import android.support.v7.app.ActionBarDrawerToggle; | ||||||
| import android.support.v7.app.AppCompatActivity; | import android.support.v7.app.AppCompatActivity; | ||||||
| import android.support.v7.widget.SwitchCompat; | import android.support.v7.widget.SwitchCompat; | ||||||
| import android.support.v7.widget.Toolbar; | import android.support.v7.widget.Toolbar; | ||||||
|  | import android.text.Html; | ||||||
| import android.util.AttributeSet; | import android.util.AttributeSet; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.view.GestureDetector; | import android.view.GestureDetector; | ||||||
|  | @ -536,12 +538,35 @@ public class OrbotMainActivity extends AppCompatActivity | ||||||
|             TextView versionName = (TextView)view.findViewById(R.id.versionName); |             TextView versionName = (TextView)view.findViewById(R.id.versionName); | ||||||
|             versionName.setText(version); |             versionName.setText(version); | ||||||
| 
 | 
 | ||||||
|  |             TextView aboutOther = (TextView)view.findViewById(R.id.aboutother); | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 String aboutText = readFromAssets(this,"LICENSE"); | ||||||
|  |                 aboutOther.setText(Html.fromHtml(aboutText)); | ||||||
|  |             } | ||||||
|  |             catch (Exception e){} | ||||||
|  |              | ||||||
|                     new AlertDialog.Builder(this) |                     new AlertDialog.Builder(this) | ||||||
|             .setTitle(getString(R.string.button_about)) |             .setTitle(getString(R.string.button_about)) | ||||||
|             .setView(view) |             .setView(view) | ||||||
|             .show(); |             .show(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |     public static String readFromAssets(Context context, String filename) throws IOException { | ||||||
|  |         BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename))); | ||||||
|  | 
 | ||||||
|  |         // do reading, usually loop until end of file reading | ||||||
|  |         StringBuilder sb = new StringBuilder(); | ||||||
|  |         String mLine = reader.readLine(); | ||||||
|  |         while (mLine != null) { | ||||||
|  |             sb.append(mLine); // process line | ||||||
|  |             mLine = reader.readLine(); | ||||||
|  |         } | ||||||
|  |         reader.close(); | ||||||
|  |         return sb.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * This is our attempt to REALLY exit Orbot, and stop the background service |      * This is our attempt to REALLY exit Orbot, and stop the background service | ||||||
|  | @ -724,8 +749,6 @@ public class OrbotMainActivity extends AppCompatActivity | ||||||
|         String action = intent.getAction(); |         String action = intent.getAction(); | ||||||
|         Log.d(TAG, "handleIntents " + action); |         Log.d(TAG, "handleIntents " + action); | ||||||
| 
 | 
 | ||||||
|         //String type = intent.getType(); |  | ||||||
| 
 |  | ||||||
|         if (action == null) |         if (action == null) | ||||||
|             return; |             return; | ||||||
| 
 | 
 | ||||||
|  | @ -944,31 +967,7 @@ public class OrbotMainActivity extends AppCompatActivity | ||||||
|         if (request == REQUEST_SETTINGS && response == RESULT_OK) |         if (request == REQUEST_SETTINGS && response == RESULT_OK) | ||||||
|         { |         { | ||||||
|             OrbotApp.forceChangeLanguage(this); |             OrbotApp.forceChangeLanguage(this); | ||||||
|             if (data != null && data.getBooleanExtra("transproxywipe", false)) |  | ||||||
|             { |  | ||||||
| 
 | 
 | ||||||
|                     boolean result = flushTransProxy(); |  | ||||||
|                      |  | ||||||
|                     if (result) |  | ||||||
|                     { |  | ||||||
| 
 |  | ||||||
|                         Toast.makeText(this, R.string.transparent_proxy_rules_flushed_, Toast.LENGTH_SHORT).show(); |  | ||||||
|                           |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
| 
 |  | ||||||
|                         Toast.makeText(this, R.string.you_do_not_have_root_access_enabled, Toast.LENGTH_SHORT).show(); |  | ||||||
|                           |  | ||||||
|                     } |  | ||||||
|                  |  | ||||||
|             } |  | ||||||
|             else if (torStatus == TorServiceConstants.STATUS_ON) |  | ||||||
|             { |  | ||||||
|                 updateTransProxy(); |  | ||||||
|                // Toast.makeText(this, R.string.you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_, Toast.LENGTH_SHORT).show(); |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         else if (request == REQUEST_VPN) |         else if (request == REQUEST_VPN) | ||||||
|         { |         { | ||||||
|  | @ -1184,19 +1183,7 @@ public class OrbotMainActivity extends AppCompatActivity | ||||||
|         sendIntentToService(TorServiceConstants.CMD_VPN_CLEAR); |         sendIntentToService(TorServiceConstants.CMD_VPN_CLEAR); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean flushTransProxy () |        @Override | ||||||
|     { |  | ||||||
|         sendIntentToService(TorServiceConstants.CMD_FLUSH); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     private boolean updateTransProxy () |  | ||||||
|     { |  | ||||||
|         sendIntentToService(TorServiceConstants.CMD_UPDATE_TRANS_PROXY); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     protected void onResume() { |     protected void onResume() { | ||||||
|         super.onResume(); |         super.onResume(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ import android.content.SharedPreferences; | ||||||
| import android.os.Build; | import android.os.Build; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.preference.CheckBoxPreference; | import android.preference.CheckBoxPreference; | ||||||
| import android.preference.EditTextPreference; |  | ||||||
| import android.preference.ListPreference; | import android.preference.ListPreference; | ||||||
| import android.preference.Preference; | import android.preference.Preference; | ||||||
| import android.preference.Preference.OnPreferenceChangeListener; | import android.preference.Preference.OnPreferenceChangeListener; | ||||||
|  | @ -19,7 +18,6 @@ import android.util.Log; | ||||||
| 
 | 
 | ||||||
| import org.torproject.android.OrbotApp; | import org.torproject.android.OrbotApp; | ||||||
| import org.torproject.android.R; | import org.torproject.android.R; | ||||||
| import org.torproject.android.service.transproxy.TorTransProxy; |  | ||||||
| import org.torproject.android.ui.AppManager; | import org.torproject.android.ui.AppManager; | ||||||
| import org.torproject.android.service.util.TorServiceUtils; | import org.torproject.android.service.util.TorServiceUtils; | ||||||
| 
 | 
 | ||||||
|  | @ -30,14 +28,7 @@ public class SettingsPreferences | ||||||
| 		extends PreferenceActivity implements OnPreferenceClickListener { | 		extends PreferenceActivity implements OnPreferenceClickListener { | ||||||
|     private static final String TAG = "SettingsPreferences"; |     private static final String TAG = "SettingsPreferences"; | ||||||
| 
 | 
 | ||||||
| 	private CheckBoxPreference prefCBTransProxy = null; |  | ||||||
| 	private CheckBoxPreference prefcBTransProxyAll = null; |  | ||||||
|     private CheckBoxPreference prefcbTransTethering = null; |  | ||||||
| 
 |  | ||||||
| 	private Preference prefTransProxyFlush = null; |  | ||||||
| 	 |  | ||||||
| 	private Preference prefTransProxyApps = null; | 	private Preference prefTransProxyApps = null; | ||||||
| 	private CheckBoxPreference prefRequestRoot = null; |  | ||||||
| 	private ListPreference prefLocale = null; | 	private ListPreference prefLocale = null; | ||||||
| 	 | 	 | ||||||
|     protected void onCreate(Bundle savedInstanceState) { |     protected void onCreate(Bundle savedInstanceState) { | ||||||
|  | @ -47,9 +38,6 @@ public class SettingsPreferences | ||||||
|         getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS); |         getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS); | ||||||
|         SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); |         SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); | ||||||
| 
 | 
 | ||||||
|         prefRequestRoot = (CheckBoxPreference) findPreference("has_root"); |  | ||||||
|         prefRequestRoot.setOnPreferenceClickListener(this); |  | ||||||
| 
 |  | ||||||
|         prefLocale = (ListPreference) findPreference("pref_default_locale"); |         prefLocale = (ListPreference) findPreference("pref_default_locale"); | ||||||
|         prefLocale.setOnPreferenceClickListener(this); |         prefLocale.setOnPreferenceClickListener(this); | ||||||
|         Languages languages = Languages.get(this); |         Languages languages = Languages.get(this); | ||||||
|  | @ -76,38 +64,9 @@ public class SettingsPreferences | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         prefCBTransProxy = (CheckBoxPreference) findPreference("pref_transparent"); |  | ||||||
|         prefcBTransProxyAll = (CheckBoxPreference) findPreference("pref_transparent_all"); |  | ||||||
|         prefcbTransTethering = (CheckBoxPreference) findPreference("pref_transparent_tethering"); |  | ||||||
| 
 |  | ||||||
|         prefTransProxyFlush = (Preference) findPreference("pref_transproxy_flush"); |  | ||||||
|         prefTransProxyFlush.setOnPreferenceClickListener(new OnPreferenceClickListener() { |  | ||||||
| 
 |  | ||||||
|             @Override |  | ||||||
|             public boolean onPreferenceClick(Preference arg0) { |  | ||||||
| 
 |  | ||||||
|                 Intent data = new Intent(); |  | ||||||
|                 data.putExtra("transproxywipe", true); |  | ||||||
|                 setResult(RESULT_OK, data); |  | ||||||
| 
 |  | ||||||
|                 finish(); |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|         prefTransProxyApps = findPreference("pref_transparent_app_list"); |         prefTransProxyApps = findPreference("pref_transparent_app_list"); | ||||||
|         prefTransProxyApps.setOnPreferenceClickListener(this); |         prefTransProxyApps.setOnPreferenceClickListener(this); | ||||||
|         prefCBTransProxy.setOnPreferenceClickListener(this); |  | ||||||
|         prefcBTransProxyAll.setOnPreferenceClickListener(this); |  | ||||||
| 
 |  | ||||||
|         prefCBTransProxy.setEnabled(prefRequestRoot.isChecked()); |  | ||||||
|         prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked()); |  | ||||||
|         prefcbTransTethering.setEnabled(prefCBTransProxy.isChecked()); |  | ||||||
| 
 |  | ||||||
|         if (prefCBTransProxy.isChecked()) |  | ||||||
|         	prefTransProxyApps.setEnabled((!prefcBTransProxyAll.isChecked())); |  | ||||||
| 
 | 
 | ||||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) | ||||||
|         { |         { | ||||||
|  | @ -121,35 +80,6 @@ public class SettingsPreferences | ||||||
| 		 | 		 | ||||||
| 		setResult(RESULT_OK); | 		setResult(RESULT_OK); | ||||||
| 
 | 
 | ||||||
| 		if (preference == prefRequestRoot) |  | ||||||
| 		{ |  | ||||||
| 			if (prefRequestRoot.isChecked()) |  | ||||||
| 			{ |  | ||||||
| 
 |  | ||||||
|                 try { |  | ||||||
|                     TorTransProxy.testRoot(); |  | ||||||
|                     prefCBTransProxy.setEnabled(true); |  | ||||||
| 
 |  | ||||||
|                 } |  | ||||||
|                 catch (Exception e) |  | ||||||
|                 { |  | ||||||
|                     Log.d(OrbotApp.TAG,"root not yet enabled"); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		else if (preference == prefTransProxyApps) |  | ||||||
| 		{ |  | ||||||
| 			startActivity(new Intent(this, AppManager.class)); |  | ||||||
| 			 |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked()); |  | ||||||
| 			prefTransProxyApps.setEnabled(prefCBTransProxy.isChecked() && (!prefcBTransProxyAll.isChecked())); |  | ||||||
| 			 |  | ||||||
| 			 |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -13,9 +13,8 @@ import java.util.StringTokenizer; | ||||||
| import org.torproject.android.service.OrbotConstants; | import org.torproject.android.service.OrbotConstants; | ||||||
| import org.torproject.android.R; | import org.torproject.android.R; | ||||||
| import org.torproject.android.service.util.TorServiceUtils; | import org.torproject.android.service.util.TorServiceUtils; | ||||||
| import org.torproject.android.service.transproxy.TorifiedApp; | import org.torproject.android.service.vpn.TorifiedApp; | ||||||
| 
 | 
 | ||||||
| import android.app.Activity; |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
| import android.content.SharedPreferences.Editor; | import android.content.SharedPreferences.Editor; | ||||||
|  | @ -23,7 +22,6 @@ import android.content.pm.ApplicationInfo; | ||||||
| import android.content.pm.PackageInfo; | import android.content.pm.PackageInfo; | ||||||
| import android.content.pm.PackageManager; | import android.content.pm.PackageManager; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.support.v7.app.ActionBarActivity; |  | ||||||
| import android.support.v7.app.AppCompatActivity; | import android.support.v7.app.AppCompatActivity; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
|  |  | ||||||
|  | @ -54,25 +54,6 @@ | ||||||
| 				android:textColorLink="#ffffff" | 				android:textColorLink="#ffffff" | ||||||
| 				android:paddingLeft="15px"		 | 				android:paddingLeft="15px"		 | ||||||
| 				android:textColor="#ffffff" /> | 				android:textColor="#ffffff" /> | ||||||
| 			<TextView android:text="License: " |  | ||||||
| 				android:layout_width="fill_parent"  |  | ||||||
| 				android:layout_height="wrap_content" |  | ||||||
| 				android:paddingTop="15px" |  | ||||||
| 				android:paddingLeft="15px" |  | ||||||
| 				android:textStyle="bold" |  | ||||||
| 				android:textColor="#00ff00" />	 |  | ||||||
| 			<TextView android:text="@string/the_tor_license" |  | ||||||
| 				android:layout_width="fill_parent"  |  | ||||||
| 				android:layout_height="wrap_content" |  | ||||||
| 				android:paddingLeft="15px"								 |  | ||||||
| 				android:textColor="#ffffff" />	 |  | ||||||
| 			<TextView android:text="@string/https_torproject_org" |  | ||||||
| 				android:layout_width="fill_parent"  |  | ||||||
| 				android:layout_height="wrap_content" |  | ||||||
| 				android:autoLink="web" |  | ||||||
| 				android:textColorLink="#ffffff" |  | ||||||
| 				android:paddingLeft="15px"		 |  | ||||||
| 				android:textColor="#ffffff" />				 |  | ||||||
| 			<TextView android:text="@string/third_party_software" | 			<TextView android:text="@string/third_party_software" | ||||||
| 				android:layout_width="fill_parent"  | 				android:layout_width="fill_parent"  | ||||||
| 				android:layout_height="wrap_content"		 | 				android:layout_height="wrap_content"		 | ||||||
|  | @ -115,6 +96,22 @@ | ||||||
| 				android:textColorLink="#ffffff" | 				android:textColorLink="#ffffff" | ||||||
| 				android:paddingLeft="15px"	 | 				android:paddingLeft="15px"	 | ||||||
| 				android:textColor="#ffffff" /> | 				android:textColor="#ffffff" /> | ||||||
| 			</LinearLayout> | 
 | ||||||
|  | 			<TextView android:text="License: " | ||||||
|  | 				android:layout_width="fill_parent" | ||||||
|  | 				android:layout_height="wrap_content" | ||||||
|  | 				android:paddingTop="15px" | ||||||
|  | 				android:paddingLeft="15px" | ||||||
|  | 				android:textStyle="bold" | ||||||
|  | 				android:textColor="#00ff00" /> | ||||||
|  | 			<TextView | ||||||
|  | 				android:id="@+id/aboutother" | ||||||
|  | 				android:layout_width="fill_parent" | ||||||
|  | 				android:layout_height="wrap_content" | ||||||
|  | 				android:autoLink="web" | ||||||
|  | 				android:textColorLink="#ffffff" | ||||||
|  | 				android:paddingLeft="15px" | ||||||
|  | 				android:textColor="#ffffff" /> | ||||||
|  | 		</LinearLayout> | ||||||
| 		</ScrollView>			 | 		</ScrollView>			 | ||||||
| </LinearLayout> | </LinearLayout> | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ | ||||||
|   <string name="btn_cancel">Cancel</string> |   <string name="btn_cancel">Cancel</string> | ||||||
|   <!--Welcome Wizard strings (DJH)--> |   <!--Welcome Wizard strings (DJH)--> | ||||||
|   <string name="wizard_details">Some Orbot Details</string> |   <string name="wizard_details">Some Orbot Details</string> | ||||||
|   <string name="wizard_details_msg">Orbot is an open-source application that contains Tor, LibEvent and Polipo. It provides a local HTTP proxy (8118) and a SOCKS proxy (9050) into the Tor network. Orbot also has the ability, on rooted device, to send all internet traffic through Tor.</string> |   <string name="wizard_details_msg">Orbot is an open-source application that contains Tor, Obfs4Proxy, BadVPN Tun2Socks, LibEvent and Polipo. It provides a local HTTP proxy (8118) and a SOCKS proxy (9050) into the Tor network. Orbot also has the ability, on rooted device, to send all internet traffic through Tor.</string> | ||||||
|   <string name="wizard_permissions_root">Permission Granted</string> |   <string name="wizard_permissions_root">Permission Granted</string> | ||||||
|   <string name="wizard_permissions_stock">Orbot Permissions</string> |   <string name="wizard_permissions_stock">Orbot Permissions</string> | ||||||
|   <string name="wizard_premissions_msg_root">Excellent! We\'ve detected that you have root permissions enabled for Orbot. We will use this power wisely.</string> |   <string name="wizard_premissions_msg_root">Excellent! We\'ve detected that you have root permissions enabled for Orbot. We will use this power wisely.</string> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ buildscript { | ||||||
|         jcenter() |         jcenter() | ||||||
|     } |     } | ||||||
|     dependencies { |     dependencies { | ||||||
|         classpath 'com.android.tools.build:gradle:2.3.2' |         classpath 'com.android.tools.build:gradle:2.3.3' | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,8 +28,8 @@ android { | ||||||
| 
 | 
 | ||||||
| dependencies { | dependencies { | ||||||
|     compile project(':jsocksAndroid') |     compile project(':jsocksAndroid') | ||||||
|     compile project(':RootCommands') |  | ||||||
|     compile 'com.android.support:appcompat-v7:25.0.0' |     compile 'com.android.support:appcompat-v7:25.0.0' | ||||||
|  |     compile 'com.jrummyapps:android-shell:1.0.1' | ||||||
|     compile fileTree(dir: 'libs', include: ['*.jar','*.so']) |     compile fileTree(dir: 'libs', include: ['*.jar','*.so']) | ||||||
|     testCompile 'junit:junit:4.12' |     testCompile 'junit:junit:4.12' | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,12 +38,12 @@ import android.text.TextUtils; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.widget.RemoteViews; | import android.widget.RemoteViews; | ||||||
| 
 | 
 | ||||||
| import org.sufficientlysecure.rootcommands.Shell; | import com.jrummyapps.android.shell.CommandResult; | ||||||
| import org.sufficientlysecure.rootcommands.command.SimpleCommand; | import com.jrummyapps.android.shell.Shell; | ||||||
|  | 
 | ||||||
| import org.torproject.android.control.ConfigEntry; | import org.torproject.android.control.ConfigEntry; | ||||||
| import org.torproject.android.control.TorControlConnection; | import org.torproject.android.control.TorControlConnection; | ||||||
| import org.torproject.android.service.transproxy.TorTransProxy; | import org.torproject.android.service.vpn.TorifiedApp; | ||||||
| import org.torproject.android.service.transproxy.TorifiedApp; |  | ||||||
| import org.torproject.android.service.util.DummyActivity; | import org.torproject.android.service.util.DummyActivity; | ||||||
| import org.torproject.android.service.util.Prefs; | import org.torproject.android.service.util.Prefs; | ||||||
| import org.torproject.android.service.util.TorResourceInstaller; | import org.torproject.android.service.util.TorResourceInstaller; | ||||||
|  | @ -105,8 +105,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
| 
 | 
 | ||||||
|     private File fileControlPort; |     private File fileControlPort; | ||||||
| 
 | 
 | ||||||
|     private TorTransProxy mTransProxy; |  | ||||||
| 
 |  | ||||||
|     private boolean mConnectivity = true; |     private boolean mConnectivity = true; | ||||||
|     private int mNetworkType = -1; |     private int mNetworkType = -1; | ||||||
| 
 | 
 | ||||||
|  | @ -127,17 +125,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|     public static File fileTor; |     public static File fileTor; | ||||||
|     public static File filePolipo; |     public static File filePolipo; | ||||||
|     public static File fileObfsclient; |     public static File fileObfsclient; | ||||||
|     public static File fileXtables; |  | ||||||
|     public static File fileTorRc; |     public static File fileTorRc; | ||||||
|     private File mHSBasePath; |     private File mHSBasePath; | ||||||
| 
 | 
 | ||||||
|     private Shell mShell; |  | ||||||
|     private Shell mShellPolipo; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     private ArrayList<Bridge> alBridges = null; |     private ArrayList<Bridge> alBridges = null; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     private static final Uri HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs"); |     private static final Uri HS_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers/hs"); | ||||||
|     private static final Uri COOKIE_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers.cookie/cookie"); |     private static final Uri COOKIE_CONTENT_URI = Uri.parse("content://org.torproject.android.ui.hiddenservices.providers.cookie/cookie"); | ||||||
| 
 | 
 | ||||||
|  | @ -410,10 +402,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|                     requestTorRereadConfig(); |                     requestTorRereadConfig(); | ||||||
|                 } else if (action.equals(CMD_NEWNYM)) { |                 } else if (action.equals(CMD_NEWNYM)) { | ||||||
|                     newIdentity(); |                     newIdentity(); | ||||||
|                 } else if (action.equals(CMD_FLUSH)) { |  | ||||||
|                     flushTransparentProxyRules(); |  | ||||||
|                 } else if (action.equals(CMD_UPDATE_TRANS_PROXY)) { |  | ||||||
|                     processTransparentProxying(); |  | ||||||
|                 } else if (action.equals(CMD_VPN)) { |                 } else if (action.equals(CMD_VPN)) { | ||||||
|                     startVPNService(); |                     startVPNService(); | ||||||
|                 } else if (action.equals(CMD_VPN_CLEAR)) { |                 } else if (action.equals(CMD_VPN_CLEAR)) { | ||||||
|  | @ -442,6 +430,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
| 
 | 
 | ||||||
|         stopTor(); |         stopTor(); | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             mShell.close(); |             mShell.close(); | ||||||
|  | @ -449,7 +438,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|         catch (IOException ioe) |         catch (IOException ioe) | ||||||
|         { |         { | ||||||
|             Log.d(TAG, "Error closing shell",ioe); |             Log.d(TAG, "Error closing shell",ioe); | ||||||
|         } |         }**/ | ||||||
| 
 | 
 | ||||||
|         super.onDestroy(); |         super.onDestroy(); | ||||||
|     } |     } | ||||||
|  | @ -477,11 +466,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|             //stop the foreground priority and make sure to remove the persistant notification |             //stop the foreground priority and make sure to remove the persistant notification | ||||||
|             stopForeground(true); |             stopForeground(true); | ||||||
| 
 | 
 | ||||||
|             if (Prefs.useRoot() && Prefs.useTransparentProxying()) |  | ||||||
|             { |  | ||||||
|                 disableTransparentProxy(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             sendCallbackLogMessage(getString(R.string.status_disabled)); |             sendCallbackLogMessage(getString(R.string.status_disabled)); | ||||||
|         } |         } | ||||||
|         catch (Exception e) |         catch (Exception e) | ||||||
|  | @ -516,12 +500,13 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|             conn = null; |             conn = null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|         if (mShellPolipo != null) |         if (mShellPolipo != null) | ||||||
|         { |         { | ||||||
|             mShellPolipo.close(); |             mShellPolipo.close(); | ||||||
|             //logNotice("Polipo exited with value: " + exitValue); |             //logNotice("Polipo exited with value: " + exitValue); | ||||||
| 
 | 
 | ||||||
|         } |         }**/ | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -560,12 +545,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|             appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE); |             appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE); | ||||||
|             appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE); |             appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE); | ||||||
| 
 | 
 | ||||||
|             mShell = Shell.startShell(); |             //mShell = Shell.startShell(); | ||||||
| 
 | 
 | ||||||
|             fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); |             fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); | ||||||
|             filePolipo = new File(appBinHome, TorServiceConstants.POLIPO_ASSET_KEY); |             filePolipo = new File(appBinHome, TorServiceConstants.POLIPO_ASSET_KEY); | ||||||
|             fileObfsclient = new File(appBinHome, TorServiceConstants.OBFSCLIENT_ASSET_KEY); |             fileObfsclient = new File(appBinHome, TorServiceConstants.OBFSCLIENT_ASSET_KEY); | ||||||
|             fileXtables = new File(appBinHome, TorServiceConstants.IPTABLES_ASSET_KEY); |  | ||||||
|             fileTorRc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY); |             fileTorRc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY); | ||||||
| 
 | 
 | ||||||
|             mHSBasePath = new File( |             mHSBasePath = new File( | ||||||
|  | @ -802,12 +786,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|             if (mPortHTTP != -1) |             if (mPortHTTP != -1) | ||||||
|                 runPolipoShellCmd(); |                 runPolipoShellCmd(); | ||||||
| 
 | 
 | ||||||
|             if (Prefs.useRoot() && Prefs.useTransparentProxying()) |  | ||||||
|             { |  | ||||||
|                 disableTransparentProxy(); |  | ||||||
|                 enableTransparentProxy(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Tor is running, update new .onion names at db |             // Tor is running, update new .onion names at db | ||||||
|             ContentResolver mCR = getApplicationContext().getContentResolver(); |             ContentResolver mCR = getApplicationContext().getContentResolver(); | ||||||
|             Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null); |             Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null); | ||||||
|  | @ -868,125 +846,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean flushTransparentProxyRules () { |  | ||||||
| 
 | 
 | ||||||
|         try { |  | ||||||
|             if (Prefs.useRoot()) { |  | ||||||
|                 if (mTransProxy == null) |  | ||||||
|                     mTransProxy = new TorTransProxy(this, fileXtables); |  | ||||||
| 
 |  | ||||||
|                 try { |  | ||||||
|                     mTransProxy.flushTransproxyRules(this); |  | ||||||
|                 } catch (Exception e) { |  | ||||||
|                     e.printStackTrace(); |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return true; |  | ||||||
|             } else { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         catch (IOException ioe) |  | ||||||
|         { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     /* |  | ||||||
|      * activate means whether to apply the users preferences |  | ||||||
|      * or clear them out |  | ||||||
|      *  |  | ||||||
|      * the idea is that if Tor is off then transproxy is off |  | ||||||
|      */ |  | ||||||
|     private boolean enableTransparentProxy () throws Exception |  | ||||||
|      { |  | ||||||
|          |  | ||||||
|          if (mTransProxy == null) |  | ||||||
|          { |  | ||||||
|              mTransProxy = new TorTransProxy(this, fileXtables); |  | ||||||
|               |  | ||||||
|          } |  | ||||||
| 
 |  | ||||||
|         SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); |  | ||||||
|         String transProxy = prefs.getString("pref_transport", TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT+""); |  | ||||||
|         String dnsPort = prefs.getString("pref_dnsport", TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT+""); |  | ||||||
|          |  | ||||||
|         if (transProxy.indexOf(':')!=-1) //we just want the port for this |  | ||||||
|             transProxy = transProxy.split(":")[1]; |  | ||||||
|          |  | ||||||
|         if (dnsPort.indexOf(':')!=-1) //we just want the port for this |  | ||||||
|             dnsPort = dnsPort.split(":")[1]; |  | ||||||
|          |  | ||||||
|         mTransProxy.setTransProxyPort(Integer.parseInt(transProxy)); |  | ||||||
|         mTransProxy.setDNSPort(Integer.parseInt(dnsPort)); |  | ||||||
|          |  | ||||||
|         int code = 0; // Default state is "okay" |  | ||||||
|          |  | ||||||
|         if(Prefs.transparentProxyAll()) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             code = mTransProxy.setTransparentProxyingAll(this, true); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             ArrayList<TorifiedApp> apps = TorTransProxy.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); |  | ||||||
| 
 |  | ||||||
|             code = mTransProxy.setTransparentProxyingByApp(this,apps, true); |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         debug ("TorTransProxy resp code: " + code); |  | ||||||
|          |  | ||||||
|         if (code == 0) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             if (Prefs.transparentTethering()) |  | ||||||
|             { |  | ||||||
|                 showToolbarNotification(getString(R.string.transproxy_enabled_for_tethering_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor); |  | ||||||
| 
 |  | ||||||
|                 mTransProxy.enableTetheringRules(this); |  | ||||||
| 
 |  | ||||||
|                    |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 showToolbarNotification(getString(R.string.transparent_proxying_enabled), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor); |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             showToolbarNotification(getString(R.string.warning_error_starting_transparent_proxying_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         return true; |  | ||||||
|      } |  | ||||||
| 
 |  | ||||||
|     /* |  | ||||||
|      * activate means whether to apply the users preferences |  | ||||||
|      * or clear them out |  | ||||||
|      *  |  | ||||||
|      * the idea is that if Tor is off then transproxy is off |  | ||||||
|      */ |  | ||||||
|     private boolean disableTransparentProxy () throws Exception |  | ||||||
|      { |  | ||||||
|          |  | ||||||
|          debug ("Transparent Proxying: disabling..."); |  | ||||||
| 
 |  | ||||||
|          if (mTransProxy == null) |  | ||||||
|              mTransProxy = new TorTransProxy(this, fileXtables); |  | ||||||
|   |  | ||||||
|          mTransProxy.setTransparentProxyingAll(this, false); |  | ||||||
| 
 |  | ||||||
|         ArrayList<TorifiedApp> apps = TorTransProxy.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); |  | ||||||
|         mTransProxy.setTransparentProxyingByApp(this, apps, false); |  | ||||||
| 
 |  | ||||||
|          mTransProxy.closeShell(); |  | ||||||
|          mTransProxy = null; |  | ||||||
| 
 |  | ||||||
|          return true; |  | ||||||
|      } |  | ||||||
| 
 | 
 | ||||||
|     private boolean runTorShellCmd() throws Exception |     private boolean runTorShellCmd() throws Exception | ||||||
|     { |     { | ||||||
|  | @ -1055,13 +915,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
| 
 | 
 | ||||||
|     private int exec (String cmd, boolean wait) throws Exception |     private int exec (String cmd, boolean wait) throws Exception | ||||||
|     { |     { | ||||||
|  |         CommandResult shellResult = Shell.run(cmd); | ||||||
|  |         shellResult.isSuccessful(); | ||||||
|  |         debug("CMD: " + cmd + "; SUCCESS=" + shellResult.isSuccessful()); | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|         SimpleCommand command = new SimpleCommand(cmd); |         SimpleCommand command = new SimpleCommand(cmd); | ||||||
|         mShell.add(command); |         mShell.add(command); | ||||||
| 
 |  | ||||||
|         if (wait) |         if (wait) | ||||||
|             command.waitForFinish(); |             command.waitForFinish(); | ||||||
| 
 |  | ||||||
|         return command.getExitCode(); |         return command.getExitCode(); | ||||||
|  |          **/ | ||||||
|  |         return shellResult.exitCode; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     private void updatePolipoConfig () throws FileNotFoundException, IOException |     private void updatePolipoConfig () throws FileNotFoundException, IOException | ||||||
|  | @ -1092,12 +957,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|         String polipoConfigPath = new File(appBinHome, POLIPOCONFIG_ASSET_KEY).getCanonicalPath(); |         String polipoConfigPath = new File(appBinHome, POLIPOCONFIG_ASSET_KEY).getCanonicalPath(); | ||||||
|         String cmd = (filePolipo.getCanonicalPath() + " -c " + polipoConfigPath); |         String cmd = (filePolipo.getCanonicalPath() + " -c " + polipoConfigPath); | ||||||
| 
 | 
 | ||||||
|         if (mShellPolipo != null) |         CommandResult shellResult = Shell.run(cmd); | ||||||
|             mShellPolipo.close(); |  | ||||||
| 
 |  | ||||||
|         mShellPolipo = Shell.startShell(); |  | ||||||
|         SimpleCommand cmdPolipo = new SimpleCommand(cmd); |  | ||||||
|         mShellPolipo.add(cmdPolipo); |  | ||||||
| 
 | 
 | ||||||
|         sendCallbackLogMessage(getString(R.string.privoxy_is_running_on_port_) + mPortHTTP); |         sendCallbackLogMessage(getString(R.string.privoxy_is_running_on_port_) + mPortHTTP); | ||||||
|              |              | ||||||
|  | @ -1277,28 +1137,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|      |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         public void processTransparentProxying() { |  | ||||||
|             try{ |  | ||||||
|                 if (Prefs.useRoot()) |  | ||||||
|                 { |  | ||||||
|                     if (Prefs.useTransparentProxying()){ |  | ||||||
|                         enableTransparentProxy(); |  | ||||||
|                     } else { |  | ||||||
|                         disableTransparentProxy(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 // TODO Auto-generated catch block |  | ||||||
|                 e.printStackTrace(); |  | ||||||
|             } |  | ||||||
|              |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public String getInfo (String key) { |         public String getInfo (String key) { | ||||||
|             try { |             try { | ||||||
|                 if(conn !=null){ |                 if(conn !=null){ | ||||||
|  | @ -1587,25 +1425,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|                     showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor); |                     showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 try { |  | ||||||
| 
 |  | ||||||
|                     if (mConnectivity) |  | ||||||
|                     { |  | ||||||
|                         if (Prefs.useRoot() && Prefs.useTransparentProxying() && Prefs.transProxyNetworkRefresh()) |  | ||||||
|                         { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                             disableTransparentProxy(); |  | ||||||
|                             enableTransparentProxy(); |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                 } catch (Exception e) { |  | ||||||
|                     logException ("error updating state after network restart",e); |  | ||||||
|                 } |  | ||||||
| 		             |  | ||||||
| 
 |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|              |              | ||||||
|  | @ -2045,7 +1864,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon | ||||||
|     { |     { | ||||||
|         debug ("clearing VPN Proxy"); |         debug ("clearing VPN Proxy"); | ||||||
|         Prefs.putUseVpn(false); |         Prefs.putUseVpn(false); | ||||||
|         processTransparentProxying(); |  | ||||||
| 
 | 
 | ||||||
|         Intent intentVpn = new Intent(this,TorVpnService.class); |         Intent intentVpn = new Intent(this,TorVpnService.class); | ||||||
|         intentVpn.setAction("stop"); |         intentVpn.setAction("stop"); | ||||||
|  |  | ||||||
|  | @ -1,997 +0,0 @@ | ||||||
| package org.torproject.android.service.transproxy; |  | ||||||
| 
 |  | ||||||
| import java.io.DataOutputStream; |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Arrays; |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.Iterator; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.StringTokenizer; |  | ||||||
| 
 |  | ||||||
| import android.content.Context; |  | ||||||
| import android.content.SharedPreferences; |  | ||||||
| import android.content.pm.ApplicationInfo; |  | ||||||
| import android.content.pm.PackageInfo; |  | ||||||
| import android.content.pm.PackageManager; |  | ||||||
| 
 |  | ||||||
| import org.sufficientlysecure.rootcommands.Shell; |  | ||||||
| import org.sufficientlysecure.rootcommands.command.SimpleCommand; |  | ||||||
| import org.torproject.android.service.OrbotConstants; |  | ||||||
| import org.torproject.android.service.util.Prefs; |  | ||||||
| import org.torproject.android.service.TorService; |  | ||||||
| import org.torproject.android.service.TorServiceConstants; |  | ||||||
| 
 |  | ||||||
| public class TorTransProxy implements TorServiceConstants { |  | ||||||
| 	 |  | ||||||
| 	private String mSysIptables = null; |  | ||||||
| 	private TorService mTorService = null; |  | ||||||
| 	private File mFileXtables = null; |  | ||||||
| 	 |  | ||||||
| 	private final static String ALLOW_LOCAL = " ! -d 127.0.0.1"; |  | ||||||
| 
 |  | ||||||
| 	private int mTransProxyPort = TOR_TRANSPROXY_PORT_DEFAULT; |  | ||||||
| 	private int mDNSPort = TOR_DNS_PORT_DEFAULT; |  | ||||||
| 
 |  | ||||||
| 	private Shell mShell; |  | ||||||
| 
 |  | ||||||
|     public TorTransProxy (TorService torService, File fileXTables) throws IOException |  | ||||||
| 	{ |  | ||||||
| 		mTorService = torService; |  | ||||||
| 		mFileXtables = fileXTables; |  | ||||||
| 
 |  | ||||||
| 		// start root shell |  | ||||||
| 		mShell = Shell.startRootShell(); |  | ||||||
| 
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
|     public static boolean testRoot () throws IOException |  | ||||||
|     { |  | ||||||
|         Runtime.getRuntime().exec("su"); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 	 |  | ||||||
| 	public void setTransProxyPort (int transProxyPort) |  | ||||||
| 	{ |  | ||||||
| 		mTransProxyPort = transProxyPort; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public void setDNSPort (int dnsPort) |  | ||||||
| 	{ |  | ||||||
| 		mDNSPort = dnsPort; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public String getIpTablesPath (Context context) |  | ||||||
| 	{ |  | ||||||
| 
 |  | ||||||
| 		String ipTablesPath = null; |  | ||||||
| 
 |  | ||||||
| 		if (Prefs.useSystemIpTables()) |  | ||||||
| 		{ |  | ||||||
| 			ipTablesPath = findSystemIPTables(); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			ipTablesPath = mFileXtables.getAbsolutePath(); |  | ||||||
| 			ipTablesPath += " iptables"; //append subcommand since we are using xtables now |  | ||||||
| 			 |  | ||||||
| 		} |  | ||||||
| 			 |  | ||||||
| 		return ipTablesPath; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public String getIp6TablesPath (Context context) |  | ||||||
| 	{ |  | ||||||
| 
 |  | ||||||
| 		String ipTablesPath = null; |  | ||||||
| 		 |  | ||||||
| 		if (Prefs.useSystemIpTables()) |  | ||||||
| 		{ |  | ||||||
| 			ipTablesPath = findSystemIP6Tables(); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			ipTablesPath = mFileXtables.getAbsolutePath(); |  | ||||||
| 			ipTablesPath += " ip6tables"; //append subcommand since we are using xtables now |  | ||||||
| 			 |  | ||||||
| 		} |  | ||||||
| 			 |  | ||||||
| 		return ipTablesPath; |  | ||||||
| 	 |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	private String findSystemIPTables () |  | ||||||
| 	{ |  | ||||||
| 		if (mSysIptables == null) { |  | ||||||
| 			//if the user wants us to use the built-in iptables, then we have to find it |  | ||||||
| 			File fileIpt = new File("/system/xbin/iptables"); |  | ||||||
| 
 |  | ||||||
| 			if (fileIpt.exists()) |  | ||||||
| 				mSysIptables = fileIpt.getAbsolutePath(); |  | ||||||
| 			else { |  | ||||||
| 
 |  | ||||||
| 				fileIpt = new File("/system/bin/iptables"); |  | ||||||
| 
 |  | ||||||
| 				if (fileIpt.exists()) |  | ||||||
| 					mSysIptables = fileIpt.getAbsolutePath(); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return mSysIptables; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 
 |  | ||||||
| 	 |  | ||||||
| 	private String findSystemIP6Tables () |  | ||||||
| 	{ |  | ||||||
| 		 |  | ||||||
| 		//if the user wants us to use the built-in iptables, then we have to find it |  | ||||||
| 		File fileIpt = new File("/system/xbin/ip6tables"); |  | ||||||
| 		 |  | ||||||
| 		if (fileIpt.exists()) |  | ||||||
| 			mSysIptables = fileIpt.getAbsolutePath(); |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 		 |  | ||||||
| 			fileIpt = new File("/system/bin/ip6tables"); |  | ||||||
| 			 |  | ||||||
| 			if (fileIpt.exists()) |  | ||||||
| 				mSysIptables = fileIpt.getAbsolutePath(); |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		 |  | ||||||
| 		return mSysIptables; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	public int flushIptablesAll(Context context) throws Exception { |  | ||||||
| 		 |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 	 |  | ||||||
|     	final StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
| 
 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(" -F || exit\n"); |  | ||||||
| 	 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(" -F || exit\n"); |  | ||||||
|     	 |  | ||||||
|     	String[] cmd = {script.toString()};	    	 |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmd, res, true, true);		 |  | ||||||
| 		String msg = res.toString(); |  | ||||||
| 		 |  | ||||||
| 		TorService.logMessage(cmd[0] + ";errCode=" + code + ";resp=" + msg); |  | ||||||
| 			 |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
| 	 |  | ||||||
| 	}*/ |  | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	public static int purgeIptablesByApp(Context context, TorifiedApp[] apps) throws Exception { |  | ||||||
| 
 |  | ||||||
| 		//restoreDNSResolvConf(); //not working yet |  | ||||||
| 		 |  | ||||||
| 		String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); |  | ||||||
| 		 |  | ||||||
|     	final StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
|     	 |  | ||||||
| 		for (int i = 0; i < apps.length; i++) |  | ||||||
| 		{ |  | ||||||
| 			//flush nat for every app |  | ||||||
| 			script.append(ipTablesPath); |  | ||||||
| 			script.append(" -t nat -m owner --uid-owner "); |  | ||||||
| 			script.append(tApp.getUid()); |  | ||||||
| 			script.append(" -F || exit\n"); |  | ||||||
|     public static ArrayList<TorifiedApp> getApps (Context context, SharedPreferences prefs) |  | ||||||
|     { |  | ||||||
| 
 |  | ||||||
|         String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, ""); |  | ||||||
|         String[] tordApps; |  | ||||||
| 
 |  | ||||||
|         StringTokenizer st = new StringTokenizer(tordAppString,"|"); |  | ||||||
|         tordApps = new String[st.countTokens()]; |  | ||||||
|         int tordIdx = 0; |  | ||||||
|         while (st.hasMoreTokens()) |  | ||||||
|         { |  | ||||||
|             tordApps[tordIdx++] = st.nextToken(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         Arrays.sort(tordApps); |  | ||||||
| 
 |  | ||||||
|         //else load the apps up |  | ||||||
|         PackageManager pMgr = context.getPackageManager(); |  | ||||||
| 
 |  | ||||||
|         List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0); |  | ||||||
| 
 |  | ||||||
|         Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator(); |  | ||||||
| 
 |  | ||||||
|         ArrayList<TorifiedApp> apps = new ArrayList<TorifiedApp>(); |  | ||||||
| 
 |  | ||||||
|         ApplicationInfo aInfo = null; |  | ||||||
| 
 |  | ||||||
|         int appIdx = 0; |  | ||||||
|         TorifiedApp app = null; |  | ||||||
| 
 |  | ||||||
|         while (itAppInfo.hasNext()) |  | ||||||
|         { |  | ||||||
|             aInfo = itAppInfo.next(); |  | ||||||
| 
 |  | ||||||
|             app = new TorifiedApp(); |  | ||||||
| 
 |  | ||||||
|             try { |  | ||||||
|                 PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS); |  | ||||||
| 
 |  | ||||||
|                 if (pInfo != null && pInfo.requestedPermissions != null) |  | ||||||
|                 { |  | ||||||
|                     for (String permInfo:pInfo.requestedPermissions) |  | ||||||
|                     { |  | ||||||
|                         if (permInfo.equals("android.permission.INTERNET")) |  | ||||||
|                         { |  | ||||||
|                             app.setUsesInternet(true); |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 // TODO Auto-generated catch block |  | ||||||
|                 e.printStackTrace(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) |  | ||||||
|             { |  | ||||||
|                 //System app |  | ||||||
|                 app.setUsesInternet(true); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             if (!app.usesInternet()) |  | ||||||
|                 continue; |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 apps.add(app); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             app.setEnabled(aInfo.enabled); |  | ||||||
|             app.setUid(aInfo.uid); |  | ||||||
|             app.setUsername(pMgr.getNameForUid(app.getUid())); |  | ||||||
|             app.setProcname(aInfo.processName); |  | ||||||
|             app.setPackageName(aInfo.packageName); |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 app.setName(pMgr.getApplicationLabel(aInfo).toString()); |  | ||||||
|             } |  | ||||||
|             catch (Exception e) |  | ||||||
|             { |  | ||||||
|                 app.setName(aInfo.packageName); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             //app.setIcon(pMgr.getApplicationIcon(aInfo)); |  | ||||||
| 
 |  | ||||||
|             // check if this application is allowed |  | ||||||
|             if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) { |  | ||||||
|                 app.setTorified(true); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 app.setTorified(false); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             appIdx++; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         Collections.sort(apps); |  | ||||||
| 
 |  | ||||||
|         return apps; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 		 |  | ||||||
| 			script.append(ipTablesPath); |  | ||||||
| 			script.append(" -t filter -m owner --uid-owner "); |  | ||||||
| 			script.append(tApp.getUid()); |  | ||||||
| 			script.append(" -F || exit\n"); |  | ||||||
| 				 |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
|     	 |  | ||||||
|     	String[] cmd = {script.toString()};	    	 |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmd, res, true, true);		 |  | ||||||
| 		String msg = res.toString(); |  | ||||||
| 		logNotice(cmd[0] + ";errCode=" + code + ";resp=" + msg); |  | ||||||
| 			 |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
| 		 |  | ||||||
| 	}*/ |  | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	 // 9/19/2010 - NF This code is in process... /etc path on System partition |  | ||||||
| 	 // is read-only on Android for now. |  | ||||||
| 	public static int redirectDNSResolvConf () throws Exception |  | ||||||
| 	{ |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
|     	 |  | ||||||
| 		//mv resolv.conf to resolve.conf.bak |  | ||||||
| 		String cmd = "mv /etc/resolv.conf /etc/resolv.conf.bak"; |  | ||||||
| 		script.append(cmd); |  | ||||||
| 		 |  | ||||||
| 		//create new resolve.conf pointing to localhost/127.0.0.1 |  | ||||||
| 		cmd = "echo \"nameserver 127.0.0.1\" > /etc/resolv.conf"; |  | ||||||
| 		script.append(cmd); |  | ||||||
| 		 |  | ||||||
| 		String[] cmdFlush = {script.toString()}; |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true); |  | ||||||
| 		//String msg = res.toString(); //get stdout from command |  | ||||||
| 		 |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public static int restoreDNSResolvConf () throws Exception |  | ||||||
| 	{ |  | ||||||
| 		StringBuilder script = new StringBuilder(); |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
|     	 |  | ||||||
| 		//mv resolv.conf to resolve.conf.bak |  | ||||||
| 		String cmd = "mv /etc/resolv.conf.bak /etc/resolv.conf"; |  | ||||||
| 		script.append(cmd); |  | ||||||
| 		script.append(" || exit\n"); |  | ||||||
| 		 |  | ||||||
| 		String[] cmdFlush = {script.toString()}; |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true); |  | ||||||
| 		//String msg = res.toString(); //get stdout from command |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
| 	} |  | ||||||
| 	*/ |  | ||||||
| 	/* |  | ||||||
| 	public int testOwnerModule(Context context, String ipTablesPath) throws Exception |  | ||||||
| 	{ |  | ||||||
| 
 |  | ||||||
| 		TorBinaryInstaller.assertIpTablesBinaries(context, false); |  | ||||||
| 		 |  | ||||||
| 		boolean runRoot = true; |  | ||||||
|     	boolean waitFor = true; |  | ||||||
|     	 |  | ||||||
|     	int torUid = context.getApplicationInfo().uid; |  | ||||||
| 
 |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
|     	 |  | ||||||
|     	// Allow everything for Tor |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -A OUTPUT"); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(" -m owner --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 		script.append(" || exit\n"); |  | ||||||
| 		 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -D OUTPUT"); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(" -m owner --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 		script.append(" || exit\n"); |  | ||||||
| 		 |  | ||||||
| 		String[] cmdAdd = {script.toString()};    	 |  | ||||||
|     	 |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmdAdd, res, runRoot, waitFor); |  | ||||||
| 		String msg = res.toString(); |  | ||||||
| 		 |  | ||||||
| 		if (mTorService != null) |  | ||||||
| 		logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg); |  | ||||||
| 		 |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
|     }	 |  | ||||||
| 	*/ |  | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	public int clearTransparentProxyingByApp (Context context, ArrayList<TorifiedApp> apps) throws Exception |  | ||||||
| 	{ |  | ||||||
| 		boolean runRoot = true; |  | ||||||
|     	boolean waitFor = true; |  | ||||||
|     	 |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 		 |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder res = new StringBuilder(); |  | ||||||
|     	int code = -1; |  | ||||||
|     	 |  | ||||||
|     	String chainName = "ORBOT"; |  | ||||||
| 		String jumpChainName = "OUTPUT"; |  | ||||||
| 		 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
|     	script.append(" --flush ").append(chainName); //delete previous user-defined chain |  | ||||||
|     	script.append(" || exit\n"); |  | ||||||
|     	 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
|     	script.append(" -D ").append(jumpChainName); |  | ||||||
|     	script.append(" -j ").append(chainName); |  | ||||||
|     	script.append(" || exit\n"); |  | ||||||
|     	 |  | ||||||
|     	script.append(ipTablesPath); |  | ||||||
|     	script.append(" -X ").append(chainName); //delete previous user-defined chain |  | ||||||
|     	script.append(" || exit\n"); |  | ||||||
| 
 |  | ||||||
| 		String[] cmdAdd = {script.toString()};    	 |  | ||||||
|     		 |  | ||||||
| 		code = TorServiceUtils.doShellCommand(cmdAdd, res, runRoot, waitFor); |  | ||||||
| 		String msg = res.toString(); |  | ||||||
| 		 |  | ||||||
| 		logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg); |  | ||||||
| 		 |  | ||||||
| 		return code; |  | ||||||
| 	}*/ |  | ||||||
| 	 |  | ||||||
| 	public int setTransparentProxyingByApp(Context context, ArrayList<TorifiedApp> apps, boolean enableRule) throws Exception |  | ||||||
| 	{ |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 		 |  | ||||||
|     	//StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
| 		String action = " -A "; |  | ||||||
|     	String srcChainName = "OUTPUT"; |  | ||||||
| 
 |  | ||||||
| 		if (!enableRule) |  | ||||||
| 			action = " -D "; |  | ||||||
| 		 |  | ||||||
|     	//run the delete commands in a separate process as it might error out |  | ||||||
|     	//String[] cmdExecClear = {script.toString()};    	    	 |  | ||||||
| 		//code = TorServiceUtils.doShellCommand(cmdExecClear, res, runRoot, waitFor); |  | ||||||
| 		 |  | ||||||
| 		//reset script |  | ||||||
| 		 |  | ||||||
|     	int lastExit = -1; |  | ||||||
|     	StringBuilder script;    	 |  | ||||||
|     	 |  | ||||||
| 
 |  | ||||||
| 		// Same for DNS |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p udp"); |  | ||||||
| 		//script.append(" -m owner --uid-owner "); |  | ||||||
| 		//script.append(tApp.getUid()); |  | ||||||
| 		//script.append(" -m udp --dport ");  |  | ||||||
| 		script.append(" --dport "); |  | ||||||
| 		script.append(STANDARD_DNS_PORT); |  | ||||||
| 		script.append(" -j REDIRECT --to-ports "); |  | ||||||
| 		script.append(mDNSPort); |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		 |  | ||||||
|     	// Allow everything for Tor |  | ||||||
|     	 |  | ||||||
| 		//build up array of shell cmds to execute under one root context |  | ||||||
| 		for (TorifiedApp tApp:apps) |  | ||||||
| 		{ |  | ||||||
| 
 |  | ||||||
| 			if (((!enableRule) || tApp.isTorified()) |  | ||||||
| 					&& (!tApp.getUsername().equals(TOR_APP_USERNAME)) |  | ||||||
| 					) //if app is set to true |  | ||||||
| 			{ |  | ||||||
| 				 |  | ||||||
| 				 |  | ||||||
| 				logMessage("transproxy for app: " + tApp.getUsername() + " (" + tApp.getUid() + "): enable=" + enableRule); |  | ||||||
| 				 |  | ||||||
| 				dropAllIPv6Traffic(context, tApp.getUid(),enableRule); |  | ||||||
| 				 |  | ||||||
| 		    	script = new StringBuilder(); |  | ||||||
| 
 |  | ||||||
| 				// Allow loopback |  | ||||||
| 		    	/** |  | ||||||
| 				script.append(ipTablesPath); |  | ||||||
| 				script.append(" -t filter"); |  | ||||||
| 		        script.append(action).append(srcChainName); |  | ||||||
| 				script.append(" -m owner --uid-owner "); |  | ||||||
| 				script.append(tApp.getUid()); |  | ||||||
| 				script.append(" -o lo"); |  | ||||||
| 				script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 				executeCommand (shell, script.toString()); |  | ||||||
| 				script = new StringBuilder(); |  | ||||||
| 				**/ |  | ||||||
| 				 |  | ||||||
| 				// Set up port redirection |  | ||||||
| 		    	script.append(ipTablesPath); |  | ||||||
| 		    	script.append(" -t nat"); |  | ||||||
| 		    	script.append(action).append(srcChainName);				 |  | ||||||
| 				script.append(" -p tcp"); |  | ||||||
| 				script.append(ALLOW_LOCAL); |  | ||||||
| 				script.append(" -m owner --uid-owner "); |  | ||||||
| 				script.append(tApp.getUid()); |  | ||||||
| 				script.append(" -m tcp --syn"); |  | ||||||
| 				script.append(" -j REDIRECT --to-ports "); |  | ||||||
| 				script.append(mTransProxyPort); |  | ||||||
| 				 |  | ||||||
| 				executeCommand (script.toString()); |  | ||||||
| 				 |  | ||||||
| 				 |  | ||||||
| 				script = new StringBuilder(); |  | ||||||
| 				 |  | ||||||
| 				// Reject all other outbound packets |  | ||||||
| 				script.append(ipTablesPath); |  | ||||||
| 				script.append(" -t filter"); |  | ||||||
| 		        script.append(action).append(srcChainName); |  | ||||||
| 				script.append(" -m owner --uid-owner "); |  | ||||||
| 				script.append(tApp.getUid());				 |  | ||||||
| 				script.append(ALLOW_LOCAL); |  | ||||||
| 				script.append(" -j REJECT"); |  | ||||||
| 
 |  | ||||||
| 				lastExit = executeCommand (script.toString()); |  | ||||||
| 				 |  | ||||||
| 		 |  | ||||||
| 			}		 |  | ||||||
| 		}		 |  | ||||||
| 		 |  | ||||||
| 		return lastExit; |  | ||||||
|     }	 |  | ||||||
| 	 |  | ||||||
| 	private int executeCommand (String cmdString) throws Exception { |  | ||||||
| 
 |  | ||||||
| 		SimpleCommand command = new SimpleCommand(cmdString); |  | ||||||
| 
 |  | ||||||
| 		mShell.add(command).waitForFinish(); |  | ||||||
| 
 |  | ||||||
| 		logMessage("Command Exec: " + cmdString); |  | ||||||
| 		logMessage("Output: " + command.getOutput()); |  | ||||||
| 		logMessage("Exit code: " + command.getExitCode()); |  | ||||||
| 		 |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
|     public void closeShell () throws IOException |  | ||||||
|     { |  | ||||||
|         mShell.close(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 	public int enableTetheringRules (Context context) throws Exception |  | ||||||
| 	{ |  | ||||||
| 		 |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 		 |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|      |  | ||||||
|     	String[] hwinterfaces = {"usb0","wl0.1"}; |  | ||||||
|     	 |  | ||||||
|     	 |  | ||||||
|     	int lastExit = -1; |  | ||||||
|     	 |  | ||||||
|     	for (int i = 0; i < hwinterfaces.length; i++) |  | ||||||
|     	{ |  | ||||||
| 
 |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 	    	script.append(ipTablesPath); |  | ||||||
| 			script.append(" -t nat -A PREROUTING -i "); |  | ||||||
| 			script.append(hwinterfaces[i]); |  | ||||||
| 			script.append(" -p udp --dport 53 -j REDIRECT --to-ports "); |  | ||||||
| 			script.append(mDNSPort); |  | ||||||
| 			 |  | ||||||
| 			executeCommand (script.toString()); |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 			 |  | ||||||
| 			 |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 			script.append(ipTablesPath); |  | ||||||
| 			script.append(" -t nat -A PREROUTING -i "); |  | ||||||
| 			script.append(hwinterfaces[i]); |  | ||||||
| 			script.append(" -p tcp -j REDIRECT --to-ports "); |  | ||||||
| 			script.append(mTransProxyPort); |  | ||||||
| 			 |  | ||||||
| 			lastExit = executeCommand (script.toString()); |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 			 |  | ||||||
| 			 |  | ||||||
|     	} |  | ||||||
|     	 |  | ||||||
| 		return lastExit; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	private void logMessage (String msg) |  | ||||||
| 	{ |  | ||||||
| 		if (mTorService != null) |  | ||||||
| 			mTorService.debug(msg); |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 
 |  | ||||||
| 	 |  | ||||||
| 	public int fixTransproxyLeak (Context context) throws Exception |  | ||||||
| 	{ |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 		 |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|     	script.append(ipTablesPath); |  | ||||||
| 		script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j DROP"); |  | ||||||
| 		 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,RST ACK,RST -j DROP"); |  | ||||||
| 		 |  | ||||||
| 		int lastExit = executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		return lastExit; |  | ||||||
| 		  |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop) throws Exception { |  | ||||||
| 
 |  | ||||||
| 		String action = " -A "; |  | ||||||
| 		String chain = "OUTPUT"; |  | ||||||
| 		 |  | ||||||
| 		if (!enableDrop) |  | ||||||
| 			action = " -D "; |  | ||||||
| 		 |  | ||||||
| 		String ip6tablesPath = getIp6TablesPath(context); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder script; |  | ||||||
| 
 |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		script.append(ip6tablesPath);			 |  | ||||||
| 		script.append(action); |  | ||||||
| 		script.append(chain); |  | ||||||
| 
 |  | ||||||
| 		if (appUid != -1) |  | ||||||
| 		{ |  | ||||||
| 			script.append(" -m owner --uid-owner "); |  | ||||||
| 			script.append(appUid);	 |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		script.append(" -j DROP"); |  | ||||||
| 		 |  | ||||||
| 		int lastExit = executeCommand (script.toString()); |  | ||||||
| 		 |  | ||||||
| 		return lastExit; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	public int clearAllIPv6Filters (Context context) throws Exception |  | ||||||
| 	{ |  | ||||||
| 
 |  | ||||||
| 		String ip6tablesPath = getIp6TablesPath(context); |  | ||||||
| 		Shell shell = Shell.startRootShell(); |  | ||||||
|     	 |  | ||||||
|     	StringBuilder script; |  | ||||||
| 
 |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		script.append(ip6tablesPath);			 |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(" -F OUTPUT"); |  | ||||||
| 		int lastExit = executeCommand (shell, script.toString()); |  | ||||||
| 		 |  | ||||||
| 		shell.close(); |  | ||||||
| 		 |  | ||||||
| 		return lastExit; |  | ||||||
| 	}*/ |  | ||||||
| 	 |  | ||||||
| 	public int flushTransproxyRules (Context context) throws Exception { |  | ||||||
| 		int exit = -1; |  | ||||||
| 		 |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 
 |  | ||||||
| 		StringBuilder script = new StringBuilder(); |  | ||||||
| 		script.append(ipTablesPath);			 |  | ||||||
| 		script.append(" -t nat "); |  | ||||||
| 		script.append(" -F "); |  | ||||||
| 		 |  | ||||||
|     	executeCommand (script.toString()); |  | ||||||
| 		 |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		script.append(ipTablesPath);			 |  | ||||||
| 		script.append(" -t filter "); |  | ||||||
| 		script.append(" -F "); |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		 |  | ||||||
| 		dropAllIPv6Traffic(context,-1,false); |  | ||||||
| 		dropAllIPv6Traffic(context,-1,false); |  | ||||||
| 
 |  | ||||||
| 		 |  | ||||||
| 		return exit; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	public int setTransparentProxyingAll(Context context, boolean enable) throws Exception |  | ||||||
| 	{ |  | ||||||
| 	  	 |  | ||||||
| 		String action = " -A "; |  | ||||||
|     	String srcChainName = "OUTPUT"; |  | ||||||
| 
 |  | ||||||
| 		if (!enable) |  | ||||||
| 			action = " -D "; |  | ||||||
| 
 |  | ||||||
| 		dropAllIPv6Traffic(context,-1,enable); |  | ||||||
| 		 |  | ||||||
| 		String ipTablesPath = getIpTablesPath(context); |  | ||||||
| 		 |  | ||||||
|     	 |  | ||||||
|     	int torUid = context.getApplicationInfo().uid; |  | ||||||
|     	 |  | ||||||
|     	StringBuilder script = new StringBuilder(); |  | ||||||
|     	 |  | ||||||
| 		// Allow everything for Tor |  | ||||||
|     	 |  | ||||||
| 		script.append(ipTablesPath);			 |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -m owner --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 		 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 
 |  | ||||||
| 		// Allow loopback |  | ||||||
| 		 |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -o lo"); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
|     	// Set up port redirection    	 |  | ||||||
| 		script.append(ipTablesPath);		 |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p tcp"); |  | ||||||
| 		script.append(ALLOW_LOCAL); //allow access to localhost |  | ||||||
| 		script.append(" -m owner ! --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		script.append(" -m tcp --syn"); |  | ||||||
| 		script.append(" -j REDIRECT --to-ports "); |  | ||||||
| 		script.append(mTransProxyPort); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		// Same for DNS |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t nat"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p udp"); |  | ||||||
| 		script.append(ALLOW_LOCAL); //allow access to localhost |  | ||||||
| 		script.append(" -m owner ! --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		//script.append(" -m udp --dport ");  |  | ||||||
| 		script.append(" --dport "); |  | ||||||
| 		script.append(STANDARD_DNS_PORT); |  | ||||||
| 		script.append(" -j REDIRECT --to-ports "); |  | ||||||
| 		script.append(mDNSPort); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
| 		if (Prefs.useDebugLogging()) |  | ||||||
| 		{ |  | ||||||
| 			//XXX: Comment the following rules for non-debug builds |  | ||||||
| 			script.append(ipTablesPath);			 |  | ||||||
| 			script.append(" -t filter"); |  | ||||||
| 			script.append(action).append(srcChainName); |  | ||||||
| 			script.append(" -p udp"); |  | ||||||
| 			script.append(" --dport "); |  | ||||||
| 			script.append(STANDARD_DNS_PORT); |  | ||||||
| 			script.append(" -j LOG"); |  | ||||||
| 			script.append(" --log-prefix='ORBOT_DNSLEAK_PROTECTION'"); |  | ||||||
| 			script.append(" --log-uid"); |  | ||||||
| 
 |  | ||||||
| 			executeCommand (script.toString()); |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 			 |  | ||||||
| 			script.append(ipTablesPath);			 |  | ||||||
| 			script.append(" -t filter"); |  | ||||||
| 			script.append(action).append(srcChainName); |  | ||||||
| 	    	script.append(" -p tcp"); |  | ||||||
| 			script.append(" -j LOG"); |  | ||||||
| 			script.append(" --log-prefix='ORBOT_TCPLEAK_PROTECTION'"); |  | ||||||
| 			script.append(" --log-uid"); |  | ||||||
| 
 |  | ||||||
| 			executeCommand (script.toString()); |  | ||||||
| 			script = new StringBuilder(); |  | ||||||
| 
 |  | ||||||
| 		}**/ |  | ||||||
| 
 |  | ||||||
| 		//allow access to transproxy port |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p tcp"); |  | ||||||
| 		script.append(" -m tcp"); |  | ||||||
| 		script.append(" --dport ").append(mTransProxyPort); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		//allow access to local HTTP port |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p tcp"); |  | ||||||
| 		script.append(" -m tcp"); |  | ||||||
| 		script.append(" --dport ").append(mTorService.getHTTPPort()); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		//allow access to local SOCKS port |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p tcp"); |  | ||||||
| 		script.append(" -m tcp"); |  | ||||||
| 		script.append(" --dport ").append(mTorService.getSOCKSPort()); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		//allow access to local DNS port |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -p udp"); |  | ||||||
| 		script.append(" -m udp"); |  | ||||||
| 		script.append(" --dport ").append(mDNSPort); |  | ||||||
| 		script.append(" -j ACCEPT"); |  | ||||||
| 
 |  | ||||||
| 		executeCommand (script.toString()); |  | ||||||
| 		script = new StringBuilder(); |  | ||||||
| 		 |  | ||||||
| 		// Reject all other packets |  | ||||||
| 		script.append(ipTablesPath); |  | ||||||
| 		script.append(" -t filter"); |  | ||||||
| 		script.append(action).append(srcChainName); |  | ||||||
| 		script.append(" -m owner ! --uid-owner "); |  | ||||||
| 		script.append(torUid); |  | ||||||
| 		script.append(ALLOW_LOCAL); //allow access to localhost |  | ||||||
| 		script.append(" -j REJECT"); |  | ||||||
| 
 |  | ||||||
| 		int lastExit = executeCommand (script.toString()); |  | ||||||
| 		 |  | ||||||
| 	//	fixTransproxyLeak (context); |  | ||||||
| 		 |  | ||||||
|     	return lastExit; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	public static ArrayList<TorifiedApp> getApps (Context context, SharedPreferences prefs) |  | ||||||
| 	{ |  | ||||||
| 
 |  | ||||||
| 		String tordAppString = prefs.getString(OrbotConstants.PREFS_KEY_TORIFIED, ""); |  | ||||||
| 		String[] tordApps; |  | ||||||
| 
 |  | ||||||
| 		StringTokenizer st = new StringTokenizer(tordAppString,"|"); |  | ||||||
| 		tordApps = new String[st.countTokens()]; |  | ||||||
| 		int tordIdx = 0; |  | ||||||
| 		while (st.hasMoreTokens()) |  | ||||||
| 		{ |  | ||||||
| 			tordApps[tordIdx++] = st.nextToken(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		Arrays.sort(tordApps); |  | ||||||
| 
 |  | ||||||
| 		//else load the apps up |  | ||||||
| 		PackageManager pMgr = context.getPackageManager(); |  | ||||||
| 
 |  | ||||||
| 		List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0); |  | ||||||
| 
 |  | ||||||
| 		Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator(); |  | ||||||
| 
 |  | ||||||
| 		ArrayList<TorifiedApp> apps = new ArrayList<TorifiedApp>(); |  | ||||||
| 
 |  | ||||||
| 		ApplicationInfo aInfo = null; |  | ||||||
| 
 |  | ||||||
| 		int appIdx = 0; |  | ||||||
| 		TorifiedApp app = null; |  | ||||||
| 
 |  | ||||||
| 		while (itAppInfo.hasNext()) |  | ||||||
| 		{ |  | ||||||
| 			aInfo = itAppInfo.next(); |  | ||||||
| 
 |  | ||||||
| 			app = new TorifiedApp(); |  | ||||||
| 
 |  | ||||||
| 			try { |  | ||||||
| 				PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS); |  | ||||||
| 
 |  | ||||||
| 				if (pInfo != null && pInfo.requestedPermissions != null) |  | ||||||
| 				{ |  | ||||||
| 					for (String permInfo:pInfo.requestedPermissions) |  | ||||||
| 					{ |  | ||||||
| 						if (permInfo.equals("android.permission.INTERNET")) |  | ||||||
| 						{ |  | ||||||
| 							app.setUsesInternet(true); |  | ||||||
| 
 |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 			} catch (Exception e) { |  | ||||||
| 				// TODO Auto-generated catch block |  | ||||||
| 				e.printStackTrace(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) |  | ||||||
| 			{ |  | ||||||
| 				//System app |  | ||||||
| 				app.setUsesInternet(true); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 			if (!app.usesInternet()) |  | ||||||
| 				continue; |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				apps.add(app); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 			app.setEnabled(aInfo.enabled); |  | ||||||
| 			app.setUid(aInfo.uid); |  | ||||||
| 			app.setUsername(pMgr.getNameForUid(app.getUid())); |  | ||||||
| 			app.setProcname(aInfo.processName); |  | ||||||
| 			app.setPackageName(aInfo.packageName); |  | ||||||
| 
 |  | ||||||
| 			try |  | ||||||
| 			{ |  | ||||||
| 				app.setName(pMgr.getApplicationLabel(aInfo).toString()); |  | ||||||
| 			} |  | ||||||
| 			catch (Exception e) |  | ||||||
| 			{ |  | ||||||
| 				app.setName(aInfo.packageName); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 			//app.setIcon(pMgr.getApplicationIcon(aInfo)); |  | ||||||
| 
 |  | ||||||
| 			// check if this application is allowed |  | ||||||
| 			if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) { |  | ||||||
| 				app.setTorified(true); |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				app.setTorified(false); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			appIdx++; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		Collections.sort(apps); |  | ||||||
| 
 |  | ||||||
| 		return apps; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -38,7 +38,6 @@ import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone; | ||||||
| 
 | 
 | ||||||
| import org.torproject.android.service.R; | import org.torproject.android.service.R; | ||||||
| import org.torproject.android.service.TorServiceConstants; | import org.torproject.android.service.TorServiceConstants; | ||||||
| import org.torproject.android.service.transproxy.TorifiedApp; |  | ||||||
| import org.torproject.android.service.util.TorServiceUtils; | import org.torproject.android.service.util.TorServiceUtils; | ||||||
| 
 | 
 | ||||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||||
|  | @ -46,7 +45,6 @@ import java.io.File; | ||||||
| import java.io.FileNotFoundException; | import java.io.FileNotFoundException; | ||||||
| import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; |  | ||||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||||
| import java.io.PrintStream; | import java.io.PrintStream; | ||||||
| import java.net.InetAddress; | import java.net.InetAddress; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| package org.torproject.android.service.transproxy; | package org.torproject.android.service.vpn; | ||||||
| 
 | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
|  | @ -112,7 +112,7 @@ | ||||||
|   <string name="wizard_tips_fdroid">Find all Guardian Project apps on F-Droid</string> |   <string name="wizard_tips_fdroid">Find all Guardian Project apps on F-Droid</string> | ||||||
|   <string name="wizard_tips_fdroid_org">Find all Guardian Project apps on https://f-droid.org</string> |   <string name="wizard_tips_fdroid_org">Find all Guardian Project apps on https://f-droid.org</string> | ||||||
|   <!--Transparent Proxy screen--> |   <!--Transparent Proxy screen--> | ||||||
|   <string name="wizard_transproxy_title">Transparent Proxying</string> |   <string name="wizard_transproxy_title">Tunneled Apps</string> | ||||||
|   <string name="wizard_transproxy_msg">This allows your apps to automatically run through the Tor network without any configuration.</string> |   <string name="wizard_transproxy_msg">This allows your apps to automatically run through the Tor network without any configuration.</string> | ||||||
|   <string name="wizard_transproxy_hint">(Check this box if you have no idea what we are talking about)</string> |   <string name="wizard_transproxy_hint">(Check this box if you have no idea what we are talking about)</string> | ||||||
|   <string name="wizard_transproxy_none">None</string> |   <string name="wizard_transproxy_none">None</string> | ||||||
|  | @ -286,14 +286,6 @@ | ||||||
|   <string name="please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_">"Please disable this app in Android->Settings->Apps if you are having problems with Orbot: "</string> |   <string name="please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_">"Please disable this app in Android->Settings->Apps if you are having problems with Orbot: "</string> | ||||||
|   <string name="app_conflict">App Conflict</string> |   <string name="app_conflict">App Conflict</string> | ||||||
|    |    | ||||||
| 
 |  | ||||||
|   <string name="pref_transproxy_refresh_title">Transproxy Auto-Refresh</string> |  | ||||||
|   <string name="pref_transproxy_refresh_summary">Re-apply Transproxy rules when the network state changes</string> |  | ||||||
|    |  | ||||||
|   <string name="pref_transproxy_flush_title">Transproxy FORCE REMOVE</string> |  | ||||||
|   <string name="pref_transproxy_flush_summary">Tap here to flush all transproxy network rules NOW</string> |  | ||||||
|   <string name="transparent_proxy_rules_flushed_">Transparent proxy rules flushed!</string> |  | ||||||
|   <string name="you_do_not_have_root_access_enabled">You do not have ROOT access enabled</string> |  | ||||||
|   <string name="you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_">You may need to stop and start Orbot for settings change to be enabled.</string> |   <string name="you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_">You may need to stop and start Orbot for settings change to be enabled.</string> | ||||||
|    |    | ||||||
|   <string name="menu_vpn">VPN</string> |   <string name="menu_vpn">VPN</string> | ||||||
|  |  | ||||||
|  | @ -1,2 +1,2 @@ | ||||||
| include ':jsocksAndroid', ':orbotservice', ':RootCommands' | include ':jsocksAndroid', ':orbotservice' | ||||||
| include ':app' | include ':app' | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue