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 = 3; 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 <IpConfiguration> section in minor version 0 to 3 159 private static final Set<String> IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS = Set.of( 160 IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT, 161 IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS, 162 IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH, 163 IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS, 164 IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES, 165 IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS, 166 IpConfigurationXmlUtil.XML_TAG_PROXY_HOST, 167 IpConfigurationXmlUtil.XML_TAG_PROXY_PORT, 168 IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST, 169 IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE); 170 171 @Override parseNetworkConfigurationsFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)172 public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in, 173 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 174 // clamp down the minorVersion to the highest one that this parser version supports 175 if (minorVersion > HIGHEST_SUPPORTED_MINOR_VERSION) { 176 minorVersion = HIGHEST_SUPPORTED_MINOR_VERSION; 177 } 178 // Find the configuration list section. 179 XmlUtil.gotoNextSectionWithName(in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK_LIST, 180 outerTagDepth); 181 // Find all the configurations within the configuration list section. 182 int networkListTagDepth = outerTagDepth + 1; 183 List<WifiConfiguration> configurations = new ArrayList<>(); 184 while (XmlUtil.gotoNextSectionWithNameOrEnd( 185 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) { 186 WifiConfiguration configuration = 187 parseNetworkConfigurationFromXml(in, minorVersion, networkListTagDepth); 188 if (configuration != null) { 189 Log.v(TAG, "Parsed Configuration: " + configuration.getKey()); 190 configurations.add(configuration); 191 } 192 } 193 return configurations; 194 } 195 196 @Override getHighestSupportedMinorVersion()197 public int getHighestSupportedMinorVersion() { 198 return HIGHEST_SUPPORTED_MINOR_VERSION; 199 } 200 201 /** 202 * Parses the configuration data elements from the provided XML stream to a Configuration. 203 * 204 * @param in XmlPullParser instance pointing to the XML stream. 205 * @param minorVersion minor version number parsed from incoming data. 206 * @param outerTagDepth depth of the outer tag in the XML document. 207 * @return WifiConfiguration object if parsing is successful, null otherwise. 208 */ parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion, int outerTagDepth)209 private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion, 210 int outerTagDepth) throws XmlPullParserException, IOException { 211 WifiConfiguration configuration = null; 212 int networkTagDepth = outerTagDepth + 1; 213 // Retrieve WifiConfiguration object first. 214 XmlUtil.gotoNextSectionWithName( 215 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, 216 networkTagDepth); 217 int configTagDepth = networkTagDepth + 1; 218 configuration = parseWifiConfigurationFromXml(in, configTagDepth, minorVersion); 219 if (configuration == null) { 220 return null; 221 } 222 // Now retrieve any IP configuration info. 223 XmlUtil.gotoNextSectionWithName( 224 in, WifiBackupRestore.XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth); 225 IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, configTagDepth, 226 minorVersion); 227 configuration.setIpConfiguration(ipConfiguration); 228 return configuration; 229 } 230 231 /** 232 * Helper method to parse the WifiConfiguration object. 233 */ parseWifiConfigurationFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)234 private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, 235 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 236 Pair<String, WifiConfiguration> parsedConfig = 237 parseWifiConfigurationFromXmlInternal(in, outerTagDepth, minorVersion); 238 if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) { 239 return null; 240 } 241 String configKeyParsed = parsedConfig.first; 242 WifiConfiguration configuration = parsedConfig.second; 243 String configKeyCalculated = configuration.getKey(); 244 if (!configKeyParsed.equals(configKeyCalculated)) { 245 // configKey is not part of the SDK. So, we can't expect this to be the same 246 // across OEM's. Just log a warning & continue. 247 Log.w(TAG, "Configuration key does not match. Retrieved: " + configKeyParsed 248 + ", Calculated: " + configKeyCalculated); 249 } 250 return configuration; 251 } 252 253 /** 254 * Helper method to mask out any invalid data in parsed WifiConfiguration. 255 * 256 * This is a compatibility layer added to the parsing logic to try and weed out any known 257 * issues in the backup data format from other OEM's. 258 */ clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config)259 private static void clearAnyKnownIssuesInParsedConfiguration(WifiConfiguration config) { 260 /** 261 * Fix for b/73987207. Clear any invalid bits in the bitsets. 262 */ 263 // |allowedKeyManagement| 264 if (config.allowedKeyManagement.length() 265 > WifiConfiguration.KeyMgmt.strings.length) { 266 config.allowedKeyManagement.clear( 267 WifiConfiguration.KeyMgmt.strings.length, 268 config.allowedKeyManagement.length()); 269 } 270 // |allowedProtocols| 271 if (config.allowedProtocols.length() 272 > WifiConfiguration.Protocol.strings.length) { 273 config.allowedProtocols.clear( 274 WifiConfiguration.Protocol.strings.length, 275 config.allowedProtocols.length()); 276 } 277 // |allowedAuthAlgorithms| 278 if (config.allowedAuthAlgorithms.length() 279 > WifiConfiguration.AuthAlgorithm.strings.length) { 280 config.allowedAuthAlgorithms.clear( 281 WifiConfiguration.AuthAlgorithm.strings.length, 282 config.allowedAuthAlgorithms.length()); 283 } 284 // |allowedGroupCiphers| 285 if (config.allowedGroupCiphers.length() 286 > WifiConfiguration.GroupCipher.strings.length) { 287 config.allowedGroupCiphers.clear( 288 WifiConfiguration.GroupCipher.strings.length, 289 config.allowedGroupCiphers.length()); 290 } 291 // |allowedPairwiseCiphers| 292 if (config.allowedPairwiseCiphers.length() 293 > WifiConfiguration.PairwiseCipher.strings.length) { 294 config.allowedPairwiseCiphers.clear( 295 WifiConfiguration.PairwiseCipher.strings.length, 296 config.allowedPairwiseCiphers.length()); 297 } 298 // Add any other fixable issues discovered from other OEM's here. 299 } 300 301 /** 302 * Parses the configuration data elements from the provided XML stream to a 303 * WifiConfiguration object. 304 * Looping through the tags makes it easy to add elements in the future minor versions if 305 * needed. Unsupported elements will be ignored. 306 * 307 * @param in XmlPullParser instance pointing to the XML stream. 308 * @param outerTagDepth depth of the outer tag in the XML document. 309 * @param minorVersion minor version number parsed from incoming data. 310 * @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise. 311 */ parseWifiConfigurationFromXmlInternal( XmlPullParser in, int outerTagDepth, int minorVersion)312 private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXmlInternal( 313 XmlPullParser in, int outerTagDepth, int minorVersion) 314 throws XmlPullParserException, IOException { 315 WifiConfiguration configuration = new WifiConfiguration(); 316 String configKeyInData = null; 317 Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion); 318 319 // Loop through and parse out all the elements from the stream within this section. 320 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 321 String tagName = null; 322 Object value = null; 323 if (in.getAttributeValue(null, "name") != null) { 324 String[] valueName = new String[1]; 325 value = XmlUtil.readCurrentValue(in, valueName); 326 tagName = valueName[0]; 327 if (tagName == null) { 328 throw new XmlPullParserException("Missing value name"); 329 } 330 } else { 331 tagName = in.getName(); 332 if (tagName == null) { 333 throw new XmlPullParserException("Unexpected null tag found"); 334 } 335 } 336 337 // ignore the tags that are not supported up until the current minor version 338 if (!supportedTags.contains(tagName)) { 339 Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <WifiConfiguration>" 340 + " section, ignoring."); 341 continue; 342 } 343 344 // note: the below switch case list should contain all tags supported up until the 345 // highest minor version supported by this parser 346 switch (tagName) { 347 case WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY: 348 configKeyInData = (String) value; 349 break; 350 case WifiConfigurationXmlUtil.XML_TAG_SSID: 351 configuration.SSID = (String) value; 352 break; 353 case WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY: 354 configuration.preSharedKey = (String) value; 355 break; 356 case WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS: 357 populateWepKeysFromXmlValue(value, configuration.wepKeys); 358 break; 359 case WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX: 360 configuration.wepTxKeyIndex = (int) value; 361 break; 362 case WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID: 363 configuration.hiddenSSID = (boolean) value; 364 break; 365 case WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF: 366 configuration.requirePmf = (boolean) value; 367 break; 368 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT: 369 byte[] allowedKeyMgmt = (byte[]) value; 370 configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 371 break; 372 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS: 373 byte[] allowedProtocols = (byte[]) value; 374 configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 375 break; 376 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS: 377 byte[] allowedAuthAlgorithms = (byte[]) value; 378 configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); 379 break; 380 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS: 381 byte[] allowedGroupCiphers = (byte[]) value; 382 configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); 383 break; 384 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS: 385 byte[] allowedPairwiseCiphers = (byte[]) value; 386 configuration.allowedPairwiseCiphers = 387 BitSet.valueOf(allowedPairwiseCiphers); 388 break; 389 case WifiConfigurationXmlUtil.XML_TAG_SHARED: 390 configuration.shared = (boolean) value; 391 break; 392 case WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE: 393 configuration.meteredOverride = (int) value; 394 break; 395 case WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN: 396 configuration.allowAutojoin = (boolean) value; 397 break; 398 case WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY: 399 configuration.setDeletionPriority((int) value); 400 break; 401 case WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE: 402 configuration.numRebootsSinceLastUse = (int) value; 403 break; 404 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST: 405 parseSecurityParamsListFromXml(in, outerTagDepth + 1, configuration); 406 break; 407 default: 408 // should never happen, since other tags are filtered out earlier 409 throw new XmlPullParserException( 410 "Unknown value name found: " + tagName); 411 } 412 } 413 clearAnyKnownIssuesInParsedConfiguration(configuration); 414 return Pair.create(configKeyInData, configuration); 415 } 416 417 /** 418 * Returns a set of supported tags of <WifiConfiguration> element for all minor versions of 419 * this major version up to and including the specified minorVersion (only adding tags is 420 * supported in minor versions, removal or changing the meaning of tags requires bumping 421 * the major version and reseting the minor to 0). 422 * 423 * @param minorVersion minor version number parsed from incoming data. 424 */ getSupportedWifiConfigurationTags(int minorVersion)425 private static Set<String> getSupportedWifiConfigurationTags(int minorVersion) { 426 switch (minorVersion) { 427 case 0: 428 return WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS; 429 case 1: 430 return WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS; 431 case 2: 432 return WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS; 433 case 3: 434 return WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS; 435 default: 436 Log.e(TAG, "Invalid minorVersion: " + minorVersion); 437 return Collections.<String>emptySet(); 438 } 439 } 440 441 /** 442 * Populate wepKeys array elements only if they were non-empty in the backup data. 443 * 444 * @throws XmlPullParserException if parsing errors occur. 445 */ populateWepKeysFromXmlValue(Object value, String[] wepKeys)446 private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 447 throws XmlPullParserException, IOException { 448 String[] wepKeysInData = (String[]) value; 449 if (wepKeysInData == null) { 450 return; 451 } 452 if (wepKeysInData.length != wepKeys.length) { 453 throw new XmlPullParserException( 454 "Invalid Wep Keys length: " + wepKeysInData.length); 455 } 456 for (int i = 0; i < wepKeys.length; i++) { 457 if (wepKeysInData[i].isEmpty()) { 458 wepKeys[i] = null; 459 } else { 460 wepKeys[i] = wepKeysInData[i]; 461 } 462 } 463 } 464 parseSecurityParamsFromXml( XmlPullParser in, int outerTagDepth)465 private static SecurityParams parseSecurityParamsFromXml( 466 XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { 467 SecurityParams params = null; 468 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 469 String[] valueName = new String[1]; 470 Object value = XmlUtil.readCurrentValue(in, valueName); 471 String tagName = valueName[0]; 472 if (tagName == null) { 473 throw new XmlPullParserException("Missing value name"); 474 } 475 switch (tagName) { 476 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE: 477 params = SecurityParams.createSecurityParamsBySecurityType((int) value); 478 break; 479 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE: 480 if (null == params) throw new XmlPullParserException("Missing security type."); 481 params.enableSaeH2eOnlyMode((boolean) value); 482 break; 483 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE: 484 if (null == params) throw new XmlPullParserException("Missing security type."); 485 params.enableSaePkOnlyMode((boolean) value); 486 break; 487 case WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE: 488 if (null == params) throw new XmlPullParserException("Missing security type."); 489 params.setIsAddedByAutoUpgrade((boolean) value); 490 break; 491 } 492 } 493 return params; 494 } 495 496 /** 497 * Populate security params list elements only if they were non-empty in the backup data. 498 * 499 * @throws XmlPullParserException if parsing errors occur. 500 */ parseSecurityParamsListFromXml( XmlPullParser in, int outerTagDepth, WifiConfiguration configuration)501 private static void parseSecurityParamsListFromXml( 502 XmlPullParser in, int outerTagDepth, 503 WifiConfiguration configuration) 504 throws XmlPullParserException, IOException { 505 506 List<SecurityParams> paramsList = new ArrayList<>(); 507 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 508 switch (in.getName()) { 509 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS: 510 SecurityParams params = parseSecurityParamsFromXml(in, outerTagDepth + 1); 511 if (params != null) { 512 paramsList.add(params); 513 } 514 break; 515 } 516 } 517 if (!paramsList.isEmpty()) { 518 configuration.setSecurityParams(paramsList); 519 } 520 } 521 parseProxyExclusionListString( @ullable String exclusionListString)522 private static List<String> parseProxyExclusionListString( 523 @Nullable String exclusionListString) { 524 if (exclusionListString == null) { 525 return Collections.emptyList(); 526 } else { 527 return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); 528 } 529 } 530 531 /** 532 * Parses the IP configuration data elements from the provided XML stream to an 533 * IpConfiguration object. 534 * 535 * @param in XmlPullParser instance pointing to the XML stream. 536 * @param outerTagDepth depth of the outer tag in the XML document. 537 * @param minorVersion minor version number parsed from incoming data. 538 * @return IpConfiguration object if parsing is successful, null otherwise. 539 */ parseIpConfigurationFromXml(XmlPullParser in, int outerTagDepth, int minorVersion)540 private static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, 541 int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { 542 // First parse *all* of the tags in <IpConfiguration> section 543 Set<String> supportedTags = getSupportedIpConfigurationTags(minorVersion); 544 545 String ipAssignmentString = null; 546 String linkAddressString = null; 547 Integer linkPrefixLength = null; 548 String gatewayAddressString = null; 549 String[] dnsServerAddressesString = null; 550 String proxySettingsString = null; 551 String proxyHost = null; 552 int proxyPort = -1; 553 String proxyExclusionList = null; 554 String proxyPacFile = null; 555 556 // Loop through and parse out all the elements from the stream within this section. 557 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 558 String[] valueName = new String[1]; 559 Object value = XmlUtil.readCurrentValue(in, valueName); 560 String tagName = valueName[0]; 561 if (tagName == null) { 562 throw new XmlPullParserException("Missing value name"); 563 } 564 565 // ignore the tags that are not supported up until the current minor version 566 if (!supportedTags.contains(tagName)) { 567 Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <IpConfiguration>" 568 + " section, ignoring."); 569 continue; 570 } 571 572 // note: the below switch case list should contain all tags supported up until the 573 // highest minor version supported by this parser 574 // should any tags be added in next minor versions, conditional processing of them 575 // also needs to be added in the below code (processing into IpConfiguration object) 576 switch (tagName) { 577 case IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT: 578 ipAssignmentString = (String) value; 579 break; 580 case IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS: 581 linkAddressString = (String) value; 582 break; 583 case IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH: 584 linkPrefixLength = (Integer) value; 585 break; 586 case IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS: 587 gatewayAddressString = (String) value; 588 break; 589 case IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES: 590 dnsServerAddressesString = (String[]) value; 591 break; 592 case IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS: 593 proxySettingsString = (String) value; 594 break; 595 case IpConfigurationXmlUtil.XML_TAG_PROXY_HOST: 596 proxyHost = (String) value; 597 break; 598 case IpConfigurationXmlUtil.XML_TAG_PROXY_PORT: 599 proxyPort = (int) value; 600 break; 601 case IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST: 602 proxyExclusionList = (String) value; 603 break; 604 case IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE: 605 proxyPacFile = (String) value; 606 break; 607 default: 608 // should never happen, since other tags are filtered out earlier 609 throw new XmlPullParserException( 610 "Unknown value name found: " + valueName[0]); 611 } 612 } 613 614 // Now process the values into IpConfiguration object 615 IpConfiguration ipConfiguration = new IpConfiguration(); 616 if (ipAssignmentString == null) { 617 throw new XmlPullParserException("IpAssignment was missing in IpConfiguration section"); 618 } 619 IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); 620 ipConfiguration.setIpAssignment(ipAssignment); 621 switch (ipAssignment) { 622 case STATIC: 623 StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder(); 624 if (linkAddressString != null && linkPrefixLength != null) { 625 LinkAddress linkAddress = new LinkAddress( 626 InetAddresses.parseNumericAddress(linkAddressString), linkPrefixLength); 627 if (linkAddress.getAddress() instanceof Inet4Address) { 628 builder.setIpAddress(linkAddress); 629 } else { 630 Log.w(TAG, "Non-IPv4 address: " + linkAddress); 631 } 632 } 633 if (gatewayAddressString != null) { 634 InetAddress gateway = InetAddresses.parseNumericAddress(gatewayAddressString); 635 RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST); 636 if (route.isDefaultRoute() 637 && route.getDestination().getAddress() instanceof Inet4Address) { 638 builder.setGateway(gateway); 639 } else { 640 Log.w(TAG, "Non-IPv4 default route: " + route); 641 } 642 } 643 if (dnsServerAddressesString != null) { 644 List<InetAddress> dnsServerAddresses = new ArrayList<>(); 645 for (String dnsServerAddressString : dnsServerAddressesString) { 646 InetAddress dnsServerAddress = 647 InetAddresses.parseNumericAddress(dnsServerAddressString); 648 dnsServerAddresses.add(dnsServerAddress); 649 } 650 builder.setDnsServers(dnsServerAddresses); 651 } 652 ipConfiguration.setStaticIpConfiguration(builder.build()); 653 break; 654 case DHCP: 655 case UNASSIGNED: 656 break; 657 default: 658 throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment); 659 } 660 661 // Process the proxy settings next 662 if (proxySettingsString == null) { 663 throw new XmlPullParserException("ProxySettings was missing in" 664 + " IpConfiguration section"); 665 } 666 ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); 667 ipConfiguration.setProxySettings(proxySettings); 668 switch (proxySettings) { 669 case STATIC: 670 if (proxyHost == null) { 671 throw new XmlPullParserException("ProxyHost was missing in" 672 + " IpConfiguration section"); 673 } 674 if (proxyPort == -1) { 675 throw new XmlPullParserException("ProxyPort was missing in" 676 + " IpConfiguration section"); 677 } 678 if (proxyExclusionList == null) { 679 throw new XmlPullParserException("ProxyExclusionList was missing in" 680 + " IpConfiguration section"); 681 } 682 ipConfiguration.setHttpProxy( 683 ProxyInfo.buildDirectProxy( 684 proxyHost, proxyPort, 685 parseProxyExclusionListString(proxyExclusionList))); 686 break; 687 case PAC: 688 if (proxyPacFile == null) { 689 throw new XmlPullParserException("ProxyPac was missing in" 690 + " IpConfiguration section"); 691 } 692 ipConfiguration.setHttpProxy( 693 ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile))); 694 break; 695 case NONE: 696 case UNASSIGNED: 697 break; 698 default: 699 throw new XmlPullParserException( 700 "Unknown proxy settings type: " + proxySettings); 701 } 702 703 return ipConfiguration; 704 } 705 706 /** 707 * Returns a set of supported tags of <IpConfiguration> element for all minor versions of 708 * this major version up to and including the specified minorVersion (only adding tags is 709 * supported in minor versions, removal or changing the meaning of tags requires bumping 710 * the major version and reseting the minor to 0). 711 * 712 * @param minorVersion minor version number parsed from incoming data. 713 */ getSupportedIpConfigurationTags(int minorVersion)714 private static Set<String> getSupportedIpConfigurationTags(int minorVersion) { 715 switch (minorVersion) { 716 case 0: 717 case 1: 718 case 2: 719 case 3: 720 return IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS; 721 default: 722 Log.e(TAG, "Invalid minorVersion: " + minorVersion); 723 return Collections.<String>emptySet(); 724 } 725 } 726 } 727