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