mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Compare commits
2 Commits
feature-fl
...
2165-windo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcd52261fe | ||
|
|
fa6f7e62ed |
@@ -105,43 +105,46 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
|||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(TorPlugin.class.getName());
|
static final Logger LOG = getLogger(TorPlugin.class.getName());
|
||||||
|
|
||||||
private static final String[] EVENTS = {
|
static final String[] EVENTS = {
|
||||||
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
||||||
};
|
};
|
||||||
private static final String OWNER = "__OwningControllerProcess";
|
static final String OWNER = "__OwningControllerProcess";
|
||||||
private static final int COOKIE_TIMEOUT_MS = 3000;
|
static final int COOKIE_TIMEOUT_MS = 3000;
|
||||||
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
||||||
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
||||||
|
|
||||||
private final Executor ioExecutor, wakefulIoExecutor;
|
private final Executor ioExecutor, wakefulIoExecutor;
|
||||||
private final Executor connectionStatusExecutor;
|
private final Executor connectionStatusExecutor;
|
||||||
private final NetworkManager networkManager;
|
final NetworkManager networkManager;
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
private final Clock clock;
|
final Clock clock;
|
||||||
private final BatteryManager batteryManager;
|
final BatteryManager batteryManager;
|
||||||
private final Backoff backoff;
|
private final Backoff backoff;
|
||||||
private final TorRendezvousCrypto torRendezvousCrypto;
|
private final TorRendezvousCrypto torRendezvousCrypto;
|
||||||
private final PluginCallback callback;
|
final PluginCallback callback;
|
||||||
private final String architecture;
|
private final String architecture;
|
||||||
private final CircumventionProvider circumventionProvider;
|
private final CircumventionProvider circumventionProvider;
|
||||||
private final ResourceProvider resourceProvider;
|
private final ResourceProvider resourceProvider;
|
||||||
private final long maxLatency;
|
private final long maxLatency;
|
||||||
private final int maxIdleTime;
|
private final int maxIdleTime;
|
||||||
private final int socketTimeout;
|
private final int socketTimeout;
|
||||||
private final File torDirectory, geoIpFile, configFile;
|
final File torDirectory;
|
||||||
private final int torSocksPort;
|
final File geoIpFile;
|
||||||
private final int torControlPort;
|
final File configFile;
|
||||||
private final File doneFile, cookieFile;
|
final int torSocksPort;
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
final int torControlPort;
|
||||||
|
private final File doneFile;
|
||||||
|
final File cookieFile;
|
||||||
|
final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
protected final PluginState state = new PluginState();
|
protected final PluginState state = new PluginState();
|
||||||
|
|
||||||
private volatile Socket controlSocket = null;
|
volatile Socket controlSocket = null;
|
||||||
private volatile TorControlConnection controlConnection = null;
|
volatile TorControlConnection controlConnection = null;
|
||||||
private volatile Settings settings = null;
|
volatile Settings settings = null;
|
||||||
|
|
||||||
protected abstract int getProcessId();
|
protected abstract int getProcessId();
|
||||||
|
|
||||||
@@ -242,6 +245,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
Process torProcess;
|
Process torProcess;
|
||||||
ProcessBuilder pb =
|
ProcessBuilder pb =
|
||||||
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
|
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
|
||||||
|
// TODO: pb.redirectErrorStream on Linux, too?
|
||||||
Map<String, String> env = pb.environment();
|
Map<String, String> env = pb.environment();
|
||||||
env.put("HOME", torDirectory.getAbsolutePath());
|
env.put("HOME", torDirectory.getAbsolutePath());
|
||||||
pb.directory(torDirectory);
|
pb.directory(torDirectory);
|
||||||
@@ -318,8 +322,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
bind();
|
bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Remove after a reasonable migration period (added 2020-06-25)
|
// TODO: Remove after a reasonable migration period (added 2020-06-25)
|
||||||
private Settings migrateSettings(Settings settings) {
|
Settings migrateSettings(Settings settings) {
|
||||||
int network = settings.getInt(PREF_TOR_NETWORK,
|
int network = settings.getInt(PREF_TOR_NETWORK,
|
||||||
DEFAULT_PREF_TOR_NETWORK);
|
DEFAULT_PREF_TOR_NETWORK);
|
||||||
if (network == PREF_TOR_NETWORK_NEVER) {
|
if (network == PREF_TOR_NETWORK_NEVER) {
|
||||||
@@ -330,11 +335,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean assetsAreUpToDate() {
|
boolean assetsAreUpToDate() {
|
||||||
return doneFile.lastModified() > getLastUpdateTime();
|
return doneFile.lastModified() > getLastUpdateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installAssets() throws PluginException {
|
void installAssets() throws PluginException {
|
||||||
try {
|
try {
|
||||||
// The done file may already exist from a previous installation
|
// The done file may already exist from a previous installation
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
@@ -389,20 +394,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
private InputStream getObfs4InputStream() throws IOException {
|
private InputStream getObfs4InputStream() throws IOException {
|
||||||
InputStream in = resourceProvider
|
InputStream in = resourceProvider
|
||||||
.getResourceInputStream("obfs4proxy_" + architecture, ".zip");
|
.getResourceInputStream("obfs4proxy_" + "linux-x86_64", ".zip");
|
||||||
ZipInputStream zin = new ZipInputStream(in);
|
ZipInputStream zin = new ZipInputStream(in);
|
||||||
if (zin.getNextEntry() == null) throw new IOException();
|
if (zin.getNextEntry() == null) throw new IOException();
|
||||||
return zin;
|
return zin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void append(StringBuilder strb, String name, int value) {
|
protected static void append(StringBuilder strb, String name, int value) {
|
||||||
strb.append(name);
|
strb.append(name);
|
||||||
strb.append(" ");
|
strb.append(" ");
|
||||||
strb.append(value);
|
strb.append(value);
|
||||||
strb.append("\n");
|
strb.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getConfigInputStream() {
|
protected InputStream getConfigInputStream() {
|
||||||
StringBuilder strb = new StringBuilder();
|
StringBuilder strb = new StringBuilder();
|
||||||
append(strb, "ControlPort", torControlPort);
|
append(strb, "ControlPort", torControlPort);
|
||||||
append(strb, "CookieAuthentication", 1);
|
append(strb, "CookieAuthentication", 1);
|
||||||
@@ -415,7 +420,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
strb.toString().getBytes(Charset.forName("UTF-8")));
|
strb.toString().getBytes(Charset.forName("UTF-8")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listFiles(File f) {
|
void listFiles(File f) {
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
File[] children = f.listFiles();
|
File[] children = f.listFiles();
|
||||||
if (children != null) for (File child : children) listFiles(child);
|
if (children != null) for (File child : children) listFiles(child);
|
||||||
@@ -424,7 +429,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] read(File f) throws IOException {
|
byte[] read(File f) throws IOException {
|
||||||
byte[] b = new byte[(int) f.length()];
|
byte[] b = new byte[(int) f.length()];
|
||||||
FileInputStream in = new FileInputStream(f);
|
FileInputStream in = new FileInputStream(f);
|
||||||
try {
|
try {
|
||||||
@@ -440,7 +445,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind() {
|
void bind() {
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = settings.get(PREF_TOR_PORT);
|
String portString = settings.get(PREF_TOR_PORT);
|
||||||
@@ -814,8 +819,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConnectionStatus(NetworkStatus status,
|
void updateConnectionStatus(NetworkStatus status,
|
||||||
boolean charging) {
|
boolean charging) {
|
||||||
connectionStatusExecutor.execute(() -> {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!state.isTorRunning()) return;
|
if (!state.isTorRunning()) return;
|
||||||
boolean online = status.isConnected();
|
boolean online = status.isConnected();
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.briarproject.bramble.system;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.security.Provider;
|
||||||
|
|
||||||
|
public class WindowsSecureRandomProvider extends AbstractSecureRandomProvider {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Provider getProvider() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ dependencies {
|
|||||||
def jna_version = '4.5.2'
|
def jna_version = '4.5.2'
|
||||||
implementation "net.java.dev.jna:jna:$jna_version"
|
implementation "net.java.dev.jna:jna:$jna_version"
|
||||||
implementation "net.java.dev.jna:jna-platform:$jna_version"
|
implementation "net.java.dev.jna:jna-platform:$jna_version"
|
||||||
tor "org.briarproject:tor:$tor_version"
|
tor fileTree(dir: 'libs', include: '*.zip')
|
||||||
tor "org.briarproject:obfs4proxy:$obfs4proxy_version@zip"
|
tor "org.briarproject:obfs4proxy:$obfs4proxy_version@zip"
|
||||||
|
|
||||||
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
|
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
|
||||||
|
|||||||
BIN
bramble-java/libs/tor-0.3.5.17.zip
Normal file
BIN
bramble-java/libs/tor-0.3.5.17.zip
Normal file
Binary file not shown.
@@ -32,13 +32,14 @@ import javax.net.SocketFactory;
|
|||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.OsUtils.isLinux;
|
import static org.briarproject.bramble.util.OsUtils.isLinux;
|
||||||
|
import static org.briarproject.bramble.util.OsUtils.isWindows;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class UnixTorPluginFactory implements DuplexPluginFactory {
|
public class DesktopTorPluginFactory implements DuplexPluginFactory {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(UnixTorPluginFactory.class.getName());
|
getLogger(DesktopTorPluginFactory.class.getName());
|
||||||
|
|
||||||
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||||
@@ -62,7 +63,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
|
|||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UnixTorPluginFactory(@IoExecutor Executor ioExecutor,
|
DesktopTorPluginFactory(@IoExecutor Executor ioExecutor,
|
||||||
@WakefulIoExecutor Executor wakefulIoExecutor,
|
@WakefulIoExecutor Executor wakefulIoExecutor,
|
||||||
NetworkManager networkManager,
|
NetworkManager networkManager,
|
||||||
LocationUtils locationUtils,
|
LocationUtils locationUtils,
|
||||||
@@ -107,25 +108,33 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexPlugin createPlugin(PluginCallback callback) {
|
public DuplexPlugin createPlugin(PluginCallback callback) {
|
||||||
// Check that we have a Tor binary for this architecture
|
// Check that we have a Tor binary for this architecture
|
||||||
String architecture = null;
|
|
||||||
if (isLinux()) {
|
if (isLinux()) {
|
||||||
String arch = System.getProperty("os.arch");
|
String arch = System.getProperty("os.arch");
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("System's os.arch is " + arch);
|
LOG.info("System's os.arch is " + arch);
|
||||||
}
|
}
|
||||||
if (arch.equals("amd64")) {
|
if (arch.equals("amd64")) {
|
||||||
architecture = "linux-x86_64";
|
return createUnixPlugin(callback, "linux-x86_64");
|
||||||
} else if (arch.equals("aarch64")) {
|
} else if (arch.equals("aarch64")) {
|
||||||
architecture = "linux-aarch64";
|
return createUnixPlugin(callback, "linux-aarch64");
|
||||||
} else if (arch.equals("arm")) {
|
} else if (arch.equals("arm")) {
|
||||||
architecture = "linux-armhf";
|
return createUnixPlugin(callback, "linux-armhf");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (architecture == null) {
|
if (isWindows()) {
|
||||||
LOG.info("Tor is not supported on this architecture");
|
String arch = System.getProperty("os.arch");
|
||||||
return null;
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("System's os.arch is " + arch);
|
||||||
|
}
|
||||||
|
if (arch.equals("amd64")) {
|
||||||
|
return createWindowsPlugin(callback, "windows-x86_64");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
LOG.info("Tor is not supported on this architecture");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DuplexPlugin createUnixPlugin(PluginCallback callback, String architecture) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("The selected architecture for Tor is " + architecture);
|
LOG.info("The selected architecture for Tor is " + architecture);
|
||||||
}
|
}
|
||||||
@@ -143,4 +152,21 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
|
|||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DuplexPlugin createWindowsPlugin(PluginCallback callback, String architecture) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("The selected architecture for Tor is " + architecture);
|
||||||
|
}
|
||||||
|
|
||||||
|
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||||
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
|
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
|
||||||
|
WindowsTorPlugin plugin = new WindowsTorPlugin(ioExecutor, wakefulIoExecutor,
|
||||||
|
networkManager, locationUtils, torSocketFactory, clock,
|
||||||
|
resourceProvider, circumventionProvider, batteryManager,
|
||||||
|
backoff, torRendezvousCrypto, callback, architecture,
|
||||||
|
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, torControlPort);
|
||||||
|
eventBus.addListener(plugin);
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import com.sun.jna.Library;
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
|
||||||
|
import net.freehaven.tor.control.TorControlConnection;
|
||||||
|
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginCallback;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginException;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class WindowsTorPlugin extends JavaTorPlugin {
|
||||||
|
|
||||||
|
WindowsTorPlugin(Executor ioExecutor,
|
||||||
|
Executor wakefulIoExecutor,
|
||||||
|
NetworkManager networkManager,
|
||||||
|
LocationUtils locationUtils,
|
||||||
|
SocketFactory torSocketFactory,
|
||||||
|
Clock clock,
|
||||||
|
ResourceProvider resourceProvider,
|
||||||
|
CircumventionProvider circumventionProvider,
|
||||||
|
BatteryManager batteryManager,
|
||||||
|
Backoff backoff,
|
||||||
|
TorRendezvousCrypto torRendezvousCrypto,
|
||||||
|
PluginCallback callback,
|
||||||
|
String architecture,
|
||||||
|
long maxLatency,
|
||||||
|
int maxIdleTime,
|
||||||
|
File torDirectory,
|
||||||
|
int torSocksPort,
|
||||||
|
int torControlPort) {
|
||||||
|
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
|
||||||
|
torSocketFactory, clock, resourceProvider,
|
||||||
|
circumventionProvider, batteryManager, backoff,
|
||||||
|
torRendezvousCrypto, callback, architecture,
|
||||||
|
maxLatency, maxIdleTime, torDirectory, torSocksPort, torControlPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File getTorExecutableFile() {
|
||||||
|
return new File(torDirectory, "tor.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InputStream getConfigInputStream() {
|
||||||
|
StringBuilder strb = new StringBuilder();
|
||||||
|
append(strb, "ControlPort", torControlPort);
|
||||||
|
append(strb, "CookieAuthentication", 1);
|
||||||
|
append(strb, "DisableNetwork", 1);
|
||||||
|
append(strb, "RunAsDaemon", 1);
|
||||||
|
append(strb, "SafeSocks", 1);
|
||||||
|
append(strb, "SocksPort", torSocksPort);
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(
|
||||||
|
strb.toString().getBytes(Charset.forName("UTF-8")));
|
||||||
|
InputStream windowsPaths = new ByteArrayInputStream(getTorrcPaths());
|
||||||
|
inputStream = new SequenceInputStream(inputStream, windowsPaths);
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getTorrcPaths() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append("GeoIPFile ");
|
||||||
|
sb.append(geoIpFile.getAbsolutePath());
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append("GeoIPv6File ");
|
||||||
|
sb.append(geoIpFile.getAbsolutePath());
|
||||||
|
sb.append("6");
|
||||||
|
sb.append("\n");
|
||||||
|
sb.append("DataDirectory ");
|
||||||
|
sb.append(torDirectory);
|
||||||
|
sb.append("\\.tor");
|
||||||
|
return sb.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() throws PluginException {
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
- properly handle and throw PluginExceptions etc.
|
||||||
|
- absolute paths in Windows torrc (Linux too?)
|
||||||
|
- don't do 10 seconds sleep in main thread
|
||||||
|
*/
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
|
if (!torDirectory.exists()) {
|
||||||
|
if (!torDirectory.mkdirs()) {
|
||||||
|
LOG.warning("Could not create Tor directory.");
|
||||||
|
throw new PluginException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load the settings
|
||||||
|
settings = migrateSettings(callback.getSettings());
|
||||||
|
// Install or update the assets if necessary
|
||||||
|
if (!assetsAreUpToDate()) installAssets();
|
||||||
|
if (cookieFile.exists() && !cookieFile.delete())
|
||||||
|
LOG.warning("Old auth cookie not deleted");
|
||||||
|
// Start a new Tor process
|
||||||
|
LOG.info("Starting Tor");
|
||||||
|
File torFile = getTorExecutableFile();
|
||||||
|
String torPath = torFile.getAbsolutePath();
|
||||||
|
String configPath = configFile.getAbsolutePath();
|
||||||
|
String pid = String.valueOf(getProcessId());
|
||||||
|
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Process torProcess;
|
||||||
|
ProcessBuilder pb =
|
||||||
|
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
|
||||||
|
pb.redirectErrorStream(true); // logged only first line on Windows otherwise
|
||||||
|
Map<String, String> env = pb.environment();
|
||||||
|
env.put("HOME", torDirectory.getAbsolutePath());
|
||||||
|
pb.directory(torDirectory);
|
||||||
|
try {
|
||||||
|
torProcess = pb.start();
|
||||||
|
// Log the process's standard output until it detaches
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
Scanner stdout = new Scanner(torProcess.getInputStream());
|
||||||
|
while (stdout.hasNextLine()) {
|
||||||
|
if (stdout.hasNextLine()) {
|
||||||
|
LOG.info(stdout.nextLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stdout.close();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Wait for the process to detach or exit
|
||||||
|
int exit = torProcess.waitFor();
|
||||||
|
if (exit != 0) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.warning("Tor exited with value " + exit);
|
||||||
|
}
|
||||||
|
// Wait for the auth cookie file to be created/updated
|
||||||
|
long start = clock.currentTimeMillis();
|
||||||
|
while (cookieFile.length() < 32) {
|
||||||
|
if (clock.currentTimeMillis() - start > COOKIE_TIMEOUT_MS) {
|
||||||
|
LOG.warning("Auth cookie not created");
|
||||||
|
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
|
||||||
|
}
|
||||||
|
Thread.sleep(COOKIE_POLLING_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
LOG.info("Auth cookie created");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOG.warning("Interrupted while starting Tor");
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (SecurityException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(10);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Open a control connection and authenticate using the cookie file
|
||||||
|
controlSocket = new Socket("127.0.0.1", torControlPort);
|
||||||
|
controlConnection = new TorControlConnection(controlSocket);
|
||||||
|
controlConnection.authenticate(read(cookieFile));
|
||||||
|
// Tell Tor to exit when the control connection is closed
|
||||||
|
controlConnection.takeOwnership();
|
||||||
|
controlConnection.resetConf(singletonList(OWNER));
|
||||||
|
// Register to receive events from the Tor process
|
||||||
|
controlConnection.setEventHandler(this);
|
||||||
|
controlConnection.setEvents(asList(EVENTS));
|
||||||
|
// Check whether Tor has already bootstrapped
|
||||||
|
String phase = controlConnection.getInfo("status/bootstrap-phase");
|
||||||
|
if (phase != null && phase.contains("PROGRESS=100")) {
|
||||||
|
LOG.info("Tor has already bootstrapped");
|
||||||
|
state.setBootstrapped();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PluginException(e);
|
||||||
|
}
|
||||||
|
state.setStarted();
|
||||||
|
// Check whether we're online
|
||||||
|
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||||
|
batteryManager.isCharging());
|
||||||
|
// Bind a server socket to receive incoming hidden service connections
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getProcessId() {
|
||||||
|
return CLibrary.INSTANCE._getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface CLibrary extends Library {
|
||||||
|
|
||||||
|
CLibrary INSTANCE = Native.loadLibrary("msvcrt", CLibrary.class);
|
||||||
|
|
||||||
|
int _getpid();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import dagger.Provides;
|
|||||||
|
|
||||||
import static org.briarproject.bramble.util.OsUtils.isLinux;
|
import static org.briarproject.bramble.util.OsUtils.isLinux;
|
||||||
import static org.briarproject.bramble.util.OsUtils.isMac;
|
import static org.briarproject.bramble.util.OsUtils.isMac;
|
||||||
|
import static org.briarproject.bramble.util.OsUtils.isWindows;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
public class DesktopSecureRandomModule {
|
public class DesktopSecureRandomModule {
|
||||||
@@ -18,7 +19,8 @@ public class DesktopSecureRandomModule {
|
|||||||
SecureRandomProvider provideSecureRandomProvider() {
|
SecureRandomProvider provideSecureRandomProvider() {
|
||||||
if (isLinux() || isMac())
|
if (isLinux() || isMac())
|
||||||
return new UnixSecureRandomProvider();
|
return new UnixSecureRandomProvider();
|
||||||
// TODO: Create a secure random provider for Windows
|
if (isWindows())
|
||||||
|
return new WindowsSecureRandomProvider();
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
private final File torDir = getTestDirectory();
|
private final File torDir = getTestDirectory();
|
||||||
private final Params params;
|
private final Params params;
|
||||||
|
|
||||||
private UnixTorPluginFactory factory;
|
private DesktopTorPluginFactory factory;
|
||||||
|
|
||||||
public BridgeTest(Params params) {
|
public BridgeTest(Params params) {
|
||||||
this.params = params;
|
this.params = params;
|
||||||
@@ -152,7 +152,7 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
return singletonList(params.bridge);
|
return singletonList(params.bridge);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor,
|
factory = new DesktopTorPluginFactory(ioExecutor, wakefulIoExecutor,
|
||||||
networkManager, locationUtils, eventBus, torSocketFactory,
|
networkManager, locationUtils, eventBus, torSocketFactory,
|
||||||
backoffFactory, resourceProvider, bridgeProvider,
|
backoffFactory, resourceProvider, bridgeProvider,
|
||||||
batteryManager, clock, torDir, DEFAULT_SOCKS_PORT,
|
batteryManager, clock, torDir, DEFAULT_SOCKS_PORT,
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ dependencyVerification {
|
|||||||
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
|
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
|
||||||
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
|
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
|
||||||
'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
|
'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
|
||||||
'org.briarproject:tor:0.3.5.17:tor-0.3.5.17.jar:ce0e1f4d8f14878e61b23a35a452bc0f2a8e3117ced5a74773cd78475fa7af39',
|
|
||||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
||||||
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
|
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
|
||||||
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
|
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
|
||||||
|
|||||||
Reference in New Issue
Block a user