• 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.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      */
WifiConfigurationHelper()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      */
createOpenConfig(String ssid)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      */
createWepConfig(String ssid, String password)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      */
createPskConfig(String ssid, String password)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      */
createEapConfig(String ssid, String password, int eapMethod, Integer phase2, String identity, String anonymousIdentity, String caCert, String clientCert)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      */
createGenericConfig(String ssid)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      */
parseJson(String in)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      */
getWifiConfiguration(JSONObject jsonConfig)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 
quotedString(String s)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      */
getSecurityType(String security)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      */
getEapMethod(String eapMethod)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      */
getPhase2(String phase2)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      */
getInetAddress(String ipAddress)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      */
getPrefixLength(int prefixLength)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      */
isHex(String input, int length)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