1 /*
2  * Copyright (C) 2015 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 com.android.cts.deviceowner;
18 
19 import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_CREATE_WIFI_CONFIG;
20 import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_REMOVE_WIFI_CONFIG;
21 import static com.android.compatibility.common.util.WifiConfigCreator.ACTION_UPDATE_WIFI_CONFIG;
22 import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_NETID;
23 import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_PASSWORD;
24 import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SECURITY_TYPE;
25 import static com.android.compatibility.common.util.WifiConfigCreator.EXTRA_SSID;
26 import static com.android.compatibility.common.util.WifiConfigCreator.SECURITY_TYPE_NONE;
27 import static com.android.compatibility.common.util.WifiConfigCreator.SECURITY_TYPE_WPA;
28 
29 import static com.google.common.truth.Truth.assertWithMessage;
30 
31 import android.content.Intent;
32 import android.net.wifi.WifiConfiguration;
33 import android.os.Process;
34 import android.provider.Settings;
35 import android.util.Log;
36 
37 import java.util.List;
38 import java.util.stream.Collectors;
39 
40 /**
41  * Testing WiFi configuration lockdown by Device Owner
42  */
43 public final class WifiConfigLockdownTest extends BaseDeviceOwnerTest {
44     private static final String TAG = "WifiConfigLockdownTest";
45     private static final String ORIGINAL_DEVICE_OWNER_SSID = "DOCTSTest";
46     private static final String CHANGED_DEVICE_OWNER_SSID = "DOChangedCTSTest";
47     private static final String ORIGINAL_REGULAR_SSID = "RegularCTSTest";
48     private static final String CHANGED_REGULAR_SSID = "RegularChangedCTSTest";
49     private static final String ORIGINAL_PASSWORD = "originalpassword";
50 
51     @Override
setUp()52     protected void setUp() throws Exception {
53         super.setUp();
54         mDevicePolicyManager.setGlobalSetting(getWho(),
55                 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, "1");
56         mWifiConfigCreator.addNetwork(ORIGINAL_DEVICE_OWNER_SSID, true, SECURITY_TYPE_WPA,
57                 ORIGINAL_PASSWORD);
58 
59         Log.d(TAG, "setUp: user=" + Process.myUserHandle() + ", creator=" + mWifiConfigCreator
60                 + ", dpm=" + mDevicePolicyManager + ", wifiMgr=" + mWifiManager
61                 + ", mCurrentUserWifiManager= " + mCurrentUserWifiManager);
62         logConfigs("setup()", getConfiguredNetworks());
63 
64         startRegularActivity(ACTION_CREATE_WIFI_CONFIG, -1, ORIGINAL_REGULAR_SSID,
65                 SECURITY_TYPE_WPA, ORIGINAL_PASSWORD);
66     }
67 
68     @Override
tearDown()69     protected void tearDown() throws Exception {
70         mDevicePolicyManager.setGlobalSetting(getWho(),
71                 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, "0");
72         List<WifiConfiguration> configs = getConfiguredNetworks();
73         logConfigs("tearDown()", configs);
74         for (WifiConfiguration config : configs) {
75             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID) ||
76                     areMatchingSsids(CHANGED_DEVICE_OWNER_SSID, config.SSID) ||
77                     areMatchingSsids(ORIGINAL_REGULAR_SSID, config.SSID) ||
78                     areMatchingSsids(CHANGED_REGULAR_SSID, config.SSID)) {
79                 Log.d(TAG, "Removing " + config.networkId);
80                 mWifiManager.removeNetwork(config.networkId);
81             }
82         }
83         super.tearDown();
84     }
85 
testDeviceOwnerCanUpdateConfig()86     public void testDeviceOwnerCanUpdateConfig() throws Exception {
87         List<WifiConfiguration> configs = getConfiguredNetworks();
88         logConfigs("testDeviceOwnerCanUpdateConfig()", configs);
89         int updateCount = 0;
90         for (WifiConfiguration config : configs) {
91             Log.d(TAG, "testDeviceOwnerCanUpdateConfig(): testing " + config.SSID);
92             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)) {
93                 int netId = mWifiConfigCreator.updateNetwork(config,
94                         CHANGED_DEVICE_OWNER_SSID, true, SECURITY_TYPE_NONE, null);
95                 Log.d(TAG, "netid after updateNetwork(REGULAR_SSID):" + netId);
96                 assertWithMessage("netid after updateNetwork(%s, DO_SSID)", config.SSID)
97                         .that(netId).isNotEqualTo(-1);
98                 ++updateCount;
99             }
100             if (areMatchingSsids(ORIGINAL_REGULAR_SSID, config.SSID)) {
101                 int netId = mWifiConfigCreator.updateNetwork(config,
102                         CHANGED_REGULAR_SSID, true, SECURITY_TYPE_NONE, null);
103                 Log.d(TAG, "netid after updateNetwork(REGULAR_SSID):" + netId);
104                 assertWithMessage("netid after updateNetwork(%s, REGULAR_SSID)", config.SSID)
105                         .that(netId).isNotEqualTo(-1);
106                 ++updateCount;
107             }
108         }
109         // There might be auto-upgrade configs returned.
110         assertWithMessage("number of updated configs (the DO created one and the regular one)")
111                 .that(updateCount).isAtLeast(2);
112     }
113 
testDeviceOwnerCanRemoveConfig()114     public void testDeviceOwnerCanRemoveConfig() throws Exception {
115         List<WifiConfiguration> configs = getConfiguredNetworks();
116         logConfigs("testDeviceOwnerCanRemoveConfig()", configs);
117         int removeCount = 0;
118         for (WifiConfiguration config : configs) {
119             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)
120                     || areMatchingSsids(ORIGINAL_REGULAR_SSID, config.SSID)) {
121                 // On some devices a wpa3-sae configuration is auto-created for every wpa2
122                 // config, and they are auto-removed when the corresponding config is removed.
123                 // Recheck every config against the latest list of wifi configurations and skip
124                 // those which is already auto-removed.
125                 Log.d(TAG, "Checking if SSID " + config.SSID + " / id " + config.networkId
126                         + " should be removed");
127                 if (getConfiguredNetworks().stream()
128                         .noneMatch(c -> c.networkId == config.networkId)) {
129                     Log.d(TAG, "Skipping it");
130                     continue;
131                 }
132                 Log.d(TAG, "Removing using " + mWifiManager);
133                 assertWithMessage("removeNetwork(%s)", config.networkId)
134                         .that(mWifiManager.removeNetwork(config.networkId)).isTrue();
135                 ++removeCount;
136             }
137         }
138         logConfigs("After removing " + removeCount, configs);
139         assertWithMessage("number of removed configs (the DO created one and the regular one)")
140                 .that(removeCount).isEqualTo(2);
141     }
142 
testRegularAppCannotUpdateDeviceOwnerConfig()143     public void testRegularAppCannotUpdateDeviceOwnerConfig() throws Exception {
144         List<WifiConfiguration> configs = getConfiguredNetworks();
145         logConfigs("testRegularAppCannotUpdateDeviceOwnerConfig()", configs);
146         int updateCount = 0;
147         for (WifiConfiguration config : configs) {
148             Log.d(TAG, "testRegularAppCannotUpdateDeviceOwnerConfig(): testing " + config.SSID);
149             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)) {
150                 startRegularActivity(ACTION_UPDATE_WIFI_CONFIG, config.networkId,
151                         CHANGED_DEVICE_OWNER_SSID, SECURITY_TYPE_NONE, null);
152                 ++updateCount;
153             }
154         }
155         // There might be auto-upgrade configs returned.
156         assertWithMessage("number of updated configs (the DO created one)")
157                 .that(updateCount).isAtLeast(1);
158 
159         // Assert nothing has changed
160         configs = getConfiguredNetworks();
161         int notChangedCount = 0;
162         for (WifiConfiguration config : configs) {
163             Log.d(TAG, "testRegularAppCannotUpdateDeviceOwnerConfig(): testing " + config.SSID);
164             assertWithMessage("matching ssids for %s / %s", CHANGED_DEVICE_OWNER_SSID, config.SSID)
165                     .that(areMatchingSsids(CHANGED_DEVICE_OWNER_SSID, config.SSID)).isFalse();
166             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)) {
167                 ++notChangedCount;
168             }
169         }
170         // There might be auto-upgrade configs returned.
171         assertWithMessage("number of unchanged configs").that(notChangedCount).isAtLeast(1);
172     }
173 
testRegularAppCannotRemoveDeviceOwnerConfig()174     public void testRegularAppCannotRemoveDeviceOwnerConfig() throws Exception {
175         List<WifiConfiguration> configs = getConfiguredNetworks();
176         logConfigs("testRegularAppCannotUpdateDeviceOwnerConfig()", configs);
177         int removeCount = 0;
178         for (WifiConfiguration config : configs) {
179             Log.d(TAG, "testRegularAppCannotRemoveDeviceOwnerConfig(): testing " + config.SSID);
180             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)) {
181                 startRegularActivity(ACTION_REMOVE_WIFI_CONFIG, config.networkId,
182                         null, SECURITY_TYPE_NONE, null);
183                 ++removeCount;
184             }
185         }
186 
187         // There might be auto-upgrade configs returned.
188         assertWithMessage("number of removed configs (the DO created one)")
189                 .that(removeCount).isAtLeast(1);
190 
191         // Assert nothing has changed
192         configs = getConfiguredNetworks();
193         int notChangedCount = 0;
194         for (WifiConfiguration config : configs) {
195             Log.d(TAG, "testRegularAppCannotRemoveDeviceOwnerConfig(): testing " + config.SSID);
196             if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)) {
197                 ++notChangedCount;
198             }
199         }
200         // There might be auto-upgrade configs returned.
201         assertWithMessage("number of unchanged configs").that(notChangedCount).isAtLeast(1);
202     }
203 
startRegularActivity(String action, int netId, String ssid, int securityType, String password)204     private void startRegularActivity(String action, int netId, String ssid, int securityType,
205             String password) throws InterruptedException {
206         Intent createRegularConfig = new Intent(action);
207         createRegularConfig.putExtra(EXTRA_NETID, netId);
208         createRegularConfig.putExtra(EXTRA_SSID, ssid);
209         createRegularConfig.putExtra(EXTRA_SECURITY_TYPE, securityType);
210         createRegularConfig.putExtra(EXTRA_PASSWORD, password);
211         createRegularConfig.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
212         Log.d(TAG, "Starting " + action  + " on user " + mContext.getUserId());
213         mContext.startActivity(createRegularConfig);
214 
215         // Give some time for the other app to finish the action
216         Log.d(TAG, "Sleeping 5s");
217         Thread.sleep(5000);
218     }
219 
areMatchingSsids(String s1, String s2)220     private boolean areMatchingSsids(String s1, String s2) {
221         if (s1 == null || s2 == null) {
222             return false;
223         }
224         return s1.replace("\"", "").equals(s2.replace("\"", ""));
225     }
226 
logConfigs(String prefix, List<WifiConfiguration> configs)227     private void logConfigs(String prefix, List<WifiConfiguration> configs) {
228         if (configs == null) {
229             Log.d(TAG, prefix + ": null configs");
230             return;
231         }
232         Log.d(TAG, prefix + ": " + configs.size() + " configs: "
233                 + configs.stream().map((c) -> c.SSID + "/" + c.networkId)
234                         .collect(Collectors.toList()));
235     }
236 }
237