diff --git a/BUILD b/BUILD index bbbeaa8f2..8e9b9b333 100644 --- a/BUILD +++ b/BUILD @@ -23,10 +23,9 @@ You then need to run "ndk-build" from: cd orbotservice/src/main ndk-build - mkdir -p assets/armeabi - zip assets/armeabi/pdnsd.mp3 libs/armeabi/pdnsd - mkdir -p assets/x86 - zip assets/x86/pdnsd.mp3 libs/x86/pdnsd + mv libs/armeabi/pdnsd libs/armeabi/pdnsd.so + mv libs/armeabi-v7a/pdnsd libs/armeabi-v7a/pdnsd.so + mv libs/x86/pdnsd libs/x86/pdnsd.so This isn't enough though and we'll now sew up the binary into a small package that will handle basic Tor controlling features. diff --git a/app/build.gradle b/app/build.gradle index be2c18308..7508ccce7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { } buildTypes { release { - minifyEnabled false - shrinkResources false + minifyEnabled true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } diff --git a/app/proguard-rules.txt b/app/proguard-rules.txt index bc4eb0c15..b1120f82d 100644 --- a/app/proguard-rules.txt +++ b/app/proguard-rules.txt @@ -1,3 +1,11 @@ +-dontobfuscate +# https://stackoverflow.com/questions/9651703/using-proguard-with-android-without-obfuscation +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable + +-keep class org.torproject.android.service.vpn.Tun2Socks { + void logTun2Socks(java.lang.String, java.lang.String, java.lang.String); +} + -keepattributes Signature -keepattributes Annotation -keep class okhttp3.** { *; } diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java b/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java index 1a0f20caa..e03a8d2d9 100644 --- a/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java +++ b/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java @@ -5,26 +5,19 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.TextUtils; -import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.widget.RadioButton; import android.widget.TextView; -import android.widget.Toast; import org.torproject.android.R; import org.torproject.android.service.OrbotConstants; -import org.torproject.android.service.TorServiceConstants; import org.torproject.android.service.util.Prefs; import org.torproject.android.settings.LocaleHelper; @@ -41,57 +34,52 @@ public class BridgeWizardActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bridge_wizard); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - tvStatus = (TextView)findViewById(R.id.lbl_bridge_test_status); + tvStatus = findViewById(R.id.lbl_bridge_test_status); tvStatus.setVisibility(View.GONE); setTitle(getString(R.string.bridges)); - RadioButton btnDirect = (RadioButton) - findViewById(R.id.btnBridgesDirect); + RadioButton btnDirect = findViewById(R.id.btnBridgesDirect); btnDirect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Prefs.setBridgesList(""); Prefs.putBridgesEnabled(false); testBridgeConnection(); - } }); - RadioButton btnObfs4 = (RadioButton)findViewById(R.id.btnBridgesObfs4); + RadioButton btnObfs4 = findViewById(R.id.btnBridgesObfs4); btnObfs4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Prefs.setBridgesList("obfs4"); Prefs.putBridgesEnabled(true); testBridgeConnection(); - } }); - RadioButton btnMeek = (RadioButton)findViewById(R.id.btnBridgesMeek); - + RadioButton btnMeek = findViewById(R.id.btnBridgesMeek); btnMeek.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Prefs.setBridgesList("meek"); Prefs.putBridgesEnabled(true); testBridgeConnection(); - } }); - RadioButton btnNew = (RadioButton)findViewById(R.id.btnBridgesNew); + RadioButton btnNew = findViewById(R.id.btnBridgesNew); btnNew.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - showGetBridgePrompt(""); + showGetBridgePrompt(); } }); @@ -102,7 +90,6 @@ else if (Prefs.getBridgesList().equals("meek")) else if (Prefs.getBridgesList().equals("obfs4")) btnObfs4.setChecked(true); - } @Override @@ -112,8 +99,7 @@ protected void attachBaseContext(Context base) { @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) - { + if (item.getItemId() == android.R.id.home) { finish(); return true; } @@ -122,180 +108,100 @@ public boolean onOptionsItemSelected(MenuItem item) { } - private void showGetBridgePrompt (final String type) - { - LayoutInflater li = LayoutInflater.from(this); - View view = li.inflate(R.layout.layout_diag, null); - - TextView versionName = (TextView)view.findViewById(R.id.diaglog); - versionName.setText(R.string.you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_); - + private void showGetBridgePrompt() { new AlertDialog.Builder(this) .setTitle(R.string.bridge_mode) - .setView(view) - .setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener() - { + .setMessage(R.string.you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_) + .setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //do nothing } }) - .setNeutralButton(R.string.get_bridges_email, new Dialog.OnClickListener () - { - + .setNeutralButton(R.string.get_bridges_email, new Dialog.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - - - sendGetBridgeEmail(type); - + sendGetBridgeEmail(); } - }) - .setPositiveButton(R.string.get_bridges_web, new Dialog.OnClickListener () - { - + .setPositiveButton(R.string.get_bridges_web, new Dialog.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - - openBrowser(OrbotConstants.URL_TOR_BRIDGES + type,true, null); - + openBrowser(OrbotConstants.URL_TOR_BRIDGES, true); } - - }).show(); } - private void sendGetBridgeEmail (String type) - { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("message/rfc822"); - intent.putExtra(Intent.EXTRA_EMAIL , new String[]{"bridges@torproject.org"}); - - if (type != null) - { - intent.putExtra(Intent.EXTRA_SUBJECT, "get transport " + type); - intent.putExtra(Intent.EXTRA_TEXT, "get transport " + type); - - } - else - { - intent.putExtra(Intent.EXTRA_SUBJECT, "get bridges"); - intent.putExtra(Intent.EXTRA_TEXT, "get bridges"); - - } - - startActivity(Intent.createChooser(intent, getString(R.string.send_email))); + private void sendGetBridgeEmail() { + String email = "bridges@torproject.org"; + Uri emailUri = Uri.parse("mailto:" + email); + Intent emailIntent = new Intent(Intent.ACTION_SENDTO, emailUri); + emailIntent.putExtra(Intent.EXTRA_SUBJECT, "get transport"); + emailIntent.putExtra(Intent.EXTRA_TEXT, "get transport"); + startActivity(Intent.createChooser(emailIntent, getString(R.string.send_email))); } /* * Launch the system activity for Uri viewing with the provided url */ - private void openBrowser(final String browserLaunchUrl,boolean forceExternal, String pkgId) - { - startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(browserLaunchUrl))); - } - - - private void startIntent (String pkg, String action, Uri data) - { - Intent i; - PackageManager pm = getPackageManager(); - - try { - if (pkg != null) { - i = pm.getLaunchIntentForPackage(pkg); - if (i == null) - throw new PackageManager.NameNotFoundException(); - } - else - { - i = new Intent(); - } - - i.setAction(action); - i.setData(data); - - if (i.resolveActivity(pm)!=null) - startActivity(i); - - } catch (PackageManager.NameNotFoundException e) { - - } + private void openBrowser(final String browserLaunchUrl, boolean forceExternal) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl))); } - private boolean appInstalledOrNot(String uri) - { - PackageManager pm = getPackageManager(); - try - { - PackageInfo pi = pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES); - return pi.applicationInfo.enabled; - } - catch (PackageManager.NameNotFoundException e) - { - return false; - } - } - private void testBridgeConnection () - { - if (TextUtils.isEmpty(Prefs.getBridgesList()) || (!Prefs.bridgesEnabled())) - { - new HostTester().execute("check.torproject.org","443"); - } - else if (Prefs.getBridgesList().equals("meek")) - { - new HostTester().execute("meek.azureedge.net","443","d2cly7j4zqgua7.cloudfront.net","443"); - } - else if (Prefs.getBridgesList().equals("obfs4")) - { - new HostTester().execute("85.17.30.79","443","154.35.22.9","443","192.99.11.54","443"); - } - else - { + private void testBridgeConnection() { + if (TextUtils.isEmpty(Prefs.getBridgesList()) || (!Prefs.bridgesEnabled())) { + new HostTester().execute("check.torproject.org", "443"); + } else if (Prefs.getBridgesList().equals("meek")) { + new HostTester().execute("meek.azureedge.net", "443", "d2cly7j4zqgua7.cloudfront.net", "443"); + } else if (Prefs.getBridgesList().equals("obfs4")) { + new HostTester().execute("85.17.30.79", "443", "154.35.22.9", "443", "192.99.11.54", "443"); + } else { tvStatus.setText(""); } } private class HostTester extends AsyncTask { + @Override protected void onPreExecute() { // Pre Code tvStatus.setVisibility(View.VISIBLE); tvStatus.setText(R.string.testing_bridges); } - protected Boolean doInBackground(String... host) { - // Background Code - boolean result = false; - - for (int i = 0; i < host.length; i++) { - String testHost = host[i]; - i++; //move to the port - int testPort = Integer.parseInt(host[i]); - result = isHostReachable(testHost, testPort, 10000); - if (result) - return result; - } - return result; - } - protected void onPostExecute(Boolean result) { - // Post Code - if (result) - { - tvStatus.setText(R.string.testing_bridges_success); + @Override + protected Boolean doInBackground(String... host) { + // Background Code + boolean result = false; + + for (int i = 0; i < host.length; i++) { + String testHost = host[i]; + i++; //move to the port + int testPort = Integer.parseInt(host[i]); + result = isHostReachable(testHost, testPort, 10000); + if (result) + return result; + } + return result; } - else - { - tvStatus.setText(R.string.testing_bridges_fail); + @Override + protected void onPostExecute(Boolean result) { + // Post Code + if (result) { + tvStatus.setText(R.string.testing_bridges_success); + + } else { + tvStatus.setText(R.string.testing_bridges_fail); + + } } - }}; + } - private static boolean isHostReachable(String serverAddress, int serverTCPport, int timeoutMS){ + private static boolean isHostReachable(String serverAddress, int serverTCPport, int timeoutMS) { boolean connected = false; Socket socket; try { diff --git a/app/src/main/res/layout/content_bridge_wizard.xml b/app/src/main/res/layout/content_bridge_wizard.xml index 858bf0652..a5b7995bb 100644 --- a/app/src/main/res/layout/content_bridge_wizard.xml +++ b/app/src/main/res/layout/content_bridge_wizard.xml @@ -4,71 +4,63 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="org.torproject.android.ui.onboarding.BridgeWizardActivity" - tools:showIn="@layout/activity_bridge_wizard" - android:orientation="vertical" - > + tools:showIn="@layout/activity_bridge_wizard"> + android:textSize="16sp" + android:textStyle="bold" /> + - - - + - - /> + - /> + + android:textSize="16sp" + android:textStyle="bold" /> diff --git a/app/src/main/res/layout/layout_diag.xml b/app/src/main/res/layout/layout_diag.xml deleted file mode 100644 index 5b4ce2155..000000000 --- a/app/src/main/res/layout/layout_diag.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a61dc01a5..e1ba7f9b1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -314,7 +314,7 @@ If your mobile network actively blocks Tor, you can use a \'Bridge Server\' as an alternate way in. SELECT one of the options to configure and test... - Bridge Mode + Request New Bridge Email Web @@ -327,7 +327,7 @@ Send Email - You can get a bridge address through email, the web or by scanning a bridge QR code. Select \'Email\' or \'Web\' below to request a bridge address.\n\nOnce you have an address, copy & paste it into the \"Bridges\" preference in Orbot\'s setting and restart. + You can get a bridge address through email, the web or by scanning a bridge QR code. Select \'Email\' or \'Web\' below to request a bridge address.\n\nOnce you have an address, copy & paste it into the \"Bridges\" preference in Orbot\'s settings and restart. Install Orfox 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 f63eb255a..c7cc708ed 100644 --- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java +++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java @@ -696,7 +696,6 @@ private boolean updateTorConfigFile () throws IOException, TimeoutException extraLines.append("SOCKSPort ").append(socksPortPref).append(isolate).append('\n'); extraLines.append("SafeSocks 0").append('\n'); extraLines.append("TestSocks 0").append('\n'); - extraLines.append("WarnUnsafeSocks 1").append('\n'); if (Prefs.openProxyOnAllInterfaces()) extraLines.append("SocksListenAddress 0.0.0.0").append('\n'); @@ -716,10 +715,8 @@ private boolean updateTorConfigFile () throws IOException, TimeoutException 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("DNSPort ").append(dnsPort).append('\n'); - if (Prefs.useVpn()) - extraLines.append("DNSListenAddress 0.0.0.0").append('\n'); extraLines.append("VirtualAddrNetwork 10.192.0.0/10").append('\n'); extraLines.append("AutomapHostsOnResolve 1").append('\n'); 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 d6a254360..3e910cce1 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 @@ -21,16 +21,14 @@ private static boolean loadFromZip(Context context, String libName, File destLoc ZipFile zipFile = null; - ZipInputStream stream = null; + InputStream stream = null; try { zipFile = new ZipFile(context.getApplicationInfo().sourceDir); ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + libName + ".so"); if (entry == null) { throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + libName); } - //the zip file entry is also zipped itself! - stream = new ZipInputStream(zipFile.getInputStream(entry)); - stream.getNextEntry(); + stream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(destLocalFile); byte[] buf = new byte[4096];