[tor-commits] [orbot/master] many small changes to support new binary loading, startup and more
n8fr8 at torproject.org
n8fr8 at torproject.org
Tue Mar 26 19:29:46 UTC 2019
commit 56917567cd21a734a35f3bee0e56ba23793b6887
Author: n8fr8 <nathan at guardianproject.info>
Date: Tue Mar 26 03:03:48 2019 -0400
many small changes to support new binary loading, startup and more
- improved handling of port conflicts
- fixed loading of tor binary on arm64-v8a
- changed how we execute shell commands
---
app/build.gradle | 6 +-
app/src/main/AndroidManifest.xml | 4 +-
jsocksAndroid/src/main/AndroidManifest.xml | 8 +-
orbotservice/build.gradle | 19 +-
.../org/torproject/android/service/TorService.java | 470 +++++++++++----------
.../android/service/TorServiceConstants.java | 4 +-
.../android/service/util/CustomNativeLoader.java | 132 ++++++
.../android/service/util/CustomShell.java | 101 +++++
.../service/util/CustomTorResourceInstaller.java | 244 +++++++++++
.../android/service/util/NativeLoader.java | 35 +-
.../service/util/OtherResourceInstaller.java | 6 +-
.../android/service/util/PortForwarder.java | 80 ++++
.../android/service/vpn/OrbotVpnManager.java | 29 +-
orbotservice/src/main/jni/Application.mk | 2 +-
14 files changed, 859 insertions(+), 281 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 6b59a43d..4994f51e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -34,8 +34,8 @@ android {
minSdkVersion 16
applicationId 'org.torproject.android'
targetSdkVersion 28
- versionCode 16060001
- versionName '16.0.6-BETA-1-tor-0.3.5.8'
+ versionCode 16060002
+ versionName '16.0.6-BETA-2-tor-0.3.5.8'
archivesBaseName = "Orbot-$versionName"
}
}
@@ -55,7 +55,7 @@ android {
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
- include "x86", "armeabi", "armeabi-v7a"
+ include "x86", "armeabi", "armeabi-v7a", "x86_64", "arm64-v8a"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ea90afe7..8e3b6014 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.torproject.android"
- android:installLocation="auto">
+ android:installLocation="internalOnly">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@@ -30,7 +30,7 @@
>
<activity
android:name=".OrbotMainActivity"
- android:excludeFromRecents="true"
+ android:excludeFromRecents="false"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/jsocksAndroid/src/main/AndroidManifest.xml b/jsocksAndroid/src/main/AndroidManifest.xml
index 7351fd23..fb20a650 100644
--- a/jsocksAndroid/src/main/AndroidManifest.xml
+++ b/jsocksAndroid/src/main/AndroidManifest.xml
@@ -1,11 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.jsocksandroid"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="21" />
+ package="com.example.jsocksandroid" >
</manifest>
diff --git a/orbotservice/build.gradle b/orbotservice/build.gradle
index c9f0e8a4..df861342 100644
--- a/orbotservice/build.gradle
+++ b/orbotservice/build.gradle
@@ -1,8 +1,8 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 27
- buildToolsVersion '27.0.3'
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
sourceSets {
main {
@@ -12,9 +12,10 @@ android {
defaultConfig {
minSdkVersion 16
- targetSdkVersion 27
- versionCode 1
- versionName "1.0"
+ targetSdkVersion 28
+ versionCode 16060001
+ versionName '16.0.6-BETA-1-tor-0.3.5.8-orbotservice'
+ archivesBaseName = "OrbotService-$versionName"
}
buildTypes {
@@ -27,9 +28,11 @@ android {
dependencies {
implementation project(':jsocksAndroid')
- implementation 'org.torproject:tor-android-binary:0.3.5.8-rc'
- implementation 'com.android.support:appcompat-v7:27.1.1'
- implementation 'com.jrummyapps:android-shell:1.0.1'
+ implementation 'org.torproject:tor-android-binary:0.3.5.8-rc-v2'
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.jaredrummler:android-shell:1.0.0'
implementation fileTree(dir: 'libs', include: ['.so'])
testImplementation 'junit:junit:4.12'
+
+ implementation 'com.offbynull.portmapper:portmapper:2.0.5'
}
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
index f87c0a10..7f2b37cc 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -39,12 +39,14 @@ import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
-import com.jrummyapps.android.shell.CommandResult;
-import com.jrummyapps.android.shell.Shell;
+import com.jaredrummler.android.shell.CommandResult;
+import com.jaredrummler.android.shell.Shell;
import org.torproject.android.binary.TorResourceInstaller;
import org.torproject.android.control.ConfigEntry;
import org.torproject.android.control.TorControlConnection;
+import org.torproject.android.service.util.CustomShell;
+import org.torproject.android.service.util.CustomTorResourceInstaller;
import org.torproject.android.service.util.DummyActivity;
import org.torproject.android.service.util.OtherResourceInstaller;
import org.torproject.android.service.util.Prefs;
@@ -59,6 +61,7 @@ import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
@@ -87,12 +90,13 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private final static int CONTROL_SOCKET_TIMEOUT = 0;
private TorControlConnection conn = null;
- private Socket torConnSocket = null;
private int mLastProcessId = -1;
- private int mPortHTTP = HTTP_PROXY_PORT_DEFAULT;
- private int mPortSOCKS = SOCKS_PROXY_PORT_DEFAULT;
-
+ public static int mPortSOCKS = SOCKS_PROXY_PORT_DEFAULT;
+ public static int mPortHTTP = HTTP_PROXY_PORT_DEFAULT;
+ public static int mPortDns = TOR_DNS_PORT_DEFAULT;
+ public static int mPortTrans = TOR_TRANSPROXY_PORT_DEFAULT;
+
private static final int NOTIFY_ID = 1;
private static final int ERROR_NOTIFY_ID = 3;
private static final int HS_NOTIFY_ID = 4;
@@ -340,7 +344,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
*/
public int onStartCommand(Intent intent, int flags, int startId) {
- showToolbarNotification(getString(R.string.status_starting_up),NOTIFY_ID,R.drawable.ic_stat_tor);
+ showToolbarNotification("",NOTIFY_ID,R.drawable.ic_stat_tor);
if (intent != null)
exec (new IncomingIntentRouter(intent));
@@ -509,12 +513,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
try
{
- appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
- appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE);
+ appBinHome = getFilesDir();//getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
+ if (!appBinHome.exists())
+ appBinHome.mkdirs();
+
+ appCacheHome = getCacheDir();// getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE);
+ if (!appCacheHome.exists())
+ appCacheHome.mkdirs();
fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY);
fileObfsclient = new File(appBinHome, TorServiceConstants.OBFSCLIENT_ASSET_KEY);
fileTorRc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY);
+ fileControlPort = new File(getFilesDir(), "control.txt");
mHSBasePath = new File(
getFilesDir().getAbsolutePath(),
@@ -542,15 +552,14 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (Build.VERSION.SDK_INT >= 26)
createNotificationChannel();
+ torUpgradeAndConfig();
+
new Thread(new Runnable ()
{
public void run ()
{
try
{
-
- torUpgradeAndConfig();
-
findExistingTorDaemon();
}
catch (Exception e)
@@ -578,90 +587,93 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
return mCurrentStatus;
}
- private void torUpgradeAndConfig() throws IOException, TimeoutException {
+ private boolean torUpgradeAndConfig() throws IOException, TimeoutException {
if (isTorUpgradeAndConfigComplete)
- return;
+ return true;
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
String version = prefs.getString(PREF_BINARY_TOR_VERSION_INSTALLED,null);
logNotice("checking binary version: " + version);
-
- TorResourceInstaller installer = new TorResourceInstaller(this, appBinHome);
+ CustomTorResourceInstaller installer = new CustomTorResourceInstaller(this, appBinHome);
logNotice("upgrading binaries to latest version: " + BINARY_TOR_VERSION);
fileTor = installer.installResources();
+ fileTor = new File(appBinHome,"tor");
+ if (fileTor != null && fileTor.canExecute()) {
+ prefs.edit().putString(PREF_BINARY_TOR_VERSION_INSTALLED, BINARY_TOR_VERSION).apply();
- if (fileTor != null && fileTor.canExecute())
- prefs.edit().putString(PREF_BINARY_TOR_VERSION_INSTALLED,BINARY_TOR_VERSION).apply();
+ fileTorRc = new File(appBinHome,"torrc");//installer.getTorrcFile();
+ if (!fileTorRc.exists())
+ return false;
- fileTorRc = installer.getTorrcFile();
+ OtherResourceInstaller oInstaller = new OtherResourceInstaller(this, appBinHome);
+ oInstaller.installResources();
- OtherResourceInstaller oInstaller = new OtherResourceInstaller(this, appBinHome);
- oInstaller.installResources();
+ isTorUpgradeAndConfigComplete = true;
+
+ return true;
+ }
- updateTorConfigFile ();
- isTorUpgradeAndConfigComplete = true;
+
+ return false;
}
- private boolean updateTorConfigFile () throws IOException, TimeoutException
+ private File updateTorrcCustomFile () throws IOException, TimeoutException
{
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
- TorResourceInstaller installer = new TorResourceInstaller(this, appBinHome);
-
StringBuffer extraLines = new StringBuffer();
-
- String TORRC_CONTROLPORT_FILE_KEY = "ControlPortWriteToFile";
- fileControlPort = new File(appBinHome, "control.txt");
- extraLines.append(TORRC_CONTROLPORT_FILE_KEY).append(' ').append(fileControlPort.getCanonicalPath()).append('\n');
-// extraLines.append("RunAsDaemon 1").append('\n');
- // extraLines.append("AvoidDiskWrites 1").append('\n');
+ extraLines.append("\n");
+ extraLines.append("ControlPortWriteToFile").append(' ').append(fileControlPort.getCanonicalPath()).append('\n');
+
+ // extraLines.append("RunAsDaemon 1").append('\n');
+ // extraLines.append("AvoidDiskWrites 1").append('\n');
- String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS,
- String.valueOf(TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT));
+ String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS, String.valueOf(TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT));
+
if (socksPortPref.indexOf(':')!=-1)
socksPortPref = socksPortPref.split(":")[1];
- if (!socksPortPref.equalsIgnoreCase("auto"))
- {
- boolean isPortUsed = TorServiceUtils.isPortOpen("127.0.0.1",Integer.parseInt(socksPortPref),500);
-
- if (isPortUsed) //the specified port is not available, so let Tor find one instead
- socksPortPref = "auto";
- }
+ socksPortPref = checkPortOrAuto(socksPortPref);
- String isolate = " ";
+ String isolate = "";
if(prefs.getBoolean(OrbotConstants.PREF_ISOLATE_DEST, false))
{
- isolate += "IsolateDestAddr ";
+ isolate += " IsolateDestAddr ";
}
- String ipv6Pref = " IPv6Traffic ";
+ String ipv6Pref = "";
+
if(prefs.getBoolean(OrbotConstants.PREF_PREFER_IPV6, true))
{
- ipv6Pref += "PreferIPv6 ";
+ ipv6Pref += " IPv6Traffic PreferIPv6 ";
}
+
if(prefs.getBoolean(OrbotConstants.PREF_DISABLE_IPV4, false))
{
- ipv6Pref += "NoIPv4Traffic ";
+ ipv6Pref += " IPv6Traffic NoIPv4Traffic ";
}
extraLines.append("SOCKSPort ").append(socksPortPref).append(isolate).append(ipv6Pref).append('\n');
extraLines.append("SafeSocks 0").append('\n');
extraLines.append("TestSocks 0").append('\n');
+
if (Prefs.openProxyOnAllInterfaces())
extraLines.append("SocksListenAddress 0.0.0.0").append('\n');
- extraLines.append("HTTPTunnelPort ").append(mPortHTTP).append(isolate).append(ipv6Pref).append('\n');
+ String httpPortPref = HTTP_PROXY_PORT_DEFAULT + "";
+ extraLines.append("HTTPTunnelPort ").append(checkPortOrAuto(httpPortPref)).append('\n');
+
if(prefs.getBoolean(OrbotConstants.PREF_CONNECTION_PADDING, false))
{
extraLines.append("ConnectionPadding 1").append('\n');
}
+
if(prefs.getBoolean(OrbotConstants.PREF_REDUCED_CONNECTION_PADDING, true))
{
extraLines.append("ReducedConnectionPadding 1").append('\n');
@@ -670,9 +682,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
String transPort = prefs.getString("pref_transport", TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT+"");
String dnsPort = prefs.getString("pref_dnsport", TorServiceConstants.TOR_DNS_PORT_DEFAULT+"");
- extraLines.append("TransPort ").append(transPort).append('\n');
- extraLines.append("DNSPort ").append(dnsPort).append('\n');
-
+ extraLines.append("TransPort ").append(checkPortOrAuto(transPort)).append('\n');
+ extraLines.append("DNSPort ").append(checkPortOrAuto(dnsPort)).append('\n');
extraLines.append("VirtualAddrNetwork 10.192.0.0/10").append('\n');
extraLines.append("AutomapHostsOnResolve 1").append('\n');
@@ -681,13 +692,16 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (Prefs.useDebugLogging())
{
- extraLines.append("Log debug syslog").append('\n');
+ extraLines.append("Log debug syslog").append('\n');
extraLines.append("Log info syslog").append('\n');
extraLines.append("SafeLogging 0").append('\n');
}
-
- processSettingsImpl(extraLines);
+
+ extraLines = processSettingsImpl(extraLines);
+
+ if (extraLines == null)
+ return null;
String torrcCustom = new String(prefs.getString("pref_custom_torrc", "").getBytes("US-ASCII"));
extraLines.append(torrcCustom).append('\n');
@@ -697,14 +711,38 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
debug("torrc.custom=" + extraLines.toString());
File fileTorRcCustom = new File(fileTorRc.getAbsolutePath() + ".custom");
- boolean success = installer.updateTorConfigCustom(fileTorRcCustom, extraLines.toString());
+ boolean success = updateTorConfigCustom(fileTorRcCustom, extraLines.toString());
- if (success)
+ if (success && fileTorRcCustom.exists())
{
logNotice ("success.");
+ return fileTorRcCustom;
}
-
- return success;
+ else
+ return null;
+
+ }
+
+ private String checkPortOrAuto (String port)
+ {
+ if (!port.equalsIgnoreCase("auto"))
+ {
+ boolean isPortUsed = TorServiceUtils.isPortOpen("127.0.0.1",Integer.parseInt(port),500);
+
+ if (isPortUsed) //the specified port is not available, so let Tor find one instead
+ port = "auto";
+ }
+
+ return port;
+ }
+
+ public boolean updateTorConfigCustom(File fileTorRcCustom, String extraLines) throws IOException, FileNotFoundException, TimeoutException {
+ FileWriter fos = new FileWriter(fileTorRcCustom, false);
+ PrintWriter ps = new PrintWriter(fos);
+ ps.print(extraLines);
+ ps.flush();
+ ps.close();
+ return true;
}
/**
@@ -742,27 +780,28 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
/**
* The entire process for starting tor and related services is run from this method.
*/
- private synchronized void startTor() {
+ private void startTor() {
String torProcId = null;
try { if (conn != null) torProcId = conn.getInfo("process/pid"); }
catch (Exception e){}
- // STATUS_STARTING is set in onCreate()
- if (mCurrentStatus == STATUS_STOPPING) {
- // these states should probably be handled better
- sendCallbackLogMessage("Ignoring start request, currently " + mCurrentStatus);
- return;
- } else if (mCurrentStatus == STATUS_ON && (torProcId != null)) {
-
- sendCallbackLogMessage("Ignoring start request, already started.");
- setTorNetworkEnabled (true);
+ try {
- return;
- }
+ // STATUS_STARTING is set in onCreate()
+ if (mCurrentStatus == STATUS_STOPPING) {
+ // these states should probably be handled better
+ sendCallbackLogMessage("Ignoring start request, currently " + mCurrentStatus);
+ return;
+ } else if (mCurrentStatus == STATUS_ON && (torProcId != null)) {
+
+ sendCallbackLogMessage("Ignoring start request, already started.");
+ setTorNetworkEnabled (true);
+
+ return;
+ }
- try {
// make sure there are no stray daemons running
// killAllDaemons();
@@ -786,89 +825,93 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
boolean success = runTorShellCmd();
+ if (success)
+ {
// if (mPortHTTP != -1)
// runPolipoShellCmd();
- // Tor is running, update new .onion names at db
- ContentResolver mCR = getApplicationContext().getContentResolver();
- Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null);
- if(hidden_services != null) {
- try {
- while (hidden_services.moveToNext()) {
- String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.DOMAIN));
- Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
- Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
- String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE_VALUE));
-
- // Update only new domains or restored from backup with auth cookie
- if((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) {
- String hsDirPath = new File(mHSBasePath.getAbsolutePath(),"hs" + HSLocalPort).getCanonicalPath();
- File file = new File(hsDirPath, "hostname");
-
- if (file.exists())
- {
- ContentValues fields = new ContentValues();
-
- try {
- String onionHostname = Utils.readString(new FileInputStream(file)).trim();
- if(HSAuthCookie == 1) {
- String[] aux = onionHostname.split(" ");
- onionHostname = aux[0];
- fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]);
+ // Tor is running, update new .onion names at db
+ ContentResolver mCR = getApplicationContext().getContentResolver();
+ Cursor hidden_services = mCR.query(HS_CONTENT_URI, hsProjection, null, null, null);
+ if(hidden_services != null) {
+ try {
+ while (hidden_services.moveToNext()) {
+ String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.DOMAIN));
+ Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
+ Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
+ String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE_VALUE));
+
+ // Update only new domains or restored from backup with auth cookie
+ if ((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) {
+ String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath();
+ File file = new File(hsDirPath, "hostname");
+
+ if (file.exists()) {
+ ContentValues fields = new ContentValues();
+
+ try {
+ String onionHostname = Utils.readString(new FileInputStream(file)).trim();
+ if (HSAuthCookie == 1) {
+ String[] aux = onionHostname.split(" ");
+ onionHostname = aux[0];
+ fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]);
+ }
+ fields.put(HiddenService.DOMAIN, onionHostname);
+ mCR.update(HS_CONTENT_URI, fields, "port=" + HSLocalPort, null);
+ } catch (FileNotFoundException e) {
+ logException("unable to read onion hostname file", e);
+ showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
}
- fields.put(HiddenService.DOMAIN, onionHostname);
- mCR.update(HS_CONTENT_URI, fields, "port=" + HSLocalPort , null);
- } catch (FileNotFoundException e) {
- logException("unable to read onion hostname file",e);
+ } else {
showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
- }
- }
- else
- {
- showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
+ }
}
}
+
+ } catch (NumberFormatException e) {
+ Log.e(OrbotConstants.TAG, "error parsing hsport", e);
+ } catch (Exception e) {
+ Log.e(OrbotConstants.TAG, "error starting share server", e);
}
- } catch (NumberFormatException e) {
- Log.e(OrbotConstants.TAG,"error parsing hsport",e);
- } catch (Exception e) {
- Log.e(OrbotConstants.TAG,"error starting share server",e);
+ hidden_services.close();
}
-
- hidden_services.close();
}
} catch (Exception e) {
logException("Unable to start Tor: " + e.toString(), e);
+ stopTor();
showToolbarNotification(
getString(R.string.unable_to_start_tor) + ": " + e.getMessage(),
ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
- //stopTor();
+
}
}
-
-
- private synchronized boolean runTorShellCmd() throws Exception
+ private boolean runTorShellCmd() throws Exception
{
boolean result = true;
- String torrcPath = new File(appBinHome, TORRC_ASSET_KEY).getCanonicalPath();
+ File fileTorrcCustom = updateTorrcCustomFile();
+
+ //make sure Tor exists and we can execute it
+ if ((!fileTor.exists()) || (!fileTor.canExecute()))
+ return false;
+
+ if ((!fileTorRc.exists()) || (!fileTorRc.canRead()) )
+ return false;
+
+ if ((!fileTorrcCustom.exists()) || (!fileTorrcCustom.canRead()) )
+ return false;
- updateTorConfigFile();
-
sendCallbackLogMessage(getString(R.string.status_starting_up));
-
+
String torCmdString = fileTor.getCanonicalPath()
+ " DataDirectory " + appCacheHome.getCanonicalPath()
- + " --defaults-torrc " + torrcPath
- + " -f " + torrcPath + ".custom";
+ + " --defaults-torrc " + fileTorRc.getCanonicalPath()
+ + " -f " + fileTorrcCustom.getCanonicalPath();
- debug(torCmdString);
-
-
int exitCode = -1;
try {
@@ -880,39 +923,37 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
return false;
}
+ if (exitCode == 0) {
+ logNotice("Tor configuration VERIFIED.");
+ try {
+ exitCode = exec(torCmdString, false);
+ } catch (Exception e) {
+ logNotice("Tor was unable to start: " + e.getMessage());
+ result = false;
- try {
- exitCode = exec(torCmdString, true);
- }
- catch (Exception e)
- {
- logNotice("Tor was unable to start: " + e.getMessage());
- return false;
- }
+ throw new Exception("Tor was unable to start: " + e.getMessage());
- if (exitCode != 0)
- {
- logNotice("Tor did not start. Exit:" + exitCode);
- return false;
- }
-
- //now try to connect
- mLastProcessId = initControlConnection (100,false);
+ }
- if (mLastProcessId == -1)
- {
- logNotice(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode);
- sendCallbackLogMessage(getString(R.string.couldn_t_start_tor_process_));
-
- throw new Exception ("Unable to start Tor");
- }
- else
- {
-
- logNotice("Tor started; process id=" + mLastProcessId);
-
+ if (exitCode != 0) {
+ logNotice("Tor did not start. Exit:" + exitCode);
+ return false;
+ }
+
+ //now try to connect
+ mLastProcessId = initControlConnection(10, false);
+
+ if (mLastProcessId == -1) {
+ logNotice(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode);
+ result = false;
+ throw new Exception(getString(R.string.couldn_t_start_tor_process_) + "; exit=" + exitCode);
+ } else {
+
+ logNotice("Tor started; process id=" + mLastProcessId);
+ result = true;
+ }
}
-
+
return result;
}
@@ -924,74 +965,29 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private int exec (String cmd, boolean wait) throws Exception
{
- CommandResult shellResult = Shell.run(cmd);
- debug("CMD: " + cmd + "; SUCCESS=" + shellResult.isSuccessful());
-
- if (!shellResult.isSuccessful()) {
- throw new Exception("Error: " + shellResult.exitCode + " ERR=" + shellResult.getStderr() + " OUT=" + shellResult.getStdout());
- }
-
- /**
- SimpleCommand command = new SimpleCommand(cmd);
- mShell.add(command);
- if (wait)
- command.waitForFinish();
- return command.getExitCode();
- **/
- return shellResult.exitCode;
- }
-
- /**
- private void updatePolipoConfig () throws FileNotFoundException, IOException
- {
-
-
- File file = new File(appBinHome, POLIPOCONFIG_ASSET_KEY);
-
- Properties props = new Properties();
-
- props.load(new FileReader(file));
-
- props.put("socksParentProxy", "\"localhost:" + mPortSOCKS + "\"");
- props.put("proxyPort",mPortHTTP+"");
-
- props.store(new FileWriter(file), "updated");
-
- }**/
-
-
- /**
- private void runPolipoShellCmd () throws Exception
- {
-
- logNotice( "Starting polipo process");
+ CommandResult result = CustomShell.run("sh",wait, null, cmd);
+ debug("executing: " + cmd);
+ debug("stdout: " + result.getStdout());
+ debug("stderr: " + result.getStderr());
- updatePolipoConfig();
+ return result.exitCode;
- String polipoConfigPath = new File(appBinHome, POLIPOCONFIG_ASSET_KEY).getCanonicalPath();
- String cmd = (filePolipo.getCanonicalPath() + " -c " + polipoConfigPath);
- CommandResult shellResult = Shell.run(cmd);
-
- sendCallbackLogMessage(getString(R.string.privoxy_is_running_on_port_) + mPortHTTP);
-
- logNotice("Polipo is running");
-
- }**/
+ }
protected TorControlConnection getControlConnection ()
{
return conn;
}
- private int initControlConnection (int maxTries, boolean isReconnect) throws Exception, RuntimeException
+ private int initControlConnection (int maxTries, boolean isReconnect) throws Exception
{
int controlPort = -1;
int attempt = 0;
logNotice( "Waiting for control port...");
- while (conn == null && attempt++ < maxTries)
+ while (conn == null && attempt++ < maxTries && (mCurrentStatus != STATUS_OFF))
{
try
{
@@ -1001,8 +997,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (controlPort != -1)
{
logNotice( "Connecting to control port: " + controlPort);
-
- torConnSocket = new Socket(IP_LOCALHOST, controlPort);
+
+ Socket torConnSocket = new Socket(IP_LOCALHOST, controlPort);
torConnSocket.setSoTimeout(CONTROL_SOCKET_TIMEOUT);
conn = new TorControlConnection(torConnSocket);
@@ -1022,7 +1018,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
try {
// logNotice("waiting...");
- Thread.sleep(1000); }
+ Thread.sleep(2000); }
catch (Exception e){}
}
@@ -1054,6 +1050,27 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
confSocks = st.nextToken().split(":")[1];
confSocks = confSocks.substring(0,confSocks.length()-1);
mPortSOCKS = Integer.parseInt(confSocks);
+
+ String confHttp = conn.getInfo("net/listeners/httptunnel");
+ st = new StringTokenizer(confHttp," ");
+
+ confHttp = st.nextToken().split(":")[1];
+ confHttp = confHttp.substring(0,confHttp.length()-1);
+ mPortHTTP = Integer.parseInt(confHttp);
+
+ String confDns = conn.getInfo("net/listeners/dns");
+ st = new StringTokenizer(confDns," ");
+
+ confDns = st.nextToken().split(":")[1];
+ confDns = confDns.substring(0,confDns.length()-1);
+ mPortDns = Integer.parseInt(confDns);
+
+ String confTrans = conn.getInfo("net/listeners/trans");
+ st = new StringTokenizer(confTrans," ");
+
+ confTrans = st.nextToken().split(":")[1];
+ confTrans = confDns.substring(0,confTrans.length()-1);
+ mPortTrans = Integer.parseInt(confTrans);
return Integer.parseInt(torProcId);
@@ -1066,8 +1083,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
}
}
-
- return -1;
+ throw new Exception("Tor control port could not be found");
+
}
@@ -1233,13 +1250,16 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
return false;
}
-
- public void setTorNetworkEnabled (final boolean isEnabled)
+
+ private String lastNetworkValue = "0";
+
+ public void setTorNetworkEnabled (final boolean isEnabled) throws IOException
{
+ final String newValue =isEnabled ? "0" : "1";
//it is possible to not have a connection yet, and someone might try to newnym
- if (conn != null)
+ if (conn != null && (!lastNetworkValue.equals(newValue)))
{
new Thread ()
{
@@ -1247,8 +1267,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
{
try {
- conn.setConf("DisableNetwork", isEnabled ? "0" : "1");
-
+ conn.setConf("DisableNetwork", newValue);
+ lastNetworkValue = newValue;
}
catch (Exception ioe){
debug("error requesting newnym: " + ioe.getLocalizedMessage());
@@ -1431,9 +1451,13 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if (doNetworKSleep && mCurrentStatus != STATUS_OFF)
{
- setTorNetworkEnabled (mConnectivity);
-
- if (!mConnectivity)
+ try {
+ setTorNetworkEnabled (mConnectivity);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (!mConnectivity)
{
logNotice(context.getString(R.string.no_network_connectivity_putting_tor_to_sleep_));
showToolbarNotification(getString(R.string.no_internet_connection_tor),NOTIFY_ID,R.drawable.ic_stat_tor_off);
@@ -1451,7 +1475,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
}
};
- private boolean processSettingsImpl (StringBuffer extraLines) throws IOException
+ private StringBuffer processSettingsImpl (StringBuffer extraLines) throws IOException
{
logNotice(getString(R.string.updating_settings_in_tor_service));
@@ -1612,7 +1636,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
{
showToolbarNotification (getString(R.string.your_reachableaddresses_settings_caused_an_exception_),ERROR_NOTIFY_ID,R.drawable.ic_stat_notifyerr);
- return false;
+ return null;
}
try
@@ -1636,7 +1660,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
showToolbarNotification (getString(R.string.your_relay_settings_caused_an_exception_),ERROR_NOTIFY_ID,R.drawable.ic_stat_notifyerr);
- return false;
+ return null;
}
ContentResolver mCR = getApplicationContext().getContentResolver();
@@ -1685,7 +1709,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
client_cookies.close();
}
- return true;
+ return extraLines;
}
public static String flattenToAscii(String string) {
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
index 4b62a6a8..b557de80 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
@@ -10,8 +10,8 @@ public interface TorServiceConstants {
String TOR_APP_USERNAME = "org.torproject.android";
String BROWSER_APP_USERNAME = "info.guardianproject.orfox";
- String DIRECTORY_TOR_BINARY = "bin";
- String DIRECTORY_TOR_DATA = "data";
+ //String DIRECTORY_TOR_BINARY = "bin";
+ //String DIRECTORY_TOR_DATA = "data";
//name of the tor C binary
String TOR_ASSET_KEY = "tor";
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java b/orbotservice/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java
new file mode 100644
index 00000000..6e75a98e
--- /dev/null
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/CustomNativeLoader.java
@@ -0,0 +1,132 @@
+package org.torproject.android.service.util;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Build;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+public class CustomNativeLoader {
+
+ private final static String LIB_NAME = "tor";
+ private final static String LIB_SO_NAME = "tor.so";
+
+ private final static String TAG = "TorNativeLoader";
+
+ private static boolean loadFromZip(Context context, File destLocalFile, String arch) {
+
+
+ ZipFile zipFile = null;
+ InputStream stream = null;
+
+ try {
+ zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
+ ZipEntry entry = zipFile.getEntry("lib/" + arch + "/" + LIB_SO_NAME);
+ if (entry == null) {
+ throw new Exception("Unable to find file in apk:" + "lib/" + arch + "/" + LIB_NAME);
+ }
+
+ //how we wrap this in another stream because the native .so is zipped itself
+ stream = zipFile.getInputStream(entry);
+
+ OutputStream out = new FileOutputStream(destLocalFile);
+ byte[] buf = new byte[4096];
+ int len;
+ while ((len = stream.read(buf)) > 0) {
+ Thread.yield();
+ out.write(buf, 0, len);
+ }
+ out.close();
+
+ if (Build.VERSION.SDK_INT >= 9) {
+ destLocalFile.setReadable(true, false);
+ destLocalFile.setExecutable(true, false);
+ destLocalFile.setWritable(true);
+ }
+
+ return true;
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+ if (zipFile != null) {
+ try {
+ zipFile.close();
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+ }
+ return false;
+ }
+
+ public static synchronized File initNativeLibs(Context context, File destLocalFile) {
+
+ try {
+ String folder = Build.CPU_ABI;
+
+ /**
+ try {
+
+ if (Build.CPU_ABI.equalsIgnoreCase("arm64-v8a")) {
+ folder = "arm64-v8a";
+ }
+ else if (Build.CPU_ABI.equalsIgnoreCase("arm64")) {
+ folder = "arm64";
+ }
+ else if (Build.CPU_ABI.equalsIgnoreCase("x86_64")) {
+ folder = "x86_64";
+ }
+ else if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
+ folder = "armeabi-v7a";
+ }
+ else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
+ folder = "armeabi";
+ } else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
+ folder = "x86";
+ } else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
+ folder = "mips";
+ } else {
+ folder = "armeabi";
+ //FileLog.e("tmessages", "Unsupported arch: " + Build.CPU_ABI);
+ }
+
+ } catch (Exception e) {
+ // FileLog.e("tmessages", e);
+ Log.e(TAG, e.getMessage(),e);
+ folder = "armeabi";
+ }**/
+
+
+ String javaArch = System.getProperty("os.arch");
+ if (javaArch != null && javaArch.contains("686")) {
+ folder = "x86";
+ }
+
+
+ if (loadFromZip(context, destLocalFile, folder)) {
+ return destLocalFile;
+ }
+
+ } catch (Throwable e) {
+ Log.e(TAG, e.getMessage(),e);
+ }
+
+
+ return null;
+ }
+}
+
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java b/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java
new file mode 100644
index 00000000..8bd5fe6f
--- /dev/null
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java
@@ -0,0 +1,101 @@
+package org.torproject.android.service.util;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
+
+import com.jaredrummler.android.shell.CommandResult;
+import com.jaredrummler.android.shell.Shell;
+import com.jaredrummler.android.shell.ShellExitCode;
+import com.jaredrummler.android.shell.StreamGobbler;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CustomShell extends Shell {
+
+
+ @WorkerThread
+ public static CommandResult run(@NonNull String shell, boolean waitFor, @Nullable String[] env, @NonNull String command) {
+ List<String> stdout = Collections.synchronizedList(new ArrayList<String>());
+ List<String> stderr = Collections.synchronizedList(new ArrayList<String>());
+ int exitCode = -1;
+
+ try {
+
+ // setup our process, retrieve stdin stream, and stdout/stderr gobblers
+ //Process process = runWithEnv(command, env);
+ ProcessBuilder builder = new ProcessBuilder();
+ builder.command("/system/bin/sh", "-c", command);
+ Process process = builder.start();
+
+ // DataOutputStream stdin = new DataOutputStream(process.getOutputStream());
+ StreamGobbler stdoutGobbler = null;
+ StreamGobbler stderrGobbler = null;
+
+ if (waitFor) {
+ stdoutGobbler = new StreamGobbler(process.getInputStream(), stdout);
+ stderrGobbler = new StreamGobbler(process.getErrorStream(), stderr);
+
+ // start gobbling and write our commands to the shell
+ stdoutGobbler.start();
+ stderrGobbler.start();
+ }
+
+ /**
+
+ try {
+ for (String write : commands) {
+ stdin.write((write + " &\n").getBytes("UTF-8"));
+ stdin.flush();
+ }
+
+ if (waitFor)
+ stdin.write("exit\n".getBytes("UTF-8"));
+
+ stdin.flush();
+ } catch (IOException e) {
+ //noinspection StatementWithEmptyBody
+ if (e.getMessage().contains("EPIPE")) {
+ // method most horrid to catch broken pipe, in which case we do nothing. the command is not a shell, the
+ // shell closed stdin, the script already contained the exit command, etc. these cases we want the output
+ // instead of returning null
+ } else {
+ // other issues we don't know how to handle, leads to returning null
+ throw e;
+ }
+ }**/
+
+ // wait for our process to finish, while we gobble away in the background
+ if (waitFor)
+ exitCode = process.waitFor();
+ else
+ exitCode = 0;
+
+ // make sure our threads are done gobbling, our streams are closed, and the process is destroyed - while the
+ // latter two shouldn't be needed in theory, and may even produce warnings, in "normal" Java they are required
+ // for guaranteed cleanup of resources, so lets be safe and do this on Android as well
+ /**
+ try {
+ stdin.close();
+ } catch (IOException e) {
+ // might be closed already
+ }**/
+
+ if (waitFor) {
+ stdoutGobbler.join();
+ stderrGobbler.join();
+ }
+
+ } catch (InterruptedException e) {
+ exitCode = ShellExitCode.WATCHDOG_EXIT;
+ } catch (IOException e) {
+ exitCode = ShellExitCode.SHELL_WRONG_UID;
+ }
+
+ return new CommandResult(stdout, stderr, exitCode);
+ }
+}
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java b/orbotservice/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java
new file mode 100644
index 00000000..043987e2
--- /dev/null
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/CustomTorResourceInstaller.java
@@ -0,0 +1,244 @@
+package org.torproject.android.service.util;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.util.Log;
+
+import org.torproject.android.binary.NativeLoader;
+import org.torproject.android.binary.TorServiceConstants;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.concurrent.TimeoutException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+
+public class CustomTorResourceInstaller implements TorServiceConstants {
+
+
+ File installFolder;
+ Context context;
+
+ File fileTorrc;
+ File fileTor;
+
+ public CustomTorResourceInstaller (Context context, File installFolder)
+ {
+ this.installFolder = installFolder;
+ this.context = context;
+ }
+
+ public File getTorrcFile ()
+ {
+ return fileTorrc;
+ }
+
+ public File getTorFile ()
+ {
+ return fileTor;
+ }
+
+ /**
+ private void deleteDirectory(File file) {
+ if( file.exists() ) {
+ if (file.isDirectory()) {
+ File[] files = file.listFiles();
+ for(int i=0; i<files.length; i++) {
+ if(files[i].isDirectory()) {
+ deleteDirectory(files[i]);
+ }
+ else {
+ files[i].delete();
+ }
+ }
+ }
+
+ file.delete();
+ }
+ }**/
+
+ //
+ /*
+ * Extract the Tor resources from the APK file using ZIP
+ *
+ * @File path to the Tor executable
+ */
+ public File installResources () throws IOException, TimeoutException
+ {
+
+ fileTor = new File(installFolder, TOR_ASSET_KEY);
+
+ if (!installFolder.exists())
+ installFolder.mkdirs();
+
+ installGeoIP();
+ fileTorrc = assetToFile(COMMON_ASSET_KEY + TORRC_ASSET_KEY, TORRC_ASSET_KEY, false, false);
+
+ File fileNativeDir = new File(getNativeLibraryDir(context));
+ fileTor = new File(fileNativeDir,TOR_ASSET_KEY + ".so");
+
+ if (fileTor.exists())
+ {
+ if (fileTor.canExecute())
+ return fileTor;
+ else
+ {
+ setExecutable(fileTor);
+
+ if (fileTor.canExecute())
+ return fileTor;
+ }
+ }
+
+ if (fileTor.exists()) {
+ InputStream is = new FileInputStream(fileTor);
+ streamToFile(is, fileTor, false, true);
+ setExecutable(fileTor);
+
+ if (fileTor.exists() && fileTor.canExecute())
+ return fileTor;
+ }
+
+ //let's try another approach
+ fileTor = new File(installFolder, TOR_ASSET_KEY);
+ //fileTor = NativeLoader.initNativeLibs(context,fileTor);
+ CustomNativeLoader.initNativeLibs(context,fileTor);
+
+ setExecutable(fileTor);
+
+ if (fileTor != null && fileTor.exists() && fileTor.canExecute())
+ return fileTor;
+
+ return null;
+ }
+
+
+ // Return Full path to the directory where native JNI libraries are stored.
+ private static String getNativeLibraryDir(Context context) {
+ ApplicationInfo appInfo = context.getApplicationInfo();
+ return appInfo.nativeLibraryDir;
+ }
+
+
+ public boolean updateTorConfigCustom (File fileTorRcCustom, String extraLines) throws IOException, FileNotFoundException, TimeoutException
+ {
+ if (fileTorRcCustom.exists())
+ {
+ fileTorRcCustom.delete();
+ Log.d("torResources","deleting existing torrc.custom");
+ }
+ else
+ fileTorRcCustom.createNewFile();
+
+ FileOutputStream fos = new FileOutputStream(fileTorRcCustom, false);
+ PrintStream ps = new PrintStream(fos);
+ ps.print(extraLines);
+ ps.close();
+
+ return true;
+ }
+
+ /*
+ * Extract the Tor binary from the APK file using ZIP
+ */
+
+ private boolean installGeoIP () throws IOException
+ {
+
+ assetToFile(COMMON_ASSET_KEY + GEOIP_ASSET_KEY, GEOIP_ASSET_KEY, false, false);
+
+ assetToFile(COMMON_ASSET_KEY + GEOIP6_ASSET_KEY, GEOIP6_ASSET_KEY, false, false);
+
+ return true;
+ }
+
+ /*
+ * Reads file from assetPath/assetKey writes it to the install folder
+ */
+ private File assetToFile(String assetPath, String assetKey, boolean isZipped, boolean isExecutable) throws IOException {
+ InputStream is = context.getAssets().open(assetPath);
+ File outFile = new File(installFolder, assetKey);
+ streamToFile(is, outFile, false, isZipped);
+ if (isExecutable) {
+ setExecutable(outFile);
+ }
+ return outFile;
+ }
+
+
+ /*
+ * Write the inputstream contents to the file
+ */
+ private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException
+
+ {
+ byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
+
+ int bytecount;
+
+ OutputStream stmOut = new FileOutputStream(outFile.getAbsolutePath(), append);
+ ZipInputStream zis = null;
+
+ if (zip)
+ {
+ zis = new ZipInputStream(stm);
+ ZipEntry ze = zis.getNextEntry();
+ stm = zis;
+
+ }
+
+ while ((bytecount = stm.read(buffer)) > 0)
+ {
+
+ stmOut.write(buffer, 0, bytecount);
+
+ }
+
+ stmOut.close();
+ stm.close();
+
+ if (zis != null)
+ zis.close();
+
+
+ return true;
+
+ }
+
+
+
+ private void setExecutable(File fileBin) {
+ fileBin.setReadable(true);
+ fileBin.setExecutable(true);
+ fileBin.setWritable(false);
+ fileBin.setWritable(true, true);
+ }
+
+ private static File[] listf(String directoryName) {
+
+ // .............list file
+ File directory = new File(directoryName);
+
+ // get all the files from a directory
+ File[] fList = directory.listFiles();
+
+ if (fList != null)
+ for (File file : fList) {
+ if (file.isFile()) {
+ Log.d(TAG,file.getAbsolutePath());
+ } else if (file.isDirectory()) {
+ listf(file.getAbsolutePath());
+ }
+ }
+
+ return fList;
+ }
+}
+
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/NativeLoader.java b/orbotservice/src/main/java/org/torproject/android/service/util/NativeLoader.java
index 4ad10bb1..8621add2 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/util/NativeLoader.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/NativeLoader.java
@@ -9,6 +9,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
@@ -24,8 +25,20 @@ public class NativeLoader {
InputStream stream = null;
try {
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
+
+ /**
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements())
+ {
+ ZipEntry entry = entries.nextElement();
+ Log.d("Zip","entry: " + entry.getName());
+ }
+ **/
+
ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + libName + ".so");
if (entry == null) {
+ entry = zipFile.getEntry("lib/" + folder + "/" + libName);
+ if (entry == null)
throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + libName);
}
stream = zipFile.getInputStream(entry);
@@ -68,27 +81,7 @@ public class NativeLoader {
public static synchronized boolean initNativeLibs(Context context, String binaryName, File destLocalFile) {
try {
- String folder = null;
-
- try {
-
- if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
- folder = "armeabi-v7a";
- } else if (Build.CPU_ABI.startsWith("armeabi")) {
- folder = "armeabi";
- } else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
- folder = "x86";
- } else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
- folder = "mips";
- } else {
- folder = "armeabi";
- }
- } catch (Exception e) {
- // FileLog.e("tmessages", e);
- Log.e(TAG, e.getMessage());
- folder = "armeabi";
- }
-
+ String folder = Build.CPU_ABI;
String javaArch = System.getProperty("os.arch");
if (javaArch != null && javaArch.contains("686")) {
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/OtherResourceInstaller.java b/orbotservice/src/main/java/org/torproject/android/service/util/OtherResourceInstaller.java
index 309f7e58..241f6c7e 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/util/OtherResourceInstaller.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/OtherResourceInstaller.java
@@ -70,12 +70,12 @@ public class OtherResourceInstaller implements TorServiceConstants {
if (!installFolder.exists())
installFolder.mkdirs();
- outFile = new File(installFolder, OBFSCLIENT_ASSET_KEY);
- NativeLoader.initNativeLibs(context,OBFSCLIENT_ASSET_KEY,outFile);
-
outFile = new File(installFolder, PDNSD_ASSET_KEY);
NativeLoader.initNativeLibs(context,PDNSD_ASSET_KEY,outFile);
+// outFile = new File(installFolder, OBFSCLIENT_ASSET_KEY);
+ // NativeLoader.initNativeLibs(context,OBFSCLIENT_ASSET_KEY,outFile);
+
return true;
}
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/PortForwarder.java b/orbotservice/src/main/java/org/torproject/android/service/util/PortForwarder.java
new file mode 100644
index 00000000..d487fb43
--- /dev/null
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/PortForwarder.java
@@ -0,0 +1,80 @@
+package org.torproject.android.service.util;
+
+import android.util.Log;
+
+import com.offbynull.portmapper.PortMapperFactory;
+import com.offbynull.portmapper.gateway.Bus;
+import com.offbynull.portmapper.gateway.Gateway;
+import com.offbynull.portmapper.gateways.network.NetworkGateway;
+import com.offbynull.portmapper.gateways.network.internalmessages.KillNetworkRequest;
+import com.offbynull.portmapper.gateways.process.ProcessGateway;
+import com.offbynull.portmapper.gateways.process.internalmessages.KillProcessRequest;
+import com.offbynull.portmapper.mapper.MappedPort;
+import com.offbynull.portmapper.mapper.PortMapper;
+import com.offbynull.portmapper.mapper.PortType;
+
+import java.util.List;
+
+public class PortForwarder {
+
+ private boolean shutdown = false;
+ private Thread mThread = null;
+
+ public void shutdown ()
+ {
+ shutdown = true;
+ }
+
+ public void forward (final int internalPort, final int externalPort, final long lifetime) throws InterruptedException {
+
+ mThread = new Thread ()
+ {
+ public void run ()
+ {
+ try {
+ forwardSync(internalPort, externalPort, lifetime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ mThread.start();
+ }
+
+
+ public void forwardSync (int internalPort, int externalPort, long lifetime) throws InterruptedException {
+ // Start gateways
+ Gateway network = NetworkGateway.create();
+ Gateway process = ProcessGateway.create();
+ Bus networkBus = network.getBus();
+ Bus processBus = process.getBus();
+
+// Discover port forwarding devices and take the first one found
+ List<PortMapper> mappers = PortMapperFactory.discover(networkBus, processBus);
+ PortMapper mapper = mappers.get(0);
+
+// Map internal port 12345 to some external port (55555 preferred)
+//
+// IMPORTANT NOTE: Many devices prevent you from mapping ports that are <= 1024
+// (both internal and external ports). Be mindful of this when choosing which
+// ports you want to map.
+ MappedPort mappedPort = mapper.mapPort(PortType.TCP, internalPort, externalPort, lifetime);
+ Log.d(getClass().getName(),"Port mapping added: " + mappedPort);
+
+// Refresh mapping half-way through the lifetime of the mapping (for example,
+// if the mapping is available for 40 seconds, refresh it every 20 seconds)
+ while(!shutdown) {
+ mappedPort = mapper.refreshPort(mappedPort, mappedPort.getLifetime() / 2L);
+ Log.d(getClass().getName(),"Port mapping refreshed: " + mappedPort);
+ Thread.sleep(mappedPort.getLifetime() * 1000L);
+ }
+
+// Unmap port 12345
+ mapper.unmapPort(mappedPort);
+
+// Stop gateways
+ networkBus.send(new KillNetworkRequest());
+ processBus.send(new KillProcessRequest()); // can kill this after discovery
+ }
+}
diff --git a/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java b/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java
index e5419f3c..5ca4505c 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/vpn/OrbotVpnManager.java
@@ -37,6 +37,7 @@ import com.runjva.sourceforge.jsocks.protocol.ProxyServer;
import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
import org.torproject.android.service.R;
+import org.torproject.android.service.TorService;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.service.util.TorServiceUtils;
@@ -73,12 +74,15 @@ public class OrbotVpnManager implements Handler.Callback {
private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
//this is the actual DNS server we talk to over UDP or TCP (now using Tor's DNS port)
- private final static String DEFAULT_ACTUAL_DNS_HOST = "127.0.0.1";
- private final static int DEFAULT_ACTUAL_DNS_PORT = TorServiceConstants.TOR_DNS_PORT_DEFAULT;
+ //private final static String DEFAULT_ACTUAL_DNS_HOST = "127.0.0.1";
+ //private final static int DEFAULT_ACTUAL_DNS_PORT = TorServiceConstants.TOR_DNS_PORT_DEFAULT;
+
File filePdnsd = null;
+ private final static int PDNSD_PORT = 8091;
+
private boolean isRestart = false;
private VpnService mService;
@@ -88,7 +92,7 @@ public class OrbotVpnManager implements Handler.Callback {
{
mService = service;
- File fileBinHome = mService.getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
+ File fileBinHome = service.getFilesDir();//mService.getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
filePdnsd = new File(fileBinHome,TorServiceConstants.PDNSD_ASSET_KEY);
Tun2Socks.init();
@@ -276,6 +280,8 @@ public class OrbotVpnManager implements Handler.Callback {
isRestart = true;
Tun2Socks.Stop();
}
+
+ final int localDns = TorService.mPortDns;
mThreadVPN = new Thread ()
{
@@ -290,10 +296,7 @@ public class OrbotVpnManager implements Handler.Callback {
Log.d(TAG,"is a restart... let's wait for a few seconds");
Thread.sleep(3000);
}
-
- //start PDNSD daemon pointing to actual DNS
- startDNS(DEFAULT_ACTUAL_DNS_HOST,DEFAULT_ACTUAL_DNS_PORT);
-
+
final String vpnName = "OrbotVPN";
final String localhost = "127.0.0.1";
@@ -306,8 +309,8 @@ public class OrbotVpnManager implements Handler.Callback {
final String localSocks = localhost + ':'
+ String.valueOf(mTorSocks);
- final String localDNS = virtualGateway + ':' + "8091";//String.valueOf(TorServiceConstants.TOR_DNS_PORT_DEFAULT);
- //final String localDNS = virtualGateway + ":" + DEFAULT_ACTUAL_DNS_PORT;
+ final String localDNS = virtualGateway + ':' + PDNSD_PORT;
+
final boolean localDnsTransparentProxy = true;
builder.setMtu(VPN_MTU);
@@ -345,8 +348,12 @@ public class OrbotVpnManager implements Handler.Callback {
Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , localDnsTransparentProxy);
isRestart = false;
-
- }
+
+ //start PDNSD daemon pointing to actual DNS
+ startDNS("127.0.0.1",localDns);
+
+
+ }
catch (Exception e)
{
Log.d(TAG,"tun2Socks has stopped",e);
diff --git a/orbotservice/src/main/jni/Application.mk b/orbotservice/src/main/jni/Application.mk
index d35e1e9c..58e4e08f 100644
--- a/orbotservice/src/main/jni/Application.mk
+++ b/orbotservice/src/main/jni/Application.mk
@@ -1,3 +1,3 @@
-APP_ABI := armeabi armeabi-v7a x86
+APP_ABI := armeabi armeabi-v7a x86 arm64-v8a x86_64
APP_PLATFORM := android-16
APP_STL := c++_static
More information about the tor-commits
mailing list