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