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.*;
20import static org.mockito.Mockito.*;
21
22import android.app.test.MockAnswerUtil.AnswerWithArguments;
23import android.net.IpConfiguration;
24import android.net.wifi.WifiConfiguration;
25import android.test.suitebuilder.annotation.SmallTest;
26import android.text.TextUtils;
27import android.util.SparseArray;
28
29import com.android.server.net.IpConfigStore;
30import com.android.server.wifi.hotspot2.LegacyPasspointConfig;
31import com.android.server.wifi.hotspot2.LegacyPasspointConfigParser;
32
33import org.junit.After;
34import org.junit.Before;
35import org.junit.Test;
36import org.mockito.Mock;
37import org.mockito.MockitoAnnotations;
38
39import java.util.ArrayList;
40import java.util.HashMap;
41import java.util.List;
42import java.util.Map;
43
44/**
45 * Unit tests for {@link com.android.server.wifi.WifiConfigStoreLegacy}.
46 */
47@SmallTest
48public class WifiConfigStoreLegacyTest {
49    private static final String MASKED_FIELD_VALUE = "*";
50
51    // Test mocks
52    @Mock private WifiNative mWifiNative;
53    @Mock private WifiNetworkHistory mWifiNetworkHistory;
54    @Mock private IpConfigStore mIpconfigStore;
55    @Mock private LegacyPasspointConfigParser mPasspointConfigParser;
56
57    /**
58     * Test instance of WifiConfigStore.
59     */
60    private WifiConfigStoreLegacy mWifiConfigStore;
61
62
63    /**
64     * Setup the test environment.
65     */
66    @Before
67    public void setUp() throws Exception {
68        MockitoAnnotations.initMocks(this);
69
70        mWifiConfigStore = new WifiConfigStoreLegacy(mWifiNetworkHistory, mWifiNative,
71                mIpconfigStore, mPasspointConfigParser);
72    }
73
74    /**
75     * Called after each test
76     */
77    @After
78    public void cleanup() {
79        validateMockitoUsage();
80    }
81
82    /**
83     * Verify loading of network configurations from legacy stores. This is verifying the population
84     * of the masked wpa_supplicant fields using wpa_supplicant.conf file.
85     */
86    @Test
87    public void testLoadFromStores() throws Exception {
88        WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork();
89        WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
90        WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
91        WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork();
92        eapNetwork.enterpriseConfig.setPassword("EapPassword");
93
94        // Initialize Passpoint configuration data.
95        int passpointNetworkId = 1234;
96        String fqdn = passpointNetwork.FQDN;
97        String providerFriendlyName = passpointNetwork.providerFriendlyName;
98        long[] roamingConsortiumIds = new long[] {0x1234, 0x5678};
99        String realm = "test.com";
100        String imsi = "214321";
101
102        // Update Passpoint network.
103        // Network ID is used for lookup network extras, so use an unique ID for passpoint network.
104        passpointNetwork.networkId = passpointNetworkId;
105        passpointNetwork.enterpriseConfig.setPassword("PaspointPassword");
106        // Reset FQDN and provider friendly name so that the derived network from #read will
107        // obtained these information from networkExtras and {@link LegacyPasspointConfigParser}.
108        passpointNetwork.FQDN = null;
109        passpointNetwork.providerFriendlyName = null;
110
111        final List<WifiConfiguration> networks = new ArrayList<>();
112        networks.add(pskNetwork);
113        networks.add(wepNetwork);
114        networks.add(eapNetwork);
115        networks.add(passpointNetwork);
116
117        // Setup legacy Passpoint configuration data.
118        Map<String, LegacyPasspointConfig> passpointConfigs = new HashMap<>();
119        LegacyPasspointConfig passpointConfig = new LegacyPasspointConfig();
120        passpointConfig.mFqdn = fqdn;
121        passpointConfig.mFriendlyName = providerFriendlyName;
122        passpointConfig.mRoamingConsortiumOis = roamingConsortiumIds;
123        passpointConfig.mRealm = realm;
124        passpointConfig.mImsi = imsi;
125        passpointConfigs.put(fqdn, passpointConfig);
126
127        // Return the config data with passwords masked from wpa_supplicant control interface.
128        doAnswer(new AnswerWithArguments() {
129            public boolean answer(Map<String, WifiConfiguration> configs,
130                    SparseArray<Map<String, String>> networkExtras) {
131                for (Map.Entry<String, WifiConfiguration> entry:
132                        createWpaSupplicantLoadData(networks).entrySet()) {
133                    configs.put(entry.getKey(), entry.getValue());
134                }
135                // Setup networkExtras for Passpoint configuration.
136                networkExtras.put(passpointNetworkId, createNetworkExtrasForPasspointConfig(fqdn));
137                return true;
138            }
139        }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class));
140
141        when(mPasspointConfigParser.parseConfig(anyString())).thenReturn(passpointConfigs);
142        WifiConfigStoreLegacy.WifiConfigStoreDataLegacy storeData = mWifiConfigStore.read();
143
144        // Update the expected configuration for Passpoint network.
145        passpointNetwork.isLegacyPasspointConfig = true;
146        passpointNetwork.FQDN = fqdn;
147        passpointNetwork.providerFriendlyName = providerFriendlyName;
148        passpointNetwork.roamingConsortiumIds = roamingConsortiumIds;
149        passpointNetwork.enterpriseConfig.setRealm(realm);
150        passpointNetwork.enterpriseConfig.setPlmn(imsi);
151
152        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
153                networks, storeData.getConfigurations());
154    }
155
156    private SparseArray<IpConfiguration> createIpConfigStoreLoadData(
157            List<WifiConfiguration> configurations) {
158        SparseArray<IpConfiguration> newIpConfigurations = new SparseArray<>();
159        for (WifiConfiguration config : configurations) {
160            newIpConfigurations.put(
161                    config.configKey().hashCode(),
162                    new IpConfiguration(config.getIpConfiguration()));
163        }
164        return newIpConfigurations;
165    }
166
167    private Map<String, String> createPskMap(List<WifiConfiguration> configurations) {
168        Map<String, String> pskMap = new HashMap<>();
169        for (WifiConfiguration config : configurations) {
170            if (!TextUtils.isEmpty(config.preSharedKey)) {
171                pskMap.put(config.configKey(), config.preSharedKey);
172            }
173        }
174        return pskMap;
175    }
176
177    private Map<String, String> createWepKey0Map(List<WifiConfiguration> configurations) {
178        Map<String, String> wepKeyMap = new HashMap<>();
179        for (WifiConfiguration config : configurations) {
180            if (!TextUtils.isEmpty(config.wepKeys[0])) {
181                wepKeyMap.put(config.configKey(), config.wepKeys[0]);
182            }
183        }
184        return wepKeyMap;
185    }
186
187    private Map<String, String> createWepKey1Map(List<WifiConfiguration> configurations) {
188        Map<String, String> wepKeyMap = new HashMap<>();
189        for (WifiConfiguration config : configurations) {
190            if (!TextUtils.isEmpty(config.wepKeys[1])) {
191                wepKeyMap.put(config.configKey(), config.wepKeys[1]);
192            }
193        }
194        return wepKeyMap;
195    }
196
197    private Map<String, String> createWepKey2Map(List<WifiConfiguration> configurations) {
198        Map<String, String> wepKeyMap = new HashMap<>();
199        for (WifiConfiguration config : configurations) {
200            if (!TextUtils.isEmpty(config.wepKeys[2])) {
201                wepKeyMap.put(config.configKey(), config.wepKeys[2]);
202            }
203        }
204        return wepKeyMap;
205    }
206
207    private Map<String, String> createWepKey3Map(List<WifiConfiguration> configurations) {
208        Map<String, String> wepKeyMap = new HashMap<>();
209        for (WifiConfiguration config : configurations) {
210            if (!TextUtils.isEmpty(config.wepKeys[3])) {
211                wepKeyMap.put(config.configKey(), config.wepKeys[3]);
212            }
213        }
214        return wepKeyMap;
215    }
216
217    private Map<String, String> createEapPasswordMap(List<WifiConfiguration> configurations) {
218        Map<String, String> eapPasswordMap = new HashMap<>();
219        for (WifiConfiguration config : configurations) {
220            if (!TextUtils.isEmpty(config.enterpriseConfig.getPassword())) {
221                eapPasswordMap.put(config.configKey(), config.enterpriseConfig.getPassword());
222            }
223        }
224        return eapPasswordMap;
225    }
226
227    private Map<String, WifiConfiguration> createWpaSupplicantLoadData(
228            List<WifiConfiguration> configurations) {
229        Map<String, WifiConfiguration> configurationMap = new HashMap<>();
230        for (WifiConfiguration config : configurations) {
231            configurationMap.put(config.configKey(true), config);
232        }
233        return configurationMap;
234    }
235
236    private List<WifiConfiguration> createMaskedWifiConfigurations(
237            List<WifiConfiguration> configurations) {
238        List<WifiConfiguration> newConfigurations = new ArrayList<>();
239        for (WifiConfiguration config : configurations) {
240            newConfigurations.add(createMaskedWifiConfiguration(config));
241        }
242        return newConfigurations;
243    }
244
245    private WifiConfiguration createMaskedWifiConfiguration(WifiConfiguration configuration) {
246        WifiConfiguration newConfig = new WifiConfiguration(configuration);
247        if (!TextUtils.isEmpty(configuration.preSharedKey)) {
248            newConfig.preSharedKey = MASKED_FIELD_VALUE;
249        }
250        if (!TextUtils.isEmpty(configuration.wepKeys[0])) {
251            newConfig.wepKeys[0] = MASKED_FIELD_VALUE;
252        }
253        if (!TextUtils.isEmpty(configuration.wepKeys[1])) {
254            newConfig.wepKeys[1] = MASKED_FIELD_VALUE;
255        }
256        if (!TextUtils.isEmpty(configuration.wepKeys[2])) {
257            newConfig.wepKeys[2] = MASKED_FIELD_VALUE;
258        }
259        if (!TextUtils.isEmpty(configuration.wepKeys[3])) {
260            newConfig.wepKeys[3] = MASKED_FIELD_VALUE;
261        }
262        if (!TextUtils.isEmpty(configuration.enterpriseConfig.getPassword())) {
263            newConfig.enterpriseConfig.setPassword(MASKED_FIELD_VALUE);
264        }
265        return newConfig;
266    }
267
268    private Map<String, String> createNetworkExtrasForPasspointConfig(String fqdn) {
269        Map<String, String> extras = new HashMap<>();
270        extras.put(SupplicantStaNetworkHal.ID_STRING_KEY_FQDN, fqdn);
271        return extras;
272    }
273}
274