Useful for validation errors and localisation later on Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>master
@@ -15,6 +15,7 @@ import android.support.annotation.Nullable; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.BR; | |||
import com.wireguard.android.R; | |||
import com.wireguard.android.configStore.ConfigStore; | |||
import com.wireguard.android.model.Tunnel.State; | |||
import com.wireguard.android.model.Tunnel.Statistics; | |||
@@ -46,6 +47,7 @@ public final class TunnelManager extends BaseObservable { | |||
private static final String KEY_RUNNING_TUNNELS = "enabled_configs"; | |||
private final ConfigStore configStore; | |||
private final Context context = Application.get(); | |||
private final CompletableFuture<ObservableSortedKeyedList<String, Tunnel>> completableTunnels = new CompletableFuture<>(); | |||
private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR); | |||
@Nullable private Tunnel lastUsedTunnel; | |||
@@ -64,9 +66,9 @@ public final class TunnelManager extends BaseObservable { | |||
public CompletionStage<Tunnel> create(final String name, @Nullable final Config config) { | |||
if (Tunnel.isNameInvalid(name)) | |||
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name")); | |||
return CompletableFuture.failedFuture(new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_name))); | |||
if (tunnels.containsKey(name)) { | |||
final String message = "Tunnel " + name + " already exists"; | |||
final String message = context.getString(R.string.tunnel_error_already_exists, name); | |||
return CompletableFuture.failedFuture(new IllegalArgumentException(message)); | |||
} | |||
return Application.getAsyncWorker().supplyAsync(() -> configStore.create(name, config)) | |||
@@ -212,9 +214,9 @@ public final class TunnelManager extends BaseObservable { | |||
CompletionStage<String> setTunnelName(final Tunnel tunnel, final String name) { | |||
if (Tunnel.isNameInvalid(name)) | |||
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name")); | |||
return CompletableFuture.failedFuture(new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_name))); | |||
if (tunnels.containsKey(name)) { | |||
final String message = "Tunnel " + name + " already exists"; | |||
final String message = context.getString(R.string.tunnel_error_already_exists, name); | |||
return CompletableFuture.failedFuture(new IllegalArgumentException(message)); | |||
} | |||
final State originalState = tunnel.getState(); | |||
@@ -6,6 +6,7 @@ | |||
package com.wireguard.config; | |||
import android.content.Context; | |||
import android.databinding.BaseObservable; | |||
import android.databinding.Bindable; | |||
import android.databinding.ObservableArrayList; | |||
@@ -15,6 +16,8 @@ import android.os.Parcelable; | |||
import android.support.annotation.Nullable; | |||
import com.android.databinding.library.baseAdapters.BR; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.R; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
@@ -43,6 +46,7 @@ public class Config { | |||
public static Config from(final BufferedReader reader) throws IOException { | |||
final Config config = new Config(); | |||
final Context context = Application.get(); | |||
Peer currentPeer = null; | |||
String line; | |||
boolean inInterfaceSection = false; | |||
@@ -65,11 +69,11 @@ public class Config { | |||
} else if (currentPeer != null) { | |||
currentPeer.parse(line); | |||
} else { | |||
throw new IllegalArgumentException("Invalid configuration line: " + line); | |||
throw new IllegalArgumentException(context.getString(R.string.tunnel_error_invalid_config_line, line)); | |||
} | |||
} | |||
if (!inInterfaceSection && currentPeer == null) { | |||
throw new IllegalArgumentException("Could not find any config information"); | |||
throw new IllegalArgumentException(context.getString(R.string.tunnel_error_no_config_information)); | |||
} | |||
return config; | |||
} | |||
@@ -8,6 +8,9 @@ package com.wireguard.config; | |||
import android.support.annotation.Nullable; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.R; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import java.net.InetAddress; | |||
@@ -30,7 +33,7 @@ public final class InetAddresses { | |||
public static InetAddress parse(@Nullable final String address) { | |||
if (address == null || address.isEmpty()) | |||
throw new IllegalArgumentException("Empty address"); | |||
throw new IllegalArgumentException(Application.get().getString(R.string.tunnel_error_empty_inetaddress)); | |||
try { | |||
return (InetAddress) PARSER_METHOD.invoke(null, address); | |||
} catch (final IllegalAccessException | InvocationTargetException e) { | |||
@@ -6,13 +6,16 @@ | |||
package com.wireguard.config; | |||
import android.content.Context; | |||
import android.databinding.BaseObservable; | |||
import android.databinding.Bindable; | |||
import android.os.Parcel; | |||
import android.os.Parcelable; | |||
import android.support.annotation.Nullable; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.BR; | |||
import com.wireguard.android.R; | |||
import com.wireguard.crypto.Keypair; | |||
import java.net.InetAddress; | |||
@@ -31,6 +34,7 @@ public class Interface { | |||
@Nullable private Keypair keypair; | |||
private int listenPort; | |||
private int mtu; | |||
private final Context context = Application.get(); | |||
public Interface() { | |||
addressList = new ArrayList<>(); | |||
@@ -42,7 +46,7 @@ public class Interface { | |||
if (addresses != null && addresses.length > 0) { | |||
for (final String addr : addresses) { | |||
if (addr.isEmpty()) | |||
throw new IllegalArgumentException("Address is empty"); | |||
throw new IllegalArgumentException(context.getString(R.string.tunnel_error_empty_interface_address)); | |||
addressList.add(new InetNetwork(addr)); | |||
} | |||
} | |||
@@ -141,7 +145,7 @@ public class Interface { | |||
public void parse(final String line) { | |||
final Attribute key = Attribute.match(line); | |||
if (key == null) | |||
throw new IllegalArgumentException(String.format("Unable to parse line: \"%s\"", line)); | |||
throw new IllegalArgumentException(String.format(context.getString(R.string.tunnel_error_interface_parse_failed), line)); | |||
switch (key) { | |||
case ADDRESS: | |||
addAddresses(key.parseList(line)); | |||
@@ -6,6 +6,7 @@ | |||
package com.wireguard.config; | |||
import android.content.Context; | |||
import android.databinding.BaseObservable; | |||
import android.databinding.Bindable; | |||
import android.os.Parcel; | |||
@@ -13,6 +14,8 @@ import android.os.Parcelable; | |||
import android.support.annotation.Nullable; | |||
import com.android.databinding.library.baseAdapters.BR; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.R; | |||
import com.wireguard.crypto.KeyEncoding; | |||
import java.net.Inet6Address; | |||
@@ -38,6 +41,7 @@ public class Peer { | |||
private int persistentKeepalive; | |||
@Nullable private String preSharedKey; | |||
@Nullable private String publicKey; | |||
private final Context context = Application.get(); | |||
public Peer() { | |||
allowedIPsList = new ArrayList<>(); | |||
@@ -117,7 +121,7 @@ public class Peer { | |||
public void parse(final String line) { | |||
final Attribute key = Attribute.match(line); | |||
if (key == null) | |||
throw new IllegalArgumentException(String.format("Unable to parse line: \"%s\"", line)); | |||
throw new IllegalArgumentException(context.getString(R.string.tunnel_error_interface_parse_failed, line)); | |||
switch (key) { | |||
case ALLOWED_IPS: | |||
addAllowedIPs(key.parseList(line)); | |||
@@ -152,7 +156,7 @@ public class Peer { | |||
if (endpoint != null && !endpoint.isEmpty()) { | |||
final InetSocketAddress constructedEndpoint; | |||
if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1) | |||
throw new IllegalArgumentException("Forbidden characters in endpoint"); | |||
throw new IllegalArgumentException(context.getString(R.string.tunnel_error_forbidden_endpoint_chars)); | |||
final URI uri; | |||
try { | |||
uri = new URI("wg://" + endpoint); | |||
@@ -253,7 +257,7 @@ public class Peer { | |||
parent.setPreSharedKey(preSharedKey); | |||
parent.setPublicKey(publicKey); | |||
if (parent.getPublicKey() == null) | |||
throw new IllegalArgumentException("Peer public key may not be empty"); | |||
throw new IllegalArgumentException(Application.get().getString(R.string.tunnel_error_empty_peer_public_key)); | |||
loadData(parent); | |||
notifyChange(); | |||
} | |||
@@ -5,6 +5,9 @@ | |||
package com.wireguard.crypto; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.R; | |||
/** | |||
* This is a specialized constant-time base64 and hex implementation that resists side-channel attacks. | |||
*/ | |||
@@ -15,11 +18,11 @@ public final class KeyEncoding { | |||
public static final int KEY_LENGTH_BASE64 = 44; | |||
public static final int KEY_LENGTH_HEX = 64; | |||
private static final String KEY_LENGTH_BASE64_EXCEPTION_MESSAGE = | |||
"WireGuard base64 keys must be 44 characters encoding 32 bytes"; | |||
Application.get().getString(R.string.key_length_base64_exception_message); | |||
private static final String KEY_LENGTH_EXCEPTION_MESSAGE = | |||
"WireGuard keys must be 32 bytes"; | |||
Application.get().getString(R.string.key_length_exception_message); | |||
private static final String KEY_LENGTH_HEX_EXCEPTION_MESSAGE = | |||
"WireGuard hex keys must be 64 characters encoding 32 bytes"; | |||
Application.get().getString(R.string.key_length_hex_exception_message); | |||
private KeyEncoding() { | |||
// Prevent instantiation. | |||
@@ -97,6 +97,18 @@ | |||
<string name="tunnel_name">Tunnel Name</string> | |||
<string name="tunnel_rename_error">Unable to rename tunnel: %s</string> | |||
<string name="tunnel_rename_success">Successfully renamed tunnel to “%s”</string> | |||
<string name="tunnel_error_invalid_name">Invalid name</string> | |||
<string name="tunnel_error_already_exists">Tunnel %s already exists</string> | |||
<string name="tunnel_error_empty_inetaddress">Empty address</string> | |||
<string name="tunnel_error_empty_interface_address">Address is empty</string> | |||
<string name="tunnel_error_interface_parse_failed">Unable to parse line: “%s”</string> | |||
<string name="tunnel_error_forbidden_endpoint_chars">Forbidden characters in endpoint</string> | |||
<string name="tunnel_error_empty_peer_public_key">Peer public key may not be empty</string> | |||
<string name="tunnel_error_invalid_config_line">Invalid configuration line: %s</string> | |||
<string name="tunnel_error_no_config_information">Could not find any config information</string> | |||
<string name="key_length_base64_exception_message">WireGuard base64 keys must be 44 characters encoding 32 bytes</string> | |||
<string name="key_length_exception_message">WireGuard keys must be 32 bytes</string> | |||
<string name="key_length_hex_exception_message">WireGuard hex keys must be 64 characters encoding 32 bytes</string> | |||
<string name="version_title">WireGuard for Android v%s"</string> | |||
<string name="version_summary">%s backend v%s</string> | |||
<string name="version_summary_checking">Checking %s backend version</string> | |||