mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Merge branch '592-scrub-addresses-before-logging-them' into 'master'
Scrub addresses before logging them MAC, IP and onion addresses are now scrubbed before logging to ensure we don't leave any sensitive information in plaintext on the device or send it in crash reports or feedback. * Bluetooth MAC addresses keep the first and last octets * IPv4 addresses keep the first and last octets * IPv6 addresses should be scrubbed completely (couldn't test) * Onion addresses keep the first three characters If an address is invalid it will not be scrubbed to enable debugging, because it is most likely not sensitive. Closes #592 See merge request !290
This commit is contained in:
@@ -57,6 +57,7 @@ import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
|
||||
|
||||
class DroidtoothPlugin implements DuplexPlugin {
|
||||
|
||||
@@ -172,7 +173,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||
adapter);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Local address " + address);
|
||||
LOG.info("Local address " + scrubMacAddress(address));
|
||||
if (!StringUtils.isNullOrEmpty(address)) {
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
@@ -237,7 +238,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
String address = s.getRemoteDevice().getAddress();
|
||||
LOG.info("Connection from " + address);
|
||||
LOG.info("Connection from " + scrubMacAddress(address));
|
||||
}
|
||||
backoff.reset();
|
||||
callback.incomingConnectionCreated(wrapSocket(s));
|
||||
@@ -307,6 +308,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
// Validate the address
|
||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
// not scrubbing here to be able to figure out the problem
|
||||
LOG.warning("Invalid address " + address);
|
||||
return null;
|
||||
}
|
||||
@@ -323,13 +325,15 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
BluetoothSocket s = null;
|
||||
try {
|
||||
s = d.createInsecureRfcommSocketToServiceRecord(u);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + address);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to " + scrubMacAddress(address));
|
||||
s.connect();
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + address);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connected to " + scrubMacAddress(address));
|
||||
return s;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Failed to connect to " + address);
|
||||
LOG.info("Failed to connect to " + scrubMacAddress(address));
|
||||
tryToClose(s);
|
||||
return null;
|
||||
}
|
||||
@@ -567,7 +571,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
} else if (action.equals(FOUND)) {
|
||||
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Discovered device: " + d.getAddress());
|
||||
LOG.info("Discovered device: " +
|
||||
scrubMacAddress(d.getAddress()));
|
||||
addresses.add(d.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ 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 {
|
||||
|
||||
@@ -405,7 +406,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
// Publish the hidden service's onion hostname in transport properties
|
||||
String hostname = response.get(HS_ADDRESS);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Hidden service " + hostname);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Hidden service " + scrubOnion(hostname));
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ONION, hostname);
|
||||
callback.mergeLocalProperties(p);
|
||||
@@ -510,21 +512,25 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
String onion = p.get(PROP_ONION);
|
||||
if (StringUtils.isNullOrEmpty(onion)) return null;
|
||||
if (!ONION.matcher(onion).matches()) {
|
||||
// not scrubbing this address, so we are able to find the problem
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + onion);
|
||||
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);
|
||||
s.setSoTimeout(socketTimeout);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + onion);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connected to " + scrubOnion(onion));
|
||||
return new TorTransportConnection(this, s);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Could not connect to " + onion + ": " + e.toString());
|
||||
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
|
||||
e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
|
||||
|
||||
class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
@@ -177,7 +178,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Failed to bind " + addr);
|
||||
LOG.info("Failed to bind " + scrubSocketAddress(addr));
|
||||
tryToClose(ss);
|
||||
}
|
||||
}
|
||||
@@ -205,20 +206,24 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
if (!isConnectable(remote)) {
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
SocketAddress local = socket.getLocalSocketAddress();
|
||||
LOG.info(remote + " is not connectable from " + local);
|
||||
LOG.info(scrubSocketAddress(remote) +
|
||||
" is not connectable from " +
|
||||
scrubSocketAddress(local));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Socket s = new Socket();
|
||||
try {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to " + scrubSocketAddress(remote));
|
||||
s.connect(remote);
|
||||
s.setSoTimeout(socketTimeout);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connected to " + scrubSocketAddress(remote));
|
||||
return new TcpTransportConnection(this, s);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Could not connect to " + remote);
|
||||
LOG.info("Could not connect to " + scrubSocketAddress(remote));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.briarproject.plugins.tcp;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import org.bitlet.weupnp.GatewayDevice;
|
||||
import org.bitlet.weupnp.GatewayDiscover;
|
||||
import org.briarproject.api.lifecycle.ShutdownManager;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
@@ -10,10 +12,9 @@ import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.bitlet.weupnp.GatewayDevice;
|
||||
import org.bitlet.weupnp.GatewayDiscover;
|
||||
import org.briarproject.api.lifecycle.ShutdownManager;
|
||||
import org.xml.sax.SAXException;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.util.PrivacyUtils.scrubInetAddress;
|
||||
|
||||
class PortMapperImpl implements PortMapper {
|
||||
|
||||
@@ -35,7 +36,7 @@ class PortMapperImpl implements PortMapper {
|
||||
InetAddress internal = gateway.getLocalAddress();
|
||||
if (internal == null) return null;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Internal address " + getHostAddress(internal));
|
||||
LOG.info("Internal address " + scrubInetAddress(internal));
|
||||
boolean succeeded = false;
|
||||
InetAddress external = null;
|
||||
try {
|
||||
@@ -50,7 +51,8 @@ class PortMapperImpl implements PortMapper {
|
||||
}
|
||||
String externalString = gateway.getExternalIPAddress();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("External address " + externalString);
|
||||
LOG.info(
|
||||
"External address " + scrubInetAddress(externalString));
|
||||
if (externalString != null)
|
||||
external = InetAddress.getByName(externalString);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
|
||||
|
||||
abstract class TcpPlugin implements DuplexPlugin {
|
||||
|
||||
@@ -107,14 +108,15 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
ServerSocket ss = null;
|
||||
for (SocketAddress addr : getLocalSocketAddresses()) {
|
||||
for (InetSocketAddress addr : getLocalSocketAddresses()) {
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(addr);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Failed to bind " + addr);
|
||||
LOG.info("Failed to bind " +
|
||||
scrubSocketAddress(addr));
|
||||
tryToClose(ss);
|
||||
}
|
||||
}
|
||||
@@ -128,9 +130,11 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
SocketAddress local = ss.getLocalSocketAddress();
|
||||
setLocalSocketAddress((InetSocketAddress) local);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Listening on " + local);
|
||||
InetSocketAddress local =
|
||||
(InetSocketAddress) ss.getLocalSocketAddress();
|
||||
setLocalSocketAddress(local);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Listening on " + scrubSocketAddress(local));
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections();
|
||||
}
|
||||
@@ -166,7 +170,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
return;
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connection from " + s.getRemoteSocketAddress());
|
||||
LOG.info("Connection from " +
|
||||
scrubSocketAddress(s.getRemoteSocketAddress()));
|
||||
backoff.reset();
|
||||
TcpTransportConnection conn = new TcpTransportConnection(this, s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
@@ -223,20 +228,25 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
if (!isConnectable(remote)) {
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
SocketAddress local = socket.getLocalSocketAddress();
|
||||
LOG.info(remote + " is not connectable from " + local);
|
||||
LOG.info(scrubSocketAddress(remote) +
|
||||
" is not connectable from " +
|
||||
scrubSocketAddress(local));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Socket s = new Socket();
|
||||
try {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + remote);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to " + scrubSocketAddress(remote));
|
||||
s.connect(remote);
|
||||
s.setSoTimeout(socketTimeout);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + remote);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connected to " + scrubSocketAddress(remote));
|
||||
return new TcpTransportConnection(this, s);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Could not connect to " + remote);
|
||||
LOG.info("Could not connect to " +
|
||||
scrubSocketAddress(remote));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -255,6 +265,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
return new InetSocketAddress(a, p);
|
||||
} catch (UnknownHostException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
// not scrubbing to enable us to find the problem
|
||||
LOG.warning("Invalid address: " + addr);
|
||||
return null;
|
||||
} catch (NumberFormatException e) {
|
||||
|
||||
57
briar-core/src/org/briarproject/util/PrivacyUtils.java
Normal file
57
briar-core/src/org/briarproject/util/PrivacyUtils.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package org.briarproject.util;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
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_]";
|
||||
}
|
||||
|
||||
public static String scrubMacAddress(String address) {
|
||||
if (address == null) return null;
|
||||
// this is a fake address we need to know about
|
||||
if (address.equals("02:00:00:00:00:00")) return address;
|
||||
// keep first and last octet of MAC address
|
||||
return address.substring(0, 3) +
|
||||
"[scrubbed]" +
|
||||
address.substring(14, 17);
|
||||
}
|
||||
|
||||
public static String scrubInetAddress(InetAddress address) {
|
||||
// don't scrub link and site local addresses
|
||||
if (address.isLinkLocalAddress() || address.isSiteLocalAddress())
|
||||
return address.toString();
|
||||
// completely scrub IPv6 addresses
|
||||
if (address instanceof Inet6Address) return "[scrubbed]";
|
||||
// keep first and last octet of IPv4 addresses
|
||||
return scrubInetAddress(address.toString());
|
||||
}
|
||||
|
||||
public static String scrubInetAddress(String address) {
|
||||
if (address == null) return null;
|
||||
|
||||
int firstDot = address.indexOf(".");
|
||||
if (firstDot == -1) return "[scrubbed]";
|
||||
String prefix = address.substring(0, firstDot + 1);
|
||||
int lastDot = address.lastIndexOf(".");
|
||||
String suffix = address.substring(lastDot, address.length());
|
||||
return prefix + "[scrubbed]" + suffix;
|
||||
}
|
||||
|
||||
public static String scrubSocketAddress(InetSocketAddress address) {
|
||||
InetAddress inetAddress = address.getAddress();
|
||||
return scrubInetAddress(inetAddress);
|
||||
}
|
||||
|
||||
public static String scrubSocketAddress(SocketAddress address) {
|
||||
if (address instanceof InetSocketAddress)
|
||||
return scrubSocketAddress((InetSocketAddress) address);
|
||||
return scrubInetAddress(address.toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user