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