1 /* 2 * Copyright (C) 2016 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.util; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.compat.CompatChanges; 22 import android.net.InetAddresses; 23 import android.net.IpConfiguration; 24 import android.net.IpConfiguration.IpAssignment; 25 import android.net.IpConfiguration.ProxySettings; 26 import android.net.LinkAddress; 27 import android.net.MacAddress; 28 import android.net.ProxyInfo; 29 import android.net.RouteInfo; 30 import android.net.StaticIpConfiguration; 31 import android.net.Uri; 32 import android.net.wifi.ScanResult; 33 import android.net.wifi.SecurityParams; 34 import android.net.wifi.SoftApConfiguration; 35 import android.net.wifi.WifiConfiguration; 36 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; 37 import android.net.wifi.WifiEnterpriseConfig; 38 import android.net.wifi.WifiManager; 39 import android.net.wifi.WifiMigration; 40 import android.net.wifi.WifiSsid; 41 import android.os.ParcelUuid; 42 import android.text.TextUtils; 43 import android.util.Log; 44 import android.util.Pair; 45 import android.util.SparseIntArray; 46 47 import com.android.modules.utils.build.SdkLevel; 48 49 import org.xmlpull.v1.XmlPullParser; 50 import org.xmlpull.v1.XmlPullParserException; 51 import org.xmlpull.v1.XmlSerializer; 52 53 import java.io.IOException; 54 import java.net.Inet4Address; 55 import java.net.InetAddress; 56 import java.nio.charset.StandardCharsets; 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.BitSet; 60 import java.util.Collections; 61 import java.util.HashMap; 62 import java.util.List; 63 import java.util.Locale; 64 65 /** 66 * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. 67 * The utility provides methods to write/parse section headers and write/parse values. 68 * This utility is designed for formatting the XML into the following format: 69 * <Document Header> 70 * <Section 1 Header> 71 * <Value 1> 72 * <Value 2> 73 * ... 74 * <Sub Section 1 Header> 75 * <Value 1> 76 * <Value 2> 77 * ... 78 * </Sub Section 1 Header> 79 * </Section 1 Header> 80 * </Document Header> 81 * 82 * Note: These utility methods are meant to be used for: 83 * 1. Backup/restore wifi network data to/from cloud. 84 * 2. Persisting wifi network data to/from disk. 85 */ 86 public class XmlUtil { 87 private static final String TAG = "WifiXmlUtil"; 88 89 /** 90 * Ensure that the XML stream is at a start tag or the end of document. 91 * 92 * @throws XmlPullParserException if parsing errors occur. 93 */ gotoStartTag(XmlPullParser in)94 private static void gotoStartTag(XmlPullParser in) 95 throws XmlPullParserException, IOException { 96 int type = in.getEventType(); 97 while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { 98 type = in.next(); 99 } 100 } 101 102 /** 103 * Ensure that the XML stream is at an end tag or the end of document. 104 * 105 * @throws XmlPullParserException if parsing errors occur. 106 */ gotoEndTag(XmlPullParser in)107 private static void gotoEndTag(XmlPullParser in) 108 throws XmlPullParserException, IOException { 109 int type = in.getEventType(); 110 while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { 111 type = in.next(); 112 } 113 } 114 115 /** 116 * Start processing the XML stream at the document header. 117 * 118 * @param in XmlPullParser instance pointing to the XML stream. 119 * @param headerName expected name for the start tag. 120 * @throws XmlPullParserException if parsing errors occur. 121 */ gotoDocumentStart(XmlPullParser in, String headerName)122 public static void gotoDocumentStart(XmlPullParser in, String headerName) 123 throws XmlPullParserException, IOException { 124 XmlUtilHelper.beginDocument(in, headerName); 125 } 126 127 /** 128 * Move the XML stream to the next section header or indicate if there are no more sections. 129 * The provided outerDepth is used to find sub sections within that depth. 130 * 131 * Use this to move across sections if the ordering of sections are variable. The returned name 132 * can be used to decide what section is next. 133 * 134 * @param in XmlPullParser instance pointing to the XML stream. 135 * @param headerName An array of one string, used to return the name of the next section. 136 * @param outerDepth Find section within this depth. 137 * @return {@code true} if a next section is found, {@code false} if there are no more sections. 138 * @throws XmlPullParserException if parsing errors occur. 139 */ gotoNextSectionOrEnd( XmlPullParser in, String[] headerName, int outerDepth)140 public static boolean gotoNextSectionOrEnd( 141 XmlPullParser in, String[] headerName, int outerDepth) 142 throws XmlPullParserException, IOException { 143 if (XmlUtilHelper.nextElementWithin(in, outerDepth)) { 144 headerName[0] = in.getName(); 145 return true; 146 } 147 return false; 148 } 149 150 /** 151 * Move the XML stream to the next section header or indicate if there are no more sections. 152 * If a section, exists ensure that the name matches the provided name. 153 * The provided outerDepth is used to find sub sections within that depth. 154 * 155 * Use this to move across repeated sections until the end. 156 * 157 * @param in XmlPullParser instance pointing to the XML stream. 158 * @param expectedName expected name for the section header. 159 * @param outerDepth Find section within this depth. 160 * @return {@code true} if a next section is found, {@code false} if there are no more sections. 161 * @throws XmlPullParserException if the section header name does not match |expectedName|, 162 * or if parsing errors occur. 163 */ gotoNextSectionWithNameOrEnd( XmlPullParser in, String expectedName, int outerDepth)164 public static boolean gotoNextSectionWithNameOrEnd( 165 XmlPullParser in, String expectedName, int outerDepth) 166 throws XmlPullParserException, IOException { 167 String[] headerName = new String[1]; 168 if (gotoNextSectionOrEnd(in, headerName, outerDepth)) { 169 if (headerName[0].equals(expectedName)) { 170 return true; 171 } 172 throw new XmlPullParserException( 173 "Next section name does not match expected name: " + expectedName); 174 } 175 return false; 176 } 177 178 /** 179 * Move the XML stream to the next section header and ensure that the name matches the provided 180 * name. 181 * The provided outerDepth is used to find sub sections within that depth. 182 * 183 * Use this to move across sections if the ordering of sections are fixed. 184 * 185 * @param in XmlPullParser instance pointing to the XML stream. 186 * @param expectedName expected name for the section header. 187 * @param outerDepth Find section within this depth. 188 * @throws XmlPullParserException if the section header name does not match |expectedName|, 189 * there are no more sections or if parsing errors occur. 190 */ gotoNextSectionWithName( XmlPullParser in, String expectedName, int outerDepth)191 public static void gotoNextSectionWithName( 192 XmlPullParser in, String expectedName, int outerDepth) 193 throws XmlPullParserException, IOException { 194 if (!gotoNextSectionWithNameOrEnd(in, expectedName, outerDepth)) { 195 throw new XmlPullParserException("Section not found. Expected: " + expectedName); 196 } 197 } 198 199 /** 200 * Checks if the stream is at the end of a section of values. This moves the stream to next tag 201 * and checks if it finds an end tag at the specified depth. 202 * 203 * @param in XmlPullParser instance pointing to the XML stream. 204 * @param sectionDepth depth of the start tag of this section. Used to match the end tag. 205 * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise 206 * @throws XmlPullParserException if parsing errors occur. 207 */ isNextSectionEnd(XmlPullParser in, int sectionDepth)208 public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) 209 throws XmlPullParserException, IOException { 210 return !XmlUtilHelper.nextElementWithin(in, sectionDepth); 211 } 212 213 /** 214 * Read the current value in the XML stream using core XmlUtils and stores the retrieved 215 * value name in the string provided. This method reads the value contained in current start 216 * tag. 217 * Note: Because there could be genuine null values being read from the XML, this method raises 218 * an exception to indicate errors. 219 * 220 * @param in XmlPullParser instance pointing to the XML stream. 221 * @param valueName An array of one string, used to return the name attribute 222 * of the value's tag. 223 * @return value retrieved from the XML stream. 224 * @throws XmlPullParserException if parsing errors occur. 225 */ readCurrentValue(XmlPullParser in, String[] valueName)226 public static Object readCurrentValue(XmlPullParser in, String[] valueName) 227 throws XmlPullParserException, IOException { 228 Object value = XmlUtilHelper.readValueXml(in, valueName); 229 // XmlUtils.readValue does not always move the stream to the end of the tag. So, move 230 // it to the end tag before returning from here. 231 gotoEndTag(in); 232 return value; 233 } 234 235 /** 236 * Read the next value in the XML stream using core XmlUtils and ensure that it matches the 237 * provided name. This method moves the stream to the next start tag and reads the value 238 * contained in it. 239 * Note: Because there could be genuine null values being read from the XML, this method raises 240 * an exception to indicate errors. 241 * 242 * @param in XmlPullParser instance pointing to the XML stream. 243 * @return value retrieved from the XML stream. 244 * @throws XmlPullParserException if the value read does not match |expectedName|, 245 * or if parsing errors occur. 246 */ readNextValueWithName(XmlPullParser in, String expectedName)247 public static Object readNextValueWithName(XmlPullParser in, String expectedName) 248 throws XmlPullParserException, IOException { 249 String[] valueName = new String[1]; 250 XmlUtilHelper.nextElement(in); 251 Object value = readCurrentValue(in, valueName); 252 if (valueName[0].equals(expectedName)) { 253 return value; 254 } 255 throw new XmlPullParserException( 256 "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); 257 } 258 259 /** 260 * Write the XML document start with the provided document header name. 261 * 262 * @param out XmlSerializer instance pointing to the XML stream. 263 * @param headerName name for the start tag. 264 */ writeDocumentStart(XmlSerializer out, String headerName)265 public static void writeDocumentStart(XmlSerializer out, String headerName) 266 throws IOException { 267 out.startDocument(null, true); 268 out.startTag(null, headerName); 269 } 270 271 /** 272 * Write the XML document end with the provided document header name. 273 * 274 * @param out XmlSerializer instance pointing to the XML stream. 275 * @param headerName name for the end tag. 276 */ writeDocumentEnd(XmlSerializer out, String headerName)277 public static void writeDocumentEnd(XmlSerializer out, String headerName) 278 throws IOException { 279 out.endTag(null, headerName); 280 out.endDocument(); 281 } 282 283 /** 284 * Write a section start header tag with the provided section name. 285 * 286 * @param out XmlSerializer instance pointing to the XML stream. 287 * @param headerName name for the start tag. 288 */ writeNextSectionStart(XmlSerializer out, String headerName)289 public static void writeNextSectionStart(XmlSerializer out, String headerName) 290 throws IOException { 291 out.startTag(null, headerName); 292 } 293 294 /** 295 * Write a section end header tag with the provided section name. 296 * 297 * @param out XmlSerializer instance pointing to the XML stream. 298 * @param headerName name for the end tag. 299 */ writeNextSectionEnd(XmlSerializer out, String headerName)300 public static void writeNextSectionEnd(XmlSerializer out, String headerName) 301 throws IOException { 302 out.endTag(null, headerName); 303 } 304 305 /** 306 * Write the value with the provided name in the XML stream using core XmlUtils. 307 * 308 * @param out XmlSerializer instance pointing to the XML stream. 309 * @param name name of the value. 310 * @param value value to be written. 311 */ writeNextValue(XmlSerializer out, String name, Object value)312 public static void writeNextValue(XmlSerializer out, String name, Object value) 313 throws XmlPullParserException, IOException { 314 XmlUtilHelper.writeValueXml(value, name, out); 315 } 316 317 /** 318 * Utility class to serialize and deserialize {@link WifiConfiguration} object to XML & 319 * vice versa. 320 * This is used by both {@link com.android.server.wifi.WifiConfigStore} & 321 * {@link com.android.server.wifi.WifiBackupRestore} modules. 322 * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. 323 * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. 324 * The parse method is written so that any element added/deleted in future revisions can 325 * be easily handled. 326 */ 327 public static class WifiConfigurationXmlUtil { 328 /** 329 * List of XML tags corresponding to WifiConfiguration object elements. 330 */ 331 public static final String XML_TAG_SSID = "SSID"; 332 public static final String XML_TAG_BSSID = "BSSID"; 333 public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; 334 public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; 335 public static final String XML_TAG_WEP_KEYS = "WEPKeys"; 336 public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; 337 public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; 338 public static final String XML_TAG_REQUIRE_PMF = "RequirePMF"; 339 public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; 340 public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; 341 public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; 342 public static final String XML_TAG_ALLOWED_GROUP_CIPHERS = "AllowedGroupCiphers"; 343 public static final String XML_TAG_ALLOWED_PAIRWISE_CIPHERS = "AllowedPairwiseCiphers"; 344 public static final String XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS = "AllowedGroupMgmtCiphers"; 345 public static final String XML_TAG_ALLOWED_SUITE_B_CIPHERS = "AllowedSuiteBCiphers"; 346 public static final String XML_TAG_SHARED = "Shared"; 347 public static final String XML_TAG_STATUS = "Status"; 348 public static final String XML_TAG_FQDN = "FQDN"; 349 public static final String XML_TAG_PROVIDER_FRIENDLY_NAME = "ProviderFriendlyName"; 350 public static final String XML_TAG_LINKED_NETWORKS_LIST = "LinkedNetworksList"; 351 public static final String XML_TAG_DEFAULT_GW_MAC_ADDRESS = "DefaultGwMacAddress"; 352 public static final String XML_TAG_VALIDATED_INTERNET_ACCESS = "ValidatedInternetAccess"; 353 public static final String XML_TAG_NO_INTERNET_ACCESS_EXPECTED = "NoInternetAccessExpected"; 354 public static final String XML_TAG_METERED_HINT = "MeteredHint"; 355 public static final String XML_TAG_METERED_OVERRIDE = "MeteredOverride"; 356 public static final String XML_TAG_USE_EXTERNAL_SCORES = "UseExternalScores"; 357 public static final String XML_TAG_CREATOR_UID = "CreatorUid"; 358 public static final String XML_TAG_CREATOR_NAME = "CreatorName"; 359 public static final String XML_TAG_LAST_UPDATE_UID = "LastUpdateUid"; 360 public static final String XML_TAG_LAST_UPDATE_NAME = "LastUpdateName"; 361 public static final String XML_TAG_LAST_CONNECT_UID = "LastConnectUid"; 362 public static final String XML_TAG_IS_LEGACY_PASSPOINT_CONFIG = "IsLegacyPasspointConfig"; 363 public static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; 364 public static final String XML_TAG_RANDOMIZED_MAC_ADDRESS = "RandomizedMacAddress"; 365 public static final String XML_TAG_MAC_RANDOMIZATION_SETTING = "MacRandomizationSetting"; 366 public static final String XML_TAG_CARRIER_ID = "CarrierId"; 367 public static final String XML_TAG_SUBSCRIPTION_ID = "SubscriptionId"; 368 public static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled"; 369 public static final String XML_TAG_DELETION_PRIORITY = "DeletionPriority"; 370 public static final String XML_TAG_NUM_REBOOTS_SINCE_LAST_USE = "NumRebootsSinceLastUse"; 371 372 public static final String XML_TAG_IS_TRUSTED = "Trusted"; 373 public static final String XML_TAG_IS_OEM_PAID = "OemPaid"; 374 public static final String XML_TAG_IS_OEM_PRIVATE = "OemPrivate"; 375 public static final String XML_TAG_IS_CARRIER_MERGED = "CarrierMerged"; 376 public static final String XML_TAG_SECURITY_PARAMS_LIST = "SecurityParamsList"; 377 public static final String XML_TAG_SECURITY_PARAMS = "SecurityParams"; 378 public static final String XML_TAG_SECURITY_TYPE = "SecurityType"; 379 public static final String XML_TAG_IS_ENABLED = "IsEnabled"; 380 public static final String XML_TAG_SAE_IS_H2E_ONLY_MODE = "SaeIsH2eOnlyMode"; 381 public static final String XML_TAG_SAE_IS_PK_ONLY_MODE = "SaeIsPkOnlyMode"; 382 public static final String XML_TAG_IS_ADDED_BY_AUTO_UPGRADE = "IsAddedByAutoUpgrade"; 383 private static final String XML_TAG_IS_MOST_RECENTLY_CONNECTED = "IsMostRecentlyConnected"; 384 private static final String XML_TAG_IS_RESTRICTED = "IsRestricted"; 385 private static final String XML_TAG_SUBSCRIPTION_GROUP = "SubscriptionGroup"; 386 public static final String XML_TAG_BSSID_ALLOW_LIST = "bssidAllowList"; 387 private static final String XML_TAG_IS_REPEATER_ENABLED = "RepeaterEnabled"; 388 public static final String XML_TAG_DPP_PRIVATE_EC_KEY = "DppPrivateEcKey"; 389 public static final String XML_TAG_DPP_CONNECTOR = "DppConnector"; 390 public static final String XML_TAG_DPP_CSIGN_KEY = "DppCSignKey"; 391 public static final String XML_TAG_DPP_NET_ACCESS_KEY = "DppNetAccessKey"; 392 393 /** 394 * Write Wep Keys to the XML stream. 395 * WepKeys array is initialized in WifiConfiguration constructor and all the elements 396 * are set to null. User may choose to set any one of the key elements in WifiConfiguration. 397 * XmlUtils serialization doesn't handle this array of nulls well . 398 * So, write empty strings if the keys are not initialized and null if all 399 * the elements are empty. 400 */ writeWepKeysToXml(XmlSerializer out, String[] wepKeys, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)401 private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys, 402 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 403 throws XmlPullParserException, IOException { 404 final int len = wepKeys == null ? 0 : wepKeys.length; 405 String[] wepKeysToWrite = new String[len]; 406 boolean hasWepKey = false; 407 for (int i = 0; i < len; i++) { 408 if (wepKeys[i] == null) { 409 wepKeysToWrite[i] = new String(); 410 } else { 411 wepKeysToWrite[i] = wepKeys[i]; 412 hasWepKey = true; 413 } 414 } 415 if (!hasWepKey) { 416 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); 417 return; 418 } 419 if (encryptionUtil == null) { 420 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); 421 return; 422 } 423 EncryptedData[] encryptedDataArray = new EncryptedData[len]; 424 for (int i = 0; i < len; i++) { 425 if (wepKeys[i] == null) { 426 encryptedDataArray[i] = new EncryptedData(null, null); 427 } else { 428 encryptedDataArray[i] = encryptionUtil.encrypt(wepKeys[i].getBytes()); 429 if (encryptedDataArray[i] == null) { 430 // We silently fail encryption failures! 431 Log.wtf(TAG, "Encryption of WEP keys failed"); 432 // If any key encryption fails, we just fall back with unencrypted keys. 433 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); 434 return; 435 } 436 } 437 } 438 XmlUtil.writeNextSectionStart(out, XML_TAG_WEP_KEYS); 439 for (int i = 0; i < len; i++) { 440 XmlUtil.EncryptedDataXmlUtil.writeToXml(out, encryptedDataArray[i]); 441 } 442 XmlUtil.writeNextSectionEnd(out, XML_TAG_WEP_KEYS); 443 } 444 445 /** 446 * Write preshared key to the XML stream. 447 * 448 * If encryptionUtil is null or if encryption fails for some reason, the pre-shared 449 * key is stored in plaintext, else the encrypted psk is stored. 450 */ writePreSharedKeyToXml( XmlSerializer out, WifiConfiguration wifiConfig, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)451 private static void writePreSharedKeyToXml( 452 XmlSerializer out, WifiConfiguration wifiConfig, 453 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 454 throws XmlPullParserException, IOException { 455 EncryptedData encryptedData = null; 456 if (encryptionUtil != null && wifiConfig.preSharedKey != null) { 457 if (wifiConfig.hasEncryptedPreSharedKey() && !wifiConfig.hasPreSharedKeyChanged()) { 458 encryptedData = new EncryptedData(wifiConfig.getEncryptedPreSharedKey(), 459 wifiConfig.getEncryptedPreSharedKeyIv()); 460 } else { 461 encryptedData = encryptionUtil.encrypt(wifiConfig.preSharedKey.getBytes()); 462 if (encryptedData == null) { 463 // We silently fail encryption failures! 464 Log.wtf(TAG, "Encryption of preSharedKey failed"); 465 } 466 } 467 } 468 if (encryptedData != null) { 469 writeNextSectionStart(out, XML_TAG_PRE_SHARED_KEY); 470 EncryptedDataXmlUtil.writeToXml(out, encryptedData); 471 wifiConfig.setEncryptedPreSharedKey(encryptedData.getEncryptedData(), 472 encryptedData.getIv()); 473 wifiConfig.setHasPreSharedKeyChanged(false); 474 writeNextSectionEnd(out, XML_TAG_PRE_SHARED_KEY); 475 } else { 476 writeNextValue(out, XML_TAG_PRE_SHARED_KEY, wifiConfig.preSharedKey); 477 } 478 } 479 writeSecurityParamsListToXml( XmlSerializer out, WifiConfiguration configuration)480 private static void writeSecurityParamsListToXml( 481 XmlSerializer out, WifiConfiguration configuration) 482 throws XmlPullParserException, IOException { 483 XmlUtil.writeNextSectionStart(out, XML_TAG_SECURITY_PARAMS_LIST); 484 for (SecurityParams params: configuration.getSecurityParamsList()) { 485 XmlUtil.writeNextSectionStart(out, XML_TAG_SECURITY_PARAMS); 486 XmlUtil.writeNextValue( 487 out, XML_TAG_SECURITY_TYPE, 488 params.getSecurityType()); 489 XmlUtil.writeNextValue( 490 out, XML_TAG_IS_ENABLED, 491 params.isEnabled()); 492 XmlUtil.writeNextValue( 493 out, XML_TAG_SAE_IS_H2E_ONLY_MODE, 494 params.isSaeH2eOnlyMode()); 495 XmlUtil.writeNextValue( 496 out, XML_TAG_SAE_IS_PK_ONLY_MODE, 497 params.isSaePkOnlyMode()); 498 XmlUtil.writeNextValue( 499 out, XML_TAG_IS_ADDED_BY_AUTO_UPGRADE, 500 params.isAddedByAutoUpgrade()); 501 XmlUtil.writeNextValue( 502 out, XML_TAG_ALLOWED_SUITE_B_CIPHERS, 503 params.getAllowedSuiteBCiphers().toByteArray()); 504 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECURITY_PARAMS); 505 } 506 507 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECURITY_PARAMS_LIST); 508 } 509 writeEncryptedBytesToXml( XmlSerializer out, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, String tag, byte[] data)510 private static void writeEncryptedBytesToXml( 511 XmlSerializer out, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, 512 String tag, byte[] data) 513 throws XmlPullParserException, IOException { 514 EncryptedData encryptedData = null; 515 if (encryptionUtil != null) { 516 encryptedData = encryptionUtil.encrypt(data); 517 if (encryptedData == null) { 518 // We silently fail encryption failures! 519 Log.wtf(TAG, "Encryption of " + tag + " failed"); 520 } 521 } 522 if (encryptedData != null) { 523 XmlUtil.writeNextSectionStart(out, tag); 524 EncryptedDataXmlUtil.writeToXml(out, encryptedData); 525 XmlUtil.writeNextSectionEnd(out, tag); 526 } else { 527 XmlUtil.writeNextValue(out, tag, data); 528 } 529 } 530 531 /** 532 * Write dpp configuration and connection keys to the XML stream. 533 * 534 * If encryptionUtil is null or if encryption fails for some reason, the dpp 535 * keys are stored in plaintext, else the encrypted keys are stored. 536 */ writeDppConfigurationToXml( XmlSerializer out, WifiConfiguration configuration, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)537 private static void writeDppConfigurationToXml( 538 XmlSerializer out, WifiConfiguration configuration, 539 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 540 throws XmlPullParserException, IOException { 541 writeEncryptedBytesToXml(out, encryptionUtil, XML_TAG_DPP_PRIVATE_EC_KEY, 542 configuration.getDppPrivateEcKey()); 543 writeEncryptedBytesToXml(out, encryptionUtil, XML_TAG_DPP_CONNECTOR, 544 configuration.getDppConnector()); 545 writeEncryptedBytesToXml(out, encryptionUtil, XML_TAG_DPP_CSIGN_KEY, 546 configuration.getDppCSignKey()); 547 writeEncryptedBytesToXml(out, encryptionUtil, XML_TAG_DPP_NET_ACCESS_KEY, 548 configuration.getDppNetAccessKey()); 549 } 550 551 /** 552 * Write the Configuration data elements that are common for backup & config store to the 553 * XML stream. 554 * 555 * @param out XmlSerializer instance pointing to the XML stream. 556 * @param configuration WifiConfiguration object to be serialized. 557 * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. Backup/restore stores 558 * keys unencrypted. 559 */ writeCommonElementsToXml( XmlSerializer out, WifiConfiguration configuration, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)560 public static void writeCommonElementsToXml( 561 XmlSerializer out, WifiConfiguration configuration, 562 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 563 throws XmlPullParserException, IOException { 564 XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.getKey()); 565 XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); 566 writePreSharedKeyToXml(out, configuration, encryptionUtil); 567 writeWepKeysToXml(out, configuration.wepKeys, encryptionUtil); 568 XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); 569 XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); 570 XmlUtil.writeNextValue(out, XML_TAG_REQUIRE_PMF, configuration.requirePmf); 571 XmlUtil.writeNextValue( 572 out, XML_TAG_ALLOWED_KEY_MGMT, 573 configuration.allowedKeyManagement.toByteArray()); 574 XmlUtil.writeNextValue( 575 out, XML_TAG_ALLOWED_PROTOCOLS, 576 configuration.allowedProtocols.toByteArray()); 577 XmlUtil.writeNextValue( 578 out, XML_TAG_ALLOWED_AUTH_ALGOS, 579 configuration.allowedAuthAlgorithms.toByteArray()); 580 XmlUtil.writeNextValue( 581 out, XML_TAG_ALLOWED_GROUP_CIPHERS, 582 configuration.allowedGroupCiphers.toByteArray()); 583 XmlUtil.writeNextValue( 584 out, XML_TAG_ALLOWED_PAIRWISE_CIPHERS, 585 configuration.allowedPairwiseCiphers.toByteArray()); 586 XmlUtil.writeNextValue( 587 out, XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS, 588 configuration.allowedGroupManagementCiphers.toByteArray()); 589 XmlUtil.writeNextValue( 590 out, XML_TAG_ALLOWED_SUITE_B_CIPHERS, 591 configuration.allowedSuiteBCiphers.toByteArray()); 592 XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); 593 XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN, configuration.allowAutojoin); 594 XmlUtil.writeNextValue( 595 out, XML_TAG_DELETION_PRIORITY, 596 configuration.getDeletionPriority()); 597 XmlUtil.writeNextValue( 598 out, XML_TAG_NUM_REBOOTS_SINCE_LAST_USE, 599 configuration.numRebootsSinceLastUse); 600 XmlUtil.writeNextValue(out, XML_TAG_IS_REPEATER_ENABLED, 601 configuration.isRepeaterEnabled()); 602 writeSecurityParamsListToXml(out, configuration); 603 } 604 605 /** 606 * Write the Configuration data elements for backup from the provided Configuration to the 607 * XML stream. 608 * Note: This is a subset of the elements serialized for config store. 609 * 610 * @param out XmlSerializer instance pointing to the XML stream. 611 * @param configuration WifiConfiguration object to be serialized. 612 */ writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration)613 public static void writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration) 614 throws XmlPullParserException, IOException { 615 writeCommonElementsToXml(out, configuration, null); 616 XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride); 617 } 618 619 /** 620 * Write the Configuration data elements for config store from the provided Configuration 621 * to the XML stream. 622 * 623 * @param out XmlSerializer instance pointing to the XML stream. 624 * @param configuration WifiConfiguration object to be serialized. 625 * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. 626 */ writeToXmlForConfigStore( XmlSerializer out, WifiConfiguration configuration, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)627 public static void writeToXmlForConfigStore( 628 XmlSerializer out, WifiConfiguration configuration, 629 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 630 throws XmlPullParserException, IOException { 631 writeCommonElementsToXml(out, configuration, encryptionUtil); 632 XmlUtil.writeNextValue(out, XML_TAG_IS_TRUSTED, configuration.trusted); 633 XmlUtil.writeNextValue(out, XML_TAG_IS_RESTRICTED, configuration.restricted); 634 XmlUtil.writeNextValue(out, XML_TAG_IS_OEM_PAID, configuration.oemPaid); 635 XmlUtil.writeNextValue(out, XML_TAG_IS_OEM_PRIVATE, configuration.oemPrivate); 636 XmlUtil.writeNextValue(out, XML_TAG_IS_CARRIER_MERGED, 637 configuration.carrierMerged); 638 XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); 639 XmlUtil.writeNextValue(out, XML_TAG_STATUS, configuration.status); 640 XmlUtil.writeNextValue(out, XML_TAG_FQDN, configuration.FQDN); 641 XmlUtil.writeNextValue( 642 out, XML_TAG_PROVIDER_FRIENDLY_NAME, configuration.providerFriendlyName); 643 XmlUtil.writeNextValue( 644 out, XML_TAG_LINKED_NETWORKS_LIST, configuration.linkedConfigurations); 645 XmlUtil.writeNextValue( 646 out, XML_TAG_DEFAULT_GW_MAC_ADDRESS, configuration.defaultGwMacAddress); 647 XmlUtil.writeNextValue( 648 out, XML_TAG_VALIDATED_INTERNET_ACCESS, configuration.validatedInternetAccess); 649 XmlUtil.writeNextValue( 650 out, XML_TAG_NO_INTERNET_ACCESS_EXPECTED, 651 configuration.noInternetAccessExpected); 652 XmlUtil.writeNextValue(out, XML_TAG_METERED_HINT, configuration.meteredHint); 653 XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride); 654 XmlUtil.writeNextValue( 655 out, XML_TAG_USE_EXTERNAL_SCORES, configuration.useExternalScores); 656 XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); 657 XmlUtil.writeNextValue(out, XML_TAG_CREATOR_NAME, configuration.creatorName); 658 XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_UID, configuration.lastUpdateUid); 659 XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_NAME, configuration.lastUpdateName); 660 XmlUtil.writeNextValue(out, XML_TAG_LAST_CONNECT_UID, configuration.lastConnectUid); 661 XmlUtil.writeNextValue( 662 out, XML_TAG_IS_LEGACY_PASSPOINT_CONFIG, 663 configuration.isLegacyPasspointConfig); 664 XmlUtil.writeNextValue( 665 out, XML_TAG_ROAMING_CONSORTIUM_OIS, configuration.roamingConsortiumIds); 666 XmlUtil.writeNextValue(out, XML_TAG_RANDOMIZED_MAC_ADDRESS, 667 configuration.getRandomizedMacAddress().toString()); 668 XmlUtil.writeNextValue(out, XML_TAG_MAC_RANDOMIZATION_SETTING, 669 configuration.macRandomizationSetting); 670 XmlUtil.writeNextValue(out, XML_TAG_CARRIER_ID, configuration.carrierId); 671 XmlUtil.writeNextValue(out, XML_TAG_IS_MOST_RECENTLY_CONNECTED, 672 configuration.isMostRecentlyConnected); 673 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_ID, configuration.subscriptionId); 674 if (configuration.getSubscriptionGroup() != null) { 675 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_GROUP, 676 configuration.getSubscriptionGroup().toString()); 677 } 678 if (configuration.getBssidAllowlistInternal() != null) { 679 XmlUtil.writeNextValue(out, XML_TAG_BSSID_ALLOW_LIST, 680 covertMacAddressListToStringList(configuration 681 .getBssidAllowlistInternal())); 682 } 683 writeDppConfigurationToXml(out, configuration, encryptionUtil); 684 } 685 covertMacAddressListToStringList(List<MacAddress> macList)686 private static List<String> covertMacAddressListToStringList(List<MacAddress> macList) { 687 List<String> bssidList = new ArrayList<>(); 688 for (MacAddress address : macList) { 689 bssidList.add(address.toString()); 690 } 691 return bssidList; 692 } 693 covertStringListToMacAddressList(List<String> stringList)694 private static List<MacAddress> covertStringListToMacAddressList(List<String> stringList) { 695 List<MacAddress> macAddressList = new ArrayList<>(); 696 for (String address : stringList) { 697 try { 698 macAddressList.add(MacAddress.fromString(address)); 699 } catch (Exception e) { 700 Log.e(TAG, "Invalid BSSID String: " + address); 701 } 702 } 703 return macAddressList; 704 } 705 706 /** 707 * Populate wepKeys array elements only if they were non-empty in the backup data. 708 * 709 * @throws XmlPullParserException if parsing errors occur. 710 */ populateWepKeysFromXmlValue(Object value, String[] wepKeys)711 private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 712 throws XmlPullParserException, IOException { 713 String[] wepKeysInData = (String[]) value; 714 if (wepKeysInData == null) { 715 return; 716 } 717 if (wepKeysInData.length != wepKeys.length) { 718 throw new XmlPullParserException( 719 "Invalid Wep Keys length: " + wepKeysInData.length); 720 } 721 for (int i = 0; i < wepKeys.length; i++) { 722 if (wepKeysInData[i].isEmpty()) { 723 wepKeys[i] = null; 724 } else { 725 wepKeys[i] = wepKeysInData[i]; 726 } 727 } 728 } 729 populateWepKeysFromXmlValue(XmlPullParser in, int outerTagDepth, @NonNull WifiConfigStoreEncryptionUtil encryptionUtil)730 private static String[] populateWepKeysFromXmlValue(XmlPullParser in, 731 int outerTagDepth, @NonNull WifiConfigStoreEncryptionUtil encryptionUtil) 732 throws XmlPullParserException, IOException { 733 List<String> wepKeyList = new ArrayList<>(); 734 final List<EncryptedData> encryptedDataList = 735 XmlUtil.EncryptedDataXmlUtil.parseListFromXml(in, outerTagDepth); 736 for (int i = 0; i < encryptedDataList.size(); i++) { 737 byte[] passphraseBytes = encryptionUtil.decrypt(encryptedDataList.get(i)); 738 if (passphraseBytes == null) { 739 Log.wtf(TAG, "Decryption of passphraseBytes failed"); 740 } else { 741 wepKeyList.add(new String(passphraseBytes, StandardCharsets.UTF_8)); 742 } 743 } 744 return wepKeyList.size() > 0 ? wepKeyList.toArray( 745 new String[wepKeyList.size()]) : null; 746 } 747 parseSecurityParamsFromXml( XmlPullParser in, int outerTagDepth)748 private static SecurityParams parseSecurityParamsFromXml( 749 XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { 750 SecurityParams params = null; 751 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 752 String[] valueName = new String[1]; 753 Object value = XmlUtil.readCurrentValue(in, valueName); 754 String tagName = valueName[0]; 755 if (tagName == null) { 756 throw new XmlPullParserException("Missing value name"); 757 } 758 switch (tagName) { 759 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE: 760 params = SecurityParams.createSecurityParamsBySecurityType((int) value); 761 break; 762 case WifiConfigurationXmlUtil.XML_TAG_IS_ENABLED: 763 params.setEnabled((boolean) value); 764 break; 765 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE: 766 if (null == params) { 767 throw new XmlPullParserException("Missing security type."); 768 } 769 params.enableSaeH2eOnlyMode((boolean) value); 770 break; 771 case WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE: 772 if (null == params) { 773 throw new XmlPullParserException("Missing security type."); 774 } 775 params.enableSaePkOnlyMode((boolean) value); 776 break; 777 case WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE: 778 if (null == params) { 779 throw new XmlPullParserException("Missing security type."); 780 } 781 params.setIsAddedByAutoUpgrade((boolean) value); 782 break; 783 case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_SUITE_B_CIPHERS: 784 if (null == params) { 785 throw new XmlPullParserException("Missing security type."); 786 } 787 byte[] suiteBCiphers = (byte[]) value; 788 BitSet suiteBCiphersBitSet = BitSet.valueOf(suiteBCiphers); 789 params.enableSuiteBCiphers( 790 suiteBCiphersBitSet.get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA), 791 suiteBCiphersBitSet.get(WifiConfiguration.SuiteBCipher.ECDHE_RSA)); 792 break; 793 } 794 } 795 return params; 796 } 797 readEncrytepdBytesFromXml( @ullable WifiConfigStoreEncryptionUtil encryptionUtil, XmlPullParser in, int outerTagDepth)798 private static byte[] readEncrytepdBytesFromXml( 799 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, 800 XmlPullParser in, int outerTagDepth) 801 throws XmlPullParserException, IOException { 802 if (encryptionUtil == null) { 803 throw new XmlPullParserException( 804 "Encrypted preSharedKey section not expected"); 805 } 806 EncryptedData encryptedData = 807 EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); 808 return encryptionUtil.decrypt(encryptedData); 809 } 810 parseSecurityParamsListFromXml( XmlPullParser in, int outerTagDepth, WifiConfiguration configuration)811 private static void parseSecurityParamsListFromXml( 812 XmlPullParser in, int outerTagDepth, 813 WifiConfiguration configuration) 814 throws XmlPullParserException, IOException { 815 List<SecurityParams> paramsList = new ArrayList<>(); 816 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 817 switch (in.getName()) { 818 case WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS: 819 SecurityParams params = parseSecurityParamsFromXml(in, outerTagDepth + 1); 820 if (params != null) { 821 paramsList.add(params); 822 } 823 break; 824 } 825 } 826 if (!paramsList.isEmpty()) { 827 configuration.setSecurityParams(paramsList); 828 } 829 } 830 831 /** 832 * Parses the configuration data elements from the provided XML stream to a 833 * WifiConfiguration object. 834 * Note: This is used for parsing both backup data and config store data. Looping through 835 * the tags make it easy to add or remove elements in the future versions if needed. 836 * 837 * @param in XmlPullParser instance pointing to the XML stream. 838 * @param outerTagDepth depth of the outer tag in the XML document. 839 * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. 840 * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. 841 * @param fromSuggestion Is this WifiConfiguration created from a WifiNetworkSuggestion. 842 * @return Pair<Config key, WifiConfiguration object> if parsing is successful, 843 * null otherwise. 844 */ parseFromXml( XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, boolean fromSuggestion)845 public static Pair<String, WifiConfiguration> parseFromXml( 846 XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, 847 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, boolean fromSuggestion) 848 throws XmlPullParserException, IOException { 849 WifiConfiguration configuration = new WifiConfiguration(); 850 String configKeyInData = null; 851 boolean macRandomizationSettingExists = false; 852 byte[] dppConnector = null; 853 byte[] dppCSign = null; 854 byte[] dppNetAccessKey = null; 855 856 // Loop through and parse out all the elements from the stream within this section. 857 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 858 if (in.getAttributeValue(null, "name") != null) { 859 // Value elements. 860 String[] valueName = new String[1]; 861 Object value = XmlUtil.readCurrentValue(in, valueName); 862 if (valueName[0] == null) { 863 throw new XmlPullParserException("Missing value name"); 864 } 865 switch (valueName[0]) { 866 case XML_TAG_CONFIG_KEY: 867 configKeyInData = (String) value; 868 break; 869 case XML_TAG_SSID: 870 configuration.SSID = (String) value; 871 break; 872 case XML_TAG_BSSID: 873 configuration.BSSID = (String) value; 874 break; 875 case XML_TAG_PRE_SHARED_KEY: 876 configuration.preSharedKey = (String) value; 877 break; 878 case XML_TAG_WEP_KEYS: 879 populateWepKeysFromXmlValue(value, configuration.wepKeys); 880 break; 881 case XML_TAG_WEP_TX_KEY_INDEX: 882 configuration.wepTxKeyIndex = (int) value; 883 break; 884 case XML_TAG_HIDDEN_SSID: 885 configuration.hiddenSSID = (boolean) value; 886 break; 887 case XML_TAG_REQUIRE_PMF: 888 configuration.requirePmf = (boolean) value; 889 break; 890 case XML_TAG_ALLOWED_KEY_MGMT: 891 byte[] allowedKeyMgmt = (byte[]) value; 892 configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 893 break; 894 case XML_TAG_ALLOWED_PROTOCOLS: 895 byte[] allowedProtocols = (byte[]) value; 896 configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 897 break; 898 case XML_TAG_ALLOWED_AUTH_ALGOS: 899 byte[] allowedAuthAlgorithms = (byte[]) value; 900 configuration.allowedAuthAlgorithms = BitSet.valueOf( 901 allowedAuthAlgorithms); 902 break; 903 case XML_TAG_ALLOWED_GROUP_CIPHERS: 904 byte[] allowedGroupCiphers = (byte[]) value; 905 configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); 906 break; 907 case XML_TAG_ALLOWED_PAIRWISE_CIPHERS: 908 byte[] allowedPairwiseCiphers = (byte[]) value; 909 configuration.allowedPairwiseCiphers = 910 BitSet.valueOf(allowedPairwiseCiphers); 911 break; 912 case XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS: 913 byte[] allowedGroupMgmtCiphers = (byte[]) value; 914 configuration.allowedGroupManagementCiphers = 915 BitSet.valueOf(allowedGroupMgmtCiphers); 916 break; 917 case XML_TAG_ALLOWED_SUITE_B_CIPHERS: 918 byte[] allowedSuiteBCiphers = (byte[]) value; 919 configuration.allowedSuiteBCiphers = 920 BitSet.valueOf(allowedSuiteBCiphers); 921 break; 922 case XML_TAG_SHARED: 923 configuration.shared = (boolean) value; 924 break; 925 case XML_TAG_STATUS: 926 int status = (int) value; 927 // Any network which was CURRENT before reboot needs 928 // to be restored to ENABLED. 929 if (status == WifiConfiguration.Status.CURRENT) { 930 status = WifiConfiguration.Status.ENABLED; 931 } 932 configuration.status = status; 933 break; 934 case XML_TAG_FQDN: 935 configuration.FQDN = (String) value; 936 break; 937 case XML_TAG_PROVIDER_FRIENDLY_NAME: 938 configuration.providerFriendlyName = (String) value; 939 break; 940 case XML_TAG_LINKED_NETWORKS_LIST: 941 configuration.linkedConfigurations = (HashMap<String, Integer>) value; 942 break; 943 case XML_TAG_DEFAULT_GW_MAC_ADDRESS: 944 configuration.defaultGwMacAddress = (String) value; 945 break; 946 case XML_TAG_VALIDATED_INTERNET_ACCESS: 947 configuration.validatedInternetAccess = (boolean) value; 948 break; 949 case XML_TAG_NO_INTERNET_ACCESS_EXPECTED: 950 configuration.noInternetAccessExpected = (boolean) value; 951 break; 952 case XML_TAG_METERED_HINT: 953 configuration.meteredHint = (boolean) value; 954 break; 955 case XML_TAG_METERED_OVERRIDE: 956 configuration.meteredOverride = (int) value; 957 break; 958 case XML_TAG_USE_EXTERNAL_SCORES: 959 configuration.useExternalScores = (boolean) value; 960 break; 961 case XML_TAG_CREATOR_UID: 962 configuration.creatorUid = (int) value; 963 break; 964 case XML_TAG_CREATOR_NAME: 965 configuration.creatorName = (String) value; 966 break; 967 case XML_TAG_LAST_UPDATE_UID: 968 configuration.lastUpdateUid = (int) value; 969 break; 970 case XML_TAG_LAST_UPDATE_NAME: 971 configuration.lastUpdateName = (String) value; 972 break; 973 case XML_TAG_LAST_CONNECT_UID: 974 configuration.lastConnectUid = (int) value; 975 break; 976 case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG: 977 configuration.isLegacyPasspointConfig = (boolean) value; 978 break; 979 case XML_TAG_ROAMING_CONSORTIUM_OIS: 980 configuration.roamingConsortiumIds = (long[]) value; 981 break; 982 case XML_TAG_RANDOMIZED_MAC_ADDRESS: 983 configuration.setRandomizedMacAddress( 984 MacAddress.fromString((String) value)); 985 break; 986 case XML_TAG_MAC_RANDOMIZATION_SETTING: 987 configuration.macRandomizationSetting = (int) value; 988 macRandomizationSettingExists = true; 989 break; 990 case XML_TAG_CARRIER_ID: 991 configuration.carrierId = (int) value; 992 break; 993 case XML_TAG_SUBSCRIPTION_ID: 994 configuration.subscriptionId = (int) value; 995 break; 996 case XML_TAG_IS_AUTO_JOIN: 997 configuration.allowAutojoin = (boolean) value; 998 break; 999 case XML_TAG_DELETION_PRIORITY: 1000 configuration.setDeletionPriority((int) value); 1001 break; 1002 case XML_TAG_NUM_REBOOTS_SINCE_LAST_USE: 1003 configuration.numRebootsSinceLastUse = (int) value; 1004 break; 1005 case XML_TAG_IS_TRUSTED: 1006 configuration.trusted = (boolean) value; 1007 break; 1008 case XML_TAG_IS_OEM_PAID: 1009 configuration.oemPaid = (boolean) value; 1010 break; 1011 case XML_TAG_IS_OEM_PRIVATE: 1012 configuration.oemPrivate = (boolean) value; 1013 break; 1014 case XML_TAG_IS_MOST_RECENTLY_CONNECTED: 1015 configuration.isMostRecentlyConnected = (boolean) value; 1016 break; 1017 case XML_TAG_IS_CARRIER_MERGED: 1018 configuration.carrierMerged = (boolean) value; 1019 break; 1020 case XML_TAG_IS_RESTRICTED: 1021 configuration.restricted = (boolean) value; 1022 break; 1023 case XML_TAG_SUBSCRIPTION_GROUP: 1024 configuration.setSubscriptionGroup( 1025 ParcelUuid.fromString((String) value)); 1026 break; 1027 case XML_TAG_BSSID_ALLOW_LIST: 1028 configuration.setBssidAllowlist( 1029 covertStringListToMacAddressList((List<String>) value)); 1030 break; 1031 case XML_TAG_IS_REPEATER_ENABLED: 1032 configuration.setRepeaterEnabled((boolean) value); 1033 break; 1034 case XML_TAG_DPP_PRIVATE_EC_KEY: 1035 configuration.setDppConfigurator((byte[]) value); 1036 break; 1037 case XML_TAG_DPP_CONNECTOR: 1038 dppConnector = (byte[]) value; 1039 break; 1040 case XML_TAG_DPP_CSIGN_KEY: 1041 dppCSign = (byte[]) value; 1042 break; 1043 case XML_TAG_DPP_NET_ACCESS_KEY: 1044 dppNetAccessKey = (byte[]) value; 1045 break; 1046 default: 1047 Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); 1048 break; 1049 } 1050 } else { 1051 String tagName = in.getName(); 1052 if (tagName == null) { 1053 throw new XmlPullParserException("Unexpected null tag found"); 1054 } 1055 switch (tagName) { 1056 case XML_TAG_PRE_SHARED_KEY: 1057 if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { 1058 throw new XmlPullParserException( 1059 "Encrypted preSharedKey section not expected"); 1060 } 1061 EncryptedData encryptedData = 1062 EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); 1063 byte[] preSharedKeyBytes = encryptionUtil.decrypt(encryptedData); 1064 if (preSharedKeyBytes == null) { 1065 Log.wtf(TAG, "Decryption of preSharedKey failed"); 1066 } else { 1067 configuration.preSharedKey = new String(preSharedKeyBytes); 1068 configuration.setEncryptedPreSharedKey( 1069 encryptedData.getEncryptedData(), 1070 encryptedData.getIv()); 1071 } 1072 break; 1073 case XML_TAG_WEP_KEYS: 1074 if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { 1075 throw new XmlPullParserException( 1076 "Encrypted wepKeys section not expected"); 1077 } 1078 configuration.wepKeys = populateWepKeysFromXmlValue(in, 1079 outerTagDepth + 1, encryptionUtil); 1080 break; 1081 case XML_TAG_SECURITY_PARAMS_LIST: 1082 parseSecurityParamsListFromXml(in, outerTagDepth + 1, configuration); 1083 break; 1084 case XML_TAG_DPP_PRIVATE_EC_KEY: 1085 configuration.setDppConfigurator(readEncrytepdBytesFromXml( 1086 encryptionUtil, in, outerTagDepth)); 1087 break; 1088 case XML_TAG_DPP_CONNECTOR: 1089 dppConnector = readEncrytepdBytesFromXml(encryptionUtil, in, 1090 outerTagDepth); 1091 break; 1092 case XML_TAG_DPP_CSIGN_KEY: 1093 dppCSign = readEncrytepdBytesFromXml(encryptionUtil, in, 1094 outerTagDepth); 1095 break; 1096 case XML_TAG_DPP_NET_ACCESS_KEY: 1097 dppNetAccessKey = readEncrytepdBytesFromXml(encryptionUtil, in, 1098 outerTagDepth); 1099 break; 1100 default: 1101 Log.w(TAG, "Ignoring unknown tag found: " + tagName); 1102 break; 1103 } 1104 } 1105 } 1106 if (!macRandomizationSettingExists) { 1107 configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; 1108 } 1109 if (configuration.macRandomizationSetting 1110 == WifiConfiguration.RANDOMIZATION_PERSISTENT && !fromSuggestion) { 1111 configuration.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO; 1112 } 1113 configuration.convertLegacyFieldsToSecurityParamsIfNeeded(); 1114 configuration.setDppConnectionKeys(dppConnector, dppCSign, dppNetAccessKey); 1115 return Pair.create(configKeyInData, configuration); 1116 } 1117 } 1118 1119 /** 1120 * Utility class to serialize and deseriaize {@link IpConfiguration} object to XML & vice versa. 1121 * This is used by both {@link com.android.server.wifi.WifiConfigStore} & 1122 * {@link com.android.server.wifi.WifiBackupRestore} modules. 1123 */ 1124 public static class IpConfigurationXmlUtil { 1125 1126 /** 1127 * List of XML tags corresponding to IpConfiguration object elements. 1128 */ 1129 public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment"; 1130 public static final String XML_TAG_LINK_ADDRESS = "LinkAddress"; 1131 public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength"; 1132 public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress"; 1133 public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers"; 1134 public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings"; 1135 public static final String XML_TAG_PROXY_HOST = "ProxyHost"; 1136 public static final String XML_TAG_PROXY_PORT = "ProxyPort"; 1137 public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac"; 1138 public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; 1139 parseProxyExclusionListString( @ullable String exclusionListString)1140 private static List<String> parseProxyExclusionListString( 1141 @Nullable String exclusionListString) { 1142 if (exclusionListString == null) { 1143 return Collections.emptyList(); 1144 } else { 1145 return Arrays.asList(exclusionListString.toLowerCase(Locale.ROOT).split(",")); 1146 } 1147 } 1148 generateProxyExclusionListString(@onNull String[] exclusionList)1149 private static String generateProxyExclusionListString(@NonNull String[] exclusionList) { 1150 return TextUtils.join(",", exclusionList); 1151 } 1152 1153 /** 1154 * Write the static IP configuration data elements to XML stream. 1155 */ writeStaticIpConfigurationToXml( XmlSerializer out, StaticIpConfiguration staticIpConfiguration)1156 private static void writeStaticIpConfigurationToXml( 1157 XmlSerializer out, StaticIpConfiguration staticIpConfiguration) 1158 throws XmlPullParserException, IOException { 1159 if (staticIpConfiguration.getIpAddress() != null) { 1160 XmlUtil.writeNextValue( 1161 out, XML_TAG_LINK_ADDRESS, 1162 staticIpConfiguration.getIpAddress().getAddress().getHostAddress()); 1163 XmlUtil.writeNextValue( 1164 out, XML_TAG_LINK_PREFIX_LENGTH, 1165 staticIpConfiguration.getIpAddress().getPrefixLength()); 1166 } else { 1167 XmlUtil.writeNextValue( 1168 out, XML_TAG_LINK_ADDRESS, null); 1169 XmlUtil.writeNextValue( 1170 out, XML_TAG_LINK_PREFIX_LENGTH, null); 1171 } 1172 if (staticIpConfiguration.getGateway() != null) { 1173 XmlUtil.writeNextValue( 1174 out, XML_TAG_GATEWAY_ADDRESS, 1175 staticIpConfiguration.getGateway().getHostAddress()); 1176 } else { 1177 XmlUtil.writeNextValue( 1178 out, XML_TAG_GATEWAY_ADDRESS, null); 1179 1180 } 1181 // Create a string array of DNS server addresses 1182 String[] dnsServers = new String[staticIpConfiguration.getDnsServers().size()]; 1183 int dnsServerIdx = 0; 1184 for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) { 1185 dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); 1186 } 1187 XmlUtil.writeNextValue( 1188 out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers); 1189 } 1190 1191 /** 1192 * Write the IP configuration data elements from the provided Configuration to the XML 1193 * stream. 1194 * 1195 * @param out XmlSerializer instance pointing to the XML stream. 1196 * @param ipConfiguration IpConfiguration object to be serialized. 1197 */ writeToXml(XmlSerializer out, IpConfiguration ipConfiguration)1198 public static void writeToXml(XmlSerializer out, IpConfiguration ipConfiguration) 1199 throws XmlPullParserException, IOException { 1200 // Write IP assignment settings 1201 XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT, 1202 ipConfiguration.getIpAssignment().toString()); 1203 switch (ipConfiguration.getIpAssignment()) { 1204 case STATIC: 1205 writeStaticIpConfigurationToXml( 1206 out, ipConfiguration.getStaticIpConfiguration()); 1207 break; 1208 case DHCP: 1209 case UNASSIGNED: 1210 break; 1211 default: 1212 Log.w(TAG, "Ignoring unknown ip assignment type: " 1213 + ipConfiguration.getIpAssignment()); 1214 break; 1215 } 1216 1217 // Write proxy settings 1218 XmlUtil.writeNextValue( 1219 out, XML_TAG_PROXY_SETTINGS, 1220 ipConfiguration.getProxySettings().toString()); 1221 switch (ipConfiguration.getProxySettings()) { 1222 case STATIC: 1223 XmlUtil.writeNextValue( 1224 out, XML_TAG_PROXY_HOST, 1225 ipConfiguration.getHttpProxy().getHost()); 1226 XmlUtil.writeNextValue( 1227 out, XML_TAG_PROXY_PORT, 1228 ipConfiguration.getHttpProxy().getPort()); 1229 XmlUtil.writeNextValue( 1230 out, XML_TAG_PROXY_EXCLUSION_LIST, 1231 generateProxyExclusionListString( 1232 ipConfiguration.getHttpProxy().getExclusionList())); 1233 break; 1234 case PAC: 1235 XmlUtil.writeNextValue( 1236 out, XML_TAG_PROXY_PAC_FILE, 1237 ipConfiguration.getHttpProxy().getPacFileUrl().toString()); 1238 break; 1239 case NONE: 1240 case UNASSIGNED: 1241 break; 1242 default: 1243 Log.w(TAG, "Ignoring unknown proxy settings type: " 1244 + ipConfiguration.getProxySettings()); 1245 break; 1246 } 1247 } 1248 1249 /** 1250 * Parse out the static IP configuration from the XML stream. 1251 */ parseStaticIpConfigurationFromXml(XmlPullParser in)1252 private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) 1253 throws XmlPullParserException, IOException { 1254 StaticIpConfiguration.Builder builder = new StaticIpConfiguration.Builder(); 1255 1256 String linkAddressString = 1257 (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS); 1258 Integer linkPrefixLength = 1259 (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH); 1260 if (linkAddressString != null && linkPrefixLength != null) { 1261 LinkAddress linkAddress = new LinkAddress( 1262 InetAddresses.parseNumericAddress(linkAddressString), 1263 linkPrefixLength); 1264 if (linkAddress.getAddress() instanceof Inet4Address) { 1265 builder.setIpAddress(linkAddress); 1266 } else { 1267 Log.w(TAG, "Non-IPv4 address: " + linkAddress); 1268 } 1269 } 1270 String gatewayAddressString = 1271 (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS); 1272 if (gatewayAddressString != null) { 1273 InetAddress gateway = 1274 InetAddresses.parseNumericAddress(gatewayAddressString); 1275 RouteInfo route = new RouteInfo(null, gateway, null, RouteInfo.RTN_UNICAST); 1276 if (route.isDefaultRoute() 1277 && route.getDestination().getAddress() instanceof Inet4Address) { 1278 builder.setGateway(gateway); 1279 } else { 1280 Log.w(TAG, "Non-IPv4 default route: " + route); 1281 } 1282 } 1283 String[] dnsServerAddressesString = 1284 (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES); 1285 if (dnsServerAddressesString != null) { 1286 List<InetAddress> dnsServerAddresses = new ArrayList<>(); 1287 for (String dnsServerAddressString : dnsServerAddressesString) { 1288 InetAddress dnsServerAddress = 1289 InetAddresses.parseNumericAddress(dnsServerAddressString); 1290 dnsServerAddresses.add(dnsServerAddress); 1291 } 1292 builder.setDnsServers(dnsServerAddresses); 1293 } 1294 return builder.build(); 1295 } 1296 1297 /** 1298 * Parses the IP configuration data elements from the provided XML stream to an 1299 * IpConfiguration object. 1300 * 1301 * @param in XmlPullParser instance pointing to the XML stream. 1302 * @param outerTagDepth depth of the outer tag in the XML document. 1303 * @return IpConfiguration object if parsing is successful, null otherwise. 1304 */ parseFromXml(XmlPullParser in, int outerTagDepth)1305 public static IpConfiguration parseFromXml(XmlPullParser in, int outerTagDepth) 1306 throws XmlPullParserException, IOException { 1307 IpConfiguration ipConfiguration = new IpConfiguration(); 1308 1309 // Parse out the IP assignment info first. 1310 String ipAssignmentString = 1311 (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT); 1312 IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); 1313 ipConfiguration.setIpAssignment(ipAssignment); 1314 switch (ipAssignment) { 1315 case STATIC: 1316 ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in)); 1317 break; 1318 case DHCP: 1319 case UNASSIGNED: 1320 break; 1321 default: 1322 Log.w(TAG, "Ignoring unknown ip assignment type: " + ipAssignment); 1323 break; 1324 } 1325 1326 // Parse out the proxy settings next. 1327 String proxySettingsString = 1328 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS); 1329 ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); 1330 ipConfiguration.setProxySettings(proxySettings); 1331 switch (proxySettings) { 1332 case STATIC: 1333 String proxyHost = 1334 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST); 1335 int proxyPort = 1336 (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT); 1337 String proxyExclusionList = 1338 (String) XmlUtil.readNextValueWithName( 1339 in, XML_TAG_PROXY_EXCLUSION_LIST); 1340 ipConfiguration.setHttpProxy( 1341 ProxyInfo.buildDirectProxy( 1342 proxyHost, proxyPort, 1343 parseProxyExclusionListString(proxyExclusionList))); 1344 break; 1345 case PAC: 1346 String proxyPacFile = 1347 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE); 1348 ipConfiguration.setHttpProxy( 1349 ProxyInfo.buildPacProxy(Uri.parse(proxyPacFile))); 1350 break; 1351 case NONE: 1352 case UNASSIGNED: 1353 break; 1354 default: 1355 Log.w(TAG, "Ignoring unknown proxy settings type: " + proxySettings); 1356 break; 1357 } 1358 return ipConfiguration; 1359 } 1360 } 1361 1362 /** 1363 * Utility class to serialize and deserialize {@link NetworkSelectionStatus} object to XML & 1364 * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. 1365 */ 1366 public static class NetworkSelectionStatusXmlUtil { 1367 1368 /** 1369 * List of XML tags corresponding to NetworkSelectionStatus object elements. 1370 */ 1371 public static final String XML_TAG_SELECTION_STATUS = "SelectionStatus"; 1372 public static final String XML_TAG_DISABLE_REASON = "DisableReason"; 1373 public static final String XML_TAG_CONNECT_CHOICE = "ConnectChoice"; 1374 public static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected"; 1375 public static final String XML_TAG_IS_CAPTIVE_PORTAL_NEVER_DETECTED = 1376 "CaptivePortalNeverDetected"; 1377 public static final String XML_TAG_CONNECT_CHOICE_RSSI = "ConnectChoiceRssi"; 1378 1379 /** 1380 * Write the NetworkSelectionStatus data elements from the provided status to the XML 1381 * stream. 1382 * 1383 * @param out XmlSerializer instance pointing to the XML stream. 1384 * @param selectionStatus NetworkSelectionStatus object to be serialized. 1385 */ writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus)1386 public static void writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus) 1387 throws XmlPullParserException, IOException { 1388 XmlUtil.writeNextValue( 1389 out, XML_TAG_SELECTION_STATUS, selectionStatus.getNetworkStatusString()); 1390 XmlUtil.writeNextValue( 1391 out, XML_TAG_DISABLE_REASON, 1392 selectionStatus.getNetworkSelectionDisableReasonString()); 1393 XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE, selectionStatus.getConnectChoice()); 1394 XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE_RSSI, 1395 selectionStatus.getConnectChoiceRssi()); 1396 XmlUtil.writeNextValue( 1397 out, XML_TAG_HAS_EVER_CONNECTED, selectionStatus.hasEverConnected()); 1398 XmlUtil.writeNextValue(out, XML_TAG_IS_CAPTIVE_PORTAL_NEVER_DETECTED, 1399 selectionStatus.hasNeverDetectedCaptivePortal()); 1400 } 1401 1402 /** 1403 * Parses the NetworkSelectionStatus data elements from the provided XML stream to a 1404 * NetworkSelectionStatus object. 1405 * 1406 * @param in XmlPullParser instance pointing to the XML stream. 1407 * @param outerTagDepth depth of the outer tag in the XML document. 1408 * @return NetworkSelectionStatus object if parsing is successful, null otherwise. 1409 */ parseFromXml(XmlPullParser in, int outerTagDepth)1410 public static NetworkSelectionStatus parseFromXml(XmlPullParser in, int outerTagDepth) 1411 throws XmlPullParserException, IOException { 1412 NetworkSelectionStatus selectionStatus = new NetworkSelectionStatus(); 1413 String statusString = ""; 1414 String disableReasonString = ""; 1415 // Initialize hasNeverDetectedCaptivePortal to "false" for upgrading legacy configs 1416 // which do not have the XML_TAG_IS_CAPTIVE_PORTAL_NEVER_DETECTED tag. 1417 selectionStatus.setHasNeverDetectedCaptivePortal(false); 1418 1419 // Loop through and parse out all the elements from the stream within this section. 1420 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 1421 String[] valueName = new String[1]; 1422 Object value = XmlUtil.readCurrentValue(in, valueName); 1423 if (valueName[0] == null) { 1424 throw new XmlPullParserException("Missing value name"); 1425 } 1426 switch (valueName[0]) { 1427 case XML_TAG_SELECTION_STATUS: 1428 statusString = (String) value; 1429 break; 1430 case XML_TAG_DISABLE_REASON: 1431 disableReasonString = (String) value; 1432 break; 1433 case XML_TAG_CONNECT_CHOICE: 1434 selectionStatus.setConnectChoice((String) value); 1435 break; 1436 case XML_TAG_CONNECT_CHOICE_RSSI: 1437 selectionStatus.setConnectChoiceRssi((int) value); 1438 break; 1439 case XML_TAG_HAS_EVER_CONNECTED: 1440 selectionStatus.setHasEverConnected((boolean) value); 1441 break; 1442 case XML_TAG_IS_CAPTIVE_PORTAL_NEVER_DETECTED: 1443 selectionStatus.setHasNeverDetectedCaptivePortal((boolean) value); 1444 default: 1445 Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); 1446 break; 1447 } 1448 } 1449 // Now figure out the network selection status codes from |selectionStatusString| & 1450 // |disableReasonString|. 1451 int status = 1452 Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_STATUS) 1453 .indexOf(statusString); 1454 int disableReason = 1455 NetworkSelectionStatus.getDisableReasonByString(disableReasonString); 1456 1457 // If either of the above codes are invalid or if the network was temporarily disabled 1458 // (blacklisted), restore the status as enabled. We don't want to persist blacklists 1459 // across reboots. 1460 if (status == -1 || disableReason == -1 || 1461 status == NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) { 1462 status = NetworkSelectionStatus.NETWORK_SELECTION_ENABLED; 1463 disableReason = NetworkSelectionStatus.DISABLED_NONE; 1464 } 1465 selectionStatus.setNetworkSelectionStatus(status); 1466 selectionStatus.setNetworkSelectionDisableReason(disableReason); 1467 if (status == NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED) { 1468 // Make the counter non-zero so that logging code works properly 1469 selectionStatus.setDisableReasonCounter(disableReason, 1); 1470 } 1471 return selectionStatus; 1472 } 1473 } 1474 1475 /** 1476 * Utility class to serialize and deseriaize {@link WifiEnterpriseConfig} object to XML & 1477 * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. 1478 */ 1479 public static class WifiEnterpriseConfigXmlUtil { 1480 1481 /** 1482 * List of XML tags corresponding to WifiEnterpriseConfig object elements. 1483 */ 1484 public static final String XML_TAG_IDENTITY = "Identity"; 1485 public static final String XML_TAG_ANON_IDENTITY = "AnonIdentity"; 1486 public static final String XML_TAG_PASSWORD = "Password"; 1487 public static final String XML_TAG_CLIENT_CERT = "ClientCert"; 1488 public static final String XML_TAG_CA_CERT = "CaCert"; 1489 public static final String XML_TAG_SUBJECT_MATCH = "SubjectMatch"; 1490 public static final String XML_TAG_ENGINE = "Engine"; 1491 public static final String XML_TAG_ENGINE_ID = "EngineId"; 1492 public static final String XML_TAG_PRIVATE_KEY_ID = "PrivateKeyId"; 1493 public static final String XML_TAG_ALT_SUBJECT_MATCH = "AltSubjectMatch"; 1494 public static final String XML_TAG_DOM_SUFFIX_MATCH = "DomSuffixMatch"; 1495 public static final String XML_TAG_CA_PATH = "CaPath"; 1496 public static final String XML_TAG_EAP_METHOD = "EapMethod"; 1497 public static final String XML_TAG_PHASE2_METHOD = "Phase2Method"; 1498 public static final String XML_TAG_PLMN = "PLMN"; 1499 public static final String XML_TAG_REALM = "Realm"; 1500 public static final String XML_TAG_OCSP = "Ocsp"; 1501 public static final String XML_TAG_WAPI_CERT_SUITE = "WapiCertSuite"; 1502 public static final String XML_TAG_APP_INSTALLED_ROOT_CA_CERT = "AppInstalledRootCaCert"; 1503 public static final String XML_TAG_APP_INSTALLED_PRIVATE_KEY = "AppInstalledPrivateKey"; 1504 public static final String XML_TAG_KEYCHAIN_KEY_ALIAS = "KeyChainAlias"; 1505 public static final String XML_TAG_DECORATED_IDENTITY_PREFIX = "DecoratedIdentityPrefix"; 1506 public static final String XML_TAG_TRUST_ON_FIRST_USE = "TrustOnFirstUse"; 1507 public static final String XML_TAG_USER_APPROVE_NO_CA_CERT = "UserApproveNoCaCert"; 1508 public static final String XML_TAG_MINIMUM_TLS_VERSION = "MinimumTlsVersion"; 1509 1510 /** 1511 * Write password key to the XML stream. 1512 * 1513 * If encryptionUtil is null or if encryption fails for some reason, the password is stored 1514 * in plaintext, else the encrypted psk is stored. 1515 */ writePasswordToXml( XmlSerializer out, String password, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)1516 private static void writePasswordToXml( 1517 XmlSerializer out, String password, 1518 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 1519 throws XmlPullParserException, IOException { 1520 EncryptedData encryptedData = null; 1521 if (encryptionUtil != null) { 1522 if (password != null) { 1523 encryptedData = encryptionUtil.encrypt(password.getBytes()); 1524 if (encryptedData == null) { 1525 // We silently fail encryption failures! 1526 Log.wtf(TAG, "Encryption of password failed"); 1527 } 1528 } 1529 } 1530 if (encryptedData != null) { 1531 XmlUtil.writeNextSectionStart(out, XML_TAG_PASSWORD); 1532 EncryptedDataXmlUtil.writeToXml(out, encryptedData); 1533 XmlUtil.writeNextSectionEnd(out, XML_TAG_PASSWORD); 1534 } else { 1535 XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, password); 1536 } 1537 } 1538 1539 /** 1540 * Write the WifiEnterpriseConfig data elements from the provided config to the XML 1541 * stream. 1542 * 1543 * @param out XmlSerializer instance pointing to the XML stream. 1544 * @param enterpriseConfig WifiEnterpriseConfig object to be serialized. 1545 * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. 1546 */ writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)1547 public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig, 1548 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 1549 throws XmlPullParserException, IOException { 1550 XmlUtil.writeNextValue(out, XML_TAG_IDENTITY, 1551 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY)); 1552 XmlUtil.writeNextValue(out, XML_TAG_ANON_IDENTITY, 1553 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY)); 1554 writePasswordToXml( 1555 out, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY), 1556 encryptionUtil); 1557 XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERT, 1558 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY)); 1559 XmlUtil.writeNextValue(out, XML_TAG_CA_CERT, 1560 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY)); 1561 XmlUtil.writeNextValue(out, XML_TAG_SUBJECT_MATCH, 1562 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY)); 1563 XmlUtil.writeNextValue(out, XML_TAG_ENGINE, 1564 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY)); 1565 XmlUtil.writeNextValue(out, XML_TAG_ENGINE_ID, 1566 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY)); 1567 XmlUtil.writeNextValue(out, XML_TAG_PRIVATE_KEY_ID, 1568 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)); 1569 XmlUtil.writeNextValue(out, XML_TAG_ALT_SUBJECT_MATCH, 1570 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)); 1571 XmlUtil.writeNextValue(out, XML_TAG_DOM_SUFFIX_MATCH, 1572 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)); 1573 XmlUtil.writeNextValue(out, XML_TAG_CA_PATH, 1574 enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY)); 1575 XmlUtil.writeNextValue(out, XML_TAG_EAP_METHOD, enterpriseConfig.getEapMethod()); 1576 XmlUtil.writeNextValue(out, XML_TAG_PHASE2_METHOD, enterpriseConfig.getPhase2Method()); 1577 XmlUtil.writeNextValue(out, XML_TAG_PLMN, enterpriseConfig.getPlmn()); 1578 XmlUtil.writeNextValue(out, XML_TAG_REALM, enterpriseConfig.getRealm()); 1579 XmlUtil.writeNextValue(out, XML_TAG_OCSP, enterpriseConfig.getOcsp()); 1580 XmlUtil.writeNextValue(out, 1581 XML_TAG_WAPI_CERT_SUITE, enterpriseConfig.getWapiCertSuite()); 1582 XmlUtil.writeNextValue(out, XML_TAG_APP_INSTALLED_ROOT_CA_CERT, 1583 enterpriseConfig.isAppInstalledCaCert()); 1584 XmlUtil.writeNextValue(out, XML_TAG_APP_INSTALLED_PRIVATE_KEY, 1585 enterpriseConfig.isAppInstalledDeviceKeyAndCert()); 1586 XmlUtil.writeNextValue(out, XML_TAG_KEYCHAIN_KEY_ALIAS, 1587 enterpriseConfig.getClientKeyPairAliasInternal()); 1588 if (SdkLevel.isAtLeastS()) { 1589 XmlUtil.writeNextValue(out, XML_TAG_DECORATED_IDENTITY_PREFIX, 1590 enterpriseConfig.getDecoratedIdentityPrefix()); 1591 } 1592 XmlUtil.writeNextValue(out, XML_TAG_TRUST_ON_FIRST_USE, 1593 enterpriseConfig.isTrustOnFirstUseEnabled()); 1594 XmlUtil.writeNextValue(out, XML_TAG_USER_APPROVE_NO_CA_CERT, 1595 enterpriseConfig.isUserApproveNoCaCert()); 1596 XmlUtil.writeNextValue(out, XML_TAG_MINIMUM_TLS_VERSION, 1597 enterpriseConfig.getMinimumTlsVersion()); 1598 } 1599 1600 /** 1601 * Parses the data elements from the provided XML stream to a WifiEnterpriseConfig object. 1602 * 1603 * @param in XmlPullParser instance pointing to the XML stream. 1604 * @param outerTagDepth depth of the outer tag in the XML document. 1605 * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. 1606 * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. 1607 * @return WifiEnterpriseConfig object if parsing is successful, null otherwise. 1608 */ parseFromXml(XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)1609 public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth, 1610 boolean shouldExpectEncryptedCredentials, 1611 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 1612 throws XmlPullParserException, IOException { 1613 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 1614 1615 // Loop through and parse out all the elements from the stream within this section. 1616 while (XmlUtilHelper.nextElementWithin(in, outerTagDepth)) { 1617 if (in.getAttributeValue(null, "name") != null) { 1618 // Value elements. 1619 String[] valueName = new String[1]; 1620 Object value = XmlUtil.readCurrentValue(in, valueName); 1621 if (valueName[0] == null) { 1622 throw new XmlPullParserException("Missing value name"); 1623 } 1624 switch (valueName[0]) { 1625 case XML_TAG_IDENTITY: 1626 enterpriseConfig.setFieldValue( 1627 WifiEnterpriseConfig.IDENTITY_KEY, (String) value); 1628 break; 1629 case XML_TAG_ANON_IDENTITY: 1630 enterpriseConfig.setFieldValue( 1631 WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value); 1632 break; 1633 case XML_TAG_PASSWORD: 1634 enterpriseConfig.setFieldValue( 1635 WifiEnterpriseConfig.PASSWORD_KEY, (String) value); 1636 if (shouldExpectEncryptedCredentials 1637 && !TextUtils.isEmpty(enterpriseConfig.getFieldValue( 1638 WifiEnterpriseConfig.PASSWORD_KEY))) { 1639 // Indicates that encryption of password failed when it was last 1640 // written. 1641 Log.e(TAG, "password value not expected"); 1642 } 1643 break; 1644 case XML_TAG_CLIENT_CERT: 1645 enterpriseConfig.setFieldValue( 1646 WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value); 1647 break; 1648 case XML_TAG_CA_CERT: 1649 enterpriseConfig.setFieldValue( 1650 WifiEnterpriseConfig.CA_CERT_KEY, (String) value); 1651 break; 1652 case XML_TAG_SUBJECT_MATCH: 1653 enterpriseConfig.setFieldValue( 1654 WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value); 1655 break; 1656 case XML_TAG_ENGINE: 1657 enterpriseConfig.setFieldValue( 1658 WifiEnterpriseConfig.ENGINE_KEY, (String) value); 1659 break; 1660 case XML_TAG_ENGINE_ID: 1661 enterpriseConfig.setFieldValue( 1662 WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value); 1663 break; 1664 case XML_TAG_PRIVATE_KEY_ID: 1665 enterpriseConfig.setFieldValue( 1666 WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value); 1667 break; 1668 case XML_TAG_ALT_SUBJECT_MATCH: 1669 enterpriseConfig.setFieldValue( 1670 WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value); 1671 break; 1672 case XML_TAG_DOM_SUFFIX_MATCH: 1673 enterpriseConfig.setFieldValue( 1674 WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value); 1675 break; 1676 case XML_TAG_CA_PATH: 1677 enterpriseConfig.setFieldValue( 1678 WifiEnterpriseConfig.CA_PATH_KEY, (String) value); 1679 break; 1680 case XML_TAG_OCSP: 1681 enterpriseConfig.setOcsp((int) value); 1682 break; 1683 case XML_TAG_EAP_METHOD: 1684 enterpriseConfig.setEapMethod((int) value); 1685 break; 1686 case XML_TAG_PHASE2_METHOD: 1687 enterpriseConfig.setPhase2Method((int) value); 1688 break; 1689 case XML_TAG_PLMN: 1690 enterpriseConfig.setPlmn((String) value); 1691 break; 1692 case XML_TAG_REALM: 1693 enterpriseConfig.setRealm((String) value); 1694 break; 1695 case XML_TAG_WAPI_CERT_SUITE: 1696 enterpriseConfig.setWapiCertSuite((String) value); 1697 break; 1698 case XML_TAG_APP_INSTALLED_ROOT_CA_CERT: 1699 enterpriseConfig.initIsAppInstalledCaCert((boolean) value); 1700 break; 1701 case XML_TAG_APP_INSTALLED_PRIVATE_KEY: 1702 enterpriseConfig.initIsAppInstalledDeviceKeyAndCert((boolean) value); 1703 break; 1704 case XML_TAG_KEYCHAIN_KEY_ALIAS: 1705 if (SdkLevel.isAtLeastS()) { 1706 enterpriseConfig.setClientKeyPairAlias((String) value); 1707 } 1708 break; 1709 case XML_TAG_DECORATED_IDENTITY_PREFIX: 1710 if (SdkLevel.isAtLeastS()) { 1711 enterpriseConfig.setDecoratedIdentityPrefix((String) value); 1712 } 1713 break; 1714 case XML_TAG_TRUST_ON_FIRST_USE: 1715 enterpriseConfig.enableTrustOnFirstUse((boolean) value); 1716 break; 1717 case XML_TAG_USER_APPROVE_NO_CA_CERT: 1718 enterpriseConfig.setUserApproveNoCaCert((boolean) value); 1719 break; 1720 case XML_TAG_MINIMUM_TLS_VERSION: 1721 enterpriseConfig.setMinimumTlsVersion((int) value); 1722 break; 1723 default: 1724 Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); 1725 break; 1726 } 1727 } else { 1728 String tagName = in.getName(); 1729 if (tagName == null) { 1730 throw new XmlPullParserException("Unexpected null tag found"); 1731 } 1732 switch (tagName) { 1733 case XML_TAG_PASSWORD: 1734 if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { 1735 throw new XmlPullParserException( 1736 "encrypted password section not expected"); 1737 } 1738 EncryptedData encryptedData = 1739 EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); 1740 byte[] passwordBytes = encryptionUtil.decrypt(encryptedData); 1741 if (passwordBytes == null) { 1742 Log.wtf(TAG, "Decryption of password failed"); 1743 } else { 1744 enterpriseConfig.setFieldValue( 1745 WifiEnterpriseConfig.PASSWORD_KEY, 1746 new String(passwordBytes)); 1747 } 1748 break; 1749 default: 1750 Log.w(TAG, "Ignoring unknown tag name found: " + tagName); 1751 break; 1752 } 1753 } 1754 } 1755 return enterpriseConfig; 1756 } 1757 } 1758 1759 /** 1760 * Utility class to serialize and deseriaize {@link EncryptedData} object to XML & 1761 * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. 1762 */ 1763 public static class EncryptedDataXmlUtil { 1764 /** 1765 * List of XML tags corresponding to EncryptedData object elements. 1766 */ 1767 private static final String XML_TAG_ENCRYPTED_DATA = "EncryptedData"; 1768 private static final String XML_TAG_IV = "IV"; 1769 1770 /** 1771 * Write the NetworkSelectionStatus data elements from the provided status to the XML 1772 * stream. 1773 * 1774 * @param out XmlSerializer instance pointing to the XML stream. 1775 * @param encryptedData EncryptedData object to be serialized. 1776 */ writeToXml(XmlSerializer out, EncryptedData encryptedData)1777 public static void writeToXml(XmlSerializer out, EncryptedData encryptedData) 1778 throws XmlPullParserException, IOException { 1779 XmlUtil.writeNextValue( 1780 out, XML_TAG_ENCRYPTED_DATA, encryptedData.getEncryptedData()); 1781 XmlUtil.writeNextValue(out, XML_TAG_IV, encryptedData.getIv()); 1782 } 1783 1784 /** 1785 * Parses the EncryptedData data elements from the provided XML stream to a 1786 * EncryptedData object. 1787 * 1788 * @param in XmlPullParser instance pointing to the XML stream. 1789 * @param outerTagDepth depth of the outer tag in the XML document. 1790 * @return EncryptedData object if parsing is successful, null otherwise. 1791 */ parseFromXml(XmlPullParser in, int outerTagDepth)1792 public static EncryptedData parseFromXml(XmlPullParser in, int outerTagDepth) 1793 throws XmlPullParserException, IOException { 1794 byte[] encryptedData = null; 1795 byte[] iv = null; 1796 1797 // Loop through and parse out all the elements from the stream within this section. 1798 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 1799 String[] valueName = new String[1]; 1800 Object value = XmlUtil.readCurrentValue(in, valueName); 1801 if (valueName[0] == null) { 1802 throw new XmlPullParserException("Missing value name"); 1803 } 1804 switch (valueName[0]) { 1805 case XML_TAG_ENCRYPTED_DATA: 1806 encryptedData = (byte[]) value; 1807 break; 1808 case XML_TAG_IV: 1809 iv = (byte[]) value; 1810 break; 1811 default: 1812 Log.e(TAG, "Unknown value name found: " + valueName[0]); 1813 break; 1814 } 1815 } 1816 return new EncryptedData(encryptedData, iv); 1817 } 1818 1819 /** 1820 * Parses the EncryptedData data elements arrays from the provided XML stream to a list of 1821 * EncryptedData object. 1822 * 1823 * @param in XmlPullParser instance pointing to the XML stream. 1824 * @param outerTagDepth depth of the outer tag in the XML document. 1825 * @return List of encryptedData object if parsing is successful, empty otherwise. 1826 */ parseListFromXml(XmlPullParser in, int outerTagDepth)1827 public static @NonNull List<EncryptedData> parseListFromXml(XmlPullParser in, 1828 int outerTagDepth) throws XmlPullParserException, IOException { 1829 List<EncryptedData> encryptedDataList = new ArrayList<>(); 1830 // Loop through and parse out all the elements from the stream within this section. 1831 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 1832 if (in.getAttributeValue(null, "name") != null) { 1833 String[] valueName = new String[1]; 1834 Object value = XmlUtil.readCurrentValue(in, valueName); 1835 if (valueName[0] == null) { 1836 throw new XmlPullParserException("Missing value name"); 1837 } 1838 byte[] encryptedData; 1839 byte[] iv; 1840 if (XML_TAG_ENCRYPTED_DATA.equals(valueName[0])) { 1841 encryptedData = (byte[]) value; 1842 if (!XmlUtil.isNextSectionEnd(in, outerTagDepth) && in.getAttributeValue( 1843 null, "name") != null) { 1844 value = XmlUtil.readCurrentValue(in, valueName); 1845 if (valueName[0] == null) { 1846 throw new XmlPullParserException("Missing value name"); 1847 } 1848 if (XML_TAG_IV.equals(valueName[0])) { 1849 iv = (byte[]) value; 1850 encryptedDataList.add(new EncryptedData(encryptedData, iv)); 1851 } 1852 } 1853 } 1854 } 1855 } 1856 return encryptedDataList; 1857 } 1858 } 1859 nextElementWithin(XmlPullParser parser, int outerDepth)1860 public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) 1861 throws IOException, XmlPullParserException { 1862 return XmlUtilHelper.nextElementWithin(parser, outerDepth); 1863 } 1864 1865 /** 1866 * Utility class to serialize and deseriaize {@link SoftApConfiguration} object to XML 1867 * & vice versa. This is used by both {@link com.android.server.wifi.SoftApStore} modules. 1868 */ 1869 public static class SoftApConfigurationXmlUtil { 1870 /** 1871 * List of XML tags corresponding to SoftApConfiguration object elements. 1872 */ 1873 public static final String XML_TAG_CLIENT_MACADDRESS = "ClientMacAddress"; 1874 public static final String XML_TAG_BAND_CHANNEL = "BandChannel"; 1875 public static final String XML_TAG_SSID = "SSID"; // Use XML_TAG_WIFI_SSID instead 1876 public static final String XML_TAG_WIFI_SSID = "WifiSsid"; 1877 public static final String XML_TAG_BSSID = "Bssid"; 1878 public static final String XML_TAG_BAND = "Band"; 1879 public static final String XML_TAG_CHANNEL = "Channel"; 1880 public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; 1881 public static final String XML_TAG_SECURITY_TYPE = "SecurityType"; 1882 public static final String XML_TAG_WPA2_PASSPHRASE = "Wpa2Passphrase"; 1883 public static final String XML_TAG_AP_BAND = "ApBand"; 1884 public static final String XML_TAG_PASSPHRASE = "Passphrase"; 1885 public static final String XML_TAG_MAX_NUMBER_OF_CLIENTS = "MaxNumberOfClients"; 1886 public static final String XML_TAG_AUTO_SHUTDOWN_ENABLED = "AutoShutdownEnabled"; 1887 public static final String XML_TAG_SHUTDOWN_TIMEOUT_MILLIS = "ShutdownTimeoutMillis"; 1888 public static final String XML_TAG_CLIENT_CONTROL_BY_USER = "ClientControlByUser"; 1889 public static final String XML_TAG_BLOCKED_CLIENT_LIST = "BlockedClientList"; 1890 public static final String XML_TAG_ALLOWED_CLIENT_LIST = "AllowedClientList"; 1891 public static final String XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED = 1892 "BridgedModeOpportunisticShutdownEnabled"; 1893 public static final String XML_TAG_MAC_RAMDOMIZATION_SETTING = "MacRandomizationSetting"; 1894 public static final String XML_TAG_BAND_CHANNEL_MAP = "BandChannelMap"; 1895 public static final String XML_TAG_80211_AX_ENABLED = "80211axEnabled"; 1896 public static final String XML_TAG_80211_BE_ENABLED = "80211beEnabled"; 1897 public static final String XML_TAG_USER_CONFIGURATION = "UserConfiguration"; 1898 public static final String XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_TIMEOUT_MILLIS = 1899 "BridgedModeOpportunisticShutdownTimeoutMillis"; 1900 public static final String XML_TAG_VENDOR_ELEMENT = "VendorElement"; 1901 public static final String XML_TAG_VENDOR_ELEMENTS = "VendorElements"; 1902 public static final String XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS = 1903 "PersistentRandomizedMacAddress"; 1904 1905 1906 /** 1907 * Parses the client list from the provided XML stream to a ArrayList object. 1908 * 1909 * @param in XmlPullParser instance pointing to the XML stream. 1910 * @param outerTagDepth depth of the outer tag in the XML document. 1911 * @return ArrayList object if parsing is successful, null otherwise. 1912 */ parseClientListFromXml(XmlPullParser in, int outerTagDepth)1913 public static List<MacAddress> parseClientListFromXml(XmlPullParser in, 1914 int outerTagDepth) throws XmlPullParserException, IOException, 1915 IllegalArgumentException { 1916 List<MacAddress> clientList = new ArrayList<>(); 1917 // Loop through and parse out all the elements from the stream within this section. 1918 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 1919 String[] valueName = new String[1]; 1920 Object value = XmlUtil.readCurrentValue(in, valueName); 1921 if (valueName[0] == null) { 1922 throw new XmlPullParserException("Missing value name"); 1923 } 1924 switch (valueName[0]) { 1925 case XML_TAG_CLIENT_MACADDRESS: 1926 MacAddress client = MacAddress.fromString((String) value); 1927 clientList.add(client); 1928 break; 1929 default: 1930 Log.e(TAG, "Unknown value name found: " + valueName[0]); 1931 break; 1932 } 1933 } 1934 return clientList; 1935 } 1936 1937 /** 1938 * Write the SoftApConfiguration client control list data elements 1939 * from the provided list to the XML stream. 1940 * 1941 * @param out XmlSerializer instance pointing to the XML stream. 1942 * @param clientList Client list object to be serialized. 1943 */ writeClientListToXml(XmlSerializer out, List<MacAddress> clientList)1944 public static void writeClientListToXml(XmlSerializer out, List<MacAddress> clientList) 1945 throws XmlPullParserException, IOException { 1946 for (MacAddress mac: clientList) { 1947 XmlUtil.writeNextValue(out, XML_TAG_CLIENT_MACADDRESS, mac.toString()); 1948 } 1949 } 1950 1951 /** 1952 * Write the SoftApConfiguration vendor elements list information elements to the XML 1953 * 1954 * @param out XmlSerializer instance pointing to the XML stream 1955 * @param elements Vendor elements list 1956 */ writeVendorElementsSetToXml( XmlSerializer out, List<ScanResult.InformationElement> elements)1957 public static void writeVendorElementsSetToXml( 1958 XmlSerializer out, List<ScanResult.InformationElement> elements) 1959 throws XmlPullParserException, IOException { 1960 for (ScanResult.InformationElement e : elements) { 1961 XmlUtil.writeNextValue(out, XML_TAG_VENDOR_ELEMENT, 1962 InformationElementUtil.toHexString(e)); 1963 } 1964 } 1965 1966 /** 1967 * Parses the vendor elements from the provided XML stream to HashSet object. 1968 * 1969 * @param in XmlPullParser instance pointing to the XML stream 1970 * @param outerTagDepth depth of the outer tag in the XML document 1971 * @return HashSet object if parsing is successful, empty set otherwise 1972 */ parseVendorElementsFromXml( XmlPullParser in, int outerTagDepth)1973 public static List<ScanResult.InformationElement> parseVendorElementsFromXml( 1974 XmlPullParser in, int outerTagDepth) 1975 throws XmlPullParserException, IOException, IllegalArgumentException { 1976 List<ScanResult.InformationElement> elements = new ArrayList<>(); 1977 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 1978 String[] valueName = new String[1]; 1979 Object value = XmlUtil.readCurrentValue(in, valueName); 1980 if (valueName[0] == null) { 1981 throw new XmlPullParserException("Missing value name"); 1982 } 1983 if (XML_TAG_VENDOR_ELEMENT.equals(valueName[0])) { 1984 ScanResult.InformationElement[] data = 1985 InformationElementUtil.parseInformationElements((String) value); 1986 elements.addAll(Arrays.asList(data)); 1987 } else { 1988 Log.e(TAG, "Unknown value name found: " + valueName[0]); 1989 } 1990 } 1991 return elements; 1992 } 1993 1994 /** 1995 * Parses the band and channel from the provided XML stream to a SparseIntArray object. 1996 * 1997 * @param in XmlPullParser instance pointing to the XML stream. 1998 * @param outerTagDepth depth of the outer tag in the XML document. 1999 * @return SparseIntArray object if parsing is successful, null otherwise. 2000 */ parseChannelsFromXml(XmlPullParser in, int outerTagDepth)2001 public static SparseIntArray parseChannelsFromXml(XmlPullParser in, 2002 int outerTagDepth) throws XmlPullParserException, IOException, 2003 IllegalArgumentException { 2004 SparseIntArray channels = new SparseIntArray(); 2005 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 2006 int band = ApConfigUtil.INVALID_VALUE_FOR_BAND_OR_CHANNEL; 2007 int channel = ApConfigUtil.INVALID_VALUE_FOR_BAND_OR_CHANNEL; 2008 switch (in.getName()) { 2009 case XML_TAG_BAND_CHANNEL: 2010 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth + 1)) { 2011 String[] valueName = new String[1]; 2012 Object value = XmlUtil.readCurrentValue(in, valueName); 2013 if (valueName[0] == null) { 2014 throw new XmlPullParserException("Missing value name"); 2015 } 2016 switch (valueName[0]) { 2017 case XML_TAG_BAND: 2018 band = (int) value; 2019 break; 2020 case XML_TAG_CHANNEL: 2021 channel = (int) value; 2022 break; 2023 default: 2024 Log.e(TAG, "Unknown value name found: " + valueName[0]); 2025 break; 2026 } 2027 } 2028 channels.put(band, channel); 2029 break; 2030 } 2031 } 2032 return channels; 2033 } 2034 2035 /** 2036 * Write the SoftApConfiguration channels data elements 2037 * from the provided SparseIntArray to the XML stream. 2038 * 2039 * @param out XmlSerializer instance pointing to the XML stream. 2040 * @param channels SparseIntArray, which includes bands and channels, to be serialized. 2041 */ writeChannelsToXml(XmlSerializer out, SparseIntArray channels)2042 public static void writeChannelsToXml(XmlSerializer out, SparseIntArray channels) 2043 throws XmlPullParserException, IOException { 2044 for (int i = 0; i < channels.size(); i++) { 2045 XmlUtil.writeNextSectionStart(out, XML_TAG_BAND_CHANNEL); 2046 XmlUtil.writeNextValue(out, XML_TAG_BAND, channels.keyAt(i)); 2047 XmlUtil.writeNextValue(out, XML_TAG_CHANNEL, channels.valueAt(i)); 2048 XmlUtil.writeNextSectionEnd(out, XML_TAG_BAND_CHANNEL); 2049 } 2050 } 2051 2052 /** 2053 * Write the SoftApConfiguration data elements to the XML stream. 2054 * 2055 * @param out XmlSerializer instance pointing to the XML stream. 2056 * @param softApConfig configuration of the Soft AP. 2057 */ writeSoftApConfigurationToXml(@onNull XmlSerializer out, @NonNull SoftApConfiguration softApConfig, WifiConfigStoreEncryptionUtil encryptionUtil)2058 public static void writeSoftApConfigurationToXml(@NonNull XmlSerializer out, 2059 @NonNull SoftApConfiguration softApConfig, 2060 WifiConfigStoreEncryptionUtil encryptionUtil) 2061 throws XmlPullParserException, IOException { 2062 if (softApConfig.getWifiSsid() != null) { 2063 XmlUtil.writeNextValue(out, XML_TAG_WIFI_SSID, 2064 softApConfig.getWifiSsid().toString()); 2065 } 2066 if (softApConfig.getBssid() != null) { 2067 XmlUtil.writeNextValue(out, XML_TAG_BSSID, softApConfig.getBssid().toString()); 2068 } 2069 if (!SdkLevel.isAtLeastS()) { 2070 // Band and channel change to store in Tag:BandChannelMap from S. 2071 XmlUtil.writeNextValue(out, XML_TAG_AP_BAND, softApConfig.getBand()); 2072 XmlUtil.writeNextValue(out, XML_TAG_CHANNEL, softApConfig.getChannel()); 2073 } 2074 XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, softApConfig.isHiddenSsid()); 2075 XmlUtil.writeNextValue(out, XML_TAG_SECURITY_TYPE, softApConfig.getSecurityType()); 2076 if (!ApConfigUtil.isNonPasswordAP(softApConfig.getSecurityType())) { 2077 XmlUtil.writeSoftApPassphraseToXml(out, softApConfig.getPassphrase(), 2078 encryptionUtil); 2079 } 2080 2081 XmlUtil.writeNextValue(out, XML_TAG_MAX_NUMBER_OF_CLIENTS, 2082 softApConfig.getMaxNumberOfClients()); 2083 XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CONTROL_BY_USER, 2084 softApConfig.isClientControlByUserEnabled()); 2085 XmlUtil.writeNextValue(out, XML_TAG_AUTO_SHUTDOWN_ENABLED, 2086 softApConfig.isAutoShutdownEnabled()); 2087 XmlUtil.writeNextValue(out, XML_TAG_SHUTDOWN_TIMEOUT_MILLIS, 2088 softApConfig.getShutdownTimeoutMillis()); 2089 XmlUtil.writeNextSectionStart(out, XML_TAG_BLOCKED_CLIENT_LIST); 2090 XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out, 2091 softApConfig.getBlockedClientList()); 2092 XmlUtil.writeNextSectionEnd(out, XML_TAG_BLOCKED_CLIENT_LIST); 2093 2094 XmlUtil.writeNextSectionStart(out, XML_TAG_ALLOWED_CLIENT_LIST); 2095 XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out, 2096 softApConfig.getAllowedClientList()); 2097 XmlUtil.writeNextSectionEnd(out, XML_TAG_ALLOWED_CLIENT_LIST); 2098 if (SdkLevel.isAtLeastS()) { 2099 XmlUtil.writeNextValue(out, XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED, 2100 softApConfig.isBridgedModeOpportunisticShutdownEnabled()); 2101 XmlUtil.writeNextValue(out, XML_TAG_MAC_RAMDOMIZATION_SETTING, 2102 softApConfig.getMacRandomizationSetting()); 2103 2104 XmlUtil.writeNextSectionStart(out, XML_TAG_BAND_CHANNEL_MAP); 2105 XmlUtil.SoftApConfigurationXmlUtil.writeChannelsToXml(out, 2106 softApConfig.getChannels()); 2107 XmlUtil.writeNextSectionEnd(out, XML_TAG_BAND_CHANNEL_MAP); 2108 XmlUtil.writeNextValue(out, XML_TAG_80211_AX_ENABLED, 2109 softApConfig.isIeee80211axEnabled()); 2110 XmlUtil.writeNextValue(out, XML_TAG_USER_CONFIGURATION, 2111 softApConfig.isUserConfiguration()); 2112 } 2113 if (SdkLevel.isAtLeastT()) { 2114 XmlUtil.writeNextValue(out, 2115 XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_TIMEOUT_MILLIS, 2116 softApConfig.getBridgedModeOpportunisticShutdownTimeoutMillisInternal()); 2117 XmlUtil.writeNextSectionStart(out, XML_TAG_VENDOR_ELEMENTS); 2118 XmlUtil.SoftApConfigurationXmlUtil.writeVendorElementsSetToXml(out, 2119 softApConfig.getVendorElementsInternal()); 2120 XmlUtil.writeNextSectionEnd(out, XML_TAG_VENDOR_ELEMENTS); 2121 XmlUtil.writeNextValue(out, XML_TAG_80211_BE_ENABLED, 2122 softApConfig.isIeee80211beEnabled()); 2123 if (softApConfig.getPersistentRandomizedMacAddress() != null) { 2124 XmlUtil.writeNextValue(out, XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS, 2125 softApConfig.getPersistentRandomizedMacAddress().toString()); 2126 } 2127 } 2128 } // End of writeSoftApConfigurationToXml 2129 2130 /** 2131 * Returns configuration of the SoftAp from the XML stream. 2132 * 2133 * @param in XmlPullParser instance pointing to the XML stream. 2134 * @param outerTagDepth depth of the outer tag in the XML document. 2135 * @param settingsMigrationDataHolder the class instance of SettingsMigrationDataHolder 2136 */ 2137 @Nullable parseFromXml(XmlPullParser in, int outerTagDepth, SettingsMigrationDataHolder settingsMigrationDataHolder, boolean shouldExpectEncryptedCredentials, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)2138 public static SoftApConfiguration parseFromXml(XmlPullParser in, int outerTagDepth, 2139 SettingsMigrationDataHolder settingsMigrationDataHolder, 2140 boolean shouldExpectEncryptedCredentials, 2141 @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) 2142 throws XmlPullParserException, IOException { 2143 SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); 2144 int securityType = SoftApConfiguration.SECURITY_TYPE_OPEN; 2145 String passphrase = null; 2146 // SSID may be retrieved from the old encoding (XML_TAG_SSID) or the new encoding 2147 // (XML_TAG_WIFI_SSID). 2148 boolean hasSsid = false; 2149 String bssid = null; 2150 // Note that, during deserialization, we may read the old band encoding (XML_TAG_BAND) 2151 // or the new band encoding (XML_TAG_AP_BAND) that is used after the introduction of the 2152 // 6GHz band. If the old encoding is found, a conversion is done. 2153 int channel = -1; 2154 int apBand = -1; 2155 boolean hasBandChannelMap = false; 2156 List<MacAddress> blockedList = new ArrayList<>(); 2157 List<MacAddress> allowedList = new ArrayList<>(); 2158 boolean autoShutdownEnabledTagPresent = false; 2159 try { 2160 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 2161 if (in.getAttributeValue(null, "name") != null) { 2162 String[] valueName = new String[1]; 2163 Object value = XmlUtil.readCurrentValue(in, valueName); 2164 if (TextUtils.isEmpty(valueName[0])) { 2165 throw new XmlPullParserException("Missing value name"); 2166 } 2167 switch (valueName[0]) { 2168 case XML_TAG_SSID: 2169 hasSsid = true; 2170 softApConfigBuilder.setSsid((String) value); 2171 break; 2172 case XML_TAG_WIFI_SSID: 2173 hasSsid = true; 2174 final WifiSsid wifiSsid = WifiSsid.fromString((String) value); 2175 if (SdkLevel.isAtLeastT()) { 2176 softApConfigBuilder.setWifiSsid(wifiSsid); 2177 } else { 2178 // If the SSID is non-UTF-8, then use WifiManager.UNKNOWN_SSID. 2179 // This should not happen since non-UTF-8 SSIDs may only be set 2180 // with SoftApConfiguration#Builder#setWifiSsid(WifiSsid), 2181 // which is only available in T and above. 2182 final CharSequence utf8Ssid = wifiSsid.getUtf8Text(); 2183 softApConfigBuilder.setSsid(utf8Ssid != null 2184 ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID); 2185 } 2186 break; 2187 case XML_TAG_BSSID: 2188 bssid = (String) value; 2189 softApConfigBuilder.setBssid(MacAddress.fromString(bssid)); 2190 break; 2191 case XML_TAG_BAND: 2192 apBand = ApConfigUtil.convertWifiConfigBandToSoftApConfigBand( 2193 (int) value); 2194 break; 2195 case XML_TAG_AP_BAND: 2196 apBand = (int) value; 2197 break; 2198 case XML_TAG_CHANNEL: 2199 channel = (int) value; 2200 break; 2201 case XML_TAG_HIDDEN_SSID: 2202 softApConfigBuilder.setHiddenSsid((boolean) value); 2203 break; 2204 case XML_TAG_SECURITY_TYPE: 2205 securityType = (int) value; 2206 break; 2207 case XML_TAG_WPA2_PASSPHRASE: 2208 case XML_TAG_PASSPHRASE: 2209 passphrase = (String) value; 2210 break; 2211 case XML_TAG_MAX_NUMBER_OF_CLIENTS: 2212 softApConfigBuilder.setMaxNumberOfClients((int) value); 2213 break; 2214 case XML_TAG_AUTO_SHUTDOWN_ENABLED: 2215 softApConfigBuilder.setAutoShutdownEnabled((boolean) value); 2216 autoShutdownEnabledTagPresent = true; 2217 break; 2218 case XML_TAG_SHUTDOWN_TIMEOUT_MILLIS: 2219 long shutDownMillis = 0; 2220 if (value instanceof Integer) { 2221 shutDownMillis = Long.valueOf((int) value); 2222 } else if (value instanceof Long) { 2223 shutDownMillis = (long) value; 2224 } 2225 if (shutDownMillis == 0 2226 && CompatChanges.isChangeEnabled( 2227 SoftApConfiguration.REMOVE_ZERO_FOR_TIMEOUT_SETTING)) { 2228 shutDownMillis = SoftApConfiguration.DEFAULT_TIMEOUT; 2229 } 2230 softApConfigBuilder.setShutdownTimeoutMillis(shutDownMillis); 2231 break; 2232 case XML_TAG_CLIENT_CONTROL_BY_USER: 2233 softApConfigBuilder.setClientControlByUserEnabled((boolean) value); 2234 break; 2235 case XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED: 2236 if (SdkLevel.isAtLeastS()) { 2237 softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled( 2238 (boolean) value); 2239 } 2240 break; 2241 case XML_TAG_MAC_RAMDOMIZATION_SETTING: 2242 if (SdkLevel.isAtLeastS()) { 2243 softApConfigBuilder.setMacRandomizationSetting((int) value); 2244 } 2245 break; 2246 case XML_TAG_80211_AX_ENABLED: 2247 if (SdkLevel.isAtLeastS()) { 2248 softApConfigBuilder.setIeee80211axEnabled((boolean) value); 2249 } 2250 break; 2251 case XML_TAG_80211_BE_ENABLED: 2252 if (SdkLevel.isAtLeastT()) { 2253 softApConfigBuilder.setIeee80211beEnabled((boolean) value); 2254 } 2255 break; 2256 case XML_TAG_USER_CONFIGURATION: 2257 if (SdkLevel.isAtLeastS()) { 2258 softApConfigBuilder.setUserConfiguration((boolean) value); 2259 } 2260 break; 2261 case XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_TIMEOUT_MILLIS: 2262 if (SdkLevel.isAtLeastT()) { 2263 long bridgedTimeout = (long) value; 2264 bridgedTimeout = bridgedTimeout == 0 2265 ? SoftApConfiguration.DEFAULT_TIMEOUT : bridgedTimeout; 2266 softApConfigBuilder 2267 .setBridgedModeOpportunisticShutdownTimeoutMillis( 2268 bridgedTimeout); 2269 } 2270 break; 2271 case XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS: 2272 if (SdkLevel.isAtLeastT()) { 2273 softApConfigBuilder.setRandomizedMacAddress( 2274 MacAddress.fromString((String) value)); 2275 } 2276 break; 2277 default: 2278 Log.w(TAG, "Ignoring unknown value name " + valueName[0]); 2279 break; 2280 } 2281 } else { 2282 String tagName = in.getName(); 2283 List<MacAddress> parseredList; 2284 if (tagName == null) { 2285 throw new XmlPullParserException("Unexpected null tag found"); 2286 } 2287 switch (tagName) { 2288 case XML_TAG_BLOCKED_CLIENT_LIST: 2289 parseredList = 2290 XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml( 2291 in, outerTagDepth + 1); 2292 if (parseredList != null) { 2293 blockedList = new ArrayList<>(parseredList); 2294 } 2295 break; 2296 case XML_TAG_ALLOWED_CLIENT_LIST: 2297 parseredList = 2298 XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml( 2299 in, outerTagDepth + 1); 2300 if (parseredList != null) { 2301 allowedList = new ArrayList<>(parseredList); 2302 } 2303 break; 2304 case XML_TAG_BAND_CHANNEL_MAP: 2305 if (SdkLevel.isAtLeastS()) { 2306 hasBandChannelMap = true; 2307 SparseIntArray channels = XmlUtil.SoftApConfigurationXmlUtil 2308 .parseChannelsFromXml(in, outerTagDepth + 1); 2309 softApConfigBuilder.setChannels(channels); 2310 } 2311 break; 2312 case XML_TAG_VENDOR_ELEMENTS: 2313 if (SdkLevel.isAtLeastT()) { 2314 softApConfigBuilder.setVendorElements( 2315 SoftApConfigurationXmlUtil.parseVendorElementsFromXml( 2316 in, outerTagDepth + 1)); 2317 } 2318 break; 2319 case XML_TAG_PASSPHRASE: 2320 passphrase = readSoftApPassphraseFromXml(in, outerTagDepth, 2321 shouldExpectEncryptedCredentials, encryptionUtil); 2322 break; 2323 default: 2324 Log.w(TAG, "Ignoring unknown tag found: " + tagName); 2325 break; 2326 } 2327 } 2328 } 2329 softApConfigBuilder.setBlockedClientList(blockedList); 2330 softApConfigBuilder.setAllowedClientList(allowedList); 2331 if (!hasBandChannelMap) { 2332 // Set channel and band 2333 if (channel == 0) { 2334 softApConfigBuilder.setBand(apBand); 2335 } else { 2336 softApConfigBuilder.setChannel(channel, apBand); 2337 } 2338 } 2339 2340 // We should at least have an SSID restored from store. 2341 if (!hasSsid) { 2342 Log.e(TAG, "Failed to parse SSID"); 2343 return null; 2344 } 2345 if (ApConfigUtil.isNonPasswordAP(securityType)) { 2346 softApConfigBuilder.setPassphrase(null, securityType); 2347 } else { 2348 softApConfigBuilder.setPassphrase(passphrase, securityType); 2349 } 2350 if (!autoShutdownEnabledTagPresent) { 2351 // Migrate data out of settings. 2352 WifiMigration.SettingsMigrationData migrationData = 2353 settingsMigrationDataHolder.retrieveData(); 2354 if (migrationData == null) { 2355 Log.e(TAG, "No migration data present"); 2356 } else { 2357 softApConfigBuilder.setAutoShutdownEnabled( 2358 migrationData.isSoftApTimeoutEnabled()); 2359 } 2360 } 2361 if (bssid != null && SdkLevel.isAtLeastS()) { 2362 // Force MAC randomization setting to none when BSSID is configured 2363 softApConfigBuilder.setMacRandomizationSetting( 2364 SoftApConfiguration.RANDOMIZATION_NONE); 2365 } 2366 } catch (IllegalArgumentException e) { 2367 Log.e(TAG, "Failed to parse configuration " + e); 2368 return null; 2369 } 2370 return softApConfigBuilder.build(); 2371 } // End of parseFromXml 2372 } 2373 writeSoftApPassphraseToXml( XmlSerializer out, String passphrase, WifiConfigStoreEncryptionUtil encryptionUtil)2374 private static void writeSoftApPassphraseToXml( 2375 XmlSerializer out, String passphrase, WifiConfigStoreEncryptionUtil encryptionUtil) 2376 throws XmlPullParserException, IOException { 2377 EncryptedData encryptedData = null; 2378 if (encryptionUtil != null && passphrase != null) { 2379 encryptedData = encryptionUtil.encrypt(passphrase.getBytes()); 2380 if (encryptedData == null) { 2381 // We silently fail encryption failures! 2382 Log.wtf(TAG, "Encryption of softAp passphrase failed"); 2383 } 2384 } 2385 if (encryptedData != null) { 2386 writeNextSectionStart(out, SoftApConfigurationXmlUtil.XML_TAG_PASSPHRASE); 2387 EncryptedDataXmlUtil.writeToXml(out, encryptedData); 2388 writeNextSectionEnd(out, SoftApConfigurationXmlUtil.XML_TAG_PASSPHRASE); 2389 } else { 2390 writeNextValue(out, SoftApConfigurationXmlUtil.XML_TAG_PASSPHRASE, passphrase); 2391 } 2392 } 2393 readSoftApPassphraseFromXml(XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, WifiConfigStoreEncryptionUtil encryptionUtil)2394 private static String readSoftApPassphraseFromXml(XmlPullParser in, int outerTagDepth, 2395 boolean shouldExpectEncryptedCredentials, WifiConfigStoreEncryptionUtil encryptionUtil) 2396 throws XmlPullParserException, IOException { 2397 if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { 2398 throw new XmlPullParserException( 2399 "Encrypted passphraseBytes section not expected"); 2400 } 2401 EncryptedData encryptedData = 2402 XmlUtil.EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); 2403 byte[] passphraseBytes = encryptionUtil.decrypt(encryptedData); 2404 if (passphraseBytes == null) { 2405 Log.wtf(TAG, "Decryption of passphraseBytes failed"); 2406 return null; 2407 } else { 2408 return new String(passphraseBytes); 2409 } 2410 } 2411 } 2412 2413