tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2017
- 20 participants
- 1183 discussions
commit ed5e8aca9c765b1a46029e4a4125df325d1042f2
Author: arrase <arrase(a)gmail.com>
Date: Tue Nov 29 19:09:10 2016 +0100
fix
---
app/src/main/java/org/torproject/android/OrbotMainActivity.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index abad2db..2cb44c4 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -27,6 +27,7 @@ import org.torproject.android.ui.AppManager;
import org.torproject.android.ui.ImageProgressView;
import org.torproject.android.ui.PromoAppsActivity;
import org.torproject.android.ui.Rotate3dAnimation;
+import org.torproject.android.ui.hiddenservices.HiddenServicesActivity;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.vpn.VPNEnableActivity;
@@ -510,6 +511,8 @@ public class OrbotMainActivity extends AppCompatActivity
}
}
+ } else if (item.getItemId() == R.id.menu_hidden_services) {
+ startActivity(new Intent(this, HiddenServicesActivity.class));
}
return super.onOptionsItemSelected(item);
1
0

[orbot/master] adds optional HiddenServiceAuthorizeClient option for each hidden service
by n8fr8@torproject.org 02 Mar '17
by n8fr8@torproject.org 02 Mar '17
02 Mar '17
commit 4d0fe27ea3ed88a1c8cf6cefb28acce075ae17da
Author: arrase <arrase(a)gmail.com>
Date: Sun Dec 4 21:10:44 2016 +0100
adds optional HiddenServiceAuthorizeClient option for each hidden service
---
.../org/torproject/android/OrbotMainActivity.java | 8 ++++++--
.../ui/hiddenservices/HiddenServicesActivity.java | 8 ++++++++
.../ui/hiddenservices/backup/BackupUtils.java | 15 ++++++++++++++
.../ui/hiddenservices/database/HSDatabase.java | 2 ++
.../ui/hiddenservices/dialogs/HSActionsDialog.java | 24 ++++++++++++++++++++++
.../ui/hiddenservices/dialogs/HSDataDialog.java | 9 ++++++--
.../providers/HSContentProvider.java | 4 ++++
app/src/main/res/layout/layout_hs_actions.xml | 6 ++++++
app/src/main/res/layout/layout_hs_data_dialog.xml | 8 ++++++++
app/src/main/res/values/strings.xml | 4 ++++
.../org/torproject/android/service/TorService.java | 23 ++++++++++++++++++---
11 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 2cb44c4..07d0199 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -593,7 +593,8 @@ public class OrbotMainActivity extends AppCompatActivity
private void enableHiddenServicePort(
String hsName, final int hsPort, int hsRemotePort,
- final String backupToPackage, final Uri hsKeyPath
+ final String backupToPackage, final Uri hsKeyPath,
+ final Boolean authCookie
) throws RemoteException, InterruptedException {
String onionHostname = null;
@@ -608,6 +609,7 @@ public class OrbotMainActivity extends AppCompatActivity
fields.put(HSContentProvider.HiddenService.NAME, hsName);
fields.put(HSContentProvider.HiddenService.PORT, hsPort);
fields.put(HSContentProvider.HiddenService.ONION_PORT, hsRemotePort);
+ fields.put(HSContentProvider.HiddenService.AUTH_COOKIE, authCookie);
ContentResolver cr = getContentResolver();
@@ -725,6 +727,7 @@ public class OrbotMainActivity extends AppCompatActivity
final int hiddenServiceRemotePort = intent.getIntExtra("hs_onion_port", -1);
final String hiddenServiceName = intent.getStringExtra("hs_name");
final String backupToPackage = intent.getStringExtra("hs_backup_to_package");
+ final Boolean authCookie = intent.getBooleanExtra("hs_auth_cookie", false);
final Uri mKeyUri = intent.getData();
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@@ -735,7 +738,8 @@ public class OrbotMainActivity extends AppCompatActivity
try {
enableHiddenServicePort(
hiddenServiceName, hiddenServicePort,
- hiddenServiceRemotePort, backupToPackage, mKeyUri
+ hiddenServiceRemotePort, backupToPackage,
+ mKeyUri, authCookie
);
} catch (RemoteException e) {
// TODO Auto-generated catch block
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index 99af182..c4f55a1 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -90,6 +90,14 @@ public class HiddenServicesActivity extends AppCompatActivity {
"onion", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
);
+ arguments.putInt(
+ "auth_cookie", item.getInt(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
+ );
+
+ arguments.putString(
+ "auth_cookie_value", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
+ );
+
HSActionsDialog dialog = new HSActionsDialog();
dialog.setArguments(arguments);
dialog.show(getSupportFragmentManager(), "HSActionsDialog");
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
index 5a1185c..1dccbf8 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
@@ -89,6 +89,16 @@ public class BackupUtils {
);
config.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE,
+ portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
+ );
+
+ config.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE_VALUE,
+ portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
+ );
+
+ config.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.CREATED_BY_USER))
);
@@ -174,6 +184,11 @@ public class BackupUtils {
);
fields.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE,
+ savedValues.getInt(HSContentProvider.HiddenService.AUTH_COOKIE)
+ );
+
+ fields.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
savedValues.getInt(HSContentProvider.HiddenService.CREATED_BY_USER)
);
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
index 8f1123f..93ccd25 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
@@ -16,6 +16,8 @@ public class HSDatabase extends SQLiteOpenHelper {
"name TEXT, " +
"domain TEXT, " +
"onion_port INTEGER, " +
+ "auth_cookie INTEGER DEFAULT 0, " +
+ "auth_cookie_value TEXT, " +
"created_by_user INTEGER DEFAULT 0, " +
"port INTEGER);";
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
index e1b9dd3..06b650b 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
@@ -83,6 +83,30 @@ public class HSActionsDialog extends DialogFragment {
}
});
+ Button showAuth = (Button) dialog_view.findViewById(R.id.bt_hs_show_auth);
+ showAuth.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ String auth_cookie_value = arguments.getString("auth_cookie_value");
+ if (arguments.getInt("auth_cookie") == 1) {
+ if (auth_cookie_value == null || auth_cookie_value.length() < 1) {
+ Toast.makeText(
+ v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
+ } else {
+ new AlertDialog.Builder(getActivity())
+ .setMessage(auth_cookie_value)
+ .show();
+ }
+ } else {
+ Toast.makeText(
+ v.getContext(), R.string.auth_cookie_was_not_configured, Toast.LENGTH_LONG
+ ).show();
+ }
+
+ actionDialog.dismiss();
+ }
+ });
+
Button delete = (Button) dialog_view.findViewById(R.id.btn_hs_delete);
delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
index 329d6a8..56c6d3f 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
@@ -10,6 +10,7 @@ import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
@@ -42,8 +43,10 @@ public class HSDataDialog extends DialogFragment {
((EditText) dialog_view.findViewById(R.id.hsOnionPort)).getText().toString()
);
+ Boolean authCookie = ((CheckBox) dialog_view.findViewById(R.id.hsAuth)).isChecked();
+
if (checkInput(serverName, localPort, onionPort)) {
- saveData(serverName, localPort, onionPort);
+ saveData(serverName, localPort, onionPort, authCookie);
serviceDataDialog.dismiss();
}
}
@@ -80,11 +83,13 @@ public class HSDataDialog extends DialogFragment {
return is_ok;
}
- private void saveData(String name, Integer local, Integer remote) {
+ private void saveData(String name, Integer local, Integer remote, Boolean authCookie) {
+
ContentValues fields = new ContentValues();
fields.put(HSContentProvider.HiddenService.NAME, name);
fields.put(HSContentProvider.HiddenService.PORT, local);
fields.put(HSContentProvider.HiddenService.ONION_PORT, remote);
+ fields.put(HSContentProvider.HiddenService.AUTH_COOKIE, authCookie);
fields.put(HSContentProvider.HiddenService.CREATED_BY_USER, 1);
ContentResolver cr = getContext().getContentResolver();
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
index fe6dbf1..a0e85dd 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
@@ -22,6 +22,8 @@ public class HSContentProvider extends ContentProvider {
HiddenService.PORT,
HiddenService.DOMAIN,
HiddenService.ONION_PORT,
+ HiddenService.AUTH_COOKIE,
+ HiddenService.AUTH_COOKIE_VALUE,
HiddenService.CREATED_BY_USER
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
@@ -130,6 +132,8 @@ public class HSContentProvider extends ContentProvider {
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE = "auth_cookie";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String CREATED_BY_USER = "created_by_user";
private HiddenService() {
diff --git a/app/src/main/res/layout/layout_hs_actions.xml b/app/src/main/res/layout/layout_hs_actions.xml
index 64bda7d..0e5a668 100644
--- a/app/src/main/res/layout/layout_hs_actions.xml
+++ b/app/src/main/res/layout/layout_hs_actions.xml
@@ -10,6 +10,12 @@
android:id="@+id/btn_hs_clipboard" />
<Button
+ android:text="@string/show_auth_cookie"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/bt_hs_show_auth" />
+
+ <Button
android:text="@string/backup_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/layout_hs_data_dialog.xml b/app/src/main/res/layout/layout_hs_data_dialog.xml
index d791b1b..524d69a 100644
--- a/app/src/main/res/layout/layout_hs_data_dialog.xml
+++ b/app/src/main/res/layout/layout_hs_data_dialog.xml
@@ -53,6 +53,14 @@
android:id="@+id/hsOnionPort"
android:inputType="number" />
+ <CheckBox
+ android:text="@string/auth_cookie"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/hsAuth"
+ android:paddingTop="5dp"
+ android:paddingBottom="10dp"/>
+
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c8af6bb..b8192b8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -347,6 +347,7 @@
<string name="done">Done!</string>
<string name="invalid_port">Invalid Port</string>
<string name="copy_address_to_clipboard">Copy address to clipboard</string>
+ <string name="show_auth_cookie">Show auth cookie</string>
<string name="backup_service">Backup Service</string>
<string name="delete_service">Delete Service</string>
<string name="backup_saved_at_external_storage">Backup saved at external storage</string>
@@ -362,4 +363,7 @@
<string name="confirm_service_deletion">Confirm service deletion</string>
<string name="click_again_for_backup">Click again for backup</string>
<string name="service_type">Service type</string>
+ <string name="auth_cookie">Auth cookie</string>
+ <string name="auth_cookie_was_not_configured">Auth cookie was not configured</string>
+ <string name="please_restart_Orbot_to_enable_the_changes">Please restart Orbot to enable the changes</string>
</resources>
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 b7eab99..ff37d8c 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -139,6 +139,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE = "auth_cookie";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String CREATED_BY_USER = "created_by_user";
private HiddenService() {
@@ -147,8 +149,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private String[] mProjection = new String[]{
HiddenService._ID,
+ HiddenService.NAME,
HiddenService.DOMAIN,
HiddenService.PORT,
+ HiddenService.AUTH_COOKIE,
+ HiddenService.AUTH_COOKIE_VALUE,
HiddenService.ONION_PORT};
public void debug(String msg)
@@ -777,9 +782,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
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
- if(HSDomain == null || HSDomain.length() < 1) {
+ // 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");
@@ -789,7 +796,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
try {
String onionHostname = Utils.readString(new FileInputStream(file)).trim();
- fields.put("domain", onionHostname);
+ 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(CONTENT_URI, fields, "port=" + HSLocalPort , null);
} catch (FileNotFoundException e) {
logException("unable to read onion hostname file",e);
@@ -1784,14 +1796,19 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if(hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
+ String HSname = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.NAME));
Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
Integer HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.ONION_PORT));
+ Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
String hsDirPath = new File(mHSBasePath.getAbsolutePath(),"hs" + HSLocalPort).getCanonicalPath();
debug("Adding hidden service on port: " + HSLocalPort);
extraLines.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n');
extraLines.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n');
+
+ if(HSAuthCookie == 1)
+ extraLines.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n');
}
} catch (NumberFormatException e) {
Log.e(OrbotConstants.TAG,"error parsing hsport",e);
1
0
commit 54e2e5e37297d075cd76f53fdf23ada63a7e8e88
Author: arrase <arrase(a)gmail.com>
Date: Tue Nov 29 21:04:41 2016 +0100
fix for:
https://github.com/n8fr8/orbot/issues/63
---
app/src/main/java/org/torproject/android/OrbotMainActivity.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 7706c0f..551fb6e 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -105,6 +105,7 @@ public class OrbotMainActivity extends AppCompatActivity
/* Some tracking bits */
private String torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service
private Intent lastStatusIntent; // the last ACTION_STATUS Intent received
+ private Boolean isFirstRun = true;
private SharedPreferences mPrefs = null;
@@ -1301,8 +1302,9 @@ public class OrbotMainActivity extends AppCompatActivity
String newTorStatus = msg.getData().getString("status");
String log = (String)msg.obj;
- if (torStatus == null && newTorStatus != null) //first time status
+ if (isFirstRun && newTorStatus != null) //first time status
{
+ isFirstRun = false;
torStatus = newTorStatus;
findViewById(R.id.frameMain).setVisibility(View.VISIBLE);
updateStatus(log);
1
0
commit 07532bb04c787be0914e5a1f68da87998f087c18
Author: arrase <arrase(a)gmail.com>
Date: Tue Nov 29 20:33:34 2016 +0100
a better isolation of my changes
---
app/src/main/AndroidManifest.xml | 168 +++++++++++++++++++--------------------
1 file changed, 84 insertions(+), 84 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1704c70..826ce67 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,30 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.torproject.android"
- android:installLocation="auto"
- android:versionCode="15208000"
- android:versionName="15.2.0-RC-8-multi">
-
- <uses-sdk
- android:minSdkVersion="16"
- android:targetSdkVersion="23" />
- <!--
+ package="org.torproject.android"
+ android:versionName="15.2.0-RC-8-multi"
+ android:versionCode="15208000"
+ android:installLocation="auto"
+ >
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/>
+ <!--
<permission android:name="org.torproject.android.MANAGE_TOR"
android:label="@string/permission_manage_tor_label"
android:description="@string/permission_manage_tor_description"
android:protectionLevel="signature"/>
<uses-permission android:name="org.torproject.android.MANAGE_TOR"/>
- -->
+ -->
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
- <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
- <android:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".OrbotApp"
@@ -41,100 +38,103 @@
android:name=".OrbotMainActivity"
android:configChanges="orientation|screenSize"
android:excludeFromRecents="true"
- android:launchMode="singleTop">
+ android:launchMode="singleTop"
+ >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
+ </intent-filter>
+
<intent-filter>
<action android:name="android.intent.action.VIEW" />
-
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
-
<data android:scheme="bridge" />
</intent-filter>
- <intent-filter>
- <category android:name="android.intent.category.DEFAULT" />
+ <intent-filter>
+ <category android:name="android.intent.category.DEFAULT" />
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
</intent-filter>
- <intent-filter>
+ <intent-filter>
<category android:name="android.intent.category.DEFAULT" />
-
<action android:name="org.torproject.android.START_TOR" />
</intent-filter>
+
</activity>
- <!-- This is for ensuring the background service still runs when/if the app is swiped away -->
- <activity
- android:name=".service.util.DummyActivity"
- android:allowTaskReparenting="true"
- android:alwaysRetainTaskState="false"
- android:clearTaskOnLaunch="true"
- android:enabled="true"
- android:excludeFromRecents="true"
- android:finishOnTaskLaunch="true"
- android:noHistory="true"
- android:stateNotNeeded="true"
- android:theme="@android:style/Theme.Translucent" />
- <activity
- android:name=".vpn.VPNEnableActivity"
- android:exported="false"
- android:label="@string/app_name" />
- <activity
- android:name=".ui.PromoAppsActivity"
- android:exported="false" />
- <activity
- android:name=".settings.SettingsPreferences"
- android:label="@string/app_name" />
- <activity
- android:name=".ui.AppManager"
- android:label="@string/app_name"
- android:theme="@style/Theme.AppCompat" />
+ <!--
+ This is for ensuring the background service still runs when/if the app is swiped away
+ -->
+ <activity
+ android:name=".service.util.DummyActivity"
+ android:theme="@android:style/Theme.Translucent"
+ android:enabled="true"
+ android:allowTaskReparenting="true"
+ android:noHistory="true"
+ android:excludeFromRecents="true"
+ android:alwaysRetainTaskState="false"
+ android:stateNotNeeded="true"
+ android:clearTaskOnLaunch="true"
+ android:finishOnTaskLaunch="true"
+
+ />
+
+ <activity
+ android:name=".vpn.VPNEnableActivity" android:label="@string/app_name" android:exported="false"
+ />
+
+
+ <activity android:name="org.torproject.android.ui.PromoAppsActivity" android:exported="false"/>
+
+
+ <activity android:name=".settings.SettingsPreferences" android:label="@string/app_name"/>
+ <activity android:name=".ui.AppManager" android:label="@string/app_name"
+ android:theme="@style/Theme.AppCompat"
+ />
<service
android:name=".service.TorService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE"
- android:stopWithTask="false" />
- <service
- android:name=".service.vpn.TorVpnService"
- android:enabled="true"
- android:permission="android.permission.BIND_VPN_SERVICE">
- <intent-filter>
- <action android:name="android.net.VpnService" />
- </intent-filter>
+ android:stopWithTask="false" >
</service>
+
+ <service
+ android:name=".service.vpn.TorVpnService"
+ android:enabled="true"
+ android:permission="android.permission.BIND_VPN_SERVICE" >
+ <intent-filter>
+ <action android:name="android.net.VpnService"/>
+ </intent-filter>
+ </service>
+
<receiver
android:name=".service.StartTorReceiver"
android:exported="true">
- <intent-filter>
- <action android:name="org.torproject.android.intent.action.START" />
- </intent-filter>
+ <intent-filter>
+ <action android:name="org.torproject.android.intent.action.START" />
+ </intent-filter>
</receiver>
- <receiver
- android:name=".OnBootReceiver"
- android:enabled="true"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
-
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.QUICKBOOT_POWERON" />
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.MEDIA_MOUNTED" />
-
- <category android:name="android.intent.category.HOME" />
- </intent-filter>
- </receiver>
+ <receiver android:name=".OnBootReceiver"
+ android:enabled="true" android:exported="true"
+
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.QUICKBOOT_POWERON" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MEDIA_MOUNTED"/>
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </receiver>
<activity
android:name=".ui.hiddenservices.HiddenServicesActivity"
@@ -159,6 +159,6 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/hidden_services_paths"/>
</provider>
- </application>
-</manifest>
\ No newline at end of file
+</application>
+</manifest>
1
0
commit 94c68579e066d6531eb7f60b1b0705fad8bbbd72
Author: arrase <arrase(a)gmail.com>
Date: Mon Dec 5 22:29:33 2016 +0100
fix untranslated arrays
---
app/src/main/res/values-es/arrays.xml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/app/src/main/res/values-es/arrays.xml b/app/src/main/res/values-es/arrays.xml
new file mode 100644
index 0000000..f521c31
--- /dev/null
+++ b/app/src/main/res/values-es/arrays.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+
+ <string-array name="bridge_options">
+ <item>Obfs4 (Preferido)</item>
+ <item>Túnel a través de Azure</item>
+ <item>Túnel a través de Amazon</item>
+ <item>Obtener nuevos puentes</item>
+ <item></item>
+ </string-array>
+ <string-array name="array_hs_types">
+ <item>Usuarios</item>
+ <item>Aplicaciones</item>
+ </string-array>
+</resources>
1
0

[orbot/master] Merge branch 'fixiptables' of https://github.com/Unpublished/orbot into Unpublished-fixiptables
by n8fr8@torproject.org 02 Mar '17
by n8fr8@torproject.org 02 Mar '17
02 Mar '17
commit 970710d03cbe5ef167c71c6f4329e134cbd28224
Merge: ff61d66 639bc32
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Fri Jan 13 22:13:10 2017 -0500
Merge branch 'fixiptables' of https://github.com/Unpublished/orbot into Unpublished-fixiptables
.../android/service/transproxy/TorTransProxy.java | 27 ++++++++--------------
1 file changed, 10 insertions(+), 17 deletions(-)
diff --cc orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java
index da0a4a7,0000000..ca6d830
mode 100644,000000..100644
--- a/orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/transproxy/TorTransProxy.java
@@@ -1,1004 -1,0 +1,997 @@@
+package org.torproject.android.service.transproxy;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import org.sufficientlysecure.rootcommands.Shell;
+import org.sufficientlysecure.rootcommands.command.SimpleCommand;
+import org.torproject.android.service.OrbotConstants;
+import org.torproject.android.service.util.Prefs;
+import org.torproject.android.service.TorService;
+import org.torproject.android.service.TorServiceConstants;
+
+public class TorTransProxy implements TorServiceConstants {
+
+ private String mSysIptables = null;
+ private TorService mTorService = null;
+ private File mFileXtables = null;
+
+ private final static String ALLOW_LOCAL = " ! -d 127.0.0.1";
+
+ private int mTransProxyPort = TOR_TRANSPROXY_PORT_DEFAULT;
+ private int mDNSPort = TOR_DNS_PORT_DEFAULT;
+
+ private Shell mShell;
+
+ public TorTransProxy (TorService torService, File fileXTables) throws IOException
+ {
+ mTorService = torService;
+ mFileXtables = fileXTables;
+
+ // start root shell
+ mShell = Shell.startRootShell();
+
+ }
+
+ public static boolean testRoot () throws IOException
+ {
+ Runtime.getRuntime().exec("su");
+ return true;
+ }
+
+ public void setTransProxyPort (int transProxyPort)
+ {
+ mTransProxyPort = transProxyPort;
+ }
+
+ public void setDNSPort (int dnsPort)
+ {
+ mDNSPort = dnsPort;
+ }
+
+ public String getIpTablesPath (Context context)
+ {
+
+ String ipTablesPath = null;
+
+ if (Prefs.useSystemIpTables())
+ {
+ ipTablesPath = findSystemIPTables();
+ }
+ else
+ {
+ ipTablesPath = mFileXtables.getAbsolutePath();
+ ipTablesPath += " iptables"; //append subcommand since we are using xtables now
+
+ }
+
+ return ipTablesPath;
+ }
+
+ public String getIp6TablesPath (Context context)
+ {
+
+ String ipTablesPath = null;
+
+ if (Prefs.useSystemIpTables())
+ {
+ ipTablesPath = findSystemIP6Tables();
+ }
+ else
+ {
+ ipTablesPath = mFileXtables.getAbsolutePath();
+ ipTablesPath += " ip6tables"; //append subcommand since we are using xtables now
+
+ }
+
+ return ipTablesPath;
+
+ }
+
+ private String findSystemIPTables ()
+ {
- if (mSysIptables != null)
- {
- return mSysIptables;
- }
++
++ //if the user wants us to use the built-in iptables, then we have to find it
++ File fileIpt = new File("/system/xbin/iptables");
++
++ if (fileIpt.exists())
++ mSysIptables = fileIpt.getAbsolutePath();
+ else
+ {
-
- //if the user wants us to use the built-in iptables, then we have to find it
- File fileIpt = new File("/system/xbin/iptables");
-
++
++ fileIpt = new File("/system/bin/iptables");
++
+ if (fileIpt.exists())
+ mSysIptables = fileIpt.getAbsolutePath();
- else
- {
-
- fileIpt = new File("/system/bin/iptables");
-
- if (fileIpt.exists())
- mSysIptables = fileIpt.getAbsolutePath();
- }
+ }
-
++
+ return mSysIptables;
+ }
+
+
+
+ private String findSystemIP6Tables ()
+ {
+
+ //if the user wants us to use the built-in iptables, then we have to find it
+ File fileIpt = new File("/system/xbin/ip6tables");
+
+ if (fileIpt.exists())
+ mSysIptables = fileIpt.getAbsolutePath();
+ else
+ {
+
+ fileIpt = new File("/system/bin/ip6tables");
+
+ if (fileIpt.exists())
+ mSysIptables = fileIpt.getAbsolutePath();
+ }
+
+
+ return mSysIptables;
+ }
+
+ /*
+ public int flushIptablesAll(Context context) throws Exception {
+
+ String ipTablesPath = getIpTablesPath(context);
+
+ final StringBuilder script = new StringBuilder();
+
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(" -F || exit\n");
+
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(" -F || exit\n");
+
+ String[] cmd = {script.toString()};
+ code = TorServiceUtils.doShellCommand(cmd, res, true, true);
+ String msg = res.toString();
+
+ TorService.logMessage(cmd[0] + ";errCode=" + code + ";resp=" + msg);
+
+
+ return code;
+
+ }*/
+
+ /*
+ public static int purgeIptablesByApp(Context context, TorifiedApp[] apps) throws Exception {
+
+ //restoreDNSResolvConf(); //not working yet
+
+ String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+
+ final StringBuilder script = new StringBuilder();
+
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ for (int i = 0; i < apps.length; i++)
+ {
+ //flush nat for every app
+ script.append(ipTablesPath);
+ script.append(" -t nat -m owner --uid-owner ");
+ script.append(tApp.getUid());
+ script.append(" -F || exit\n");
+ public static ArrayList<TorifiedApp> getApps (Context context, SharedPreferences prefs)
+ {
+
+ String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
+ String[] tordApps;
+
+ StringTokenizer st = new StringTokenizer(tordAppString,"|");
+ tordApps = new String[st.countTokens()];
+ int tordIdx = 0;
+ while (st.hasMoreTokens())
+ {
+ tordApps[tordIdx++] = st.nextToken();
+ }
+
+ Arrays.sort(tordApps);
+
+ //else load the apps up
+ PackageManager pMgr = context.getPackageManager();
+
+ List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
+
+ Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
+
+ ArrayList<TorifiedApp> apps = new ArrayList<TorifiedApp>();
+
+ ApplicationInfo aInfo = null;
+
+ int appIdx = 0;
+ TorifiedApp app = null;
+
+ while (itAppInfo.hasNext())
+ {
+ aInfo = itAppInfo.next();
+
+ app = new TorifiedApp();
+
+ try {
+ PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
+
+ if (pInfo != null && pInfo.requestedPermissions != null)
+ {
+ for (String permInfo:pInfo.requestedPermissions)
+ {
+ if (permInfo.equals("android.permission.INTERNET"))
+ {
+ app.setUsesInternet(true);
+
+ }
+ }
+
+ }
+
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1)
+ {
+ //System app
+ app.setUsesInternet(true);
+ }
+
+
+ if (!app.usesInternet())
+ continue;
+ else
+ {
+ apps.add(app);
+ }
+
+
+ app.setEnabled(aInfo.enabled);
+ app.setUid(aInfo.uid);
+ app.setUsername(pMgr.getNameForUid(app.getUid()));
+ app.setProcname(aInfo.processName);
+ app.setPackageName(aInfo.packageName);
+
+ try
+ {
+ app.setName(pMgr.getApplicationLabel(aInfo).toString());
+ }
+ catch (Exception e)
+ {
+ app.setName(aInfo.packageName);
+ }
+
+
+ //app.setIcon(pMgr.getApplicationIcon(aInfo));
+
+ // check if this application is allowed
+ if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
+ app.setTorified(true);
+ }
+ else
+ {
+ app.setTorified(false);
+ }
+
+ appIdx++;
+ }
+
+ Collections.sort(apps);
+
+ return apps;
+ }
+
+
+ script.append(ipTablesPath);
+ script.append(" -t filter -m owner --uid-owner ");
+ script.append(tApp.getUid());
+ script.append(" -F || exit\n");
+
+ }
+
+
+ String[] cmd = {script.toString()};
+ code = TorServiceUtils.doShellCommand(cmd, res, true, true);
+ String msg = res.toString();
+ logNotice(cmd[0] + ";errCode=" + code + ";resp=" + msg);
+
+
+ return code;
+
+ }*/
+
+
+ /*
+ // 9/19/2010 - NF This code is in process... /etc path on System partition
+ // is read-only on Android for now.
+ public static int redirectDNSResolvConf () throws Exception
+ {
+ StringBuilder script = new StringBuilder();
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ //mv resolv.conf to resolve.conf.bak
+ String cmd = "mv /etc/resolv.conf /etc/resolv.conf.bak";
+ script.append(cmd);
+
+ //create new resolve.conf pointing to localhost/127.0.0.1
+ cmd = "echo \"nameserver 127.0.0.1\" > /etc/resolv.conf";
+ script.append(cmd);
+
+ String[] cmdFlush = {script.toString()};
+ code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true);
+ //String msg = res.toString(); //get stdout from command
+
+
+ return code;
+ }
+
+ public static int restoreDNSResolvConf () throws Exception
+ {
+ StringBuilder script = new StringBuilder();
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ //mv resolv.conf to resolve.conf.bak
+ String cmd = "mv /etc/resolv.conf.bak /etc/resolv.conf";
+ script.append(cmd);
+ script.append(" || exit\n");
+
+ String[] cmdFlush = {script.toString()};
+ code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true);
+ //String msg = res.toString(); //get stdout from command
+
+ return code;
+ }
+ */
+ /*
+ public int testOwnerModule(Context context, String ipTablesPath) throws Exception
+ {
+
+ TorBinaryInstaller.assertIpTablesBinaries(context, false);
+
+ boolean runRoot = true;
+ boolean waitFor = true;
+
+ int torUid = context.getApplicationInfo().uid;
+
+ StringBuilder script = new StringBuilder();
+
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ // Allow everything for Tor
+ script.append(ipTablesPath);
+ script.append(" -A OUTPUT");
+ script.append(" -t filter");
+ script.append(" -m owner --uid-owner ");
+ script.append(torUid);
+ script.append(" -j ACCEPT");
+ script.append(" || exit\n");
+
+ script.append(ipTablesPath);
+ script.append(" -D OUTPUT");
+ script.append(" -t filter");
+ script.append(" -m owner --uid-owner ");
+ script.append(torUid);
+ script.append(" -j ACCEPT");
+ script.append(" || exit\n");
+
+ String[] cmdAdd = {script.toString()};
+
+ code = TorServiceUtils.doShellCommand(cmdAdd, res, runRoot, waitFor);
+ String msg = res.toString();
+
+ if (mTorService != null)
+ logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg);
+
+
+ return code;
+ }
+ */
+
+ /*
+ public int clearTransparentProxyingByApp (Context context, ArrayList<TorifiedApp> apps) throws Exception
+ {
+ boolean runRoot = true;
+ boolean waitFor = true;
+
+ String ipTablesPath = getIpTablesPath(context);
+
+ StringBuilder script = new StringBuilder();
+
+ StringBuilder res = new StringBuilder();
+ int code = -1;
+
+ String chainName = "ORBOT";
+ String jumpChainName = "OUTPUT";
+
+ script.append(ipTablesPath);
+ script.append(" --flush ").append(chainName); //delete previous user-defined chain
+ script.append(" || exit\n");
+
+ script.append(ipTablesPath);
+ script.append(" -D ").append(jumpChainName);
+ script.append(" -j ").append(chainName);
+ script.append(" || exit\n");
+
+ script.append(ipTablesPath);
+ script.append(" -X ").append(chainName); //delete previous user-defined chain
+ script.append(" || exit\n");
+
+ String[] cmdAdd = {script.toString()};
+
+ code = TorServiceUtils.doShellCommand(cmdAdd, res, runRoot, waitFor);
+ String msg = res.toString();
+
+ logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg);
+
+ return code;
+ }*/
+
+ public int setTransparentProxyingByApp(Context context, ArrayList<TorifiedApp> apps, boolean enableRule) throws Exception
+ {
+ String ipTablesPath = getIpTablesPath(context);
+
+ //StringBuilder script = new StringBuilder();
+
+ String action = " -A ";
+ String srcChainName = "OUTPUT";
+
+ if (!enableRule)
+ action = " -D ";
+
+ //run the delete commands in a separate process as it might error out
+ //String[] cmdExecClear = {script.toString()};
+ //code = TorServiceUtils.doShellCommand(cmdExecClear, res, runRoot, waitFor);
+
+ //reset script
+
+ int lastExit = -1;
+ StringBuilder script;
+
+
+ // Same for DNS
+ script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -p udp");
+ //script.append(" -m owner --uid-owner ");
+ //script.append(tApp.getUid());
+ //script.append(" -m udp --dport ");
+ script.append(" --dport ");
+ script.append(STANDARD_DNS_PORT);
+ script.append(" -j REDIRECT --to-ports ");
+ script.append(mDNSPort);
+ executeCommand (script.toString());
+
+ // Allow everything for Tor
+
+ //build up array of shell cmds to execute under one root context
+ for (TorifiedApp tApp:apps)
+ {
+
+ if (((!enableRule) || tApp.isTorified())
+ && (!tApp.getUsername().equals(TOR_APP_USERNAME))
+ ) //if app is set to true
+ {
+
+
+ logMessage("transproxy for app: " + tApp.getUsername() + " (" + tApp.getUid() + "): enable=" + enableRule);
+
+ dropAllIPv6Traffic(context, tApp.getUid(),enableRule);
+
+ script = new StringBuilder();
+
+ // Allow loopback
+ /**
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -m owner --uid-owner ");
+ script.append(tApp.getUid());
+ script.append(" -o lo");
+ script.append(" -j ACCEPT");
+
+ executeCommand (shell, script.toString());
+ script = new StringBuilder();
+ **/
+
+ // Set up port redirection
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(ALLOW_LOCAL);
+ script.append(" -m owner --uid-owner ");
+ script.append(tApp.getUid());
+ script.append(" -m tcp --syn");
+ script.append(" -j REDIRECT --to-ports ");
+ script.append(mTransProxyPort);
+
+ executeCommand (script.toString());
+
+
+ script = new StringBuilder();
+
+ // Reject all other outbound packets
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -m owner --uid-owner ");
+ script.append(tApp.getUid());
+ script.append(ALLOW_LOCAL);
+ script.append(" -j REJECT");
+
+ lastExit = executeCommand (script.toString());
+
+
+ }
+ }
+
+ return lastExit;
+ }
+
+ private int executeCommand (String cmdString) throws Exception {
+
+ SimpleCommand command = new SimpleCommand(cmdString);
+
+ mShell.add(command).waitForFinish();
+
+ logMessage("Command Exec: " + cmdString);
+ logMessage("Output: " + command.getOutput());
+ logMessage("Exit code: " + command.getExitCode());
+
+ return 0;
+ }
+
+ public void closeShell () throws IOException
+ {
+ mShell.close();
+ }
+
+ public int enableTetheringRules (Context context) throws Exception
+ {
+
+ String ipTablesPath = getIpTablesPath(context);
+
+ StringBuilder script = new StringBuilder();
+
+ String[] hwinterfaces = {"usb0","wl0.1"};
+
+
+ int lastExit = -1;
+
+ for (int i = 0; i < hwinterfaces.length; i++)
+ {
+
+ script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -t nat -A PREROUTING -i ");
+ script.append(hwinterfaces[i]);
+ script.append(" -p udp --dport 53 -j REDIRECT --to-ports ");
+ script.append(mDNSPort);
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+
+ script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -t nat -A PREROUTING -i ");
+ script.append(hwinterfaces[i]);
+ script.append(" -p tcp -j REDIRECT --to-ports ");
+ script.append(mTransProxyPort);
+
+ lastExit = executeCommand (script.toString());
+ script = new StringBuilder();
+
+
+ }
+
+ return lastExit;
+ }
+
+ private void logMessage (String msg)
+ {
+ if (mTorService != null)
+ mTorService.debug(msg);
+ }
+
+
+
+ public int fixTransproxyLeak (Context context) throws Exception
+ {
+ String ipTablesPath = getIpTablesPath(context);
+
+ StringBuilder script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j DROP");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,RST ACK,RST -j DROP");
+
+ int lastExit = executeCommand (script.toString());
+ script = new StringBuilder();
+
+ return lastExit;
+
+ }
+
+ public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop) throws Exception {
+
+ String action = " -A ";
+ String chain = "OUTPUT";
+
+ if (!enableDrop)
+ action = " -D ";
+
+ String ip6tablesPath = getIp6TablesPath(context);
+
+ StringBuilder script;
+
+ script = new StringBuilder();
+ script.append(ip6tablesPath);
+ script.append(action);
+ script.append(chain);
+
+ if (appUid != -1)
+ {
+ script.append(" -m owner --uid-owner ");
+ script.append(appUid);
+ }
+
+ script.append(" -j DROP");
+
+ int lastExit = executeCommand (script.toString());
+
+ return lastExit;
+ }
+
+ /*
+ public int clearAllIPv6Filters (Context context) throws Exception
+ {
+
+ String ip6tablesPath = getIp6TablesPath(context);
+ Shell shell = Shell.startRootShell();
+
+ StringBuilder script;
+
+ script = new StringBuilder();
+ script.append(ip6tablesPath);
+ script.append(" -t filter");
+ script.append(" -F OUTPUT");
+ int lastExit = executeCommand (shell, script.toString());
+
+ shell.close();
+
+ return lastExit;
+ }*/
+
+ public int flushTransproxyRules (Context context) throws Exception {
+ int exit = -1;
+
+ String ipTablesPath = getIpTablesPath(context);
+
+ StringBuilder script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -t nat ");
+ script.append(" -F ");
+
+ executeCommand (script.toString());
+
+ script = new StringBuilder();
+ script.append(ipTablesPath);
+ script.append(" -t filter ");
+ script.append(" -F ");
+ executeCommand (script.toString());
+
+ dropAllIPv6Traffic(context,-1,false);
+ dropAllIPv6Traffic(context,-1,false);
+
+
+ return exit;
+ }
+
+ public int setTransparentProxyingAll(Context context, boolean enable) throws Exception
+ {
+
+ String action = " -A ";
+ String srcChainName = "OUTPUT";
+
+ if (!enable)
+ action = " -D ";
+
+ dropAllIPv6Traffic(context,-1,enable);
+
+ String ipTablesPath = getIpTablesPath(context);
+
+
+ int torUid = context.getApplicationInfo().uid;
+
+ StringBuilder script = new StringBuilder();
+
+ // Allow everything for Tor
+
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -m owner --uid-owner ");
+ script.append(torUid);
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ // Allow loopback
+
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -o lo");
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ // Set up port redirection
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(ALLOW_LOCAL); //allow access to localhost
+ script.append(" -m owner ! --uid-owner ");
+ script.append(torUid);
+ script.append(" -m tcp --syn");
+ script.append(" -j REDIRECT --to-ports ");
+ script.append(mTransProxyPort);
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ // Same for DNS
+ script.append(ipTablesPath);
+ script.append(" -t nat");
+ script.append(action).append(srcChainName);
+ script.append(" -p udp");
+ script.append(ALLOW_LOCAL); //allow access to localhost
+ script.append(" -m owner ! --uid-owner ");
+ script.append(torUid);
+ //script.append(" -m udp --dport ");
+ script.append(" --dport ");
+ script.append(STANDARD_DNS_PORT);
+ script.append(" -j REDIRECT --to-ports ");
+ script.append(mDNSPort);
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+
+ /**
+ if (Prefs.useDebugLogging())
+ {
+ //XXX: Comment the following rules for non-debug builds
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p udp");
+ script.append(" --dport ");
+ script.append(STANDARD_DNS_PORT);
+ script.append(" -j LOG");
+ script.append(" --log-prefix='ORBOT_DNSLEAK_PROTECTION'");
+ script.append(" --log-uid");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(" -j LOG");
+ script.append(" --log-prefix='ORBOT_TCPLEAK_PROTECTION'");
+ script.append(" --log-uid");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ }**/
+
+ //allow access to transproxy port
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(" -m tcp");
+ script.append(" --dport ").append(mTransProxyPort);
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ //allow access to local HTTP port
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(" -m tcp");
+ script.append(" --dport ").append(mTorService.getHTTPPort());
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ //allow access to local SOCKS port
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p tcp");
+ script.append(" -m tcp");
+ script.append(" --dport ").append(mTorService.getSOCKSPort());
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ //allow access to local DNS port
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -p udp");
+ script.append(" -m udp");
+ script.append(" --dport ").append(mDNSPort);
+ script.append(" -j ACCEPT");
+
+ executeCommand (script.toString());
+ script = new StringBuilder();
+
+ // Reject all other packets
+ script.append(ipTablesPath);
+ script.append(" -t filter");
+ script.append(action).append(srcChainName);
+ script.append(" -m owner ! --uid-owner ");
+ script.append(torUid);
+ script.append(ALLOW_LOCAL); //allow access to localhost
+ script.append(" -j REJECT");
+
+ int lastExit = executeCommand (script.toString());
+
+ // fixTransproxyLeak (context);
+
+ return lastExit;
+ }
+
+
+ public static ArrayList<TorifiedApp> getApps (Context context, SharedPreferences prefs)
+ {
+
+ String tordAppString = prefs.getString(OrbotConstants.PREFS_KEY_TORIFIED, "");
+ String[] tordApps;
+
+ StringTokenizer st = new StringTokenizer(tordAppString,"|");
+ tordApps = new String[st.countTokens()];
+ int tordIdx = 0;
+ while (st.hasMoreTokens())
+ {
+ tordApps[tordIdx++] = st.nextToken();
+ }
+
+ Arrays.sort(tordApps);
+
+ //else load the apps up
+ PackageManager pMgr = context.getPackageManager();
+
+ List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
+
+ Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
+
+ ArrayList<TorifiedApp> apps = new ArrayList<TorifiedApp>();
+
+ ApplicationInfo aInfo = null;
+
+ int appIdx = 0;
+ TorifiedApp app = null;
+
+ while (itAppInfo.hasNext())
+ {
+ aInfo = itAppInfo.next();
+
+ app = new TorifiedApp();
+
+ try {
+ PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
+
+ if (pInfo != null && pInfo.requestedPermissions != null)
+ {
+ for (String permInfo:pInfo.requestedPermissions)
+ {
+ if (permInfo.equals("android.permission.INTERNET"))
+ {
+ app.setUsesInternet(true);
+
+ }
+ }
+
+ }
+
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1)
+ {
+ //System app
+ app.setUsesInternet(true);
+ }
+
+
+ if (!app.usesInternet())
+ continue;
+ else
+ {
+ apps.add(app);
+ }
+
+
+ app.setEnabled(aInfo.enabled);
+ app.setUid(aInfo.uid);
+ app.setUsername(pMgr.getNameForUid(app.getUid()));
+ app.setProcname(aInfo.processName);
+ app.setPackageName(aInfo.packageName);
+
+ try
+ {
+ app.setName(pMgr.getApplicationLabel(aInfo).toString());
+ }
+ catch (Exception e)
+ {
+ app.setName(aInfo.packageName);
+ }
+
+
+ //app.setIcon(pMgr.getApplicationIcon(aInfo));
+
+ // check if this application is allowed
+ if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
+ app.setTorified(true);
+ }
+ else
+ {
+ app.setTorified(false);
+ }
+
+ appIdx++;
+ }
+
+ Collections.sort(apps);
+
+ return apps;
+ }
+
+}
1
0

[orbot/master] Merge branch 'update-ant-build' of https://github.com/eighthave/orbot into eighthave-update-ant-build
by n8fr8@torproject.org 02 Mar '17
by n8fr8@torproject.org 02 Mar '17
02 Mar '17
commit d937b9b958acd197f2e2ec4f827dc913d2ad5aa2
Merge: a5744d7 1e93ef4
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Fri Jan 13 22:16:59 2017 -0500
Merge branch 'update-ant-build' of https://github.com/eighthave/orbot into eighthave-update-ant-build
jenkins-build | 6 ++++--
make-release-build | 4 ++--
.../src/main/java/org/torproject/android/service/TorService.java | 4 +++-
.../java/org/torproject/android/service/TorServiceConstants.java | 4 +++-
4 files changed, 12 insertions(+), 6 deletions(-)
diff --cc orbotservice/src/main/java/org/torproject/android/service/TorService.java
index 53dd07a,0000000..b64bf0c
mode 100644,000000..100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@@ -1,2028 -1,0 +1,2030 @@@
+/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info/apps/orbot */
+/* See LICENSE for licensing information */
+/*
+ * Code for iptables binary management taken from DroidWall GPLv3
+ * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro
+ */
+
+package org.torproject.android.service;
+
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.app.Application;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.content.LocalBroadcastManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import org.sufficientlysecure.rootcommands.Shell;
+import org.sufficientlysecure.rootcommands.command.SimpleCommand;
+import org.torproject.android.control.ConfigEntry;
+import org.torproject.android.control.TorControlConnection;
+import org.torproject.android.service.transproxy.TorTransProxy;
+import org.torproject.android.service.transproxy.TorifiedApp;
+import org.torproject.android.service.util.DummyActivity;
+import org.torproject.android.service.util.Prefs;
+import org.torproject.android.service.util.TorResourceInstaller;
+import org.torproject.android.service.util.TorServiceUtils;
+import org.torproject.android.service.util.Utils;
+import org.torproject.android.service.vpn.OrbotVpnManager;
+import org.torproject.android.service.vpn.TorVpnService;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.text.Normalizer;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeoutException;
+
+public class TorService extends Service implements TorServiceConstants, OrbotConstants
+{
+
+ private String mCurrentStatus = STATUS_OFF;
+
+ 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;
+
+ private static final int NOTIFY_ID = 1;
+ private static final int TRANSPROXY_NOTIFY_ID = 2;
+ private static final int ERROR_NOTIFY_ID = 3;
+ private static final int HS_NOTIFY_ID = 4;
+
+ private ArrayList<String> configBuffer = null;
+ private ArrayList<String> resetBuffer = null;
+
+ private boolean isTorUpgradeAndConfigComplete = false;
+
+ private File fileControlPort;
+
+ private TorTransProxy mTransProxy;
+
+ private boolean mConnectivity = true;
+ private int mNetworkType = -1;
+
+ private NotificationManager mNotificationManager = null;
+ private NotificationCompat.Builder mNotifyBuilder;
+ private Notification mNotification;
+ private boolean mNotificationShowing = false;
+
+ boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+
+ private ExecutorService mExecutor = Executors.newFixedThreadPool(3);
+
+ TorEventHandler mEventHandler;
+
+ public static File appBinHome;
+ public static File appCacheHome;
+
+ public static File fileTor;
+ public static File filePolipo;
+ public static File fileObfsclient;
+ public static File fileXtables;
+ public static File fileTorRc;
+
+ private Shell mShell;
+ private Shell mShellPolipo;
+
+ public void debug(String msg)
+ {
+ if (Prefs.useDebugLogging())
+ {
+ Log.d(OrbotConstants.TAG,msg);
+ sendCallbackLogMessage(msg);
+
+ }
+ }
+
+ public void logException(String msg, Exception e)
+ {
+ if (Prefs.useDebugLogging())
+ {
+ Log.e(OrbotConstants.TAG,msg,e);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+
+ sendCallbackLogMessage(msg + '\n'+ new String(baos.toByteArray()));
+
+ }
+ else
+ sendCallbackLogMessage(msg);
+
+
+ }
+
+
+ private boolean findExistingTorDaemon() {
+ try {
+ mLastProcessId = initControlConnection(3, true);
+
+ if (mLastProcessId != -1 && conn != null) {
+ sendCallbackLogMessage(getString(R.string.found_existing_tor_process));
+ sendCallbackStatus(STATUS_ON);
+ showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
+
+ return true;
+ }
+ } catch (Exception e) {
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see android.app.Service#onLowMemory()
+ */
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+
+ logNotice( "Low Memory Warning!");
+
+ }
+
+ private void clearNotifications ()
+ {
+ if (mNotificationManager != null)
+ mNotificationManager.cancelAll();
+
+ if (mEventHandler != null)
+ mEventHandler.getNodes().clear();
+
+ mNotificationShowing = false;
+ }
+
+ @SuppressLint("NewApi")
+ protected void showToolbarNotification (String notifyMsg, int notifyType, int icon)
+ {
+
+ //Reusable code.
+ PackageManager pm = getPackageManager();
+ Intent intent = pm.getLaunchIntentForPackage(getPackageName());
+ PendingIntent pendIntent = PendingIntent.getActivity(TorService.this, 0, intent, 0);
+
+ if (mNotifyBuilder == null)
+ {
+
+ mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+
+ if (mNotifyBuilder == null)
+ {
+ mNotifyBuilder = new NotificationCompat.Builder(this)
+ .setContentTitle(getString(R.string.app_name))
+ .setSmallIcon(R.drawable.ic_stat_tor);
+
+ mNotifyBuilder.setContentIntent(pendIntent);
+
+ /**
+ //Restart intent
+ Intent yesReceive = new Intent();
+ yesReceive.setAction("Restart");
+ PendingIntent pendingIntentYes = PendingIntent.getBroadcast(this, 12345, yesReceive, PendingIntent.FLAG_UPDATE_CURRENT);
+ mNotifyBuilder.addAction(R.drawable.ic_stat_tor_off, "Restart", pendingIntentYes);
+
+
+ //Maybe intent
+ Intent maybeReceive = new Intent();
+ maybeReceive.setAction("Identity");
+ PendingIntent pendingIntentMaybe = PendingIntent.getBroadcast(this, 12345, maybeReceive, PendingIntent.FLAG_UPDATE_CURRENT);
+ mNotifyBuilder.addAction(R.drawable.ic_stat_tor_xfer, "New Identity", pendingIntentMaybe);
+ **/
+
+ }
+
+ }
+
+ mNotifyBuilder.setContentText(notifyMsg);
+ mNotifyBuilder.setSmallIcon(icon);
+
+ if (notifyType != NOTIFY_ID)
+ {
+ mNotifyBuilder.setTicker(notifyMsg);
+ }
+ else
+ {
+ mNotifyBuilder.setTicker(null);
+ }
+
+ mNotifyBuilder.setOngoing(Prefs.persistNotifications());
+
+ if (!Prefs.persistNotifications())
+ mNotifyBuilder.setPriority(Notification.PRIORITY_LOW);
+
+ mNotifyBuilder.setCategory(Notification.CATEGORY_SERVICE);
+
+ mNotification = mNotifyBuilder.build();
+
+ if (Build.VERSION.SDK_INT >= 16 && Prefs.expandedNotifications()) {
+ // Create remote view that needs to be set as bigContentView for the notification.
+ RemoteViews expandedView = new RemoteViews(this.getPackageName(),
+ R.layout.layout_notification_expanded);
+
+ StringBuffer sbInfo = new StringBuffer();
+
+ if (notifyType == NOTIFY_ID)
+ expandedView.setTextViewText(R.id.text, notifyMsg);
+ else
+ {
+ expandedView.setTextViewText(R.id.info, notifyMsg);
+ }
+
+ if (mEventHandler != null && mEventHandler.getNodes().size() > 0)
+ {
+ Set<String> itBuiltNodes = mEventHandler.getNodes().keySet();
+ for (String key : itBuiltNodes)
+ {
+ TorEventHandler.Node node = mEventHandler.getNodes().get(key);
+
+ if (node.ipAddress != null)
+ {
+ sbInfo.append(node.ipAddress);
+
+ if (node.country != null)
+ sbInfo.append(' ').append(node.country);
+
+ if (node.organization != null)
+ sbInfo.append(" (").append(node.organization).append(')');
+
+ sbInfo.append('\n');
+ }
+
+ }
+
+ expandedView.setTextViewText(R.id.text2, sbInfo.toString());
+ }
+
+ expandedView.setTextViewText(R.id.title, getString(R.string.app_name));
+
+ expandedView.setImageViewResource(R.id.icon, icon);
+ mNotification.bigContentView = expandedView;
+ }
+
+ if (Prefs.persistNotifications() && (!mNotificationShowing))
+ {
+ startForeground(NOTIFY_ID, mNotification);
+ logNotice("Set background service to FOREGROUND");
+ }
+ else
+ {
+ mNotificationManager.notify(NOTIFY_ID, mNotification);
+ }
+
+ mNotificationShowing = true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see android.app.Service#onStart(android.content.Intent, int)
+ */
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null)
+ exec (new IncomingIntentRouter(intent));
+ else
+ Log.d(OrbotConstants.TAG, "Got null onStartCommand() intent");
+
+ return Service.START_STICKY;
+ }
+
+ private class IncomingIntentRouter implements Runnable
+ {
+ Intent mIntent;
+
+ public IncomingIntentRouter (Intent intent)
+ {
+ mIntent = intent;
+ }
+
+ public void run() {
+
+ while (!isTorUpgradeAndConfigComplete)
+ {
+ try { Thread.sleep (500);}
+ catch (Exception e){}
+ }
+
+ String action = mIntent.getAction();
+
+ if (action != null) {
+ if (action.equals(ACTION_START)) {
+ replyWithStatus(mIntent);
+ startTor();
+ }
+ else if (action.equals(ACTION_STATUS)) {
+ replyWithStatus(mIntent);
+ }
+ else if (action.equals(CMD_SIGNAL_HUP)) {
+ requestTorRereadConfig();
+ } else if (action.equals(CMD_NEWNYM)) {
+ newIdentity();
+ } else if (action.equals(CMD_FLUSH)) {
+ flushTransparentProxyRules();
+ } else if (action.equals(CMD_UPDATE_TRANS_PROXY)) {
+ processTransparentProxying();
+ } else if (action.equals(CMD_VPN)) {
+ startVPNService();
+ } else if (action.equals(CMD_VPN_CLEAR)) {
+ clearVpnProxy();
+ } else if (action.equals(CMD_SET_EXIT)) {
+
+ setExitNode(mIntent.getStringExtra("exit"));
+
+ } else {
+ Log.w(OrbotConstants.TAG, "unhandled TorService Intent: " + action);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onTaskRemoved(Intent rootIntent){
+ Log.d(OrbotConstants.TAG,"task removed");
+ Intent intent = new Intent( this, DummyActivity.class );
+ intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
+ startActivity( intent );
+ }
+
+ @Override
+ public void onDestroy() {
+ stopTor();
+ unregisterReceiver(mNetworkStateReceiver);
+
+ try
+ {
+ mShell.close();
+ }
+ catch (IOException ioe)
+ {
+ Log.d(TAG, "Error closing shell",ioe);
+ }
+
+ super.onDestroy();
+ }
+
+ private void stopTor ()
+ {
+ exec(new Runnable ()
+ {
+ public void run ()
+ {
+ stopTorAsync();
+ }
+ });
+
+ }
+
+ private void stopTorAsync () {
+ Log.i("TorService", "stopTor");
+ try {
+ sendCallbackStatus(STATUS_STOPPING);
+ sendCallbackLogMessage(getString(R.string.status_shutting_down));
+
+ killAllDaemons();
+
+ //stop the foreground priority and make sure to remove the persistant notification
+ stopForeground(true);
+
+ if (Prefs.useRoot() && Prefs.useTransparentProxying())
+ {
+ disableTransparentProxy();
+ }
+
+ sendCallbackLogMessage(getString(R.string.status_disabled));
+ }
+ catch (Exception e)
+ {
+ logNotice("An error occured stopping Tor: " + e.getMessage());
+ sendCallbackLogMessage(getString(R.string.something_bad_happened));
+ }
+ clearNotifications();
+ sendCallbackStatus(STATUS_OFF);
+ }
+
+
+ private String getHiddenServiceHostname ()
+ {
+
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+
+ boolean enableHiddenServices = prefs.getBoolean("pref_hs_enable", false);
+
+ StringBuffer result = new StringBuffer();
+
+ if (enableHiddenServices)
+ {
+ String hsPorts = prefs.getString("pref_hs_ports","");
+
+ StringTokenizer st = new StringTokenizer (hsPorts,",");
+ String hsPortConfig = null;
+
+ while (st.hasMoreTokens())
+ {
+
+ int hsPort = Integer.parseInt(st.nextToken().split(" ")[0]);;
+
+ File fileDir = new File(appCacheHome, "hs" + hsPort);
+ File file = new File(fileDir, "hostname");
+
+
+ if (file.exists())
+ {
+ try {
+ String onionHostname = Utils.readString(new FileInputStream(file)).trim();
+
+ if (result.length() > 0)
+ result.append(",");
+
+ result.append(onionHostname);
+
+
+ } 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);
+ return null;
+ }
+ }
+ else
+ {
+ showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
+ return null;
+
+ }
+ }
+
+ if (result.length() > 0)
+ {
+ String onionHostname = result.toString();
+
+ showToolbarNotification(getString(R.string.hidden_service_on) + ' ' + onionHostname, HS_NOTIFY_ID, R.drawable.ic_stat_tor);
+ Editor pEdit = prefs.edit();
+ pEdit.putString("pref_hs_hostname",onionHostname);
+ pEdit.commit();
+
+ return onionHostname;
+ }
+
+ }
+
+ return null;
+ }
+
+
+ private void killAllDaemons() throws Exception {
+ if (conn != null) {
+ logNotice("Using control port to shutdown Tor");
+
+ try {
+ logNotice("sending HALT signal to Tor process");
+ conn.shutdownTor("HALT");
+
+ } catch (IOException e) {
+ Log.d(OrbotConstants.TAG, "error shutting down Tor via connection", e);
+ }
+
+ conn = null;
+ }
+
+ if (mShellPolipo != null)
+ {
+ mShellPolipo.close();
+ //logNotice("Polipo exited with value: " + exitValue);
+
+ }
+
+ }
+
+ private void requestTorRereadConfig() {
+ try {
+ conn.signal("HUP");
+ return;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // if that fails, try again using native utils
+ try {
+ TorServiceUtils.killProcess(fileTor, "-1"); // this is -HUP
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void logNotice (String msg)
+ {
+ if (msg != null && msg.trim().length() > 0)
+ {
+ if (Prefs.useDebugLogging())
+ Log.d(OrbotConstants.TAG, msg);
+
+ sendCallbackLogMessage(msg);
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ try
+ {
+ appBinHome = getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
+ appCacheHome = getDir(TorServiceConstants.DIRECTORY_TOR_DATA,Application.MODE_PRIVATE);
+
+ mShell = Shell.startShell();
+
+ fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY);
+ filePolipo = new File(appBinHome, TorServiceConstants.POLIPO_ASSET_KEY);
+ fileObfsclient = new File(appBinHome, TorServiceConstants.OBFSCLIENT_ASSET_KEY);
+ fileXtables = new File(appBinHome, TorServiceConstants.IPTABLES_ASSET_KEY);
+ fileTorRc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY);
+
+ mEventHandler = new TorEventHandler(this);
+
+ if (mNotificationManager == null)
+ {
+ mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ IntentFilter mNetworkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
+ registerReceiver(mNetworkStateReceiver , mNetworkStateFilter);
+
+
+ new Thread(new Runnable ()
+ {
+ public void run ()
+ {
+ try
+ {
+
+ torUpgradeAndConfig();
+
+ findExistingTorDaemon();
+ }
+ catch (Exception e)
+ {
+ Log.e(OrbotConstants.TAG,"error onBind",e);
+ logNotice("error finding exiting process: " + e.toString());
+ }
+
+ }
+ }).start();
+
+ }
+ catch (Exception e)
+ {
+ //what error here
+ Log.e(OrbotConstants.TAG, "Error installing Orbot binaries",e);
+ logNotice("There was an error installing Orbot binaries");
+ }
+
+ Log.i("TorService", "onCreate end");
+ }
+
+ protected String getCurrentStatus ()
+ {
+ return mCurrentStatus;
+ }
+
+ private void torUpgradeAndConfig() throws IOException, TimeoutException {
+ if (isTorUpgradeAndConfigComplete)
+ return;
+
+ 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);
+
+ if (version == null || (!version.equals(BINARY_TOR_VERSION)) || (!fileTor.exists()))
+ {
+ logNotice("upgrading binaries to latest version: " + BINARY_TOR_VERSION);
+
+ boolean success = installer.installResources();
+
+ if (success)
+ prefs.edit().putString(PREF_BINARY_TOR_VERSION_INSTALLED,BINARY_TOR_VERSION).commit();
+ }
+
+ updateTorConfigFile ();
+ isTorUpgradeAndConfigComplete = true;
+ }
+
+ private boolean updateTorConfigFile () throws FileNotFoundException, 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');
+
+ 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";
+ }
+
+ extraLines.append("SOCKSPort ").append(socksPortPref).append('\n');
+ extraLines.append("SafeSocks 0").append('\n');
+ extraLines.append("TestSocks 0").append('\n');
+ extraLines.append("WarnUnsafeSocks 1").append('\n');
+
+ 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");
+
+ if (Prefs.useVpn())
+ extraLines.append("DNSListenAddress 0.0.0.0").append('\n');
+
+ if (Prefs.transparentTethering())
+ {
+ extraLines.append("TransListenAddress 0.0.0.0").append('\n');
+ 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');
+
+ extraLines.append("DisableNetwork 0").append('\n');
+
+ if (Prefs.useDebugLogging())
+ {
+ extraLines.append("Log debug syslog").append('\n');
+ extraLines.append("Log info syslog").append('\n');
+ extraLines.append("SafeLogging 0").append('\n');
+
+ }
+
+ processSettingsImpl(extraLines);
+
+ String torrcCustom = new String(prefs.getString("pref_custom_torrc", "").getBytes("US-ASCII"));
+ extraLines.append(torrcCustom).append('\n');
+
+ logNotice("updating torrc custom configuration...");
+
+ debug("torrc.custom=" + extraLines.toString());
+
+ File fileTorRcCustom = new File(fileTorRc.getAbsolutePath() + ".custom");
+ boolean success = installer.updateTorConfigCustom(fileTorRcCustom, extraLines.toString());
+
+ if (success)
+ {
+ logNotice ("success.");
+ }
+
+ return success;
+ }
+
+ /**
+ * Send Orbot's status in reply to an
+ * {@link TorServiceConstants#ACTION_START} {@link Intent}, targeted only to
- * the app that sent the initial request.
++ * the app that sent the initial request. If the user has disabled auto-
++ * starts, the reply {@code ACTION_START Intent} will include the extra
++ * {@link TorServiceConstants#STATUS_STARTS_DISABLED}
+ */
+ private void replyWithStatus(Intent startRequest) {
+ String packageName = startRequest.getStringExtra(EXTRA_PACKAGE_NAME);
+
+ Intent reply = new Intent(ACTION_STATUS);
+ reply.putExtra(EXTRA_STATUS, mCurrentStatus);
+ reply.putExtra(EXTRA_SOCKS_PROXY, "socks://127.0.0.1:" + mPortSOCKS);
+ reply.putExtra(EXTRA_SOCKS_PROXY_HOST, "127.0.0.1");
+ reply.putExtra(EXTRA_SOCKS_PROXY_PORT, mPortSOCKS);
+ reply.putExtra(EXTRA_HTTP_PROXY, "http://127.0.0.1" + mPortHTTP);
+ reply.putExtra(EXTRA_HTTP_PROXY_HOST, "127.0.0.1");
+ reply.putExtra(EXTRA_HTTP_PROXY_PORT, mPortHTTP);
+
+ if (packageName != null)
+ {
+ reply.setPackage(packageName);
+ sendBroadcast(reply);
+ }
+ else
+ {
+ LocalBroadcastManager.getInstance(this).sendBroadcast(reply);
+
+ }
+
+ }
+
+ /**
+ * The entire process for starting tor and related services is run from this method.
+ */
+ private void startTor() {
+ // 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) {
+
+ sendCallbackLogMessage("Ignoring start request, already started.");
+ setTorNetworkEnabled (true);
+
+ return;
+ }
+
+
+ try {
+
+ // make sure there are no stray daemons running
+// killAllDaemons();
+
+ sendCallbackStatus(STATUS_STARTING);
+ showToolbarNotification(getString(R.string.status_starting_up),NOTIFY_ID,R.drawable.ic_stat_tor);
+ sendCallbackLogMessage(getString(R.string.status_starting_up));
+ logNotice(getString(R.string.status_starting_up));
+
+ ArrayList<String> customEnv = new ArrayList<String>();
+
+ if (Prefs.bridgesEnabled())
+ if (Prefs.useVpn() && !mIsLollipop)
+ {
+ customEnv.add("TOR_PT_PROXY=socks5://" + OrbotVpnManager.sSocksProxyLocalhost + ":" + OrbotVpnManager.sSocksProxyServerPort);
+ }
+
+ boolean success = runTorShellCmd();
+
+ if (mPortHTTP != -1)
+ runPolipoShellCmd();
+
+ if (Prefs.useRoot() && Prefs.useTransparentProxying())
+ {
+ disableTransparentProxy();
+ enableTransparentProxy();
+ }
+
+ getHiddenServiceHostname ();
+
+ } catch (Exception e) {
+ logException("Unable to start Tor: " + e.toString(), e);
+ showToolbarNotification(
+ getString(R.string.unable_to_start_tor) + ": " + e.getMessage(),
+ ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
+ stopTor();
+ }
+ }
+
+ private boolean flushTransparentProxyRules () {
+
+ try {
+ if (Prefs.useRoot()) {
+ if (mTransProxy == null)
+ mTransProxy = new TorTransProxy(this, fileXtables);
+
+ try {
+ mTransProxy.flushTransproxyRules(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ catch (IOException ioe)
+ {
+ return false;
+ }
+ }
+
+ /*
+ * activate means whether to apply the users preferences
+ * or clear them out
+ *
+ * the idea is that if Tor is off then transproxy is off
+ */
+ private boolean enableTransparentProxy () throws Exception
+ {
+
+ if (mTransProxy == null)
+ {
+ mTransProxy = new TorTransProxy(this, fileXtables);
+
+ }
+
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+ String transProxy = prefs.getString("pref_transport", TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT+"");
+ String dnsPort = prefs.getString("pref_dnsport", TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT+"");
+
+ if (transProxy.indexOf(':')!=-1) //we just want the port for this
+ transProxy = transProxy.split(":")[1];
+
+ if (dnsPort.indexOf(':')!=-1) //we just want the port for this
+ dnsPort = dnsPort.split(":")[1];
+
+ mTransProxy.setTransProxyPort(Integer.parseInt(transProxy));
+ mTransProxy.setDNSPort(Integer.parseInt(dnsPort));
+
+ int code = 0; // Default state is "okay"
+
+ if(Prefs.transparentProxyAll())
+ {
+
+ code = mTransProxy.setTransparentProxyingAll(this, true);
+ }
+ else
+ {
+ ArrayList<TorifiedApp> apps = TorTransProxy.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext()));
+
+ code = mTransProxy.setTransparentProxyingByApp(this,apps, true);
+ }
+
+ debug ("TorTransProxy resp code: " + code);
+
+ if (code == 0)
+ {
+
+ if (Prefs.transparentTethering())
+ {
+ showToolbarNotification(getString(R.string.transproxy_enabled_for_tethering_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
+
+ mTransProxy.enableTetheringRules(this);
+
+
+ }
+ else
+ {
+ showToolbarNotification(getString(R.string.transparent_proxying_enabled), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
+
+ }
+ }
+ else
+ {
+ showToolbarNotification(getString(R.string.warning_error_starting_transparent_proxying_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
+
+ }
+
+ return true;
+ }
+
+ /*
+ * activate means whether to apply the users preferences
+ * or clear them out
+ *
+ * the idea is that if Tor is off then transproxy is off
+ */
+ private boolean disableTransparentProxy () throws Exception
+ {
+
+ debug ("Transparent Proxying: disabling...");
+
+ if (mTransProxy == null)
+ mTransProxy = new TorTransProxy(this, fileXtables);
+
+ mTransProxy.setTransparentProxyingAll(this, false);
+
+ ArrayList<TorifiedApp> apps = TorTransProxy.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext()));
+ mTransProxy.setTransparentProxyingByApp(this, apps, false);
+
+ mTransProxy.closeShell();
+ mTransProxy = null;
+
+ return true;
+ }
+
+ private boolean runTorShellCmd() throws Exception
+ {
+ boolean result = true;
+
+ String torrcPath = new File(appBinHome, TORRC_ASSET_KEY).getCanonicalPath();
+
+ updateTorConfigFile();
+
+ sendCallbackLogMessage(getString(R.string.status_starting_up));
+
+ String torCmdString = fileTor.getCanonicalPath()
+ + " DataDirectory " + appCacheHome.getCanonicalPath()
+ + " --defaults-torrc " + torrcPath
+ + " -f " + torrcPath + ".custom";
+
+ debug(torCmdString);
+
+ int exitCode = exec(torCmdString + " --verify-config", true);
+
+ String output = "";
+ // String output = shellTorCommand.getOutput();
+
+ if (exitCode != 0)
+ {
+ logNotice("Tor (" + exitCode + "): " + output);
+ throw new Exception ("Torrc config did not verify");
+
+ }
+
+ exitCode = exec(torCmdString, true);
+ output = "";// shellTorCommand.getOutput();
+
+ if (exitCode != 0)
+ {
+ logNotice("Tor (" + exitCode + "): " + output);
+ //throw new Exception ("unable to start");
+ 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);
+
+ }
+
+ return result;
+ }
+
+
+ protected void exec (Runnable runn)
+ {
+ mExecutor.execute(runn);
+ }
+
+ private int exec (String cmd, boolean wait) throws Exception
+ {
+ SimpleCommand command = new SimpleCommand(cmd);
+ mShell.add(command);
+
+ if (wait)
+ command.waitForFinish();
+
+ return command.getExitCode();
+ }
+
+ 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");
+
+ updatePolipoConfig();
+
+ String polipoConfigPath = new File(appBinHome, POLIPOCONFIG_ASSET_KEY).getCanonicalPath();
+ String cmd = (filePolipo.getCanonicalPath() + " -c " + polipoConfigPath);
+
+ if (mShellPolipo != null)
+ mShellPolipo.close();
+
+ mShellPolipo = Shell.startShell();
+ SimpleCommand cmdPolipo = new SimpleCommand(cmd);
+ mShellPolipo.add(cmdPolipo);
+
+ 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
+ {
+ int controlPort = -1;
+ int attempt = 0;
+
+ logNotice( "Waiting for control port...");
+
+ while (conn == null && attempt++ < maxTries)
+ {
+ try
+ {
+
+ controlPort = getControlPort();
+
+ if (controlPort != -1)
+ {
+ logNotice( "Connecting to control port: " + controlPort);
+
+ torConnSocket = new Socket(IP_LOCALHOST, controlPort);
+ torConnSocket.setSoTimeout(CONTROL_SOCKET_TIMEOUT);
+
+ conn = new TorControlConnection(torConnSocket);
+ conn.launchThread(true);//is daemon
+
+ break;
+ }
+
+ }
+ catch (Exception ce)
+ {
+ conn = null;
+ // logException( "Error connecting to Tor local control port: " + ce.getMessage(),ce);
+
+ }
+
+
+ try {
+ // logNotice("waiting...");
+ Thread.sleep(1000); }
+ catch (Exception e){}
+ }
+
+ if (conn != null)
+ {
+ logNotice( "SUCCESS connected to Tor control port.");
+
+ File fileCookie = new File(appCacheHome, TOR_CONTROL_COOKIE);
+
+ if (fileCookie.exists())
+ {
+ byte[] cookie = new byte[(int)fileCookie.length()];
+ DataInputStream fis = new DataInputStream(new FileInputStream(fileCookie));
+ fis.read(cookie);
+ fis.close();
+ conn.authenticate(cookie);
+
+ logNotice( "SUCCESS - authenticated to control port.");
+
+ sendCallbackLogMessage(getString(R.string.tor_process_starting) + ' ' + getString(R.string.tor_process_complete));
+
+ addEventHandler();
+
+ String torProcId = conn.getInfo("process/pid");
+
+ String confSocks = conn.getInfo("net/listeners/socks");
+ StringTokenizer st = new StringTokenizer(confSocks," ");
+
+ confSocks = st.nextToken().split(":")[1];
+ confSocks = confSocks.substring(0,confSocks.length()-1);
+ mPortSOCKS = Integer.parseInt(confSocks);
+
+ return Integer.parseInt(torProcId);
+
+ }
+ else
+ {
+ logNotice ("Tor authentication cookie does not exist yet");
+ conn = null;
+
+ }
+ }
+
+
+ return -1;
+
+ }
+
+ private int getControlPort ()
+ {
+ int result = -1;
+
+ try
+ {
+ if (fileControlPort.exists())
+ {
+ debug("Reading control port config file: " + fileControlPort.getCanonicalPath());
+ BufferedReader bufferedReader = new BufferedReader(new FileReader(fileControlPort));
+ String line = bufferedReader.readLine();
+
+ if (line != null)
+ {
+ String[] lineParts = line.split(":");
+ result = Integer.parseInt(lineParts[1]);
+ }
+
+
+ bufferedReader.close();
+
+ //store last valid control port
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+ prefs.edit().putInt("controlport", result).commit();
+
+ }
+ else
+ {
+ debug("Control Port config file does not yet exist (waiting for tor): " + fileControlPort.getCanonicalPath());
+
+ }
+
+
+ }
+ catch (FileNotFoundException e)
+ {
+ debug("unable to get control port; file not found");
+ }
+ catch (Exception e)
+ {
+ debug("unable to read control port config file");
+ }
+
+ return result;
+ }
+
+ public synchronized void addEventHandler () throws Exception
+ {
+ // We extend NullEventHandler so that we don't need to provide empty
+ // implementations for all the events we don't care about.
+ // ...
+ logNotice( "adding control port event handler");
+
+ conn.setEventHandler(mEventHandler);
+
+
+ conn.setEvents(Arrays.asList(new String[]{
+ "ORCONN", "CIRC", "NOTICE", "WARN", "ERR","BW"}));
+ // conn.setEvents(Arrays.asList(new String[]{
+ // "DEBUG", "INFO", "NOTICE", "WARN", "ERR"}));
+
+ logNotice( "SUCCESS added control port event handler");
+ }
+
+ /**
+ * Returns the port number that the HTTP proxy is running on
+ */
+ public int getHTTPPort() throws RemoteException {
+ return mPortHTTP;
+ }
+
+
+ /**
+ * Returns the port number that the HTTP proxy is running on
+ */
+ public int getSOCKSPort() throws RemoteException {
+ return mPortSOCKS;
+ }
+
+
+
+
+
+
+
+ public void processTransparentProxying() {
+ try{
+ if (Prefs.useRoot())
+ {
+ if (Prefs.useTransparentProxying()){
+ enableTransparentProxy();
+ } else {
+ disableTransparentProxy();
+ }
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ public String getInfo (String key) {
+ try {
+ if(conn !=null){
+ String m = conn.getInfo(key);
+ return m;
+ }
+ }
+ catch(Exception ioe){
+ // Log.e(TAG,"Unable to get Tor information",ioe);
+ logNotice("Unable to get Tor information"+ioe.getMessage());
+ }
+ return null;
+ }
+
+ public String getConfiguration (String name)
+ {
+ try
+ {
+ if (conn != null)
+ {
+ StringBuffer result = new StringBuffer();
+
+ List<ConfigEntry> listCe = conn.getConf(name);
+
+ Iterator<ConfigEntry> itCe = listCe.iterator();
+ ConfigEntry ce = null;
+
+
+
+ while (itCe.hasNext())
+ {
+ ce = itCe.next();
+
+ result.append(ce.key);
+ result.append(' ');
+ result.append(ce.value);
+ result.append('\n');
+ }
+
+ return result.toString();
+ }
+ }
+ catch (Exception ioe)
+ {
+
+ logException("Unable to get Tor configuration: " + ioe.getMessage(),ioe);
+ }
+
+ return null;
+ }
+
+ private final static String RESET_STRING = "=\"\"";
+ /**
+ * Set configuration
+ **/
+ public boolean updateConfiguration (String name, String value, boolean saveToDisk)
+ {
+
+
+ if (configBuffer == null)
+ configBuffer = new ArrayList<String>();
+
+ if (resetBuffer == null)
+ resetBuffer = new ArrayList<String>();
+
+ if (value == null || value.length() == 0)
+ {
+ resetBuffer.add(name + RESET_STRING);
+
+ }
+ else
+ {
+ StringBuffer sbConf = new StringBuffer();
+ sbConf.append(name);
+ sbConf.append(' ');
+ sbConf.append(value);
+
+ configBuffer.add(sbConf.toString());
+ }
+
+ return false;
+ }
+
+ public void setTorNetworkEnabled (final boolean isEnabled)
+ {
+
+
+ //it is possible to not have a connection yet, and someone might try to newnym
+ if (conn != null)
+ {
+ new Thread ()
+ {
+ public void run ()
+ {
+ try {
+
+ conn.setConf("DisableNetwork", isEnabled ? "0" : "1");
+
+ }
+ catch (Exception ioe){
+ debug("error requesting newnym: " + ioe.getLocalizedMessage());
+ }
+ }
+ }.start();
+ }
+
+ }
+
+ public void newIdentity ()
+ {
+ //it is possible to not have a connection yet, and someone might try to newnym
+ if (conn != null)
+ {
+ new Thread ()
+ {
+ public void run ()
+ {
+ try {
+
+ conn.signal("NEWNYM");
+
+ }
+ catch (Exception ioe){
+
+ debug("error requesting newnym: " + ioe.getLocalizedMessage());
+
+ }
+ }
+ }.start();
+ }
+ }
+
+ public boolean saveConfiguration ()
+ {
+ try
+ {
+ if (conn != null)
+ {
+
+ if (resetBuffer != null && resetBuffer.size() > 0)
+ {
+ for (String value : configBuffer)
+ {
+
+ // debug("removing torrc conf: " + value);
+
+
+ }
+
+ // conn.resetConf(resetBuffer);
+ resetBuffer = null;
+ }
+
+ if (configBuffer != null && configBuffer.size() > 0)
+ {
+
+ for (String value : configBuffer)
+ {
+
+ debug("Setting torrc conf: " + value);
+
+
+ }
+
+ conn.setConf(configBuffer);
+
+ configBuffer = null;
+ }
+
+ // Flush the configuration to disk.
+ //this is doing bad things right now NF 22/07/10
+ //conn.saveConf();
+
+ return true;
+ }
+ }
+ catch (Exception ioe)
+ {
+ logException("Unable to update Tor configuration: " + ioe.getMessage(),ioe);
+ }
+
+ return false;
+ }
+
+ protected void sendCallbackBandwidth(long upload, long download, long written, long read) {
+ Intent intent = new Intent(LOCAL_ACTION_BANDWIDTH);
+
+ intent.putExtra("up",upload);
+ intent.putExtra("down",download);
+ intent.putExtra("written",written);
+ intent.putExtra("read",read);
+ intent.putExtra(EXTRA_STATUS, mCurrentStatus);
+
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
+ }
+
+ private void sendCallbackLogMessage (String logMessage)
+ {
+
+ Intent intent = new Intent(LOCAL_ACTION_LOG);
+ // You can also include some extra data.
+ intent.putExtra(LOCAL_EXTRA_LOG, logMessage);
+ intent.putExtra(EXTRA_STATUS, mCurrentStatus);
+
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
+
+ }
+
+ protected void sendCallbackStatus(String currentStatus) {
+ mCurrentStatus = currentStatus;
+ Intent intent = getActionStatusIntent(currentStatus);
+ // send for Orbot internals, using secure local broadcast
+ sendBroadcastOnlyToOrbot(intent);
+ // send for any apps that are interested
+ sendBroadcast(intent);
+ }
+
+ /**
+ * Send a secure broadcast only to Orbot itself
+ * @see {@link ContextWrapper#sendBroadcast(Intent)}
+ * @see {@link LocalBroadcastManager}
+ */
+ private boolean sendBroadcastOnlyToOrbot(Intent intent) {
+ return LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
+ }
+
+ private Intent getActionStatusIntent(String currentStatus) {
+ Intent intent = new Intent(ACTION_STATUS);
+ intent.putExtra(EXTRA_STATUS, currentStatus);
+ return intent;
+ }
+
+ /*
+ * Another way to do this would be to use the Observer pattern by defining the
+ * BroadcastReciever in the Android manifest.
+ */
+ private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ if (mCurrentStatus == STATUS_OFF)
+ return;
+
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+
+ boolean doNetworKSleep = prefs.getBoolean(OrbotConstants.PREF_DISABLE_NETWORK, true);
+
+ final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkInfo netInfo = cm.getActiveNetworkInfo();
+
+ boolean newConnectivityState = false;
+ int newNetType = -1;
+
+ boolean isChanged = false;
+
+ if (netInfo!=null)
+ newNetType = netInfo.getType();
+
+ isChanged = ((mNetworkType != newNetType)&&(mConnectivity != newConnectivityState));
+
+ if(netInfo != null && netInfo.isConnected()) {
+ // WE ARE CONNECTED: DO SOMETHING
+ newConnectivityState = true;
+ }
+ else {
+ // WE ARE NOT: DO SOMETHING ELSE
+ newConnectivityState = false;
+ }
+
+ mNetworkType = newNetType;
+ mConnectivity = newConnectivityState;
+
+ if (doNetworKSleep && mCurrentStatus != STATUS_OFF)
+ {
+ setTorNetworkEnabled (mConnectivity);
+
+ 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);
+
+ }
+ else
+ {
+ logNotice(context.getString(R.string.network_connectivity_is_good_waking_tor_up_));
+ showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
+ }
+
+ try {
+
+ if (mConnectivity)
+ {
+ if (Prefs.useRoot() && Prefs.useTransparentProxying() && Prefs.transProxyNetworkRefresh())
+ {
+
+
+ disableTransparentProxy();
+ enableTransparentProxy();
+
+ }
+ }
+
+ } catch (Exception e) {
+ logException ("error updating state after network restart",e);
+ }
+
+
+ }
+
+
+ }
+ };
+
+ private boolean processSettingsImpl (StringBuffer extraLines) throws IOException
+ {
+ logNotice(getString(R.string.updating_settings_in_tor_service));
+
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+
+ boolean useBridges = Prefs.bridgesEnabled();
+
+ boolean becomeRelay = prefs.getBoolean(OrbotConstants.PREF_OR, false);
+ boolean ReachableAddresses = prefs.getBoolean(OrbotConstants.PREF_REACHABLE_ADDRESSES,false);
+ boolean enableHiddenServices = prefs.getBoolean("pref_hs_enable", false);
+
+ boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false);
+ String entranceNodes = prefs.getString("pref_entrance_nodes", "");
+ String exitNodes = prefs.getString("pref_exit_nodes", "");
+ String excludeNodes = prefs.getString("pref_exclude_nodes", "");
+
+ if (!useBridges)
+ {
+
+ extraLines.append("UseBridges 0").append('\n');
+
+ if (Prefs.useVpn()) //set the proxy here if we aren't using a bridge
+ {
+
+ if (!mIsLollipop)
+ {
+ String proxyType = "socks5";
+ extraLines.append(proxyType + "Proxy" + ' ' + OrbotVpnManager.sSocksProxyLocalhost + ':' + OrbotVpnManager.sSocksProxyServerPort).append('\n');
+ };
+
+ }
+ else
+ {
+ String proxyType = prefs.getString("pref_proxy_type", null);
+ if (proxyType != null && proxyType.length() > 0)
+ {
+ String proxyHost = prefs.getString("pref_proxy_host", null);
+ String proxyPort = prefs.getString("pref_proxy_port", null);
+ String proxyUser = prefs.getString("pref_proxy_username", null);
+ String proxyPass = prefs.getString("pref_proxy_password", null);
+
+ if ((proxyHost != null && proxyHost.length()>0) && (proxyPort != null && proxyPort.length() > 0))
+ {
+ extraLines.append(proxyType + "Proxy" + ' ' + proxyHost + ':' + proxyPort).append('\n');
+
+ if (proxyUser != null && proxyPass != null)
+ {
+ if (proxyType.equalsIgnoreCase("socks5"))
+ {
+ extraLines.append("Socks5ProxyUsername" + ' ' + proxyUser).append('\n');
+ extraLines.append("Socks5ProxyPassword" + ' ' + proxyPass).append('\n');
+ }
+ else
+ extraLines.append(proxyType + "ProxyAuthenticator" + ' ' + proxyUser + ':' + proxyPort).append('\n');
+
+ }
+ else if (proxyPass != null)
+ extraLines.append(proxyType + "ProxyAuthenticator" + ' ' + proxyUser + ':' + proxyPort).append('\n');
+
+
+
+ }
+ }
+ }
+ }
+ else
+ {
+
+
+ extraLines.append("UseBridges 1").append('\n');
+
+ String bridgeList = new String(Prefs.getBridgesList().getBytes("ISO-8859-1"));
+
+ if (bridgeList != null && bridgeList.length() > 1) //longer then 1 = some real values here
+ {
+
+ //check if any PT bridges are needed
+ boolean obfsBridges = bridgeList.contains("obfs3")||bridgeList.contains("obfs4")||bridgeList.contains("scramblesuit");
+
+ if (obfsBridges)
+ {
+ extraLines.append("ClientTransportPlugin obfs3 exec " + fileObfsclient.getCanonicalPath()).append('\n');
+ extraLines.append("ClientTransportPlugin obfs4 exec " + fileObfsclient.getCanonicalPath()).append('\n');
+ extraLines.append("ClientTransportPlugin scramblesuit exec " + fileObfsclient.getCanonicalPath()).append('\n');
+ }
+
+ boolean meekBridges = bridgeList.contains("meek");
+ if (meekBridges)
+ {
+ extraLines.append("ClientTransportPlugin meek_lite exec " + fileObfsclient.getCanonicalPath()).append('\n');
+ }
+
+ String[] bridgeListLines = bridgeList.split("\\r?\\n");
+
+ for (String bridgeConfigLine : bridgeListLines)
+ {
+ if (!TextUtils.isEmpty(bridgeConfigLine))
+ {
+ extraLines.append("Bridge ");
+
+ //bridgeConfigLine = bridgeConfigLine.replace('�', ' ');
+
+ StringTokenizer st = new StringTokenizer (bridgeConfigLine," ");
+ while (st.hasMoreTokens())
+ extraLines.append(st.nextToken()).append(' ');
+
+ extraLines.append("\n");
+
+ }
+
+ }
+
+ }
+ else
+ {
+ //time to do autobridges, aka meek
+
+ debug ("Using meek bridges");
+
+ // String bridgeConfig = "meek exec " + fileMeekclient.getCanonicalPath();
+ String bridgeConfig = "meek_lite exec " + fileObfsclient.getCanonicalPath();
+
+ extraLines.append("ClientTransportPlugin" + ' ' + bridgeConfig).append('\n');
+
+ int meekIdx = 2; //let's use Azure by default
+
+ if (bridgeList != null && bridgeList.length() == 1)
+ {
+ try
+ {
+ meekIdx = Integer.parseInt(bridgeList);
+
+ if (meekIdx+1 > BRIDGES_MEEK.length)
+ throw new Exception("not valid meek idx");
+ }
+ catch (Exception e)
+ {
+ debug("invalid meek type; please enter 0=Google, 1=AWS, 2=Azure");
+ }
+ }
+
+ extraLines.append("Bridge " + BRIDGES_MEEK[meekIdx]).append('\n');
+
+ }
+
+ }
+
+
+ //only apply GeoIP if you need it
+ File fileGeoIP = new File(appBinHome, GEOIP_ASSET_KEY);
+ File fileGeoIP6 = new File(appBinHome, GEOIP6_ASSET_KEY);
+
+ if (fileGeoIP.exists())
+ {
+ extraLines.append("GeoIPFile" + ' ' + fileGeoIP.getCanonicalPath()).append('\n');
+ extraLines.append("GeoIPv6File" + ' ' + fileGeoIP6.getCanonicalPath()).append('\n');
+ }
+
+ if (!TextUtils.isEmpty(entranceNodes))
+ extraLines.append("EntryNodes" + ' ' + entranceNodes).append('\n');
+
+ if (!TextUtils.isEmpty(exitNodes))
+ extraLines.append("ExitNodes" + ' ' + exitNodes).append('\n');
+
+ if (!TextUtils.isEmpty(excludeNodes))
+ extraLines.append("ExcludeNodes" + ' ' + excludeNodes).append('\n');
+
+ extraLines.append("StrictNodes" + ' ' + (enableStrictNodes ? "1" : "0")).append('\n');
+
+ try
+ {
+ if (ReachableAddresses)
+ {
+ String ReachableAddressesPorts =
+ prefs.getString(OrbotConstants.PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443");
+
+ extraLines.append("ReachableAddresses" + ' ' + ReachableAddressesPorts).append('\n');
+
+ }
+
+ }
+ catch (Exception e)
+ {
+ showToolbarNotification (getString(R.string.your_reachableaddresses_settings_caused_an_exception_),ERROR_NOTIFY_ID,R.drawable.ic_stat_notifyerr);
+
+ return false;
+ }
+
+ try
+ {
+ if (becomeRelay && (!useBridges) && (!ReachableAddresses))
+ {
+ int ORPort = Integer.parseInt(prefs.getString(OrbotConstants.PREF_OR_PORT, "9001"));
+ String nickname = prefs.getString(OrbotConstants.PREF_OR_NICKNAME, "Orbot");
+
+ String dnsFile = writeDNSFile ();
+
+ extraLines.append("ServerDNSResolvConfFile" + ' ' + dnsFile).append('\n');
+ extraLines.append("ORPort" + ' ' + ORPort).append('\n');
+ extraLines.append("Nickname" + ' ' + nickname).append('\n');
+ extraLines.append("ExitPolicy" + ' ' + "reject *:*").append('\n');
+
+ }
+ }
+ catch (Exception e)
+ {
+ showToolbarNotification (getString(R.string.your_relay_settings_caused_an_exception_),ERROR_NOTIFY_ID,R.drawable.ic_stat_notifyerr);
+
+
+ return false;
+ }
+
+ if (enableHiddenServices)
+ {
+ logNotice("hidden services are enabled");
+
+ //updateConfiguration("RendPostPeriod", "600 seconds", false); //possible feature to investigate
+
+ String hsPorts = prefs.getString("pref_hs_ports","");
+
+ StringTokenizer st = new StringTokenizer (hsPorts,",");
+ String hsPortConfig = null;
+ int hsPort = -1;
+
+ while (st.hasMoreTokens())
+ {
+ try
+ {
+ hsPortConfig = st.nextToken().trim();
+
+ if (hsPortConfig.indexOf(":")==-1) //setup the port to localhost if not specifed
+ {
+ hsPortConfig = hsPortConfig + " 127.0.0.1:" + hsPortConfig;
+ }
+
+ hsPort = Integer.parseInt(hsPortConfig.split(" ")[0]);
+
+ String hsDirPath = new File(appCacheHome,"hs" + hsPort).getCanonicalPath();
+
+ debug("Adding hidden service on port: " + hsPortConfig);
+
+ extraLines.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n');
+ extraLines.append("HiddenServicePort" + ' ' + hsPortConfig).append('\n');
+
+
+ } catch (NumberFormatException e) {
+ Log.e(OrbotConstants.TAG,"error parsing hsport",e);
+ } catch (Exception e) {
+ Log.e(OrbotConstants.TAG,"error starting share server",e);
+ }
+ }
+
+
+ }
+
+ return true;
+ }
+
+ public static String flattenToAscii(String string) {
+ char[] out = new char[string.length()];
+ string = Normalizer.normalize(string, Normalizer.Form.NFD);
+ int j = 0;
+ for (int i = 0, n = string.length(); i < n; ++i) {
+ char c = string.charAt(i);
+ if (c <= '\u007F') out[j++] = c;
+ }
+ return new String(out);
+ }
+
+ //using Google DNS for now as the public DNS server
+ private String writeDNSFile () throws IOException
+ {
+ File file = new File(appBinHome, "resolv.conf");
+
+ PrintWriter bw = new PrintWriter(new FileWriter(file));
+ bw.println("nameserver 8.8.8.8");
+ bw.println("nameserver 8.8.4.4");
+ bw.close();
+
+ return file.getCanonicalPath();
+ }
+
+ @SuppressLint("NewApi")
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+
+ switch (level)
+ {
+
+ case TRIM_MEMORY_BACKGROUND:
+ debug("trim memory requested: app in the background");
+ return;
+
+ /**
+ public static final int TRIM_MEMORY_BACKGROUND
+ Added in API level 14
+ Level for onTrimMemory(int): the process has gone on to the LRU list. This is a good opportunity to clean up resources that can efficiently and quickly be re-built if the user returns to the app.
+ Constant Value: 40 (0x00000028)
+ */
+
+ case TRIM_MEMORY_COMPLETE:
+
+ debug("trim memory requested: cleanup all memory");
+ return;
+ /**
+ public static final int TRIM_MEMORY_COMPLETE
+ Added in API level 14
+ Level for onTrimMemory(int): the process is nearing the end of the background LRU list, and if more memory isn't found soon it will be killed.
+ Constant Value: 80 (0x00000050)
+ */
+ case TRIM_MEMORY_MODERATE:
+
+ debug("trim memory requested: clean up some memory");
+ return;
+
+ /**
+ public static final int TRIM_MEMORY_MODERATE
+ Added in API level 14
+ Level for onTrimMemory(int): the process is around the middle of the background LRU list; freeing memory can help the system keep other processes running later in the list for better overall performance.
+ Constant Value: 60 (0x0000003c)
+ */
+
+ case TRIM_MEMORY_RUNNING_CRITICAL:
+
+ debug("trim memory requested: memory on device is very low and critical");
+ return;
+ /**
+ public static final int TRIM_MEMORY_RUNNING_CRITICAL
+ Added in API level 16
+ Level for onTrimMemory(int): the process is not an expendable background process, but the device is running extremely low on memory and is about to not be able to keep any background processes running. Your running process should free up as many non-critical resources as it can to allow that memory to be used elsewhere. The next thing that will happen after this is onLowMemory() called to report that nothing at all can be kept in the background, a situation that can start to notably impact the user.
+ Constant Value: 15 (0x0000000f)
+ */
+
+ case TRIM_MEMORY_RUNNING_LOW:
+
+ debug("trim memory requested: memory on device is running low");
+ return;
+ /**
+ public static final int TRIM_MEMORY_RUNNING_LOW
+ Added in API level 16
+ Level for onTrimMemory(int): the process is not an expendable background process, but the device is running low on memory. Your running process should free up unneeded resources to allow that memory to be used elsewhere.
+ Constant Value: 10 (0x0000000a)
+ */
+ case TRIM_MEMORY_RUNNING_MODERATE:
+
+ debug("trim memory requested: memory on device is moderate");
+ return;
+ /**
+ public static final int TRIM_MEMORY_RUNNING_MODERATE
+ Added in API level 16
+ Level for onTrimMemory(int): the process is not an expendable background process, but the device is running moderately low on memory. Your running process may want to release some unneeded resources for use elsewhere.
+ Constant Value: 5 (0x00000005)
+ */
+ case TRIM_MEMORY_UI_HIDDEN:
+
+ debug("trim memory requested: app is not showing UI anymore");
+ return;
+
+ /**
+ public static final int TRIM_MEMORY_UI_HIDDEN
+ Level for onTrimMemory(int): the process had been showing a user interface, and is no longer doing so. Large allocations with the UI should be released at this point to allow memory to be better managed.
+ Constant Value: 20 (0x00000014)
+ */
+ }
+
+ }
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private void setExitNode (String newExits)
+ {
+ SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
+
+ if (TextUtils.isEmpty(newExits))
+ {
+ prefs.edit().remove("pref_exit_nodes").apply();
+
+ if (conn != null)
+ {
+ try
+ {
+ ArrayList<String> resetBuffer = new ArrayList<String>();
+ resetBuffer.add("ExitNodes");
+ resetBuffer.add("StrictNodes");
+ conn.resetConf(resetBuffer);
+ conn.setConf("DisableNetwork","1");
+ conn.setConf("DisableNetwork","0");
+
+ }
+ catch (Exception ioe)
+ {
+ Log.e(OrbotConstants.TAG, "Connection exception occured resetting exits",ioe);
+ }
+ }
+ }
+ else
+ {
+ prefs.edit().putString("pref_exit_nodes", newExits).apply();
+
+ if (conn != null)
+ {
+ try
+ {
+ File fileGeoIP = new File(appBinHome, GEOIP_ASSET_KEY);
+ File fileGeoIP6 = new File(appBinHome, GEOIP6_ASSET_KEY);
+
+ conn.setConf("GeoIPFile",fileGeoIP.getCanonicalPath());
+ conn.setConf("GeoIPv6File",fileGeoIP6.getCanonicalPath());
+
+ conn.setConf("ExitNodes", newExits);
+ conn.setConf("StrictNodes","1");
+
+ conn.setConf("DisableNetwork","1");
+ conn.setConf("DisableNetwork","0");
+
+ }
+ catch (Exception ioe)
+ {
+ Log.e(OrbotConstants.TAG, "Connection exception occured resetting exits",ioe);
+ }
+ }
+ }
+
+ }
+
+ public boolean hasConnectivity ()
+ {
+ return mConnectivity;
+ }
+
+ public int getNotifyId ()
+ {
+ return NOTIFY_ID;
+ }
+
+ private void startVPNService ()
+ {
+ Intent intentVpn = new Intent(this,TorVpnService.class);
+ intentVpn.setAction("start");
+ intentVpn.putExtra("torSocks",mPortSOCKS);
+ startService(intentVpn);
+ }
+
+
+ @TargetApi(14)
+ public void clearVpnProxy ()
+ {
+ debug ("clearing VPN Proxy");
+ Prefs.putUseVpn(false);
+ processTransparentProxying();
+
+ Intent intentVpn = new Intent(this,TorVpnService.class);
+ intentVpn.setAction("stop");
+ startService(intentVpn);
+
+ }
+
+}
diff --cc orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
index 00ade29,0000000..d38d910
mode 100644,000000..100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorServiceConstants.java
@@@ -1,162 -1,0 +1,164 @@@
+/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
+/* See LICENSE for licensing information */
+
+package org.torproject.android.service;
+
+import android.content.Intent;
+
+public interface TorServiceConstants {
+
+ public final static String TOR_APP_USERNAME = "org.torproject.android";
+ public final static String BROWSER_APP_USERNAME = "info.guardianproject.orfox";
+
+ public final static String DIRECTORY_TOR_BINARY = "bin";
+ public final static String DIRECTORY_TOR_DATA = "data";
+
+ //name of the tor C binary
+ public final static String TOR_ASSET_KEY = "tor";
+
+ //torrc (tor config file)
+ public final static String TORRC_ASSET_KEY = "torrc";
+ public final static String TORRCDIAG_ASSET_KEY = "torrcdiag";
+ public final static String TORRC_TETHER_KEY = "torrctether";
+
+ public final static String TOR_CONTROL_COOKIE = "control_auth_cookie";
+
+ //privoxy
+ public final static String POLIPO_ASSET_KEY = "polipo";
+
+ //privoxy.config
+ public final static String POLIPOCONFIG_ASSET_KEY = "torpolipo.conf";
+
+ //geoip data file asset key
+ public final static String GEOIP_ASSET_KEY = "geoip";
+ public final static String GEOIP6_ASSET_KEY = "geoip6";
+
+ //various console cmds
+ public final static String SHELL_CMD_CHMOD = "chmod";
+ public final static String SHELL_CMD_KILL = "kill -9";
+ public final static String SHELL_CMD_RM = "rm";
+ public final static String SHELL_CMD_PS = "toolbox ps";
+ public final static String SHELL_CMD_PS_ALT = "ps";
+
+
+ //public final static String SHELL_CMD_PIDOF = "pidof";
+ public final static String SHELL_CMD_LINK = "ln -s";
+ public final static String SHELL_CMD_CP = "cp";
+
+
+ public final static String CHMOD_EXE_VALUE = "770";
+
+ public final static int FILE_WRITE_BUFFER_SIZE = 1024;
+
+ public final static String IP_LOCALHOST = "127.0.0.1";
+ public final static int UPDATE_TIMEOUT = 1000;
+ public final static int TOR_TRANSPROXY_PORT_DEFAULT = 9040;
+
+ public final static int STANDARD_DNS_PORT = 53;
+ public final static int TOR_DNS_PORT_DEFAULT = 5400;
+ public final static String TOR_VPN_DNS_LISTEN_ADDRESS = "127.0.0.1";
+
+ public final static int CONTROL_PORT_DEFAULT = 9051;
+ public final static int HTTP_PROXY_PORT_DEFAULT = 8118; // like Privoxy!
+ public final static int SOCKS_PROXY_PORT_DEFAULT = 9050;
+
+
+ //path to check Tor against
+ public final static String URL_TOR_CHECK = "https://check.torproject.org";
+
+ //control port
+ public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%";
+ public final static String LOG_NOTICE_HEADER = "NOTICE";
+ public final static String LOG_NOTICE_BOOTSTRAPPED = "Bootstrapped";
+
+ /**
+ * A request to Orbot to transparently start Tor services
+ */
+ public final static String ACTION_START = "org.torproject.android.intent.action.START";
+ /**
+ * {@link Intent} send by Orbot with {@code ON/OFF/STARTING/STOPPING} status
+ */
+ public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS";
+ /**
+ * {@code String} that contains a status constant: {@link #STATUS_ON},
+ * {@link #STATUS_OFF}, {@link #STATUS_STARTING}, or
+ * {@link #STATUS_STOPPING}
+ */
+ public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS";
+ /**
+ * A {@link String} {@code packageName} for Orbot to direct its status reply
+ * to, used in {@link #ACTION_START} {@link Intent}s sent to Orbot
+ */
+ public final static String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME";
+ /**
+ * The SOCKS proxy settings in URL form.
+ */
+ public final static String EXTRA_SOCKS_PROXY = "org.torproject.android.intent.extra.SOCKS_PROXY";
+ public final static String EXTRA_SOCKS_PROXY_HOST = "org.torproject.android.intent.extra.SOCKS_PROXY_HOST";
+ public final static String EXTRA_SOCKS_PROXY_PORT = "org.torproject.android.intent.extra.SOCKS_PROXY_PORT";
+ /**
+ * The HTTP proxy settings in URL form.
+ */
+ public final static String EXTRA_HTTP_PROXY = "org.torproject.android.intent.extra.HTTP_PROXY";
+ public final static String EXTRA_HTTP_PROXY_HOST = "org.torproject.android.intent.extra.HTTP_PROXY_HOST";
+ public final static String EXTRA_HTTP_PROXY_PORT = "org.torproject.android.intent.extra.HTTP_PROXY_PORT";
+
+ public final static String LOCAL_ACTION_LOG = "log";
+ public final static String LOCAL_ACTION_BANDWIDTH = "bandwidth";
+ public final static String LOCAL_EXTRA_LOG = "log";
+
+ /**
+ * All tor-related services and daemons are stopped
+ */
+ public final static String STATUS_OFF = "OFF";
+ /**
+ * All tor-related services and daemons have completed starting
+ */
+ public final static String STATUS_ON = "ON";
+ public final static String STATUS_STARTING = "STARTING";
+ public final static String STATUS_STOPPING = "STOPPING";
++
+ /**
+ * The user has disabled the ability for background starts triggered by
- * apps. Fallback to the old Intent that brings up Orbot.
++ * apps. Fallback to the old {@link Intent} action that brings up Orbot:
++ * {@link org.torproject.android.OrbotMainActivity#INTENT_ACTION_REQUEST_START_TOR}
+ */
+ public final static String STATUS_STARTS_DISABLED = "STARTS_DISABLED";
+
+ // actions for internal command Intents
+ public static final String CMD_SIGNAL_HUP = "signal_hup";
+ public static final String CMD_STATUS = "status";
+ public static final String CMD_FLUSH = "flush";
+ public static final String CMD_NEWNYM = "newnym";
+ public static final String CMD_VPN = "vpn";
+ public static final String CMD_VPN_CLEAR = "vpnclear";
+ public static final String CMD_UPDATE_TRANS_PROXY = "update";
+ public static final String CMD_SET_EXIT = "setexit";
+
+
+ public static final String BINARY_TOR_VERSION = "0.2.8.9armx86-openssl1.0.2j";
+ public static final String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
+
+ //obfsproxy
+ public static final String OBFSCLIENT_ASSET_KEY = "obfs4proxy";
+
+ // public static final String MEEK_ASSET_KEY = "meek-client";
+
+ //name of the iptables binary
+ public final static String IPTABLES_ASSET_KEY = "xtables";
+
+ //DNS daemon for TCP DNS over TOr
+ public final static String PDNSD_ASSET_KEY = "pdnsd";
+
+ //EXIT COUNTRY CODES
+ public final static String[] COUNTRY_CODES = {"DE","AT","SE","CH","IS","CA","US","ES","FR","BG","PL","AU","BR","CZ","DK","FI","GB","HU","NL","JP","RO","RU","SG","SK"};
+
+ //MEEK BRIDGEs
+ public final static String[] BRIDGES_MEEK =
+ {
+ "meek_lite 0.0.2.0:1 url=https://meek-reflect.appspot.com/ front=www.google.com",
+ "meek_lite 0.0.2.0:2 url=https://d2zfqthxsdq309.cloudfront.net/ front=a0.awsstatic.com",
+ "meek_lite 0.0.2.0:3 url=https://az668014.vo.msecnd.net/ front=ajax.aspnetcdn.com"
+ };
+
+}
1
0
commit f3af9daa55aaafc63989046b549964d623bb08a2
Author: arrase <arrase(a)gmail.com>
Date: Tue Dec 6 00:52:24 2016 +0100
fix: focusable
---
.../android/ui/hiddenservices/adapters/OnionListAdapter.java | 1 +
app/src/main/res/layout/layout_hs_list_item.xml | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
index b9f750a..9824c77 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
@@ -38,6 +38,7 @@ public class OnionListAdapter extends CursorAdapter {
name.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.NAME)));
TextView domain = (TextView) view.findViewById(R.id.hs_onion);
domain.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.DOMAIN)));
+
Switch enabled = (Switch) view.findViewById(R.id.hs_switch);
enabled.setChecked(
cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService.ENABLED)) == 1
diff --git a/app/src/main/res/layout/layout_hs_list_item.xml b/app/src/main/res/layout/layout_hs_list_item.xml
index c8878b0..44e6057 100644
--- a/app/src/main/res/layout/layout_hs_list_item.xml
+++ b/app/src/main/res/layout/layout_hs_list_item.xml
@@ -49,7 +49,9 @@
<Switch
android:id="@+id/hs_switch"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:focusableInTouchMode="false" />
</LinearLayout>
1
0
commit 2d0437a834449b4b4069933bad65f63471f9ac3a
Author: arrase <arrase(a)gmail.com>
Date: Sun Dec 4 22:12:41 2016 +0100
return auth cookie at intent service
---
app/src/main/java/org/torproject/android/OrbotMainActivity.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 07d0199..caed0c3 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -675,6 +675,13 @@ public class OrbotMainActivity extends AppCompatActivity
nResult.putExtra("hs_host", hostname);
+ if (authCookie) {
+ nResult.putExtra(
+ "hs_auth_cookie",
+ onion.getString(onion.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
+ );
+ }
+
if (backupToPackage != null && backupToPackage.length() > 0) {
String servicePath = getFilesDir() + "/" + TorServiceConstants.HIDDEN_SERVICES_DIR + "/hs" + hsPort;
File hidden_service_key = new File(servicePath, "private_key");
1
0
commit ad68947dd414d4217d7581fcfa987d1421d870fb
Author: arrase <arrase(a)gmail.com>
Date: Thu Dec 8 16:12:29 2016 +0100
fix for bug 63
---
.../java/org/torproject/android/OrbotMainActivity.java | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 551fb6e..062db3d 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -103,9 +103,8 @@ public class OrbotMainActivity extends AppCompatActivity
private ActionBarDrawerToggle mDrawerToggle;
/* Some tracking bits */
- private String torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service
+ private String torStatus = null; //latest status reported from the tor service
private Intent lastStatusIntent; // the last ACTION_STATUS Intent received
- private Boolean isFirstRun = true;
private SharedPreferences mPrefs = null;
@@ -1199,8 +1198,12 @@ public class OrbotMainActivity extends AppCompatActivity
if (resultIntent == null)
resultIntent = new Intent(TorServiceConstants.ACTION_START);
- resultIntent.putExtra(TorServiceConstants.EXTRA_STATUS, torStatus);
- setResult(RESULT_OK, resultIntent);
+ resultIntent.putExtra(
+ TorServiceConstants.EXTRA_STATUS,
+ torStatus == null?TorServiceConstants.STATUS_OFF:torStatus
+ );
+
+ setResult(RESULT_OK, resultIntent);
finish();
Log.d(TAG, "autoStartFromIntent finish");
}
@@ -1301,10 +1304,9 @@ public class OrbotMainActivity extends AppCompatActivity
String newTorStatus = msg.getData().getString("status");
String log = (String)msg.obj;
-
- if (isFirstRun && newTorStatus != null) //first time status
+
+ if (torStatus == null && newTorStatus != null) //first time status
{
- isFirstRun = false;
torStatus = newTorStatus;
findViewById(R.id.frameMain).setVisibility(View.VISIBLE);
updateStatus(log);
1
0