mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 14:19:53 +01:00
Merge branch '1499-do-not-apply-redundant-settings' into 'master'
Start from default Tor config every time, don't apply redundant settings See merge request briar/briar!1681
This commit is contained in:
@@ -65,6 +65,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
@@ -93,9 +94,7 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
||||||
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.DEFAULT_OBFS4;
|
|
||||||
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
|
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
|
||||||
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4;
|
|
||||||
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
|
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
|
||||||
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
@@ -239,8 +238,14 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
// Load the settings
|
// Load the settings
|
||||||
settings = callback.getSettings();
|
settings = callback.getSettings();
|
||||||
// Install or update the assets if necessary
|
try {
|
||||||
if (!assetsAreUpToDate()) installAssets();
|
// Install or update the assets if necessary
|
||||||
|
if (!assetsAreUpToDate()) installAssets();
|
||||||
|
// Start from the default config every time
|
||||||
|
extract(getConfigInputStream(), configFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PluginException(e);
|
||||||
|
}
|
||||||
if (cookieFile.exists() && !cookieFile.delete())
|
if (cookieFile.exists() && !cookieFile.delete())
|
||||||
LOG.warning("Old auth cookie not deleted");
|
LOG.warning("Old auth cookie not deleted");
|
||||||
// Start a new Tor process
|
// Start a new Tor process
|
||||||
@@ -302,7 +307,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
info = controlConnection.getInfo("status/circuit-established");
|
info = controlConnection.getInfo("status/circuit-established");
|
||||||
if ("1".equals(info)) {
|
if ("1".equals(info)) {
|
||||||
LOG.info("Tor has already built a circuit");
|
LOG.info("Tor has already built a circuit");
|
||||||
state.getAndSetCircuitBuilt(true);
|
state.setCircuitBuilt(true);
|
||||||
}
|
}
|
||||||
} catch (TorNotRunningException e) {
|
} catch (TorNotRunningException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@@ -321,25 +326,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
return doneFile.lastModified() > getLastUpdateTime();
|
return doneFile.lastModified() > getLastUpdateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installAssets() throws PluginException {
|
private void installAssets() throws IOException {
|
||||||
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
|
doneFile.delete();
|
||||||
doneFile.delete();
|
// The GeoIP file may exist from a previous installation - we can
|
||||||
// The GeoIP file may exist from a previous installation - we can
|
// save some space by deleting it.
|
||||||
// save some space by deleting it.
|
// TODO: Remove after a reasonable migration period
|
||||||
// TODO: Remove after a reasonable migration period
|
// (added 2022-03-29)
|
||||||
// (added 2022-03-29)
|
//noinspection ResultOfMethodCallIgnored
|
||||||
//noinspection ResultOfMethodCallIgnored
|
geoIpFile.delete();
|
||||||
geoIpFile.delete();
|
installTorExecutable();
|
||||||
installTorExecutable();
|
installObfs4Executable();
|
||||||
installObfs4Executable();
|
if (!doneFile.createNewFile())
|
||||||
extract(getConfigInputStream(), configFile);
|
LOG.warning("Failed to create done file");
|
||||||
if (!doneFile.createNewFile())
|
|
||||||
LOG.warning("Failed to create done file");
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new PluginException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void extract(InputStream in, File dest) throws IOException {
|
protected void extract(InputStream in, File dest) throws IOException {
|
||||||
@@ -398,6 +398,10 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
append(strb, "SocksPort", torSocksPort);
|
append(strb, "SocksPort", torSocksPort);
|
||||||
strb.append("GeoIPFile\n");
|
strb.append("GeoIPFile\n");
|
||||||
strb.append("GeoIPv6File\n");
|
strb.append("GeoIPv6File\n");
|
||||||
|
append(strb, "ConnectionPadding", 0);
|
||||||
|
String obfs4Path = getObfs4ExecutableFile().getAbsolutePath();
|
||||||
|
append(strb, "ClientTransportPlugin obfs4 exec", obfs4Path);
|
||||||
|
append(strb, "ClientTransportPlugin meek_lite exec", obfs4Path);
|
||||||
//noinspection CharsetObjectCanBeUsed
|
//noinspection CharsetObjectCanBeUsed
|
||||||
return new ByteArrayInputStream(
|
return new ByteArrayInputStream(
|
||||||
strb.toString().getBytes(Charset.forName("UTF-8")));
|
strb.toString().getBytes(Charset.forName("UTF-8")));
|
||||||
@@ -547,7 +551,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void enableNetwork(boolean enable) throws IOException {
|
protected void enableNetwork(boolean enable) throws IOException {
|
||||||
state.enableNetwork(enable);
|
if (!state.enableNetwork(enable)) return; // Unchanged
|
||||||
try {
|
try {
|
||||||
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
||||||
} catch (TorNotRunningException e) {
|
} catch (TorNotRunningException e) {
|
||||||
@@ -555,28 +559,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableBridges(boolean enable, List<BridgeType> bridgeTypes)
|
private void enableBridges(List<BridgeType> bridgeTypes)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (!state.setBridgeTypes(bridgeTypes)) return; // Unchanged
|
||||||
try {
|
try {
|
||||||
if (enable) {
|
if (bridgeTypes.isEmpty()) {
|
||||||
|
controlConnection.setConf("UseBridges", "0");
|
||||||
|
controlConnection.resetConf(singletonList("Bridge"));
|
||||||
|
} else {
|
||||||
Collection<String> conf = new ArrayList<>();
|
Collection<String> conf = new ArrayList<>();
|
||||||
conf.add("UseBridges 1");
|
conf.add("UseBridges 1");
|
||||||
File obfs4File = getObfs4ExecutableFile();
|
|
||||||
if (bridgeTypes.contains(MEEK)) {
|
|
||||||
conf.add("ClientTransportPlugin meek_lite exec " +
|
|
||||||
obfs4File.getAbsolutePath());
|
|
||||||
}
|
|
||||||
if (bridgeTypes.contains(DEFAULT_OBFS4) ||
|
|
||||||
bridgeTypes.contains(NON_DEFAULT_OBFS4)) {
|
|
||||||
conf.add("ClientTransportPlugin obfs4 exec " +
|
|
||||||
obfs4File.getAbsolutePath());
|
|
||||||
}
|
|
||||||
for (BridgeType bridgeType : bridgeTypes) {
|
for (BridgeType bridgeType : bridgeTypes) {
|
||||||
conf.addAll(circumventionProvider.getBridges(bridgeType));
|
conf.addAll(circumventionProvider.getBridges(bridgeType));
|
||||||
}
|
}
|
||||||
controlConnection.setConf(conf);
|
controlConnection.setConf(conf);
|
||||||
} else {
|
|
||||||
controlConnection.setConf("UseBridges", "0");
|
|
||||||
}
|
}
|
||||||
} catch (TorNotRunningException e) {
|
} catch (TorNotRunningException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@@ -758,7 +754,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
public void circuitStatus(String status, String id, String path) {
|
public void circuitStatus(String status, String id, String path) {
|
||||||
// In case of races between receiving CIRCUIT_ESTABLISHED and setting
|
// In case of races between receiving CIRCUIT_ESTABLISHED and setting
|
||||||
// DisableNetwork, set our circuitBuilt flag if not already set
|
// DisableNetwork, set our circuitBuilt flag if not already set
|
||||||
if (status.equals("BUILT") && !state.getAndSetCircuitBuilt(true)) {
|
if (status.equals("BUILT") && state.setCircuitBuilt(true)) {
|
||||||
LOG.info("Circuit built");
|
LOG.info("Circuit built");
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
}
|
}
|
||||||
@@ -815,12 +811,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
state.setBootstrapped();
|
state.setBootstrapped();
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
} else if (msg.startsWith("CIRCUIT_ESTABLISHED")) {
|
} else if (msg.startsWith("CIRCUIT_ESTABLISHED")) {
|
||||||
if (!state.getAndSetCircuitBuilt(true)) {
|
if (state.setCircuitBuilt(true)) {
|
||||||
LOG.info("Circuit built");
|
LOG.info("Circuit built");
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
}
|
}
|
||||||
} else if (msg.startsWith("CIRCUIT_NOT_ESTABLISHED")) {
|
} else if (msg.startsWith("CIRCUIT_NOT_ESTABLISHED")) {
|
||||||
if (state.getAndSetCircuitBuilt(false)) {
|
if (state.setCircuitBuilt(false)) {
|
||||||
LOG.info("Circuit not built");
|
LOG.info("Circuit not built");
|
||||||
// TODO: Disable and re-enable network to prompt Tor to rebuild
|
// TODO: Disable and re-enable network to prompt Tor to rebuild
|
||||||
// its guard/bridge connections? This will also close any
|
// its guard/bridge connections? This will also close any
|
||||||
@@ -911,10 +907,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int reasonsDisabled = 0;
|
int reasonsDisabled = 0;
|
||||||
boolean enableNetwork = false, enableBridges = false;
|
boolean enableNetwork = false, enableConnectionPadding = false;
|
||||||
boolean enableConnectionPadding = false;
|
List<BridgeType> bridgeTypes = emptyList();
|
||||||
List<BridgeType> bridgeTypes =
|
|
||||||
circumventionProvider.getSuitableBridgeTypes(country);
|
|
||||||
|
|
||||||
if (!online) {
|
if (!online) {
|
||||||
LOG.info("Disabling network, device is offline");
|
LOG.info("Disabling network, device is offline");
|
||||||
@@ -943,8 +937,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
enableNetwork = true;
|
enableNetwork = true;
|
||||||
if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
|
if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
|
||||||
(automatic && bridgesWork)) {
|
(automatic && bridgesWork)) {
|
||||||
if (ipv6Only) bridgeTypes = singletonList(MEEK);
|
if (ipv6Only) {
|
||||||
enableBridges = true;
|
bridgeTypes = singletonList(MEEK);
|
||||||
|
} else {
|
||||||
|
bridgeTypes = circumventionProvider
|
||||||
|
.getSuitableBridgeTypes(country);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Using bridge types " + bridgeTypes);
|
LOG.info("Using bridge types " + bridgeTypes);
|
||||||
}
|
}
|
||||||
@@ -964,9 +962,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (enableNetwork) {
|
if (enableNetwork) {
|
||||||
enableBridges(enableBridges, bridgeTypes);
|
enableBridges(bridgeTypes);
|
||||||
enableConnectionPadding(enableConnectionPadding);
|
enableConnectionPadding(enableConnectionPadding);
|
||||||
useIpv6(ipv6Only);
|
enableIpv6(ipv6Only);
|
||||||
}
|
}
|
||||||
enableNetwork(enableNetwork);
|
enableNetwork(enableNetwork);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -976,6 +974,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void enableConnectionPadding(boolean enable) throws IOException {
|
private void enableConnectionPadding(boolean enable) throws IOException {
|
||||||
|
if (!state.enableConnectionPadding(enable)) return; // Unchanged
|
||||||
try {
|
try {
|
||||||
controlConnection.setConf("ConnectionPadding", enable ? "1" : "0");
|
controlConnection.setConf("ConnectionPadding", enable ? "1" : "0");
|
||||||
} catch (TorNotRunningException e) {
|
} catch (TorNotRunningException e) {
|
||||||
@@ -983,10 +982,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void useIpv6(boolean ipv6Only) throws IOException {
|
private void enableIpv6(boolean enable) throws IOException {
|
||||||
|
if (!state.enableIpv6(enable)) return; // Unchanged
|
||||||
try {
|
try {
|
||||||
controlConnection.setConf("ClientUseIPv4", ipv6Only ? "0" : "1");
|
controlConnection.setConf("ClientUseIPv4", enable ? "0" : "1");
|
||||||
controlConnection.setConf("ClientUseIPv6", ipv6Only ? "1" : "0");
|
controlConnection.setConf("ClientUseIPv6", enable ? "1" : "0");
|
||||||
} catch (TorNotRunningException e) {
|
} catch (TorNotRunningException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -1001,6 +1001,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
stopped = false,
|
stopped = false,
|
||||||
networkInitialised = false,
|
networkInitialised = false,
|
||||||
networkEnabled = false,
|
networkEnabled = false,
|
||||||
|
paddingEnabled = false,
|
||||||
|
ipv6Enabled = false,
|
||||||
bootstrapped = false,
|
bootstrapped = false,
|
||||||
circuitBuilt = false,
|
circuitBuilt = false,
|
||||||
settingsChecked = false;
|
settingsChecked = false;
|
||||||
@@ -1015,6 +1017,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private int orConnectionsConnected = 0;
|
private int orConnectionsConnected = 0;
|
||||||
|
|
||||||
|
@GuardedBy("this")
|
||||||
|
private List<BridgeType> bridgeTypes = emptyList();
|
||||||
|
|
||||||
private synchronized void setStarted() {
|
private synchronized void setStarted() {
|
||||||
started = true;
|
started = true;
|
||||||
callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
@@ -1035,28 +1040,66 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void setBootstrapped() {
|
private synchronized void setBootstrapped() {
|
||||||
|
boolean wasBootstrapped = bootstrapped;
|
||||||
bootstrapped = true;
|
bootstrapped = true;
|
||||||
callback.pluginStateChanged(getState());
|
if (!wasBootstrapped) callback.pluginStateChanged(getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean getAndSetCircuitBuilt(boolean built) {
|
/**
|
||||||
boolean old = circuitBuilt;
|
* Sets the `circuitBuilt` flag and returns true if the flag has
|
||||||
|
* changed.
|
||||||
|
*/
|
||||||
|
private synchronized boolean setCircuitBuilt(boolean built) {
|
||||||
|
if (built == circuitBuilt) return false; // Unchanged
|
||||||
circuitBuilt = built;
|
circuitBuilt = built;
|
||||||
if (built != old) callback.pluginStateChanged(getState());
|
callback.pluginStateChanged(getState());
|
||||||
return old;
|
return true; // Changed
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void enableNetwork(boolean enable) {
|
/**
|
||||||
|
* Sets the `networkEnabled` flag and returns true if the flag has
|
||||||
|
* changed.
|
||||||
|
*/
|
||||||
|
private synchronized boolean enableNetwork(boolean enable) {
|
||||||
|
boolean wasInitialised = networkInitialised;
|
||||||
|
boolean wasEnabled = networkEnabled;
|
||||||
networkInitialised = true;
|
networkInitialised = true;
|
||||||
networkEnabled = enable;
|
networkEnabled = enable;
|
||||||
if (!enable) circuitBuilt = false;
|
if (!enable) circuitBuilt = false;
|
||||||
callback.pluginStateChanged(getState());
|
if (!wasInitialised || enable != wasEnabled) {
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
|
}
|
||||||
|
return enable != wasEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void setReasonsDisabled(int reasonsDisabled) {
|
/**
|
||||||
|
* Sets the `paddingEnabled` flag and returns true if the flag has
|
||||||
|
* changed. Doesn't affect getState().
|
||||||
|
*/
|
||||||
|
private synchronized boolean enableConnectionPadding(boolean enable) {
|
||||||
|
if (enable == paddingEnabled) return false; // Unchanged
|
||||||
|
paddingEnabled = enable;
|
||||||
|
return true; // Changed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the `ipv6Enabled` flag and returns true if the flag has
|
||||||
|
* changed. Doesn't affect getState().
|
||||||
|
*/
|
||||||
|
private synchronized boolean enableIpv6(boolean enable) {
|
||||||
|
if (enable == ipv6Enabled) return false; // Unchanged
|
||||||
|
ipv6Enabled = enable;
|
||||||
|
return true; // Changed
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void setReasonsDisabled(int reasons) {
|
||||||
|
boolean wasChecked = settingsChecked;
|
||||||
settingsChecked = true;
|
settingsChecked = true;
|
||||||
this.reasonsDisabled = reasonsDisabled;
|
int oldReasons = reasonsDisabled;
|
||||||
callback.pluginStateChanged(getState());
|
reasonsDisabled = reasons;
|
||||||
|
if (!wasChecked || reasons != oldReasons) {
|
||||||
|
callback.pluginStateChanged(getState());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't affect getState()
|
// Doesn't affect getState()
|
||||||
@@ -1071,6 +1114,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (serverSocket == ss) serverSocket = null;
|
if (serverSocket == ss) serverSocket = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of bridge types being used and returns true if the
|
||||||
|
* list has changed. The list is empty if bridges are disabled.
|
||||||
|
* Doesn't affect getState().
|
||||||
|
*/
|
||||||
|
private synchronized boolean setBridgeTypes(List<BridgeType> types) {
|
||||||
|
if (types.equals(bridgeTypes)) return false; // Unchanged
|
||||||
|
bridgeTypes = types;
|
||||||
|
return true; // Changed
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized State getState() {
|
private synchronized State getState() {
|
||||||
if (!started || stopped || !settingsChecked) {
|
if (!started || stopped || !settingsChecked) {
|
||||||
return STARTING_STOPPING;
|
return STARTING_STOPPING;
|
||||||
|
|||||||
Reference in New Issue
Block a user