[tor-commits] [orbot/master] update jtorctl to 0.4 and add more tor DataDirectory corruption debug capabilties

n8fr8 at torproject.org n8fr8 at torproject.org
Mon Aug 24 21:02:52 UTC 2020


commit 74fce069df64b5cd35003c8bad75cc0f0a2622d2
Author: n8fr8 <nathan at guardianproject.info>
Date:   Wed Aug 12 14:53:24 2020 -0400

    update jtorctl to 0.4 and add more tor DataDirectory corruption debug capabilties
---
 .../org/torproject/android/OrbotMainActivity.java  |  29 ++++++
 orbotservice/src/main/AndroidManifest.xml          |   2 +
 .../torproject/android/service/OrbotService.java   | 112 +++++++++++++++------
 .../android/service/TorEventHandler.java           |  22 ++--
 .../org/torproject/android/service/util/Utils.java |  92 ++++++++++++++++-
 5 files changed, 218 insertions(+), 39 deletions(-)

diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 1d2e1493..af311c34 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -5,6 +5,7 @@ package org.torproject.android;
 
 import android.app.AlertDialog;
 
+import android.app.Application;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -19,7 +20,9 @@ import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.net.VpnService;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
 import android.text.TextUtils;
@@ -39,6 +42,7 @@ import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.RequiresApi;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.widget.SwitchCompat;
 import androidx.appcompat.widget.Toolbar;
@@ -54,6 +58,7 @@ import org.torproject.android.service.OrbotConstants;
 import org.torproject.android.service.OrbotService;
 import org.torproject.android.service.TorServiceConstants;
 import org.torproject.android.service.util.Prefs;
+import org.torproject.android.service.util.Utils;
 import org.torproject.android.service.vpn.VpnConstants;
 import org.torproject.android.service.vpn.VpnPrefs;
 import org.torproject.android.service.vpn.VpnUtils;
@@ -77,6 +82,7 @@ import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Locale;
 import java.util.StringTokenizer;
 
@@ -89,6 +95,7 @@ import static org.torproject.android.MainConstants.URL_TOR_CHECK;
 import static org.torproject.android.service.TorServiceConstants.ACTION_START;
 import static org.torproject.android.service.TorServiceConstants.ACTION_START_VPN;
 import static org.torproject.android.service.TorServiceConstants.ACTION_STOP_VPN;
+import static org.torproject.android.service.TorServiceConstants.DIRECTORY_TOR_DATA;
 import static org.torproject.android.service.vpn.VpnPrefs.PREFS_KEY_TORIFIED;
 
 public class OrbotMainActivity extends AppCompatActivity implements OrbotConstants {
@@ -198,6 +205,11 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
         VpnUtils.getSharedPrefs(getApplicationContext()).edit().putInt(VpnPrefs.PREFS_DNS_PORT,
                 VpnConstants.TOR_DNS_PORT_DEFAULT).apply();
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            if (Prefs.useDebugLogging())
+                exportTorData();
+        }
+
     }
 
     private void sendIntentToService(final String action) {
@@ -1250,4 +1262,21 @@ public class OrbotMainActivity extends AppCompatActivity implements OrbotConstan
         llBoxShortcuts.addView(tv);
     }
 
+    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+    private void exportTorData ()
+    {
+        File fileTorData = null;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+            fileTorData = new File(getDataDir(),DIRECTORY_TOR_DATA);
+        }
+        else {
+            fileTorData = getDir(DIRECTORY_TOR_DATA, Application.MODE_PRIVATE);
+        }
+
+        File fileZip = new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),"orbotdata" + new Date().getTime() + ".zip");
+        Utils.zipFileAtPath(fileTorData.getAbsolutePath(), fileZip.getAbsolutePath());
+        fileZip.setReadable(true,false);
+        Log.d (TAG,"debugdata: " + fileZip.getAbsolutePath());
+
+    }
 }
diff --git a/orbotservice/src/main/AndroidManifest.xml b/orbotservice/src/main/AndroidManifest.xml
index 801a9c18..962fe09c 100644
--- a/orbotservice/src/main/AndroidManifest.xml
+++ b/orbotservice/src/main/AndroidManifest.xml
@@ -1,4 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.torproject.android.service">
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
 </manifest>
diff --git a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
index 7bf6ade0..a3aa2d98 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
@@ -28,6 +28,8 @@ import android.database.Cursor;
 import android.net.Uri;
 import android.net.VpnService;
 import android.os.Build;
+import android.os.Environment;
+import android.os.Handler;
 import android.os.IBinder;
 import android.provider.BaseColumns;
 import androidx.annotation.RequiresApi;
@@ -39,8 +41,10 @@ import android.util.Log;
 import com.jaredrummler.android.shell.CommandResult;
 
 import net.freehaven.tor.control.ConfigEntry;
+import net.freehaven.tor.control.RawEventListener;
 import net.freehaven.tor.control.TorControlConnection;
 
+import org.apache.commons.io.FileUtils;
 import org.torproject.android.service.util.CustomShell;
 import org.torproject.android.service.util.CustomTorResourceInstaller;
 import org.torproject.android.service.util.DummyActivity;
@@ -66,9 +70,12 @@ import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.net.Socket;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -133,6 +140,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
     OrbotVpnManager mVpnManager;
 
+    Handler mHandler;
+
     public static final class HiddenService implements BaseColumns {
         public static final String NAME = "name";
         public static final String PORT = "port";
@@ -174,10 +183,12 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
     public void debug(String msg)
     {
+
+        Log.d(OrbotConstants.TAG,msg);
+
         if (Prefs.useDebugLogging())
         {
-            Log.d(OrbotConstants.TAG,msg);
-            sendCallbackLogMessage(msg);
+           sendCallbackLogMessage(msg);
 
         }
     }
@@ -535,6 +546,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
         try
         {
+            mHandler = new Handler();
+
             appBinHome = getFilesDir();//getDir(TorServiceConstants.DIRECTORY_TOR_BINARY, Application.MODE_PRIVATE);
             if (!appBinHome.exists())
                 appBinHome.mkdirs();
@@ -549,6 +562,20 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
             if (!appCacheHome.exists())
                 appCacheHome.mkdirs();
 
+
+            debug("listing files in DataDirectory: " + appCacheHome.getAbsolutePath());
+            Iterator<File> files = FileUtils.iterateFiles(appCacheHome,null,true);
+            while (files.hasNext())
+            {
+                File fileNext = files.next();
+                debug(fileNext.getAbsolutePath()
+                        + " length=" + fileNext.length()
+                        + " rw=" + fileNext.canRead() + "/" + fileNext.canWrite()
+                        + " lastMod=" + new Date(fileNext.lastModified()).toLocaleString()
+
+                );
+            }
+
             fileTorRc = new File(appBinHome, TORRC_ASSET_KEY);
             fileControlPort = new File(getFilesDir(), TOR_CONTROL_PORT_FILE);
             filePid = new File(getFilesDir(), TOR_PID_FILE);
@@ -680,8 +707,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
         extraLines.append("PidFile").append(' ').append(filePid.getCanonicalPath()).append('\n');
 
-       //extraLines.append("RunAsDaemon 1").append('\n');
-       //extraLines.append("AvoidDiskWrites 1").append('\n');
+        extraLines.append("RunAsDaemon 1").append('\n');
+        extraLines.append("AvoidDiskWrites 1").append('\n');
         
          String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS, (TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT));
 
@@ -756,8 +783,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
         extraLines.append("VirtualAddrNetwork 10.192.0.0/10").append('\n');
         extraLines.append("AutomapHostsOnResolve 1").append('\n');
 
-        extraLines.append("DormantClientTimeout 10 minutes").append('\n');
-        extraLines.append("DormantOnFirstStartup 0").append('\n');
+       // extraLines.append("DormantClientTimeout 10 minutes").append('\n');
+       // extraLines.append("DormantOnFirstStartup 0").append('\n');
 
         extraLines.append("DisableNetwork 0").append('\n');
 
@@ -992,10 +1019,10 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
         sendCallbackLogMessage(getString(R.string.status_starting_up));
 
-        String torCmdString = fileTor.getCanonicalPath()
-                + " DataDirectory " + appCacheHome.getCanonicalPath()
-                + " --defaults-torrc " + fileTorRc.getCanonicalPath()
-                + " -f " + fileTorrcCustom.getCanonicalPath();
+        String torCmdString = fileTor.getAbsolutePath()
+                + " DataDirectory " + appCacheHome.getAbsolutePath()
+                + " --defaults-torrc " + fileTorRc.getAbsolutePath()
+                + " -f " + fileTorrcCustom.getAbsolutePath();
 
         int exitCode = -1;
 
@@ -1122,16 +1149,42 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
                     if (fileCookie.exists())
                     {
 
+                        // We extend NullEventHandler so that we don't need to provide empty
+                        // implementations for all the events we don't care about.
+                        logNotice( "adding control port event handler");
+
+                        if (Prefs.useDebugLogging()) {
+                            conn.setDebugging(System.out);
+                            conn.addRawEventListener(new RawEventListener() {
+                                @Override
+                                public void onEvent(String keyword, String data) {
+
+
+                                    debug(keyword + ": " + data);
+                                }
+                            });
+                        }
+
+                        conn.setEventHandler(mEventHandler);
+
+                        logNotice( "SUCCESS added control port event handler");
                         byte[] cookie = new byte[(int)fileCookie.length()];
                         DataInputStream fis = new DataInputStream(new FileInputStream(fileCookie));
                         fis.read(cookie);
                         fis.close();
                         conn.authenticate(cookie);
 
-                        addEventHandler();
-
                         logNotice( "SUCCESS - authenticated to control port.");
 
+                 //       conn.setEvents(Arrays.asList(new String[]{"DEBUG","STATUS_CLIENT","STATUS_GENERAL","BW"}));
+
+                        if (Prefs.useDebugLogging())
+                            conn.setEvents(Arrays.asList(new String[]{
+                                "CIRC","STREAM", "ORCONN" , "BW" , "INFO" ,"NOTICE" , "WARN" , "DEBUG","ERR" , "NEWDESC" , "ADDRMAP"}));
+                        else
+                            conn.setEvents(Arrays.asList(new String[]{
+                                    "CIRC","STREAM", "ORCONN" , "BW" , "NOTICE" ,"ERR" , "NEWDESC" , "ADDRMAP"}));
+
                       //  sendCallbackLogMessage(getString(R.string.tor_process_starting) + ' ' + getString(R.string.tor_process_complete));
 
                         String torProcId = conn.getInfo("process/pid");
@@ -1169,6 +1222,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
 
                         sendCallbackPorts(mPortSOCKS, mPortHTTP, mPortDns, mPortTrans);
 
+                        setTorNetworkEnabled(true);
 
                         return Integer.parseInt(torProcId);
 
@@ -1221,20 +1275,6 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
         return result;
     }
 
-    public void addEventHandler () throws Exception {
-           // We extend NullEventHandler so that we don't need to provide empty
-           // implementations for all the events we don't care about.
-           // ...
-        logNotice( "adding control port event handler");
-
-
-        conn.setEvents(Arrays.asList(new String[]{
-                "CIRC","STREAM", "ORCONN" , "BW" , "INFO" ,"NOTICE" , "WARN" , "ERR" , "NEWDESC" , "ADDRMAP"}));
-
-        conn.setEventHandler(mEventHandler);
-
-        logNotice( "SUCCESS added control port event handler");
-    }
 
         /**
          * Returns the port number that the HTTP proxy is running on
@@ -1453,15 +1493,23 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
         LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
     }
 
-    private void sendCallbackLogMessage (String logMessage)
+    private void sendCallbackLogMessage (final String logMessage)
     {
 
-        Intent intent = new Intent(LOCAL_ACTION_LOG);
-          // You can also include some extra data.
-          intent.putExtra(LOCAL_EXTRA_LOG, logMessage);
-	      intent.putExtra(EXTRA_STATUS, mCurrentStatus);
+        mHandler.post(new Runnable () {
+
+            public void run ()
+            {
+
+                Intent intent = new Intent(LOCAL_ACTION_LOG);
+                // You can also include some extra data.
+                intent.putExtra(LOCAL_EXTRA_LOG, logMessage);
+                intent.putExtra(EXTRA_STATUS, mCurrentStatus);
+
+                LocalBroadcastManager.getInstance(OrbotService.this).sendBroadcast(intent);
+            }
 
-          LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
+        });
 
     }
 
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java b/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
index ce7a6633..7cebd794 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
@@ -57,7 +57,11 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
 
     @Override
     public void message(String severity, String msg) {
-        mService.logNotice(severity + ": " + msg);
+
+        if (severity.equalsIgnoreCase("debug"))
+            mService.debug(severity + ": " + msg);
+        else
+            mService.logNotice(severity + ": " + msg);
     }
 
     @Override
@@ -89,7 +93,7 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
         sb.append("): ");
         sb.append(status);
 
-        mService.logNotice(sb.toString());
+        mService.debug(sb.toString());
     }
 
     @Override
@@ -104,10 +108,12 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
         mService.logNotice(sb.toString());
     }
 
+    private final static int BW_THRESDHOLD = 10000;
+
     @Override
     public void bandwidthUsed(long read, long written) {
 
-        if (read != lastRead || written != lastWritten)
+        if (lastWritten > BW_THRESDHOLD || lastRead > BW_THRESDHOLD)
         {
             StringBuilder sb = new StringBuilder();
             sb.append(formatCount(read));
@@ -125,12 +131,16 @@ public class TorEventHandler implements EventHandler, TorServiceConstants {
 
             mTotalTrafficWritten += written;
             mTotalTrafficRead += read;
+
+            mService.sendCallbackBandwidth(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead);
+
+            lastWritten = 0;
+            lastRead = 0;
         }
 
-        lastWritten = written;
-        lastRead = read;
+        lastWritten += written;
+        lastRead += read;
 
-        mService.sendCallbackBandwidth(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead);
     }
 
     private String formatCount(long count) {
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/Utils.java b/orbotservice/src/main/java/org/torproject/android/service/util/Utils.java
index 0fac4019..e6e203e3 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/util/Utils.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/Utils.java
@@ -4,13 +4,19 @@
 
 package org.torproject.android.service.util;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 public class Utils {
 
@@ -94,7 +100,91 @@ public class Utils {
 				
 		    	
 		    }
-	
 
 
+	/*
+	 *
+	 * Zips a file at a location and places the resulting zip file at the toLocation
+	 * Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip");
+	 */
+
+	public static boolean zipFileAtPath(String sourcePath, String toLocation) {
+		final int BUFFER = 2048;
+
+		File sourceFile = new File(sourcePath);
+		try {
+			BufferedInputStream origin = null;
+			FileOutputStream dest = new FileOutputStream(toLocation);
+			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
+					dest));
+			if (sourceFile.isDirectory()) {
+				zipSubFolder(out, sourceFile, sourceFile.getParent().length());
+			} else {
+				byte data[] = new byte[BUFFER];
+				FileInputStream fi = new FileInputStream(sourcePath);
+				origin = new BufferedInputStream(fi, BUFFER);
+				ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
+				entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
+				out.putNextEntry(entry);
+				int count;
+				while ((count = origin.read(data, 0, BUFFER)) != -1) {
+					out.write(data, 0, count);
+				}
+			}
+			out.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+			return false;
+		}
+		return true;
+	}
+
+	/*
+	 *
+	 * Zips a subfolder
+	 *
+	 */
+
+	private static void zipSubFolder(ZipOutputStream out, File folder,
+							  int basePathLength) throws IOException {
+
+		final int BUFFER = 2048;
+
+		File[] fileList = folder.listFiles();
+		BufferedInputStream origin = null;
+		for (File file : fileList) {
+			if (file.isDirectory()) {
+				zipSubFolder(out, file, basePathLength);
+			} else {
+				byte data[] = new byte[BUFFER];
+				String unmodifiedFilePath = file.getPath();
+				String relativePath = unmodifiedFilePath
+						.substring(basePathLength);
+				FileInputStream fi = new FileInputStream(unmodifiedFilePath);
+				origin = new BufferedInputStream(fi, BUFFER);
+				ZipEntry entry = new ZipEntry(relativePath);
+				entry.setTime(file.lastModified()); // to keep modification time after unzipping
+				out.putNextEntry(entry);
+				int count;
+				while ((count = origin.read(data, 0, BUFFER)) != -1) {
+					out.write(data, 0, count);
+				}
+				origin.close();
+			}
+		}
+	}
+
+	/*
+	 * gets the last path component
+	 *
+	 * Example: getLastPathComponent("downloads/example/fileToZip");
+	 * Result: "fileToZip"
+	 */
+	public static String getLastPathComponent(String filePath) {
+		String[] segments = filePath.split("/");
+		if (segments.length == 0)
+			return "";
+		String lastPathComponent = segments[segments.length - 1];
+		return lastPathComponent;
+	}
 }





More information about the tor-commits mailing list