aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/app/src/main/java/com/wireguard/config
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/wireguard/config')
-rw-r--r--app/src/main/java/com/wireguard/config/Attribute.java49
-rw-r--r--app/src/main/java/com/wireguard/config/BadConfigException.java118
-rw-r--r--app/src/main/java/com/wireguard/config/Config.java221
-rw-r--r--app/src/main/java/com/wireguard/config/InetAddresses.java64
-rw-r--r--app/src/main/java/com/wireguard/config/InetEndpoint.java125
-rw-r--r--app/src/main/java/com/wireguard/config/InetNetwork.java76
-rw-r--r--app/src/main/java/com/wireguard/config/Interface.java355
-rw-r--r--app/src/main/java/com/wireguard/config/ParseException.java44
-rw-r--r--app/src/main/java/com/wireguard/config/Peer.java306
9 files changed, 0 insertions, 1358 deletions
diff --git a/app/src/main/java/com/wireguard/config/Attribute.java b/app/src/main/java/com/wireguard/config/Attribute.java
deleted file mode 100644
index 375acc42..00000000
--- a/app/src/main/java/com/wireguard/config/Attribute.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import android.text.TextUtils;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import java9.util.Optional;
-
-public final class Attribute {
- private static final Pattern LINE_PATTERN = Pattern.compile("(\\w+)\\s*=\\s*([^\\s#][^#]*)");
- private static final Pattern LIST_SEPARATOR = Pattern.compile("\\s*,\\s*");
-
- private final String key;
- private final String value;
-
- private Attribute(final String key, final String value) {
- this.key = key;
- this.value = value;
- }
-
- public static String join(final Iterable<?> values) {
- return TextUtils.join(", ", values);
- }
-
- public static Optional<Attribute> parse(final CharSequence line) {
- final Matcher matcher = LINE_PATTERN.matcher(line);
- if (!matcher.matches())
- return Optional.empty();
- return Optional.of(new Attribute(matcher.group(1), matcher.group(2)));
- }
-
- public static String[] split(final CharSequence value) {
- return LIST_SEPARATOR.split(value);
- }
-
- public String getKey() {
- return key;
- }
-
- public String getValue() {
- return value;
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/BadConfigException.java b/app/src/main/java/com/wireguard/config/BadConfigException.java
deleted file mode 100644
index 6d41b065..00000000
--- a/app/src/main/java/com/wireguard/config/BadConfigException.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-import com.wireguard.crypto.KeyFormatException;
-
-public class BadConfigException extends Exception {
- private final Location location;
- private final Reason reason;
- private final Section section;
- @Nullable private final CharSequence text;
-
- private BadConfigException(final Section section, final Location location,
- final Reason reason, @Nullable final CharSequence text,
- @Nullable final Throwable cause) {
- super(cause);
- this.section = section;
- this.location = location;
- this.reason = reason;
- this.text = text;
- }
-
- public BadConfigException(final Section section, final Location location,
- final Reason reason, @Nullable final CharSequence text) {
- this(section, location, reason, text, null);
- }
-
- public BadConfigException(final Section section, final Location location,
- final KeyFormatException cause) {
- this(section, location, Reason.INVALID_KEY, null, cause);
- }
-
- public BadConfigException(final Section section, final Location location,
- @Nullable final CharSequence text,
- final NumberFormatException cause) {
- this(section, location, Reason.INVALID_NUMBER, text, cause);
- }
-
- public BadConfigException(final Section section, final Location location,
- final ParseException cause) {
- this(section, location, Reason.INVALID_VALUE, cause.getText(), cause);
- }
-
- public Location getLocation() {
- return location;
- }
-
- public Reason getReason() {
- return reason;
- }
-
- public Section getSection() {
- return section;
- }
-
- @Nullable
- public CharSequence getText() {
- return text;
- }
-
- public enum Location {
- TOP_LEVEL(""),
- ADDRESS("Address"),
- ALLOWED_IPS("AllowedIPs"),
- DNS("DNS"),
- ENDPOINT("Endpoint"),
- EXCLUDED_APPLICATIONS("ExcludedApplications"),
- LISTEN_PORT("ListenPort"),
- MTU("MTU"),
- PERSISTENT_KEEPALIVE("PersistentKeepalive"),
- PRE_SHARED_KEY("PresharedKey"),
- PRIVATE_KEY("PrivateKey"),
- PUBLIC_KEY("PublicKey");
-
- private final String name;
-
- Location(final String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
- }
-
- public enum Reason {
- INVALID_KEY,
- INVALID_NUMBER,
- INVALID_VALUE,
- MISSING_ATTRIBUTE,
- MISSING_SECTION,
- MISSING_VALUE,
- SYNTAX_ERROR,
- UNKNOWN_ATTRIBUTE,
- UNKNOWN_SECTION
- }
-
- public enum Section {
- CONFIG("Config"),
- INTERFACE("Interface"),
- PEER("Peer");
-
- private final String name;
-
- Section(final String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/Config.java b/app/src/main/java/com/wireguard/config/Config.java
deleted file mode 100644
index 62651b08..00000000
--- a/app/src/main/java/com/wireguard/config/Config.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-import com.wireguard.config.BadConfigException.Location;
-import com.wireguard.config.BadConfigException.Reason;
-import com.wireguard.config.BadConfigException.Section;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Represents the contents of a wg-quick configuration file, made up of one or more "Interface"
- * sections (combined together), and zero or more "Peer" sections (treated individually).
- * <p>
- * Instances of this class are immutable.
- */
-public final class Config {
- private final Interface interfaze;
- private final List<Peer> peers;
-
- private Config(final Builder builder) {
- interfaze = Objects.requireNonNull(builder.interfaze, "An [Interface] section is required");
- // Defensively copy to ensure immutability even if the Builder is reused.
- peers = Collections.unmodifiableList(new ArrayList<>(builder.peers));
- }
-
- /**
- * Parses an series of "Interface" and "Peer" sections into a {@code Config}. Throws
- * {@link BadConfigException} if the input is not well-formed or contains data that cannot
- * be parsed.
- *
- * @param stream a stream of UTF-8 text that is interpreted as a WireGuard configuration
- * @return a {@code Config} instance representing the supplied configuration
- */
- public static Config parse(final InputStream stream)
- throws IOException, BadConfigException {
- return parse(new BufferedReader(new InputStreamReader(stream)));
- }
-
- /**
- * Parses an series of "Interface" and "Peer" sections into a {@code Config}. Throws
- * {@link BadConfigException} if the input is not well-formed or contains data that cannot
- * be parsed.
- *
- * @param reader a BufferedReader of UTF-8 text that is interpreted as a WireGuard configuration
- * @return a {@code Config} instance representing the supplied configuration
- */
- public static Config parse(final BufferedReader reader)
- throws IOException, BadConfigException {
- final Builder builder = new Builder();
- final Collection<String> interfaceLines = new ArrayList<>();
- final Collection<String> peerLines = new ArrayList<>();
- boolean inInterfaceSection = false;
- boolean inPeerSection = false;
- @Nullable String line;
- while ((line = reader.readLine()) != null) {
- final int commentIndex = line.indexOf('#');
- if (commentIndex != -1)
- line = line.substring(0, commentIndex);
- line = line.trim();
- if (line.isEmpty())
- continue;
- if (line.startsWith("[")) {
- // Consume all [Peer] lines read so far.
- if (inPeerSection) {
- builder.parsePeer(peerLines);
- peerLines.clear();
- }
- if ("[Interface]".equalsIgnoreCase(line)) {
- inInterfaceSection = true;
- inPeerSection = false;
- } else if ("[Peer]".equalsIgnoreCase(line)) {
- inInterfaceSection = false;
- inPeerSection = true;
- } else {
- throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL,
- Reason.UNKNOWN_SECTION, line);
- }
- } else if (inInterfaceSection) {
- interfaceLines.add(line);
- } else if (inPeerSection) {
- peerLines.add(line);
- } else {
- throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL,
- Reason.UNKNOWN_SECTION, line);
- }
- }
- if (inPeerSection)
- builder.parsePeer(peerLines);
- else if (!inInterfaceSection)
- throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL,
- Reason.MISSING_SECTION, null);
- // Combine all [Interface] sections in the file.
- builder.parseInterface(interfaceLines);
- return builder.build();
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof Config))
- return false;
- final Config other = (Config) obj;
- return interfaze.equals(other.interfaze) && peers.equals(other.peers);
- }
-
- /**
- * Returns the interface section of the configuration.
- *
- * @return the interface configuration
- */
- public Interface getInterface() {
- return interfaze;
- }
-
- /**
- * Returns a list of the configuration's peer sections.
- *
- * @return a list of {@link Peer}s
- */
- public List<Peer> getPeers() {
- return peers;
- }
-
- @Override
- public int hashCode() {
- return 31 * interfaze.hashCode() + peers.hashCode();
- }
-
- /**
- * Converts the {@code Config} into a string suitable for debugging purposes. The {@code Config}
- * is identified by its interface's public key and the number of peers it has.
- *
- * @return a concise single-line identifier for the {@code Config}
- */
- @Override
- public String toString() {
- return "(Config " + interfaze + " (" + peers.size() + " peers))";
- }
-
- /**
- * Converts the {@code Config} into a string suitable for use as a {@code wg-quick}
- * configuration file.
- *
- * @return the {@code Config} represented as one [Interface] and zero or more [Peer] sections
- */
- public String toWgQuickString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("[Interface]\n").append(interfaze.toWgQuickString());
- for (final Peer peer : peers)
- sb.append("\n[Peer]\n").append(peer.toWgQuickString());
- return sb.toString();
- }
-
- /**
- * Serializes the {@code Config} for use with the WireGuard cross-platform userspace API.
- *
- * @return the {@code Config} represented as a series of "key=value" lines
- */
- public String toWgUserspaceString() {
- final StringBuilder sb = new StringBuilder();
- sb.append(interfaze.toWgUserspaceString());
- sb.append("replace_peers=true\n");
- for (final Peer peer : peers)
- sb.append(peer.toWgUserspaceString());
- return sb.toString();
- }
-
- @SuppressWarnings("UnusedReturnValue")
- public static final class Builder {
- // Defaults to an empty set.
- private final Set<Peer> peers = new LinkedHashSet<>();
- // No default; must be provided before building.
- @Nullable private Interface interfaze;
-
- public Builder addPeer(final Peer peer) {
- peers.add(peer);
- return this;
- }
-
- public Builder addPeers(final Collection<Peer> peers) {
- this.peers.addAll(peers);
- return this;
- }
-
- public Config build() {
- if (interfaze == null)
- throw new IllegalArgumentException("An [Interface] section is required");
- return new Config(this);
- }
-
- public Builder parseInterface(final Iterable<? extends CharSequence> lines)
- throws BadConfigException {
- return setInterface(Interface.parse(lines));
- }
-
- public Builder parsePeer(final Iterable<? extends CharSequence> lines)
- throws BadConfigException {
- return addPeer(Peer.parse(lines));
- }
-
- public Builder setInterface(final Interface interfaze) {
- this.interfaze = interfaze;
- return this;
- }
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/InetAddresses.java b/app/src/main/java/com/wireguard/config/InetAddresses.java
deleted file mode 100644
index 6396492e..00000000
--- a/app/src/main/java/com/wireguard/config/InetAddresses.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import android.os.Build;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-
-/**
- * Utility methods for creating instances of {@link InetAddress}.
- */
-public final class InetAddresses {
- private static Method PARSER_METHOD;
-
-
- private static Method getParserMethod() {
- if (PARSER_METHOD != null)
- return PARSER_METHOD;
- try {
- // This method is only present on Android.
- // noinspection JavaReflectionMemberAccess
- PARSER_METHOD = InetAddress.class.getMethod("parseNumericAddress", String.class);
- } catch (final NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- return PARSER_METHOD;
- }
-
- private InetAddresses() {
- // Prevent instantiation.
- }
-
- /**
- * Parses a numeric IPv4 or IPv6 address without performing any DNS lookups.
- *
- * @param address a string representing the IP address
- * @return an instance of {@link Inet4Address} or {@link Inet6Address}, as appropriate
- */
- public static InetAddress parse(final String address) throws ParseException {
- if (address.isEmpty())
- throw new ParseException(InetAddress.class, address, "Empty address");
- try {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
- return (InetAddress) getParserMethod().invoke(null, address);
- else
- return android.net.InetAddresses.parseNumericAddress(address);
- } catch (final IllegalAccessException | InvocationTargetException e) {
- final Throwable cause = e.getCause();
- // Re-throw parsing exceptions with the original type, as callers might try to catch
- // them. On the other hand, callers cannot be expected to handle reflection failures.
- if (cause instanceof IllegalArgumentException)
- throw new ParseException(InetAddress.class, address, cause);
- throw new RuntimeException(e);
- } catch (final IllegalArgumentException e) {
- throw new ParseException(InetAddress.class, address, e);
- }
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/InetEndpoint.java b/app/src/main/java/com/wireguard/config/InetEndpoint.java
deleted file mode 100644
index a442258e..00000000
--- a/app/src/main/java/com/wireguard/config/InetEndpoint.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-import org.threeten.bp.Duration;
-import org.threeten.bp.Instant;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.regex.Pattern;
-
-import java9.util.Optional;
-
-
-/**
- * An external endpoint (host and port) used to connect to a WireGuard {@link Peer}.
- * <p>
- * Instances of this class are externally immutable.
- */
-public final class InetEndpoint {
- private static final Pattern BARE_IPV6 = Pattern.compile("^[^\\[\\]]*:[^\\[\\]]*");
- private static final Pattern FORBIDDEN_CHARACTERS = Pattern.compile("[/?#]");
-
- private final String host;
- private final boolean isResolved;
- private final Object lock = new Object();
- private final int port;
- private Instant lastResolution = Instant.EPOCH;
- @Nullable private InetEndpoint resolved;
-
- private InetEndpoint(final String host, final boolean isResolved, final int port) {
- this.host = host;
- this.isResolved = isResolved;
- this.port = port;
- }
-
- public static InetEndpoint parse(final String endpoint) throws ParseException {
- if (FORBIDDEN_CHARACTERS.matcher(endpoint).find())
- throw new ParseException(InetEndpoint.class, endpoint, "Forbidden characters");
- final URI uri;
- try {
- uri = new URI("wg://" + endpoint);
- } catch (final URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- if (uri.getPort() < 0 || uri.getPort() > 65535)
- throw new ParseException(InetEndpoint.class, endpoint, "Missing/invalid port number");
- try {
- InetAddresses.parse(uri.getHost());
- // Parsing ths host as a numeric address worked, so we don't need to do DNS lookups.
- return new InetEndpoint(uri.getHost(), true, uri.getPort());
- } catch (final ParseException ignored) {
- // Failed to parse the host as a numeric address, so it must be a DNS hostname/FQDN.
- return new InetEndpoint(uri.getHost(), false, uri.getPort());
- }
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof InetEndpoint))
- return false;
- final InetEndpoint other = (InetEndpoint) obj;
- return host.equals(other.host) && port == other.port;
- }
-
- public String getHost() {
- return host;
- }
-
- public int getPort() {
- return port;
- }
-
- /**
- * Generate an {@code InetEndpoint} instance with the same port and the host resolved using DNS
- * to a numeric address. If the host is already numeric, the existing instance may be returned.
- * Because this function may perform network I/O, it must not be called from the main thread.
- *
- * @return the resolved endpoint, or {@link Optional#empty()}
- */
- public Optional<InetEndpoint> getResolved() {
- if (isResolved)
- return Optional.of(this);
- synchronized (lock) {
- //TODO(zx2c4): Implement a real timeout mechanism using DNS TTL
- if (Duration.between(lastResolution, Instant.now()).toMinutes() > 1) {
- try {
- // Prefer v4 endpoints over v6 to work around DNS64 and IPv6 NAT issues.
- final InetAddress[] candidates = InetAddress.getAllByName(host);
- InetAddress address = candidates[0];
- for (final InetAddress candidate : candidates) {
- if (candidate instanceof Inet4Address) {
- address = candidate;
- break;
- }
- }
- resolved = new InetEndpoint(address.getHostAddress(), true, port);
- lastResolution = Instant.now();
- } catch (final UnknownHostException e) {
- resolved = null;
- }
- }
- return Optional.ofNullable(resolved);
- }
- }
-
- @Override
- public int hashCode() {
- return host.hashCode() ^ port;
- }
-
- @Override
- public String toString() {
- final boolean isBareIpv6 = isResolved && BARE_IPV6.matcher(host).matches();
- return (isBareIpv6 ? '[' + host + ']' : host) + ':' + port;
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/InetNetwork.java b/app/src/main/java/com/wireguard/config/InetNetwork.java
deleted file mode 100644
index f89322fd..00000000
--- a/app/src/main/java/com/wireguard/config/InetNetwork.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-
-/**
- * An Internet network, denoted by its address and netmask
- * <p>
- * Instances of this class are immutable.
- */
-public final class InetNetwork {
- private final InetAddress address;
- private final int mask;
-
- private InetNetwork(final InetAddress address, final int mask) {
- this.address = address;
- this.mask = mask;
- }
-
- public static InetNetwork parse(final String network) throws ParseException {
- final int slash = network.lastIndexOf('/');
- final String maskString;
- final int rawMask;
- final String rawAddress;
- if (slash >= 0) {
- maskString = network.substring(slash + 1);
- try {
- rawMask = Integer.parseInt(maskString, 10);
- } catch (final NumberFormatException ignored) {
- throw new ParseException(Integer.class, maskString);
- }
- rawAddress = network.substring(0, slash);
- } else {
- maskString = "";
- rawMask = -1;
- rawAddress = network;
- }
- final InetAddress address = InetAddresses.parse(rawAddress);
- final int maxMask = (address instanceof Inet4Address) ? 32 : 128;
- if (rawMask > maxMask)
- throw new ParseException(InetNetwork.class, maskString, "Invalid network mask");
- final int mask = rawMask >= 0 && rawMask <= maxMask ? rawMask : maxMask;
- return new InetNetwork(address, mask);
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof InetNetwork))
- return false;
- final InetNetwork other = (InetNetwork) obj;
- return address.equals(other.address) && mask == other.mask;
- }
-
- public InetAddress getAddress() {
- return address;
- }
-
- public int getMask() {
- return mask;
- }
-
- @Override
- public int hashCode() {
- return address.hashCode() ^ mask;
- }
-
- @Override
- public String toString() {
- return address.getHostAddress() + '/' + mask;
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/Interface.java b/app/src/main/java/com/wireguard/config/Interface.java
deleted file mode 100644
index 54944424..00000000
--- a/app/src/main/java/com/wireguard/config/Interface.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-import com.wireguard.config.BadConfigException.Location;
-import com.wireguard.config.BadConfigException.Reason;
-import com.wireguard.config.BadConfigException.Section;
-import com.wireguard.crypto.Key;
-import com.wireguard.crypto.KeyFormatException;
-import com.wireguard.crypto.KeyPair;
-
-import java.net.InetAddress;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-
-import java9.util.Lists;
-import java9.util.Optional;
-import java9.util.stream.Collectors;
-import java9.util.stream.StreamSupport;
-
-/**
- * Represents the configuration for a WireGuard interface (an [Interface] block). Interfaces must
- * have a private key (used to initialize a {@code KeyPair}), and may optionally have several other
- * attributes.
- * <p>
- * Instances of this class are immutable.
- */
-public final class Interface {
- private static final int MAX_UDP_PORT = 65535;
- private static final int MIN_UDP_PORT = 0;
-
- private final Set<InetNetwork> addresses;
- private final Set<InetAddress> dnsServers;
- private final Set<String> excludedApplications;
- private final KeyPair keyPair;
- private final Optional<Integer> listenPort;
- private final Optional<Integer> mtu;
-
- private Interface(final Builder builder) {
- // Defensively copy to ensure immutability even if the Builder is reused.
- addresses = Collections.unmodifiableSet(new LinkedHashSet<>(builder.addresses));
- dnsServers = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsServers));
- excludedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.excludedApplications));
- keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key");
- listenPort = builder.listenPort;
- mtu = builder.mtu;
- }
-
- /**
- * Parses an series of "KEY = VALUE" lines into an {@code Interface}. Throws
- * {@link ParseException} if the input is not well-formed or contains unknown attributes.
- *
- * @param lines An iterable sequence of lines, containing at least a private key attribute
- * @return An {@code Interface} with all of the attributes from {@code lines} set
- */
- public static Interface parse(final Iterable<? extends CharSequence> lines)
- throws BadConfigException {
- final Builder builder = new Builder();
- for (final CharSequence line : lines) {
- final Attribute attribute = Attribute.parse(line).orElseThrow(() ->
- new BadConfigException(Section.INTERFACE, Location.TOP_LEVEL,
- Reason.SYNTAX_ERROR, line));
- switch (attribute.getKey().toLowerCase(Locale.ENGLISH)) {
- case "address":
- builder.parseAddresses(attribute.getValue());
- break;
- case "dns":
- builder.parseDnsServers(attribute.getValue());
- break;
- case "excludedapplications":
- builder.parseExcludedApplications(attribute.getValue());
- break;
- case "listenport":
- builder.parseListenPort(attribute.getValue());
- break;
- case "mtu":
- builder.parseMtu(attribute.getValue());
- break;
- case "privatekey":
- builder.parsePrivateKey(attribute.getValue());
- break;
- default:
- throw new BadConfigException(Section.INTERFACE, Location.TOP_LEVEL,
- Reason.UNKNOWN_ATTRIBUTE, attribute.getKey());
- }
- }
- return builder.build();
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof Interface))
- return false;
- final Interface other = (Interface) obj;
- return addresses.equals(other.addresses)
- && dnsServers.equals(other.dnsServers)
- && excludedApplications.equals(other.excludedApplications)
- && keyPair.equals(other.keyPair)
- && listenPort.equals(other.listenPort)
- && mtu.equals(other.mtu);
- }
-
- /**
- * Returns the set of IP addresses assigned to the interface.
- *
- * @return a set of {@link InetNetwork}s
- */
- public Set<InetNetwork> getAddresses() {
- // The collection is already immutable.
- return addresses;
- }
-
- /**
- * Returns the set of DNS servers associated with the interface.
- *
- * @return a set of {@link InetAddress}es
- */
- public Set<InetAddress> getDnsServers() {
- // The collection is already immutable.
- return dnsServers;
- }
-
- /**
- * Returns the set of applications excluded from using the interface.
- *
- * @return a set of package names
- */
- public Set<String> getExcludedApplications() {
- // The collection is already immutable.
- return excludedApplications;
- }
-
- /**
- * Returns the public/private key pair used by the interface.
- *
- * @return a key pair
- */
- public KeyPair getKeyPair() {
- return keyPair;
- }
-
- /**
- * Returns the UDP port number that the WireGuard interface will listen on.
- *
- * @return a UDP port number, or {@code Optional.empty()} if none is configured
- */
- public Optional<Integer> getListenPort() {
- return listenPort;
- }
-
- /**
- * Returns the MTU used for the WireGuard interface.
- *
- * @return the MTU, or {@code Optional.empty()} if none is configured
- */
- public Optional<Integer> getMtu() {
- return mtu;
- }
-
- @Override
- public int hashCode() {
- int hash = 1;
- hash = 31 * hash + addresses.hashCode();
- hash = 31 * hash + dnsServers.hashCode();
- hash = 31 * hash + excludedApplications.hashCode();
- hash = 31 * hash + keyPair.hashCode();
- hash = 31 * hash + listenPort.hashCode();
- hash = 31 * hash + mtu.hashCode();
- return hash;
- }
-
- /**
- * Converts the {@code Interface} into a string suitable for debugging purposes. The {@code
- * Interface} is identified by its public key and (if set) the port used for its UDP socket.
- *
- * @return A concise single-line identifier for the {@code Interface}
- */
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("(Interface ");
- sb.append(keyPair.getPublicKey().toBase64());
- listenPort.ifPresent(lp -> sb.append(" @").append(lp));
- sb.append(')');
- return sb.toString();
- }
-
- /**
- * Converts the {@code Interface} into a string suitable for inclusion in a {@code wg-quick}
- * configuration file.
- *
- * @return The {@code Interface} represented as a series of "Key = Value" lines
- */
- public String toWgQuickString() {
- final StringBuilder sb = new StringBuilder();
- if (!addresses.isEmpty())
- sb.append("Address = ").append(Attribute.join(addresses)).append('\n');
- if (!dnsServers.isEmpty()) {
- final List<String> dnsServerStrings = StreamSupport.stream(dnsServers)
- .map(InetAddress::getHostAddress)
- .collect(Collectors.toUnmodifiableList());
- sb.append("DNS = ").append(Attribute.join(dnsServerStrings)).append('\n');
- }
- if (!excludedApplications.isEmpty())
- sb.append("ExcludedApplications = ").append(Attribute.join(excludedApplications)).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');
- return sb.toString();
- }
-
- /**
- * Serializes the {@code Interface} for use with the WireGuard cross-platform userspace API.
- * Note that not all attributes are included in this representation.
- *
- * @return the {@code Interface} represented as a series of "KEY=VALUE" lines
- */
- public String toWgUserspaceString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("private_key=").append(keyPair.getPrivateKey().toHex()).append('\n');
- listenPort.ifPresent(lp -> sb.append("listen_port=").append(lp).append('\n'));
- return sb.toString();
- }
-
- @SuppressWarnings("UnusedReturnValue")
- public static final class Builder {
- // Defaults to an empty set.
- private final Set<InetNetwork> addresses = new LinkedHashSet<>();
- // Defaults to an empty set.
- private final Set<InetAddress> dnsServers = new LinkedHashSet<>();
- // Defaults to an empty set.
- private final Set<String> excludedApplications = new LinkedHashSet<>();
- // No default; must be provided before building.
- @Nullable private KeyPair keyPair;
- // Defaults to not present.
- private Optional<Integer> listenPort = Optional.empty();
- // Defaults to not present.
- private Optional<Integer> mtu = Optional.empty();
-
- public Builder addAddress(final InetNetwork address) {
- addresses.add(address);
- return this;
- }
-
- public Builder addAddresses(final Collection<InetNetwork> addresses) {
- this.addresses.addAll(addresses);
- return this;
- }
-
- public Builder addDnsServer(final InetAddress dnsServer) {
- dnsServers.add(dnsServer);
- return this;
- }
-
- public Builder addDnsServers(final Collection<? extends InetAddress> dnsServers) {
- this.dnsServers.addAll(dnsServers);
- return this;
- }
-
- public Interface build() throws BadConfigException {
- if (keyPair == null)
- throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY,
- Reason.MISSING_ATTRIBUTE, null);
- return new Interface(this);
- }
-
- public Builder excludeApplication(final String application) {
- excludedApplications.add(application);
- return this;
- }
-
- public Builder excludeApplications(final Collection<String> applications) {
- excludedApplications.addAll(applications);
- return this;
- }
-
- public Builder parseAddresses(final CharSequence addresses) throws BadConfigException {
- try {
- for (final String address : Attribute.split(addresses))
- addAddress(InetNetwork.parse(address));
- return this;
- } catch (final ParseException e) {
- throw new BadConfigException(Section.INTERFACE, Location.ADDRESS, e);
- }
- }
-
- public Builder parseDnsServers(final CharSequence dnsServers) throws BadConfigException {
- try {
- for (final String dnsServer : Attribute.split(dnsServers))
- addDnsServer(InetAddresses.parse(dnsServer));
- return this;
- } catch (final ParseException e) {
- throw new BadConfigException(Section.INTERFACE, Location.DNS, e);
- }
- }
-
- public Builder parseExcludedApplications(final CharSequence apps) {
- return excludeApplications(Lists.of(Attribute.split(apps)));
- }
-
- public Builder parseListenPort(final String listenPort) throws BadConfigException {
- try {
- return setListenPort(Integer.parseInt(listenPort));
- } catch (final NumberFormatException e) {
- throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT, listenPort, e);
- }
- }
-
- public Builder parseMtu(final String mtu) throws BadConfigException {
- try {
- return setMtu(Integer.parseInt(mtu));
- } catch (final NumberFormatException e) {
- throw new BadConfigException(Section.INTERFACE, Location.MTU, mtu, e);
- }
- }
-
- public Builder parsePrivateKey(final String privateKey) throws BadConfigException {
- try {
- return setKeyPair(new KeyPair(Key.fromBase64(privateKey)));
- } catch (final KeyFormatException e) {
- throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY, e);
- }
- }
-
- public Builder setKeyPair(final KeyPair keyPair) {
- this.keyPair = keyPair;
- return this;
- }
-
- public Builder setListenPort(final int listenPort) throws BadConfigException {
- if (listenPort < MIN_UDP_PORT || listenPort > MAX_UDP_PORT)
- throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT,
- Reason.INVALID_VALUE, String.valueOf(listenPort));
- this.listenPort = listenPort == 0 ? Optional.empty() : Optional.of(listenPort);
- return this;
- }
-
- public Builder setMtu(final int mtu) throws BadConfigException {
- if (mtu < 0)
- throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT,
- Reason.INVALID_VALUE, String.valueOf(mtu));
- this.mtu = mtu == 0 ? Optional.empty() : Optional.of(mtu);
- return this;
- }
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/ParseException.java b/app/src/main/java/com/wireguard/config/ParseException.java
deleted file mode 100644
index c79d1fa1..00000000
--- a/app/src/main/java/com/wireguard/config/ParseException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-/**
- */
-public class ParseException extends Exception {
- private final Class<?> parsingClass;
- private final CharSequence text;
-
- public ParseException(final Class<?> parsingClass, final CharSequence text,
- @Nullable final String message, @Nullable final Throwable cause) {
- super(message, cause);
- this.parsingClass = parsingClass;
- this.text = text;
- }
-
- public ParseException(final Class<?> parsingClass, final CharSequence text,
- @Nullable final String message) {
- this(parsingClass, text, message, null);
- }
-
- public ParseException(final Class<?> parsingClass, final CharSequence text,
- @Nullable final Throwable cause) {
- this(parsingClass, text, null, cause);
- }
-
- public ParseException(final Class<?> parsingClass, final CharSequence text) {
- this(parsingClass, text, null, null);
- }
-
- public Class<?> getParsingClass() {
- return parsingClass;
- }
-
- public CharSequence getText() {
- return text;
- }
-}
diff --git a/app/src/main/java/com/wireguard/config/Peer.java b/app/src/main/java/com/wireguard/config/Peer.java
deleted file mode 100644
index 37fcfa69..00000000
--- a/app/src/main/java/com/wireguard/config/Peer.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.config;
-
-import androidx.annotation.Nullable;
-
-import com.wireguard.config.BadConfigException.Location;
-import com.wireguard.config.BadConfigException.Reason;
-import com.wireguard.config.BadConfigException.Section;
-import com.wireguard.crypto.Key;
-import com.wireguard.crypto.KeyFormatException;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-
-import java9.util.Optional;
-
-/**
- * Represents the configuration for a WireGuard peer (a [Peer] block). Peers must have a public key,
- * and may optionally have several other attributes.
- * <p>
- * Instances of this class are immutable.
- */
-public final class Peer {
- private final Set<InetNetwork> allowedIps;
- private final Optional<InetEndpoint> endpoint;
- private final Optional<Integer> persistentKeepalive;
- private final Optional<Key> preSharedKey;
- private final Key publicKey;
-
- private Peer(final Builder builder) {
- // Defensively copy to ensure immutability even if the Builder is reused.
- allowedIps = Collections.unmodifiableSet(new LinkedHashSet<>(builder.allowedIps));
- endpoint = builder.endpoint;
- persistentKeepalive = builder.persistentKeepalive;
- preSharedKey = builder.preSharedKey;
- publicKey = Objects.requireNonNull(builder.publicKey, "Peers must have a public key");
- }
-
- /**
- * Parses an series of "KEY = VALUE" lines into a {@code Peer}. Throws {@link ParseException} if
- * the input is not well-formed or contains unknown attributes.
- *
- * @param lines an iterable sequence of lines, containing at least a public key attribute
- * @return a {@code Peer} with all of its attributes set from {@code lines}
- */
- public static Peer parse(final Iterable<? extends CharSequence> lines)
- throws BadConfigException {
- final Builder builder = new Builder();
- for (final CharSequence line : lines) {
- final Attribute attribute = Attribute.parse(line).orElseThrow(() ->
- new BadConfigException(Section.PEER, Location.TOP_LEVEL,
- Reason.SYNTAX_ERROR, line));
- switch (attribute.getKey().toLowerCase(Locale.ENGLISH)) {
- case "allowedips":
- builder.parseAllowedIPs(attribute.getValue());
- break;
- case "endpoint":
- builder.parseEndpoint(attribute.getValue());
- break;
- case "persistentkeepalive":
- builder.parsePersistentKeepalive(attribute.getValue());
- break;
- case "presharedkey":
- builder.parsePreSharedKey(attribute.getValue());
- break;
- case "publickey":
- builder.parsePublicKey(attribute.getValue());
- break;
- default:
- throw new BadConfigException(Section.PEER, Location.TOP_LEVEL,
- Reason.UNKNOWN_ATTRIBUTE, attribute.getKey());
- }
- }
- return builder.build();
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof Peer))
- return false;
- final Peer other = (Peer) obj;
- return allowedIps.equals(other.allowedIps)
- && endpoint.equals(other.endpoint)
- && persistentKeepalive.equals(other.persistentKeepalive)
- && preSharedKey.equals(other.preSharedKey)
- && publicKey.equals(other.publicKey);
- }
-
- /**
- * Returns the peer's set of allowed IPs.
- *
- * @return the set of allowed IPs
- */
- public Set<InetNetwork> getAllowedIps() {
- // The collection is already immutable.
- return allowedIps;
- }
-
- /**
- * Returns the peer's endpoint.
- *
- * @return the endpoint, or {@code Optional.empty()} if none is configured
- */
- public Optional<InetEndpoint> getEndpoint() {
- return endpoint;
- }
-
- /**
- * Returns the peer's persistent keepalive.
- *
- * @return the persistent keepalive, or {@code Optional.empty()} if none is configured
- */
- public Optional<Integer> getPersistentKeepalive() {
- return persistentKeepalive;
- }
-
- /**
- * Returns the peer's pre-shared key.
- *
- * @return the pre-shared key, or {@code Optional.empty()} if none is configured
- */
- public Optional<Key> getPreSharedKey() {
- return preSharedKey;
- }
-
- /**
- * Returns the peer's public key.
- *
- * @return the public key
- */
- public Key getPublicKey() {
- return publicKey;
- }
-
- @Override
- public int hashCode() {
- int hash = 1;
- hash = 31 * hash + allowedIps.hashCode();
- hash = 31 * hash + endpoint.hashCode();
- hash = 31 * hash + persistentKeepalive.hashCode();
- hash = 31 * hash + preSharedKey.hashCode();
- hash = 31 * hash + publicKey.hashCode();
- return hash;
- }
-
- /**
- * Converts the {@code Peer} into a string suitable for debugging purposes. The {@code Peer} is
- * identified by its public key and (if known) its endpoint.
- *
- * @return a concise single-line identifier for the {@code Peer}
- */
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("(Peer ");
- sb.append(publicKey.toBase64());
- endpoint.ifPresent(ep -> sb.append(" @").append(ep));
- sb.append(')');
- return sb.toString();
- }
-
- /**
- * Converts the {@code Peer} into a string suitable for inclusion in a {@code wg-quick}
- * configuration file.
- *
- * @return the {@code Peer} represented as a series of "Key = Value" lines
- */
- public String toWgQuickString() {
- final StringBuilder sb = new StringBuilder();
- if (!allowedIps.isEmpty())
- sb.append("AllowedIPs = ").append(Attribute.join(allowedIps)).append('\n');
- endpoint.ifPresent(ep -> sb.append("Endpoint = ").append(ep).append('\n'));
- persistentKeepalive.ifPresent(pk -> sb.append("PersistentKeepalive = ").append(pk).append('\n'));
- preSharedKey.ifPresent(psk -> sb.append("PreSharedKey = ").append(psk.toBase64()).append('\n'));
- sb.append("PublicKey = ").append(publicKey.toBase64()).append('\n');
- return sb.toString();
- }
-
- /**
- * Serializes the {@code Peer} for use with the WireGuard cross-platform userspace API. Note
- * that not all attributes are included in this representation.
- *
- * @return the {@code Peer} represented as a series of "key=value" lines
- */
- public String toWgUserspaceString() {
- final StringBuilder sb = new StringBuilder();
- // The order here is important: public_key signifies the beginning of a new peer.
- sb.append("public_key=").append(publicKey.toHex()).append('\n');
- for (final InetNetwork allowedIp : allowedIps)
- sb.append("allowed_ip=").append(allowedIp).append('\n');
- endpoint.flatMap(InetEndpoint::getResolved).ifPresent(ep -> sb.append("endpoint=").append(ep).append('\n'));
- persistentKeepalive.ifPresent(pk -> sb.append("persistent_keepalive_interval=").append(pk).append('\n'));
- preSharedKey.ifPresent(psk -> sb.append("preshared_key=").append(psk.toHex()).append('\n'));
- return sb.toString();
- }
-
- @SuppressWarnings("UnusedReturnValue")
- public static final class Builder {
- // See wg(8)
- private static final int MAX_PERSISTENT_KEEPALIVE = 65535;
-
- // Defaults to an empty set.
- private final Set<InetNetwork> allowedIps = new LinkedHashSet<>();
- // Defaults to not present.
- private Optional<InetEndpoint> endpoint = Optional.empty();
- // Defaults to not present.
- private Optional<Integer> persistentKeepalive = Optional.empty();
- // Defaults to not present.
- private Optional<Key> preSharedKey = Optional.empty();
- // No default; must be provided before building.
- @Nullable private Key publicKey;
-
- public Builder addAllowedIp(final InetNetwork allowedIp) {
- allowedIps.add(allowedIp);
- return this;
- }
-
- public Builder addAllowedIps(final Collection<InetNetwork> allowedIps) {
- this.allowedIps.addAll(allowedIps);
- return this;
- }
-
- public Peer build() throws BadConfigException {
- if (publicKey == null)
- throw new BadConfigException(Section.PEER, Location.PUBLIC_KEY,
- Reason.MISSING_ATTRIBUTE, null);
- return new Peer(this);
- }
-
- public Builder parseAllowedIPs(final CharSequence allowedIps) throws BadConfigException {
- try {
- for (final String allowedIp : Attribute.split(allowedIps))
- addAllowedIp(InetNetwork.parse(allowedIp));
- return this;
- } catch (final ParseException e) {
- throw new BadConfigException(Section.PEER, Location.ALLOWED_IPS, e);
- }
- }
-
- public Builder parseEndpoint(final String endpoint) throws BadConfigException {
- try {
- return setEndpoint(InetEndpoint.parse(endpoint));
- } catch (final ParseException e) {
- throw new BadConfigException(Section.PEER, Location.ENDPOINT, e);
- }
- }
-
- public Builder parsePersistentKeepalive(final String persistentKeepalive)
- throws BadConfigException {
- try {
- return setPersistentKeepalive(Integer.parseInt(persistentKeepalive));
- } catch (final NumberFormatException e) {
- throw new BadConfigException(Section.PEER, Location.PERSISTENT_KEEPALIVE,
- persistentKeepalive, e);
- }
- }
-
- public Builder parsePreSharedKey(final String preSharedKey) throws BadConfigException {
- try {
- return setPreSharedKey(Key.fromBase64(preSharedKey));
- } catch (final KeyFormatException e) {
- throw new BadConfigException(Section.PEER, Location.PRE_SHARED_KEY, e);
- }
- }
-
- public Builder parsePublicKey(final String publicKey) throws BadConfigException {
- try {
- return setPublicKey(Key.fromBase64(publicKey));
- } catch (final KeyFormatException e) {
- throw new BadConfigException(Section.PEER, Location.PUBLIC_KEY, e);
- }
- }
-
- public Builder setEndpoint(final InetEndpoint endpoint) {
- this.endpoint = Optional.of(endpoint);
- return this;
- }
-
- public Builder setPersistentKeepalive(final int persistentKeepalive)
- throws BadConfigException {
- if (persistentKeepalive < 0 || persistentKeepalive > MAX_PERSISTENT_KEEPALIVE)
- throw new BadConfigException(Section.PEER, Location.PERSISTENT_KEEPALIVE,
- Reason.INVALID_VALUE, String.valueOf(persistentKeepalive));
- this.persistentKeepalive = persistentKeepalive == 0 ?
- Optional.empty() : Optional.of(persistentKeepalive);
- return this;
- }
-
- public Builder setPreSharedKey(final Key preSharedKey) {
- this.preSharedKey = Optional.of(preSharedKey);
- return this;
- }
-
- public Builder setPublicKey(final Key publicKey) {
- this.publicKey = publicKey;
- return this;
- }
- }
-}