Skip to content

Commit

Permalink
Bug 30501: BridgesList Preferences is an overloaded field
Browse files Browse the repository at this point in the history
Bug 30767: Custom obfs4 bridge does not work on Tor Browser for Android

TOPL fixes thaliproject#133 fixes thaliproject#134
  • Loading branch information
sisbell committed Oct 21, 2019
1 parent a720e25 commit ac9ad22
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 59 deletions.
2 changes: 1 addition & 1 deletion universal/build.gradle
Expand Up @@ -15,7 +15,7 @@ dependencies {
implementation 'org.slf4j:slf4j-api:1.7.25'
implementation 'net.freehaven.tor.control:jtorctl:0.2'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
testCompile group: 'org.mockito', name: 'mockito-core', version: '3.1.0'}

task sourcesJar(type:Jar){
from sourceSets.main.allSource
Expand Down
@@ -0,0 +1,5 @@
package com.msopentech.thali.toronionproxy;

public enum BridgeType {
MEEK_LITE, OBFS3, OBFS4
}
@@ -1,6 +1,6 @@
package com.msopentech.thali.toronionproxy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
Expand All @@ -18,6 +18,11 @@ public String dnsPort() {
return "5400";
}

@Override
public List<String> getCustomBridges() {
return Collections.emptyList();
}

@Override
public String getCustomTorrc() {
return null;
Expand All @@ -44,8 +49,8 @@ public int getHttpTunnelPort() {
}

@Override
public List<String> getListOfSupportedBridges() {
return new ArrayList<>();
public List<BridgeType> getBridgeTypes() {
return Collections.emptyList();
}

@Override
Expand Down
Expand Up @@ -92,32 +92,19 @@ public TorConfigBuilder bridge(String type, String config) {
return this;
}

public TorConfigBuilder bridgeCustom(String config) {
if (!isNullOrEmpty(config)) {
buffer.append("Bridge ").append(config).append('\n');
}
return this;
}

public TorConfigBuilder configurePluggableTransportsFromSettings(File pluggableTransportClient) throws IOException {
List<String> supportedBridges = settings.getListOfSupportedBridges();
if (pluggableTransportClient == null || !settings.hasBridges() || supportedBridges.size() < 1) {
public TorConfigBuilder configurePluggableTransports(File pluggableTransportClient,
List<BridgeType> bridgeTypes)
throws IOException {
if (pluggableTransportClient == null) {
return this;
}

if (!pluggableTransportClient.exists() || !pluggableTransportClient.canExecute()) {
throw new IOException("Bridge binary does not exist: " + pluggableTransportClient
.getCanonicalPath());
}

if (supportedBridges.contains("obfs3") || supportedBridges.contains("obfs4")) {
transportPluginObfs(pluggableTransportClient.getCanonicalPath());
}
if (supportedBridges.contains("meek")) {
transportPluginMeek(pluggableTransportClient.getCanonicalPath());
for (BridgeType bridgeType : bridgeTypes) {
writeBridgeTransport(pluggableTransportClient, bridgeType);
}
String type = supportedBridges.contains("meek") ? "meek_lite" : "obfs4";
addBridgesFromResources(type, 2);
return this;
}

Expand Down Expand Up @@ -153,6 +140,27 @@ public TorConfigBuilder controlPortWriteToFileFromConfig() {
return controlPortWriteToFile(context.config.getControlPortFile().getAbsolutePath());
}

public TorConfigBuilder customBridges(List<String> bridges) {
if(bridges.size() > 1) {
Collections.shuffle(bridges, new Random(System.nanoTime()));
}
for (String bridge : bridges) {
if(!isNullOrEmpty(bridge)) {
line("Bridge " + bridge);
}
}
return this;
}

@SettingsConfig
public TorConfigBuilder customBridgesFromSettings() {
if (!settings.hasBridges() || !hasCustomBridges()) {
return this;
}
List<String> bridges = settings.getCustomBridges();
return customBridges(bridges);
}

public TorConfigBuilder debugLogs() {
buffer.append("Log debug syslog").append('\n');
buffer.append("Log info syslog").append('\n');
Expand Down Expand Up @@ -273,6 +281,20 @@ public TorConfigBuilder nonExitRelayFromSettings() {
return this;
}

/**
* Write up two bridges from packaged bridge list if bridges option is enabled and if no custom bridges
* have been defined by the user.
*/
@SettingsConfig
public TorConfigBuilder predefinedBridgesFromSettings() {
if (!settings.hasBridges() || !hasPredefinedBridges() || hasCustomBridges()) {
return this;
}
List<BridgeType> bridgeTypes = settings.getBridgeTypes();
addPredefinedBridgesFromResources(bridgeTypes, 2);
return this;
}

public TorConfigBuilder proxyOnAllInterfaces() {
buffer.append("SocksListenAddress 0.0.0.0").append('\n');
return this;
Expand Down Expand Up @@ -413,6 +435,9 @@ public TorConfigBuilder socksPort(String socksPort, String isolationFlag) {
@SettingsConfig
public TorConfigBuilder socksPortFromSettings() {
String socksPort = settings.getSocksPort();
if(isNullOrEmpty(socksPort)) {
return this;
}
if (socksPort.indexOf(':') != -1) {
socksPort = socksPort.split(":")[1];
}
Expand Down Expand Up @@ -489,7 +514,12 @@ public TorConfigBuilder useBridges() {

@SettingsConfig
public TorConfigBuilder useBridgesFromSettings() {
return !settings.hasBridges() ? dontUseBridges() : this;
if(settings.hasBridges() && (hasCustomBridges() || hasPredefinedBridges())) {
useBridges();
} else {
dontUseBridges();
}
return this;
}

public TorConfigBuilder virtualAddressNetwork(String address) {
Expand Down Expand Up @@ -518,14 +548,25 @@ public TorConfigBuilder virtualAddressNetworkFromSettings() {
* </code>
*
*/
TorConfigBuilder addBridgesFromResources(String type, int maxBridges) throws IOException {
if(settings.hasBridges()) {
InputStream bridgesStream = context.getInstaller().openBridgesStream();
int formatType = bridgesStream.read();
if(formatType == 0) {
addBridges(bridgesStream, type, maxBridges);
} else {
addCustomBridges(bridgesStream);
TorConfigBuilder addPredefinedBridgesFromResources(List<BridgeType> types, int maxBridges) {
ArrayList<String> bridgeTypes = new ArrayList<>();
for(BridgeType bridgeType : types) {
bridgeTypes.add(bridgeType.name().toLowerCase());
}
if(settings.hasBridges() && hasPredefinedBridges() && !hasCustomBridges()) {
InputStream bridgesStream = null;
try {
bridgesStream = context.getInstaller().openBridgesStream();
addPredefinedBridgesFromStream(bridgesStream, bridgeTypes, maxBridges);
} catch(IOException e) {
e.printStackTrace();
} finally {
if(bridgesStream != null) {
try {
bridgesStream.close();
} catch (IOException e) {
}
}
}
}
return this;
Expand All @@ -534,41 +575,31 @@ TorConfigBuilder addBridgesFromResources(String type, int maxBridges) throws IOE
/**
* Add bridges from bridges.txt file.
*/
private void addBridges(InputStream input, String bridgeType, int maxBridges) {
if (input == null || isNullOrEmpty(bridgeType) || maxBridges < 1) {
private void addPredefinedBridgesFromStream(InputStream input, List<String> bridgeTypes, int maxBridges) {
if (input == null || maxBridges < 1 || bridgeTypes.isEmpty()) {
return;
}
boolean hasAddedBridge = false;
List<Bridge> bridges = readBridgesFromStream(input);
Collections.shuffle(bridges, new Random(System.nanoTime()));
if(bridges.size() > 1) {
Collections.shuffle(bridges, new Random(System.nanoTime()));
}
int bridgeCount = 0;
for (Bridge b : bridges) {
if (b.type.equals(bridgeType)) {
if(bridgeTypes.contains(b.type)) {
bridge(b.type, b.config);
hasAddedBridge = true;
if (++bridgeCount > maxBridges)
break;
}
}
if(hasAddedBridge) useBridges();
}

/**
* Add custom bridges defined by the user. These will have a bridgeType of 'custom' as the first field.
*/
private void addCustomBridges(InputStream input) {
if (input == null) {
return;
}
boolean hasAddedBridge = false;
List<Bridge> bridges = readCustomBridgesFromStream(input);
for (Bridge b : bridges) {
if (b.type.equals("custom")) {
bridgeCustom(b.config);
hasAddedBridge = true;
}
}
if(hasAddedBridge) useBridges();

private boolean hasCustomBridges() {
return !settings.getCustomBridges().isEmpty();
}

private boolean hasPredefinedBridges() {
return !settings.getBridgeTypes().isEmpty();
}

private static List<Bridge> readBridgesFromStream(InputStream input) {
Expand Down Expand Up @@ -606,6 +637,17 @@ private static List<Bridge> readCustomBridgesFromStream(InputStream input) {
return bridges;
}

private void writeBridgeTransport(File pluggableTransportClient, BridgeType bridgeType) throws IOException {
switch (bridgeType) {
case MEEK_LITE:
transportPluginMeek(pluggableTransportClient.getCanonicalPath());
break;
case OBFS3:
case OBFS4:
transportPluginObfs(pluggableTransportClient.getCanonicalPath());
}
}

private static class Bridge {
final String type;
final String config;
Expand Down
Expand Up @@ -7,6 +7,8 @@ public interface TorSettings {

String dnsPort();

List<String> getCustomBridges();

String getCustomTorrc();

String getEntryNodes();
Expand All @@ -17,10 +19,7 @@ public interface TorSettings {

int getHttpTunnelPort();

/**
* Returns a list of supported bridges. The string value will include the name: meek_lite, obfs4
*/
List<String> getListOfSupportedBridges();
List<BridgeType> getBridgeTypes();

String getProxyHost();

Expand Down

0 comments on commit ac9ad22

Please sign in to comment.