mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Compare commits
3 Commits
client-ver
...
115-tor-pe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84b3670624 | ||
|
|
749695187e | ||
|
|
c4db72abf2 |
@@ -189,8 +189,8 @@ project.afterEvaluate {
|
||||
preBuild.dependsOn {
|
||||
[
|
||||
'verifyTorGeoIp',
|
||||
'verifyTorBinaryArm',
|
||||
'verifyTorBinaryArmPie',
|
||||
// 'verifyTorBinaryArm',
|
||||
// 'verifyTorBinaryArmPie',
|
||||
'verifyTorBinaryX86',
|
||||
'verifyTorBinaryX86Pie'
|
||||
]
|
||||
|
||||
@@ -38,7 +38,7 @@ public class AndroidPluginsModule {
|
||||
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
|
||||
androidExecutor, appContext, random, backoffFactory);
|
||||
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
|
||||
locationUtils, reporter, eventBus, backoffFactory);
|
||||
locationUtils, reporter, eventBus);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
backoffFactory, appContext);
|
||||
final Collection<DuplexPluginFactory> duplex =
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.SettingsUpdatedEvent;
|
||||
import org.briarproject.api.keyagreement.KeyAgreementListener;
|
||||
import org.briarproject.api.keyagreement.TransportDescriptor;
|
||||
import org.briarproject.api.plugins.Backoff;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
@@ -52,7 +51,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -70,8 +68,6 @@ import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
|
||||
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
|
||||
import static org.briarproject.util.PrivacyUtils.scrubOnion;
|
||||
|
||||
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
@@ -85,6 +81,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
private static final String OWNER = "__OwningControllerProcess";
|
||||
private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051;
|
||||
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds
|
||||
private static final int HOSTNAME_TIMEOUT = 30 * 1000; // Milliseconds
|
||||
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(TorPlugin.class.getName());
|
||||
@@ -93,13 +90,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
private final Context appContext;
|
||||
private final LocationUtils locationUtils;
|
||||
private final DevReporter reporter;
|
||||
private final Backoff backoff;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final String architecture;
|
||||
private final int maxLatency, maxIdleTime, socketTimeout;
|
||||
private final int pollingInterval;
|
||||
private final ConnectionStatus connectionStatus;
|
||||
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||
private final File doneFile, cookieFile;
|
||||
private final File doneFile, cookieFile, hostnameFile;
|
||||
private final PowerManager.WakeLock wakeLock;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
|
||||
@@ -110,18 +107,18 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||
|
||||
TorPlugin(Executor ioExecutor, Context appContext,
|
||||
LocationUtils locationUtils, DevReporter reporter, Backoff backoff,
|
||||
LocationUtils locationUtils, DevReporter reporter,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime) {
|
||||
int maxIdleTime, int pollingInterval) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.appContext = appContext;
|
||||
this.locationUtils = locationUtils;
|
||||
this.reporter = reporter;
|
||||
this.backoff = backoff;
|
||||
this.callback = callback;
|
||||
this.architecture = architecture;
|
||||
this.maxLatency = maxLatency;
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
this.pollingInterval = pollingInterval;
|
||||
if (maxIdleTime > Integer.MAX_VALUE / 2)
|
||||
socketTimeout = Integer.MAX_VALUE;
|
||||
else socketTimeout = maxIdleTime * 2;
|
||||
@@ -132,6 +129,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
configFile = new File(torDirectory, "torrc");
|
||||
doneFile = new File(torDirectory, "done");
|
||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||
hostnameFile = new File(torDirectory, "hs/hostname");
|
||||
Object o = appContext.getSystemService(POWER_SERVICE);
|
||||
PowerManager pm = (PowerManager) o;
|
||||
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin");
|
||||
@@ -363,7 +361,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
publishHiddenService(localPort);
|
||||
}
|
||||
});
|
||||
backoff.reset();
|
||||
// Accept incoming hidden service connections from Tor
|
||||
acceptContactConnections(ss);
|
||||
}
|
||||
@@ -382,40 +379,48 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
private void publishHiddenService(String port) {
|
||||
if (!running) return;
|
||||
LOG.info("Creating hidden service");
|
||||
String privKey = callback.getSettings().get(HS_PRIVKEY);
|
||||
Map<Integer, String> portLines =
|
||||
Collections.singletonMap(80, "127.0.0.1:" + port);
|
||||
Map<String, String> response;
|
||||
try {
|
||||
// Use the control connection to set up the hidden service
|
||||
if (privKey == null)
|
||||
response = controlConnection.addOnion(portLines);
|
||||
else response = controlConnection.addOnion(privKey, portLines);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return;
|
||||
}
|
||||
if (!response.containsKey(HS_ADDRESS)) {
|
||||
LOG.warning("Tor did not return a hidden service address");
|
||||
return;
|
||||
}
|
||||
if (privKey == null && !response.containsKey(HS_PRIVKEY)) {
|
||||
LOG.warning("Tor did not return a private key");
|
||||
return;
|
||||
if (!hostnameFile.exists()) {
|
||||
LOG.info("Creating hidden service");
|
||||
try {
|
||||
// Watch for the hostname file being created/updated
|
||||
File serviceDirectory = hostnameFile.getParentFile();
|
||||
serviceDirectory.mkdirs();
|
||||
hostnameFile.createNewFile();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
FileObserver obs = new WriteObserver(hostnameFile, latch);
|
||||
obs.startWatching();
|
||||
// Use the control connection to update the Tor config
|
||||
List<String> config = Arrays.asList(
|
||||
"HiddenServiceDir " +
|
||||
serviceDirectory.getAbsolutePath(),
|
||||
"HiddenServicePort 80 127.0.0.1:" + port);
|
||||
controlConnection.setConf(config);
|
||||
controlConnection.saveConf();
|
||||
// Wait for the hostname file to be created/updated
|
||||
if (!latch.await(HOSTNAME_TIMEOUT, MILLISECONDS)) {
|
||||
LOG.warning("Hidden service not created");
|
||||
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
|
||||
return;
|
||||
}
|
||||
if (!running) return;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while creating hidden service");
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Publish the hidden service's onion hostname in transport properties
|
||||
String hostname = response.get(HS_ADDRESS);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Hidden service " + scrubOnion(hostname));
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ONION, hostname);
|
||||
callback.mergeLocalProperties(p);
|
||||
if (privKey == null) {
|
||||
// Save the hidden service's private key for next time
|
||||
Settings s = new Settings();
|
||||
s.put(HS_PRIVKEY, response.get(HS_PRIVKEY));
|
||||
callback.mergeSettings(s);
|
||||
try {
|
||||
String hostname = new String(read(hostnameFile), "UTF-8").trim();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Hidden service " + scrubOnion(hostname));
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ONION, hostname.substring(0, 16));
|
||||
callback.mergeLocalProperties(p);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +436,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
return;
|
||||
}
|
||||
LOG.info("Connection received");
|
||||
backoff.reset();
|
||||
TorTransportConnection conn = new TorTransportConnection(this, s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
}
|
||||
@@ -479,14 +483,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
@Override
|
||||
public int getPollingInterval() {
|
||||
return backoff.getPollingInterval();
|
||||
return pollingInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
if (!isRunning()) return;
|
||||
backoff.increment();
|
||||
// TODO: Pass properties to connectAndCallBack()
|
||||
for (ContactId c : callback.getRemoteProperties().keySet())
|
||||
if (!connected.contains(c)) connectAndCallBack(c);
|
||||
}
|
||||
@@ -496,10 +498,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
DuplexTransportConnection d = createConnection(c);
|
||||
if (d != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
if (d != null) callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -519,7 +518,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
try {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to " + scrubOnion(onion));
|
||||
controlConnection.forgetHiddenService(onion);
|
||||
Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
|
||||
proxy.resolveAddrLocally(false);
|
||||
Socket s = new SocksSocket(proxy, onion + ".onion", 80);
|
||||
@@ -528,9 +526,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
LOG.info("Connected to " + scrubOnion(onion));
|
||||
return new TorTransportConnection(this, s);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
|
||||
e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -567,7 +566,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
if (status.equals("BUILT") &&
|
||||
connectionStatus.getAndSetCircuitBuilt()) {
|
||||
LOG.info("First circuit built");
|
||||
backoff.reset();
|
||||
if (isRunning()) {
|
||||
sendDevReports();
|
||||
callback.transportEnabled();
|
||||
@@ -597,7 +595,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
||||
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
|
||||
connectionStatus.setBootstrapped();
|
||||
backoff.reset();
|
||||
if (isRunning()) {
|
||||
sendDevReports();
|
||||
callback.transportEnabled();
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.os.Build;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.plugins.Backoff;
|
||||
import org.briarproject.api.plugins.BackoffFactory;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
|
||||
@@ -24,26 +22,22 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
||||
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
|
||||
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
|
||||
private static final double BACKOFF_BASE = 1.2;
|
||||
private static final int POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes
|
||||
|
||||
private final Executor ioExecutor;
|
||||
private final Context appContext;
|
||||
private final LocationUtils locationUtils;
|
||||
private final DevReporter reporter;
|
||||
private final EventBus eventBus;
|
||||
private final BackoffFactory backoffFactory;
|
||||
|
||||
public TorPluginFactory(Executor ioExecutor, Context appContext,
|
||||
LocationUtils locationUtils, DevReporter reporter,
|
||||
EventBus eventBus, BackoffFactory backoffFactory) {
|
||||
EventBus eventBus) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.appContext = appContext;
|
||||
this.locationUtils = locationUtils;
|
||||
this.reporter = reporter;
|
||||
this.eventBus = eventBus;
|
||||
this.backoffFactory = backoffFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,11 +71,9 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
||||
// Use position-independent executable for SDK >= 16
|
||||
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
|
||||
|
||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
|
||||
reporter, backoff, callback, architecture, MAX_LATENCY,
|
||||
MAX_IDLE_TIME);
|
||||
reporter, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME,
|
||||
POLLING_INTERVAL);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package org.briarproject.plugins;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.event.ConnectionClosedEvent;
|
||||
import org.briarproject.api.event.ConnectionOpenedEvent;
|
||||
import org.briarproject.api.event.ContactStatusChangedEvent;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
@@ -71,18 +69,6 @@ class Poller implements EventListener {
|
||||
// Connect to the newly activated contact
|
||||
connectToContact(c.getContactId());
|
||||
}
|
||||
} else if (e instanceof ConnectionClosedEvent) {
|
||||
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
|
||||
// Reschedule polling, the polling interval may have decreased
|
||||
reschedule(c.getTransportId());
|
||||
if (!c.isIncoming()) {
|
||||
// Connect to the disconnected contact
|
||||
connectToContact(c.getContactId(), c.getTransportId());
|
||||
}
|
||||
} else if (e instanceof ConnectionOpenedEvent) {
|
||||
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
|
||||
// Reschedule polling, the polling interval may have decreased
|
||||
reschedule(c.getTransportId());
|
||||
} else if (e instanceof TransportEnabledEvent) {
|
||||
TransportEnabledEvent t = (TransportEnabledEvent) e;
|
||||
// Poll the newly enabled transport
|
||||
@@ -97,14 +83,6 @@ class Poller implements EventListener {
|
||||
if (d.shouldPoll()) connectToContact(c, d);
|
||||
}
|
||||
|
||||
private void connectToContact(ContactId c, TransportId t) {
|
||||
Plugin p = pluginManager.getPlugin(t);
|
||||
if (p instanceof SimplexPlugin && p.shouldPoll())
|
||||
connectToContact(c, (SimplexPlugin) p);
|
||||
else if (p instanceof DuplexPlugin && p.shouldPoll())
|
||||
connectToContact(c, (DuplexPlugin) p);
|
||||
}
|
||||
|
||||
private void connectToContact(final ContactId c, final SimplexPlugin p) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
@@ -133,11 +111,6 @@ class Poller implements EventListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void reschedule(TransportId t) {
|
||||
Plugin p = pluginManager.getPlugin(t);
|
||||
if (p.shouldPoll()) schedule(p, p.getPollingInterval(), false);
|
||||
}
|
||||
|
||||
private void pollNow(TransportId t) {
|
||||
Plugin p = pluginManager.getPlugin(t);
|
||||
// Randomise next polling interval
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.util;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -9,8 +8,7 @@ import java.net.SocketAddress;
|
||||
public class PrivacyUtils {
|
||||
|
||||
public static String scrubOnion(String onion) {
|
||||
// keep first three characters of onion address
|
||||
return onion.substring(0, 3) + "[_scrubbed_]";
|
||||
return onion;
|
||||
}
|
||||
|
||||
public static String scrubMacAddress(String address) {
|
||||
|
||||
Reference in New Issue
Block a user