aboutsummaryrefslogtreecommitdiffstats
path: root/test/config.py
blob: b1a76772ffdf7294ce6fc36643dc4a700513136b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#
# -*- coding: utf-8 -*-
# Wireshark tests
# By Gerald Combs <gerald@wireshark.org>
#
# Ported from a set of Bash scripts which were copyright 2005 Ulf Lamping
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
'''Configuration'''

import logging
import os
import os.path
import re
import shutil
import subprocess
import sys
import tempfile

commands = (
    'capinfos',
    'dumpcap',
    'mergecap',
    'rawshark',
    'sharkd',
    'text2pcap',
    'tshark',
    'wireshark',
)

can_capture = False
capture_interface = None

# Our executables
program_path = None
# Strings
cmd_capinfos = None
cmd_dumpcap = None
cmd_mergecap = None
cmd_rawshark = None
cmd_tshark = None
cmd_text2pcap = None
cmd_wireshark = None
# Arrays
args_ping = None

have_lua = False
have_nghttp2 = False
have_kerberos = False
have_libgcrypt16 = False
have_libgcrypt17 = False

test_env = None
program_path = None
home_path = None
conf_path = None
custom_profile_path = None
custom_profile_name = 'Custom Profile'

this_dir = os.path.dirname(__file__)
baseline_dir = os.path.join(this_dir, 'baseline')
capture_dir = os.path.join(this_dir, 'captures')
config_dir = os.path.join(this_dir, 'config')
key_dir = os.path.join(this_dir, 'keys')
lua_dir = os.path.join(this_dir, 'lua')
tools_dir = os.path.join(this_dir, '..', 'tools')

all_groups = []

def canCapture():
    # XXX This appears to be evaluated at the wrong time when called
    # from a unittest.skipXXX decorator.
    return can_capture and capture_interface is not None

def setCanCapture(new_cc):
    can_capture = new_cc

def setCaptureInterface(iface):
    global capture_interface
    setCanCapture(True)
    capture_interface = iface

def canMkfifo():
    return not sys.platform.startswith('win32')

def canDisplay():
    if sys.platform.startswith('win32') or sys.platform.startswith('darwin'):
        return True
    # Qt requires XKEYBOARD and Xrender, which Xvnc doesn't provide.
    return False

def getTsharkInfo():
    global have_lua
    global have_nghttp2
    global have_kerberos
    global have_libgcrypt16
    global have_libgcrypt17
    if not cmd_tshark:
        logging.warning("tshark binary is not yet set")
        return
    try:
        tshark_v = subprocess.check_output(
            (cmd_tshark, '--version'),
            stderr=subprocess.PIPE,
            universal_newlines=True,
            env=baseEnv()
        ).replace('\n', ' ')
    except subprocess.CalledProcessError as e:
        logging.warning("Failed to detect tshark features: %s", e)
        tshark_v = ''
    have_lua = bool(re.search('with +Lua', tshark_v))
    have_nghttp2 = bool(re.search('with +nghttp2', tshark_v))
    have_kerberos = bool(re.search('(with +MIT +Kerberos|with +Heimdal +Kerberos)', tshark_v))
    gcry_m = re.search('with +Gcrypt +([0-9]+\.[0-9]+)', tshark_v)
    have_libgcrypt16 = gcry_m and float(gcry_m.group(1)) >= 1.6
    have_libgcrypt17 = gcry_m and float(gcry_m.group(1)) >= 1.7

def getDefaultCaptureInterface():
    '''Choose a default capture interface for our platform. Currently Windows only.'''
    global capture_interface
    if capture_interface:
        return
    if cmd_dumpcap is None:
        return
    if not sys.platform.startswith('win32'):
        return
    try:
        dumpcap_d_data = subprocess.check_output((cmd_dumpcap, '-D'), stderr=subprocess.PIPE)
        if sys.version_info[0] >= 3:
            dumpcap_d_stdout = dumpcap_d_data.decode('UTF-8', 'replace')
        else:
            dumpcap_d_stdout = unicode(dumpcap_d_data, 'UTF-8', 'replace')
        for d_line in dumpcap_d_stdout.splitlines():
            iface_m = re.search('(\d+)\..*(Ethernet|Network Connection|VMware|Intel)', d_line)
            if iface_m:
                capture_interface = iface_m.group(1)
                break
    except:
        pass

def getPingCommand():
    '''Return an argument list required to ping www.wireshark.org for 60 seconds.'''
    global args_ping
    # XXX The shell script tests swept over packet sizes from 1 to 240 every 0.25 seconds.
    if sys.platform.startswith('win32'):
        # XXX Check for psping? https://docs.microsoft.com/en-us/sysinternals/downloads/psping
        args_ping = ('ping', '-n', '60', '-l', '100', 'www.wireshark.org')
    elif sys.platform.startswith('linux') or sys.platform.startswith('freebsd'):
        args_ping = ('ping', '-c', '240', '-s', '100', '-i', '0.25', 'www.wireshark.org')
    elif sys.platform.startswith('darwin'):
        args_ping = ('ping', '-c', '1', '-g', '1', '-G', '240', '-i', '0.25', 'www.wireshark.org')
    # XXX Other BSDs, Solaris, etc

def setProgramPath(path):
    global program_path
    program_path = path
    retval = True
    dotexe = ''
    if sys.platform.startswith('win32'):
        dotexe = '.exe'
    for cmd in commands:
        cmd_var = 'cmd_' + cmd
        cmd_path = os.path.normpath(os.path.join(path, cmd + dotexe))
        if not os.path.exists(cmd_path) or not os.access(cmd_path, os.X_OK):
            cmd_path = None
            program_path = None
            retval = False
        globals()[cmd_var] = cmd_path
    getTsharkInfo()
    getDefaultCaptureInterface()
    setUpHostFiles()
    return retval

def baseEnv(home=None):
    """A modified environment to ensure reproducible tests."""
    env = os.environ.copy()
    env['TZ'] = 'UTC'
    home_env = 'APPDATA' if sys.platform.startswith('win32') else 'HOME'
    if home:
        env[home_env] = home
    else:
        # This directory is supposed not to be written and is used by
        # "readonly" tests that do not read any other preferences.
        env[home_env] = "/wireshark-tests-unused"
    return env

def setUpTestEnvironment():
    global home_path
    global conf_path
    global custom_profile_path
    global test_env

    # Create our directories
    test_confdir = tempfile.mkdtemp(prefix='wireshark-tests.')
    home_path = os.path.join(test_confdir, 'home')
    if sys.platform.startswith('win32'):
        conf_path = os.path.join(home_path, 'Wireshark')
    else:
        conf_path = os.path.join(home_path, '.config', 'wireshark')
    os.makedirs(conf_path)
    # Test spaces while we're here.
    custom_profile_path = os.path.join(conf_path, 'profiles', custom_profile_name)
    os.makedirs(custom_profile_path)

    # Populate our UAT files
    uat_files = [
        '80211_keys',
        'dtlsdecrypttablefile',
        'esp_sa',
        'ssl_keys',
        'c1222_decryption_table',
        'ikev1_decryption_table',
        'ikev2_decryption_table',
    ]
    for uat in uat_files:
        setUpUatFile(uat)

    # Set up our environment
    test_env = baseEnv(home=home_path)
    test_env['WIRESHARK_RUN_FROM_BUILD_DIRECTORY'] = 'True'
    test_env['WIRESHARK_QUIT_AFTER_CAPTURE'] = 'True'

def setUpUatFile(conf_file):
    global home_path
    global conf_path
    if home_path is None or conf_path is None:
        setUpTestEnvironment()
    template = os.path.join(os.path.dirname(__file__), 'config', conf_file) + '.tmpl'
    with open(template, 'r') as tplt_fd:
        tplt_contents = tplt_fd.read()
        tplt_fd.close()
        key_dir_path = os.path.join(key_dir, '')
        # uat.c replaces backslashes...
        key_dir_path = key_dir_path.replace('\\', '\\x5c')
        cf_contents = tplt_contents.replace('TEST_KEYS_DIR', key_dir_path)
    out_file = os.path.join(conf_path, conf_file)
    with open(out_file, 'w') as cf_fd:
        cf_fd.write(cf_contents)
        cf_fd.close()

def setUpHostFiles():
    global program_path
    global conf_path
    global custom_profile_path
    if program_path is None:
        return
    if conf_path is None or custom_profile_path is None:
        setUpTestEnvironment()
    bundle_path = os.path.join(program_path, 'Wireshark.app', 'Contents', 'MacOS')
    if os.path.isdir(bundle_path):
        global_path = bundle_path
    else:
        global_path = program_path
    hosts_path_pfx = os.path.join(this_dir, 'hosts.')
    shutil.copyfile(hosts_path_pfx + 'global', os.path.join(global_path, 'hosts'))
    shutil.copyfile(hosts_path_pfx + 'personal', os.path.join(conf_path, 'hosts'))
    shutil.copyfile(hosts_path_pfx + 'custom', os.path.join(custom_profile_path, 'hosts'))

if sys.platform.startswith('win32') or sys.platform.startswith('darwin'):
    can_capture = True

# Initialize ourself.
getPingCommand()