blob: 3987e43ebcda3ea63992a1b21adee2a83d428135 [file] [log] [blame]
tturney1bdf77d2015-12-28 17:46:13 -08001#!/usr/bin/env python3.4
Ang Li73697b32015-12-03 00:41:53 +00002#
tturney1bdf77d2015-12-28 17:46:13 -08003# Copyright 2016 - The Android Open Source Project
Ang Li73697b32015-12-03 00:41:53 +00004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import pprint
Ang Li8e767182015-12-09 17:29:24 -080018import random
Ang Li73697b32015-12-03 00:41:53 +000019import time
20
Ang Li8e767182015-12-09 17:29:24 -080021import acts.base_test
Ang Lie8ed2b32015-12-11 12:30:20 -080022import acts.signals
Mitchell Wills930fa0e2016-01-29 16:17:13 -080023import acts.test_utils.wifi.wifi_test_utils as wutils
Ang Lie8ed2b32015-12-11 12:30:20 -080024
Ang Lic2d45212016-03-10 18:38:53 -080025from acts import asserts
26
Ang Lie8ed2b32015-12-11 12:30:20 -080027WifiEnums = wutils.WifiEnums
Ang Li73697b32015-12-03 00:41:53 +000028
29# EAP Macros
30EAP = WifiEnums.Eap
31EapPhase2 = WifiEnums.EapPhase2
32
33# Enterprise Config Macros
34Ent = WifiEnums.Enterprise
Ang Li73697b32015-12-03 00:41:53 +000035
Ang Li8e767182015-12-09 17:29:24 -080036class WifiEnterpriseTest(acts.base_test.BaseTestClass):
Ang Li73697b32015-12-03 00:41:53 +000037
38 def __init__(self, controllers):
Ang Lie8ed2b32015-12-11 12:30:20 -080039 acts.base_test.BaseTestClass.__init__(self, controllers)
Ang Li73697b32015-12-03 00:41:53 +000040 self.tests = (
41 "test_eap_connect",
42 "test_eap_connect_negative",
Ang Li73697b32015-12-03 00:41:53 +000043 )
44
45 def setup_class(self):
46 self.dut = self.android_devices[0]
Ang Li8e767182015-12-09 17:29:24 -080047 wutils.wifi_test_device_init(self.dut)
Ang Li73697b32015-12-03 00:41:53 +000048 required_userparam_names = (
49 "ca_cert",
50 "client_cert",
51 "client_key",
52 "passpoint_ca_cert",
53 "passpoint_client_cert",
54 "passpoint_client_key",
55 "eap_identity",
56 "eap_password",
57 "invalid_ca_cert",
58 "invalid_client_cert",
59 "invalid_client_key",
60 "fqdn",
61 "provider_friendly_name",
62 "realm",
63 "ssid_peap",
64 "ssid_tls",
65 "ssid_ttls",
66 "ssid_sim",
67 "ssid_passpoint",
68 "device_password",
69 "ping_addr"
70 )
71 optional_userparam_names = (
72 "roaming_consortium_ids",
73 "plmn"
74 )
Ang Li5cd6d3c2016-02-01 11:29:14 -080075 self.unpack_userparams(required_userparam_names,
Ang Li73697b32015-12-03 00:41:53 +000076 opt_param_names = optional_userparam_names)
77 # Default configs for EAP networks.
78 self.config_peap = {
79 Ent.EAP: EAP.PEAP,
80 Ent.CA_CERT: self.ca_cert,
81 Ent.IDENTITY: self.eap_identity,
82 Ent.PASSWORD: self.eap_password,
83 Ent.PHASE2: EapPhase2.MSCHAPV2,
84 WifiEnums.SSID_KEY: self.ssid_peap
85 }
86 self.config_tls = {
87 Ent.EAP: EAP.TLS,
88 Ent.CA_CERT: self.ca_cert,
89 WifiEnums.SSID_KEY: self.ssid_tls,
90 Ent.CLIENT_CERT: self.client_cert,
91 Ent.PRIVATE_KEY_ID: self.client_key,
92 Ent.IDENTITY: self.eap_identity,
93 }
94 self.config_ttls = {
95 Ent.EAP: EAP.TTLS,
96 Ent.CA_CERT: self.ca_cert,
97 Ent.IDENTITY: self.eap_identity,
98 Ent.PASSWORD: self.eap_password,
99 Ent.PHASE2: EapPhase2.MSCHAPV2,
100 WifiEnums.SSID_KEY: self.ssid_ttls
101 }
102 self.config_sim = {
103 Ent.EAP: EAP.SIM,
104 WifiEnums.SSID_KEY: self.ssid_sim,
105 }
106
107 # Base config for passpoint networks.
108 self.config_passpoint = {
109 Ent.FQDN: self.fqdn,
110 Ent.FRIENDLY_NAME: self.provider_friendly_name,
111 Ent.REALM: self.realm,
112 Ent.CA_CERT: self.passpoint_ca_cert
113 }
114 if hasattr(self, "plmn"):
115 self.config_passpoint[Ent.PLMN] = self.plmn
116 if hasattr(self, "roaming_consortium_ids"):
117 self.config_passpoint[Ent.ROAMING_IDS] = self.roaming_consortium_ids
118
119 # Default configs for passpoint networks.
120 self.config_passpoint_tls = dict(self.config_tls)
121 self.config_passpoint_tls.update(self.config_passpoint)
122 self.config_passpoint_tls[Ent.CLIENT_CERT] = self.passpoint_client_cert
123 self.config_passpoint_tls[Ent.PRIVATE_KEY_ID] = self.passpoint_client_key
124 del self.config_passpoint_tls[WifiEnums.SSID_KEY]
125 self.config_passpoint_ttls = dict(self.config_ttls)
126 self.config_passpoint_ttls.update(self.config_passpoint)
127 del self.config_passpoint_ttls[WifiEnums.SSID_KEY]
128 # Set screen lock password so ConfigStore is unlocked.
Ang Lia9d188f2016-02-17 18:03:01 -0800129 self.dut.droid.setDevicePassword(self.device_password)
Ang Li73697b32015-12-03 00:41:53 +0000130
131 def teardown_class(self):
Ang Li8e767182015-12-09 17:29:24 -0800132 wutils.reset_wifi(self.dut)
Ang Lia9d188f2016-02-17 18:03:01 -0800133 self.dut.droid.disableDevicePassword()
134 self.dut.ed.clear_all_events()
Ang Li73697b32015-12-03 00:41:53 +0000135
136 def setup_test(self):
Ang Lia9d188f2016-02-17 18:03:01 -0800137 self.dut.droid.wifiStartTrackingStateChange()
138 self.dut.droid.wakeLockAcquireBright()
139 self.dut.droid.wakeUpNow()
Ang Li8e767182015-12-09 17:29:24 -0800140 wutils.reset_wifi(self.dut)
Ang Lia9d188f2016-02-17 18:03:01 -0800141 self.dut.ed.clear_all_events()
Ang Li73697b32015-12-03 00:41:53 +0000142
143 def teardown_test(self):
Ang Lia9d188f2016-02-17 18:03:01 -0800144 self.dut.droid.wakeLockRelease()
145 self.dut.droid.goToSleepNow()
146 self.dut.droid.wifiStopTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +0000147
Ang Li20377aa2016-02-26 13:19:51 -0800148 def on_fail(self, test_name, begin_time):
149 self.dut.cat_adb_log(test_name, begin_time)
150
Ang Li73697b32015-12-03 00:41:53 +0000151 """Helper Functions"""
152
153 def eap_negative_connect_logic(self, config, ad):
154 """Tries to connect to an enterprise network with invalid credentials
155 and expect a failure.
156
157 Args:
158 config: A dict representing an invalid EAP credential.
159
160 Returns:
161 True if connection failed as expected, False otherwise.
162 """
Ang Li8e767182015-12-09 17:29:24 -0800163 verdict = wutils.eap_connect(config, ad)
Ang Lic2d45212016-03-10 18:38:53 -0800164 asserts.assert_true(not verdict, "Connection should have failed.")
Ang Li73697b32015-12-03 00:41:53 +0000165 self.log.info("Connection failed as expected.")
166 return True
167
168 def expand_config_by_phase2(self, config):
169 """Take an enterprise config and generate a list of configs, each with
170 a different phase2 auth type.
171
172 Args:
173 config: A dict representing enterprise config.
174
175 Returns
176 A list of enterprise configs.
177 """
178 results = []
179 for phase2_type in EapPhase2:
180 # Skip a special case for passpoint TTLS.
181 if Ent.FQDN in config and phase2_type == EapPhase2.GTC:
182 continue
183 c = dict(config)
184 c[Ent.PHASE2] = phase2_type
185 results.append(c)
186 return results
187
188 def gen_eap_configs(self):
189 """Generates configurations for different EAP authentication types.
190
191 Returns:
192 A list of dicts each representing an EAP configuration.
193 """
194 configs = [self.config_tls]
195 # self.config_sim
Ang Li8e767182015-12-09 17:29:24 -0800196 configs += wutils.expand_enterprise_config_by_phase2(self.config_ttls)
197 configs += wutils.expand_enterprise_config_by_phase2(self.config_peap)
Ang Li73697b32015-12-03 00:41:53 +0000198 return configs
199
200 def gen_passpoint_configs(self):
201 """Generates passpoint configurations for different EAP authentication
202 types.
203
204 Returns:
205 A list of dicts each representing an EAP configuration for
206 passpoint networks.
207 """
208 configs = [self.config_passpoint_tls]
Ang Li8e767182015-12-09 17:29:24 -0800209 configs += wutils.expand_enterprise_config_by_phase2(self.config_passpoint_ttls)
Ang Li73697b32015-12-03 00:41:53 +0000210 return configs
211
212 def gen_negative_configs(self, configs, neg_params):
213 """Generic function used to generate negative configs.
214
215 For all the valid configurations, if a param in the neg_params also
216 exists in a config, a copy of the config is made with an invalid value
217 of the param.
218
219 Args:
220 configs: A list of valid configurations.
221 neg_params: A dict that has all the invalid values.
222
223 Returns:
224 A list of invalid configurations generated based on the valid
225 configurations. Each invalid configuration has a different invalid
226 field.
227 """
228 results = []
229 for c in configs:
230 for k, v in neg_params.items():
231 # Skip negative test for TLS's identity field since it's not
232 # used for auth.
233 if c[Ent.EAP] == EAP.TLS and k == Ent.IDENTITY:
234 continue
235 if k in c:
236 nc = dict(c)
237 nc[k] = v
238 nc["invalid_field"] = k
239 results.append(nc)
240 return results
241
242 def gen_negative_eap_configs(self):
243 """Generates invalid configurations for different EAP authentication
244 types.
245
246 For all the valid EAP configurations, if a param that is part of the
247 authentication info exists in a config, a copy of the config is made
248 with an invalid value of the param.
249
250 Returns:
251 A list of dicts each representing an invalid EAP configuration.
252 """
253 neg_params = {
254 Ent.CLIENT_CERT: self.invalid_client_cert,
255 Ent.CA_CERT: self.invalid_ca_cert,
256 Ent.PRIVATE_KEY_ID: self.invalid_client_key,
257 Ent.IDENTITY: "fake_identity",
258 Ent.PASSWORD: "wrong_password"
259 }
260 configs = self.gen_eap_configs()
261 return self.gen_negative_configs(configs, neg_params)
262
263 def gen_negative_passpoint_configs(self):
264 """Generates invalid configurations for different EAP authentication
265 types with passpoint support.
266
267 Returns:
268 A list of dicts each representing an invalid EAP configuration
269 with passpoint fields.
270 """
271 neg_params = {
272 Ent.CLIENT_CERT: self.invalid_client_cert,
273 Ent.CA_CERT: self.invalid_ca_cert,
274 Ent.PRIVATE_KEY_ID: self.invalid_client_key,
275 Ent.IDENTITY: "fake_identity",
276 Ent.PASSWORD: "wrong_password",
277 Ent.FQDN: "fake_fqdn",
278 Ent.REALM: "where_no_one_has_gone_before",
279 Ent.PLMN: "fake_plmn",
280 Ent.ROAMING_IDS: [1234567890, 9876543210]
281 }
282 configs = self.gen_passpoint_configs()
283 return self.gen_negative_configs(configs, neg_params)
284
285 def gen_eap_test_name(self, config, ad):
286 """Generates a test case name based on an EAP configuration.
287
288 Args:
289 config: A dict representing an EAP credential.
290 ad: Discarded. This is here because name function signature needs
291 to be consistent with logic function signature for generated
292 test cases.
293
294 Returns:
295 A string representing the name of a generated EAP test case.
296 """
297 name = "test_connect-%s" % config[Ent.EAP].name
298 if Ent.PHASE2 in config:
299 name += "-{}".format(config[Ent.PHASE2].name)
300 return name
301
302 def gen_passpoint_test_name(self, config, ad):
303 """Generates a test case name based on an EAP passpoint configuration.
304
305 Args:
306 config: A dict representing an EAP passpoint credential.
307 ad: Discarded. This is here because name function signature needs
308 to be consistent with logic function signature for generated
309 test cases.
310
311 Returns:
312 A string representing the name of a generated EAP passpoint connect
313 test case.
314 """
315 name = self.gen_eap_test_name(config, ad)
316 name = name.replace("connect", "passpoint_connect")
317 return name
318
319 """Tests"""
Ang Lie8ed2b32015-12-11 12:30:20 -0800320 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000321 def test_eap_connect(self):
322 """Test connecting to enterprise networks of different authentication
323 types.
324
325 The authentication types tested are:
326 EAP-TLS
327 EAP-PEAP with different phase2 types.
328 EAP-TTLS with different phase2 types.
329
330 Procedures:
331 For each enterprise wifi network
332 1. Connect to the network.
333 2. Send a GET request to a website and check response.
334
335 Expect:
336 Successful connection and Internet access through the enterprise
337 networks.
338 """
339 eap_configs = self.gen_eap_configs()
340 self.log.info("Testing %d different configs." % len(eap_configs))
Ang Li8e767182015-12-09 17:29:24 -0800341 random.shuffle(eap_configs)
Ang Li73697b32015-12-03 00:41:53 +0000342 failed = self.run_generated_testcases(
Ang Li8e767182015-12-09 17:29:24 -0800343 wutils.eap_connect,
Ang Li73697b32015-12-03 00:41:53 +0000344 eap_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800345 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000346 name_func=self.gen_eap_test_name)
347 msg = ("The following configs failed EAP connect test: %s" %
348 pprint.pformat(failed))
Ang Lic2d45212016-03-10 18:38:53 -0800349 asserts.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000350
Ang Lie8ed2b32015-12-11 12:30:20 -0800351 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000352 def test_eap_connect_negative(self):
353 """Test connecting to enterprise networks.
354
355 Procedures:
356 For each enterprise wifi network
357 1. Connect to the network with invalid credentials.
358
359 Expect:
360 Fail to establish connection.
361 """
362 neg_eap_configs = self.gen_negative_eap_configs()
363 self.log.info("Testing %d different configs." % len(neg_eap_configs))
Ang Li8e767182015-12-09 17:29:24 -0800364 random.shuffle(neg_eap_configs)
Ang Li73697b32015-12-03 00:41:53 +0000365 def name_gen(config, ad):
366 name = self.gen_eap_test_name(config, ad)
367 name += "-with_wrong-{}".format(config["invalid_field"])
368 return name
369 failed = self.run_generated_testcases(
370 self.eap_negative_connect_logic,
371 neg_eap_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800372 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000373 name_func=name_gen)
374 msg = ("The following configs failed negative EAP connect test: %s" %
375 pprint.pformat(failed))
Ang Lic2d45212016-03-10 18:38:53 -0800376 asserts.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000377
Ang Lie8ed2b32015-12-11 12:30:20 -0800378 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000379 def test_passpoint_connect(self):
380 """Test connecting to enterprise networks of different authentication
381 types with passpoint support.
382
383 The authentication types tested are:
384 EAP-TLS
385 EAP-TTLS with MSCHAPV2 as phase2.
386
387 Procedures:
388 For each enterprise wifi network
389 1. Connect to the network.
390 2. Send a GET request to a website and check response.
391
392 Expect:
393 Successful connection and Internet access through the enterprise
394 networks with passpoint support.
395 """
Ang Lic2d45212016-03-10 18:38:53 -0800396 asserts.skip_if(not self.dut.droid.wifiIsPasspointSupported(),
Ang Li73697b32015-12-03 00:41:53 +0000397 "Passpoint is not supported on device %s" % self.dut.model)
398 passpoint_configs = self.gen_passpoint_configs()
399 self.log.info("Testing %d different configs." % len(passpoint_configs))
Ang Li8e767182015-12-09 17:29:24 -0800400 random.shuffle(passpoint_configs)
Ang Li73697b32015-12-03 00:41:53 +0000401 failed = self.run_generated_testcases(
Ang Li8e767182015-12-09 17:29:24 -0800402 wutils.eap_connect,
Ang Li73697b32015-12-03 00:41:53 +0000403 passpoint_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800404 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000405 name_func=self.gen_passpoint_test_name)
406 msg = ("The following configs failed passpoint connect test: %s" %
407 pprint.pformat(failed))
Ang Lic2d45212016-03-10 18:38:53 -0800408 asserts.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000409
Ang Lie8ed2b32015-12-11 12:30:20 -0800410 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000411 def test_passpoint_connect_negative(self):
412 """Test connecting to enterprise networks.
413
414 Procedures:
415 For each enterprise wifi network
416 1. Connect to the network with invalid credentials.
417
418 Expect:
419 Fail to establish connection.
420 """
Ang Lic2d45212016-03-10 18:38:53 -0800421 asserts.skip_if(not self.dut.droid.wifiIsPasspointSupported(),
Ang Li73697b32015-12-03 00:41:53 +0000422 "Passpoint is not supported on device %s" % self.dut.model)
423 neg_passpoint_configs = self.gen_negative_passpoint_configs()
424 self.log.info("Testing %d different configs." % len(neg_passpoint_configs))
Ang Li8e767182015-12-09 17:29:24 -0800425 random.shuffle(neg_passpoint_configs)
Ang Li73697b32015-12-03 00:41:53 +0000426 def name_gen(config, ad):
427 name = self.gen_passpoint_test_name(config, ad)
428 name += "-with_wrong-{}".format(config["invalid_field"])
429 return name
430 failed = self.run_generated_testcases(
431 self.eap_negative_connect_logic,
432 neg_passpoint_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800433 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000434 name_func=name_gen)
435 msg = ("The following configs failed negative passpoint connect test: "
436 "%s") % pprint.pformat(failed)
Ang Lic2d45212016-03-10 18:38:53 -0800437 asserts.assert_true(len(failed) == 0, msg)