Home | History | Annotate | Download | only in connectivitymanagertest
      1 /*
      2  * Copyright (C) 2010, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.connectivitymanagertest;
     18 
     19 import android.net.IpConfiguration.IpAssignment;
     20 import android.net.IpConfiguration.ProxySettings;
     21 import android.net.LinkAddress;
     22 import android.net.StaticIpConfiguration;
     23 import android.net.wifi.WifiConfiguration;
     24 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
     25 import android.net.wifi.WifiConfiguration.KeyMgmt;
     26 import android.net.wifi.WifiEnterpriseConfig;
     27 
     28 import org.json.JSONArray;
     29 import org.json.JSONException;
     30 import org.json.JSONObject;
     31 
     32 import java.net.InetAddress;
     33 import java.net.UnknownHostException;
     34 import java.util.ArrayList;
     35 import java.util.List;
     36 
     37 /**
     38  * Helper for dealing with creating {@link WifiConfiguration} objects.
     39  */
     40 public class WifiConfigurationHelper {
     41     private static final int NONE = 0;
     42     private static final int WEP = 1;
     43     private static final int PSK = 2;
     44     private static final int EAP = 3;
     45 
     46     /**
     47      * Private constructor since this a static class.
     48      */
     49     private WifiConfigurationHelper() {}
     50 
     51     /**
     52      * Create a {@link WifiConfiguration} for an open network
     53      *
     54      * @param ssid The SSID of the wifi network
     55      * @return The {@link WifiConfiguration}
     56      */
     57     public static WifiConfiguration createOpenConfig(String ssid) {
     58         WifiConfiguration config = createGenericConfig(ssid);
     59 
     60         config.allowedKeyManagement.set(KeyMgmt.NONE);
     61         return config;
     62     }
     63 
     64     /**
     65      * Create a {@link WifiConfiguration} for a WEP secured network
     66      *
     67      * @param ssid The SSID of the wifi network
     68      * @param password Either a 10, 26, or 58 character hex string or the plain text password
     69      * @return The {@link WifiConfiguration}
     70      */
     71     public static WifiConfiguration createWepConfig(String ssid, String password) {
     72         WifiConfiguration config = createGenericConfig(ssid);
     73 
     74         if (isHex(password, 10) || isHex(password, 26) || isHex(password, 58)) {
     75             config.wepKeys[0] = password;
     76         } else {
     77             config.wepKeys[0] = quotedString(password);
     78         }
     79 
     80         config.allowedKeyManagement.set(KeyMgmt.NONE);
     81         config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
     82         config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
     83         return config;
     84     }
     85 
     86     /**
     87      * Create a {@link WifiConfiguration} for a PSK secured network
     88      *
     89      * @param ssid The SSID of the wifi network
     90      * @param password Either a 64 character hex string or the plain text password
     91      * @return The {@link WifiConfiguration}
     92      */
     93     public static WifiConfiguration createPskConfig(String ssid, String password) {
     94         WifiConfiguration config = createGenericConfig(ssid);
     95 
     96         if (isHex(password, 64)) {
     97             config.preSharedKey = password;
     98         } else {
     99             config.preSharedKey = quotedString(password);
    100         }
    101         config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
    102         return config;
    103     }
    104 
    105     /**
    106      * Create a {@link WifiConfiguration} for an EAP secured network
    107      *
    108      * @param ssid The SSID of the wifi network
    109      * @param password The password
    110      * @param eapMethod The EAP method
    111      * @param phase2 The phase 2 method or null
    112      * @param identity The identity or null
    113      * @param anonymousIdentity The anonymous identity or null
    114      * @param caCert The CA certificate or null
    115      * @param clientCert The client certificate or null
    116      * @return The {@link WifiConfiguration}
    117      */
    118     public static WifiConfiguration createEapConfig(String ssid, String password, int eapMethod,
    119             Integer phase2, String identity, String anonymousIdentity, String caCert,
    120             String clientCert) {
    121         WifiConfiguration config = new WifiConfiguration();
    122         config.SSID = quotedString(ssid);
    123 
    124         config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
    125         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
    126 
    127         // Set defaults
    128         if (phase2 == null) phase2 = WifiEnterpriseConfig.Phase2.NONE;
    129         if (identity == null) identity = "";
    130         if (anonymousIdentity == null) anonymousIdentity = "";
    131         if (caCert == null) caCert = "";
    132         if (clientCert == null) clientCert = "";
    133 
    134         config.enterpriseConfig.setPassword(password);
    135         config.enterpriseConfig.setEapMethod(eapMethod);
    136         config.enterpriseConfig.setPhase2Method(phase2);
    137         config.enterpriseConfig.setIdentity(identity);
    138         config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
    139         config.enterpriseConfig.setCaCertificateAlias(caCert);
    140         config.enterpriseConfig.setClientCertificateAlias(clientCert);
    141         return config;
    142     }
    143 
    144     /**
    145      * Create a generic {@link WifiConfiguration} used by the other create methods.
    146      */
    147     private static WifiConfiguration createGenericConfig(String ssid) {
    148         WifiConfiguration config = new WifiConfiguration();
    149         config.SSID = quotedString(ssid);
    150         config.setIpAssignment(IpAssignment.DHCP);
    151         config.setProxySettings(ProxySettings.NONE);
    152         return config;
    153     }
    154 
    155     /**
    156      * Parse a JSON string for WiFi configurations stored as a JSON string.
    157      * <p>
    158      * This json string should be a list of dictionaries, with each dictionary containing a single
    159      * wifi configuration. The wifi configuration requires the fields "ssid" and "security" with
    160      * security being one of NONE, WEP, PSK, or EAP. If WEP, PSK, or EAP are selected, the field
    161      * "password" must also be provided.  If EAP is selected, then the fiels "eap", "phase2",
    162      * "identity", "ananymous_identity", "ca_cert", and "client_cert" are also required. Lastly,
    163      * static IP settings are also supported.  If the field "ip" is set, then the fields "gateway",
    164      * "prefix_length", "dns1", and "dns2" are required.
    165      * </p>
    166      * @throws IllegalArgumentException if the input string was not valid JSON or if any mandatory
    167      * fields are missing.
    168      */
    169     public static List<WifiConfiguration> parseJson(String in) {
    170         try {
    171             JSONArray jsonConfigs = new JSONArray(in);
    172             List<WifiConfiguration> wifiConfigs = new ArrayList<>(jsonConfigs.length());
    173 
    174             for (int i = 0; i < jsonConfigs.length(); i++) {
    175                 JSONObject jsonConfig = jsonConfigs.getJSONObject(i);
    176 
    177                 wifiConfigs.add(getWifiConfiguration(jsonConfig));
    178             }
    179             return wifiConfigs;
    180         } catch (JSONException e) {
    181             throw new IllegalArgumentException(e);
    182         }
    183     }
    184 
    185     /**
    186      * Parse a {@link JSONObject} and return the wifi configuration.
    187      *
    188      * @throws IllegalArgumentException if any mandatory fields are missing.
    189      */
    190     private static WifiConfiguration getWifiConfiguration(JSONObject jsonConfig)
    191             throws JSONException {
    192         String ssid = jsonConfig.getString("ssid");
    193         String password = null;
    194         WifiConfiguration config;
    195 
    196         int securityType = getSecurityType(jsonConfig.getString("security"));
    197         switch (securityType) {
    198             case NONE:
    199                 config = createOpenConfig(ssid);
    200                 break;
    201             case WEP:
    202                 password = jsonConfig.getString("password");
    203                 config = createWepConfig(ssid, password);
    204                 break;
    205             case PSK:
    206                 password = jsonConfig.getString("password");
    207                 config = createPskConfig(ssid, password);
    208                 break;
    209             case EAP:
    210                 password = jsonConfig.getString("password");
    211                 int eapMethod = getEapMethod(jsonConfig.getString("eap"));
    212                 Integer phase2 = null;
    213                 if (jsonConfig.has("phase2")) {
    214                     phase2 = getPhase2(jsonConfig.getString("phase2"));
    215                 }
    216                 String identity = null;
    217                 if (jsonConfig.has("identity")) {
    218                     identity = jsonConfig.getString("identity");
    219                 }
    220                 String anonymousIdentity = null;
    221                 if (jsonConfig.has("anonymous_identity")) {
    222                     anonymousIdentity = jsonConfig.getString("anonymous_identity");
    223                 }
    224                 String caCert = null;
    225                 if (jsonConfig.has("ca_cert")) {
    226                     caCert = (jsonConfig.getString("ca_cert"));
    227                 }
    228                 String clientCert = null;
    229                 if (jsonConfig.has("client_cert")) {
    230                     clientCert = jsonConfig.getString("client_cert");
    231                 }
    232                 config = createEapConfig(ssid, password, eapMethod, phase2, identity,
    233                         anonymousIdentity, caCert, clientCert);
    234                 break;
    235             default:
    236                 // Should never reach here as getSecurityType will already throw an exception
    237                 throw new IllegalArgumentException();
    238         }
    239 
    240         if (jsonConfig.has("ip")) {
    241             StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
    242 
    243             InetAddress ipAddress = getInetAddress(jsonConfig.getString("ip"));
    244             int prefixLength = getPrefixLength(jsonConfig.getInt("prefix_length"));
    245             staticIpConfig.ipAddress = new LinkAddress(ipAddress, prefixLength);
    246             staticIpConfig.gateway = getInetAddress(jsonConfig.getString("gateway"));
    247             staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns1")));
    248             staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns2")));
    249 
    250             config.setIpAssignment(IpAssignment.STATIC);
    251             config.setStaticIpConfiguration(staticIpConfig);
    252         } else {
    253             config.setIpAssignment(IpAssignment.DHCP);
    254         }
    255 
    256         config.setProxySettings(ProxySettings.NONE);
    257         return config;
    258     }
    259 
    260     private static String quotedString(String s) {
    261         return String.format("\"%s\"", s);
    262     }
    263 
    264     /**
    265      * Get the security type from a string.
    266      *
    267      * @throws IllegalArgumentException if the string is not a supported security type.
    268      */
    269     private static int getSecurityType(String security) {
    270         if ("NONE".equalsIgnoreCase(security)) {
    271             return NONE;
    272         }
    273         if ("WEP".equalsIgnoreCase(security)) {
    274             return WEP;
    275         }
    276         if ("PSK".equalsIgnoreCase(security)) {
    277             return PSK;
    278         }
    279         if ("EAP".equalsIgnoreCase(security)) {
    280             return EAP;
    281         }
    282         throw new IllegalArgumentException("Security type must be one of NONE, WEP, PSK, or EAP");
    283     }
    284 
    285     /**
    286      * Get the EAP method from a string.
    287      *
    288      * @throws IllegalArgumentException if the string is not a supported EAP method.
    289      */
    290     private static int getEapMethod(String eapMethod) {
    291         if ("TLS".equalsIgnoreCase(eapMethod)) {
    292             return WifiEnterpriseConfig.Eap.TLS;
    293         }
    294         if ("TTLS".equalsIgnoreCase(eapMethod)) {
    295             return WifiEnterpriseConfig.Eap.TTLS;
    296         }
    297         if ("PEAP".equalsIgnoreCase(eapMethod)) {
    298             return WifiEnterpriseConfig.Eap.PEAP;
    299         }
    300         throw new IllegalArgumentException("EAP method must be one of TLS, TTLS, or PEAP");
    301     }
    302 
    303     /**
    304      * Get the phase 2 method from a string.
    305      *
    306      * @throws IllegalArgumentException if the string is not a supported phase 2 method.
    307      */
    308     private static int getPhase2(String phase2) {
    309         if ("PAP".equalsIgnoreCase(phase2)) {
    310             return WifiEnterpriseConfig.Phase2.PAP;
    311         }
    312         if ("MSCHAP".equalsIgnoreCase(phase2)) {
    313             return WifiEnterpriseConfig.Phase2.MSCHAP;
    314         }
    315         if ("MSCHAPV2".equalsIgnoreCase(phase2)) {
    316             return WifiEnterpriseConfig.Phase2.MSCHAPV2;
    317         }
    318         if ("GTC".equalsIgnoreCase(phase2)) {
    319             return WifiEnterpriseConfig.Phase2.GTC;
    320         }
    321         throw new IllegalArgumentException("Phase2 must be one of PAP, MSCHAP, MSCHAPV2, or GTC");
    322     }
    323 
    324     /**
    325      * Get an {@link InetAddress} from a string
    326      *
    327      * @throws IllegalArgumentException if the string is not a valid IP address.
    328      */
    329     private static InetAddress getInetAddress(String ipAddress) {
    330         if (!InetAddress.isNumeric(ipAddress)) {
    331             throw new IllegalArgumentException(
    332                     String.format("IP address %s is not numeric", ipAddress));
    333         }
    334 
    335         try {
    336             return InetAddress.getByName(ipAddress);
    337         } catch (UnknownHostException e) {
    338             throw new IllegalArgumentException(
    339                     String.format("IP address %s could not be resolved", ipAddress));
    340         }
    341     }
    342 
    343     /**
    344      * Get the prefix length from an int.
    345      *
    346      * @throws IllegalArgumentException if the prefix length is less than 0 or greater than 32.
    347      */
    348     private static int getPrefixLength(int prefixLength) {
    349         if (prefixLength < 0 || prefixLength > 32) {
    350             throw new IllegalArgumentException("Prefix length cannot be less than 0 or more than 32");
    351         }
    352         return prefixLength;
    353     }
    354 
    355     /**
    356      * Utility method to check if a given string is a hexadecimal string of given length
    357      */
    358     public static boolean isHex(String input, int length) {
    359         if (input == null || length < 0) {
    360             return false;
    361         }
    362         return input.matches(String.format("[0-9A-Fa-f]{%d}", length));
    363     }
    364 }
    365