1/*
2 * Copyright (C) 2016 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 com.android.server.wifi;
18
19import static org.junit.Assert.*;
20
21import android.content.pm.UserInfo;
22import android.net.wifi.WifiConfiguration;
23import android.net.wifi.WifiEnterpriseConfig;
24import android.net.wifi.WifiScanner;
25import android.os.UserHandle;
26import android.test.suitebuilder.annotation.SmallTest;
27
28import org.junit.Test;
29
30import java.security.cert.X509Certificate;
31import java.util.ArrayList;
32import java.util.Arrays;
33import java.util.Collections;
34import java.util.List;
35
36/**
37 * Unit tests for {@link com.android.server.wifi.WifiConfigurationUtil}.
38 */
39@SmallTest
40public class WifiConfigurationUtilTest {
41    static final int CURRENT_USER_ID = 0;
42    static final int CURRENT_USER_MANAGED_PROFILE_USER_ID = 10;
43    static final int OTHER_USER_ID = 11;
44    static final String TEST_SSID = "test_ssid";
45    static final String TEST_SSID_1 = "test_ssid_1";
46    static final List<UserInfo> PROFILES = Arrays.asList(
47            new UserInfo(CURRENT_USER_ID, "owner", 0),
48            new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0));
49
50    /**
51     * Test for {@link WifiConfigurationUtil.isVisibleToAnyProfile}.
52     */
53    @Test
54    public void isVisibleToAnyProfile() {
55        // Shared network configuration created by another user.
56        final WifiConfiguration configuration = new WifiConfiguration();
57        configuration.creatorUid = UserHandle.getUid(OTHER_USER_ID, 0);
58        assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
59
60        // Private network configuration created by another user.
61        configuration.shared = false;
62        assertFalse(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
63
64        // Private network configuration created by the current user.
65        configuration.creatorUid = UserHandle.getUid(CURRENT_USER_ID, 0);
66        assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
67
68        // Private network configuration created by the current user's managed profile.
69        configuration.creatorUid = UserHandle.getUid(CURRENT_USER_MANAGED_PROFILE_USER_ID, 0);
70        assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
71    }
72
73    /**
74     * Verify that new WifiEnterpriseConfig is detected.
75     */
76    @Test
77    public void testEnterpriseConfigAdded() {
78        EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
79                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
80                .setIdentity("username", "password")
81                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
82
83        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(
84                null, eapConfig.enterpriseConfig));
85    }
86
87    /**
88     * Verify WifiEnterpriseConfig eap change is detected.
89     */
90    @Test
91    public void testEnterpriseConfigEapChangeDetected() {
92        EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS);
93        EnterpriseConfig peapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.PEAP);
94
95        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig,
96                peapConfig.enterpriseConfig));
97    }
98
99    /**
100     * Verify WifiEnterpriseConfig phase2 method change is detected.
101     */
102    @Test
103    public void testEnterpriseConfigPhase2ChangeDetected() {
104        EnterpriseConfig eapConfig =
105                new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
106                        .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2);
107        EnterpriseConfig papConfig =
108                new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
109                        .setPhase2(WifiEnterpriseConfig.Phase2.PAP);
110
111        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig,
112                papConfig.enterpriseConfig));
113    }
114
115    /**
116     * Verify WifiEnterpriseConfig added Certificate is detected.
117     */
118    @Test
119    public void testCaCertificateAddedDetected() {
120        EnterpriseConfig eapConfigNoCerts = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
121                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
122                .setIdentity("username", "password");
123
124        EnterpriseConfig eapConfig1Cert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
125                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
126                .setIdentity("username", "password")
127                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
128
129        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(
130                eapConfigNoCerts.enterpriseConfig, eapConfig1Cert.enterpriseConfig));
131    }
132
133    /**
134     * Verify WifiEnterpriseConfig Certificate change is detected.
135     */
136    @Test
137    public void testDifferentCaCertificateDetected() {
138        EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
139                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
140                .setIdentity("username", "password")
141                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
142
143        EnterpriseConfig eapConfigNewCert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
144                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
145                .setIdentity("username", "password")
146                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT1});
147
148        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig,
149                eapConfigNewCert.enterpriseConfig));
150    }
151
152    /**
153     * Verify WifiEnterpriseConfig added Certificate changes are detected.
154     */
155    @Test
156    public void testCaCertificateChangesDetected() {
157        EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
158                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
159                .setIdentity("username", "password")
160                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
161
162        EnterpriseConfig eapConfigAddedCert = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
163                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
164                .setIdentity("username", "password")
165                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
166
167        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig,
168                eapConfigAddedCert.enterpriseConfig));
169    }
170
171    /**
172     * Verify that WifiEnterpriseConfig does not detect changes for identical configs.
173     */
174    @Test
175    public void testWifiEnterpriseConfigNoChanges() {
176        EnterpriseConfig eapConfig = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
177                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
178                .setIdentity("username", "password")
179                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
180
181        // Just to be clear that check is not against the same object
182        EnterpriseConfig eapConfigSame = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
183                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
184                .setIdentity("username", "password")
185                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
186
187        assertFalse(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig.enterpriseConfig,
188                eapConfigSame.enterpriseConfig));
189    }
190
191    /**
192     * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created
193     * for an open network using {@link WifiConfigurationUtil#createPnoNetwork(
194     * WifiConfiguration, int)}.
195     */
196    @Test
197    public void testCreatePnoNetworkWithOpenNetwork() {
198        WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork();
199        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
200                WifiConfigurationUtil.createPnoNetwork(network, 1);
201        assertEquals(network.SSID, pnoNetwork.ssid);
202        assertEquals(
203                WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND
204                        | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags);
205        assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN, pnoNetwork.authBitField);
206    }
207
208    /**
209     * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created
210     * for an open hidden network using {@link WifiConfigurationUtil#createPnoNetwork(
211     * WifiConfiguration, int)}.
212     */
213    @Test
214    public void testCreatePnoNetworkWithOpenHiddenNetwork() {
215        WifiConfiguration network = WifiConfigurationTestUtil.createOpenHiddenNetwork();
216        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
217                WifiConfigurationUtil.createPnoNetwork(network, 1);
218        assertEquals(network.SSID, pnoNetwork.ssid);
219        assertEquals(
220                WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND
221                        | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND
222                        | WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN, pnoNetwork.flags);
223        assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_OPEN, pnoNetwork.authBitField);
224    }
225
226    /**
227     * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created
228     * for a PSK network using {@link WifiConfigurationUtil#createPnoNetwork(WifiConfiguration, int)
229     * }.
230     */
231    @Test
232    public void testCreatePnoNetworkWithPskNetwork() {
233        WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork();
234        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
235                WifiConfigurationUtil.createPnoNetwork(network, 1);
236        assertEquals(network.SSID, pnoNetwork.ssid);
237        assertEquals(
238                WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND
239                        | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags);
240        assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_PSK, pnoNetwork.authBitField);
241    }
242
243    /**
244     * Verify that WifiConfigurationUtil.isSameNetwork returns true when two WifiConfiguration
245     * objects have the same parameters.
246     */
247    @Test
248    public void testIsSameNetworkReturnsTrueOnSameNetwork() {
249        WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID);
250        WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID);
251        assertTrue(WifiConfigurationUtil.isSameNetwork(network, network1));
252    }
253
254    /**
255     * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration
256     * objects have the different SSIDs.
257     */
258    @Test
259    public void testIsSameNetworkReturnsFalseOnDifferentSSID() {
260        WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID);
261        WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1);
262        assertFalse(WifiConfigurationUtil.isSameNetwork(network, network1));
263    }
264
265    /**
266     * Verify that WifiConfigurationUtil.isSameNetwork returns false when two WifiConfiguration
267     * objects have the different security type.
268     */
269    @Test
270    public void testIsSameNetworkReturnsFalseOnDifferentSecurityType() {
271        WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID);
272        WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(TEST_SSID);
273        assertFalse(WifiConfigurationUtil.isSameNetwork(network, network1));
274    }
275
276
277    /**
278     * Verify the instance of {@link android.net.wifi.WifiScanner.PnoSettings.PnoNetwork} created
279     * for a EAP network using {@link WifiConfigurationUtil#createPnoNetwork(WifiConfiguration, int)
280     * }.
281     */
282    @Test
283    public void testCreatePnoNetworkWithEapNetwork() {
284        WifiConfiguration network = WifiConfigurationTestUtil.createEapNetwork();
285        WifiScanner.PnoSettings.PnoNetwork pnoNetwork =
286                WifiConfigurationUtil.createPnoNetwork(network, 1);
287        assertEquals(network.SSID, pnoNetwork.ssid);
288        assertEquals(
289                WifiScanner.PnoSettings.PnoNetwork.FLAG_A_BAND
290                        | WifiScanner.PnoSettings.PnoNetwork.FLAG_G_BAND, pnoNetwork.flags);
291        assertEquals(WifiScanner.PnoSettings.PnoNetwork.AUTH_CODE_EAPOL, pnoNetwork.authBitField);
292    }
293
294    /**
295     * Verify that the generalized
296     * {@link com.android.server.wifi.WifiConfigurationUtil.WifiConfigurationComparator}
297     * can be used to sort a List given a 'compareNetworkWithSameStatus' method.
298     */
299    @Test
300    public void testPnoListComparator() {
301        List<WifiConfiguration> networks = new ArrayList<>();
302        final WifiConfiguration enabledNetwork1 = WifiConfigurationTestUtil.createEapNetwork();
303        enabledNetwork1.getNetworkSelectionStatus().setNetworkSelectionStatus(
304                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
305        final WifiConfiguration enabledNetwork2 = WifiConfigurationTestUtil.createEapNetwork();
306        enabledNetwork2.getNetworkSelectionStatus().setNetworkSelectionStatus(
307                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
308        final WifiConfiguration tempDisabledNetwork1 = WifiConfigurationTestUtil.createEapNetwork();
309        tempDisabledNetwork1.getNetworkSelectionStatus().setNetworkSelectionStatus(
310                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
311        final WifiConfiguration tempDisabledNetwork2 = WifiConfigurationTestUtil.createEapNetwork();
312        tempDisabledNetwork2.getNetworkSelectionStatus().setNetworkSelectionStatus(
313                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
314        WifiConfiguration permDisabledNetwork = WifiConfigurationTestUtil.createEapNetwork();
315        permDisabledNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus(
316                WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
317
318        // Add all the networks to the list.
319        networks.add(tempDisabledNetwork1);
320        networks.add(enabledNetwork1);
321        networks.add(permDisabledNetwork);
322        networks.add(tempDisabledNetwork2);
323        networks.add(enabledNetwork2);
324
325        // Prefer |enabledNetwork1| over |enabledNetwork2| and |tempDisabledNetwork1| over
326        // |tempDisabledNetwork2|.
327        WifiConfigurationUtil.WifiConfigurationComparator comparator =
328                new WifiConfigurationUtil.WifiConfigurationComparator() {
329                    @Override
330                    public int compareNetworksWithSameStatus(
331                            WifiConfiguration a, WifiConfiguration b) {
332                        if (a == enabledNetwork1 && b == enabledNetwork2) {
333                            return -1;
334                        } else if (b == enabledNetwork1 && a == enabledNetwork2) {
335                            return 1;
336                        } else if (a == tempDisabledNetwork1 && b == tempDisabledNetwork2) {
337                            return -1;
338                        } else if (b == tempDisabledNetwork1 && a == tempDisabledNetwork2) {
339                            return 1;
340                        }
341                        return 0;
342                    }
343                };
344        Collections.sort(networks, comparator);
345
346        // Now ensure that the networks were sorted correctly.
347        assertEquals(enabledNetwork1, networks.get(0));
348        assertEquals(enabledNetwork2, networks.get(1));
349        assertEquals(tempDisabledNetwork1, networks.get(2));
350        assertEquals(tempDisabledNetwork2, networks.get(3));
351        assertEquals(permDisabledNetwork, networks.get(4));
352    }
353
354    private static class EnterpriseConfig {
355        public String eap;
356        public String phase2;
357        public String identity;
358        public String password;
359        public X509Certificate[] caCerts;
360        public WifiEnterpriseConfig enterpriseConfig;
361
362        EnterpriseConfig(int eapMethod) {
363            enterpriseConfig = new WifiEnterpriseConfig();
364            enterpriseConfig.setEapMethod(eapMethod);
365            eap = WifiEnterpriseConfig.Eap.strings[eapMethod];
366        }
367
368        public EnterpriseConfig setPhase2(int phase2Method) {
369            enterpriseConfig.setPhase2Method(phase2Method);
370            phase2 = "auth=" + WifiEnterpriseConfig.Phase2.strings[phase2Method];
371            return this;
372        }
373
374        public EnterpriseConfig setIdentity(String identity, String password) {
375            enterpriseConfig.setIdentity(identity);
376            enterpriseConfig.setPassword(password);
377            this.identity = identity;
378            this.password = password;
379            return this;
380        }
381
382        public EnterpriseConfig setCaCerts(X509Certificate[] certs) {
383            enterpriseConfig.setCaCertificates(certs);
384            caCerts = certs;
385            return this;
386        }
387    }
388}
389