From e424765a615f95fd98d90b0e54282fa1f0a86392 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 5 Apr 2020 19:45:45 -0600 Subject: tunnel: support IncludedApplications as whitelist Signed-off-by: Jason A. Donenfeld --- .../com/wireguard/android/backend/GoBackend.java | 3 ++ .../com/wireguard/config/BadConfigException.java | 1 + .../main/java/com/wireguard/config/Interface.java | 38 ++++++++++++++++++++++ 3 files changed, 42 insertions(+) (limited to 'tunnel/src/main/java/com/wireguard') diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java index 019bc980..c859323b 100644 --- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -193,6 +193,9 @@ public final class GoBackend implements Backend { for (final String excludedApplication : config.getInterface().getExcludedApplications()) builder.addDisallowedApplication(excludedApplication); + for (final String includedApplication : config.getInterface().getIncludedApplications()) + builder.addAllowedApplication(includedApplication); + for (final InetNetwork addr : config.getInterface().getAddresses()) builder.addAddress(addr.getAddress(), addr.getMask()); diff --git a/tunnel/src/main/java/com/wireguard/config/BadConfigException.java b/tunnel/src/main/java/com/wireguard/config/BadConfigException.java index 49fb39af..d1e3c627 100644 --- a/tunnel/src/main/java/com/wireguard/config/BadConfigException.java +++ b/tunnel/src/main/java/com/wireguard/config/BadConfigException.java @@ -72,6 +72,7 @@ public class BadConfigException extends Exception { DNS("DNS"), ENDPOINT("Endpoint"), EXCLUDED_APPLICATIONS("ExcludedApplications"), + INCLUDED_APPLICATIONS("IncludedApplications"), LISTEN_PORT("ListenPort"), MTU("MTU"), PERSISTENT_KEEPALIVE("PersistentKeepalive"), diff --git a/tunnel/src/main/java/com/wireguard/config/Interface.java b/tunnel/src/main/java/com/wireguard/config/Interface.java index 32621d2f..c49357f7 100644 --- a/tunnel/src/main/java/com/wireguard/config/Interface.java +++ b/tunnel/src/main/java/com/wireguard/config/Interface.java @@ -43,6 +43,7 @@ public final class Interface { private final Set addresses; private final Set dnsServers; private final Set excludedApplications; + private final Set includedApplications; private final KeyPair keyPair; private final Optional listenPort; private final Optional mtu; @@ -52,6 +53,7 @@ public final class Interface { addresses = Collections.unmodifiableSet(new LinkedHashSet<>(builder.addresses)); dnsServers = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsServers)); excludedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.excludedApplications)); + includedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.includedApplications)); keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key"); listenPort = builder.listenPort; mtu = builder.mtu; @@ -81,6 +83,9 @@ public final class Interface { case "excludedapplications": builder.parseExcludedApplications(attribute.getValue()); break; + case "includedapplications": + builder.parseIncludedApplications(attribute.getValue()); + break; case "listenport": builder.parseListenPort(attribute.getValue()); break; @@ -106,6 +111,7 @@ public final class Interface { return addresses.equals(other.addresses) && dnsServers.equals(other.dnsServers) && excludedApplications.equals(other.excludedApplications) + && includedApplications.equals(other.includedApplications) && keyPair.equals(other.keyPair) && listenPort.equals(other.listenPort) && mtu.equals(other.mtu); @@ -141,6 +147,16 @@ public final class Interface { return excludedApplications; } + /** + * Returns the set of applications included exclusively for using the interface. + * + * @return a set of package names + */ + public Set getIncludedApplications() { + // The collection is already immutable. + return includedApplications; + } + /** * Returns the public/private key pair used by the interface. * @@ -174,6 +190,7 @@ public final class Interface { hash = 31 * hash + addresses.hashCode(); hash = 31 * hash + dnsServers.hashCode(); hash = 31 * hash + excludedApplications.hashCode(); + hash = 31 * hash + includedApplications.hashCode(); hash = 31 * hash + keyPair.hashCode(); hash = 31 * hash + listenPort.hashCode(); hash = 31 * hash + mtu.hashCode(); @@ -213,6 +230,8 @@ public final class Interface { } if (!excludedApplications.isEmpty()) sb.append("ExcludedApplications = ").append(Attribute.join(excludedApplications)).append('\n'); + if (!includedApplications.isEmpty()) + sb.append("IncludedApplications = ").append(Attribute.join(includedApplications)).append('\n'); listenPort.ifPresent(lp -> sb.append("ListenPort = ").append(lp).append('\n')); mtu.ifPresent(m -> sb.append("MTU = ").append(m).append('\n')); sb.append("PrivateKey = ").append(keyPair.getPrivateKey().toBase64()).append('\n'); @@ -240,6 +259,8 @@ public final class Interface { private final Set dnsServers = new LinkedHashSet<>(); // Defaults to an empty set. private final Set excludedApplications = new LinkedHashSet<>(); + // Defaults to an empty set. + private final Set includedApplications = new LinkedHashSet<>(); // No default; must be provided before building. @Nullable private KeyPair keyPair; // Defaults to not present. @@ -271,6 +292,9 @@ public final class Interface { if (keyPair == null) throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY, Reason.MISSING_ATTRIBUTE, null); + if (!includedApplications.isEmpty() && !excludedApplications.isEmpty()) + throw new BadConfigException(Section.INTERFACE, Location.INCLUDED_APPLICATIONS, + Reason.INVALID_KEY, null); return new Interface(this); } @@ -284,6 +308,16 @@ public final class Interface { return this; } + public Builder includeApplication(final String application) { + includedApplications.add(application); + return this; + } + + public Builder includeApplications(final Collection applications) { + includedApplications.addAll(applications); + return this; + } + public Builder parseAddresses(final CharSequence addresses) throws BadConfigException { try { for (final String address : Attribute.split(addresses)) @@ -308,6 +342,10 @@ public final class Interface { return excludeApplications(Lists.of(Attribute.split(apps))); } + public Builder parseIncludedApplications(final CharSequence apps) { + return includeApplications(Lists.of(Attribute.split(apps))); + } + public Builder parseListenPort(final String listenPort) throws BadConfigException { try { return setListenPort(Integer.parseInt(listenPort)); -- cgit v1.2.3