modified control port usage, updated startup UI screen, implemented all-app torification and more

svn:r22677
This commit is contained in:
Nathan Freitas 2010-07-23 11:10:00 +00:00
parent fd0b1375a6
commit a9083a3999
17 changed files with 548 additions and 364 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.torproject.android" package="org.torproject.android"
android:versionName="0.2.2.13-orbot-alpha-0.0.8" android:versionCode="2"> android:versionName="0.2.2.13-orbot-alpha-0.0.8" android:versionCode="8">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

View File

@ -10,5 +10,5 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=android-8 target=android-3
apk-configurations= apk-configurations=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -4,11 +4,15 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
> >
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/itemcheck"></CheckBox>
<ImageView android:id="@+id/itemicon" android:layout_width="48px" android:layout_height="48px"></ImageView> <ImageView android:id="@+id/itemicon" android:layout_width="48px" android:layout_height="48px"></ImageView>
<TextView android:layout_height="wrap_content" android:id="@+id/itemtext" android:text="uid:packages" android:layout_width="wrap_content" <TextView android:layout_height="wrap_content" android:id="@+id/itemtext" android:text="uid:packages"
android:textSize="18sp"></TextView> android:layout_width="220px" android:textSize="18sp"></TextView>
<CheckBox android:layout_width="48px" android:layout_height="48px" android:id="@+id/itemcheck"></CheckBox>
</LinearLayout> </LinearLayout>

View File

@ -1,17 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/bgtitanium">
<RelativeLayout android:id="@+id/layoutHeaderMain"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:background="#A0909090">
<ImageView android:id="@+id/radioModeImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0px"
android:layout_marginRight="3px"
android:gravity="right"
android:layout_toRightOf="@+id/radioModeLabel"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@drawable/tor25"
/>
<TextView android:id="@+id/radioModeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/powered_by"
android:layout_marginTop="9px"
android:layout_marginRight="0px"
android:gravity="right"
android:layout_toLeftOf="@+id/radioModeImage"
android:textColor="#333333" />
</RelativeLayout>
<ScrollView android:orientation="vertical" <ScrollView android:orientation="vertical"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:id="@+id/logScrollView" android:layout_width="fill_parent" android:id="@+id/logScrollView"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/messageLog" <TextView android:id="@+id/messageLog"
android:layout_height="fill_parent" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_x="2px" android:layout_x="2px"
android:layout_y="2px" android:layout_y="2px"
android:textSize="12px" android:textSize="12px"
android:background="#A0222222"
/> />
</ScrollView> </ScrollView>
</LinearLayout>

View File

@ -15,7 +15,7 @@
<string name="status_shutting_down">Orbot is shutting down</string> <string name="status_shutting_down">Orbot is shutting down</string>
<string name="tor_process_connecting">Starting Tor...</string> <string name="tor_process_connecting">Starting Tor...</string>
<string name="tor_process_connecting_step2">authenticating control connection...</string> <string name="tor_process_connecting_step2">Setting up control...</string>
<string name="tor_process_connecting_step3">complete.</string> <string name="tor_process_connecting_step3">complete.</string>
<string name="tor_process_connecting_step4">waiting.</string> <string name="tor_process_connecting_step4">waiting.</string>
@ -37,7 +37,7 @@
<string name="help_text_1">Orbot requires different configuration depending on the Android operating system version it is used on. <string name="help_text_1">Orbot requires different configuration depending on the Android operating system version it is used on.
Please visit https://www.torproject.org/docs/android.html for the latest information.</string> Please visit https://www.torproject.org/docs/android.html for the latest information.</string>
<string name="help_text_2">For non-rooted Android 1.x devices (G1, MyTouch3G, Hero): Please use the "ProxySurf" browser available in the Android Market, and set <string name="help_text_2">For non-rooted Android 1.x devices: Please use the "ProxySurf" browser available in the Android Market, and set
the HTTP Proxy to 127.0.0.1 and port 8118, for HTTP traffic only (HTTP/S will not work).</string> the HTTP Proxy to 127.0.0.1 and port 8118, for HTTP traffic only (HTTP/S will not work).</string>
<string name="help_text_3">For Instant Messaging, try "Beem" in the market, and set the SOCKS5 proxy to 127.0.0.1 / port 9050.</string> <string name="help_text_3">For Instant Messaging, try "Beem" in the market, and set the SOCKS5 proxy to 127.0.0.1 / port 9050.</string>
@ -52,4 +52,16 @@ and all DNS requests. This includes the built-in Browser, Gmail, YouTube and Map
<string name="menu_exit">Exit</string> <string name="menu_exit">Exit</string>
<string name="powered_by">powered by the Tor Project</string> <string name="powered_by">powered by the Tor Project</string>
<string name="press_to_start">- press to start -</string> <string name="press_to_start">- press to start -</string>
<string name="pref_trans_proxy_group">Transparent Proxying (Requires Root)</string>
<string name="pref_trans_proxy_title">Transparent Proxying</string>
<string name="pref_trans_proxy_summary">Automatic Torifying of Apps</string>
<string name="pref_transparent_all_title">Tor Everything</string>
<string name="pref_transparent_all_summary">Send traffic for all apps through Tor</string>
<string name="status_install_success">Tor binaries successfully installed!</string>
<string name="status_install_fail">The Tor binary files were unable to be installed. Please check the log and notify tor-assistants@torproject.org</string>
<string name="title_error">Application Error</string>
</resources> </resources>

View File

@ -1,20 +1,20 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Transparent Proxying (Requires Root)"> <PreferenceCategory android:title="@string/pref_trans_proxy_group">
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="false" android:defaultValue="false"
android:key="pref_transparent" android:key="pref_transparent"
android:title="Transparent Proxying" android:title="@string/pref_trans_proxy_title"
android:summary="Auto-Tor Proxying" android:summary="@string/pref_trans_proxy_summary"
android:enabled="true"/> android:enabled="true"/>
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="false" android:defaultValue="false"
android:key="pref_transparent_all" android:key="pref_transparent_all"
android:title="Auto-Proxy All Apps" android:summary="@string/pref_transparent_all_summary"
android:summary="Route All Traffic Through Tor" android:enabled="true"
android:enabled="true"/> android:title="@string/pref_transparent_all_title"/>
<Preference <Preference
android:defaultValue="" android:defaultValue=""

View File

@ -3,15 +3,11 @@
package org.torproject.android; package org.torproject.android;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.torproject.android.service.ITorService; import org.torproject.android.service.ITorService;
import org.torproject.android.service.ITorServiceCallback; import org.torproject.android.service.ITorServiceCallback;
import org.torproject.android.service.TorServiceUtils;
import org.torproject.android.service.TorTransProxy; import org.torproject.android.service.TorTransProxy;
import org.torproject.android.service.TorServiceConstants;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -36,28 +32,21 @@ import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.ArrayAdapter; import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class Orbot extends Activity implements OnClickListener, TorConstants, OnCheckedChangeListener public class Orbot extends Activity implements OnClickListener, TorConstants
{ {
/* Useful UI bits */ /* Useful UI bits */
private TextView txtMessageLog = null; //the full screen log view of Tor control messages private TextView txtMessageLog = null; //the full screen log view of Tor control messages
private TextView lblStatus = null; //the main text display widget private TextView lblStatus = null; //the main text display widget
private ImageView imgStatus = null; //the main touchable image for activating Orbot private ImageView imgStatus = null; //the main touchable image for activating Orbot
private ProgressDialog progressDialog; // private ProgressDialog progressDialog;
private ListView listApps;
private boolean showingSettings = false;
private MenuItem mItemOnOff = null; private MenuItem mItemOnOff = null;
/* Some tracking bits */ /* Some tracking bits */
@ -96,7 +85,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
mItem.setIcon(R.drawable.ic_menu_register); mItem.setIcon(R.drawable.ic_menu_register);
mItem = menu.add(0, 7, Menu.NONE, getString(R.string.menu_verify)); mItem = menu.add(0, 7, Menu.NONE, getString(R.string.menu_verify));
mItem.setIcon(R.drawable.ic_menu_goto); mItem.setIcon(R.drawable.ic_menu_check);
mItem = menu.add(0,6, Menu.NONE, getString(R.string.menu_log)); mItem = menu.add(0,6, Menu.NONE, getString(R.string.menu_log));
mItem.setIcon(R.drawable.ic_menu_reports); mItem.setIcon(R.drawable.ic_menu_reports);
@ -163,10 +152,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
{ {
showHelp(); showHelp();
} }
else if (item.getItemId() == 5)
{
showApps();
}
else if (item.getItemId() == 7) else if (item.getItemId() == 7)
{ {
//launch check.torproject.org //launch check.torproject.org
@ -257,22 +242,22 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll(); mNotificationManager.cancelAll();
updateStatus (""); //update the status, which checks the service status
if (showingSettings) if (mService != null)
{ {
try {
showingSettings = false; processSettings();
processSettings(); } catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -285,8 +270,10 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
startService(new Intent(INTENT_TOR_SERVICE)); startService(new Intent(INTENT_TOR_SERVICE));
bindService (); bindService ();
updateStatus (""); //updateStatus ("");
hasRoot = TorTransProxy.hasRootAccess();
} }
@ -298,8 +285,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
TorServiceUtils.saveAppSettings(this);
unbindService(); unbindService();
} }
@ -312,23 +297,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
{ {
bindService(); //connect the UI activity to the remote service bindService(); //connect the UI activity to the remote service
if (currentView == R.layout.layout_apps)
{
if (hasRoot)
{
TorServiceUtils.saveAppSettings(this);
if (enableTransparentProxy)
{
TorTransProxy.purgeNatIptables();
TorTransProxy.setDNSProxying();
TorTransProxy.setTransparentProxying(this, TorServiceUtils.getApps(this));
}
}
}
currentView = R.layout.layout_main; currentView = R.layout.layout_main;
setContentView(currentView); setContentView(currentView);
@ -352,61 +320,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
} }
private void loadApps ()
{
final TorifiedApp[] apps = TorServiceUtils.getApps(this);
Arrays.sort(apps, new Comparator<TorifiedApp>() {
public int compare(TorifiedApp o1, TorifiedApp o2) {
if (o1.isTorified() == o2.isTorified()) return o1.getName().compareTo(o2.getName());
if (o1.isTorified()) return -1;
return 1;
}
});
final LayoutInflater inflater = getLayoutInflater();
final ListAdapter adapter = new ArrayAdapter<TorifiedApp>(this,R.layout.layout_apps_item,R.id.itemtext,apps) {
public View getView(int position, View convertView, ViewGroup parent) {
ListEntry entry;
if (convertView == null) {
// Inflate a new view
convertView = inflater.inflate(R.layout.layout_apps_item, parent, false);
entry = new ListEntry();
entry.box = (CheckBox) convertView.findViewById(R.id.itemcheck);
entry.text = (TextView) convertView.findViewById(R.id.itemtext);
convertView.setTag(entry);
entry.box.setOnCheckedChangeListener(Orbot.this);
} else {
// Convert an existing view
entry = (ListEntry) convertView.getTag();
}
final TorifiedApp app = apps[position];
entry.text.setText(app.getName());
final CheckBox box = entry.box;
box.setTag(app);
box.setChecked(app.isTorified());
return convertView;
}
};
this.listApps.setAdapter(adapter);
}
/**
* Called an application is check/unchecked
*/
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final TorifiedApp app = (TorifiedApp) buttonView.getTag();
if (app != null) {
app.setTorified(isChecked);
}
TorServiceUtils.saveAppSettings(this);
}
private static class ListEntry { private static class ListEntry {
private CheckBox box; private CheckBox box;
@ -424,7 +337,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
versionName.setText(R.string.app_version); versionName.setText(R.string.app_version);
new AlertDialog.Builder(this) new AlertDialog.Builder(this)
.setTitle(getString(R.string.menu_info)) .setTitle(getString(R.string.button_about))
.setView(view) .setView(view)
.setNeutralButton(getString(R.string.button_help), new DialogInterface.OnClickListener() { .setNeutralButton(getString(R.string.button_help), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { public void onClick(DialogInterface dialog, int whichButton) {
@ -451,6 +364,25 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append(getString(R.string.help_text_1)); msg.append(getString(R.string.help_text_1));
msg.append("\n\n"); msg.append("\n\n");
if (hasRoot)
{
msg.append("Your device is ROOTED. Please enable the 'Transparent Proxying' setting to select which apps to send through Tor.");
}
else
{
msg.append("Your device is NOT rooted.\n");
msg.append(getString(R.string.help_text_5));
msg.append("\n\n");
msg.append(getString(R.string.not_anonymous_yet));
}
/*
msg.append(getString(R.string.help_text_2)); msg.append(getString(R.string.help_text_2));
msg.append("\n\n"); msg.append("\n\n");
msg.append(getString(R.string.help_text_3)); msg.append(getString(R.string.help_text_3));
@ -459,6 +391,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
msg.append("\n\n"); msg.append("\n\n");
msg.append(getString(R.string.help_text_5)); msg.append(getString(R.string.help_text_5));
msg.append("\n\n"); msg.append("\n\n");
*/
new AlertDialog.Builder(this) new AlertDialog.Builder(this)
@ -478,16 +411,14 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
.show(); .show();
} }
private void showApps () private void showHelpWizard ()
{ {
currentView = R.layout.layout_apps;
setContentView(currentView);
listApps = (ListView)findViewById(R.id.applistview);
loadApps(); //sshowAlert("Configure",getString(R.string.not_anonymous_yet));
} }
/* /*
* Show the message log UI * Show the message log UI
*/ */
@ -510,7 +441,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
private void showSettings () private void showSettings ()
{ {
showingSettings = true;
startActivity(new Intent(this, SettingsPreferences.class)); startActivity(new Intent(this, SettingsPreferences.class));
@ -520,7 +451,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
* Read in the Preferences and write then to the .torrc file * Read in the Preferences and write then to the .torrc file
*/ */
private void processSettings () /*
private void processSettingsOld ()
{ {
StringBuffer torrcText = new StringBuffer(); StringBuffer torrcText = new StringBuffer();
@ -566,6 +498,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
return; return;
} }
torrcText.append("UseBridges 1"); torrcText.append("UseBridges 1");
torrcText.append('\n'); torrcText.append('\n');
@ -645,6 +578,111 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
Utils.saveTextFile(TorServiceConstants.TORRC_INSTALL_PATH, torrcText.toString()); Utils.saveTextFile(TorServiceConstants.TORRC_INSTALL_PATH, torrcText.toString());
} }
*/
private void processSettings () throws RemoteException
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean useBridges = prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
boolean autoUpdateBridges = prefs.getBoolean(PREF_BRIDGES_UPDATED, false);
boolean becomeRelay = prefs.getBoolean(PREF_OR, false);
boolean ReachableAddresses = prefs.getBoolean(PREF_REACHABLE_ADDRESSES,false);
boolean enableTransparentProxy = prefs.getBoolean(PREF_TRANSPARENT, false);
String bridgeList = prefs.getString(PREF_BRIDGES_LIST,"");
if (useBridges)
{
if (bridgeList == null || bridgeList.length() == 0)
{
showAlert("Bridge Error","In order to use the bridge feature, you must enter at least one bridge IP address." +
"Send an email to bridges@torproject.org with the line \"get bridges\" by itself in the body of the mail from a gmail account.");
return;
}
mService.updateConfiguration("UseBridges", "1", false);
if (autoUpdateBridges)
{
mService.updateConfiguration("UpdateBridgesFromAuthority", "1", false);
}
else
{
mService.updateConfiguration("UpdateBridgesFromAuthority", "0", false);
}
String bridgeDelim = "\n";
if (bridgeList.indexOf(",") != -1)
{
bridgeDelim = ",";
}
StringTokenizer st = new StringTokenizer(bridgeList,bridgeDelim);
while (st.hasMoreTokens())
{
mService.updateConfiguration("bridge", st.nextToken(), false);
}
}
else
{
mService.updateConfiguration("UseBridges", "0", false);
}
try
{
if (ReachableAddresses)
{
String ReachableAddressesPorts =
prefs.getString(PREF_REACHABLE_ADDRESSES_PORTS, "*:80,*:443");
mService.updateConfiguration("ReachableAddresses", ReachableAddressesPorts, false);
}
}
catch (Exception e)
{
showAlert("Config Error","Your ReachableAddresses settings caused an exception!");
}
try
{
if (becomeRelay && (!useBridges) && (!ReachableAddresses))
{
int ORPort = Integer.parseInt(prefs.getString(PREF_OR_PORT, "9001"));
String nickname = prefs.getString(PREF_OR_NICKNAME, "Orbot");
mService.updateConfiguration("ORPort", ORPort + "", false);
mService.updateConfiguration("Nickname", nickname, false);
mService.updateConfiguration("ExitPolicy", "reject *:*", false);
}
}
catch (Exception e)
{
showAlert("Uh-oh!","Your relay settings caused an exception!");
return;
}
mService.saveConfiguration();
}
private void showAlert(String title, String msg) private void showAlert(String title, String msg)
{ {
@ -679,9 +717,14 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
if (torStatus == STATUS_ON) if (torStatus == STATUS_ON)
{ {
imgStatus.setImageResource(R.drawable.toron); imgStatus.setImageResource(R.drawable.toron);
imgStatus.clearAnimation();
lblStatus.setText(getString(R.string.status_activated)); lblStatus.setText(getString(R.string.status_activated));
showHelpWizard ();
/*
if (progressDialog != null) if (progressDialog != null)
{ {
@ -689,23 +732,28 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
progressDialog.hide(); progressDialog.hide();
progressDialog = null; progressDialog = null;
if (!enableTransparentProxy)
{ }*/
showAlert("Configure",getString(R.string.not_anonymous_yet));
}
}
// if (torServiceMsg != null && torServiceMsg.length()>0)
// Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
} }
else if (torStatus == STATUS_CONNECTING) else if (torStatus == STATUS_CONNECTING)
{ {
imgStatus.setImageResource(R.drawable.torstarting); imgStatus.setImageResource(R.drawable.torstarting);
lblStatus.setText(getString(R.string.status_starting_up));
/*
if (imgStatus.getAnimation()==null)
{
imgStatus.setAnimation(AnimationUtils.loadAnimation(this, R.anim.starting));
imgStatus.getAnimation().setRepeatMode(Animation.INFINITE);
imgStatus.getAnimation().setRepeatCount(Animation.INFINITE);
}*/
/*
if (progressDialog == null) if (progressDialog == null)
{ {
progressDialog = new ProgressDialog(this); progressDialog = new ProgressDialog(this);
@ -719,14 +767,18 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
} }
progressDialog.setMessage(torServiceMsg); progressDialog.setMessage(torServiceMsg);
*/
lblStatus.setText(torServiceMsg);
int idx = torServiceMsg.indexOf("%"); int idx = torServiceMsg.indexOf("%");
if (idx != -1) if (idx != -1)
{ {
String pComp = torServiceMsg.substring(idx-2,idx).trim(); String pComp = torServiceMsg.substring(idx-2,idx).trim();
int ipComp = Integer.parseInt(pComp); int ipComp = Integer.parseInt(pComp);
progressDialog.setProgress(ipComp); // progressDialog.setProgress(ipComp);
} }
@ -734,21 +786,16 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
else if (torStatus == STATUS_OFF) else if (torStatus == STATUS_OFF)
{ {
imgStatus.setImageResource(R.drawable.torstopping); imgStatus.setImageResource(R.drawable.torstopping);
imgStatus.clearAnimation();
lblStatus.setText(getString(R.string.status_shutting_down)); lblStatus.setText(getString(R.string.status_shutting_down));
//if (torServiceMsg != null && torServiceMsg.length()>0)
//Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
} }
else else
{ {
//if (torServiceMsg != null && torServiceMsg.length()>0)
//Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
/*
if (progressDialog != null) if (progressDialog != null)
{ {
@ -756,7 +803,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
progressDialog.hide(); progressDialog.hide();
progressDialog = null; progressDialog = null;
} }
*/
imgStatus.clearAnimation();
imgStatus.setImageResource(R.drawable.toroff); imgStatus.setImageResource(R.drawable.toroff);
lblStatus.setText(getString(R.string.status_disabled)); lblStatus.setText(getString(R.string.status_disabled));
@ -837,31 +885,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
} }
private void doTorSetup (boolean enabled)
{
if (enabled)
{
processSettings();
if (hasRoot && enableTransparentProxy)
{
TorTransProxy.setDNSProxying();
TorTransProxy.setTransparentProxying(this,TorServiceUtils.getApps(this));
}
}
else
{
if (hasRoot && enableTransparentProxy)
{
TorTransProxy.purgeNatIptables();
//TorRoot.setDNSProxying(false);
//TorRoot.setTransparentProxying(this,false);
}
}
}
/** /**
* This implementation is used to receive callbacks from the remote * This implementation is used to receive callbacks from the remote
* service. * service.
@ -876,21 +900,30 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
*/ */
public void statusChanged(String value) { public void statusChanged(String value) {
Message msg = mHandler.obtainMessage(BUMP_MSG); Message msg = mHandler.obtainMessage(STATUS_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value); msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
@Override
public void logMessage(String value) throws RemoteException {
Message msg = mHandler.obtainMessage(LOG_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg);
}
}; };
private static final int BUMP_MSG = 1; private static final int STATUS_MSG = 1;
private static final int ENABLE_TOR_MSG = 2; private static final int ENABLE_TOR_MSG = 2;
private static final int DISABLE_TOR_MSG = 3; private static final int DISABLE_TOR_MSG = 3;
private static final int LOG_MSG = 4;
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case BUMP_MSG: case STATUS_MSG:
String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG);
@ -899,16 +932,24 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
if (torServiceMsg.length() > 0 && torServiceMsg.charAt(0)!='>') if (torServiceMsg.length() > 0 && torServiceMsg.charAt(0)!='>')
updateStatus(torServiceMsg); updateStatus(torServiceMsg);
break;
case LOG_MSG:
String torLogMsg = (String)msg.getData().getString(HANDLER_TOR_MSG);
logBuffer.append(torLogMsg);
logBuffer.append('\n');
break; break;
case ENABLE_TOR_MSG: case ENABLE_TOR_MSG:
doTorSetup(true);
break; break;
case DISABLE_TOR_MSG: case DISABLE_TOR_MSG:
doTorSetup(false);
break; break;
default: default:
@ -958,7 +999,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
boolean mIsBound = false; boolean mIsBound = false;
boolean hasRoot = false; boolean hasRoot = false;
boolean enableTransparentProxy = false;
private void bindService () private void bindService ()
{ {
@ -967,8 +1007,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
mIsBound = true; mIsBound = true;
hasRoot = TorTransProxy.hasRootAccess();
} }

View File

@ -21,12 +21,25 @@ public class SettingsPreferences
private CheckBoxPreference prefcBTransProxyAll = null; private CheckBoxPreference prefcBTransProxyAll = null;
private Preference prefTransProxyApps = null; private Preference prefTransProxyApps = null;
protected void onCreate(Bundle savedInstanceState) { private boolean hasRoot = false;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
hasRoot = TorServiceUtils.hasRoot();
if (!TorServiceUtils.hasRoot()) }
@Override
protected void onResume() {
super.onResume();
if (!hasRoot)
{ {
getPreferenceScreen().getPreference(0).setEnabled(false); getPreferenceScreen().getPreference(0).setEnabled(false);
} }

View File

@ -6,6 +6,10 @@ package org.torproject.android;
public interface TorConstants { public interface TorConstants {
public final static String TAG = "Orbot"; public final static String TAG = "Orbot";
public final static String PREFS_KEY = "OrbotPrefs";
public final static String PREFS_KEY_TORIFIED = "PrefTord";
public final static int FILE_WRITE_BUFFER_SIZE = 2048; public final static int FILE_WRITE_BUFFER_SIZE = 2048;
@ -23,10 +27,12 @@ public interface TorConstants {
public final static String NEWLINE = "\n"; public final static String NEWLINE = "\n";
/*
public final static String TORRC_DEFAULT = public final static String TORRC_DEFAULT =
"SocksPort 9050\nSocksListenAddress 127.0.0.1\nSafeSocks 1\nDNSPort 5400\nLog debug syslog\nDataDirectory /data/data/org.torproject.android/cache\n" "SocksPort 9050\nSocksListenAddress 127.0.0.1\nSafeSocks 1\nDNSPort 5400\nLog debug syslog\nDataDirectory /data/data/org.torproject.android/cache\n"
+ "ControlPort 9051\nCookieAuthentication 1\nRelayBandwidthRate 20 KBytes\nRelayBandwidthBurst 20 KBytes\nAutomapHostsOnResolve 1\nTransPort 9040\n"; + "ControlPort 9051\nCookieAuthentication 1\nRelayBandwidthRate 20 KBytes\nRelayBandwidthBurst 20 KBytes\nAutomapHostsOnResolve 1\nTransPort 9040\n";
*/
public final static String INTENT_TOR_SERVICE = "org.torproject.android.service.TOR_SERVICE"; public final static String INTENT_TOR_SERVICE = "org.torproject.android.service.TOR_SERVICE";
public final static String HANDLER_TOR_MSG = "torServiceMsg"; public final static String HANDLER_TOR_MSG = "torServiceMsg";

View File

@ -6,19 +6,40 @@ import org.torproject.android.service.ITorServiceCallback;
* an interface for calling on to a remote service * an interface for calling on to a remote service
*/ */
interface ITorService { interface ITorService {
/** /**
* Often you want to allow a service to call back to its clients. * This allows Tor service to send messages back to the GUI
* This shows how to do so, by registering a callback interface with
* the service.
*/ */
void registerCallback(ITorServiceCallback cb); void registerCallback(ITorServiceCallback cb);
/** /**
* Remove a previously registered callback interface. * Remove registered callback interface.
*/ */
void unregisterCallback(ITorServiceCallback cb); void unregisterCallback(ITorServiceCallback cb);
/**
* Get a simple int status value for the state of Tor
**/
int getStatus(); int getStatus();
/**
* The profile value is the start/stop state for Tor
**/
void setProfile(int profile); void setProfile(int profile);
/**
* Set configuration
**/
boolean updateConfiguration (String name, String value, boolean saveToDisk);
/**
* Set configuration
**/
boolean saveConfiguration ();
/**
* Get current configuration value from torrc
*/
String getConfiguration (String name);
} }

View File

@ -7,7 +7,13 @@ package org.torproject.android.service;
*/ */
oneway interface ITorServiceCallback { oneway interface ITorServiceCallback {
/** /**
* Called when the service has a new value for you. * Called when the service has a something to display to the user
*/ */
void statusChanged(String value); void statusChanged(String value);
/**
* Called when the service has something to add to the log
*/
void logMessage(String value);
} }

View File

@ -15,25 +15,28 @@ import net.freehaven.tor.control.ConfigEntry;
import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection; import net.freehaven.tor.control.TorControlConnection;
import org.torproject.android.AppManager;
import org.torproject.android.Orbot; import org.torproject.android.Orbot;
import org.torproject.android.R; import org.torproject.android.R;
import android.app.AlertDialog;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteCallbackList; import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
public class TorService extends Service implements TorServiceConstants, Runnable, EventHandler public class TorService extends Service implements TorServiceConstants, Runnable, EventHandler
{ {
private static int currentStatus = STATUS_READY; private static int currentStatus = STATUS_READY;
private TorControlConnection conn = null; private TorControlConnection conn = null;
@ -44,7 +47,10 @@ public class TorService extends Service implements TorServiceConstants, Runnable
private static final int MAX_START_TRIES = 3; private static final int MAX_START_TRIES = 3;
private ArrayList<String> configBuffer = null;
private boolean hasRoot = false;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -57,6 +63,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
_torInstance = this; _torInstance = this;
hasRoot = TorServiceUtils.hasRoot();
} }
@ -130,19 +137,19 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
private void showToolbarNotification (String title, String notifyMsg, int icon) private void showToolbarNotification (String notifyMsg, int icon)
{ {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence tickerText = title; CharSequence tickerText = notifyMsg;
long when = System.currentTimeMillis(); long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when); Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext(); Context context = getApplicationContext();
CharSequence contentTitle = title; CharSequence contentTitle = getString(R.string.app_name);
CharSequence contentText = notifyMsg; CharSequence contentText = notifyMsg;
Intent notificationIntent = new Intent(this, Orbot.class); Intent notificationIntent = new Intent(this, Orbot.class);
@ -189,7 +196,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
catch (Exception e) catch (Exception e)
{ {
currentStatus = STATUS_OFF; currentStatus = STATUS_OFF;
this.showToolbarNotification("Orbot", "Unable to start Tor", R.drawable.tornotification); this.showToolbarNotification(getString(R.string.status_disabled), R.drawable.tornotification);
Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e); Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e);
} }
} }
@ -220,9 +227,11 @@ public class TorService extends Service implements TorServiceConstants, Runnable
currentStatus = STATUS_READY; currentStatus = STATUS_READY;
showToolbarNotification ("Orbot","Tor is disabled",R.drawable.tornotificationoff);
sendCallbackMessage("Tor is disabled"); showToolbarNotification (getString(R.string.status_disabled),R.drawable.tornotificationoff);
sendCallbackMessage(getString(R.string.status_disabled));
setupTransProxy(false);
} }
@ -254,7 +263,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (conn != null) if (conn != null)
{ {
try { try {
Log.i(TAG,"sending SHUTDOWN signal"); logNotice("sending SHUTDOWN signal to Tor process");
// conn.shutdownTor(arg0)
conn.signal("SHUTDOWN"); conn.signal("SHUTDOWN");
} catch (Exception e) { } catch (Exception e) {
Log.i(TAG,"error shutting down Tor via connection",e); Log.i(TAG,"error shutting down Tor via connection",e);
@ -269,7 +279,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
while (procId != -1) while (procId != -1)
{ {
Log.i(TAG,"Found Tor PID=" + procId + " - killing now..."); logNotice("Found Tor PID=" + procId + " - killing now...");
String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" }; String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" };
TorServiceUtils.doShellCommand(cmd,log, false, false); TorServiceUtils.doShellCommand(cmd,log, false, false);
@ -290,22 +300,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable
procId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH); procId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH);
} }
/*
//removing this for now
if (_webProxy != null)
{
try
{
//shutdown web proxy
_webProxy.stop();
_webProxy = null;
}
catch (Exception e)
{
Log.i(TAG,"error stopping web proxy",e);
}
}*/
} }
private void logNotice (String msg) private void logNotice (String msg)
@ -335,17 +329,17 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (torBinaryExists && privoxyBinaryExists) if (torBinaryExists && privoxyBinaryExists)
{ {
logNotice("Tor, Privoxy, IPtables binaries installed!"); logNotice(getString(R.string.status_install_success));
this.showToolbarNotification("Orbot Installed!", "Tor was successfully extracted and installed", R.drawable.tornotification); showToolbarNotification(getString(R.string.status_install_success), R.drawable.tornotification);
} }
else else
{ {
logNotice("Binary install FAILED!");
logNotice(getString(R.string.status_install_fail));
this.showToolbarNotification("Orbot FAIL!", "The binaries were unable to be installed", R.drawable.tornotification);
showAlert(getString(R.string.title_error),getString(R.string.status_install_fail));
return false; return false;
} }
@ -354,11 +348,11 @@ public class TorService extends Service implements TorServiceConstants, Runnable
StringBuilder log = new StringBuilder (); StringBuilder log = new StringBuilder ();
Log.i(TAG,"Setting permission on Tor binary"); logNotice("Setting permission on Tor binary");
String[] cmd1 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + TOR_BINARY_INSTALL_PATH}; String[] cmd1 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + TOR_BINARY_INSTALL_PATH};
TorServiceUtils.doShellCommand(cmd1, log, false, true); TorServiceUtils.doShellCommand(cmd1, log, false, true);
Log.i(TAG,"Setting permission on Privoxy binary"); logNotice("Setting permission on Privoxy binary");
String[] cmd2 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + PRIVOXY_INSTALL_PATH}; String[] cmd2 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + PRIVOXY_INSTALL_PATH};
TorServiceUtils.doShellCommand(cmd2, log, false, true); TorServiceUtils.doShellCommand(cmd2, log, false, true);
@ -367,17 +361,19 @@ public class TorService extends Service implements TorServiceConstants, Runnable
public void initTor () throws Exception public void initTor () throws Exception
{ {
// android.os.Debug.waitForDebugger();
currentStatus = STATUS_CONNECTING; currentStatus = STATUS_CONNECTING;
logNotice("Tor is starting up..."); logNotice(getString(R.string.status_starting_up));
this.sendCallbackMessage("starting...");
sendCallbackMessage(getString(R.string.status_starting_up));
killTorProcess (); killTorProcess ();
checkTorBinaries (); checkTorBinaries ();
new Thread() new Thread()
{ {
@ -401,6 +397,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
try { try {
runTorShellCmd(); runTorShellCmd();
setupTransProxy(true);
} catch (Exception e) { } catch (Exception e) {
Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e); Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e);
@ -440,7 +438,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
sendCallbackMessage("Couldn't start Tor process...\n" + log.toString()); sendCallbackMessage("Couldn't start Tor process...\n" + log.toString());
Thread.sleep(1000); Thread.sleep(1000);
sendCallbackMessage("Trying to start Tor again...\n" + log.toString()); sendCallbackMessage(getString(R.string.status_starting_up));
Thread.sleep(3000); Thread.sleep(3000);
attempts++; attempts++;
} }
@ -457,7 +455,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
logNotice("Tor process id=" + procId); logNotice("Tor process id=" + procId);
showToolbarNotification("Orbot starting...", "Tor is running", R.drawable.tornotification); showToolbarNotification(getString(R.string.status_starting_up), R.drawable.tornotification);
initControlConnection (); initControlConnection ();
} }
@ -489,7 +487,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (privoxyProcId == -1) if (privoxyProcId == -1)
{ {
this.sendCallbackMessage("Couldn't start Privoxy process... retrying...\n" + log); logNotice("Couldn't start Privoxy process... retrying...\n" + log);
Thread.sleep(3000); Thread.sleep(3000);
attempts++; attempts++;
} }
@ -506,18 +504,16 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
/*
public String generateHashPassword () public String generateHashPassword ()
{ {
/*
PasswordDigest d = PasswordDigest.generateDigest(); PasswordDigest d = PasswordDigest.generateDigest();
byte[] s = d.getSecret(); // pass this to authenticate byte[] s = d.getSecret(); // pass this to authenticate
String h = d.getHashedPassword(); // pass this to the Tor on startup. String h = d.getHashedPassword(); // pass this to the Tor on startup.
*/
return null; return null;
} }*/
public void initControlConnection () throws Exception, RuntimeException public void initControlConnection () throws Exception, RuntimeException
{ {
@ -534,7 +530,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
conn = TorControlConnection.getConnection(s); conn = TorControlConnection.getConnection(s);
// conn.authenticate(new byte[0]); // See section 3.2 // conn.authenticate(new byte[0]); // See section 3.2
sendCallbackMessage(baseMessage + ' ' + getString(R.string.tor_process_connecting_step2)); sendCallbackMessage(getString(R.string.tor_process_connecting_step2));
Log.i(TAG,"SUCCESS connected to control port"); Log.i(TAG,"SUCCESS connected to control port");
@ -542,13 +538,20 @@ public class TorService extends Service implements TorServiceConstants, Runnable
byte[] cookie = new byte[(int)fileCookie.length()]; byte[] cookie = new byte[(int)fileCookie.length()];
new FileInputStream(new File(TOR_CONTROL_AUTH_COOKIE)).read(cookie); new FileInputStream(new File(TOR_CONTROL_AUTH_COOKIE)).read(cookie);
conn.authenticate(cookie); conn.authenticate(cookie);
Log.i(TAG,"SUCCESS authenticated to control port"); Log.i(TAG,"SUCCESS authenticated to control port");
sendCallbackMessage(baseMessage + ' ' + getString(R.string.tor_process_connecting_step3)); sendCallbackMessage(getString(R.string.tor_process_connecting_step2) + getString(R.string.tor_process_connecting_step3));
addEventHandler(); addEventHandler();
if (configBuffer != null)
{
conn.setConf(configBuffer);
//conn.saveConf();
configBuffer = null;
}
break; //don't need to retry break; //don't need to retry
} }
catch (Exception ce) catch (Exception ce)
@ -568,29 +571,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
public void modifyConf () throws IOException
{
// Get one configuration variable.
List<ConfigEntry> options = conn.getConf("contact");
options.size();
// Get a set of configuration variables.
// List options = conn.getConf(Arrays.asList(new String[]{
// "contact", "orport", "socksport"}));
// Change a single configuration variable
conn.setConf("BandwidthRate", "1 MB");
// Change several configuration variables
conn.setConf(Arrays.asList(new String[]{
"HiddenServiceDir /home/tor/service1",
"HiddenServicePort 80",
}));
// Reset some variables to their defaults
conn.resetConf(Arrays.asList(new String[]{
"contact", "socksport"
}));
// Flush the configuration to disk.
conn.saveConf();
}
/* /*
private void getTorStatus () throws IOException private void getTorStatus () throws IOException
@ -640,7 +620,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
conn.setEventHandler(this); conn.setEventHandler(this);
conn.setEvents(Arrays.asList(new String[]{ conn.setEvents(Arrays.asList(new String[]{
"ORCONN", "CIRC", "NOTICE", "ERR"})); "ORCONN", "CIRC", "NOTICE", "WARN", "ERR"}));
// conn.setEvents(Arrays.asList(new String[]{ // conn.setEvents(Arrays.asList(new String[]{
// "DEBUG", "INFO", "NOTICE", "WARN", "ERR"})); // "DEBUG", "INFO", "NOTICE", "WARN", "ERR"}));
@ -701,7 +681,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1) if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1)
{ {
currentStatus = STATUS_ON; currentStatus = STATUS_ON;
showToolbarNotification ("Orbot","Tor is enabled",R.drawable.tornotification); showToolbarNotification (getString(R.string.status_activated),R.drawable.tornotification);
} }
@ -709,6 +689,15 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
private void showAlert(String title, String msg)
{
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(msg)
.setPositiveButton(android.R.string.ok, null)
.show();
}
public void newDescriptors(List<String> orList) { public void newDescriptors(List<String> orList) {
@ -783,6 +772,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
private Intent launchContext = null;
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
// Select the interface to return. If your service only implements // Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking // a single interface, you can just return it here without checking
@ -807,6 +798,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
* The IRemoteInterface is defined through IDL * The IRemoteInterface is defined through IDL
*/ */
private final ITorService.Stub mBinder = new ITorService.Stub() { private final ITorService.Stub mBinder = new ITorService.Stub() {
public void registerCallback(ITorServiceCallback cb) { public void registerCallback(ITorServiceCallback cb) {
if (cb != null) mCallbacks.register(cb); if (cb != null) mCallbacks.register(cb);
} }
@ -820,10 +812,103 @@ public class TorService extends Service implements TorServiceConstants, Runnable
public void setProfile (int profile) public void setProfile (int profile)
{ {
setTorProfile(profile); setTorProfile(profile);
sendCallbackMessage("");
} }
public String getConfiguration (String name)
{
try
{
if (conn != null)
{
StringBuffer result = new StringBuffer();
List<ConfigEntry> listCe = conn.getConf(name);
Iterator<ConfigEntry> itCe = listCe.iterator();
ConfigEntry ce = null;
while (itCe.hasNext())
{
ce = itCe.next();
result.append(ce.key);
result.append(' ');
result.append(ce.value);
result.append('\n');
}
return result.toString();
}
}
catch (IOException ioe)
{
Log.e(TAG, "Unable to update Tor configuration", ioe);
logNotice("Unable to update Tor configuration: " + ioe.getMessage());
}
return null;
}
/**
* Set configuration
**/
public boolean updateConfiguration (String name, String value, boolean saveToDisk)
{
try
{
if (conn != null)
{
conn.setConf(name, value);
if (saveToDisk)
{
// Flush the configuration to disk.
//conn.saveConf(); //NF 22/07/10 this is crashing right now
}
return true;
}
else
{
if (configBuffer == null)
configBuffer = new ArrayList<String>();
configBuffer.add(name + ' ' + value);
}
}
catch (IOException ioe)
{
Log.e(TAG, "Unable to update Tor configuration", ioe);
logNotice("Unable to update Tor configuration: " + ioe.getMessage());
}
return false;
}
public boolean saveConfiguration ()
{
try
{
if (conn != null)
{
// Flush the configuration to disk.
//this is doing bad things right now NF 22/07/10
//conn.saveConf();
return true;
}
}
catch (Exception ioe)
{
Log.e(TAG, "Unable to update Tor configuration", ioe);
logNotice("Unable to update Tor configuration: " + ioe.getMessage());
}
return false;
}
}; };
private ArrayList<String> callbackBuffer = new ArrayList<String>(); private ArrayList<String> callbackBuffer = new ArrayList<String>();
@ -864,4 +949,40 @@ public class TorService extends Service implements TorServiceConstants, Runnable
mCallbacks.finishBroadcast(); mCallbacks.finishBroadcast();
} }
private void setupTransProxy (boolean enabled)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
boolean transProxyAll = prefs.getBoolean("pref_transparent_all", false);
logNotice ("Transparent Proxying: " + enableTransparentProxy);
if (enabled)
{
if (hasRoot && enableTransparentProxy)
{
TorTransProxy.setDNSProxying();
TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll);
}
else
{
TorTransProxy.purgeNatIptables();
}
}
else
{
if (hasRoot)
{
TorTransProxy.purgeNatIptables();
}
}
}
} }

View File

@ -6,10 +6,12 @@ public interface TorServiceConstants {
public final static String TAG = "TOR_SERVICE"; public final static String TAG = "TOR_SERVICE";
public final static String TOR_APP_USERNAME = "org.torproject.android";
//home directory of Android application //home directory of Android application
public final static String TOR_HOME = "/data/data/org.torproject.android/"; public final static String TOR_HOME = "/data/data/" + TOR_APP_USERNAME + "/";
public final static String TOR_HOME_DATA_DIR = TOR_HOME + "cache/"; public final static String TOR_HOME_DATA_DIR = TOR_HOME + "data/";
//name of the tor C binary //name of the tor C binary
public final static String TOR_BINARY_ASSET_KEY = "tor"; public final static String TOR_BINARY_ASSET_KEY = "tor";

View File

@ -21,94 +21,10 @@ import android.util.Log;
public class TorServiceUtils implements TorServiceConstants { public class TorServiceUtils implements TorServiceConstants {
private static TorifiedApp[] apps = null;
private final static String PREFS_KEY = "OrbotPrefs"; private final static String PREFS_KEY = "OrbotPrefs";
private final static String PREFS_KEY_TORIFIED = "PrefTord"; private final static String PREFS_KEY_TORIFIED = "PrefTord";
public static void saveAppSettings (Context context)
{
if (apps == null)
return;
final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
StringBuilder tordApps = new StringBuilder();
for (int i = 0; i < apps.length; i++)
{
if (apps[i].isTorified())
{
tordApps.append(apps[i].getUsername());
tordApps.append("|");
}
}
Editor edit = prefs.edit();
edit.putString(PREFS_KEY_TORIFIED, tordApps.toString());
edit.commit();
}
public static TorifiedApp[] getApps (Context context)
{
if (apps != null)
return apps;
final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
String[] tordApps;
StringTokenizer st = new StringTokenizer(tordAppString,"|");
tordApps = new String[st.countTokens()];
int tordIdx = 0;
while (st.hasMoreTokens())
{
tordApps[tordIdx++] = st.nextToken();
}
Arrays.sort(tordApps);
//else load the apps up
PackageManager pMgr = context.getPackageManager();
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
apps = new TorifiedApp[lAppInfo.size()];
ApplicationInfo aInfo = null;
int appIdx = 0;
while (itAppInfo.hasNext())
{
aInfo = itAppInfo.next();
apps[appIdx] = new TorifiedApp();
apps[appIdx].setEnabled(aInfo.enabled);
apps[appIdx].setUid(aInfo.uid);
apps[appIdx].setUsername(pMgr.getNameForUid(apps[appIdx].getUid()));
apps[appIdx].setProcname(aInfo.processName);
apps[appIdx].setName(pMgr.getApplicationLabel(aInfo).toString());
// check if this application is allowed
if (Arrays.binarySearch(tordApps, apps[appIdx].getUsername()) >= 0) {
apps[appIdx].setTorified(true);
}
else
{
apps[appIdx].setTorified(false);
}
appIdx++;
}
return apps;
}
public static int findProcessId(String command) public static int findProcessId(String command)
{ {

View File

@ -93,7 +93,7 @@ public class TorTransProxy {
} }
} }
public static boolean setTransparentProxying(Context context, TorifiedApp[] apps) { public static boolean setTransparentProxyingByApp(Context context, TorifiedApp[] apps, boolean forceAll) {
String command = null; String command = null;
@ -101,14 +101,24 @@ public class TorTransProxy {
final StringBuilder script = new StringBuilder(); final StringBuilder script = new StringBuilder();
StringBuilder res = new StringBuilder();
int code = -1;
try { try {
int code;
for (int i = 0; i < apps.length; i++) for (int i = 0; i < apps.length; i++)
{ {
if (forceAll || apps[i].isTorified())
if (apps[i].isTorified())
{ {
if (apps[i].getUsername().equals(TorServiceConstants.TOR_APP_USERNAME))
{
Log.i(TAG,"detected Orbot app - will not transproxy");
continue;
}
Log.i(TAG,"enabling transproxy for app: " + apps[i].getUsername() + "(" + apps[i].getUid() + ")"); Log.i(TAG,"enabling transproxy for app: " + apps[i].getUsername() + "(" + apps[i].getUid() + ")");
//TCP //TCP
@ -129,17 +139,16 @@ public class TorTransProxy {
} }
} }
StringBuilder res = new StringBuilder();
String[] cmd = {script.toString()}; String[] cmd = {script.toString()};
code = TorServiceUtils.doShellCommand(cmd, res, true, true); code = TorServiceUtils.doShellCommand(cmd, res, true, true);
String msg = res.toString(); String msg = res.toString();
Log.e(TAG, msg); Log.e(TAG, msg);
} catch (Exception e) { } catch (Exception e) {
Log.w(TAG, "error refreshing iptables: " + e); Log.w(TAG, "error refreshing iptables: err=" + code + "; resp=" + res.toString(), e);
} }
return false; return false;
} }