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.os.Parcelable; 20import android.os.Parcel; 21 22import java.util.BitSet; 23 24/** 25 * A class representing a configured Wi-Fi network, including the 26 * security configuration. Android will not necessarily support 27 * all of these security schemes initially. 28 */ 29public class WifiConfiguration implements Parcelable { 30 31 /** {@hide} */ 32 public static final String ssidVarName = "ssid"; 33 /** {@hide} */ 34 public static final String bssidVarName = "bssid"; 35 /** {@hide} */ 36 public static final String pskVarName = "psk"; 37 /** {@hide} */ 38 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 39 /** {@hide} */ 40 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 41 /** {@hide} */ 42 public static final String priorityVarName = "priority"; 43 /** {@hide} */ 44 public static final String hiddenSSIDVarName = "scan_ssid"; 45 46 /** {@hide} */ 47 public class EnterpriseField { 48 private String varName; 49 private String value; 50 51 private EnterpriseField(String varName) { 52 this.varName = varName; 53 this.value = null; 54 } 55 56 public void setValue(String value) { 57 this.value = value; 58 } 59 60 public String varName() { 61 return varName; 62 } 63 64 public String value() { 65 return value; 66 } 67 } 68 69 /** {@hide} */ 70 public EnterpriseField eap = new EnterpriseField("eap"); 71 /** {@hide} */ 72 public EnterpriseField phase2 = new EnterpriseField("phase2"); 73 /** {@hide} */ 74 public EnterpriseField identity = new EnterpriseField("identity"); 75 /** {@hide} */ 76 public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity"); 77 /** {@hide} */ 78 public EnterpriseField password = new EnterpriseField("password"); 79 /** {@hide} */ 80 public EnterpriseField client_cert = new EnterpriseField("client_cert"); 81 /** {@hide} */ 82 public EnterpriseField private_key = new EnterpriseField("private_key"); 83 /** {@hide} */ 84 public EnterpriseField ca_cert = new EnterpriseField("ca_cert"); 85 86 /** {@hide} */ 87 public EnterpriseField[] enterpriseFields = { 88 eap, phase2, identity, anonymous_identity, password, client_cert, 89 private_key, ca_cert }; 90 91 /** 92 * Recognized key management schemes. 93 */ 94 public static class KeyMgmt { 95 private KeyMgmt() { } 96 97 /** WPA is not used; plaintext or static WEP could be used. */ 98 public static final int NONE = 0; 99 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 100 public static final int WPA_PSK = 1; 101 /** WPA using EAP authentication. Generally used with an external authentication server. */ 102 public static final int WPA_EAP = 2; 103 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 104 * generated WEP keys. */ 105 public static final int IEEE8021X = 3; 106 107 public static final String varName = "key_mgmt"; 108 109 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X" }; 110 } 111 112 /** 113 * Recognized security protocols. 114 */ 115 public static class Protocol { 116 private Protocol() { } 117 118 /** WPA/IEEE 802.11i/D3.0 */ 119 public static final int WPA = 0; 120 /** WPA2/IEEE 802.11i */ 121 public static final int RSN = 1; 122 123 public static final String varName = "proto"; 124 125 public static final String[] strings = { "WPA", "RSN" }; 126 } 127 128 /** 129 * Recognized IEEE 802.11 authentication algorithms. 130 */ 131 public static class AuthAlgorithm { 132 private AuthAlgorithm() { } 133 134 /** Open System authentication (required for WPA/WPA2) */ 135 public static final int OPEN = 0; 136 /** Shared Key authentication (requires static WEP keys) */ 137 public static final int SHARED = 1; 138 /** LEAP/Network EAP (only used with LEAP) */ 139 public static final int LEAP = 2; 140 141 public static final String varName = "auth_alg"; 142 143 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 144 } 145 146 /** 147 * Recognized pairwise ciphers for WPA. 148 */ 149 public static class PairwiseCipher { 150 private PairwiseCipher() { } 151 152 /** Use only Group keys (deprecated) */ 153 public static final int NONE = 0; 154 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 155 public static final int TKIP = 1; 156 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 157 public static final int CCMP = 2; 158 159 public static final String varName = "pairwise"; 160 161 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 162 } 163 164 /** 165 * Recognized group ciphers. 166 * <pre> 167 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 168 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 169 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 170 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 171 * </pre> 172 */ 173 public static class GroupCipher { 174 private GroupCipher() { } 175 176 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ 177 public static final int WEP40 = 0; 178 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ 179 public static final int WEP104 = 1; 180 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 181 public static final int TKIP = 2; 182 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 183 public static final int CCMP = 3; 184 185 public static final String varName = "group"; 186 187 public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" }; 188 } 189 190 /** Possible status of a network configuration. */ 191 public static class Status { 192 private Status() { } 193 194 /** this is the network we are currently connected to */ 195 public static final int CURRENT = 0; 196 /** supplicant will not attempt to use this network */ 197 public static final int DISABLED = 1; 198 /** supplicant will consider this network available for association */ 199 public static final int ENABLED = 2; 200 201 public static final String[] strings = { "current", "disabled", "enabled" }; 202 } 203 204 /** 205 * The ID number that the supplicant uses to identify this 206 * network configuration entry. This must be passed as an argument 207 * to most calls into the supplicant. 208 */ 209 public int networkId; 210 211 /** 212 * The current status of this network configuration entry. 213 * @see Status 214 */ 215 public int status; 216 /** 217 * The network's SSID. Can either be an ASCII string, 218 * which must be enclosed in double quotation marks 219 * (e.g., {@code "MyNetwork"}, or a string of 220 * hex digits,which are not enclosed in quotes 221 * (e.g., {@code 01a243f405}). 222 */ 223 public String SSID; 224 /** 225 * When set, this network configuration entry should only be used when 226 * associating with the AP having the specified BSSID. The value is 227 * a string in the format of an Ethernet MAC address, e.g., 228 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 229 */ 230 public String BSSID; 231 232 /** 233 * Pre-shared key for use with WPA-PSK. 234 * <p/> 235 * When the value of this key is read, the actual key is 236 * not returned, just a "*" if the key has a value, or the null 237 * string otherwise. 238 */ 239 public String preSharedKey; 240 /** 241 * Up to four WEP keys. Either an ASCII string enclosed in double 242 * quotation marks (e.g., {@code "abcdef"} or a string 243 * of hex digits (e.g., {@code 0102030405}). 244 * <p/> 245 * When the value of one of these keys is read, the actual key is 246 * not returned, just a "*" if the key has a value, or the null 247 * string otherwise. 248 */ 249 public String[] wepKeys; 250 251 /** Default WEP key index, ranging from 0 to 3. */ 252 public int wepTxKeyIndex; 253 254 /** 255 * Priority determines the preference given to a network by {@code wpa_supplicant} 256 * when choosing an access point with which to associate. 257 */ 258 public int priority; 259 260 /** 261 * This is a network that does not broadcast its SSID, so an 262 * SSID-specific probe request must be used for scans. 263 */ 264 public boolean hiddenSSID; 265 266 /** 267 * The set of key management protocols supported by this configuration. 268 * See {@link KeyMgmt} for descriptions of the values. 269 * Defaults to WPA-PSK WPA-EAP. 270 */ 271 public BitSet allowedKeyManagement; 272 /** 273 * The set of security protocols supported by this configuration. 274 * See {@link Protocol} for descriptions of the values. 275 * Defaults to WPA RSN. 276 */ 277 public BitSet allowedProtocols; 278 /** 279 * The set of authentication protocols supported by this configuration. 280 * See {@link AuthAlgorithm} for descriptions of the values. 281 * Defaults to automatic selection. 282 */ 283 public BitSet allowedAuthAlgorithms; 284 /** 285 * The set of pairwise ciphers for WPA supported by this configuration. 286 * See {@link PairwiseCipher} for descriptions of the values. 287 * Defaults to CCMP TKIP. 288 */ 289 public BitSet allowedPairwiseCiphers; 290 /** 291 * The set of group ciphers supported by this configuration. 292 * See {@link GroupCipher} for descriptions of the values. 293 * Defaults to CCMP TKIP WEP104 WEP40. 294 */ 295 public BitSet allowedGroupCiphers; 296 297 298 public WifiConfiguration() { 299 networkId = -1; 300 SSID = null; 301 BSSID = null; 302 priority = 0; 303 hiddenSSID = false; 304 allowedKeyManagement = new BitSet(); 305 allowedProtocols = new BitSet(); 306 allowedAuthAlgorithms = new BitSet(); 307 allowedPairwiseCiphers = new BitSet(); 308 allowedGroupCiphers = new BitSet(); 309 wepKeys = new String[4]; 310 for (int i = 0; i < wepKeys.length; i++) 311 wepKeys[i] = null; 312 for (EnterpriseField field : enterpriseFields) { 313 field.setValue(null); 314 } 315 } 316 317 public String toString() { 318 StringBuffer sbuf = new StringBuffer(); 319 if (this.status == WifiConfiguration.Status.CURRENT) { 320 sbuf.append("* "); 321 } else if (this.status == WifiConfiguration.Status.DISABLED) { 322 sbuf.append("- "); 323 } 324 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 325 append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority). 326 append('\n'); 327 sbuf.append(" KeyMgmt:"); 328 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 329 if (this.allowedKeyManagement.get(k)) { 330 sbuf.append(" "); 331 if (k < KeyMgmt.strings.length) { 332 sbuf.append(KeyMgmt.strings[k]); 333 } else { 334 sbuf.append("??"); 335 } 336 } 337 } 338 sbuf.append(" Protocols:"); 339 for (int p = 0; p < this.allowedProtocols.size(); p++) { 340 if (this.allowedProtocols.get(p)) { 341 sbuf.append(" "); 342 if (p < Protocol.strings.length) { 343 sbuf.append(Protocol.strings[p]); 344 } else { 345 sbuf.append("??"); 346 } 347 } 348 } 349 sbuf.append('\n'); 350 sbuf.append(" AuthAlgorithms:"); 351 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 352 if (this.allowedAuthAlgorithms.get(a)) { 353 sbuf.append(" "); 354 if (a < AuthAlgorithm.strings.length) { 355 sbuf.append(AuthAlgorithm.strings[a]); 356 } else { 357 sbuf.append("??"); 358 } 359 } 360 } 361 sbuf.append('\n'); 362 sbuf.append(" PairwiseCiphers:"); 363 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 364 if (this.allowedPairwiseCiphers.get(pc)) { 365 sbuf.append(" "); 366 if (pc < PairwiseCipher.strings.length) { 367 sbuf.append(PairwiseCipher.strings[pc]); 368 } else { 369 sbuf.append("??"); 370 } 371 } 372 } 373 sbuf.append('\n'); 374 sbuf.append(" GroupCiphers:"); 375 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 376 if (this.allowedGroupCiphers.get(gc)) { 377 sbuf.append(" "); 378 if (gc < GroupCipher.strings.length) { 379 sbuf.append(GroupCipher.strings[gc]); 380 } else { 381 sbuf.append("??"); 382 } 383 } 384 } 385 sbuf.append('\n').append(" PSK: "); 386 if (this.preSharedKey != null) { 387 sbuf.append('*'); 388 } 389 390 for (EnterpriseField field : enterpriseFields) { 391 sbuf.append('\n').append(" " + field.varName() + ": "); 392 String value = field.value(); 393 if (value != null) sbuf.append(value); 394 } 395 sbuf.append('\n'); 396 return sbuf.toString(); 397 } 398 399 /** 400 * Construct a WifiConfiguration from a scanned network 401 * @param scannedAP the scan result used to construct the config entry 402 * TODO: figure out whether this is a useful way to construct a new entry. 403 * 404 public WifiConfiguration(ScanResult scannedAP) { 405 networkId = -1; 406 SSID = scannedAP.SSID; 407 BSSID = scannedAP.BSSID; 408 } 409 */ 410 411 private static BitSet readBitSet(Parcel src) { 412 int cardinality = src.readInt(); 413 414 BitSet set = new BitSet(); 415 for (int i = 0; i < cardinality; i++) 416 set.set(src.readInt()); 417 418 return set; 419 } 420 421 private static void writeBitSet(Parcel dest, BitSet set) { 422 int nextSetBit = -1; 423 424 dest.writeInt(set.cardinality()); 425 426 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) 427 dest.writeInt(nextSetBit); 428 } 429 430 /** Implement the Parcelable interface {@hide} */ 431 public int describeContents() { 432 return 0; 433 } 434 435 /** Implement the Parcelable interface {@hide} */ 436 public void writeToParcel(Parcel dest, int flags) { 437 dest.writeInt(networkId); 438 dest.writeInt(status); 439 dest.writeString(SSID); 440 dest.writeString(BSSID); 441 dest.writeString(preSharedKey); 442 for (String wepKey : wepKeys) 443 dest.writeString(wepKey); 444 dest.writeInt(wepTxKeyIndex); 445 dest.writeInt(priority); 446 dest.writeInt(hiddenSSID ? 1 : 0); 447 448 writeBitSet(dest, allowedKeyManagement); 449 writeBitSet(dest, allowedProtocols); 450 writeBitSet(dest, allowedAuthAlgorithms); 451 writeBitSet(dest, allowedPairwiseCiphers); 452 writeBitSet(dest, allowedGroupCiphers); 453 454 for (EnterpriseField field : enterpriseFields) { 455 dest.writeString(field.value()); 456 } 457 } 458 459 /** Implement the Parcelable interface {@hide} */ 460 public static final Creator<WifiConfiguration> CREATOR = 461 new Creator<WifiConfiguration>() { 462 public WifiConfiguration createFromParcel(Parcel in) { 463 WifiConfiguration config = new WifiConfiguration(); 464 config.networkId = in.readInt(); 465 config.status = in.readInt(); 466 config.SSID = in.readString(); 467 config.BSSID = in.readString(); 468 config.preSharedKey = in.readString(); 469 for (int i = 0; i < config.wepKeys.length; i++) 470 config.wepKeys[i] = in.readString(); 471 config.wepTxKeyIndex = in.readInt(); 472 config.priority = in.readInt(); 473 config.hiddenSSID = in.readInt() != 0; 474 config.allowedKeyManagement = readBitSet(in); 475 config.allowedProtocols = readBitSet(in); 476 config.allowedAuthAlgorithms = readBitSet(in); 477 config.allowedPairwiseCiphers = readBitSet(in); 478 config.allowedGroupCiphers = readBitSet(in); 479 480 for (EnterpriseField field : config.enterpriseFields) { 481 field.setValue(in.readString()); 482 } 483 return config; 484 } 485 486 public WifiConfiguration[] newArray(int size) { 487 return new WifiConfiguration[size]; 488 } 489 }; 490} 491