diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java index 33f35f49d6d7a48b1f9dacf0973c9ea35ad012f0..b6f82ebf5ae6a75a2c36487bbae583cff65905a0 100644 --- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java +++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java @@ -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()); } } diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index c9586af6d82e0f72e2edded3e56a8a449fea4ba3..94346424f0e306d8e733e8f9f53e861b9d1a6bd8 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -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; } } diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java index 34de50400f325671e808ae066af2cf7bab94278c..87ba78fab88d5a8c40b11303b395ed83860bd763 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java @@ -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; } } diff --git a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java b/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java index a1585b6bec60d9dbbbc91a81d5c33cbc5e5b68f8..5e135419bffc799a24049f6cd0102222430fb0e0 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java +++ b/briar-core/src/org/briarproject/plugins/tcp/PortMapperImpl.java @@ -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) { diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java index fab2a1cbb57a9f0afb91cd0098a980c65df344f5..9ba84875bd40da38467b0899af4d566d6c26df2b 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java @@ -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) { diff --git a/briar-core/src/org/briarproject/util/PrivacyUtils.java b/briar-core/src/org/briarproject/util/PrivacyUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..247ccda3f24a69d32d55f3d465a0427ab7d74b6e --- /dev/null +++ b/briar-core/src/org/briarproject/util/PrivacyUtils.java @@ -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()); + } +}