• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2#   Copyright 2018 - 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
16from acts import asserts
17from acts import base_test
18from acts.test_decorators import test_tracker_info
19from acts.test_utils.net.net_test_utils import start_tcpdump
20from acts.test_utils.net.net_test_utils import stop_tcpdump
21from acts.test_utils.wifi import wifi_test_utils as wutils
22from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
23
24
25from scapy.all import IP
26from scapy.all import TCP
27from scapy.all import UDP
28from scapy.all import Raw
29from scapy.all import rdpcap
30from scapy.all import Scapy_Exception
31
32
33class ProxyTest(WifiBaseTest):
34    """ Network proxy tests """
35
36    def setup_class(self):
37        """ Setup devices for tests and unpack params """
38        self.dut = self.android_devices[0]
39        req_params = ("proxy_pac", "proxy_server",
40                      "proxy_port", "bypass_host", "non_bypass_host")
41        opt_params = ["reference_networks", "wpa_networks",]
42        self.unpack_userparams(req_param_names=req_params,
43                               opt_param_names=opt_params)
44        if "AccessPoint" in self.user_params:
45            self.legacy_configure_ap_and_start(wpa_network=True)
46        asserts.assert_true(len(self.reference_networks) > 0,
47                            "Need at least one reference network with psk.")
48        self.wifi_network = self.reference_networks[0]["2g"]
49        wutils.wifi_test_device_init(self.dut)
50        wutils.wifi_toggle_state(self.dut, True)
51        wutils.wifi_connect(self.dut, self.wifi_network)
52        self.tcpdump_pid = None
53        self.proxy_port = int(self.proxy_port)
54
55    def teardown_test(self):
56        self.dut.droid.connectivityResetGlobalProxy()
57        global_proxy = self.dut.droid.connectivityGetGlobalProxy()
58        if global_proxy:
59            self.log.error("Failed to reset global proxy settings")
60
61    def teardown_class(self):
62        wutils.reset_wifi(self.dut)
63
64    def on_fail(self, test_name, begin_time):
65        self.dut.take_bug_report(test_name, begin_time)
66
67    """ Helper methods """
68
69    def _verify_http_request(self, ad):
70        """ Send http requests to hosts
71
72        Steps:
73            1. Send http requests to hosts
74                a. Host that is bypassed by proxy server
75                b. Host that goes through proxy server
76            2. Verify that both return valid responses
77
78        Args:
79            1. ad: dut to run http requests
80        """
81        for host in [self.bypass_host, self.non_bypass_host]:
82            host = "https://%s" % host
83            result = ad.droid.httpRequestString(host)
84            asserts.assert_true(result, "Http request failed for %s" % host)
85
86    def _verify_proxy_server(self, pcap_file, bypass_host, hostname):
87        """ Verify that http requests are going through proxy server
88
89        Args:
90            1. tcpdump: pcap file
91            2. bypass_host: boolean value if the request goes through proxy
92            3. hostname: hostname requested
93
94        Returns:
95            True/False if the bypass condition met
96        """
97        self.log.info("Checking proxy server for query to: %s" % hostname)
98        try:
99            packets = rdpcap(pcap_file)
100        except Scapy_Exception:
101            asserts.fail("Not a valid pcap file")
102
103        dns_query = False
104        http_query = False
105        for pkt in packets:
106            summary = "%s" % pkt.summary()
107            if UDP in pkt and pkt[UDP].dport == 53 and hostname in summary:
108                dns_query = True
109                break
110            if TCP in pkt and pkt[TCP].dport == self.proxy_port and Raw in pkt\
111                and hostname in str(pkt[Raw]):
112                  http_query = True
113
114        self.log.info("Bypass hostname set to: %s" % bypass_host)
115        self.log.info("Found DNS query for host: %s" % dns_query)
116        self.log.info("Found HTTP query for host: %s" % http_query)
117        if bypass_host and http_query and not dns_query or \
118            not bypass_host and not http_query and dns_query:
119              return False
120        return True
121
122    def _test_proxy(self):
123        """ Test pac piroxy and manual proxy settings
124
125        Steps:
126            1. Start tcpdump
127            2. Run http requests
128            3. Stop tcpdump
129            4. Verify the packets from tcpdump have valid queries
130        """
131
132        # start tcpdump on the device
133        self.tcpdump_pid = start_tcpdump(self.dut, self.test_name)
134
135        # verify http requests
136        self._verify_http_request(self.dut)
137
138        # stop tcpdump on the device
139        pcap_file = stop_tcpdump(self.dut, self.tcpdump_pid, self.test_name)
140
141        # verify proxy server
142        result = self._verify_proxy_server(pcap_file, True, self.bypass_host)
143        asserts.assert_true(result, "Proxy failed for %s" % self.bypass_host)
144        result = self._verify_proxy_server(pcap_file, False, self.non_bypass_host)
145        asserts.assert_true(result, "Proxy failed for %s" % self.non_bypass_host)
146
147    """ Test Cases """
148
149    @test_tracker_info(uuid="16881315-1a50-48ce-bd36-7b0d2f21b734")
150    def test_pac_proxy_over_wifi(self):
151        """ Test proxy with auto config over wifi
152
153        Steps:
154            1. Connect to a wifi network
155            2. Set a global proxy with auto config
156            3. Do a http request on the hostnames
157            4. Verify that no DNS packets seen for non bypassed hostnames
158            5. Verify that DNS packets seen for bypassed hostnames
159        """
160        # set global pac proxy
161        self.log.info("Setting global proxy to: %s" % self.proxy_pac)
162        self.dut.droid.connectivitySetGlobalPacProxy(self.proxy_pac)
163        global_proxy = self.dut.droid.connectivityGetGlobalProxy()
164        asserts.assert_true(global_proxy['PacUrl'] == self.proxy_pac,
165                            "Failed to set pac proxy")
166
167        # test proxy
168        self._test_proxy()
169
170    @test_tracker_info(uuid="4d3361f6-866d-423c-9ed7-5a6943575fe9")
171    def test_manual_proxy_over_wifi(self):
172        """ Test manual proxy over wifi
173
174        Steps:
175            1. Connect to a wifi network
176            2. Set a global manual proxy with proxy server, port & bypass URLs
177            3. Do a http request on the hostnames
178            4. Verify that no DNS packets are seen for non bypassed hostnames
179            5. Verify that DNS packets seen for bypassed hostnames
180        """
181        # set global manual proxy
182        self.log.info("Setting global proxy to: %s %s %s" %
183                      (self.proxy_server, self.proxy_port, self.bypass_host))
184        self.dut.droid.connectivitySetGlobalProxy(self.proxy_server,
185                                                  self.proxy_port,
186                                                  self.bypass_host)
187        global_proxy = self.dut.droid.connectivityGetGlobalProxy()
188        asserts.assert_true(global_proxy['Hostname'] == self.proxy_server,
189                            "Failed to set manual proxy")
190
191        # test proxy
192        self._test_proxy()
193