WifiConfiguration.java revision b815edf3aba63c2cd46f3ceb243ed13192102940
1/* 2 * Copyright (C) 2008 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 17package android.net.wifi; 18 19import android.net.LinkProperties; 20import android.os.Parcelable; 21import android.os.Parcel; 22import android.text.TextUtils; 23 24import java.util.BitSet; 25 26/** 27 * A class representing a configured Wi-Fi network, including the 28 * security configuration. 29 */ 30public class WifiConfiguration implements Parcelable { 31 private static final String TAG = "WifiConfiguration"; 32 /** {@hide} */ 33 public static final String ssidVarName = "ssid"; 34 /** {@hide} */ 35 public static final String bssidVarName = "bssid"; 36 /** {@hide} */ 37 public static final String pskVarName = "psk"; 38 /** {@hide} */ 39 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 40 /** {@hide} */ 41 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 42 /** {@hide} */ 43 public static final String priorityVarName = "priority"; 44 /** {@hide} */ 45 public static final String hiddenSSIDVarName = "scan_ssid"; 46 /** {@hide} */ 47 public static final int INVALID_NETWORK_ID = -1; 48 /** 49 * Recognized key management schemes. 50 */ 51 public static class KeyMgmt { 52 private KeyMgmt() { } 53 54 /** WPA is not used; plaintext or static WEP could be used. */ 55 public static final int NONE = 0; 56 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 57 public static final int WPA_PSK = 1; 58 /** WPA using EAP authentication. Generally used with an external authentication server. */ 59 public static final int WPA_EAP = 2; 60 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 61 * generated WEP keys. */ 62 public static final int IEEE8021X = 3; 63 64 /** WPA2 pre-shared key for use with soft access point 65 * (requires {@code preSharedKey} to be specified). 66 * @hide 67 */ 68 public static final int WPA2_PSK = 4; 69 70 public static final String varName = "key_mgmt"; 71 72 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", 73 "WPA2_PSK" }; 74 } 75 76 /** 77 * Recognized security protocols. 78 */ 79 public static class Protocol { 80 private Protocol() { } 81 82 /** WPA/IEEE 802.11i/D3.0 */ 83 public static final int WPA = 0; 84 /** WPA2/IEEE 802.11i */ 85 public static final int RSN = 1; 86 87 public static final String varName = "proto"; 88 89 public static final String[] strings = { "WPA", "RSN" }; 90 } 91 92 /** 93 * Recognized IEEE 802.11 authentication algorithms. 94 */ 95 public static class AuthAlgorithm { 96 private AuthAlgorithm() { } 97 98 /** Open System authentication (required for WPA/WPA2) */ 99 public static final int OPEN = 0; 100 /** Shared Key authentication (requires static WEP keys) */ 101 public static final int SHARED = 1; 102 /** LEAP/Network EAP (only used with LEAP) */ 103 public static final int LEAP = 2; 104 105 public static final String varName = "auth_alg"; 106 107 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 108 } 109 110 /** 111 * Recognized pairwise ciphers for WPA. 112 */ 113 public static class PairwiseCipher { 114 private PairwiseCipher() { } 115 116 /** Use only Group keys (deprecated) */ 117 public static final int NONE = 0; 118 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 119 public static final int TKIP = 1; 120 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 121 public static final int CCMP = 2; 122 123 public static final String varName = "pairwise"; 124 125 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 126 } 127 128 /** 129 * Recognized group ciphers. 130 * <pre> 131 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 132 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 133 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 134 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 135 * </pre> 136 */ 137 public static class GroupCipher { 138 private GroupCipher() { } 139 140 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ 141 public static final int WEP40 = 0; 142 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ 143 public static final int WEP104 = 1; 144 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 145 public static final int TKIP = 2; 146 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 147 public static final int CCMP = 3; 148 149 public static final String varName = "group"; 150 151 public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" }; 152 } 153 154 /** Possible status of a network configuration. */ 155 public static class Status { 156 private Status() { } 157 158 /** this is the network we are currently connected to */ 159 public static final int CURRENT = 0; 160 /** supplicant will not attempt to use this network */ 161 public static final int DISABLED = 1; 162 /** supplicant will consider this network available for association */ 163 public static final int ENABLED = 2; 164 165 public static final String[] strings = { "current", "disabled", "enabled" }; 166 } 167 168 /** @hide */ 169 public static final int DISABLED_UNKNOWN_REASON = 0; 170 /** @hide */ 171 public static final int DISABLED_DNS_FAILURE = 1; 172 /** @hide */ 173 public static final int DISABLED_DHCP_FAILURE = 2; 174 /** @hide */ 175 public static final int DISABLED_AUTH_FAILURE = 3; 176 177 /** 178 * The ID number that the supplicant uses to identify this 179 * network configuration entry. This must be passed as an argument 180 * to most calls into the supplicant. 181 */ 182 public int networkId; 183 184 /** 185 * The current status of this network configuration entry. 186 * @see Status 187 */ 188 public int status; 189 190 /** 191 * The code referring to a reason for disabling the network 192 * Valid when {@link #status} == Status.DISABLED 193 * @hide 194 */ 195 public int disableReason; 196 197 /** 198 * The network's SSID. Can either be an ASCII string, 199 * which must be enclosed in double quotation marks 200 * (e.g., {@code "MyNetwork"}, or a string of 201 * hex digits,which are not enclosed in quotes 202 * (e.g., {@code 01a243f405}). 203 */ 204 public String SSID; 205 /** 206 * When set, this network configuration entry should only be used when 207 * associating with the AP having the specified BSSID. The value is 208 * a string in the format of an Ethernet MAC address, e.g., 209 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 210 */ 211 public String BSSID; 212 213 /** 214 * Pre-shared key for use with WPA-PSK. 215 * <p/> 216 * When the value of this key is read, the actual key is 217 * not returned, just a "*" if the key has a value, or the null 218 * string otherwise. 219 */ 220 public String preSharedKey; 221 /** 222 * Up to four WEP keys. Either an ASCII string enclosed in double 223 * quotation marks (e.g., {@code "abcdef"} or a string 224 * of hex digits (e.g., {@code 0102030405}). 225 * <p/> 226 * When the value of one of these keys is read, the actual key is 227 * not returned, just a "*" if the key has a value, or the null 228 * string otherwise. 229 */ 230 public String[] wepKeys; 231 232 /** Default WEP key index, ranging from 0 to 3. */ 233 public int wepTxKeyIndex; 234 235 /** 236 * Priority determines the preference given to a network by {@code wpa_supplicant} 237 * when choosing an access point with which to associate. 238 */ 239 public int priority; 240 241 /** 242 * This is a network that does not broadcast its SSID, so an 243 * SSID-specific probe request must be used for scans. 244 */ 245 public boolean hiddenSSID; 246 247 /** 248 * The set of key management protocols supported by this configuration. 249 * See {@link KeyMgmt} for descriptions of the values. 250 * Defaults to WPA-PSK WPA-EAP. 251 */ 252 public BitSet allowedKeyManagement; 253 /** 254 * The set of security protocols supported by this configuration. 255 * See {@link Protocol} for descriptions of the values. 256 * Defaults to WPA RSN. 257 */ 258 public BitSet allowedProtocols; 259 /** 260 * The set of authentication protocols supported by this configuration. 261 * See {@link AuthAlgorithm} for descriptions of the values. 262 * Defaults to automatic selection. 263 */ 264 public BitSet allowedAuthAlgorithms; 265 /** 266 * The set of pairwise ciphers for WPA supported by this configuration. 267 * See {@link PairwiseCipher} for descriptions of the values. 268 * Defaults to CCMP TKIP. 269 */ 270 public BitSet allowedPairwiseCiphers; 271 /** 272 * The set of group ciphers supported by this configuration. 273 * See {@link GroupCipher} for descriptions of the values. 274 * Defaults to CCMP TKIP WEP104 WEP40. 275 */ 276 public BitSet allowedGroupCiphers; 277 /** 278 * The enterprise configuration details specifying the EAP method, 279 * certificates and other settings associated with the EAP. 280 * @hide 281 */ 282 public WifiEnterpriseConfig enterpriseConfig; 283 284 /** 285 * @hide 286 */ 287 public enum IpAssignment { 288 /* Use statically configured IP settings. Configuration can be accessed 289 * with linkProperties */ 290 STATIC, 291 /* Use dynamically configured IP settigns */ 292 DHCP, 293 /* no IP details are assigned, this is used to indicate 294 * that any existing IP settings should be retained */ 295 UNASSIGNED 296 } 297 /** 298 * @hide 299 */ 300 public IpAssignment ipAssignment; 301 302 /** 303 * @hide 304 */ 305 public enum ProxySettings { 306 /* No proxy is to be used. Any existing proxy settings 307 * should be cleared. */ 308 NONE, 309 /* Use statically configured proxy. Configuration can be accessed 310 * with linkProperties */ 311 STATIC, 312 /* no proxy details are assigned, this is used to indicate 313 * that any existing proxy settings should be retained */ 314 UNASSIGNED 315 } 316 /** 317 * @hide 318 */ 319 public ProxySettings proxySettings; 320 /** 321 * @hide 322 */ 323 public LinkProperties linkProperties; 324 325 public WifiConfiguration() { 326 networkId = INVALID_NETWORK_ID; 327 SSID = null; 328 BSSID = null; 329 priority = 0; 330 hiddenSSID = false; 331 disableReason = DISABLED_UNKNOWN_REASON; 332 allowedKeyManagement = new BitSet(); 333 allowedProtocols = new BitSet(); 334 allowedAuthAlgorithms = new BitSet(); 335 allowedPairwiseCiphers = new BitSet(); 336 allowedGroupCiphers = new BitSet(); 337 wepKeys = new String[4]; 338 for (int i = 0; i < wepKeys.length; i++) { 339 wepKeys[i] = null; 340 } 341 enterpriseConfig = new WifiEnterpriseConfig(); 342 ipAssignment = IpAssignment.UNASSIGNED; 343 proxySettings = ProxySettings.UNASSIGNED; 344 linkProperties = new LinkProperties(); 345 } 346 347 @Override 348 public String toString() { 349 StringBuilder sbuf = new StringBuilder(); 350 if (this.status == WifiConfiguration.Status.CURRENT) { 351 sbuf.append("* "); 352 } else if (this.status == WifiConfiguration.Status.DISABLED) { 353 sbuf.append("- DSBLE: ").append(this.disableReason).append(" "); 354 } 355 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 356 append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority). 357 append('\n'); 358 sbuf.append(" KeyMgmt:"); 359 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 360 if (this.allowedKeyManagement.get(k)) { 361 sbuf.append(" "); 362 if (k < KeyMgmt.strings.length) { 363 sbuf.append(KeyMgmt.strings[k]); 364 } else { 365 sbuf.append("??"); 366 } 367 } 368 } 369 sbuf.append(" Protocols:"); 370 for (int p = 0; p < this.allowedProtocols.size(); p++) { 371 if (this.allowedProtocols.get(p)) { 372 sbuf.append(" "); 373 if (p < Protocol.strings.length) { 374 sbuf.append(Protocol.strings[p]); 375 } else { 376 sbuf.append("??"); 377 } 378 } 379 } 380 sbuf.append('\n'); 381 sbuf.append(" AuthAlgorithms:"); 382 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 383 if (this.allowedAuthAlgorithms.get(a)) { 384 sbuf.append(" "); 385 if (a < AuthAlgorithm.strings.length) { 386 sbuf.append(AuthAlgorithm.strings[a]); 387 } else { 388 sbuf.append("??"); 389 } 390 } 391 } 392 sbuf.append('\n'); 393 sbuf.append(" PairwiseCiphers:"); 394 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 395 if (this.allowedPairwiseCiphers.get(pc)) { 396 sbuf.append(" "); 397 if (pc < PairwiseCipher.strings.length) { 398 sbuf.append(PairwiseCipher.strings[pc]); 399 } else { 400 sbuf.append("??"); 401 } 402 } 403 } 404 sbuf.append('\n'); 405 sbuf.append(" GroupCiphers:"); 406 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 407 if (this.allowedGroupCiphers.get(gc)) { 408 sbuf.append(" "); 409 if (gc < GroupCipher.strings.length) { 410 sbuf.append(GroupCipher.strings[gc]); 411 } else { 412 sbuf.append("??"); 413 } 414 } 415 } 416 sbuf.append('\n').append(" PSK: "); 417 if (this.preSharedKey != null) { 418 sbuf.append('*'); 419 } 420 421 sbuf.append(enterpriseConfig); 422 sbuf.append('\n'); 423 424 sbuf.append("IP assignment: " + ipAssignment.toString()); 425 sbuf.append("\n"); 426 sbuf.append("Proxy settings: " + proxySettings.toString()); 427 sbuf.append("\n"); 428 sbuf.append(linkProperties.toString()); 429 sbuf.append("\n"); 430 431 return sbuf.toString(); 432 } 433 434 /** 435 * Construct a WifiConfiguration from a scanned network 436 * @param scannedAP the scan result used to construct the config entry 437 * TODO: figure out whether this is a useful way to construct a new entry. 438 * 439 public WifiConfiguration(ScanResult scannedAP) { 440 networkId = -1; 441 SSID = scannedAP.SSID; 442 BSSID = scannedAP.BSSID; 443 } 444 */ 445 446 /** {@hide} */ 447 public String getPrintableSsid() { 448 if (SSID == null) return ""; 449 final int length = SSID.length(); 450 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 451 return SSID.substring(1, length - 1); 452 } 453 454 /** The ascii-encoded string format is P"<ascii-encoded-string>" 455 * The decoding is implemented in the supplicant for a newly configured 456 * network. 457 */ 458 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 459 (SSID.charAt(length-1) == '"')) { 460 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 461 SSID.substring(2, length - 1)); 462 return wifiSsid.toString(); 463 } 464 return SSID; 465 } 466 467 /** 468 * Get an identifier for associating credentials with this config 469 * @param current configuration contains values for additional fields 470 * that are not part of this configuration. Used 471 * when a config with some fields is passed by an application. 472 * @throws IllegalStateException if config is invalid for key id generation 473 * @hide 474 */ 475 String getKeyIdForCredentials(WifiConfiguration current) { 476 String keyMgmt = null; 477 478 try { 479 // Get current config details for fields that are not initialized 480 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 481 if (allowedKeyManagement.cardinality() == 0) { 482 allowedKeyManagement = current.allowedKeyManagement; 483 } 484 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 485 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 486 } 487 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 488 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 489 } 490 491 if (TextUtils.isEmpty(keyMgmt)) { 492 throw new IllegalStateException("Not an EAP network"); 493 } 494 495 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 496 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 497 current.enterpriseConfig : null)); 498 } catch (NullPointerException e) { 499 throw new IllegalStateException("Invalid config details"); 500 } 501 } 502 503 private String trimStringForKeyId(String string) { 504 // Remove quotes and spaces 505 return string.replace("\"", "").replace(" ", ""); 506 } 507 508 private static BitSet readBitSet(Parcel src) { 509 int cardinality = src.readInt(); 510 511 BitSet set = new BitSet(); 512 for (int i = 0; i < cardinality; i++) { 513 set.set(src.readInt()); 514 } 515 516 return set; 517 } 518 519 private static void writeBitSet(Parcel dest, BitSet set) { 520 int nextSetBit = -1; 521 522 dest.writeInt(set.cardinality()); 523 524 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 525 dest.writeInt(nextSetBit); 526 } 527 } 528 529 /** @hide */ 530 public int getAuthType() { 531 if (allowedKeyManagement.cardinality() > 1) { 532 throw new IllegalStateException("More than one auth type set"); 533 } 534 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 535 return KeyMgmt.WPA_PSK; 536 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 537 return KeyMgmt.WPA2_PSK; 538 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 539 return KeyMgmt.WPA_EAP; 540 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 541 return KeyMgmt.IEEE8021X; 542 } 543 return KeyMgmt.NONE; 544 } 545 546 /** Implement the Parcelable interface {@hide} */ 547 public int describeContents() { 548 return 0; 549 } 550 551 /** copy constructor {@hide} */ 552 public WifiConfiguration(WifiConfiguration source) { 553 if (source != null) { 554 networkId = source.networkId; 555 status = source.status; 556 disableReason = source.disableReason; 557 SSID = source.SSID; 558 BSSID = source.BSSID; 559 preSharedKey = source.preSharedKey; 560 561 wepKeys = new String[4]; 562 for (int i = 0; i < wepKeys.length; i++) { 563 wepKeys[i] = source.wepKeys[i]; 564 } 565 566 wepTxKeyIndex = source.wepTxKeyIndex; 567 priority = source.priority; 568 hiddenSSID = source.hiddenSSID; 569 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 570 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 571 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 572 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 573 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 574 575 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 576 577 ipAssignment = source.ipAssignment; 578 proxySettings = source.proxySettings; 579 linkProperties = new LinkProperties(source.linkProperties); 580 } 581 } 582 583 /** Implement the Parcelable interface {@hide} */ 584 public void writeToParcel(Parcel dest, int flags) { 585 dest.writeInt(networkId); 586 dest.writeInt(status); 587 dest.writeInt(disableReason); 588 dest.writeString(SSID); 589 dest.writeString(BSSID); 590 dest.writeString(preSharedKey); 591 for (String wepKey : wepKeys) { 592 dest.writeString(wepKey); 593 } 594 dest.writeInt(wepTxKeyIndex); 595 dest.writeInt(priority); 596 dest.writeInt(hiddenSSID ? 1 : 0); 597 598 writeBitSet(dest, allowedKeyManagement); 599 writeBitSet(dest, allowedProtocols); 600 writeBitSet(dest, allowedAuthAlgorithms); 601 writeBitSet(dest, allowedPairwiseCiphers); 602 writeBitSet(dest, allowedGroupCiphers); 603 604 dest.writeParcelable(enterpriseConfig, flags); 605 606 dest.writeString(ipAssignment.name()); 607 dest.writeString(proxySettings.name()); 608 dest.writeParcelable(linkProperties, flags); 609 } 610 611 /** Implement the Parcelable interface {@hide} */ 612 public static final Creator<WifiConfiguration> CREATOR = 613 new Creator<WifiConfiguration>() { 614 public WifiConfiguration createFromParcel(Parcel in) { 615 WifiConfiguration config = new WifiConfiguration(); 616 config.networkId = in.readInt(); 617 config.status = in.readInt(); 618 config.disableReason = in.readInt(); 619 config.SSID = in.readString(); 620 config.BSSID = in.readString(); 621 config.preSharedKey = in.readString(); 622 for (int i = 0; i < config.wepKeys.length; i++) { 623 config.wepKeys[i] = in.readString(); 624 } 625 config.wepTxKeyIndex = in.readInt(); 626 config.priority = in.readInt(); 627 config.hiddenSSID = in.readInt() != 0; 628 config.allowedKeyManagement = readBitSet(in); 629 config.allowedProtocols = readBitSet(in); 630 config.allowedAuthAlgorithms = readBitSet(in); 631 config.allowedPairwiseCiphers = readBitSet(in); 632 config.allowedGroupCiphers = readBitSet(in); 633 634 config.enterpriseConfig = in.readParcelable(null); 635 636 config.ipAssignment = IpAssignment.valueOf(in.readString()); 637 config.proxySettings = ProxySettings.valueOf(in.readString()); 638 config.linkProperties = in.readParcelable(null); 639 640 return config; 641 } 642 643 public WifiConfiguration[] newArray(int size) { 644 return new WifiConfiguration[size]; 645 } 646 }; 647} 648