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