1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import dbus
6import logging
7import sys
8
9from autotest_lib.client.bin import test
10from autotest_lib.client.cros import shill_temporary_profile
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.cros.networking import wifi_proxy
13
14class network_WiFiInvalidParameters(test.test):
15    """Test that shill will reject invalid WiFi service configurations.
16
17    In particular, this test checks shill's behavior with invalid SSIDs,
18    WEP keys, and WPA passphrases.
19
20    """
21    version = 1
22    unique_counter = 1
23
24
25    SSID_TOO_LONG = ('MaxLengthSSID' * 8)[:33]
26    SSID_TOO_SHORT = ''
27
28    WPA_PASSPHRASE_TOO_LONG = ('x123456789' * 8)[:64]
29    WPA_PASSPHRASE_TOO_SHORT= 'x123456'
30    WPA_PMK_TOO_LONG = ('0123456789' * 8)[:65]
31
32
33    @staticmethod
34    def get_ssid():
35        """@return string a unique SSID."""
36        reserved_value = network_WiFiInvalidParameters.unique_counter
37        network_WiFiInvalidParameters.unique_counter += 1
38        return 'an ssid%d' % reserved_value
39
40
41    def check_bad_ssids(self, shill):
42        """Assert that shill will reject attempts connect to invalid SSIDs.
43
44        @param shill ShillProxy object representing shill.
45
46        """
47        bad_ssids = [self.SSID_TOO_LONG, self.SSID_TOO_SHORT]
48        for ssid in bad_ssids:
49            config_params = {shill.SERVICE_PROPERTY_TYPE: 'wifi',
50                             shill.SERVICE_PROPERTY_SSID: ssid,
51                             shill.SERVICE_PROPERTY_SECURITY_CLASS: 'none'}
52            try:
53                accepted = True
54                shill.configure_service(config_params)
55            except dbus.exceptions.DBusException, e:
56                accepted = False
57                if (e.get_dbus_name() !=
58                        'org.chromium.flimflam.Error.InvalidNetworkName'):
59                    raise error.TestFail('Got an unexpected exception from '
60                                         'shill: %s: %s.' %
61                                         (e.get_dbus_name(),
62                                          e.get_dbus_message()))
63            if accepted:
64                raise error.TestFail('Expected shill to stop us, but it let us '
65                                     'configure a bad SSID "%r"' % ssid)
66
67
68    def check_bad_wep_keys(self, shill):
69        """Assert that shill will reject attempts to use invalid WEP keys.
70
71        @param shill ShillProxy object representing shill.
72
73        """
74        LONG_HEX_STRING = '0123456789abcdef' * 8
75        BAD_PREFIXES = ('4', '001', '-22', 'a', )
76        bad_keys = []
77        # Generate a bunch of hex keys.  Some of these are good ASCII keys, but
78        # we'll fix this in a moment.
79        for index in range(4):
80            for length in range(0, 10) + range(11, 26) + range(27, 30):
81                bad_keys.append('%d:%s' % (index, LONG_HEX_STRING[:length]))
82                bad_keys.append('%d:0x%s' % (index, LONG_HEX_STRING[:length]))
83        # |bad_keys| contains all bad hex keys, but some of those hex keys
84        # could be interpretted as valid ASCII keys.  Lets take those out.
85        good_keys = []
86        for key in bad_keys:
87            # 5 and 13 length keys are just ASCII keys.  7 and 15 are ASCII keys
88            # with the key index prefix.
89            if len(key) in (5, 7, 13, 15):
90                good_keys.append(key)
91        map(bad_keys.remove, good_keys)
92        # Now add some keys that are bad because the prefix is no good.
93        for valid_key in (LONG_HEX_STRING[:10], LONG_HEX_STRING[:26]):
94            for prefix in BAD_PREFIXES:
95                bad_keys.append('%s:%s' % (prefix, valid_key))
96                bad_keys.append('%s:0x%s' % (prefix, valid_key))
97        for valid_key in ('wep40', 'wep104is13len'):
98            for prefix in BAD_PREFIXES:
99                bad_keys.append('%s:%s' % (prefix, valid_key))
100        for key in bad_keys:
101            config_params = {shill.SERVICE_PROPERTY_TYPE: 'wifi',
102                             shill.SERVICE_PROPERTY_SSID: self.get_ssid(),
103                             shill.SERVICE_PROPERTY_PASSPHRASE: key,
104                             shill.SERVICE_PROPERTY_SECURITY_CLASS: 'wep'}
105            try:
106                accepted = True
107                shill.configure_service(config_params)
108            except dbus.exceptions.DBusException, e:
109                accepted = False
110                if (e.get_dbus_name() !=
111                        'org.chromium.flimflam.Error.InvalidPassphrase'):
112                    raise error.TestFail('Got an unexpected exception from '
113                                         'shill: %s: %s.' %
114                                         (e.get_dbus_name(),
115                                          e.get_dbus_message()))
116
117            if accepted:
118                raise error.TestFail('Expected shill to stop us, but it let us '
119                                     'configure a bad WEP key: %s' % key)
120
121        for key in good_keys:
122            config_params = {shill.SERVICE_PROPERTY_TYPE: 'wifi',
123                             shill.SERVICE_PROPERTY_SSID: self.get_ssid(),
124                             shill.SERVICE_PROPERTY_PASSPHRASE: key,
125                             shill.SERVICE_PROPERTY_SECURITY_CLASS: 'wep'}
126            try:
127                shill.configure_service(config_params)
128            except:
129                logging.error('%r', sys.exc_info())
130                raise error.TestFail('shill should let us use a WEP key '
131                                     'like: %s' % key)
132
133
134    def check_bad_wpa_passphrases(self, shill):
135        """Assert that shill will reject invalid WPA passphrases.
136
137        @param shill ShillProxy object representing shill.
138
139        """
140        bad_passphrases = [self.WPA_PASSPHRASE_TOO_LONG,
141                           self.WPA_PASSPHRASE_TOO_SHORT,
142                           self.WPA_PMK_TOO_LONG]
143        for psk in bad_passphrases:
144            for security in ('rsn', 'wpa', 'psk'):
145                config_params = {
146                    shill.SERVICE_PROPERTY_TYPE: 'wifi',
147                    shill.SERVICE_PROPERTY_SSID: self.get_ssid(),
148                    shill.SERVICE_PROPERTY_PASSPHRASE: psk,
149                    shill.SERVICE_PROPERTY_SECURITY_RAW: security}
150                try:
151                    accepted = True
152                    shill.configure_service(config_params)
153                except dbus.exceptions.DBusException, e:
154                    accepted = False
155                    if (e.get_dbus_name() !=
156                            'org.chromium.flimflam.Error.InvalidPassphrase'):
157                        raise error.TestFail('Got an unexpected exception from '
158                                             'shill: %s: %s.' %
159                                             (e.get_dbus_name(),
160                                              e.get_dbus_message()))
161                if accepted:
162                    raise error.TestFail('Expected shill to stop us, but it '
163                                         'let us configure a bad passphrase: '
164                                         '%s' % psk)
165
166
167    def run_once(self):
168        """Test body."""
169        shill = wifi_proxy.WifiProxy.get_proxy()
170        with shill_temporary_profile.ShillTemporaryProfile(shill.manager):
171            self.check_bad_ssids(shill)
172            self.check_bad_wep_keys(shill)
173            self.check_bad_wpa_passphrases(shill)
174