Merge branch '1259-headless-mac-os' into 'master'

Enable headless app to start on MacOS

See merge request briar/briar!1003
This commit is contained in:
Torsten Grote
2018-11-26 12:01:27 +00:00
14 changed files with 144 additions and 101 deletions

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.system; package org.briarproject.bramble.system;
import android.annotation.SuppressLint;
import android.app.Application; import android.app.Application;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
@@ -26,7 +27,7 @@ import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class AndroidSecureRandomProvider extends LinuxSecureRandomProvider { class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
private static final int SEED_LENGTH = 32; private static final int SEED_LENGTH = 32;
@@ -37,6 +38,7 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
appContext = app.getApplicationContext(); appContext = app.getApplicationContext();
} }
@SuppressLint("HardwareIds")
@Override @Override
protected void writeToEntropyPool(DataOutputStream out) throws IOException { protected void writeToEntropyPool(DataOutputStream out) throws IOException {
super.writeToEntropyPool(out); super.writeToEntropyPool(out);
@@ -49,12 +51,14 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
String id = Settings.Secure.getString(contentResolver, ANDROID_ID); String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
if (id != null) out.writeUTF(id); if (id != null) out.writeUTF(id);
Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain();
WifiManager wm = WifiManager wm = (WifiManager) appContext.getApplicationContext()
(WifiManager) appContext.getSystemService(WIFI_SERVICE); .getSystemService(WIFI_SERVICE);
List<WifiConfiguration> configs = wm.getConfiguredNetworks(); if (wm != null) {
if (configs != null) { List<WifiConfiguration> configs = wm.getConfiguredNetworks();
for (WifiConfiguration config : configs) if (configs != null) {
parcel.writeParcelable(config, 0); for (WifiConfiguration config : configs)
parcel.writeParcelable(config, 0);
}
} }
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) { if (bt != null) {
@@ -77,13 +81,13 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html // Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private void applyOpenSslFix() { private void applyOpenSslFix() {
byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed( byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
SEED_LENGTH); SEED_LENGTH);
try { try {
// Seed the OpenSSL PRNG // Seed the OpenSSL PRNG
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class) .getMethod("RAND_seed", byte[].class)
.invoke(null, seed); .invoke(null, (Object) seed);
// Mix the output of the Linux PRNG into the OpenSSL PRNG // Mix the output of the Linux PRNG into the OpenSSL PRNG
int bytesRead = (Integer) Class.forName( int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto") "org.apache.harmony.xnet.provider.jsse.NativeCrypto")

View File

@@ -10,8 +10,6 @@ public class OsUtils {
@Nullable @Nullable
private static final String os = System.getProperty("os.name"); private static final String os = System.getProperty("os.name");
@Nullable @Nullable
private static final String version = System.getProperty("os.version");
@Nullable
private static final String vendor = System.getProperty("java.vendor"); private static final String vendor = System.getProperty("java.vendor");
public static boolean isWindows() { public static boolean isWindows() {

View File

@@ -13,32 +13,33 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class LinuxSecureRandomProvider extends AbstractSecureRandomProvider { class UnixSecureRandomProvider extends AbstractSecureRandomProvider {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(LinuxSecureRandomProvider.class.getName()); getLogger(UnixSecureRandomProvider.class.getName());
private static final File RANDOM_DEVICE = new File("/dev/urandom"); private static final File RANDOM_DEVICE = new File("/dev/urandom");
private final AtomicBoolean seeded = new AtomicBoolean(false); private final AtomicBoolean seeded = new AtomicBoolean(false);
private final File outputDevice; private final File outputDevice;
LinuxSecureRandomProvider() { UnixSecureRandomProvider() {
this(RANDOM_DEVICE); this(RANDOM_DEVICE);
} }
LinuxSecureRandomProvider(File outputDevice) { UnixSecureRandomProvider(File outputDevice) {
this.outputDevice = outputDevice; this.outputDevice = outputDevice;
} }
@Override @Override
public Provider getProvider() { public Provider getProvider() {
if (!seeded.getAndSet(true)) writeSeed(); if (!seeded.getAndSet(true)) writeSeed();
return new LinuxProvider(); return new UnixProvider();
} }
protected void writeSeed() { protected void writeSeed() {
@@ -55,15 +56,15 @@ class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
} }
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html // Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private static class LinuxProvider extends Provider { private static class UnixProvider extends Provider {
private LinuxProvider() { private UnixProvider() {
super("LinuxPRNG", 1.1, "A Linux-specific PRNG using /dev/urandom"); super("UnixPRNG", 1.0, "A Unix-specific PRNG using /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some callers // Although /dev/urandom is not a SHA-1 PRNG, some callers
// explicitly request a SHA1PRNG SecureRandom and we need to // explicitly request a SHA1PRNG SecureRandom and we need to
// prevent them from getting the default implementation whose // prevent them from getting the default implementation whose
// output may have low entropy. // output may have low entropy.
put("SecureRandom.SHA1PRNG", LinuxSecureRandomSpi.class.getName()); put("SecureRandom.SHA1PRNG", UnixSecureRandomSpi.class.getName());
put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
} }
} }

View File

@@ -10,22 +10,24 @@ import java.security.SecureRandomSpi;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
public class LinuxSecureRandomSpi extends SecureRandomSpi { public class UnixSecureRandomSpi extends SecureRandomSpi {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(LinuxSecureRandomSpi.class.getName()); getLogger(UnixSecureRandomSpi.class.getName());
private static final File RANDOM_DEVICE = new File("/dev/urandom"); private static final File RANDOM_DEVICE = new File("/dev/urandom");
private final File inputDevice, outputDevice; private final File inputDevice, outputDevice;
public LinuxSecureRandomSpi() { @SuppressWarnings("WeakerAccess")
public UnixSecureRandomSpi() {
this(RANDOM_DEVICE, RANDOM_DEVICE); this(RANDOM_DEVICE, RANDOM_DEVICE);
} }
LinuxSecureRandomSpi(File inputDevice, File outputDevice) { UnixSecureRandomSpi(File inputDevice, File outputDevice) {
this.inputDevice = inputDevice; this.inputDevice = inputDevice;
this.outputDevice = outputDevice; this.outputDevice = outputDevice;
} }

View File

@@ -1,8 +1,6 @@
package org.briarproject.bramble.system; package org.briarproject.bramble.system;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.OsUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -10,48 +8,50 @@ import org.junit.Test;
import java.io.File; import java.io.File;
import java.security.Provider; import java.security.Provider;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.OsUtils.isLinux;
import static org.briarproject.bramble.util.OsUtils.isMac;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
public class LinuxSecureRandomProviderTest extends BrambleTestCase { public class UnixSecureRandomProviderTest extends BrambleTestCase {
private final File testDir = TestUtils.getTestDirectory(); private final File testDir = getTestDirectory();
@Before @Before
public void setUp() { public void setUp() {
testDir.mkdirs(); assumeTrue(isLinux() || isMac());
assertTrue(testDir.mkdirs());
} }
@Test @Test
public void testGetProviderWritesToRandomDeviceOnFirstCall() public void testGetProviderWritesToRandomDeviceOnFirstCall()
throws Exception { throws Exception {
if (!(OsUtils.isLinux())) {
System.err.println("WARNING: Skipping test, can't run on this OS");
return;
}
// Redirect the provider's output to a file // Redirect the provider's output to a file
File urandom = new File(testDir, "urandom"); File urandom = new File(testDir, "urandom");
urandom.delete(); if (urandom.exists()) assertTrue(urandom.delete());
assertTrue(urandom.createNewFile()); assertTrue(urandom.createNewFile());
assertEquals(0, urandom.length()); assertEquals(0, urandom.length());
LinuxSecureRandomProvider p = new LinuxSecureRandomProvider(urandom); UnixSecureRandomProvider p = new UnixSecureRandomProvider(urandom);
// Getting a provider should write entropy to the file // Getting a provider should write entropy to the file
Provider provider = p.getProvider(); Provider provider = p.getProvider();
assertNotNull(provider); assertNotNull(provider);
assertEquals("LinuxPRNG", provider.getName()); assertEquals("UnixPRNG", provider.getName());
// There should be at least 16 bytes from the clock, 8 from the runtime // There should be at least 16 bytes from the clock, 8 from the runtime
long length = urandom.length(); long length = urandom.length();
assertTrue(length >= 24); assertTrue(length >= 24);
// Getting another provider should not write to the file again // Getting another provider should not write to the file again
provider = p.getProvider(); provider = p.getProvider();
assertNotNull(provider); assertNotNull(provider);
assertEquals("LinuxPRNG", provider.getName()); assertEquals("UnixPRNG", provider.getName());
assertEquals(length, urandom.length()); assertEquals(length, urandom.length());
} }
@After @After
public void tearDown() { public void tearDown() {
TestUtils.deleteTestDirectory(testDir); deleteTestDirectory(testDir);
} }
} }

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.OsUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -15,31 +14,33 @@ import java.io.FileOutputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.OsUtils.isLinux;
import static org.briarproject.bramble.util.OsUtils.isMac;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
public class LinuxSecureRandomSpiTest extends BrambleTestCase { public class UnixSecureRandomSpiTest extends BrambleTestCase {
private static final File RANDOM_DEVICE = new File("/dev/urandom"); private static final File RANDOM_DEVICE = new File("/dev/urandom");
private static final int SEED_BYTES = 32; private static final int SEED_BYTES = 32;
private final File testDir = TestUtils.getTestDirectory(); private final File testDir = getTestDirectory();
@Before @Before
public void setUp() { public void setUp() {
testDir.mkdirs(); assumeTrue(isLinux() || isMac());
assertTrue(testDir.mkdirs());
} }
@Test @Test
public void testSeedsAreDistinct() { public void testSeedsAreDistinct() {
if (!(OsUtils.isLinux())) {
System.err.println("WARNING: Skipping test, can't run on this OS");
return;
}
Set<Bytes> seeds = new HashSet<>(); Set<Bytes> seeds = new HashSet<>();
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(); UnixSecureRandomSpi engine = new UnixSecureRandomSpi();
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
byte[] seed = engine.engineGenerateSeed(SEED_BYTES); byte[] seed = engine.engineGenerateSeed(SEED_BYTES);
assertEquals(SEED_BYTES, seed.length); assertEquals(SEED_BYTES, seed.length);
@@ -49,19 +50,15 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
@Test @Test
public void testEngineSetSeedWritesToRandomDevice() throws Exception { public void testEngineSetSeedWritesToRandomDevice() throws Exception {
if (!(OsUtils.isLinux())) {
System.err.println("WARNING: Skipping test, can't run on this OS");
return;
}
// Redirect the engine's output to a file // Redirect the engine's output to a file
File urandom = new File(testDir, "urandom"); File urandom = new File(testDir, "urandom");
urandom.delete(); if (urandom.exists()) assertTrue(urandom.delete());
assertTrue(urandom.createNewFile()); assertTrue(urandom.createNewFile());
assertEquals(0, urandom.length()); assertEquals(0, urandom.length());
// Generate a seed // Generate a seed
byte[] seed = TestUtils.getRandomBytes(SEED_BYTES); byte[] seed = TestUtils.getRandomBytes(SEED_BYTES);
// Check that the engine writes the seed to the file // Check that the engine writes the seed to the file
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(RANDOM_DEVICE, UnixSecureRandomSpi engine = new UnixSecureRandomSpi(RANDOM_DEVICE,
urandom); urandom);
engine.engineSetSeed(seed); engine.engineSetSeed(seed);
assertEquals(SEED_BYTES, urandom.length()); assertEquals(SEED_BYTES, urandom.length());
@@ -74,15 +71,11 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
@Test @Test
public void testEngineNextBytesReadsFromRandomDevice() throws Exception { public void testEngineNextBytesReadsFromRandomDevice() throws Exception {
if (!(OsUtils.isLinux())) {
System.err.println("WARNING: Skipping test, can't run on this OS");
return;
}
// Generate some entropy // Generate some entropy
byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES); byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES);
// Write the entropy to a file // Write the entropy to a file
File urandom = new File(testDir, "urandom"); File urandom = new File(testDir, "urandom");
urandom.delete(); if (urandom.exists()) assertTrue(urandom.delete());
FileOutputStream out = new FileOutputStream(urandom); FileOutputStream out = new FileOutputStream(urandom);
out.write(entropy); out.write(entropy);
out.flush(); out.flush();
@@ -90,7 +83,7 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
assertTrue(urandom.exists()); assertTrue(urandom.exists());
assertEquals(SEED_BYTES, urandom.length()); assertEquals(SEED_BYTES, urandom.length());
// Check that the engine reads from the file // Check that the engine reads from the file
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(urandom, UnixSecureRandomSpi engine = new UnixSecureRandomSpi(urandom,
RANDOM_DEVICE); RANDOM_DEVICE);
byte[] b = new byte[SEED_BYTES]; byte[] b = new byte[SEED_BYTES];
engine.engineNextBytes(b); engine.engineNextBytes(b);
@@ -99,15 +92,11 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
@Test @Test
public void testEngineGenerateSeedReadsFromRandomDevice() throws Exception { public void testEngineGenerateSeedReadsFromRandomDevice() throws Exception {
if (!(OsUtils.isLinux())) {
System.err.println("WARNING: Skipping test, can't run on this OS");
return;
}
// Generate some entropy // Generate some entropy
byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES); byte[] entropy = TestUtils.getRandomBytes(SEED_BYTES);
// Write the entropy to a file // Write the entropy to a file
File urandom = new File(testDir, "urandom"); File urandom = new File(testDir, "urandom");
urandom.delete(); if (urandom.exists()) assertTrue(urandom.delete());
FileOutputStream out = new FileOutputStream(urandom); FileOutputStream out = new FileOutputStream(urandom);
out.write(entropy); out.write(entropy);
out.flush(); out.flush();
@@ -115,7 +104,7 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
assertTrue(urandom.exists()); assertTrue(urandom.exists());
assertEquals(SEED_BYTES, urandom.length()); assertEquals(SEED_BYTES, urandom.length());
// Check that the engine reads from the file // Check that the engine reads from the file
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi(urandom, UnixSecureRandomSpi engine = new UnixSecureRandomSpi(urandom,
RANDOM_DEVICE); RANDOM_DEVICE);
byte[] b = engine.engineGenerateSeed(SEED_BYTES); byte[] b = engine.engineGenerateSeed(SEED_BYTES);
assertArrayEquals(entropy, b); assertArrayEquals(entropy, b);
@@ -123,6 +112,6 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
@After @After
public void tearDown() { public void tearDown() {
TestUtils.deleteTestDirectory(testDir); deleteTestDirectory(testDir);
} }
} }

View File

@@ -1,20 +1,21 @@
package org.briarproject.bramble.lifecycle; package org.briarproject.bramble.lifecycle;
import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.util.OsUtils;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static org.briarproject.bramble.util.OsUtils.isWindows;
@Module @Module
public class DesktopLifecycleModule extends LifecycleModule { public class DesktopLifecycleModule extends LifecycleModule {
@Provides @Provides
@Singleton @Singleton
ShutdownManager provideDesktopShutdownManager() { ShutdownManager provideDesktopShutdownManager() {
if (OsUtils.isWindows()) return new WindowsShutdownManagerImpl(); if (isWindows()) return new WindowsShutdownManagerImpl();
else return new ShutdownManagerImpl(); else return new ShutdownManagerImpl();
} }
} }

View File

@@ -15,7 +15,6 @@ import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper; import com.sun.jna.win32.W32APITypeMapper;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.OsUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -29,6 +28,7 @@ import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER;
import static com.sun.jna.Library.OPTION_TYPE_MAPPER; import static com.sun.jna.Library.OPTION_TYPE_MAPPER;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.OsUtils.isWindows;
@ThreadSafe @ThreadSafe
@NotNullByDefault @NotNullByDefault
@@ -71,7 +71,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
// Locking: lock // Locking: lock
private void initialise() { private void initialise() {
if (OsUtils.isWindows()) { if (isWindows()) {
new EventLoop().start(); new EventLoop().start();
} else { } else {
LOG.warning("Windows shutdown manager used on non-Windows OS"); LOG.warning("Windows shutdown manager used on non-Windows OS");
@@ -111,7 +111,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
public void run() { public void run() {
try { try {
// Load user32.dll // Load user32.dll
User32 user32 = (User32) Native.loadLibrary("user32", User32 user32 = Native.loadLibrary("user32",
User32.class, options); User32.class, options);
// Create a callback to handle the WM_QUERYENDSESSION message // Create a callback to handle the WM_QUERYENDSESSION message
WindowProc proc = (hwnd, msg, wp, lp) -> { WindowProc proc = (hwnd, msg, wp, lp) -> {

View File

@@ -10,7 +10,6 @@ import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.security.CodeSource; import java.security.CodeSource;
@@ -19,9 +18,9 @@ import java.util.concurrent.Executor;
import javax.net.SocketFactory; import javax.net.SocketFactory;
@NotNullByDefault @NotNullByDefault
class LinuxTorPlugin extends TorPlugin { abstract class JavaTorPlugin extends TorPlugin {
LinuxTorPlugin(Executor ioExecutor, NetworkManager networkManager, JavaTorPlugin(Executor ioExecutor, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory, LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
@@ -34,17 +33,6 @@ class LinuxTorPlugin extends TorPlugin {
torDirectory); torDirectory);
} }
@Override
protected int getProcessId() {
try {
// Java 9: ProcessHandle.current().pid()
return Integer.parseInt(
new File("/proc/self").getCanonicalFile().getName());
} catch (IOException e) {
throw new AssertionError(e);
}
}
@Override @Override
protected long getLastUpdateTime() { protected long getLastUpdateTime() {
CodeSource codeSource = CodeSource codeSource =
@@ -58,5 +46,4 @@ class LinuxTorPlugin extends TorPlugin {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
} }

View File

@@ -0,0 +1,47 @@
package org.briarproject.bramble.plugin.tor;
import com.sun.jna.Library;
import com.sun.jna.Native;
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.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.File;
import java.util.concurrent.Executor;
import javax.net.SocketFactory;
@NotNullByDefault
class UnixTorPlugin extends JavaTorPlugin {
UnixTorPlugin(Executor ioExecutor, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
torDirectory);
}
@Override
protected int getProcessId() {
return CLibrary.INSTANCE.getpid();
}
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid();
}
}

View File

@@ -22,14 +22,15 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.OsUtils.isLinux; import static org.briarproject.bramble.util.OsUtils.isLinux;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class LinuxTorPluginFactory implements DuplexPluginFactory { public class UnixTorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(LinuxTorPluginFactory.class.getName()); getLogger(UnixTorPluginFactory.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
@@ -49,7 +50,7 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
private final Clock clock; private final Clock clock;
private final File torDirectory; private final File torDirectory;
public LinuxTorPluginFactory(Executor ioExecutor, public UnixTorPluginFactory(Executor ioExecutor,
NetworkManager networkManager, LocationUtils locationUtils, NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory, EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, ResourceProvider resourceProvider, BackoffFactory backoffFactory, ResourceProvider resourceProvider,
@@ -95,7 +96,7 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
LinuxTorPlugin plugin = new LinuxTorPlugin(ioExecutor, networkManager, UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, networkManager,
locationUtils, torSocketFactory, clock, resourceProvider, locationUtils, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, callback, circumventionProvider, batteryManager, backoff, callback,
architecture, MAX_LATENCY, MAX_IDLE_TIME, torDirectory); architecture, MAX_LATENCY, MAX_IDLE_TIME, torDirectory);

View File

@@ -1,19 +1,24 @@
package org.briarproject.bramble.system; package org.briarproject.bramble.system;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.OsUtils;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static org.briarproject.bramble.util.OsUtils.isLinux;
import static org.briarproject.bramble.util.OsUtils.isMac;
@Module @Module
public class DesktopSecureRandomModule { public class DesktopSecureRandomModule {
@Provides @Provides
@Singleton @Singleton
SecureRandomProvider provideSecureRandomProvider() { SecureRandomProvider provideSecureRandomProvider() {
return OsUtils.isLinux() ? new LinuxSecureRandomProvider() : null; if (isLinux() || isMac())
return new UnixSecureRandomProvider();
// TODO: Create a secure random provider for Windows
throw new UnsupportedOperationException();
} }
} }

View File

@@ -70,7 +70,7 @@ public class BridgeTest extends BrambleTestCase {
private final File torDir = getTestDirectory(); private final File torDir = getTestDirectory();
private final String bridge; private final String bridge;
private LinuxTorPluginFactory factory; private UnixTorPluginFactory factory;
public BridgeTest(String bridge) { public BridgeTest(String bridge) {
this.bridge = bridge; this.bridge = bridge;
@@ -108,7 +108,7 @@ public class BridgeTest extends BrambleTestCase {
return singletonList(bridge); return singletonList(bridge);
} }
}; };
factory = new LinuxTorPluginFactory(ioExecutor, networkManager, factory = new UnixTorPluginFactory(ioExecutor, networkManager,
locationUtils, eventBus, torSocketFactory, backoffFactory, locationUtils, eventBus, torSocketFactory, backoffFactory,
resourceProvider, bridgeProvider, batteryManager, clock, resourceProvider, bridgeProvider, batteryManager, clock,
torDir); torDir);
@@ -124,7 +124,7 @@ public class BridgeTest extends BrambleTestCase {
DuplexPlugin duplexPlugin = DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack()); factory.createPlugin(new TorPluginCallBack());
assertNotNull(duplexPlugin); assertNotNull(duplexPlugin);
LinuxTorPlugin plugin = (LinuxTorPlugin) duplexPlugin; UnixTorPlugin plugin = (UnixTorPlugin) duplexPlugin;
LOG.warning("Testing " + bridge); LOG.warning("Testing " + bridge);
try { try {

View File

@@ -24,8 +24,10 @@ import org.briarproject.bramble.battery.DefaultBatteryManagerModule
import org.briarproject.bramble.network.JavaNetworkModule import org.briarproject.bramble.network.JavaNetworkModule
import org.briarproject.bramble.plugin.tor.CircumventionModule import org.briarproject.bramble.plugin.tor.CircumventionModule
import org.briarproject.bramble.plugin.tor.CircumventionProvider import org.briarproject.bramble.plugin.tor.CircumventionProvider
import org.briarproject.bramble.plugin.tor.LinuxTorPluginFactory import org.briarproject.bramble.plugin.tor.UnixTorPluginFactory
import org.briarproject.bramble.system.JavaSystemModule import org.briarproject.bramble.system.JavaSystemModule
import org.briarproject.bramble.util.OsUtils.isLinux
import org.briarproject.bramble.util.OsUtils.isMac
import org.briarproject.bramble.util.StringUtils.fromHexString import org.briarproject.bramble.util.StringUtils.fromHexString
import org.briarproject.briar.headless.blogs.HeadlessBlogModule import org.briarproject.briar.headless.blogs.HeadlessBlogModule
import org.briarproject.briar.headless.contact.HeadlessContactModule import org.briarproject.briar.headless.contact.HeadlessContactModule
@@ -70,11 +72,17 @@ internal class HeadlessModule(private val appDir: File) {
circumventionProvider: CircumventionProvider, batteryManager: BatteryManager, clock: Clock circumventionProvider: CircumventionProvider, batteryManager: BatteryManager, clock: Clock
): PluginConfig { ): PluginConfig {
val torDirectory = File(appDir, "tor") val torDirectory = File(appDir, "tor")
val tor = LinuxTorPluginFactory( val duplex: List<DuplexPluginFactory>
ioExecutor, networkManager, locationUtils, eventBus, torSocketFactory, backoffFactory, if (isLinux() || isMac()) {
resourceProvider, circumventionProvider, batteryManager, clock, torDirectory val tor = UnixTorPluginFactory(
) ioExecutor, networkManager, locationUtils, eventBus, torSocketFactory,
val duplex = listOf<DuplexPluginFactory>(tor) backoffFactory, resourceProvider, circumventionProvider, batteryManager, clock,
torDirectory
)
duplex = listOf(tor)
} else {
duplex = emptyList()
}
return object : PluginConfig { return object : PluginConfig {
override fun getDuplexFactories(): Collection<DuplexPluginFactory> { override fun getDuplexFactories(): Collection<DuplexPluginFactory> {
return duplex return duplex