diff options
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java')
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java | 203 |
1 files changed, 167 insertions, 36 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 6f0ccf18..d9bf5dd3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -20,48 +20,125 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; import java.util.Iterator; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.Provider; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static se.leap.bitmaskclient.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.Constants.OPTIONS; +import static se.leap.bitmaskclient.Constants.PORTS; +import static se.leap.bitmaskclient.Constants.PROTOCOLS; import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.Constants.REMOTE; +import static se.leap.bitmaskclient.Constants.TRANSPORT; +import static se.leap.bitmaskclient.Constants.TYPE; +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP; +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT; public class VpnConfigGenerator { - - private JSONObject general_configuration; + private JSONObject generalConfiguration; private JSONObject gateway; private JSONObject secrets; + private JSONObject obfs4Transport; + private int apiVersion; + public final static String TAG = VpnConfigGenerator.class.getSimpleName(); private final String newLine = System.getProperty("line.separator"); // Platform new line - public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) { - this.general_configuration = general_configuration; + public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion) throws ConfigParser.ConfigParseError { + this.generalConfiguration = generalConfiguration; this.gateway = gateway; this.secrets = secrets; + this.apiVersion = apiVersion; + checkCapabilities(); } - public String generate() { - return - generalConfiguration() - + newLine - + gatewayConfiguration() - + newLine - + secretsConfiguration() - + newLine - + androidCustomizations(); + public void checkCapabilities() throws ConfigParser.ConfigParseError { + + try { + if (apiVersion == 3) { + JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); + for (int i = 0; i < supportedTransports.length(); i++) { + JSONObject transport = supportedTransports.getJSONObject(i); + if (transport.getString(TYPE).equals(OBFS4.toString())) { + obfs4Transport = transport; + break; + } + } + } + + } catch (JSONException e) { + throw new ConfigParser.ConfigParseError("Api version ("+ apiVersion +") did not match required JSON fields"); + } + } + + public HashMap<Connection.TransportType, VpnProfile> generateVpnProfiles() throws + ConfigParser.ConfigParseError, + NumberFormatException, + JSONException, + IOException { + HashMap<Connection.TransportType, VpnProfile> profiles = new HashMap<>(); + profiles.put(OPENVPN, createProfile(OPENVPN)); + if (supportsObfs4()) { + profiles.put(OBFS4, createProfile(OBFS4)); + } + return profiles; + } + + private boolean supportsObfs4(){ + return obfs4Transport != null; + } + + private String getConfigurationString(Connection.TransportType transportType) { + return generalConfiguration() + + newLine + + gatewayConfiguration(transportType) + + newLine + + androidCustomizations() + + newLine + + secretsConfiguration(); + } + + private VpnProfile createProfile(Connection.TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException { + String configuration = getConfigurationString(transportType); + ConfigParser icsOpenvpnConfigParser = new ConfigParser(); + icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); + if (transportType == OBFS4) { + icsOpenvpnConfigParser.setObfs4Options(getObfs4Options()); + } + return icsOpenvpnConfigParser.convertProfile(transportType); + } + + private Obfs4Options getObfs4Options() throws JSONException { + JSONObject transportOptions = obfs4Transport.getJSONObject(OPTIONS); + String iatMode = transportOptions.getString("iat-mode"); + String cert = transportOptions.getString("cert"); + String port = obfs4Transport.getJSONArray(PORTS).getString(0); + String ip = gateway.getString(IP_ADDRESS); + return new Obfs4Options(ip, port, cert, iatMode); } private String generalConfiguration() { String commonOptions = ""; try { - Iterator keys = general_configuration.keys(); + Iterator keys = generalConfiguration.keys(); while (keys.hasNext()) { String key = keys.next().toString(); commonOptions += key + " "; - for (String word : String.valueOf(general_configuration.get(key)).split(" ")) + for (String word : String.valueOf(generalConfiguration.get(key)).split(" ")) commonOptions += word + " "; commonOptions += newLine; @@ -76,41 +153,95 @@ public class VpnConfigGenerator { return commonOptions; } - private String gatewayConfiguration() { + private String gatewayConfiguration(Connection.TransportType transportType) { String remotes = ""; - String ipAddressKeyword = "ip_address"; - String remoteKeyword = "remote"; - String portsKeyword = "ports"; - String protocolKeyword = "protocols"; - String capabilitiesKeyword = "capabilities"; - + StringBuilder stringBuilder = new StringBuilder(); try { - String ip_address = gateway.getString(ipAddressKeyword); - JSONObject capabilities = gateway.getJSONObject(capabilitiesKeyword); - JSONArray ports = capabilities.getJSONArray(portsKeyword); - for (int i = 0; i < ports.length(); i++) { - String port_specific_remotes = ""; - int port = ports.getInt(i); - JSONArray protocols = capabilities.getJSONArray(protocolKeyword); - for (int j = 0; j < protocols.length(); j++) { - String protocol = protocols.optString(j); - String new_remote = remoteKeyword + " " + ip_address + " " + port + " " + protocol + newLine; - - port_specific_remotes += new_remote; - } - remotes += port_specific_remotes; + String ipAddress = gateway.getString(IP_ADDRESS); + JSONObject capabilities = gateway.getJSONObject(CAPABILITIES); + switch (apiVersion) { + default: + case 1: + case 2: + gatewayConfigApiv1(stringBuilder, ipAddress, capabilities); + break; + case 3: + JSONArray transports = capabilities.getJSONArray(TRANSPORT); + gatewayConfigApiv3(transportType, stringBuilder, ipAddress, transports); + break; } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } + + remotes = stringBuilder.toString(); if (remotes.endsWith(newLine)) { remotes = remotes.substring(0, remotes.lastIndexOf(newLine)); } return remotes; } + private void gatewayConfigApiv3(Connection.TransportType transportType, StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + if (transportType == OBFS4) { + obfs4GatewayConfigApiv3(stringBuilder, ipAddress, transports); + } else { + ovpnGatewayConfigApi3(stringBuilder, ipAddress, transports); + } + } + + private void gatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException { + int port; + String protocol; + JSONArray ports = capabilities.getJSONArray(PORTS); + for (int i = 0; i < ports.length(); i++) { + port = ports.getInt(i); + JSONArray protocols = capabilities.getJSONArray(PROTOCOLS); + for (int j = 0; j < protocols.length(); j++) { + protocol = protocols.optString(j); + String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; + stringBuilder.append(newRemote); + } + } + } + + private void ovpnGatewayConfigApi3(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + String port; + String protocol; + JSONObject openvpnTransport = getTransport(transports, OPENVPN); + JSONArray ports = openvpnTransport.getJSONArray(PORTS); + for (int j = 0; j < ports.length(); j++) { + port = ports.getString(j); + JSONArray protocols = openvpnTransport.getJSONArray(PROTOCOLS); + for (int k = 0; k < protocols.length(); k++) { + protocol = protocols.optString(k); + String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; + stringBuilder.append(newRemote); + } + } + } + + private JSONObject getTransport(JSONArray transports, Connection.TransportType transportType) throws JSONException { + JSONObject selectedTransport = new JSONObject(); + for (int i = 0; i < transports.length(); i++) { + JSONObject transport = transports.getJSONObject(i); + if (transport.getString(TYPE).equals(transportType.toString())) { + selectedTransport = transport; + break; + } + } + return selectedTransport; + } + + private void obfs4GatewayConfigApiv3(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + JSONObject obfs4Transport = getTransport(transports, OBFS4); + String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; + stringBuilder.append(route); + String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " " + obfs4Transport.getJSONArray(PROTOCOLS).getString(0) + newLine; + stringBuilder.append(remote); + } + private String secretsConfiguration() { try { String ca = |