[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [orbot/master] Fix bug where Orbot couldn't host multiple onion services of the same version (v2 or v3) off the same local port
commit 8db5c3a0b4ebaf0bc5f1cf67fb8f2cea590f53fe
Author: bim <dsnake@xxxxxxxxxxxxxx>
Date: Sat Apr 24 20:55:52 2021 -0400
Fix bug where Orbot couldn't host multiple onion services of the same version (v2 or v3) off the same local port
---
.../ui/hiddenservices/database/HSDatabase.java | 11 ++--
.../ui/v3onionservice/OnionServiceDatabase.java | 8 ++-
.../torproject/android/service/OrbotService.java | 61 +++++++++++++++++-----
3 files changed, 60 insertions(+), 20 deletions(-)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
index 18bc7aa0..d9a398bd 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
@@ -9,7 +9,7 @@ public class HSDatabase extends SQLiteOpenHelper {
public static final String HS_DATA_TABLE_NAME = "hs_data";
public static final String HS_CLIENT_COOKIE_TABLE_NAME = "hs_client_cookie";
- private static final int DATABASE_VERSION = 2;
+ private static final int DATABASE_VERSION = 4;
private static final String DATABASE_NAME = "hidden_services";
private static final String HS_DATA_TABLE_CREATE =
"CREATE TABLE " + HS_DATA_TABLE_NAME + " (" +
@@ -21,7 +21,8 @@ public class HSDatabase extends SQLiteOpenHelper {
"auth_cookie_value TEXT, " +
"created_by_user INTEGER DEFAULT 0, " +
"enabled INTEGER DEFAULT 1, " +
- "port INTEGER);";
+ "port INTEGER, " +
+ "filepath TEXT);";
private static final String HS_CLIENT_COOKIE_TABLE_CREATE =
"CREATE TABLE " + HS_CLIENT_COOKIE_TABLE_NAME + " (" +
@@ -42,6 +43,8 @@ public class HSDatabase extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (newVersion > oldVersion) {
+ db.execSQL("ALTER TABLE " + HS_DATA_TABLE_NAME + " ADD COLUMN filepath TEXT");
+ }
}
-}
-
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java
index 558babac..d2c62a9d 100644
--- a/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/v3onionservice/OnionServiceDatabase.java
@@ -8,7 +8,7 @@ public class OnionServiceDatabase extends SQLiteOpenHelper {
static final String DATABASE_NAME = "onion_service",
ONION_SERVICE_TABLE_NAME = "onion_services";
- private static final int DATABASE_VERSION = 1;
+ private static final int DATABASE_VERSION = 2;
private static final String ONION_SERVICES_CREATE_SQL =
"CREATE TABLE " + ONION_SERVICE_TABLE_NAME + " (" +
@@ -18,7 +18,8 @@ public class OnionServiceDatabase extends SQLiteOpenHelper {
"onion_port INTEGER, " +
"created_by_user INTEGER DEFAULT 0, " +
"enabled INTEGER DEFAULT 1, " +
- "port INTEGER);";
+ "port INTEGER, " +
+ "filepath TEXT);";
OnionServiceDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -31,6 +32,9 @@ public class OnionServiceDatabase extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (newVersion > oldVersion) {
+ db.execSQL("ALTER TABLE " + ONION_SERVICE_TABLE_NAME + " ADD COLUMN filepath text");
+ }
}
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 5d5eb3fd..6808f088 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/OrbotService.java
@@ -72,6 +72,7 @@ import java.util.HashMap;
import java.util.Objects;
import java.util.Random;
import java.util.StringTokenizer;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
@@ -98,7 +99,8 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
OnionService.AUTH_COOKIE,
OnionService.AUTH_COOKIE_VALUE,
OnionService.ONION_PORT,
- OnionService.ENABLED};
+ OnionService.ENABLED,
+ OnionService.PATH};
private static final String[] V3_ONION_SERVICE_PROJECTION = new String[]{
OnionService._ID,
OnionService.NAME,
@@ -106,6 +108,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
OnionService.PORT,
OnionService.ONION_PORT,
OnionService.ENABLED,
+ OnionService.PATH
};
private static final String[] LEGACY_COOKIE_PROJECTION = new String[]{
ClientCookie._ID,
@@ -841,16 +844,16 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
try {
while (onionServices.moveToNext()) {
String domain = onionServices.getString(onionServices.getColumnIndex(OnionService.DOMAIN));
- int localPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.PORT));
-
if (domain == null || TextUtils.isEmpty(domain)) {
- String v3OnionDirPath = new File(mV3OnionBasePath.getAbsolutePath(), "v3" + localPort).getCanonicalPath();
+ String path = onionServices.getString(onionServices.getColumnIndex(OnionService.PATH));
+ String v3OnionDirPath = new File(mV3OnionBasePath.getAbsolutePath(), path).getCanonicalPath();
File hostname = new File(v3OnionDirPath, "hostname");
if (hostname.exists()) {
+ int id = onionServices.getInt(onionServices.getColumnIndex(OnionService._ID));
domain = Utils.readString(new FileInputStream(hostname)).trim();
ContentValues fields = new ContentValues();
fields.put(OnionService.DOMAIN, domain);
- contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, fields, "port=" + localPort, null);
+ contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, fields, OnionService._ID + "=" + id, null);
}
}
@@ -870,19 +873,18 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
try {
while (hidden_services.moveToNext()) {
String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(OnionService.DOMAIN));
- Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.PORT));
- Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE));
+ int HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE));
String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE_VALUE));
-
// Update only new domains or restored from backup with auth cookie
if ((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) {
- String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath();
+ String hsDirPath = new File(mHSBasePath.getAbsolutePath(), hidden_services.getString(hidden_services.getColumnIndex(OnionService.PATH))).getCanonicalPath();
File file = new File(hsDirPath, "hostname");
if (file.exists()) {
ContentValues fields = new ContentValues();
try {
+ int id = hidden_services.getInt(hidden_services.getColumnIndex(OnionService._ID));
String onionHostname = Utils.readString(new FileInputStream(file)).trim();
if (HSAuthCookie == 1) {
String[] aux = onionHostname.split(" ");
@@ -890,14 +892,13 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
fields.put(OnionService.AUTH_COOKIE_VALUE, aux[1]);
}
fields.put(OnionService.DOMAIN, onionHostname);
- mCR.update(V2_HS_CONTENT_URI, fields, "port=" + HSLocalPort, null);
+ mCR.update(V2_HS_CONTENT_URI, fields, OnionService._ID + "=" + id, null);
} catch (FileNotFoundException e) {
logException("unable to read onion hostname file", e);
showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
}
} else {
showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), HS_NOTIFY_ID, R.drawable.ic_stat_notifyerr);
-
}
}
}
@@ -1390,9 +1391,22 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
Cursor onionServices = contentResolver.query(V3_ONION_SERVICES_CONTENT_URI, V3_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null);
if (onionServices != null) {
while (onionServices.moveToNext()) {
+ int id = onionServices.getInt(onionServices.getColumnIndex(OnionService._ID));
int localPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.PORT));
int onionPort = onionServices.getInt(onionServices.getColumnIndex(OnionService.ONION_PORT));
- String v3DirPath = new File(mV3OnionBasePath.getAbsolutePath(), "v3" + localPort).getCanonicalPath();
+ String path = onionServices.getString(onionServices.getColumnIndex(OnionService.PATH));
+ String domain = onionServices.getString(onionServices.getColumnIndex(OnionService.DOMAIN));
+ if (path == null) {
+ path = "v3";
+ if (domain == null)
+ path += UUID.randomUUID().toString();
+ else
+ path += localPort;
+ ContentValues cv = new ContentValues();
+ cv.put(OnionService.PATH, path);
+ contentResolver.update(V3_ONION_SERVICES_CONTENT_URI, cv, OnionService._ID + "=" + id, null);
+ }
+ String v3DirPath = new File(mV3OnionBasePath.getAbsolutePath(), path).getCanonicalPath();
torrc.append("HiddenServiceDir ").append(v3DirPath).append("\n");
torrc.append("HiddenServiceVersion 3").append("\n");
torrc.append("HiddenServicePort ").append(onionPort).append(" 127.0.0.1:").append(localPort).append("\n");
@@ -1404,18 +1418,36 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
}
}
- // todo needs modifications to set hidden service version back after doing v3 stuff...
private void addV2HiddenServicesToTorrc(StringBuffer torrc, ContentResolver contentResolver) {
try {
Cursor hidden_services = contentResolver.query(V2_HS_CONTENT_URI, LEGACY_V2_ONION_SERVICE_PROJECTION, OnionService.ENABLED + "=1", null, null);
if (hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
+ int id = hidden_services.getInt(hidden_services.getColumnIndex(OnionService._ID));
String HSname = hidden_services.getString(hidden_services.getColumnIndex(OnionService.NAME));
+ String domain = hidden_services.getString(hidden_services.getColumnIndex(OnionService.DOMAIN));
int HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.PORT));
int HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.ONION_PORT));
int HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(OnionService.AUTH_COOKIE));
- String hsDirPath = new File(mHSBasePath.getAbsolutePath(), "hs" + HSLocalPort).getCanonicalPath();
+ String path = hidden_services.getString(hidden_services.getColumnIndex(OnionService.PATH));
+
+ // logic to fix bug where you can't have 2+ hidden services on same local port without breaking services that were configured before the bug fix
+ if (path == null) {
+ String newPath = "hs";
+ if (domain == null)
+ newPath +=UUID.randomUUID().toString();
+ else
+ newPath += HSLocalPort;
+
+ ContentValues cv = new ContentValues();
+ cv.put(OnionService.PATH, newPath);
+ contentResolver.update(V2_HS_CONTENT_URI, cv, OnionService._ID + "=" + id, null);
+ path = newPath;
+ }
+
+ String hsDirPath = new File(mHSBasePath.getAbsolutePath(), path).getCanonicalPath();
+
debug("Adding hidden service on port: " + HSLocalPort);
@@ -1656,6 +1688,7 @@ public class OrbotService extends VpnService implements TorServiceConstants, Orb
public static final String AUTH_COOKIE = "auth_cookie";
public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String ENABLED = "enabled";
+ public static final String PATH = "filepath";
}
public static final class V3ClientAuth implements BaseColumns {
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits