1 /* 2 * Copyright (C) 2018 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.server.wifi; 18 19 import android.annotation.Nullable; 20 import android.net.InetAddresses; 21 import android.net.IpConfiguration; 22 import android.net.IpConfiguration.IpAssignment; 23 import android.net.IpConfiguration.ProxySettings; 24 import android.net.LinkAddress; 25 import android.net.ProxyInfo; 26 import android.net.RouteInfo; 27 import android.net.StaticIpConfiguration; 28 import android.net.Uri; 29 import android.net.wifi.SecurityParams; 30 import android.net.wifi.WifiConfiguration; 31 import android.util.Log; 32 import android.util.Pair; 33 34 import com.android.server.wifi.util.XmlUtil; 35 import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; 36 import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; 37 38 import org.xmlpull.v1.XmlPullParser; 39 import org.xmlpull.v1.XmlPullParserException; 40 41 import java.io.IOException; 42 import java.net.Inet4Address; 43 import java.net.InetAddress; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.BitSet; 47 import java.util.Collections; 48 import java.util.HashSet; 49 import java.util.List; 50 import java.util.Locale; 51 import java.util.Set; 52 53 /** 54 * Parser for major version 1 of WiFi backup data. 55 * Contains whitelists of tags for WifiConfiguration and IpConfiguration sections for each of 56 * the minor versions. 57 * 58 * Overall structure of the major version 1 XML schema: 59 * <?xml version='1.0' encoding='utf-8' standalone='yes' ?> 60 * <WifiConfigStore> 61 * <float name="Version" value="1.0" /> 62 * <NetworkList> 63 * <Network> 64 * <WifiConfiguration> 65 * <string name="ConfigKey">value</string> 66 * <string name="SSID">value</string> 67 * <string name="PreSharedKey" />value</string> 68 * <string-array name="WEPKeys" num="4"> 69 * <item value="WifiConfigStoreWep1" /> 70 * <item value="WifiConfigStoreWep2" /> 71 * <item value="WifiConfigStoreWep3" /> 72 * <item value="WifiConfigStoreWep3" /> 73 * </string-array> 74 * ... (other supported tag names in minor version 1: "WEPTxKeyIndex", "HiddenSSID", 75 * "RequirePMF", "AllowedKeyMgmt", "AllowedProtocols", "AllowedAuthAlgos", 76 * "AllowedGroupCiphers", "AllowedPairwiseCiphers", "Shared") 77 * </WifiConfiguration> 78 * <IpConfiguration> 79 * <string name="IpAssignment">value</string> 80 * <string name="ProxySettings">value</string> 81 * ... (other supported tag names in minor version 1: "LinkAddress", "LinkPrefixLength", 82 * "GatewayAddress", "DNSServers", "ProxyHost", "ProxyPort", "ProxyPac", 83 * "ProxyExclusionList") 84 * </IpConfiguration> 85 * </Network> 86 * <Network> 87 * ... (format as above) 88 * </Network> 89 * </NetworkList> 90 * </WifiConfigStore> 91 */ 92 class WifiBackupDataV1Parser implements WifiBackupDataParser { 93 94 private static final String TAG = "WifiBackupDataV1Parser"; 95 96 private static final int HIGHEST_SUPPORTED_MINOR_VERSION = 4; 97 98 // List of tags supported for <WifiConfiguration> section in minor version 0 99 private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS = Set.of( 100 WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY, 101 WifiConfigurationXmlUtil.XML_TAG_SSID, 102 WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY, 103 WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS, 104 WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX, 105 WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID, 106 WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF, 107 WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT, 108 WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS, 109 WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS, 110 WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS, 111 WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS, 112 WifiConfigurationXmlUtil.XML_TAG_SHARED); 113 114 // List of tags supported for <WifiConfiguration> section in minor version 1 115 private static final Set<String> WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS = 116 new HashSet<String>(); 117 static { 118 WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS.addAll( 119 WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS); 120 WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS.add( 121 WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE); 122 } 123 124 // List of tags supported for <WifiConfiguration> section in minor version 2 125 private static final Set<String> WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS = 126 new HashSet<String>(); 127 static { 128 WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS.addAll( 129 WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS); 130 WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS.add( 131 WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN); 132 } 133 134 // List of tags supported for <WifiConfiguration> section in minor version 3 135 private static final Set<String> WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS = 136 new HashSet<String>(); 137 static { 138 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.addAll( 139 WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS); 140 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 141 WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST); 142 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 143 WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS); 144 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 145 WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE); 146 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 147 WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE); 148 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 149 WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE); 150 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 151 WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE); 152 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 153 WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY); 154 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( 155 WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE); 156 } 157 158 // List of tags supported for <WifiConfiguration> section in minor version 4 159 private static final Set<String> WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS = 160 new HashSet<String>(); 161 static { 162 WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS.addAll( 163 WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS); 164 WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS.add( 165 WifiConfigurationXmlUtil.XML_TAG_ENABLE_WIFI7); 166 WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS.add( 167 WifiConfigurationXmlUtil.XML_TAG_IS_REPEATER_ENABLED); 168 WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS.add( 169 WifiConfigurationXmlUtil.XML_TAG_SEND_DHCP_HOSTNAME); 170 } 171 172 // List of tags supported for <IpConfiguration> section in last minor version, i.e. version: 4 173 // Note: Update the getSupportedIpConfigurationTags when the minor version is increased. 174 private static final Set<String> IP_CONFIGURATION_LAST_MINOR_SUPPORTED_TAGS = Set.of( 175 IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT, 176 IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS, 177 IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH, 178 IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS, 179 IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES, 180 IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS, 181 IpConfigurationXmlUtil.XML_TAG_PROXY_HOST, 182 IpConfigurationXmlUtil.XML_TAG_PROXY_PORT, 183 IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST, 184 IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE); 185 186 @Override parseNetworkConfigurationsFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)187 public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in, 188 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 189 // clamp down the minorVersion to the highest one that this parser version supports 190 if (minorVersion > HIGHEST_SUPPORTED_MINOR_VERSION) { 191 minorVersion = HIGHEST_SUPPORTED_MINOR_VERSION; 192 } 193 // Find the configuration list section. 194 XmlUtil.gotoNextSectionWithName(in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK_LIST, 195 outerTagDepth); 196 // Find all the configurations within the configuration list section. 197 int networkListTagDepth = outerTagDepth + 1; 198 List<WifiConfiguration> configurations = new ArrayList<>(); 199 while (XmlUtil.gotoNextSectionWithNameOrEnd( 200 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) { 201 WifiConfiguration configuration = 202 parseNetworkConfigurationFromXml(in, minorVersion, networkListTagDepth); 203 if (configuration != null) { 204 Log.v(TAG, "Parsed Configuration: " + configuration.getKey()); 205 configurations.add(configuration); 206 } 207 } 208 return configurations; 209 } 210 211 @Override getHighestSupportedMinorVersion()212 public int getHighestSupportedMinorVersion() { 213 return HIGHEST_SUPPORTED_MINOR_VERSION; 214 } 215 216 /** 217 * Parses the configuration data elements from the provided XML stream to a Configuration. 218 * 219 * @param in XmlPullParser instance pointing to the XML stream. 220 * @param minorVersion minor version number parsed from incoming data. 221 * @param outerTagDepth depth of the outer tag in the XML document. 222 * @return WifiConfiguration object if parsing is successful, null otherwise. 223 */ parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion, int outerTagDepth)224 private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion, 225 int outerTagDepth) throws XmlPullParserException, IOException { 226 WifiConfiguration configuration = null; 227 int networkTagDepth = outerTagDepth + 1; 228 // Retrieve WifiConfiguration object first. 229 XmlUtil.gotoNextSectionWithName( 230 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, 231 networkTagDepth); 232 int configTagDepth = networkTagDepth + 1; 233 configuration = parseWifiConfigurationFromXml(in, configTagDepth, minorVersion); 234 if (configuration == null) { 235 return null; 236 } 237 // Now retrieve any IP configuration info. 238 XmlUtil.gotoNextSectionWithName( 239 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth); 240 IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, configTagDepth, 241 minorVersion); 242 configuration.setIpConfiguration(ipConfiguration); 243 return configuration; 244 } 245 246 /** 247 * Helper method to parse the WifiConfiguration object. 248 */ parseWifiConfigurationFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)249 private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, 250 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 251 Pair<String, WifiConfiguration> parsedConfig = 252 parseWifiConfigurationFromXmlInternal(in, outerTagDepth, minorVersion); 253 if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) { 254 return null; 255 } 256 String configKeyParsed = parsedConfig.first; 257 WifiConfiguration configuration = parsedConfig.second; 258 String configKeyCalculated = configuration.getKey(); 259 if (!configKeyParsed.equals(configKeyCalculated)) { 260 // configKey is not part of the SDK. So, we can't expect this to be the same 261 // across OEM's. Just log a warning & continue. 262 Log.w(TAG, "Configuration key does not match. Retrieved: " + configKeyParsed 263 + ", Calculated: " + configKeyCalculated); 264 } 265 return configuration; 266 } 267 268 /** 269 * Helper method to mask out any invalid data in parsed WifiConfiguration. 270 * 271 * This is a compatibility layer added to the parsing logic to try and weed out any known 272 * issues in the backup data format from other OEM's. 273 */ clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config)274 private static void clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config) { 275 /** 276 * Fix for b/73987207. Clear any invalid bits in the bitsets. 277 */ 278 // |allowedKeyManagement| 279 if (config.allowedKeyManagement.length() 280 > WifiConfiguration.KeyMgmt.strings.length) { 281 config.allowedKeyManagement.clear( 282 WifiConfiguration.KeyMgmt.strings.length, 283 config.allowedKeyManagement.length()); 284 } 285 // |allowedProtocols| 286 if (config.allowedProtocols.length() 287 > WifiConfiguration.Protocol.strings.length) { 288 config.allowedProtocols.clear( 289 WifiConfiguration.Protocol.strings.length, 290 config.allowedProtocols.length()); 291 } 292 // |allowedAuthAlgorithms| 293 if (config.allowedAuthAlgorithms.length() 294 > WifiConfiguration.AuthAlgorithm.strings.length) { 295 config.allowedAuthAlgorithms.clear( 296 WifiConfiguration.AuthAlgorithm.strings.length, 297 config.allowedAuthAlgorithms.length()); 298 } 299 // |allowedGroupCiphers| 300 if (config.allowedGroupCiphers.length() 301 > WifiConfiguration.GroupCipher.strings.length) { 302 config.allowedGroupCiphers.clear( 303 WifiConfiguration.GroupCipher.strings.length, 304 config.allowedGroupCiphers.length()); 305 } 306 // |allowedPairwiseCiphers| 307 if (config.allowedPairwiseCiphers.length() 308 > WifiConfiguration.PairwiseCipher.strings.length) { 309 config.allowedPairwiseCiphers.clear( 310 WifiConfiguration.PairwiseCipher.strings.length, 311 config.allowedPairwiseCiphers.length()); 312 } 313 // Add any other fixable issues discovered from other OEM's here. 314 } 315 316 /** 317 * Parses the configuration data elements from the provided XML stream to a 318 * WifiConfiguration object. 319 * Looping through the tags makes it easy to add elements in the future minor versions if 320 * needed. Unsupported elements will be ignored. 321 * 322 * @param in XmlPullParser instance pointing to the XML stream. 323 * @param outerTagDepth depth of the outer tag in the XML document. 324 * @param minorVersion minor version number parsed from incoming data. 325 * @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise. 326 */ parseWifiConfigurationFromXmlInternal( XmlPullParser in, int outerTagDepth, int minorVersion)327 private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXmlInternal( 328 XmlPullParser in, int outerTagDepth, int minorVersion) 329 throws XmlPullParserException, IOException { 330 WifiConfiguration configuration = new WifiConfiguration(); 331 String configKeyInData = null; 332 Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion); 333 boolean sendDhcpHostnameExists = false; 334 // Loop through and parse out all the elements from the stream within this section. 335 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 336 String tagName = null; 337 Object value = null; 338 if (in.getAttributeValue(null, "name") != null) { 339 String[] valueName = new String[1]; 340 value = XmlUtil.readCurrentValue(in, valueName); 341 tagName = valueName[0]; 342 if (tagName == null) { 343 throw new XmlPullParserException("Missing value name"); 344 } 345 } else { 346 tagName = in.getName(); 347 if (tagName == null) { 348 throw new XmlPullParserException("Unexpected null tag found"); 349 } 350 } 351 352 // ignore the tags that are not supported up until the current minor version 353 if (!supportedTags.contains(tagName)) { 354 Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <WifiConfiguration>" 355 + " section, ignoring."); 356 continue; 357 } 358 // note: the below switch case list should contain all tags supported up until the 359 // highest minor version supported by this parser 360 switch (tagName) { 361 case WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY: 362 configKeyInData = (String) value; 363 break; 364 case WifiConfigurationXmlUtil.XML_TAG_SSID: 365 configuration.SSID = (String) value; 366 break; 367 case WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY: 368 configuration.preSharedKey = (String) value; 369 break; 370 case WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS: 371 populateWepKeysFromXmlValue(value, configuration.wepKeys); 372 break; 373 case WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX: 374 configuration.wepTxKeyIndex = (int) value; 375 break; 376 case WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID: 377 configuration.hiddenSSID = (boolean) value; 378 break; 379 case WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF: 380 configuration.requirePmf = (boolean) value; 381 break; 382 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT: 383 byte[] allowedKeyMgmt = (byte[]) value; 384 configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 385 break; 386 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS: 387 byte[] allowedProtocols = (byte[]) value; 388 configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 389 break; 390 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS: 391 byte[] allowedAuthAlgorithms = (byte[]) value; 392 configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); 393 break; 394 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS: 395 byte[] allowedGroupCiphers = (byte[]) value; 396 configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); 397 break; 398 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS: 399 byte[] allowedPairwiseCiphers = (byte[]) value; 400 configuration.allowedPairwiseCiphers = 401 BitSet.valueOf(allowedPairwiseCiphers); 402 break; 403 case WifiConfigurationXmlUtil.XML_TAG_SHARED: 404 configuration.shared = (boolean) value; 405 break; 406 case WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE: 407 configuration.meteredOverride = (int) value; 408 break; 409 case WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN: 410 configuration.allowAutojoin = (boolean) value; 411 break; 412 case WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY: 413 configuration.setDeletionPriority((int) value); 414 break; 415 case WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE: 416 configuration.numRebootsSinceLastUse = (int) value; 417 break; 418 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST: 419 parseSecurityParamsListFromXml(in, outerTagDepth + 1, configuration); 420 break; 421 // V4 422 case WifiConfigurationXmlUtil.XML_TAG_IS_REPEATER_ENABLED: 423 configuration.setRepeaterEnabled((boolean) value); 424 break; 425 case WifiConfigurationXmlUtil.XML_TAG_ENABLE_WIFI7: 426 configuration.setWifi7Enabled((boolean) value); 427 break; 428 case WifiConfigurationXmlUtil.XML_TAG_SEND_DHCP_HOSTNAME: 429 configuration.setSendDhcpHostnameEnabled((boolean) value); 430 sendDhcpHostnameExists = true; 431 break; 432 default: 433 // should never happen, since other tags are filtered out earlier 434 throw new XmlPullParserException( 435 "Unknown value name found: " + tagName); 436 } 437 } 438 if (!sendDhcpHostnameExists) { 439 // Update legacy configs to send the DHCP hostname for secure networks only. 440 configuration.setSendDhcpHostnameEnabled( 441 !configuration.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN) 442 && !configuration.isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE)); 443 } 444 clearAnyKnownIssuesInParsedConfiguration(configuration); 445 return Pair.create(configKeyInData, configuration); 446 } 447 448 /** 449 * Returns a set of supported tags of <WifiConfiguration> element for all minor versions of 450 * this major version up to and including the specified minorVersion (only adding tags is 451 * supported in minor versions, removal or changing the meaning of tags requires bumping 452 * the major version and reseting the minor to 0). 453 * 454 * @param minorVersion minor version number parsed from incoming data. 455 */ getSupportedWifiConfigurationTags(int minorVersion)456 private static Set<String> getSupportedWifiConfigurationTags(int minorVersion) { 457 switch (minorVersion) { 458 case 0: 459 return WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS; 460 case 1: 461 return WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS; 462 case 2: 463 return WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS; 464 case 3: 465 return WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS; 466 case 4: 467 return WIFI_CONFIGURATION_MINOR_V4_SUPPORTED_TAGS; 468 default: 469 Log.e(TAG, "Invalid minorVersion: " + minorVersion); 470 return Collections.<String>emptySet(); 471 } 472 } 473 474 /** 475 * Populate wepKeys array elements only if they were non-empty in the backup data. 476 * 477 * @throws XmlPullParserException if parsing errors occur. 478 */ populateWepKeysFromXmlValue(Object value, String[] wepKeys)479 private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 480 throws XmlPullParserException, IOException { 481 String[] wepKeysInData = (String[]) value; 482 if (wepKeysInData == null) { 483 return; 484 } 485 if (wepKeysInData.length != wepKeys.length) { 486 throw new XmlPullParserException( 487 "Invalid Wep Keys length: " + wepKeysInData.length); 488 } 489 for (int i = 0; i < wepKeys.length; i++) { 490 if (wepKeysInData[i].isEmpty()) { 491 wepKeys[i] = null; 492 } else { 493 wepKeys[i] = wepKeysInData[i]; 494 } 495 } 496 } 497 parseSecurityParamsFromXml( XmlPullParser in, int outerTagDepth)498 private static SecurityParams parseSecurityParamsFromXml( 499 XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { 500 SecurityParams params = null; 501 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 502 String[] valueName = new String[1]; 503 Object value = XmlUtil.readCurrentValue(in, valueName); 504 String tagName = valueName[0]; 505 if (tagName == null) { 506 throw new XmlPullParserException("Missing value name"); 507 } 508 switch (tagName) { 509 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE: 510 params = SecurityParams.createSecurityParamsBySecurityType((int) value); 511 break; 512 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE: 513 if (null == params) throw new XmlPullParserException("Missing security type."); 514 params.enableSaeH2eOnlyMode((boolean) value); 515 break; 516 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE: 517 if (null == params) throw new XmlPullParserException("Missing security type."); 518 params.enableSaePkOnlyMode((boolean) value); 519 break; 520 case WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE: 521 if (null == params) throw new XmlPullParserException("Missing security type."); 522 params.setIsAddedByAutoUpgrade((boolean) value); 523 break; 524 } 525 } 526 return params; 527 } 528 529 /** 530 * Populate security params list elements only if they were non-empty in the backup data. 531 * 532 * @throws XmlPullParserException if parsing errors occur. 533 */ parseSecurityParamsListFromXml( XmlPullParser in, int outerTagDepth, WifiConfiguration configuration)534 private static void parseSecurityParamsListFromXml( 535 XmlPullParser in, int outerTagDepth, 536 WifiConfiguration configuration) 537 throws XmlPullParserException, IOException { 538 539 List<SecurityParams> paramsList = new ArrayList<>(); 540 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 541 switch (in.getName()) { 542 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS: 543 SecurityParams params = parseSecurityParamsFromXml(in, outerTagDepth + 1); 544 if (params != null) { 545 paramsList.add(params); 546 } 547 break; 548 } 549 } 550 if (!paramsList.isEmpty()) { 551 configuration.setSecurityParams(paramsList); 552 } 553 } 554 parseProxyExclusionListString( @ullable String exclusionListString)555 private static List<String> parseProxyExclusionListString( 556 @Nullable String exclusionListString) { 557 if (exclusionListString == null) { 558 return Collections.emptyList(); 559 } else { 560 return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); 561 } 562 } 563 564 /** 565 * Parses the IP configuration data elements from the provided XML stream to an 566 * IpConfiguration object. 567 * 568 * @param in XmlPullParser instance pointing to the XML stream. 569 * @param outerTagDepth depth of the outer tag in the XML document. 570 * @param minorVersion minor version number parsed from incoming data. 571 * @return IpConfiguration object if parsing is successful, null otherwise. 572 */ parseIpConfigurationFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)573 private static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, 574 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 575 // First parse *all* of the tags in <IpConfiguration> section 576 Set<String> supportedTags = getSupportedIpConfigurationTags(minorVersion); 577 578 String ipAssignmentString = null; 579 String linkAddressString = null; 580 Integer linkPrefixLength = null; 581 String gatewayAddressString = null; 582 String[] dnsServerAddressesString = null; 583 String proxySettingsString = null; 584 String proxyHost = null; 585 int proxyPort = -1; 586 String proxyExclusionList = null; 587 String proxyPacFile = null; 588 589 // Loop through and parse out all the elements from the stream within this section. 590 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 591 String[] valueName = new String[1]; 592 Object value = XmlUtil.readCurrentValue(in, valueName); 593 String tagName = valueName[0]; 594 if (tagName == null) { 595 throw new XmlPullParserException("Missing value name"); 596 } 597 598 // ignore the tags that are not supported up until the current minor version 599 if (!supportedTags.contains(tagName)) { 600 Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <IpConfiguration>" 601 + " section, ignoring."); 602 continue; 603 } 604 605 // note: the below switch case list should contain all tags supported up until the 606 // highest minor version supported by this parser 607 // should any tags be added in next minor versions, conditional processing of them 608 // also needs to be added in the below code (processing into IpConfiguration object) 609 switch (tagName) { 610 case IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT: 611 ipAssignmentString = (String) value; 612 break; 613 case IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS: 614 linkAddressString = (String) value; 615 break; 616 case IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH: 617 linkPrefixLength = (Integer) value; 618 break; 619 case IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS: 620 gatewayAddressString = (String) value; 621 break; 622 case IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES: 623 dnsServerAddressesString = (String[]) value; 624 break; 625 case IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS: 626 proxySettingsString = (String) value; 627 break; 628 case IpConfigurationXmlUtil.XML_TAG_PROXY_HOST: 629 proxyHost = (String) value; 630 break; 631 case IpConfigurationXmlUtil.XML_TAG_PROXY_PORT: 632 proxyPort = (int) value; 633 break; 634 case IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST: 635 proxyExclusionList = (String) value; 636 break; 637 case IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE: 638 proxyPacFile = (String) value; 639 break; 640 default: 641 // should never happen, since other tags are filtered out earlier 642 throw new XmlPullParserException( 643 "Unknown value name found: " + valueName[0]); 644 } 645 } 646 647 // Now process the values into IpConfiguration object 648 IpConfiguration ipConfiguration = new IpConfiguration(); 649 if (ipAssignmentString == null) { 650 throw new XmlPullParserException("IpAssignment was missing in IpConfiguration section"); 651 } 652 IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); 653 ipConfiguration.setIpAssignment(ipAssignment); 654 switch (ipAssignment) { 655 case STATIC: 656 StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder(); 657 if (linkAddressString != null && linkPrefixLength != null) { 658 LinkAddress linkAddress = new LinkAddress( 659 InetAddresses.parseNumericAddress(linkAddressString), linkPrefixLength); 660 if (linkAddress.getAddress() instanceof Inet4Address) { 661 builder.setIpAddress(linkAddress); 662 } else { 663 Log.w(TAG, "Non-IPv4 address: " + linkAddress); 664 } 665 } 666 if (gatewayAddressString != null) { 667 InetAddress gateway = InetAddresses.parseNumericAddress(gatewayAddressString); 668 RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST); 669 if (route.isDefaultRoute() 670 && route.getDestination().getAddress() instanceof Inet4Address) { 671 builder.setGateway(gateway); 672 } else { 673 Log.w(TAG, "Non-IPv4 default route: " + route); 674 } 675 } 676 if (dnsServerAddressesString != null) { 677 List<InetAddress> dnsServerAddresses = new ArrayList<>(); 678 for (String dnsServerAddressString : dnsServerAddressesString) { 679 InetAddress dnsServerAddress = 680 InetAddresses.parseNumericAddress(dnsServerAddressString); 681 dnsServerAddresses.add(dnsServerAddress); 682 } 683 builder.setDnsServers(dnsServerAddresses); 684 } 685 ipConfiguration.setStaticIpConfiguration(builder.build()); 686 break; 687 case DHCP: 688 case UNASSIGNED: 689 break; 690 default: 691 throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment); 692 } 693 694 // Process the proxy settings next 695 if (proxySettingsString == null) { 696 throw new XmlPullParserException("ProxySettings was missing in" 697 + " IpConfiguration section"); 698 } 699 ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); 700 ipConfiguration.setProxySettings(proxySettings); 701 switch (proxySettings) { 702 case STATIC: 703 if (proxyHost == null) { 704 throw new XmlPullParserException("ProxyHost was missing in" 705 + " IpConfiguration section"); 706 } 707 if (proxyPort == -1) { 708 throw new XmlPullParserException("ProxyPort was missing in" 709 + " IpConfiguration section"); 710 } 711 if (proxyExclusionList == null) { 712 throw new XmlPullParserException("ProxyExclusionList was missing in" 713 + " IpConfiguration section"); 714 } 715 ipConfiguration.setHttpProxy( 716 ProxyInfo.buildDirectProxy( 717 proxyHost, proxyPort, 718 parseProxyExclusionListString(proxyExclusionList))); 719 break; 720 case PAC: 721 if (proxyPacFile == null) { 722 throw new XmlPullParserException("ProxyPac was missing in" 723 + " IpConfiguration section"); 724 } 725 ipConfiguration.setHttpProxy( 726 ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile))); 727 break; 728 case NONE: 729 case UNASSIGNED: 730 break; 731 default: 732 throw new XmlPullParserException( 733 "Unknown proxy settings type: " + proxySettings); 734 } 735 736 return ipConfiguration; 737 } 738 739 /** 740 * Returns a set of supported tags of <IpConfiguration> element for all minor versions of 741 * this major version up to and including the specified minorVersion (only adding tags is 742 * supported in minor versions, removal or changing the meaning of tags requires bumping 743 * the major version and reseting the minor to 0). 744 * 745 * @param minorVersion minor version number parsed from incoming data. 746 */ getSupportedIpConfigurationTags(int minorVersion)747 private static Set<String> getSupportedIpConfigurationTags(int minorVersion) { 748 switch (minorVersion) { 749 case 0: 750 case 1: 751 case 2: 752 case 3: 753 case 4: 754 return IP_CONFIGURATION_LAST_MINOR_SUPPORTED_TAGS; 755 default: 756 Log.e(TAG, "Invalid minorVersion: " + minorVersion); 757 return Collections.<String>emptySet(); 758 } 759 } 760 } 761