blob: 0f13a0cf53524d371be5c464b44c7315232bfe44 [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
25WifiEnums = wutils.WifiEnums
Ang Li73697b32015-12-03 00:41:53 +000026
27# EAP Macros
28EAP = WifiEnums.Eap
29EapPhase2 = WifiEnums.EapPhase2
30
31# Enterprise Config Macros
32Ent = WifiEnums.Enterprise
Ang Li73697b32015-12-03 00:41:53 +000033
Ang Li8e767182015-12-09 17:29:24 -080034class WifiEnterpriseTest(acts.base_test.BaseTestClass):
Ang Li73697b32015-12-03 00:41:53 +000035
36 def __init__(self, controllers):
Ang Lie8ed2b32015-12-11 12:30:20 -080037 acts.base_test.BaseTestClass.__init__(self, controllers)
Ang Li73697b32015-12-03 00:41:53 +000038 self.tests = (
39 "test_eap_connect",
40 "test_eap_connect_negative",
Ang Li73697b32015-12-03 00:41:53 +000041 )
42
43 def setup_class(self):
44 self.dut = self.android_devices[0]
Ang Li8e767182015-12-09 17:29:24 -080045 wutils.wifi_test_device_init(self.dut)
Ang Li73697b32015-12-03 00:41:53 +000046 required_userparam_names = (
47 "ca_cert",
48 "client_cert",
49 "client_key",
50 "passpoint_ca_cert",
51 "passpoint_client_cert",
52 "passpoint_client_key",
53 "eap_identity",
54 "eap_password",
55 "invalid_ca_cert",
56 "invalid_client_cert",
57 "invalid_client_key",
58 "fqdn",
59 "provider_friendly_name",
60 "realm",
61 "ssid_peap",
62 "ssid_tls",
63 "ssid_ttls",
64 "ssid_sim",
65 "ssid_passpoint",
66 "device_password",
67 "ping_addr"
68 )
69 optional_userparam_names = (
70 "roaming_consortium_ids",
71 "plmn"
72 )
Ang Li5cd6d3c2016-02-01 11:29:14 -080073 self.unpack_userparams(required_userparam_names,
Ang Li73697b32015-12-03 00:41:53 +000074 opt_param_names = optional_userparam_names)
75 # Default configs for EAP networks.
76 self.config_peap = {
77 Ent.EAP: EAP.PEAP,
78 Ent.CA_CERT: self.ca_cert,
79 Ent.IDENTITY: self.eap_identity,
80 Ent.PASSWORD: self.eap_password,
81 Ent.PHASE2: EapPhase2.MSCHAPV2,
82 WifiEnums.SSID_KEY: self.ssid_peap
83 }
84 self.config_tls = {
85 Ent.EAP: EAP.TLS,
86 Ent.CA_CERT: self.ca_cert,
87 WifiEnums.SSID_KEY: self.ssid_tls,
88 Ent.CLIENT_CERT: self.client_cert,
89 Ent.PRIVATE_KEY_ID: self.client_key,
90 Ent.IDENTITY: self.eap_identity,
91 }
92 self.config_ttls = {
93 Ent.EAP: EAP.TTLS,
94 Ent.CA_CERT: self.ca_cert,
95 Ent.IDENTITY: self.eap_identity,
96 Ent.PASSWORD: self.eap_password,
97 Ent.PHASE2: EapPhase2.MSCHAPV2,
98 WifiEnums.SSID_KEY: self.ssid_ttls
99 }
100 self.config_sim = {
101 Ent.EAP: EAP.SIM,
102 WifiEnums.SSID_KEY: self.ssid_sim,
103 }
104
105 # Base config for passpoint networks.
106 self.config_passpoint = {
107 Ent.FQDN: self.fqdn,
108 Ent.FRIENDLY_NAME: self.provider_friendly_name,
109 Ent.REALM: self.realm,
110 Ent.CA_CERT: self.passpoint_ca_cert
111 }
112 if hasattr(self, "plmn"):
113 self.config_passpoint[Ent.PLMN] = self.plmn
114 if hasattr(self, "roaming_consortium_ids"):
115 self.config_passpoint[Ent.ROAMING_IDS] = self.roaming_consortium_ids
116
117 # Default configs for passpoint networks.
118 self.config_passpoint_tls = dict(self.config_tls)
119 self.config_passpoint_tls.update(self.config_passpoint)
120 self.config_passpoint_tls[Ent.CLIENT_CERT] = self.passpoint_client_cert
121 self.config_passpoint_tls[Ent.PRIVATE_KEY_ID] = self.passpoint_client_key
122 del self.config_passpoint_tls[WifiEnums.SSID_KEY]
123 self.config_passpoint_ttls = dict(self.config_ttls)
124 self.config_passpoint_ttls.update(self.config_passpoint)
125 del self.config_passpoint_ttls[WifiEnums.SSID_KEY]
126 # Set screen lock password so ConfigStore is unlocked.
Ang Lia9d188f2016-02-17 18:03:01 -0800127 self.dut.droid.setDevicePassword(self.device_password)
Ang Li73697b32015-12-03 00:41:53 +0000128
129 def teardown_class(self):
Ang Li8e767182015-12-09 17:29:24 -0800130 wutils.reset_wifi(self.dut)
Ang Lia9d188f2016-02-17 18:03:01 -0800131 self.dut.droid.disableDevicePassword()
132 self.dut.ed.clear_all_events()
Ang Li73697b32015-12-03 00:41:53 +0000133
134 def setup_test(self):
Ang Lia9d188f2016-02-17 18:03:01 -0800135 self.dut.droid.wifiStartTrackingStateChange()
136 self.dut.droid.wakeLockAcquireBright()
137 self.dut.droid.wakeUpNow()
Ang Li8e767182015-12-09 17:29:24 -0800138 wutils.reset_wifi(self.dut)
Ang Lia9d188f2016-02-17 18:03:01 -0800139 self.dut.ed.clear_all_events()
Ang Li73697b32015-12-03 00:41:53 +0000140
141 def teardown_test(self):
Ang Lia9d188f2016-02-17 18:03:01 -0800142 self.dut.droid.wakeLockRelease()
143 self.dut.droid.goToSleepNow()
144 self.dut.droid.wifiStopTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +0000145
146 """Helper Functions"""
147
148 def eap_negative_connect_logic(self, config, ad):
149 """Tries to connect to an enterprise network with invalid credentials
150 and expect a failure.
151
152 Args:
153 config: A dict representing an invalid EAP credential.
154
155 Returns:
156 True if connection failed as expected, False otherwise.
157 """
Ang Li8e767182015-12-09 17:29:24 -0800158 verdict = wutils.eap_connect(config, ad)
Ang Li73697b32015-12-03 00:41:53 +0000159 self.assert_true(not verdict, "Connection should have failed.")
160 self.log.info("Connection failed as expected.")
161 return True
162
163 def expand_config_by_phase2(self, config):
164 """Take an enterprise config and generate a list of configs, each with
165 a different phase2 auth type.
166
167 Args:
168 config: A dict representing enterprise config.
169
170 Returns
171 A list of enterprise configs.
172 """
173 results = []
174 for phase2_type in EapPhase2:
175 # Skip a special case for passpoint TTLS.
176 if Ent.FQDN in config and phase2_type == EapPhase2.GTC:
177 continue
178 c = dict(config)
179 c[Ent.PHASE2] = phase2_type
180 results.append(c)
181 return results
182
183 def gen_eap_configs(self):
184 """Generates configurations for different EAP authentication types.
185
186 Returns:
187 A list of dicts each representing an EAP configuration.
188 """
189 configs = [self.config_tls]
190 # self.config_sim
Ang Li8e767182015-12-09 17:29:24 -0800191 configs += wutils.expand_enterprise_config_by_phase2(self.config_ttls)
192 configs += wutils.expand_enterprise_config_by_phase2(self.config_peap)
Ang Li73697b32015-12-03 00:41:53 +0000193 return configs
194
195 def gen_passpoint_configs(self):
196 """Generates passpoint configurations for different EAP authentication
197 types.
198
199 Returns:
200 A list of dicts each representing an EAP configuration for
201 passpoint networks.
202 """
203 configs = [self.config_passpoint_tls]
Ang Li8e767182015-12-09 17:29:24 -0800204 configs += wutils.expand_enterprise_config_by_phase2(self.config_passpoint_ttls)
Ang Li73697b32015-12-03 00:41:53 +0000205 return configs
206
207 def gen_negative_configs(self, configs, neg_params):
208 """Generic function used to generate negative configs.
209
210 For all the valid configurations, if a param in the neg_params also
211 exists in a config, a copy of the config is made with an invalid value
212 of the param.
213
214 Args:
215 configs: A list of valid configurations.
216 neg_params: A dict that has all the invalid values.
217
218 Returns:
219 A list of invalid configurations generated based on the valid
220 configurations. Each invalid configuration has a different invalid
221 field.
222 """
223 results = []
224 for c in configs:
225 for k, v in neg_params.items():
226 # Skip negative test for TLS's identity field since it's not
227 # used for auth.
228 if c[Ent.EAP] == EAP.TLS and k == Ent.IDENTITY:
229 continue
230 if k in c:
231 nc = dict(c)
232 nc[k] = v
233 nc["invalid_field"] = k
234 results.append(nc)
235 return results
236
237 def gen_negative_eap_configs(self):
238 """Generates invalid configurations for different EAP authentication
239 types.
240
241 For all the valid EAP configurations, if a param that is part of the
242 authentication info exists in a config, a copy of the config is made
243 with an invalid value of the param.
244
245 Returns:
246 A list of dicts each representing an invalid EAP configuration.
247 """
248 neg_params = {
249 Ent.CLIENT_CERT: self.invalid_client_cert,
250 Ent.CA_CERT: self.invalid_ca_cert,
251 Ent.PRIVATE_KEY_ID: self.invalid_client_key,
252 Ent.IDENTITY: "fake_identity",
253 Ent.PASSWORD: "wrong_password"
254 }
255 configs = self.gen_eap_configs()
256 return self.gen_negative_configs(configs, neg_params)
257
258 def gen_negative_passpoint_configs(self):
259 """Generates invalid configurations for different EAP authentication
260 types with passpoint support.
261
262 Returns:
263 A list of dicts each representing an invalid EAP configuration
264 with passpoint fields.
265 """
266 neg_params = {
267 Ent.CLIENT_CERT: self.invalid_client_cert,
268 Ent.CA_CERT: self.invalid_ca_cert,
269 Ent.PRIVATE_KEY_ID: self.invalid_client_key,
270 Ent.IDENTITY: "fake_identity",
271 Ent.PASSWORD: "wrong_password",
272 Ent.FQDN: "fake_fqdn",
273 Ent.REALM: "where_no_one_has_gone_before",
274 Ent.PLMN: "fake_plmn",
275 Ent.ROAMING_IDS: [1234567890, 9876543210]
276 }
277 configs = self.gen_passpoint_configs()
278 return self.gen_negative_configs(configs, neg_params)
279
280 def gen_eap_test_name(self, config, ad):
281 """Generates a test case name based on an EAP configuration.
282
283 Args:
284 config: A dict representing an EAP credential.
285 ad: Discarded. This is here because name function signature needs
286 to be consistent with logic function signature for generated
287 test cases.
288
289 Returns:
290 A string representing the name of a generated EAP test case.
291 """
292 name = "test_connect-%s" % config[Ent.EAP].name
293 if Ent.PHASE2 in config:
294 name += "-{}".format(config[Ent.PHASE2].name)
295 return name
296
297 def gen_passpoint_test_name(self, config, ad):
298 """Generates a test case name based on an EAP passpoint configuration.
299
300 Args:
301 config: A dict representing an EAP passpoint credential.
302 ad: Discarded. This is here because name function signature needs
303 to be consistent with logic function signature for generated
304 test cases.
305
306 Returns:
307 A string representing the name of a generated EAP passpoint connect
308 test case.
309 """
310 name = self.gen_eap_test_name(config, ad)
311 name = name.replace("connect", "passpoint_connect")
312 return name
313
314 """Tests"""
Ang Lie8ed2b32015-12-11 12:30:20 -0800315 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000316 def test_eap_connect(self):
317 """Test connecting to enterprise networks of different authentication
318 types.
319
320 The authentication types tested are:
321 EAP-TLS
322 EAP-PEAP with different phase2 types.
323 EAP-TTLS with different phase2 types.
324
325 Procedures:
326 For each enterprise wifi network
327 1. Connect to the network.
328 2. Send a GET request to a website and check response.
329
330 Expect:
331 Successful connection and Internet access through the enterprise
332 networks.
333 """
334 eap_configs = self.gen_eap_configs()
335 self.log.info("Testing %d different configs." % len(eap_configs))
Ang Li8e767182015-12-09 17:29:24 -0800336 random.shuffle(eap_configs)
Ang Li73697b32015-12-03 00:41:53 +0000337 failed = self.run_generated_testcases(
Ang Li8e767182015-12-09 17:29:24 -0800338 wutils.eap_connect,
Ang Li73697b32015-12-03 00:41:53 +0000339 eap_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800340 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000341 name_func=self.gen_eap_test_name)
342 msg = ("The following configs failed EAP connect test: %s" %
343 pprint.pformat(failed))
344 self.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000345
Ang Lie8ed2b32015-12-11 12:30:20 -0800346 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000347 def test_eap_connect_negative(self):
348 """Test connecting to enterprise networks.
349
350 Procedures:
351 For each enterprise wifi network
352 1. Connect to the network with invalid credentials.
353
354 Expect:
355 Fail to establish connection.
356 """
357 neg_eap_configs = self.gen_negative_eap_configs()
358 self.log.info("Testing %d different configs." % len(neg_eap_configs))
Ang Li8e767182015-12-09 17:29:24 -0800359 random.shuffle(neg_eap_configs)
Ang Li73697b32015-12-03 00:41:53 +0000360 def name_gen(config, ad):
361 name = self.gen_eap_test_name(config, ad)
362 name += "-with_wrong-{}".format(config["invalid_field"])
363 return name
364 failed = self.run_generated_testcases(
365 self.eap_negative_connect_logic,
366 neg_eap_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800367 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000368 name_func=name_gen)
369 msg = ("The following configs failed negative EAP connect test: %s" %
370 pprint.pformat(failed))
371 self.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000372
Ang Lie8ed2b32015-12-11 12:30:20 -0800373 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000374 def test_passpoint_connect(self):
375 """Test connecting to enterprise networks of different authentication
376 types with passpoint support.
377
378 The authentication types tested are:
379 EAP-TLS
380 EAP-TTLS with MSCHAPV2 as phase2.
381
382 Procedures:
383 For each enterprise wifi network
384 1. Connect to the network.
385 2. Send a GET request to a website and check response.
386
387 Expect:
388 Successful connection and Internet access through the enterprise
389 networks with passpoint support.
390 """
391 self.skip_if(not self.dut.droid.wifiIsPasspointSupported(),
392 "Passpoint is not supported on device %s" % self.dut.model)
393 passpoint_configs = self.gen_passpoint_configs()
394 self.log.info("Testing %d different configs." % len(passpoint_configs))
Ang Li8e767182015-12-09 17:29:24 -0800395 random.shuffle(passpoint_configs)
Ang Li73697b32015-12-03 00:41:53 +0000396 failed = self.run_generated_testcases(
Ang Li8e767182015-12-09 17:29:24 -0800397 wutils.eap_connect,
Ang Li73697b32015-12-03 00:41:53 +0000398 passpoint_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800399 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000400 name_func=self.gen_passpoint_test_name)
401 msg = ("The following configs failed passpoint connect test: %s" %
402 pprint.pformat(failed))
403 self.assert_true(len(failed) == 0, msg)
Ang Li73697b32015-12-03 00:41:53 +0000404
Ang Lie8ed2b32015-12-11 12:30:20 -0800405 @acts.signals.generated_test
Ang Li73697b32015-12-03 00:41:53 +0000406 def test_passpoint_connect_negative(self):
407 """Test connecting to enterprise networks.
408
409 Procedures:
410 For each enterprise wifi network
411 1. Connect to the network with invalid credentials.
412
413 Expect:
414 Fail to establish connection.
415 """
416 self.skip_if(not self.dut.droid.wifiIsPasspointSupported(),
417 "Passpoint is not supported on device %s" % self.dut.model)
418 neg_passpoint_configs = self.gen_negative_passpoint_configs()
419 self.log.info("Testing %d different configs." % len(neg_passpoint_configs))
Ang Li8e767182015-12-09 17:29:24 -0800420 random.shuffle(neg_passpoint_configs)
Ang Li73697b32015-12-03 00:41:53 +0000421 def name_gen(config, ad):
422 name = self.gen_passpoint_test_name(config, ad)
423 name += "-with_wrong-{}".format(config["invalid_field"])
424 return name
425 failed = self.run_generated_testcases(
426 self.eap_negative_connect_logic,
427 neg_passpoint_configs,
Alexander Dorokhine5e1433d2016-02-04 12:26:06 -0800428 args=(self.dut,),
Ang Li73697b32015-12-03 00:41:53 +0000429 name_func=name_gen)
430 msg = ("The following configs failed negative passpoint connect test: "
431 "%s") % pprint.pformat(failed)
432 self.assert_true(len(failed) == 0, msg)