diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d01b58e4..781581d0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,11 +1,11 @@ + package="org.torproject.android" android:versionName="0.2.3.1-orbot-alpha-1.0.5.3" android:versionCode="16"> - + @@ -28,8 +28,12 @@ - - + + + + + + diff --git a/BUILD b/BUILD index b2e4109e..b22aec4e 100644 --- a/BUILD +++ b/BUILD @@ -124,7 +124,13 @@ Finally, we'll make a proper Android package with ant and the Android App SDK: export APP_SDK=~/Documents/projects/android/android-sdk-linux_x86-1.5_r3/tools cd ../Orbot/ cp $DROID_ROOT/external/privoxy/privoxy-3.0.12-stable/privoxy assets/privoxy - cp $DROID_ROOT/external/tor/tor/src/or/tor assets/tor + +Now you need to split and copy the tor binary into res/raw. We split it into < 1M chunks +because some Android devices don't like resources larger than 1M. + + split --bytes=1m $DROID_ROOT/external/tor/tor/src/or/tor res/raw/tor + +Now build the Android app $APP_SDK/android update project --name Orbot --target 3 --path . ant release diff --git a/CHANGELOG b/CHANGELOG index fb368390..ffababfc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,14 @@ NOTE: Specific #s below correspond to Trac tickets logged and maintained at https://trac.torproject.org/projects/tor/ +1.0.5.3 +- added auto-tor of wireless and usb tethering +- integrated new setup wizard +- moved large tor binary into split multiple 1M segments to fix for devices with 1M resource limit + +1.0.5.1/.2 +- small updates to layout of main screen to fit smaller screens +- fixed preference setting of EntryNode torrc value + 1.0.5 - added exit node and "StrictExitNode" preference - fixed tor binary installation issue related to max resource size and compression diff --git a/WALKTHROUGH b/WALKTHROUGH new file mode 100644 index 00000000..c3107e65 --- /dev/null +++ b/WALKTHROUGH @@ -0,0 +1,90 @@ + +. +└── org + └── torproject + └── android + ├── AppManager.java + //this is what helps us track the app-by-app torification + //and gets the app name, icon, etc for display - we have some problems here + //in normalizing the icon on the list label + //some of this code came originally from DroidWall project (yay open source) + + ├── boot + │ └── OnbootBroadcastReceiver.java + //i think this is a dup now and should be removed + + ├── HiddenServiceManager.java + //empty! but at some point i thought it would be good to aggregate HS functions here + + ├── OnBootReceiver.java + //this is the class registered in AndroidManifest.xml to handle Onboot events + //to start Orbot/Tor when the device boots if the user has elected to do so - what kind of permissions does this require? + // + // BTW, this shows up as a fairly unintrusive type perm request now in Android / in older versions (1.6 and earlier) + // it was reported "as read / monitor phone state" and paranoid Tor-types didn't like the idea of it + // in 1.6+ it has a much better UX in terms of having a more granular permisions around boot since it is a very + // common request - ah , that's awesome, i think i remember seeing sth of this sorts when i was going through the guardianproject mailing list. iirc this is something ioerror wanted + + + ├── Orbot.java + //our wonderful main activity! + + ├── ProcessSettingsAsyncTask.java + //this was just added in 1.0.5.x, but it was meant to help stop the UI blocking while processing settings and prefs + //it uses the AsyncTask feature of Android, which seems to work pretty well + //for this type of non-time critical function you just want to happen in the background at some point soon-ish + + ├── SettingsPreferences.java + // Settings activity that loads the res/xml/preferences.xml resource up + // has some custom event handlng, onActivityResult callback result code's as well + // basically meant to tell Orbot activity if critical settings have been modified and whether + // those new settings should be applied (like iptables/transproxy changes) + + ├── TorConstants.java + // globals! well, constants! but yeah, just a place to put values we use a lot + + ├── TorifiedApp.java + // object to store a single app's metadata for display in UI and for transproxy process + + ├── Utils.java + // random methods that can be useful, a.k.a. another place to put stuff + + ├── WizardActivity.java + // our original attempt at wizard activity that didn't get far + + └── WizardHelper.java + // the helper class that manages the dialog based wizard + + ├── service //okay the Service subpackage! + + │ ├── Api.java + //this is more code taken from DroidWall, that needs to be cleaned up and paired down to just what we need it for + //this is related to 1.0.5.x changes with how we bundle and install our C binaries (tor, privoxy and iptables) + + │ ├── ITorService.aidl + // the android remote interface definition file; + // this is the remote interface which the Orbot activity gets a reference to + // and that in the TorService is instantiated as the "binder" + + │ ├── ITorServiceCallback.aidl + // this is the callback interface that the Orbot activity instantiates, and passes + // to the ITorService; reverse of ITorService in a sense + + │ ├── TorBinaryInstaller.java + // this handles installation of binaries; uses Api.java; // tied into Wizard as well + + │ ├── TorServiceConstants.java + // reusable constants for just the Service package + + │ ├── TorService.java + // the main might powerful service class; Orbot and TorService are the front and backends of this whole app + // should run as a remote service, but the manifest doesn't seem to indicate that at the moment + + │ ├── TorServiceUtils.java + //utility methods for the service; specificaly check for root and tools for finding processID of background binaries + + │ └── TorTransProxy.java + // all the code for iptables transproxying management + + + diff --git a/res/drawable/icon_firefox.png b/res/drawable/icon_firefox.png new file mode 100644 index 00000000..27b0cf48 Binary files /dev/null and b/res/drawable/icon_firefox.png differ diff --git a/res/drawable/icon_orweb.png b/res/drawable/icon_orweb.png deleted file mode 100755 index 679986f3..00000000 Binary files a/res/drawable/icon_orweb.png and /dev/null differ diff --git a/res/drawable/icon_otrchat.png b/res/drawable/icon_otrchat.png deleted file mode 100755 index 08171aba..00000000 Binary files a/res/drawable/icon_otrchat.png and /dev/null differ diff --git a/res/drawable/proxymob.png b/res/drawable/proxymob.png new file mode 100644 index 00000000..6e232194 Binary files /dev/null and b/res/drawable/proxymob.png differ diff --git a/res/drawable/warning.png b/res/drawable/warning.png new file mode 100644 index 00000000..42dc6d66 Binary files /dev/null and b/res/drawable/warning.png differ diff --git a/res/layout/layout_apps_item.xml b/res/layout/layout_apps_item.xml index 49939644..9d16efdd 100644 --- a/res/layout/layout_apps_item.xml +++ b/res/layout/layout_apps_item.xml @@ -5,12 +5,13 @@ android:layout_height="fill_parent" android:stretchColumns="1"> - + + diff --git a/res/layout/layout_main.xml b/res/layout/layout_main.xml index 6e51cbad..382d91fb 100644 --- a/res/layout/layout_main.xml +++ b/res/layout/layout_main.xml @@ -33,11 +33,17 @@ android:layout_toLeftOf="@+id/radioModeImage" android:textColor="#cccccc" /> - + - - + diff --git a/res/layout/layout_wizard_permissions.xml b/res/layout/layout_wizard_permissions.xml new file mode 100644 index 00000000..1ba5fec1 --- /dev/null +++ b/res/layout/layout_wizard_permissions.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/layout_wizard_root.xml b/res/layout/layout_wizard_root.xml index f71c284a..530d917c 100644 --- a/res/layout/layout_wizard_root.xml +++ b/res/layout/layout_wizard_root.xml @@ -1,29 +1,69 @@ - + android:layout_height="fill_parent"> + + + + + + + + + + - + + - - - - - - - + + + + + diff --git a/res/layout/layout_wizard_tips.xml b/res/layout/layout_wizard_tips.xml index 19aaef06..17ddb88d 100644 --- a/res/layout/layout_wizard_tips.xml +++ b/res/layout/layout_wizard_tips.xml @@ -1,29 +1,63 @@ - + android:layout_height="fill_parent"> + + + + + + + + + + - + + + android:paddingRight="20dip" + > - + + + + + + diff --git a/res/layout/scrollingtext_buttons_view.xml b/res/layout/scrollingtext_buttons_view.xml new file mode 100644 index 00000000..df599220 --- /dev/null +++ b/res/layout/scrollingtext_buttons_view.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/raw/tor b/res/raw/tor deleted file mode 100755 index 46aa1faa..00000000 Binary files a/res/raw/tor and /dev/null differ diff --git a/res/raw/toraa b/res/raw/toraa new file mode 100644 index 00000000..e8aac1ad Binary files /dev/null and b/res/raw/toraa differ diff --git a/res/raw/torab b/res/raw/torab new file mode 100644 index 00000000..c3bca22e Binary files /dev/null and b/res/raw/torab differ diff --git a/res/raw/torac b/res/raw/torac new file mode 100644 index 00000000..f04ee681 Binary files /dev/null and b/res/raw/torac differ diff --git a/res/raw/torad b/res/raw/torad new file mode 100644 index 00000000..ac4fb03a Binary files /dev/null and b/res/raw/torad differ diff --git a/res/raw/torrc b/res/raw/torrc index ba0b61e5..d1cd7fd3 100644 --- a/res/raw/torrc +++ b/res/raw/torrc @@ -7,5 +7,8 @@ RelayBandwidthRate 20 KBytes RelayBandwidthBurst 20 KBytes UseBridges 0 AutomapHostsOnResolve 1 +TransListenAddress 0.0.0.0 TransPort 9040 +DNSListenAddress 0.0.0.0 DNSPort 5400 + diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index db03116b..a4e22a2d 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -1,7 +1,6 @@ اوربوت (Orbot) - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 6c4f6ee5..c6d6321b 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 35286e7f..039062b1 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 1b5b18f3..9b9768de 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 828c0307..cd52e7db 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -1,7 +1,6 @@ اوربات - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 090ec5b2..4d1454d9 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -1,7 +1,6 @@ Орбот - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index fc08bc46..1bc5d654 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 6c600696..1d4dfb4d 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 9c72969c..7b42d3f3 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 25df707e..7925730e 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org https://check.torproject.org diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 03339bcc..1b66df49 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 7455eb73..5d5be5b8 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values-zh/strings.xml b/res/values-zh/strings.xml index 5a2a44cf..0354e0d4 100644 --- a/res/values-zh/strings.xml +++ b/res/values-zh/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org diff --git a/res/values/strings.xml b/res/values/strings.xml index 2a974f11..d9befc47 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,7 +1,6 @@ Orbot - 1.0.5 http://orbot/ http://check.torproject.org @@ -130,5 +129,42 @@ General Start Orbot on Boot Automatically start Orbot and connect Tor when your Android device boots - + + + Orbot brings Tor to Android \n\nTor helps you defend against a form of network surveillance that threatens privacy, confidential business activity and relationships, and state security known as traffic analysis + + Warning + Simply installing Orbot will not automatically anonymize your mobile traffic.\n\nPlease follow the following steps to get started + + Permissions + Orbot has detected that you have root permissions enabled. To enable \'Transparent Proxying\', please grant superuser privileges to Orbot + If you choose to continue without providing superuser privileges, make sure to use apps made to work with orbot + Orbot has detected that you do not have root permissions.\nTransparent Proxying is not possible without superuser privileges.\nMake sure to use apps that have been configured to work with Orbot + + Orbot configured Apps + Gibberbot - Secure instant messaging client for Android + Firefox - Android browser - To be used along with ProxyMob Add-on + ProxyMob - Simple Firefox Add-on for setting HTTP, SOCKS and SSL proxy settings + https://market.android.com/details?id=info.guardianproject.otr.app.im + https://market.android.com/details?id=org.mozilla.firefox + https://addons.mozilla.org/mobile/downloads/latest/251558/type:attachment/addon-251558-latest.xpi?src=addon-detail + + Transparent Proxy + Transparent Proxying allows you to redirect client requests without any special configuration or knowledge at the client. + (Check this box if you have no idea what we are talking about) + None + + Tor Tethering + Enable Tor Transparent Proxying for Wifi and USB Tethered Devices + + +Select Apps +Choose Apps to Route Through Tor + +Node Configuration +These are advanced settings that can reduce your anonymity + +Entrance Nodes +Fingerprints, nicks, countries and addresses for the first hop +Enter Entrance Nodes diff --git a/res/values/theme.xml b/res/values/theme.xml new file mode 100644 index 00000000..efc15c45 --- /dev/null +++ b/res/values/theme.xml @@ -0,0 +1,9 @@ + + + + #333 + + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 067cd740..a6c0f678 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -35,18 +35,27 @@ android:title="@string/pref_transparent_all_title"/> + + - + + android:title="Use Bridges" android:key="pref_bridges_enabled" android:summary="Enable alternate entrance nodes into the Tor Network"> - 0) - showAlert("Update", torServiceMsg, false); - - boolean showFirstTime = prefs.getBoolean("connect_first_time",true); - - if (showFirstTime) - { - - Editor pEdit = prefs.edit(); - - pEdit.putBoolean("connect_first_time",false); - - pEdit.commit(); - - showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true); - - } - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); - + hideProgressDialog(); + + String lblMsg = getString(R.string.status_activated); + //+ "\n" + torServiceMsg; + + lblStatus.setText(lblMsg); + + if (torServiceMsg.length() > 0) + showAlert("Update", torServiceMsg, false); + + boolean showFirstTime = prefs.getBoolean("connect_first_time",true); + + if (showFirstTime) + { + + Editor pEdit = prefs.edit(); + + pEdit.putBoolean("connect_first_time",false); + + pEdit.commit(); + + showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true); + + } + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_stop); + - } - else if (torStatus == STATUS_CONNECTING) - { - - imgStatus.setImageResource(R.drawable.torstarting); - - if (progressDialog != null) - progressDialog.setMessage(torServiceMsg); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); - - } - else if (torStatus == STATUS_OFF) - { - imgStatus.setImageResource(R.drawable.toroff); - + } + else if (torStatus == STATUS_CONNECTING) + { + + imgStatus.setImageResource(R.drawable.torstarting); + + if (progressDialog != null) + progressDialog.setMessage(torServiceMsg); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_stop); + + } + else if (torStatus == STATUS_OFF) + { + imgStatus.setImageResource(R.drawable.toroff); + - hideProgressDialog(); - - lblStatus.setText(getString(R.string.status_shutting_down)); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_start); - } - else - { + hideProgressDialog(); + + lblStatus.setText(getString(R.string.status_shutting_down)); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_start); + } + else + { - hideProgressDialog(); - - imgStatus.setImageResource(R.drawable.toroff); - lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start)); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_start); - - } - } - - } - catch (RemoteException e) - { - Log.e(TAG,"remote exception updating status",e); - } - + hideProgressDialog(); + + imgStatus.setImageResource(R.drawable.toroff); + lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start)); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_start); + + } + } + + } + catch (RemoteException e) + { + Log.e(TAG,"remote exception updating status",e); + } + } + // guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance + // to start Tor private void startTor () throws RemoteException { - - bindService(); - - mService.setProfile(TorServiceConstants.PROFILE_ON); //this means turn on - - imgStatus.setImageResource(R.drawable.torstarting); - lblStatus.setText(getString(R.string.status_starting_up)); - - Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); - mHandler.sendMessage(msg); - - - + // here we bind AGAIN - at some point i think we had to bind multiple times just in case + // but i would love to clarify, clean this up + bindService(); + + // this is a bit of a strange/old/borrowed code/design i used to change the service state + // not sure it really makes sense when what we want to say is just "startTor" + mService.setProfile(TorServiceConstants.PROFILE_ON); //this means turn on + + //here we update the UI which is a bit sloppy and mixed up code wise + //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense + imgStatus.setImageResource(R.drawable.torstarting); + lblStatus.setText(getString(R.string.status_starting_up)); + + + //we send a message here to the progressDialog i believe, but we can clarify that shortly + Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); + mHandler.sendMessage(msg); + + + } + //now we stop Tor! amazing! private void stopTor () throws RemoteException { - if (mService != null) - { - mService.setProfile(TorServiceConstants.PROFILE_OFF); - Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); - mHandler.sendMessage(msg); - } - + //if the service is bound, then turn it off, using the same "PROFILE_" technique + if (mService != null) + { + mService.setProfile(TorServiceConstants.PROFILE_OFF); + + //again this is related to the progress dialog or some other threaded UI object + Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); + mHandler.sendMessage(msg); + } + } - /* + /* * (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ - public boolean onLongClick(View view) { - - - try - { - - if (mService == null) - { - - } - else if (mService.getStatus() == STATUS_READY) - { - - createProgressDialog(getString(R.string.status_starting_up)); + public boolean onLongClick(View view) { + + + try + { + + if (mService == null) + { + + } + else if (mService.getStatus() == STATUS_READY) + { + + createProgressDialog(getString(R.string.status_starting_up)); - startTor(); - } - else - { - - stopTor(); - - } - - } - catch (Exception e) - { - Log.d(TAG,"error onclick",e); - } - - return true; - } - + startTor(); + } + else + { + + stopTor(); + + } + + } + catch (Exception e) + { + Log.d(TAG,"error onclick",e); + } + + return true; + } + /** * This implementation is used to receive callbacks from the remote - * service. + * service. + * + * If we have this setup probably, we shouldn't have to poll or query status + * to the service, as it should send it as it changes or when we bind/unbind to it + * from this activity */ private ITorServiceCallback mCallback = new ITorServiceCallback.Stub() { /** @@ -684,50 +751,55 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants * NOT be running in our main thread like most other things -- so, * to update the UI, we need to use a Handler to hop over there. */ + + //receive a new string vaule end-user displayable message from the ITorService public void statusChanged(String value) { - Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG); - msg.getData().putString(HANDLER_TOR_MSG, value); - mHandler.sendMessage(msg); + //pass it off to the progressDialog + Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG); + msg.getData().putString(HANDLER_TOR_MSG, value); + mHandler.sendMessage(msg); } - @Override - public void logMessage(String value) throws RemoteException { - - Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG); - msg.getData().putString(HANDLER_TOR_MSG, value); - mHandler.sendMessage(msg); - - } + @Override //this was when we displayed the log in the main Activity; can prob take this out now + public void logMessage(String value) throws RemoteException { + + Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG); + msg.getData().putString(HANDLER_TOR_MSG, value); + mHandler.sendMessage(msg); + + } }; +// this is what takes messages or values from the callback threads or other non-mainUI threads +//and passes them back into the main UI thread for display to the user private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case TorServiceConstants.STATUS_MSG: - String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); - - updateStatus(torServiceMsg); - + String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); + + updateStatus(torServiceMsg); + break; case TorServiceConstants.LOG_MSG: - - + + break; case TorServiceConstants.ENABLE_TOR_MSG: - - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; + + + updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); + + break; case TorServiceConstants.DISABLE_TOR_MSG: - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; - + + updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); + + break; + default: super.handleMessage(msg); } @@ -741,6 +813,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants /** * Class for interacting with the main interface of the service. */ + // this is the connection that gets called back when a successfull bind occurs + // we should use this to activity monitor unbind so that we don't have to call + // bindService() a million times + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { @@ -756,14 +832,15 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants try { mService.registerCallback(mCallback); + //again with the update status?!? :P updateStatus(""); if (autoStartOnBind) { - autoStartOnBind = false; - - startTor(); - + autoStartOnBind = false; + + startTor(); + } } catch (RemoteException e) { @@ -771,7 +848,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants // do anything with it; we can count on soon being // disconnected (and then reconnected if it can be restarted) // so there is no need to do anything here. - Log.d(TAG,"error registering callback to service",e); + Log.d(TAG,"error registering callback to service",e); } @@ -789,20 +866,26 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants } }; + //should move this up with all the other class variables boolean mIsBound = false; + //this is where we bind! private void bindService () { - bindService(new Intent(ITorService.class.getName()), + //since its auto create, we prob don't ever need to call startService + //also we should again be consistent with using either iTorService.class.getName() + //or the variable constant + bindService(new Intent(ITorService.class.getName()), mConnection, Context.BIND_AUTO_CREATE); - - mIsBound = true; + + mIsBound = true; } + //unbind removes the callback, and unbinds the service private void unbindService () { - if (mIsBound) { + if (mIsBound) { // If we have received the service, and hence registered with // it, then now is the time to unregister. if (mService != null) { @@ -813,7 +896,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants // There is nothing special we need to do if the service // has crashed. } - } + } + + //maybe needs this? + mService = null; // Detach our existing connection. unbindService(mConnection); @@ -821,26 +907,26 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants } } - + private void createProgressDialog (String msg) { - if (progressDialog != null && progressDialog.isShowing()) - return; - - progressDialog = ProgressDialog.show(Orbot.this, "", msg); - progressDialog.setCancelable(true); + if (progressDialog != null && progressDialog.isShowing()) + return; + + progressDialog = ProgressDialog.show(Orbot.this, "", msg); + progressDialog.setCancelable(true); } private void hideProgressDialog () { - if (progressDialog != null && progressDialog.isShowing()) - { - progressDialog.dismiss(); + if (progressDialog != null && progressDialog.isShowing()) + { + progressDialog.dismiss(); - } - - + } + + } } diff --git a/src/org/torproject/android/Permissions.java b/src/org/torproject/android/Permissions.java new file mode 100644 index 00000000..2ee4f7e3 --- /dev/null +++ b/src/org/torproject/android/Permissions.java @@ -0,0 +1,229 @@ +package org.torproject.android; + +import org.torproject.android.service.TorService; +import org.torproject.android.service.TorServiceUtils; +import org.torproject.android.service.TorTransProxy; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +public class Permissions extends Activity implements TorConstants { + + private Context context; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + context = this; + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_permissions); + + stepThree(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + private void stepThree(){ + + boolean hasRoot = TorServiceUtils.checkRootAccess(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean("has_root",hasRoot); + pEdit.commit(); + + if (hasRoot) + { + stepFourRoot(); + } + else + { + stepFour(); + } + + } + + private void stepFourRoot(){ + + String title = context.getString(R.string.wizard_permissions_title); + String msg1 = context.getString(R.string.wizard_permissions_root_msg1); + String msg2 = context.getString(R.string.wizard_permissions_root_msg2); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody1 = ((TextView)findViewById(R.id.WizardTextBody1)); + txtBody1.setText(msg1); + + + TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2)); + txtBody2.setText(msg2); + txtBody2.setVisibility(TextView.VISIBLE); + + Button grantPermissions = ((Button)findViewById(R.id.grantPermissions)); + grantPermissions.setVisibility(Button.VISIBLE); + + Button back = ((Button)findViewById(R.id.btnWizard1)); + Button next = ((Button)findViewById(R.id.btnWizard2)); + next.setEnabled(false); + + CheckBox consent = (CheckBox)findViewById(R.id.checkBox); + consent.setVisibility(CheckBox.VISIBLE); + + consent.setOnCheckedChangeListener(new OnCheckedChangeListener (){ + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + + pEdit.putBoolean(PREF_TRANSPARENT, !isChecked); + pEdit.putBoolean(PREF_TRANSPARENT_ALL, !isChecked); + + pEdit.commit(); + + Button next = ((Button)findViewById(R.id.btnWizard2)); + if(isChecked) + next.setEnabled(true); + else + next.setEnabled(false); + + + } + + }); + + + grantPermissions.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + //Check and Install iptables - TorTransProxy.testOwnerModule(this) + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean hasRoot = prefs.getBoolean("has_root",false); + + if (hasRoot) + { + try { + int resp = TorTransProxy.testOwnerModule(context); + + if (resp < 0) + { + hasRoot = false; + Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show(); + + Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available"); + stepFour(); + } + + } catch (Exception e) { + + hasRoot = false; + Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e); + } + } + + startActivityForResult(new Intent(getBaseContext(), ConfigureTransProxy.class), 1); + + + } + }); + + back.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); + } + }); + + + next.setOnClickListener(new View.OnClickListener() { + + + @Override + public void onClick(View v) { + startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1); + } + }); + + } + + private void stepFour(){ + + Toast.makeText(context, "NON ROOT FUNC", Toast.LENGTH_SHORT).show(); + String title = context.getString(R.string.wizard_permissions_title); + String msg = context.getString(R.string.wizard_permissions_msg); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody1)); + txtBody.setText(msg); + + Button btn1 = ((Button)findViewById(R.id.btnWizard1)); + Button btn2 = ((Button)findViewById(R.id.btnWizard2)); + btn2.setEnabled(true); + + + TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2)); + txtBody2.setVisibility(TextView.GONE); + + Button grantPermissions = ((Button)findViewById(R.id.grantPermissions)); + grantPermissions.setVisibility(Button.GONE); + + + CheckBox consent = (CheckBox)findViewById(R.id.checkBox); + consent.setVisibility(CheckBox.GONE); + + btn1.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); + } + }); + + btn2.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1); + } + }); + } + + +} \ No newline at end of file diff --git a/src/org/torproject/android/SettingsPreferences.java b/src/org/torproject/android/SettingsPreferences.java index 2eef5535..7cf90936 100644 --- a/src/org/torproject/android/SettingsPreferences.java +++ b/src/org/torproject/android/SettingsPreferences.java @@ -28,6 +28,9 @@ public class SettingsPreferences private boolean hasRoot = false; + + private final static int HIDDEN_SERVICE_PREF_IDX = 6; + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -77,12 +80,11 @@ public class SettingsPreferences } - int hiddenGroupIdx = 6; - prefHiddenServices = ((CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(0)); + prefHiddenServices = ((CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(0)); prefHiddenServices.setOnPreferenceClickListener(this); - ((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); - ((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(2).setEnabled(prefHiddenServices.isChecked()); + ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); + ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(2).setEnabled(prefHiddenServices.isChecked()); }; @@ -113,8 +115,8 @@ public class SettingsPreferences else if (preference == prefHiddenServices) { - ((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); - ((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(2).setEnabled(prefHiddenServices.isChecked()); + ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); + ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(2).setEnabled(prefHiddenServices.isChecked()); } else diff --git a/src/org/torproject/android/TipsAndTricks.java b/src/org/torproject/android/TipsAndTricks.java new file mode 100644 index 00000000..ebb5ad37 --- /dev/null +++ b/src/org/torproject/android/TipsAndTricks.java @@ -0,0 +1,139 @@ +package org.torproject.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + +public class TipsAndTricks extends Activity implements TorConstants { + + private Context context; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + context = this; + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_tips); + + stepFive(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + void stepFive(){ + + String title = context.getString(R.string.wizard_tips_title); + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + Button btn1 = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot); + + btn1.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.gibberbot_apk_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + Button btn2 = (Button)findViewById(R.id.WizardRootButtonInstallFirefox); + + btn2.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.firefox_apk_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + Button btn3 = (Button)findViewById(R.id.WizardRootButtonInstallProxyMob); + + btn3.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.proxymob_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } + }); + + Button back = ((Button)findViewById(R.id.btnWizard1)); + Button next = ((Button)findViewById(R.id.btnWizard2)); + + back.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1); + } + }); + + next.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + showWizardFinal(); + } + }); + + } + + private void showWizardFinal () + { + String title = null; + String msg = null; + + + title = context.getString(R.string.wizard_final); + msg = context.getString(R.string.wizard_final_msg); + + DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + context.startActivity(new Intent(context, Orbot.class)); + + } + }; + + + new AlertDialog.Builder(context) + .setIcon(R.drawable.icon) + .setTitle(title) + .setPositiveButton(R.string.button_close, ocListener) + .setMessage(msg) + .show(); + + + + + } +} \ No newline at end of file diff --git a/src/org/torproject/android/WizardActivity.java b/src/org/torproject/android/WizardActivity.java deleted file mode 100644 index 2a8bf33e..00000000 --- a/src/org/torproject/android/WizardActivity.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.torproject.android; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; - -public class WizardActivity extends Activity implements OnClickListener -{ - - protected void onCreate(Bundle savedInstanceState) - { - - this.setContentView(R.layout.layout_help); - - } - - - - @Override - protected void onStart() { - - super.onStart(); - - - } - - - - @Override - protected void onResume() { - super.onResume(); - - showStep1(); - } - - - - public void showStep1() - { - showDialog("Test","","foo","bar",this); - } - - private void showDialog (String title, String msg, String button1, String button2, OnClickListener ocListener) - { - - new AlertDialog.Builder(this) - .setInverseBackgroundForced(true) - .setTitle(title) - .setMessage(msg) - .setNeutralButton(button1, ocListener) - .setNegativeButton(button2, ocListener) - .show(); - - - } - - - - @Override - public void onClick(DialogInterface arg0, int arg1) { - - - } - - - -} diff --git a/src/org/torproject/android/WizardHelper.java b/src/org/torproject/android/WizardHelper.java index c3fa3c08..c85c50a0 100644 --- a/src/org/torproject/android/WizardHelper.java +++ b/src/org/torproject/android/WizardHelper.java @@ -215,7 +215,7 @@ public class WizardHelper implements TorConstants { LayoutInflater li = LayoutInflater.from(context); View view = li.inflate(R.layout.layout_wizard_tips, null); - Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallOtrchat); + Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallGibberbot); btn1.setOnClickListener(new OnClickListener() { @@ -228,7 +228,7 @@ public class WizardHelper implements TorConstants { } }); - Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallOrweb); + Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallFirefox); btn2.setOnClickListener(new OnClickListener() { @@ -241,7 +241,7 @@ public class WizardHelper implements TorConstants { } }); - Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonProxyHelp); + Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonInstallProxyMob); btn3.setOnClickListener(new OnClickListener() { @@ -277,7 +277,7 @@ public class WizardHelper implements TorConstants { public void showWizardRootConfigureTorification() { - + /* LayoutInflater li = LayoutInflater.from(context); View view = li.inflate(R.layout.layout_wizard_root, null); @@ -347,7 +347,7 @@ public class WizardHelper implements TorConstants { } }); - + */ } diff --git a/src/org/torproject/android/boot/OnbootBroadcastReceiver.java b/src/org/torproject/android/boot/OnbootBroadcastReceiver.java deleted file mode 100644 index 163e708c..00000000 --- a/src/org/torproject/android/boot/OnbootBroadcastReceiver.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.torproject.android.boot; - -import org.torproject.android.service.ITorService; -import org.torproject.android.service.TorService; -import org.torproject.android.service.TorServiceConstants; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.Log; - -public class OnbootBroadcastReceiver extends BroadcastReceiver implements TorServiceConstants { - @Override - public void onReceive(Context context, Intent intent) { - - Log.d(TAG, "received on boot notification"); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - boolean startOnBoot = prefs.getBoolean("pref_start_boot",true); - - Log.d(TAG, "startOnBoot:" + startOnBoot); - - if (startOnBoot) - { - Intent serviceIntent = new Intent(context,TorService.class); - serviceIntent.setAction("onboot"); - context.startService(serviceIntent); - } - - //bindService(new Intent(ITorService.class.getName()), - // mConnection, Context.BIND_AUTO_CREATE); - } - -} \ No newline at end of file diff --git a/src/org/torproject/android/service/Api.java b/src/org/torproject/android/service/IptablesManager.java similarity index 96% rename from src/org/torproject/android/service/Api.java rename to src/org/torproject/android/service/IptablesManager.java index fdd357b4..27817052 100644 --- a/src/org/torproject/android/service/Api.java +++ b/src/org/torproject/android/service/IptablesManager.java @@ -55,7 +55,7 @@ import android.widget.Toast; * Contains shared programming interfaces. * All iptables "communication" is handled by this class. */ -public final class Api { +public final class IptablesManager { /** application version string */ public static final String VERSION = "1.5.1-dev"; /** special application UID used to indicate "any application" */ @@ -861,8 +861,8 @@ public final class Api { return; } /* notify */ - final Intent message = new Intent(Api.STATUS_CHANGED_MSG); - message.putExtra(Api.STATUS_EXTRA, enabled); + final Intent message = new Intent(IptablesManager.STATUS_CHANGED_MSG); + message.putExtra(IptablesManager.STATUS_EXTRA, enabled); ctx.sendBroadcast(message); } /** diff --git a/src/org/torproject/android/service/TorBinaryInstaller.java b/src/org/torproject/android/service/TorBinaryInstaller.java index 9260c093..ba6ab3fa 100644 --- a/src/org/torproject/android/service/TorBinaryInstaller.java +++ b/src/org/torproject/android/service/TorBinaryInstaller.java @@ -20,160 +20,88 @@ import android.util.Log; public class TorBinaryInstaller implements TorServiceConstants { - String installPath; - String apkPath; + File installFolder; Context context; - public TorBinaryInstaller (Context context, String installPath, String apkPath) + public TorBinaryInstaller (Context context, File installFolder) { - this.installPath = installPath; - this.apkPath = apkPath; + this.installFolder = installFolder; + this.context = context; } - /* - * Start the binary installation if the file doesn't exist or is forced - */ - public void start (boolean force) - { - - boolean torBinaryExists = new File(installPath + TOR_BINARY_ASSET_KEY).exists(); - Log.d(TAG,"Tor binary exists=" + torBinaryExists); - - boolean privoxyBinaryExists = new File(installPath + PRIVOXY_ASSET_KEY).exists(); - Log.d(TAG,"Privoxy binary exists=" + privoxyBinaryExists); - - if (!(torBinaryExists && privoxyBinaryExists) || force) - installFromRaw (); - - - - } - // /* * Extract the Tor binary from the APK file using ZIP */ - private void installFromRaw () + public boolean installFromRaw () { + boolean result = false; - InputStream is = context.getResources().openRawResource(R.raw.tor); - streamToFile(is,installPath + TOR_BINARY_ASSET_KEY); - - - is = context.getResources().openRawResource(R.raw.torrc); - streamToFile(is,installPath + TORRC_ASSET_KEY); - - is = context.getResources().openRawResource(R.raw.privoxy); - streamToFile(is,installPath + PRIVOXY_ASSET_KEY); - - is = context.getResources().openRawResource(R.raw.privoxy_config); - streamToFile(is,installPath + PRIVOXYCONFIG_ASSET_KEY); - - - - Log.d(TAG,"SUCCESS: installed tor, privoxy binaries from raw"); - - - } - /* - * Extract the Tor binary from the APK file using ZIP - */ - private void installFromZip () - { - try { + InputStream is; - ZipFile zip = new ZipFile(apkPath); + is = context.getResources().openRawResource(R.raw.toraa); + streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, false); + + is = context.getResources().openRawResource(R.raw.torab); + streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true); + + is = context.getResources().openRawResource(R.raw.torac); + streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true); + + is = context.getResources().openRawResource(R.raw.torad); + streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true); + + is = context.getResources().openRawResource(R.raw.torrc); + streamToFile(is,installFolder, TORRC_ASSET_KEY, false); - ZipEntry zipen = zip.getEntry(ASSETS_BASE + TOR_BINARY_ASSET_KEY); - streamToFile(zip.getInputStream(zipen),installPath + TOR_BINARY_ASSET_KEY); - - zipen = zip.getEntry(ASSETS_BASE + TORRC_ASSET_KEY); - streamToFile(zip.getInputStream(zipen),installPath + TORRC_ASSET_KEY); - - zipen = zip.getEntry(ASSETS_BASE + PRIVOXY_ASSET_KEY); - streamToFile(zip.getInputStream(zipen),installPath + PRIVOXY_ASSET_KEY); - - zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY); - streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY); - - zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY); - streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY); - - - zip.close(); - - Log.d(TAG,"SUCCESS: unzipped tor, privoxy, iptables binaries from apk"); + is = context.getResources().openRawResource(R.raw.privoxy); + streamToFile(is,installFolder, PRIVOXY_ASSET_KEY, false); + is = context.getResources().openRawResource(R.raw.privoxy_config); + streamToFile(is,installFolder, PRIVOXYCONFIG_ASSET_KEY, false); + } catch (IOException ioe) { - Log.d(TAG,"FAIL: unable to unzip binaries from apk",ioe); - + Log.e(TAG, "unable to install tor binaries from raw", ioe); + return false; } + + + return true; } + /* * Write the inputstream contents to the file */ - private static void streamToFile(InputStream stm, String targetFilename) + private static boolean streamToFile(InputStream stm, File folder, String targetFilename, boolean append) throws IOException { - - FileOutputStream stmOut = null; - byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE]; int bytecount; - - File outFile = new File(targetFilename); + File outFile = new File(folder, targetFilename); + + FileOutputStream stmOut = new FileOutputStream(outFile, append); + + while ((bytecount = stm.read(buffer)) > 0) + + { + + stmOut.write(buffer, 0, bytecount); + + } + + stmOut.close(); + - try { - outFile.createNewFile(); - - stmOut = new FileOutputStream(outFile); - } - - catch (java.io.IOException e) - - { - - Log.d(TAG,"Error opening output file " + targetFilename,e); - - return; - } - - - - try - - { - - while ((bytecount = stm.read(buffer)) > 0) - - { - - stmOut.write(buffer, 0, bytecount); - - } - - stmOut.close(); - - } - - catch (java.io.IOException e) - - { - - Log.d(TAG,"Error writing output file '" + targetFilename + "': " + e.toString()); - - return; - - } + return true; } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 6d2eebdb..68fe6e2d 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ +/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ /* See LICENSE for licensing information */ package org.torproject.android.service; @@ -60,16 +60,13 @@ public class TorService extends Service implements TorServiceConstants, Runnable private ArrayList resetBuffer = null; - private String appHome; - private String appBinHome; - private String appDataHome; + // private String appHome; + private File appBinHome; + private File appDataHome; private String torBinaryPath; private String privoxyPath; - - private boolean hasRoot = false; - /** Called when the activity is first created. */ public void onCreate() { super.onCreate(); @@ -416,43 +413,37 @@ public class TorService extends Service implements TorServiceConstants, Runnable private boolean checkTorBinaries () throws Exception { - //android.os.Debug.waitForDebugger(); - //check and install iptables - Api.assertBinaries(this, true); + IptablesManager.assertBinaries(this, true); - File fileInstall = getDir("",0); - String subBinPath = "bin/"; - appHome = fileInstall.getAbsolutePath(); - appBinHome = appHome + subBinPath; - appDataHome = getCacheDir().getAbsolutePath() + '/'; - logNotice( "appHome=" + appHome); + appBinHome = getDir("bin",0); + appDataHome = getCacheDir(); + + // logNotice( "appHome=" + appHome); + + File fileTor = new File(appBinHome, TOR_BINARY_ASSET_KEY); + File filePrivoxy = new File(appBinHome, PRIVOXY_ASSET_KEY); + - torBinaryPath = appBinHome + TOR_BINARY_ASSET_KEY; - privoxyPath = appBinHome + PRIVOXY_ASSET_KEY; - logNotice( "checking Tor binaries"); - - boolean torBinaryExists = new File(torBinaryPath).exists(); - boolean privoxyBinaryExists = new File(privoxyPath).exists(); - if (!(torBinaryExists && privoxyBinaryExists)) + if (!(fileTor.exists() && filePrivoxy.exists())) { killTorProcess (); - TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome, appBinHome); - installer.start(true); + TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome); + boolean success = installer.installFromRaw(); - torBinaryExists = new File(torBinaryPath).exists(); - privoxyBinaryExists = new File(privoxyPath).exists(); - - if (torBinaryExists && privoxyBinaryExists) + if (success) { logNotice(getString(R.string.status_install_success)); showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification); + + torBinaryPath = fileTor.getAbsolutePath(); + privoxyPath = filePrivoxy.getAbsolutePath(); } else { @@ -470,6 +461,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable logNotice("Found Tor binary: " + torBinaryPath); logNotice("Found Privoxy binary: " + privoxyPath); + + torBinaryPath = fileTor.getAbsolutePath(); + privoxyPath = filePrivoxy.getAbsolutePath(); } StringBuilder log = new StringBuilder (); @@ -545,6 +539,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false); boolean transProxyAll = prefs.getBoolean("pref_transparent_all", false); boolean transProxyPortFallback = prefs.getBoolean("pref_transparent_port_fallback", false); + boolean transProxyTethering = prefs.getBoolean("pref_transparent_tethering", false); TorService.logMessage ("Transparent Proxying: " + enableTransparentProxy); @@ -581,6 +576,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable showAlert("Status", "Setting up app-based transparent proxying..."); code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this)); } + } TorService.logMessage ("TorTransProxy resp code: " + code); @@ -588,11 +584,22 @@ public class TorService extends Service implements TorServiceConstants, Runnable if (code == 0) { showAlert("Status", "Transparent proxying ENABLED"); + + + + if (transProxyTethering) + { + showAlert("Status", "TransProxy enabled for Tethering!"); + + TorTransProxy.enableTetheringRules(this); + } } else { showAlert("Status", "WARNING: error starting transparent proxying!"); } + + return true; @@ -618,9 +625,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable StringBuilder log = new StringBuilder(); - String torrcPath = appBinHome + TORRC_ASSET_KEY; + String torrcPath = new File(appBinHome, TORRC_ASSET_KEY).getAbsolutePath(); - String[] torCmd = {torBinaryPath + " DataDirectory " + appDataHome + " -f " + torrcPath + " || exit\n"}; + String[] torCmd = {torBinaryPath + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + torrcPath + " || exit\n"}; boolean runAsRootFalse = false; boolean waitForProcess = false; @@ -688,7 +695,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable { log = new StringBuilder(); - String privoxyConfigPath = appBinHome + PRIVOXYCONFIG_ASSET_KEY; + String privoxyConfigPath = new File(appBinHome, PRIVOXYCONFIG_ASSET_KEY).getAbsolutePath(); String[] cmds = { privoxyPath + " " + privoxyConfigPath + " &" }; @@ -753,7 +760,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable logNotice( "SUCCESS connected to control port"); - String torAuthCookie = appDataHome + TOR_CONTROL_COOKIE; + String torAuthCookie = new File(appDataHome, TOR_CONTROL_COOKIE).getAbsolutePath(); File fileCookie = new File(torAuthCookie); @@ -1137,18 +1144,12 @@ public class TorService extends Service implements TorServiceConstants, Runnable if (value == null || value.length() == 0) { resetBuffer.add(name); - /* - if (conn != null) - { - try { - conn.resetConf(Arrays.asList(new String[]{name})); - } catch (IOException e) { - Log.w(TAG, "Unable to reset conf",e); - } - }*/ + } else + { configBuffer.add(name + ' ' + value); + } return false; } @@ -1290,13 +1291,10 @@ public class TorService extends Service implements TorServiceConstants, Runnable 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", ""); + String entranceNodes = prefs.getString("pref_entrance_nodes", null); + String exitNodes = prefs.getString("pref_exit_nodes", null); + String excludeNodes = prefs.getString("pref_exclude_nodes", null); - - //boolean enableTransparentProxy = prefs.getBoolean(TorConstants.PREF_TRANSPARENT, false); - if (currentStatus == STATUS_ON) { //reset iptables rules in active mode @@ -1311,10 +1309,10 @@ public class TorService extends Service implements TorServiceConstants, Runnable } } - mBinder.updateConfiguration("EntranceNodes", entranceNodes, false); + mBinder.updateConfiguration("EntryNodes", entranceNodes, false); mBinder.updateConfiguration("ExitNodes", exitNodes, false); mBinder.updateConfiguration("ExcludeNodes", excludeNodes, false); - mBinder.updateConfiguration("StrictExitNodes", enableStrictNodes ? "1" : "0", false); + mBinder.updateConfiguration("StrictNodes", enableStrictNodes ? "1" : "0", false); if (useBridges) { @@ -1407,7 +1405,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable if (enableHiddenServices) { - mBinder.updateConfiguration("HiddenServiceDir",appDataHome, false); + mBinder.updateConfiguration("HiddenServiceDir",appDataHome.getAbsolutePath(), false); String hsPorts = prefs.getString("pref_hs_ports",""); diff --git a/src/org/torproject/android/service/TorServiceUtils.java b/src/org/torproject/android/service/TorServiceUtils.java index 2aa58e67..657d525d 100644 --- a/src/org/torproject/android/service/TorServiceUtils.java +++ b/src/org/torproject/android/service/TorServiceUtils.java @@ -17,7 +17,9 @@ public class TorServiceUtils implements TorServiceConstants { * Check if we have root access * @return boolean true if we have root */ - public static boolean checkRootAccess() { + /* + public static boolean checkRootAccess() { + StringBuilder log = new StringBuilder(); @@ -45,7 +47,40 @@ public class TorServiceUtils implements TorServiceConstants { TorService.logMessage("Could not acquire root permissions"); return false; } + */ + public static boolean checkRootAccess(){ + + StringBuilder log = new StringBuilder(); + + try { + + // Check if Superuser.apk exists + File file = new File("/system/app/Superuser.apk"); + + //Check for 'su' binary + String[] cmd = {"which su"}; + int exitCode = TorServiceUtils.doShellCommand(cmd, log, false, true); + + if (file.exists() && exitCode == 0) { + TorService.logMessage("Can acquire root permissions"); + return true; + + } + + } catch (IOException e) { + //this means that there is no root to be had (normally) so we won't log anything + TorService.logException("Error checking for root access",e); + + } + catch (Exception e) { + TorService.logException("Error checking for root access",e); + //this means that there is no root to be had (normally) + } + + TorService.logMessage("Could not acquire root permissions"); + return false; + } public static int findProcessId(String command) diff --git a/src/org/torproject/android/service/TorTransProxy.java b/src/org/torproject/android/service/TorTransProxy.java index 548dda64..de8ea83c 100644 --- a/src/org/torproject/android/service/TorTransProxy.java +++ b/src/org/torproject/android/service/TorTransProxy.java @@ -313,14 +313,12 @@ public class TorTransProxy implements TorServiceConstants { return code; } - public static int enableWifiHotspotRules (Context context) throws Exception + public static int enableTetheringRules (Context context) throws Exception { boolean runRoot = true; boolean waitFor = true; - //redirectDNSResolvConf(); //not working yet - String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); StringBuilder script = new StringBuilder(); @@ -328,25 +326,24 @@ public class TorTransProxy implements TorServiceConstants { StringBuilder res = new StringBuilder(); int code = -1; - script.append(ipTablesPath); - script.append(" -I FORWARD"); - script.append(" -m state --state ESTABLISHED,RELATED -j ACCEPT"); - script.append(" || exit\n"); - - script.append(ipTablesPath); - script.append(" -I FORWARD"); - script.append(" -j ACCEPT"); - script.append(" || exit\n"); - - /* - script.append(ipTablesPath); - script.append(" -P FORWARD DROP"); - script.append(" || exit\n"); - */ - - script.append(ipTablesPath); - script.append(" -t nat -I POSTROUTING -j MASQUERADE"); - script.append(" || exit\n"); + String[] hwinterfaces = {"usb0","wl0.1"}; + + for (int i = 0; i < hwinterfaces.length; i++) + { + 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(TOR_DNS_PORT); + script.append(" || exit\n"); + + script.append(ipTablesPath); + script.append(" -t nat -A PREROUTING -i "); + script.append(hwinterfaces[i]); + script.append(" -p tcp -j REDIRECT --to-ports "); + script.append(TOR_TRANSPROXY_PORT); + script.append(" || exit\n"); + } String[] cmdAdd = {script.toString()}; @@ -374,8 +371,6 @@ public class TorTransProxy implements TorServiceConstants { purgeIptables(context); - enableWifiHotspotRules(context); - int torUid = context.getApplicationInfo().uid; // Set up port redirection