commit 56917567cd21a734a35f3bee0e56ba23793b6887 Author: n8fr8 nathan@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
tor-commits@lists.torproject.org