tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- 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
January 2012
- 14 participants
- 852 discussions
commit edcaeee231639b579bc2e1faa70ff6727dc10c95
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Fri Jan 13 19:19:18 2012 -0500
updated version
---
AndroidManifest.xml | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index aefb1d7..1c3e67b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.torproject.android" android:versionName="0.2.3.10-alpha-orbot-1.0.7-RC3" android:versionCode="25">
+ package="org.torproject.android" android:versionName="0.2.3.10-alpha-orbot-1.0.7-RC4" android:versionCode="26">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
1
0

14 Jan '12
commit f14ca9a2d98dce14022b0c92ab428165f07b38d1
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Fri Jan 13 19:19:04 2012 -0500
improved root detect and binary installation
---
src/org/torproject/android/Orbot.java | 2 +-
.../android/service/TorBinaryInstaller.java | 3 --
src/org/torproject/android/service/TorService.java | 34 ++++++++++++-------
3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/src/org/torproject/android/Orbot.java b/src/org/torproject/android/Orbot.java
index 5452a5a..c2a7408 100644
--- a/src/org/torproject/android/Orbot.java
+++ b/src/org/torproject/android/Orbot.java
@@ -72,7 +72,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
//if Tor binary is not running, then start the service up
//might want to look at whether we need to call this every time
//or whether binding to the service is enough
- startService(new Intent(INTENT_TOR_SERVICE));
+ startService(new Intent(INTENT_TOR_SERVICE));
//something to play with on the UI branch
setTheme(android.R.style.Theme_Black_NoTitleBar);
diff --git a/src/org/torproject/android/service/TorBinaryInstaller.java b/src/org/torproject/android/service/TorBinaryInstaller.java
index 93325db..9a56004 100644
--- a/src/org/torproject/android/service/TorBinaryInstaller.java
+++ b/src/org/torproject/android/service/TorBinaryInstaller.java
@@ -249,9 +249,6 @@ public class TorBinaryInstaller implements TorServiceConstants {
}
*/
- if (changed) {
- Toast.makeText(ctx, R.string.status_install_success, Toast.LENGTH_LONG).show();
- }
return true;
}
diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java
index 50ddb01..2d1698a 100644
--- a/src/org/torproject/android/service/TorService.java
+++ b/src/org/torproject/android/service/TorService.java
@@ -206,23 +206,32 @@ public class TorService extends Service implements TorServiceConstants, TorConst
Log.i(TAG, "service started: " + intent.getAction());
- try {
- checkTorBinaries (false);
- } catch (Exception e) {
-
- logNotice("unable to find tor binaries: " + e.getMessage());
- showToolbarNotification(getString(R.string.error_installing_binares), NOTIFY_ID, R.drawable.tornotificationerr);
-
- Log.e(TAG, "error checking tor binaries", e);
- }
+
+ Thread thread = new Thread ()
+ {
+
+ public void run ()
+ {
+ try {
+ checkTorBinaries (false);
+ } catch (Exception e) {
+
+ logNotice("unable to find tor binaries: " + e.getMessage());
+ showToolbarNotification(getString(R.string.error_installing_binares), NOTIFY_ID, R.drawable.tornotificationerr);
+
+ Log.e(TAG, "error checking tor binaries", e);
+ }
+ }
+ };
+
+ thread.start();
if (intent.getAction()!=null && intent.getAction().equals("onboot"))
{
-
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- boolean startOnBoot = prefs.getBoolean("pref_start_boot",true);
+ boolean startOnBoot = prefs.getBoolean("pref_start_boot",false);
if (startOnBoot)
{
@@ -474,8 +483,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
logNotice(getString(R.string.status_install_success));
- showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification);
-
+ //showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification);
torBinaryPath = fileTor.getAbsolutePath();
privoxyPath = filePrivoxy.getAbsolutePath();
1
0

13 Jan '12
commit 4a0e1a755e43802340020b663f6982536bd57ecf
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Jan 13 08:46:19 2012 -0800
Skipping integ that need ptrace when inaccessable
When the tor connection is inaccessable I'm skipping the system integ tests
that need ptrace support, since we can't check if it's enabled or not.
---
test/integ/util/system.py | 24 ++++++++++++++++--------
test/runner.py | 6 +++---
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/test/integ/util/system.py b/test/integ/util/system.py
index 70d73ae..e06c05b 100644
--- a/test/integ/util/system.py
+++ b/test/integ/util/system.py
@@ -135,7 +135,9 @@ class TestSystem(unittest.TestCase):
self.skipTest("(multiple tor instances)")
elif not stem.util.system.is_available("lsof"):
self.skipTest("(lsof unavailable)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_accessible():
+ self.skipTest("(unable to check for DisableDebuggerAttachment)")
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
lsof_prefix = stem.util.system.GET_PID_BY_NAME_LSOF % ""
@@ -149,7 +151,7 @@ class TestSystem(unittest.TestCase):
runner = test.runner.get_runner()
if not self._has_port():
self.skipTest("(test instance has no port)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
tor_pid, tor_port = runner.get_pid(), test.runner.CONTROL_PORT
@@ -168,7 +170,7 @@ class TestSystem(unittest.TestCase):
self.skipTest("(netstat unavailable)")
elif stem.util.system.is_bsd():
self.skipTest("(linux only)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
netstat_cmd = stem.util.system.GET_PID_BY_PORT_NETSTAT
@@ -186,7 +188,7 @@ class TestSystem(unittest.TestCase):
self.skipTest("(sockstat unavailable)")
elif not stem.util.system.is_bsd():
self.skipTest("(bsd only)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
sockstat_prefix = stem.util.system.GET_PID_BY_PORT_SOCKSTAT % ""
@@ -202,7 +204,7 @@ class TestSystem(unittest.TestCase):
self.skipTest("(test instance has no port)")
elif not stem.util.system.is_available("lsof"):
self.skipTest("(lsof unavailable)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
lsof_cmd = stem.util.system.GET_PID_BY_PORT_LSOF
@@ -229,7 +231,9 @@ class TestSystem(unittest.TestCase):
runner = test.runner.get_runner()
- if runner.is_debugging_prevented():
+ if not runner.is_accessible():
+ self.skipTest("(unable to check for DisableDebuggerAttachment)")
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
self.assertEquals(runner.get_tor_cwd(), stem.util.system.get_cwd(runner.get_pid()))
@@ -243,7 +247,9 @@ class TestSystem(unittest.TestCase):
runner = test.runner.get_runner()
if not stem.util.system.is_available("pwdx"):
self.skipTest("(pwdx unavailable)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_accessible():
+ self.skipTest("(unable to check for DisableDebuggerAttachment)")
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
# filter the call function to only allow this command
@@ -261,7 +267,9 @@ class TestSystem(unittest.TestCase):
runner = test.runner.get_runner()
if not stem.util.system.is_available("lsof"):
self.skipTest("(lsof unavailable)")
- elif runner.is_debugging_prevented():
+ elif not runner.is_accessible():
+ self.skipTest("(unable to check for DisableDebuggerAttachment)")
+ elif not runner.is_ptraceable():
self.skipTest("(DisableDebuggerAttachment is set)")
# filter the call function to only allow this command
diff --git a/test/runner.py b/test/runner.py
index 5841154..36c41ce 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -11,7 +11,7 @@ Runner - Runtime context for our integration tests.
|- stop - stops our tor instance and cleans up any temporary files
|- is_running - checks if our tor test instance is running
|- is_accessible - checks if our tor instance can be connected to
- |- is_debugging_prevented - checks if DisableDebuggerAttachment is set
+ |- is_ptraceable - checks if DisableDebuggerAttachment is set
|- get_test_dir - testing directory path
|- get_torrc_path - path to our tor instance's torrc
|- get_torrc_contents - contents of our tor instance's torrc
@@ -273,7 +273,7 @@ class Runner:
conn_opts = self.get_connection_options()
return OPT_PORT in conn_opts or OPT_SOCKET in conn_opts
- def is_debugging_prevented(self):
+ def is_ptraceable(self):
"""
Checks if tor's 'DisableDebuggerAttachment' option is set. This feature has
a lot of adverse side effects as per...
@@ -292,7 +292,7 @@ class Runner:
getconf_response = control_socket.recv()
control_socket.close()
- return str(getconf_response) == "DisableDebuggerAttachment=1"
+ return str(getconf_response) != "DisableDebuggerAttachment=1"
def get_test_dir(self):
"""
1
0
commit 19491fb8a411a5737ca438b9dc943a13f8eb44b8
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Jan 13 09:15:49 2012 -0800
Integ target for running with ptrace
Integraion target that runs with 'DisableDebuggerAttachment 0'. This allows us
to exercise use cases that require ptrace with newer tor versions. If
'DisableDebuggerAttachment' isn't supported then we skip the target.
---
run_tests.py | 13 ++++++++++++-
stem/version.py | 1 +
test/integ/connection/protocolinfo.py | 2 ++
test/runner.py | 4 +++-
test/testrc.sample | 5 ++++-
5 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index f458a80..64bde44 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -62,7 +62,7 @@ INTEG_TESTS = (
)
# Integration tests above the basic suite.
-TARGETS = stem.util.enum.Enum(*[(v, v) for v in ("ONLINE", "RELATIVE", "CONN_NONE", "CONN_OPEN", "CONN_PASSWORD", "CONN_COOKIE", "CONN_MULTIPLE", "CONN_SOCKET", "CONN_SCOOKIE", "CONN_ALL")])
+TARGETS = stem.util.enum.Enum(*[(v, v) for v in ("ONLINE", "RELATIVE", "CONN_NONE", "CONN_OPEN", "CONN_PASSWORD", "CONN_COOKIE", "CONN_MULTIPLE", "CONN_SOCKET", "CONN_SCOOKIE", "CONN_PTRACE", "CONN_ALL")])
TARGET_ATTR = {
TARGETS.ONLINE: ("test.integ.target.online", "Includes tests that require network activity."),
@@ -74,6 +74,7 @@ TARGET_ATTR = {
TARGETS.CONN_MULTIPLE: ("test.integ.target.connection.multiple", "Configuration with both password and cookie authentication."),
TARGETS.CONN_SOCKET: ("test.integ.target.connection.socket", "Configuration with a control socket."),
TARGETS.CONN_SCOOKIE: ("test.integ.target.connection.scookie", "Configuration with a control socket and authentication cookie."),
+ TARGETS.CONN_PTRACE: ("test.integ.target.connection.ptrace", "Configuration with an open control port and 'DisableDebuggerAttachment 0'"),
TARGETS.CONN_ALL: ("test.integ.target.connection.all", "Runs integration tests for all connection configurations."),
}
@@ -256,6 +257,7 @@ if __name__ == '__main__':
"multiple": test.runner.TorConnection.MULTIPLE,
"socket": test.runner.TorConnection.SOCKET,
"scookie": test.runner.TorConnection.SCOOKIE,
+ "ptrace": test.runner.TorConnection.PTRACE,
}
for type_key in conn_type_mappings:
@@ -267,6 +269,15 @@ if __name__ == '__main__':
connection_types = [test.runner.TorConnection.OPEN]
for connection_type in connection_types:
+ if connection_type == test.runner.TorConnection.PTRACE:
+ our_version = stem.version.get_system_tor_version(tor_cmd)
+ req_version = stem.version.Requirement.DISABLE_DEBUGGER_ATTACHMENT
+
+ if our_version < req_version:
+ print term.format("Unable to run CONN_PTRACE target: DisableDebuggerAttachment was added in %s" % req_version, term.Color.RED, term.Attr.BOLD)
+ print
+ continue
+
try:
integ_runner.start(tor_cmd, connection_type = connection_type)
diff --git a/stem/version.py b/stem/version.py
index 0b57301..e5b9997 100644
--- a/stem/version.py
+++ b/stem/version.py
@@ -143,5 +143,6 @@ class Version:
Requirement = stem.util.enum.Enum(
("GETINFO_CONFIG_TEXT", Version("0.2.2.7-alpha")),
("CONTROL_SOCKET", Version("0.2.0.30")),
+ ("DISABLE_DEBUGGER_ATTACHMENT", Version("0.2.3.9")),
)
diff --git a/test/integ/connection/protocolinfo.py b/test/integ/connection/protocolinfo.py
index 6f036c8..0214534 100644
--- a/test/integ/connection/protocolinfo.py
+++ b/test/integ/connection/protocolinfo.py
@@ -161,6 +161,8 @@ class TestProtocolInfo(unittest.TestCase):
auth_methods = (stem.connection.AuthMethod.NONE,)
elif connection_type == test.runner.TorConnection.SCOOKIE:
auth_methods = (stem.connection.AuthMethod.COOKIE,)
+ elif connection_type == test.runner.TorConnection.PTRACE:
+ auth_methods = (stem.connection.AuthMethod.NONE,)
else:
self.fail("Unrecognized connection type: %s" % connection_type)
diff --git a/test/runner.py b/test/runner.py
index 36c41ce..4d163bf 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -50,7 +50,7 @@ DEFAULT_CONFIG = {
# Methods for connecting to tor. General integration tests only run with the
# DEFAULT_TOR_CONNECTION, but expanded integ tests will run with all of them.
-TorConnection = stem.util.enum.Enum("NONE", "OPEN", "PASSWORD", "COOKIE", "MULTIPLE", "SOCKET", "SCOOKIE")
+TorConnection = stem.util.enum.Enum("NONE", "OPEN", "PASSWORD", "COOKIE", "MULTIPLE", "SOCKET", "SCOOKIE", "PTRACE")
DEFAULT_TOR_CONNECTION = TorConnection.OPEN
STATUS_ATTR = (term.Color.BLUE, term.Attr.BOLD)
@@ -78,6 +78,7 @@ OPT_PORT = "ControlPort %i" % CONTROL_PORT
OPT_COOKIE = "CookieAuthentication 1"
OPT_PASSWORD = "HashedControlPassword 16:8C423A41EF4A542C6078985270AE28A4E04D056FB63F9F201505DB8E06"
OPT_SOCKET = "ControlSocket %s" % CONTROL_SOCKET_PATH
+OPT_PTRACE = "DisableDebuggerAttachment 0"
# mapping of TorConnection to their options
@@ -89,6 +90,7 @@ CONNECTION_OPTS = {
TorConnection.MULTIPLE: [OPT_PORT, OPT_PASSWORD, OPT_COOKIE],
TorConnection.SOCKET: [OPT_SOCKET],
TorConnection.SCOOKIE: [OPT_SOCKET, OPT_COOKIE],
+ TorConnection.PTRACE: [OPT_PORT, OPT_PTRACE],
}
def get_runner():
diff --git a/test/testrc.sample b/test/testrc.sample
index f0b917d..d5a9326 100644
--- a/test/testrc.sample
+++ b/test/testrc.sample
@@ -23,8 +23,10 @@
# test.integ.target.connection.open
# test.integ.target.connection.password
# test.integ.target.connection.cookie
-# test.integ.target.connection.muiltipe
+# test.integ.target.connection.multiple
# test.integ.target.connection.socket
+# test.integ.target.connection.scookie
+# test.integ.target.connection.ptrace
# test.integ.target.connection.all
# Runs the integration test suite for all of the given connection and
# authentication configurations. If the 'all' option is set then the other
@@ -41,5 +43,6 @@ test.integ.target.connection.cookie false
test.integ.target.connection.muiltipe false
test.integ.target.connection.socket false
test.integ.target.connection.scookie false
+test.integ.target.connection.ptrace false
test.integ.target.connection.all false
1
0

13 Jan '12
commit 0071fadd8b69eda81cdd9826719037fafdebbb74
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Jan 13 08:28:32 2012 -0800
Making explicit checks for tor accessibility
Several 'test/runner.py' functions query against our tor instance. However, in
some integ tests we don't have any method for doing that. Rather than returning
a default value I'm raising in those cases, and adding an is_accessible method
to make our tests more readable.
---
test/integ/socket/control_message.py | 30 +++++++++--------
test/runner.py | 57 +++++++++++++++++++++++++---------
2 files changed, 58 insertions(+), 29 deletions(-)
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index d0c44dc..33a54bf 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -20,13 +20,14 @@ class TestControlMessage(unittest.TestCase):
Checks message parsing when we have a valid but unauthenticated socket.
"""
- control_socket = test.runner.get_runner().get_tor_socket(False)
- if not control_socket: self.skipTest("(no control socket)")
+ runner = test.runner.get_runner()
+ if not runner.is_accessible(): self.skipTest("(no control socket)")
# If an unauthenticated connection gets a message besides AUTHENTICATE or
# PROTOCOLINFO then tor will give an 'Authentication required.' message and
# hang up.
+ control_socket = runner.get_tor_socket(False)
control_socket.send("GETINFO version")
auth_required_response = control_socket.recv()
@@ -66,8 +67,9 @@ class TestControlMessage(unittest.TestCase):
Parses the response for a command which doesn't exist.
"""
- control_socket = test.runner.get_runner().get_tor_socket()
- if not control_socket: self.skipTest("(no control socket)")
+ runner = test.runner.get_runner()
+ if not runner.is_accessible(): self.skipTest("(no control socket)")
+ control_socket = runner.get_tor_socket()
control_socket.send("blarg")
unrecognized_command_response = control_socket.recv()
@@ -83,8 +85,9 @@ class TestControlMessage(unittest.TestCase):
Parses the response for a GETINFO query which doesn't exist.
"""
- control_socket = test.runner.get_runner().get_tor_socket()
- if not control_socket: self.skipTest("(no control socket)")
+ runner = test.runner.get_runner()
+ if not runner.is_accessible(): self.skipTest("(no control socket)")
+ control_socket = runner.get_tor_socket()
control_socket.send("GETINFO blarg")
unrecognized_key_response = control_socket.recv()
@@ -102,9 +105,8 @@ class TestControlMessage(unittest.TestCase):
runner = test.runner.get_runner()
torrc_dst = runner.get_torrc_path()
-
+ if not runner.is_accessible(): self.skipTest("(no control socket)")
control_socket = runner.get_tor_socket()
- if not control_socket: self.skipTest("(no control socket)")
control_socket.send("GETINFO config-file")
config_file_response = control_socket.recv()
@@ -122,9 +124,10 @@ class TestControlMessage(unittest.TestCase):
runner = test.runner.get_runner()
req_version = stem.version.Requirement.GETINFO_CONFIG_TEXT
- our_version = runner.get_tor_version()
- if our_version and our_version < req_version:
+ if not runner.is_accessible():
+ self.skipTest("(no control socket)")
+ elif runner.get_tor_version() < req_version:
self.skipTest("(requires %s)" % req_version)
# We can't be certain of the order, and there may be extra config-text
@@ -142,8 +145,6 @@ class TestControlMessage(unittest.TestCase):
torrc_contents.append(line)
control_socket = runner.get_tor_socket()
- if not control_socket: self.skipTest("(no control socket)")
-
control_socket.send("GETINFO config-text")
config_text_response = control_socket.recv()
@@ -169,8 +170,9 @@ class TestControlMessage(unittest.TestCase):
Issues 'SETEVENTS BW' and parses a few events.
"""
- control_socket = test.runner.get_runner().get_tor_socket()
- if not control_socket: self.skipTest("(no control socket)")
+ runner = test.runner.get_runner()
+ if not runner.is_accessible(): self.skipTest("(no control socket)")
+ control_socket = runner.get_tor_socket()
control_socket.send("SETEVENTS BW")
setevents_response = control_socket.recv()
diff --git a/test/runner.py b/test/runner.py
index d5f4a91..5841154 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -10,11 +10,13 @@ Runner - Runtime context for our integration tests.
|- start - prepares and starts a tor instance for our tests to run against
|- stop - stops our tor instance and cleans up any temporary files
|- is_running - checks if our tor test instance is running
+ |- is_accessible - checks if our tor instance can be connected to
|- is_debugging_prevented - checks if DisableDebuggerAttachment is set
|- get_test_dir - testing directory path
|- get_torrc_path - path to our tor instance's torrc
|- get_torrc_contents - contents of our tor instance's torrc
|- get_connection_type - method by which controllers can connect to tor
+ |- get_connection_options - connection related options we're running with
|- get_pid - process id of our tor process
|- get_tor_socket - provides a socket to the tor instance
+- get_tor_version - provides the version of tor we're running against
@@ -129,6 +131,10 @@ class RunnerStopped(Exception):
"Raised when we try to use a Runner that doesn't have an active tor instance"
pass
+class TorInaccessable(Exception):
+ "Raised when information is needed from tor but the instance we have is inaccessable"
+ pass
+
class Runner:
def __init__(self):
self._config = dict(DEFAULT_CONFIG)
@@ -256,6 +262,17 @@ class Runner:
return is_running
+ def is_accessible(self):
+ """
+ Checks if our tor instance has a method of being connected to or not.
+
+ Returns:
+ True if tor has a control socket or port, False otherwise
+ """
+
+ conn_opts = self.get_connection_options()
+ return OPT_PORT in conn_opts or OPT_SOCKET in conn_opts
+
def is_debugging_prevented(self):
"""
Checks if tor's 'DisableDebuggerAttachment' option is set. This feature has
@@ -263,14 +280,14 @@ class Runner:
https://trac.torproject.org/projects/tor/ticket/3313
Returns:
- True if debugger attachment is disallowd, False otherwise, and None if
- tor can't be checked
+ True if debugger attachment is disallowd, False otherwise
+
+ Raises:
+ TorInaccessable if this can't be determined
"""
# TODO: replace higher level GETCONF query when we have a controller class
control_socket = self.get_tor_socket()
- if control_socket == None: return None
-
control_socket.send("GETCONF DisableDebuggerAttachment")
getconf_response = control_socket.recv()
control_socket.close()
@@ -349,6 +366,16 @@ class Runner:
return self._connection_type
+ def get_connection_options(self):
+ """
+ Provides the connection related options we're running with.
+
+ Returns:
+ list of connection contstants (test.runner.OPT_*) we're running with
+ """
+
+ return CONNECTION_OPTS[self.get_connection_type()]
+
def get_pid(self):
"""
Provides the process id of the tor process.
@@ -371,20 +398,19 @@ class Runner:
authenticate (bool) - if True then the socket is authenticated
Returns:
- stem.socket.ControlSocket connected with our testing instance, returning
- None if we either don't have a test instance or it can't be connected to
- """
+ stem.socket.ControlSocket connected with our testing instance
- connection_type, cookie_path = self.get_connection_type(), self.get_auth_cookie_path()
- if connection_type == None: return None
+ Raises:
+ TorInaccessable if tor can't be connected to
+ """
- conn_opts = CONNECTION_OPTS[connection_type]
+ conn_opts = self.get_connection_options()
if OPT_PORT in conn_opts:
control_socket = stem.socket.ControlPort(control_port = CONTROL_PORT)
elif OPT_SOCKET in conn_opts:
control_socket = stem.socket.ControlSocketFile(CONTROL_SOCKET_PATH)
- else: return None
+ else: raise TorInaccessable("Unable to connect to tor")
if authenticate:
stem.connection.authenticate(control_socket, CONTROL_PASSWORD)
@@ -396,15 +422,16 @@ class Runner:
Queries our test instance for tor's version.
Returns:
- stem.version.Version for our test instance, None if we're unable to
- connect to it
+ stem.version.Version for our test instance
+
+ Raises:
+ TorInaccessable if this can't be determined
"""
# TODO: replace with higher level functions when we've completed a basic
# controller class
control_socket = self.get_tor_socket()
- if not control_socket: return None
control_socket.send("GETINFO version")
version_response = control_socket.recv()
@@ -466,7 +493,7 @@ class Runner:
# resides in is only accessable by the tor user (and refuses to finish
# starting if it isn't).
- if OPT_SOCKET in CONNECTION_OPTS[self._connection_type]:
+ if OPT_SOCKET in self.get_connection_options():
try:
socket_dir = os.path.dirname(CONTROL_SOCKET_PATH)
_print_status(" making control socket directory (%s)... " % socket_dir, STATUS_ATTR, quiet)
1
0

13 Jan '12
commit b01a790b902bfc8a0bb368d6b5bc72c52ff528af
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Jan 13 07:43:15 2012 -0800
Placing integ control socket in tor owned dir
Tor's new version (0.2.3.10) checks that the control socket is in a directory
that's only accessable by the tor user, and refuses to start up otherwise.
Accounting for this in stem's integ test startup.
---
test/runner.py | 26 +++++++++++++++++++++++++-
1 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/test/runner.py b/test/runner.py
index ea2a60c..d5f4a91 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -10,6 +10,7 @@ Runner - Runtime context for our integration tests.
|- start - prepares and starts a tor instance for our tests to run against
|- stop - stops our tor instance and cleans up any temporary files
|- is_running - checks if our tor test instance is running
+ |- is_debugging_prevented - checks if DisableDebuggerAttachment is set
|- get_test_dir - testing directory path
|- get_torrc_path - path to our tor instance's torrc
|- get_torrc_contents - contents of our tor instance's torrc
@@ -22,6 +23,7 @@ Runner - Runtime context for our integration tests.
import os
import sys
import time
+import stat
import socket
import shutil
import logging
@@ -68,7 +70,7 @@ INTEG_RUNNER = None
# control authentication options and attributes
CONTROL_PASSWORD = "pw"
CONTROL_PORT = 1111
-CONTROL_SOCKET_PATH = "/tmp/stem_integ_socket"
+CONTROL_SOCKET_PATH = "/tmp/stem_integ/socket"
OPT_PORT = "ControlPort %i" % CONTROL_PORT
OPT_COOKIE = "CookieAuthentication 1"
@@ -459,6 +461,28 @@ class Runner:
_print_status("failed (%s)\n" % exc, ERROR_ATTR, quiet)
raise exc
+ # Makes a directory for the control socket if needed. As of, at least, Tor
+ # 0.2.3.10 it checks during startup that the directory a control socket
+ # resides in is only accessable by the tor user (and refuses to finish
+ # starting if it isn't).
+
+ if OPT_SOCKET in CONNECTION_OPTS[self._connection_type]:
+ try:
+ socket_dir = os.path.dirname(CONTROL_SOCKET_PATH)
+ _print_status(" making control socket directory (%s)... " % socket_dir, STATUS_ATTR, quiet)
+
+ if os.path.exists(socket_dir) and stat.S_IMODE(os.stat(socket_dir).st_mode) == 0700:
+ _print_status("skipped\n", STATUS_ATTR, quiet)
+ else:
+ if not os.path.exists(socket_dir):
+ os.makedirs(socket_dir)
+
+ os.chmod(socket_dir, 0700)
+ _print_status("done\n", STATUS_ATTR, quiet)
+ except OSError, exc:
+ _print_status("failed (%s)\n" % exc, ERROR_ATTR, quiet)
+ raise exc
+
# configures logging
logging_path = self._config["test.integ.log"]
1
0

13 Jan '12
commit 4bbca2927d66b6a77e5a52bd9815810bdf77c95a
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Thu Jan 12 20:57:38 2012 -0500
added new pref for using built-in iptables binary
---
res/values/strings.xml | 4 ++++
res/xml/preferences.xml | 8 ++++++++
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 08bc34b..2ca91be 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -248,4 +248,8 @@
<string name="hidden_service_on">hidden service on:</string>
<string name="unable_to_read_hidden_service_name">unable to read hidden service name</string>
<string name="unable_to_start_tor">Unable to start Tor:</string>
+
+<string name="pref_use_sys_iptables_title">Use Default Iptables</string>
+<string name="pref_use_sys_iptables_summary">use the built-in iptables binary instead of the one bundled with Orbot</string>
+
</resources>
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 62eadc0..743cf27 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -176,6 +176,14 @@ android:summary="@string/enable_debug_log_to_output_must_use_adb_or_alogcat_to_v
android:enabled="true"></CheckBoxPreference>
+
+<CheckBoxPreference
+android:defaultValue="false"
+android:key="pref_use_sys_iptables"
+android:summary="@string/pref_use_sys_iptables_summary"
+android:enabled="true"
+android:title="@string/pref_use_sys_iptables_title"/>
+
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_transparent_port_fallback"
1
0
commit b8af143d5f32445163b761ce49618cc232339311
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Thu Jan 12 20:58:21 2012 -0500
cleaned up iptables binary handling
---
src/org/torproject/android/TorConstants.java | 1 +
.../android/service/IptablesManager.java | 1058 --------------------
.../android/service/TorBinaryInstaller.java | 98 ++
src/org/torproject/android/service/TorService.java | 26 +-
.../torproject/android/service/TorTransProxy.java | 73 ++-
src/org/torproject/android/wizard/Permissions.java | 2 +-
.../torproject/android/wizard/WizardHelper.java | 22 +-
7 files changed, 183 insertions(+), 1097 deletions(-)
diff --git a/src/org/torproject/android/TorConstants.java b/src/org/torproject/android/TorConstants.java
index df430c6..755a209 100644
--- a/src/org/torproject/android/TorConstants.java
+++ b/src/org/torproject/android/TorConstants.java
@@ -43,5 +43,6 @@ public interface TorConstants {
public final static String PREF_HAS_ROOT = "has_root";
public final static int RESULT_CLOSE_ALL = 0;
+ public final static String PREF_USE_SYSTEM_IPTABLES = "pref_use_sys_iptables";
}
diff --git a/src/org/torproject/android/service/IptablesManager.java b/src/org/torproject/android/service/IptablesManager.java
deleted file mode 100644
index 2781705..0000000
--- a/src/org/torproject/android/service/IptablesManager.java
+++ /dev/null
@@ -1,1058 +0,0 @@
-/**
- * Contains shared programming interfaces.
- * All iptables "communication" is handled by this class.
- *
- * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Rodrigo Zechin Rosauro
- * @version 1.0
- */
-
-package org.torproject.android.service;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.StringReader;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import org.torproject.android.R;
-
-import android.Manifest;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.util.Log;
-import android.widget.Toast;
-
-/**
- * Contains shared programming interfaces.
- * All iptables "communication" is handled by this class.
- */
-public final class IptablesManager {
- /** application version string */
- public static final String VERSION = "1.5.1-dev";
- /** special application UID used to indicate "any application" */
- public static final int SPECIAL_UID_ANY = -10;
- /** special application UID used to indicate the Linux Kernel */
- public static final int SPECIAL_UID_KERNEL = -11;
- /** root script filename */
- private static final String SCRIPT_FILE = "droidwall.sh";
-
- // Preferences
- public static final String PREFS_NAME = "DroidWallPrefs";
- public static final String PREF_3G_UIDS = "AllowedUids3G";
- public static final String PREF_WIFI_UIDS = "AllowedUidsWifi";
- public static final String PREF_PASSWORD = "Password";
- public static final String PREF_MODE = "BlockMode";
- public static final String PREF_ENABLED = "Enabled";
- public static final String PREF_LOGENABLED = "LogEnabled";
- // Modes
- public static final String MODE_WHITELIST = "whitelist";
- public static final String MODE_BLACKLIST = "blacklist";
- // Messages
- public static final String STATUS_CHANGED_MSG = "com.googlecode.droidwall.intent.action.STATUS_CHANGED";
- public static final String TOGGLE_REQUEST_MSG = "com.googlecode.droidwall.intent.action.TOGGLE_REQUEST";
- public static final String STATUS_EXTRA = "com.googlecode.droidwall.intent.extra.STATUS";
-
- // Cached applications
- public static DroidApp applications[] = null;
- // Do we have root access?
- private static boolean hasroot = false;
- // Flag indicating if this is an ARMv6 device (-1: unknown, 0: no, 1: yes)
- private static int isARMv6 = -1;
-
- /**
- * Display a simple alert box
- * @param ctx context
- * @param msg message
- */
- public static void alert(Context ctx, CharSequence msg) {
- if (ctx != null) {
- new AlertDialog.Builder(ctx)
- .setNeutralButton(android.R.string.ok, null)
- .setMessage(msg)
- .show();
- }
- }
- /**
- * Check if this is an ARMv6 device
- * @return true if this is ARMv6
- */
- private static boolean isARMv6() {
- if (isARMv6 == -1) {
- BufferedReader r = null;
- try {
- isARMv6 = 0;
- r = new BufferedReader(new FileReader("/proc/cpuinfo"));
- for (String line = r.readLine(); line != null; line = r.readLine()) {
- if (line.startsWith("Processor") && line.contains("ARMv6")) {
- isARMv6 = 1;
- break;
- } else if (line.startsWith("CPU architecture") && (line.contains("6TE") || line.contains("5TE"))) {
- isARMv6 = 1;
- break;
- }
- }
- } catch (Exception ex) {
- } finally {
- if (r != null) try {r.close();} catch (Exception ex) {}
- }
- }
- return (isARMv6 == 1);
- }
- /**
- * Create the generic shell script header used to determine which iptables binary to use.
- * @param ctx context
- * @return script header
- */
- private static String scriptHeader(Context ctx) {
- final String dir = ctx.getDir("bin",0).getAbsolutePath();
- final String myiptables = dir + (isARMv6() ? "/iptables_g1" : "/iptables_n1");
- return "" +
- "IPTABLES=iptables\n" +
- "BUSYBOX=busybox\n" +
- "GREP=grep\n" +
- "ECHO=echo\n" +
- "# Try to find busybox\n" +
- "if " + dir + "/busybox_g1 --help >/dev/null 2>/dev/null ; then\n" +
- " BUSYBOX="+dir+"/busybox_g1\n" +
- " GREP=\"$BUSYBOX grep\"\n" +
- " ECHO=\"$BUSYBOX echo\"\n" +
- "elif busybox --help >/dev/null 2>/dev/null ; then\n" +
- " BUSYBOX=busybox\n" +
- "elif /system/xbin/busybox --help >/dev/null 2>/dev/null ; then\n" +
- " BUSYBOX=/system/xbin/busybox\n" +
- "elif /system/bin/busybox --help >/dev/null 2>/dev/null ; then\n" +
- " BUSYBOX=/system/bin/busybox\n" +
- "fi\n" +
- "# Try to find grep\n" +
- "if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" +
- " if $ECHO 1 | $BUSYBOX grep -q 1 >/dev/null 2>/dev/null ; then\n" +
- " GREP=\"$BUSYBOX grep\"\n" +
- " fi\n" +
- " # Grep is absolutely required\n" +
- " if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" +
- " $ECHO The grep command is required. DroidWall will not work.\n" +
- " exit 1\n" +
- " fi\n" +
- "fi\n" +
- "# Try to find iptables\n" +
- "if " + myiptables + " --version >/dev/null 2>/dev/null ; then\n" +
- " IPTABLES="+myiptables+"\n" +
- "fi\n" +
- "";
- }
- /**
- * Copies a raw resource file, given its ID to the given location
- * @param ctx context
- * @param resid resource id
- * @param file destination file
- * @param mode file permissions (E.g.: "755")
- * @throws IOException on error
- * @throws InterruptedException when interrupted
- */
- private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
- {
- final String abspath = file.getAbsolutePath();
- // Write the iptables binary
- final FileOutputStream out = new FileOutputStream(file);
- final InputStream is = ctx.getResources().openRawResource(resid);
- byte buf[] = new byte[1024];
- int len;
- while ((len = is.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- out.close();
- is.close();
- // Change the permissions
- Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
- }
- /**
- * Purge and re-add all rules (internal implementation).
- * @param ctx application context (mandatory)
- * @param uidsWifi list of selected UIDs for WIFI to allow or disallow (depending on the working mode)
- * @param uids3g list of selected UIDs for 2G/3G to allow or disallow (depending on the working mode)
- * @param showErrors indicates if errors should be alerted
- */
- private static boolean applyIptablesRulesImpl(Context ctx, List<Integer> uidsWifi, List<Integer> uids3g, boolean showErrors) {
- if (ctx == null) {
- return false;
- }
- assertBinaries(ctx, showErrors);
- final String ITFS_WIFI[] = {"tiwlan+", "wlan+", "eth+"};
- final String ITFS_3G[] = {"rmnet+","pdp+","ppp+","uwbr+","wimax+","vsnet+"};
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- final boolean whitelist = prefs.getString(PREF_MODE, MODE_WHITELIST).equals(MODE_WHITELIST);
- final boolean blacklist = !whitelist;
- final boolean logenabled = ctx.getSharedPreferences(PREFS_NAME, 0).getBoolean(PREF_LOGENABLED, false);
-
- final StringBuilder script = new StringBuilder();
- try {
- int code;
- script.append(scriptHeader(ctx));
- script.append("" +
- "$IPTABLES --version || exit 1\n" +
- "# Create the droidwall chains if necessary\n" +
- "$IPTABLES -L droidwall >/dev/null 2>/dev/null || $IPTABLES --new droidwall || exit 2\n" +
- "$IPTABLES -L droidwall-3g >/dev/null 2>/dev/null || $IPTABLES --new droidwall-3g || exit 3\n" +
- "$IPTABLES -L droidwall-wifi >/dev/null 2>/dev/null || $IPTABLES --new droidwall-wifi || exit 4\n" +
- "$IPTABLES -L droidwall-reject >/dev/null 2>/dev/null || $IPTABLES --new droidwall-reject || exit 5\n" +
- "# Add droidwall chain to OUTPUT chain if necessary\n" +
- "$IPTABLES -L OUTPUT | $GREP -q droidwall || $IPTABLES -A OUTPUT -j droidwall || exit 6\n" +
- "# Flush existing rules\n" +
- "$IPTABLES -F droidwall || exit 7\n" +
- "$IPTABLES -F droidwall-3g || exit 8\n" +
- "$IPTABLES -F droidwall-wifi || exit 9\n" +
- "$IPTABLES -F droidwall-reject || exit 10\n" +
- "");
- // Check if logging is enabled
- if (logenabled) {
- script.append("" +
- "# Create the log and reject rules (ignore errors on the LOG target just in case it is not available)\n" +
- "$IPTABLES -A droidwall-reject -j LOG --log-prefix \"[DROIDWALL] \" --log-uid\n" +
- "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" +
- "");
- } else {
- script.append("" +
- "# Create the reject rule (log disabled)\n" +
- "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" +
- "");
- }
- if (whitelist && logenabled) {
- script.append("# Allow DNS lookups on white-list for a better logging (ignore errors)\n");
- script.append("$IPTABLES -A droidwall -p udp --dport 53 -j RETURN\n");
- }
- script.append("# Main rules (per interface)\n");
- for (final String itf : ITFS_3G) {
- script.append("$IPTABLES -A droidwall -o ").append(itf).append(" -j droidwall-3g || exit\n");
- }
- for (final String itf : ITFS_WIFI) {
- script.append("$IPTABLES -A droidwall -o ").append(itf).append(" -j droidwall-wifi || exit\n");
- }
-
- script.append("# Filtering rules\n");
- final String targetRule = (whitelist ? "RETURN" : "droidwall-reject");
- final boolean any_3g = uids3g.indexOf(SPECIAL_UID_ANY) >= 0;
- final boolean any_wifi = uidsWifi.indexOf(SPECIAL_UID_ANY) >= 0;
- if (whitelist && !any_wifi) {
- // When "white listing" wifi, we need to ensure that the dhcp and wifi users are allowed
- int uid = android.os.Process.getUidForName("dhcp");
- if (uid != -1) {
- script.append("# dhcp user\n");
- script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j RETURN || exit\n");
- }
- uid = android.os.Process.getUidForName("wifi");
- if (uid != -1) {
- script.append("# wifi user\n");
- script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j RETURN || exit\n");
- }
- }
- if (any_3g) {
- if (blacklist) {
- /* block any application on this interface */
- script.append("$IPTABLES -A droidwall-3g -j ").append(targetRule).append(" || exit\n");
- }
- } else {
- /* release/block individual applications on this interface */
- for (final Integer uid : uids3g) {
- if (uid >= 0) script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner ").append(uid).append(" -j ").append(targetRule).append(" || exit\n");
- }
- }
- if (any_wifi) {
- if (blacklist) {
- /* block any application on this interface */
- script.append("$IPTABLES -A droidwall-wifi -j ").append(targetRule).append(" || exit\n");
- }
- } else {
- /* release/block individual applications on this interface */
- for (final Integer uid : uidsWifi) {
- if (uid >= 0) script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j ").append(targetRule).append(" || exit\n");
- }
- }
- if (whitelist) {
- if (!any_3g) {
- if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) {
- script.append("# hack to allow kernel packets on white-list\n");
- script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n");
- } else {
- script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n");
- }
- }
- if (!any_wifi) {
- if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) {
- script.append("# hack to allow kernel packets on white-list\n");
- script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n");
- } else {
- script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n");
- }
- }
- } else {
- if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) {
- script.append("# hack to BLOCK kernel packets on black-list\n");
- script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j RETURN || exit\n");
- script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n");
- }
- if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) {
- script.append("# hack to BLOCK kernel packets on black-list\n");
- script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j RETURN || exit\n");
- script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n");
- }
- }
- final StringBuilder res = new StringBuilder();
- code = runScriptAsRoot(ctx, script.toString(), res);
- if (showErrors && code != 0) {
- String msg = res.toString();
- Log.e("DroidWall", msg);
- // Remove unnecessary help message from output
- if (msg.indexOf("\nTry `iptables -h' or 'iptables --help' for more information.") != -1) {
- msg = msg.replace("\nTry `iptables -h' or 'iptables --help' for more information.", "");
- }
- alert(ctx, "Error applying iptables rules. Exit code: " + code + "\n\n" + msg.trim());
- } else {
- return true;
- }
- } catch (Exception e) {
- if (showErrors) alert(ctx, "error refreshing iptables: " + e);
- }
- return false;
- }
- /**
- * Purge and re-add all saved rules (not in-memory ones).
- * This is much faster than just calling "applyIptablesRules", since it don't need to read installed applications.
- * @param ctx application context (mandatory)
- * @param showErrors indicates if errors should be alerted
- */
- public static boolean applySavedIptablesRules(Context ctx, boolean showErrors) {
- if (ctx == null) {
- return false;
- }
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, "");
- final String savedUids_3g = prefs.getString(PREF_3G_UIDS, "");
- final List<Integer> uids_wifi = new LinkedList<Integer>();
- if (savedUids_wifi.length() > 0) {
- // Check which applications are allowed on wifi
- final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|");
- while (tok.hasMoreTokens()) {
- final String uid = tok.nextToken();
- if (!uid.equals("")) {
- try {
- uids_wifi.add(Integer.parseInt(uid));
- } catch (Exception ex) {
- }
- }
- }
- }
- final List<Integer> uids_3g = new LinkedList<Integer>();
- if (savedUids_3g.length() > 0) {
- // Check which applications are allowed on 2G/3G
- final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|");
- while (tok.hasMoreTokens()) {
- final String uid = tok.nextToken();
- if (!uid.equals("")) {
- try {
- uids_3g.add(Integer.parseInt(uid));
- } catch (Exception ex) {
- }
- }
- }
- }
- return applyIptablesRulesImpl(ctx, uids_wifi, uids_3g, showErrors);
- }
-
- /**
- * Purge and re-add all rules.
- * @param ctx application context (mandatory)
- * @param showErrors indicates if errors should be alerted
- */
- public static boolean applyIptablesRules(Context ctx, boolean showErrors) {
- if (ctx == null) {
- return false;
- }
- saveRules(ctx);
- return applySavedIptablesRules(ctx, showErrors);
- }
-
- /**
- * Save current rules using the preferences storage.
- * @param ctx application context (mandatory)
- */
- public static void saveRules(Context ctx) {
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- final DroidApp[] apps = getApps(ctx);
- // Builds a pipe-separated list of names
- final StringBuilder newuids_wifi = new StringBuilder();
- final StringBuilder newuids_3g = new StringBuilder();
- for (int i=0; i<apps.length; i++) {
- if (apps[i].selected_wifi) {
- if (newuids_wifi.length() != 0) newuids_wifi.append('|');
- newuids_wifi.append(apps[i].uid);
- }
- if (apps[i].selected_3g) {
- if (newuids_3g.length() != 0) newuids_3g.append('|');
- newuids_3g.append(apps[i].uid);
- }
- }
- // save the new list of UIDs
- final Editor edit = prefs.edit();
- edit.putString(PREF_WIFI_UIDS, newuids_wifi.toString());
- edit.putString(PREF_3G_UIDS, newuids_3g.toString());
- edit.commit();
- }
-
- /**
- * Purge all iptables rules.
- * @param ctx mandatory context
- * @param showErrors indicates if errors should be alerted
- * @return true if the rules were purged
- */
- public static boolean purgeIptables(Context ctx, boolean showErrors) {
- StringBuilder res = new StringBuilder();
- try {
- assertBinaries(ctx, showErrors);
- int code = runScriptAsRoot(ctx, scriptHeader(ctx) +
- "$IPTABLES -F droidwall\n" +
- "$IPTABLES -F droidwall-reject\n" +
- "$IPTABLES -F droidwall-3g\n" +
- "$IPTABLES -F droidwall-wifi\n", res);
- if (code == -1) {
- if (showErrors) alert(ctx, "error purging iptables. exit code: " + code + "\n" + res);
- return false;
- }
- return true;
- } catch (Exception e) {
- if (showErrors) alert(ctx, "error purging iptables: " + e);
- return false;
- }
- }
-
- /**
- * Display iptables rules output
- * @param ctx application context
- */
- public static void showIptablesRules(Context ctx) {
- try {
- final StringBuilder res = new StringBuilder();
- runScriptAsRoot(ctx, scriptHeader(ctx) +
- "$ECHO $IPTABLES\n" +
- "$IPTABLES -L -v\n", res);
- alert(ctx, res);
- } catch (Exception e) {
- alert(ctx, "error: " + e);
- }
- }
-
- /**
- * Display logs
- * @param ctx application context
- * @return true if the clogs were cleared
- */
- public static boolean clearLog(Context ctx) {
- try {
- final StringBuilder res = new StringBuilder();
- int code = runScriptAsRoot(ctx, "dmesg -c >/dev/null || exit\n", res);
- if (code != 0) {
- alert(ctx, res);
- return false;
- }
- return true;
- } catch (Exception e) {
- alert(ctx, "error: " + e);
- }
- return false;
- }
- /**
- * Display logs
- * @param ctx application context
- */
- public static void showLog(Context ctx) {
- try {
- StringBuilder res = new StringBuilder();
- int code = runScriptAsRoot(ctx, scriptHeader(ctx) +
- "dmesg | $GREP DROIDWALL\n", res);
- if (code != 0) {
- if (res.length() == 0) {
- res.append("Log is empty");
- }
- alert(ctx, res);
- return;
- }
- final BufferedReader r = new BufferedReader(new StringReader(res.toString()));
- final Integer unknownUID = -99;
- res = new StringBuilder();
- String line;
- int start, end;
- Integer appid;
- final HashMap<Integer, LogInfo> map = new HashMap<Integer, LogInfo>();
- LogInfo loginfo = null;
- while ((line = r.readLine()) != null) {
- if (line.indexOf("[DROIDWALL]") == -1) continue;
- appid = unknownUID;
- if (((start=line.indexOf("UID=")) != -1) && ((end=line.indexOf(" ", start)) != -1)) {
- appid = Integer.parseInt(line.substring(start+4, end));
- }
- loginfo = map.get(appid);
- if (loginfo == null) {
- loginfo = new LogInfo();
- map.put(appid, loginfo);
- }
- loginfo.totalBlocked += 1;
- if (((start=line.indexOf("DST=")) != -1) && ((end=line.indexOf(" ", start)) != -1)) {
- String dst = line.substring(start+4, end);
- if (loginfo.dstBlocked.containsKey(dst)) {
- loginfo.dstBlocked.put(dst, loginfo.dstBlocked.get(dst) + 1);
- } else {
- loginfo.dstBlocked.put(dst, 1);
- }
- }
- }
- final DroidApp[] apps = getApps(ctx);
- for (Integer id : map.keySet()) {
- res.append("App ID ");
- if (id != unknownUID) {
- res.append(id);
- for (DroidApp app : apps) {
- if (app.uid == id) {
- res.append(" (").append(app.names[0]);
- if (app.names.length > 1) {
- res.append(", ...)");
- } else {
- res.append(")");
- }
- break;
- }
- }
- } else {
- res.append("(kernel)");
- }
- loginfo = map.get(id);
- res.append(" - Blocked ").append(loginfo.totalBlocked).append(" packets");
- if (loginfo.dstBlocked.size() > 0) {
- res.append(" (");
- boolean first = true;
- for (String dst : loginfo.dstBlocked.keySet()) {
- if (!first) {
- res.append(", ");
- }
- res.append(loginfo.dstBlocked.get(dst)).append(" packets for ").append(dst);
- first = false;
- }
- res.append(")");
- }
- res.append("\n\n");
- }
- if (res.length() == 0) {
- res.append("Log is empty");
- }
- alert(ctx, res);
- } catch (Exception e) {
- alert(ctx, "error: " + e);
- }
- }
-
- /**
- * @param ctx application context (mandatory)
- * @return a list of applications
- */
- public static DroidApp[] getApps(Context ctx) {
- if (applications != null) {
- // return cached instance
- return applications;
- }
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- // allowed application names separated by pipe '|' (persisted)
- final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, "");
- final String savedUids_3g = prefs.getString(PREF_3G_UIDS, "");
- int selected_wifi[] = new int[0];
- int selected_3g[] = new int[0];
- if (savedUids_wifi.length() > 0) {
- // Check which applications are allowed
- final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|");
- selected_wifi = new int[tok.countTokens()];
- for (int i=0; i<selected_wifi.length; i++) {
- final String uid = tok.nextToken();
- if (!uid.equals("")) {
- try {
- selected_wifi[i] = Integer.parseInt(uid);
- } catch (Exception ex) {
- selected_wifi[i] = -1;
- }
- }
- }
- // Sort the array to allow using "Arrays.binarySearch" later
- Arrays.sort(selected_wifi);
- }
- if (savedUids_3g.length() > 0) {
- // Check which applications are allowed
- final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|");
- selected_3g = new int[tok.countTokens()];
- for (int i=0; i<selected_3g.length; i++) {
- final String uid = tok.nextToken();
- if (!uid.equals("")) {
- try {
- selected_3g[i] = Integer.parseInt(uid);
- } catch (Exception ex) {
- selected_3g[i] = -1;
- }
- }
- }
- // Sort the array to allow using "Arrays.binarySearch" later
- Arrays.sort(selected_3g);
- }
- try {
- final PackageManager pkgmanager = ctx.getPackageManager();
- final List<ApplicationInfo> installed = pkgmanager.getInstalledApplications(0);
- final HashMap<Integer, DroidApp> map = new HashMap<Integer, DroidApp>();
- final Editor edit = prefs.edit();
- boolean changed = false;
- String name = null;
- String cachekey = null;
- DroidApp app = null;
- for (final ApplicationInfo apinfo : installed) {
- app = map.get(apinfo.uid);
- // filter applications which are not allowed to access the Internet
- if (app == null && PackageManager.PERMISSION_GRANTED != pkgmanager.checkPermission(Manifest.permission.INTERNET, apinfo.packageName)) {
- continue;
- }
- // try to get the application label from our cache - getApplicationLabel() is horribly slow!!!!
- cachekey = "cache.label."+apinfo.packageName;
- name = prefs.getString(cachekey, "");
- if (name.length() == 0) {
- // get label and put on cache
- name = pkgmanager.getApplicationLabel(apinfo).toString();
- edit.putString(cachekey, name);
- changed = true;
- }
- if (app == null) {
- app = new DroidApp();
- app.uid = apinfo.uid;
- app.names = new String[] { name };
- map.put(apinfo.uid, app);
- } else {
- final String newnames[] = new String[app.names.length + 1];
- System.arraycopy(app.names, 0, newnames, 0, app.names.length);
- newnames[app.names.length] = name;
- app.names = newnames;
- }
- // check if this application is selected
- if (!app.selected_wifi && Arrays.binarySearch(selected_wifi, app.uid) >= 0) {
- app.selected_wifi = true;
- }
- if (!app.selected_3g && Arrays.binarySearch(selected_3g, app.uid) >= 0) {
- app.selected_3g = true;
- }
- }
- if (changed) {
- edit.commit();
- }
- /* add special applications to the list */
- final DroidApp special[] = {
- new DroidApp(SPECIAL_UID_ANY,"(Any application) - Same as selecting all applications", false, false),
- new DroidApp(SPECIAL_UID_KERNEL,"(Kernel) - Linux kernel", false, false),
- new DroidApp(android.os.Process.getUidForName("root"), "(root) - Applications running as root", false, false),
- new DroidApp(android.os.Process.getUidForName("media"), "Media server", false, false),
- new DroidApp(android.os.Process.getUidForName("vpn"), "VPN networking", false, false),
- new DroidApp(android.os.Process.getUidForName("shell"), "Linux shell", false, false),
- };
- for (int i=0; i<special.length; i++) {
- app = special[i];
- if (app.uid != -1 && !map.containsKey(app.uid)) {
- // check if this application is allowed
- if (Arrays.binarySearch(selected_wifi, app.uid) >= 0) {
- app.selected_wifi = true;
- }
- if (Arrays.binarySearch(selected_3g, app.uid) >= 0) {
- app.selected_3g = true;
- }
- map.put(app.uid, app);
- }
- }
- applications = new DroidApp[map.size()];
- int index = 0;
- for (DroidApp application : map.values()) applications[index++] = application;
- return applications;
- } catch (Exception e) {
- alert(ctx, "error: " + e);
- }
- return null;
- }
- /**
- * Check if we have root access
- * @param ctx mandatory context
- * @param showErrors indicates if errors should be alerted
- * @return boolean true if we have root
- */
- public static boolean hasRootAccess(Context ctx, boolean showErrors) {
- if (hasroot) return true;
- final StringBuilder res = new StringBuilder();
- try {
- // Run an empty script just to check root access
- if (runScriptAsRoot(ctx, "exit 0", res) == 0) {
- hasroot = true;
- return true;
- }
- } catch (Exception e) {
- }
- if (showErrors) {
- alert(ctx, "Could not acquire root access.\n" +
- "You need a rooted phone to run DroidWall.\n\n" +
- "If this phone is already rooted, please make sure DroidWall has enough permissions to execute the \"su\" command.\n" +
- "Error message: " + res.toString());
- }
- return false;
- }
- /**
- * Runs a script, wither as root or as a regular user (multiple commands separated by "\n").
- * @param ctx mandatory context
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- */
- public static int runScript(Context ctx, String script, StringBuilder res, long timeout, boolean asroot) {
- final File file = new File(ctx.getDir("bin",0), SCRIPT_FILE);
- final ScriptRunner runner = new ScriptRunner(file, script, res, asroot);
- runner.start();
- try {
- if (timeout > 0) {
- runner.join(timeout);
- } else {
- runner.join();
- }
- if (runner.isAlive()) {
- // Timed-out
- runner.interrupt();
- runner.join(150);
- runner.destroy();
- runner.join(50);
- }
- } catch (InterruptedException ex) {}
- return runner.exitcode;
- }
- /**
- * Runs a script as root (multiple commands separated by "\n").
- * @param ctx mandatory context
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- */
- public static int runScriptAsRoot(Context ctx, String script, StringBuilder res, long timeout) {
- return runScript(ctx, script, res, timeout, true);
- }
- /**
- * Runs a script as root (multiple commands separated by "\n") with a default timeout of 20 seconds.
- * @param ctx mandatory context
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- * @throws IOException on any error executing the script, or writing it to disk
- */
- public static int runScriptAsRoot(Context ctx, String script, StringBuilder res) throws IOException {
- return runScriptAsRoot(ctx, script, res, 40000);
- }
- /**
- * Runs a script as a regular user (multiple commands separated by "\n") with a default timeout of 20 seconds.
- * @param ctx mandatory context
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- * @throws IOException on any error executing the script, or writing it to disk
- */
- public static int runScript(Context ctx, String script, StringBuilder res) throws IOException {
- return runScript(ctx, script, res, 40000, false);
- }
- /**
- * Asserts that the binary files are installed in the cache directory.
- * @param ctx context
- * @param showErrors indicates if errors should be alerted
- * @return false if the binary files could not be installed
- */
- public static boolean assertBinaries(Context ctx, boolean showErrors) {
- boolean changed = false;
- try {
- // Check iptables_g1
- File file = new File(ctx.getDir("bin",0), "iptables");
-
- if ((!file.exists()) && isARMv6()) {
- copyRawFile(ctx, R.raw.iptables_g1, file, "755");
- changed = true;
- }
-
- // Check iptables_n1
- file = new File(ctx.getDir("bin",0), "iptables");
- if ((!file.exists()) && (!isARMv6())) {
- copyRawFile(ctx, R.raw.iptables_n1, file, "755");
- changed = true;
- }
-
- // Check busybox
- /*
- file = new File(ctx.getDir("bin",0), "busybox_g1");
- if (!file.exists()) {
- copyRawFile(ctx, R.raw.busybox_g1, file, "755");
- changed = true;
- }
- */
-
- if (changed) {
- Toast.makeText(ctx, R.string.status_install_success, Toast.LENGTH_LONG).show();
- }
- } catch (Exception e) {
- if (showErrors) alert(ctx, "Error installing binary files: " + e);
- return false;
- }
- return true;
- }
- /**
- * Check if the firewall is enabled
- * @param ctx mandatory context
- * @return boolean
- */
- public static boolean isEnabled(Context ctx) {
- if (ctx == null) return false;
- return ctx.getSharedPreferences(PREFS_NAME, 0).getBoolean(PREF_ENABLED, false);
- }
-
- /**
- * Defines if the firewall is enabled and broadcasts the new status
- * @param ctx mandatory context
- * @param enabled enabled flag
- */
- public static void setEnabled(Context ctx, boolean enabled) {
- if (ctx == null) return;
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- if (prefs.getBoolean(PREF_ENABLED, false) == enabled) {
- return;
- }
- final Editor edit = prefs.edit();
- edit.putBoolean(PREF_ENABLED, enabled);
- if (!edit.commit()) {
- alert(ctx, "Error writing to preferences");
- return;
- }
- /* notify */
- final Intent message = new Intent(IptablesManager.STATUS_CHANGED_MSG);
- message.putExtra(IptablesManager.STATUS_EXTRA, enabled);
- ctx.sendBroadcast(message);
- }
- /**
- * Called when an application in removed (un-installed) from the system.
- * This will look for that application in the selected list and update the persisted values if necessary
- * @param ctx mandatory app context
- * @param uid UID of the application that has been removed
- */
- public static void applicationRemoved(Context ctx, int uid) {
- final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
- final Editor editor = prefs.edit();
- // allowed application names separated by pipe '|' (persisted)
- final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, "");
- final String savedUids_3g = prefs.getString(PREF_3G_UIDS, "");
- final String uid_str = uid + "";
- boolean changed = false;
- // look for the removed application in the "wi-fi" list
- if (savedUids_wifi.length() > 0) {
- final StringBuilder newuids = new StringBuilder();
- final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|");
- while (tok.hasMoreTokens()) {
- final String token = tok.nextToken();
- if (uid_str.equals(token)) {
- Log.d("DroidWall", "Removing UID " + token + " from the wi-fi list (package removed)!");
- changed = true;
- } else {
- if (newuids.length() > 0) newuids.append('|');
- newuids.append(token);
- }
- }
- if (changed) {
- editor.putString(PREF_WIFI_UIDS, newuids.toString());
- }
- }
- // look for the removed application in the "3g" list
- if (savedUids_3g.length() > 0) {
- final StringBuilder newuids = new StringBuilder();
- final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|");
- while (tok.hasMoreTokens()) {
- final String token = tok.nextToken();
- if (uid_str.equals(token)) {
- Log.d("DroidWall", "Removing UID " + token + " from the 3G list (package removed)!");
- changed = true;
- } else {
- if (newuids.length() > 0) newuids.append('|');
- newuids.append(token);
- }
- }
- if (changed) {
- editor.putString(PREF_3G_UIDS, newuids.toString());
- }
- }
- // if anything has changed, save the new prefs...
- if (changed) {
- editor.commit();
- if (isEnabled(ctx)) {
- // .. and also re-apply the rules if the firewall is enabled
- applySavedIptablesRules(ctx, false);
- }
- }
- }
-
- /**
- * Small structure to hold an application info
- */
- public static final class DroidApp {
- /** linux user id */
- int uid;
- /** application names belonging to this user id */
- String names[];
- /** indicates if this application is selected for wifi */
- boolean selected_wifi;
- /** indicates if this application is selected for 3g */
- boolean selected_3g;
- /** toString cache */
- String tostr;
-
- public DroidApp() {
- }
- public DroidApp(int uid, String name, boolean selected_wifi, boolean selected_3g) {
- this.uid = uid;
- this.names = new String[] {name};
- this.selected_wifi = selected_wifi;
- this.selected_3g = selected_3g;
- }
- /**
- * Screen representation of this application
- */
- @Override
- public String toString() {
- if (tostr == null) {
- final StringBuilder s = new StringBuilder();
- if (uid > 0) s.append(uid + ": ");
- for (int i=0; i<names.length; i++) {
- if (i != 0) s.append(", ");
- s.append(names[i]);
- }
- s.append("\n");
- tostr = s.toString();
- }
- return tostr;
- }
- }
- /**
- * Small internal structure used to hold log information
- */
- private static final class LogInfo {
- private int totalBlocked; // Total number of packets blocked
- private HashMap<String, Integer> dstBlocked; // Number of packets blocked per destination IP address
- private LogInfo() {
- this.dstBlocked = new HashMap<String, Integer>();
- }
- }
- /**
- * Internal thread used to execute scripts (as root or not).
- */
- private static final class ScriptRunner extends Thread {
- private final File file;
- private final String script;
- private final StringBuilder res;
- private final boolean asroot;
- public int exitcode = -1;
- private Process exec;
-
- /**
- * Creates a new script runner.
- * @param file temporary script file
- * @param script script to run
- * @param res response output
- * @param asroot if true, executes the script as root
- */
- public ScriptRunner(File file, String script, StringBuilder res, boolean asroot) {
- this.file = file;
- this.script = script;
- this.res = res;
- this.asroot = asroot;
- }
- @Override
- public void run() {
- try {
- file.createNewFile();
- final String abspath = file.getAbsolutePath();
- // make sure we have execution permission on the script file
- Runtime.getRuntime().exec("chmod 777 "+abspath).waitFor();
- // Write the script to be executed
- final OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file));
- if (new File("/system/bin/sh").exists()) {
- out.write("#!/system/bin/sh\n");
- }
- out.write(script);
- if (!script.endsWith("\n")) out.write("\n");
- out.write("exit\n");
- out.flush();
- out.close();
- if (this.asroot) {
- // Create the "su" request to run the script
- exec = Runtime.getRuntime().exec("su -c "+abspath);
- } else {
- // Create the "sh" request to run the script
- exec = Runtime.getRuntime().exec("sh "+abspath);
- }
- InputStreamReader r = new InputStreamReader(exec.getInputStream());
- final char buf[] = new char[1024];
- int read = 0;
- // Consume the "stdout"
- while ((read=r.read(buf)) != -1) {
- if (res != null) res.append(buf, 0, read);
- }
- // Consume the "stderr"
- r = new InputStreamReader(exec.getErrorStream());
- read=0;
- while ((read=r.read(buf)) != -1) {
- if (res != null) res.append(buf, 0, read);
- }
- // get the process exit code
- if (exec != null) this.exitcode = exec.waitFor();
- } catch (InterruptedException ex) {
- if (res != null) res.append("\nOperation timed-out");
- } catch (Exception ex) {
- if (res != null) res.append("\n" + ex);
- } finally {
- destroy();
- }
- }
- /**
- * Destroy this script runner
- */
- public synchronized void destroy() {
- if (exec != null) exec.destroy();
- exec = null;
- }
- }
-}
diff --git a/src/org/torproject/android/service/TorBinaryInstaller.java b/src/org/torproject/android/service/TorBinaryInstaller.java
index ff1e720..07b5049 100644
--- a/src/org/torproject/android/service/TorBinaryInstaller.java
+++ b/src/org/torproject/android/service/TorBinaryInstaller.java
@@ -3,10 +3,12 @@
package org.torproject.android.service;
+import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -22,6 +24,7 @@ import org.torproject.android.TorConstants;
import android.content.Context;
import android.util.Log;
+import android.widget.Toast;
public class TorBinaryInstaller implements TorServiceConstants {
@@ -29,6 +32,8 @@ public class TorBinaryInstaller implements TorServiceConstants {
File installFolder;
Context context;
+ private static int isARMv6 = -1;
+
public TorBinaryInstaller (Context context, File installFolder)
{
this.installFolder = installFolder;
@@ -151,4 +156,97 @@ public class TorBinaryInstaller implements TorServiceConstants {
+ /**
+ * Check if this is an ARMv6 device
+ * @return true if this is ARMv6
+ */
+ private static boolean isARMv6() {
+ if (isARMv6 == -1) {
+ BufferedReader r = null;
+ try {
+ isARMv6 = 0;
+ r = new BufferedReader(new FileReader("/proc/cpuinfo"));
+ for (String line = r.readLine(); line != null; line = r.readLine()) {
+ if (line.startsWith("Processor") && line.contains("ARMv6")) {
+ isARMv6 = 1;
+ break;
+ } else if (line.startsWith("CPU architecture") && (line.contains("6TE") || line.contains("5TE"))) {
+ isARMv6 = 1;
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ } finally {
+ if (r != null) try {r.close();} catch (Exception ex) {}
+ }
+ }
+ return (isARMv6 == 1);
+ }
+
+ /**
+ * Copies a raw resource file, given its ID to the given location
+ * @param ctx context
+ * @param resid resource id
+ * @param file destination file
+ * @param mode file permissions (E.g.: "755")
+ * @throws IOException on error
+ * @throws InterruptedException when interrupted
+ */
+ private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
+ {
+ final String abspath = file.getAbsolutePath();
+ // Write the iptables binary
+ final FileOutputStream out = new FileOutputStream(file);
+ final InputStream is = ctx.getResources().openRawResource(resid);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ is.close();
+ // Change the permissions
+ Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
+ }
+ /**
+ * Asserts that the binary files are installed in the cache directory.
+ * @param ctx context
+ * @param showErrors indicates if errors should be alerted
+ * @return false if the binary files could not be installed
+ */
+ public static boolean assertIpTablesBinaries(Context ctx, boolean showErrors) throws Exception {
+ boolean changed = false;
+
+ // Check iptables_g1
+ File file = new File(ctx.getDir("bin",0), "iptables");
+
+ if ((!file.exists()) && isARMv6()) {
+ copyRawFile(ctx, R.raw.iptables_g1, file, "755");
+ changed = true;
+ }
+
+ // Check iptables_n1
+ file = new File(ctx.getDir("bin",0), "iptables");
+ if ((!file.exists()) && (!isARMv6())) {
+ copyRawFile(ctx, R.raw.iptables_n1, file, "755");
+ changed = true;
+ }
+
+ // Check busybox
+ /*
+ file = new File(ctx.getDir("bin",0), "busybox_g1");
+ if (!file.exists()) {
+ copyRawFile(ctx, R.raw.busybox_g1, file, "755");
+ changed = true;
+ }
+ */
+
+ if (changed) {
+ Toast.makeText(ctx, R.string.status_install_success, Toast.LENGTH_LONG).show();
+ }
+
+ return true;
+ }
+
+
}
diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java
index df2990d..2b1c91d 100644
--- a/src/org/torproject/android/service/TorService.java
+++ b/src/org/torproject/android/service/TorService.java
@@ -1,11 +1,20 @@
/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* 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 java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
+import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
@@ -39,6 +48,7 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
+import android.widget.Toast;
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
{
@@ -414,8 +424,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private boolean checkTorBinaries () throws Exception
{
//check and install iptables
- IptablesManager.assertBinaries(this, true);
-
+ TorBinaryInstaller.assertIpTablesBinaries(this, true);
appBinHome = getDir("bin",0);
appDataHome = getCacheDir();
@@ -520,6 +529,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
+ TorTransProxy ttProxy = new TorTransProxy();
+
if (hasRoot && enableTransparentProxy)
{
@@ -544,7 +555,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
int status = code;
while (st.hasMoreTokens())
{
- status = TorTransProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
+ status = ttProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
if(status != 0)
code = status;
}
@@ -554,12 +565,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if(transProxyAll)
{
showAlert(getString(R.string.status), getString(R.string.setting_up_full_transparent_proxying_));
- code = TorTransProxy.setTransparentProxyingAll(this);
+ code = ttProxy.setTransparentProxyingAll(this);
}
else
{
showAlert(getString(R.string.status), getString(R.string.setting_up_app_based_transparent_proxying_));
- code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
+ code = ttProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
}
}
@@ -576,7 +587,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{
showAlert(getString(R.string.status), getString(R.string.transproxy_enabled_for_tethering_));
- TorTransProxy.enableTetheringRules(this);
+ ttProxy.enableTetheringRules(this);
}
}
@@ -604,12 +615,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
+
if (hasRoot && enableTransparentProxy)
{
TorService.logMessage ("Clearing TransProxy rules");
- TorTransProxy.flushIptables(this);
+ new TorTransProxy().flushIptables(this);
showAlert(getString(R.string.status), getString(R.string.transproxy_rules_cleared));
diff --git a/src/org/torproject/android/service/TorTransProxy.java b/src/org/torproject/android/service/TorTransProxy.java
index bf5fee2..462d2f0 100644
--- a/src/org/torproject/android/service/TorTransProxy.java
+++ b/src/org/torproject/android/service/TorTransProxy.java
@@ -6,17 +6,59 @@ import org.torproject.android.TorConstants;
import org.torproject.android.settings.TorifiedApp;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
import android.util.Log;
public class TorTransProxy implements TorServiceConstants {
- private final static String TAG = TorConstants.TAG;
-
+ private String ipTablesPath;
+
+ public String getIpTablesPath (Context context)
+ {
+
+ if (ipTablesPath == null)
+ {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ if (prefs.getBoolean(TorConstants.PREF_USE_SYSTEM_IPTABLES, false))
+ {
+ //if the user wants us to use the built-in iptables, then we have to find it
+ File fileIpt = new File("/system/bin/iptables");
+
+ if (fileIpt.exists())
+ ipTablesPath = fileIpt.getAbsolutePath();
+ else
+ {
+
+ fileIpt = new File("/system/xbin/iptables");
+
+ if (fileIpt.exists())
+ return (ipTablesPath = fileIpt.getAbsolutePath());
+ else
+ {
+ //use the bundled version
+ ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ }
+ }
+ }
+ else
+ {
+ //use the bundled version
- public static int flushIptables(Context context) throws Exception {
+ ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ }
+
+ }
+
+ return ipTablesPath;
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ }
+
+ public int flushIptables(Context context) throws Exception {
+ String ipTablesPath = getIpTablesPath(context);
+
final StringBuilder script = new StringBuilder();
StringBuilder res = new StringBuilder();
@@ -124,16 +166,17 @@ public class TorTransProxy implements TorServiceConstants {
}
*/
- public static int testOwnerModule(Context context) throws Exception
+ public int testOwnerModule(Context context) throws Exception
{
+ TorBinaryInstaller.assertIpTablesBinaries(context, false);
+
boolean runRoot = true;
boolean waitFor = true;
- //redirectDNSResolvConf(); //not working yet
int torUid = context.getApplicationInfo().uid;
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@@ -161,7 +204,7 @@ public class TorTransProxy implements TorServiceConstants {
- public static int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
+ public int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
{
boolean runRoot = true;
@@ -169,7 +212,7 @@ public class TorTransProxy implements TorServiceConstants {
//redirectDNSResolvConf(); //not working yet
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@@ -261,7 +304,7 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
- public static int setTransparentProxyingByPort(Context context, int port) throws Exception
+ public int setTransparentProxyingByPort(Context context, int port) throws Exception
{
//android.os.Debug.waitForDebugger();
@@ -269,7 +312,7 @@ public class TorTransProxy implements TorServiceConstants {
//redirectDNSResolvConf(); //not working yet
//String baseDir = context.getDir("bin",0).getAbsolutePath() + '/';
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@@ -318,13 +361,13 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
- public static int enableTetheringRules (Context context) throws Exception
+ public int enableTetheringRules (Context context) throws Exception
{
boolean runRoot = true;
boolean waitFor = true;
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
@@ -360,14 +403,14 @@ public class TorTransProxy implements TorServiceConstants {
return code;
}
- public static int setTransparentProxyingAll(Context context) throws Exception
+ public int setTransparentProxyingAll(Context context) throws Exception
{
boolean runRoot = true;
boolean waitFor = true;
//redirectDNSResolvConf(); //not working yet
- String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
+ String ipTablesPath = getIpTablesPath(context);
StringBuilder script = new StringBuilder();
diff --git a/src/org/torproject/android/wizard/Permissions.java b/src/org/torproject/android/wizard/Permissions.java
index 151e6cb..5e17b67 100644
--- a/src/org/torproject/android/wizard/Permissions.java
+++ b/src/org/torproject/android/wizard/Permissions.java
@@ -164,7 +164,7 @@ public class Permissions extends Activity implements TorConstants {
if (hasRoot)
{
try {
- int resp = TorTransProxy.testOwnerModule(context);
+ int resp = new TorTransProxy().testOwnerModule(context);
if (resp < 0)
{
diff --git a/src/org/torproject/android/wizard/WizardHelper.java b/src/org/torproject/android/wizard/WizardHelper.java
index 18be47f..881d38d 100644
--- a/src/org/torproject/android/wizard/WizardHelper.java
+++ b/src/org/torproject/android/wizard/WizardHelper.java
@@ -93,17 +93,16 @@ public class WizardHelper implements TorConstants {
@Override
public void onClick(View view) {
+ boolean iCanHazRoot = TorServiceUtils.isRootPossible();
- boolean isRootPossible = TorServiceUtils.isRootPossible();
-
- if (isRootPossible)
+ if (iCanHazRoot)
{
try {
- int resp = TorTransProxy.testOwnerModule(context);
+ int resp = new TorTransProxy().testOwnerModule(context);
if (resp < 0)
{
- isRootPossible = false;
+ iCanHazRoot = false;
Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show();
Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available");
@@ -111,21 +110,12 @@ public class WizardHelper implements TorConstants {
} catch (Exception e) {
- isRootPossible = false;
+ iCanHazRoot = false;
Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e);
}
}
- /*
- * we shouldn't store root here, as this step is just chekcing to see if root is possible
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-
- Editor pEdit = prefs.edit();
- pEdit.putBoolean("has_root",hasRoot);
- pEdit.commit();
- */
-
- if (isRootPossible)
+ if (iCanHazRoot)
{
currentDialog.dismiss();
showWizardStep2Root();
1
0
commit ab44b54ac2dd67b385cba7c12bd66b697b85d7e7
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Thu Jan 12 21:08:37 2012 -0500
fixed debug log issue
---
src/org/torproject/android/service/TorService.java | 13 ++-----------
1 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java
index 2b1c91d..3954ab8 100644
--- a/src/org/torproject/android/service/TorService.java
+++ b/src/org/torproject/android/service/TorService.java
@@ -7,14 +7,10 @@
package org.torproject.android.service;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.IOException;
-import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
@@ -31,9 +27,7 @@ import org.torproject.android.R;
import org.torproject.android.TorConstants;
import org.torproject.android.Utils;
import org.torproject.android.settings.AppManager;
-import org.torproject.android.settings.ProcessSettingsAsyncTask;
-import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -43,17 +37,15 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
-import android.widget.Toast;
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
{
- public static boolean ENABLE_DEBUG_LOG = true;
+ public static boolean ENABLE_DEBUG_LOG = false;
private static int currentStatus = STATUS_OFF;
@@ -1305,8 +1297,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- //ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false);
- ENABLE_DEBUG_LOG = true;
+ ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false);
Log.i(TAG,"debug logging:" + ENABLE_DEBUG_LOG);
boolean useBridges = prefs.getBoolean(TorConstants.PREF_BRIDGES_ENABLED, false);
1
0
commit f9dd487389200593865cd2cbe59d34e27575270c
Author: Nathan Freitas <nathan(a)freitas.net>
Date: Thu Jan 12 21:08:51 2012 -0500
updated version number to 1.0.7-RC2
---
AndroidManifest.xml | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8a8231f..f03e3b5 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.torproject.android" android:versionName="0.2.3.10-alpha-orbot-1.0.7-RC1" android:versionCode="23">
+ package="org.torproject.android" android:versionName="0.2.3.10-alpha-orbot-1.0.7-RC2" android:versionCode="24">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
1
0