Calendar: add FT sprint
[tails/test.git] / features / step_definitions / mac_spoofing.rb
bloba9a24fbfe3e44cddb2bd2a0a0731ae5468c36ec6
1 class MacSpoofingError < StandardError
2 end
4 def all_ethernet_nics
5   $vm.execute_successfully(
6     'get_all_ethernet_nics', libs: 'hardware'
7   ).stdout.split
8 end
10 When /^I disable MAC spoofing in Tails Greeter$/ do
11   open_greeter_additional_settings
12   @screen.wait('TailsGreeterMACSpoofing.png', 30).click
13   @screen.wait('TailsGreeterDisableMACSpoofing.png', 10).click
14   @screen.wait('TailsGreeterAdditionalSettingsAdd.png', 10).click
15 end
17 Then /^the (\d+)(?:st|nd|rd|th) network device has (its real|a spoofed) MAC address configured$/ do |dev_nr, mode|
18   is_spoofed = (mode == 'a spoofed')
19   alias_name = "net#{dev_nr.to_i - 1}"
20   nic_real_mac = $vm.real_mac(alias_name)
21   nic = "eth#{dev_nr.to_i - 1}"
22   nic_current_mac = $vm.execute_successfully(
23     "get_current_mac_of_nic #{nic}", libs: 'hardware'
24   ).stdout.chomp
25   begin
26     if is_spoofed
27       if nic_real_mac == nic_current_mac
28         raise MacSpoofingError,
29               "The MAC address was expected to be spoofed but wasn't"
30       end
31     elsif nic_real_mac != nic_current_mac
32       raise MacSpoofingError,
33             'The MAC address is spoofed but was expected to not be'
34     end
35   rescue MacSpoofingError => e
36     save_failure_artifact('Network capture', @sniffer.pcap_file)
37     raise e
38   end
39 end
41 Then /^no network device leaked the real MAC address$/ do
42   macs = $vm.all_real_macs
43   assert_all_connections(@sniffer.pcap_file) do |c|
44     macs.all? do |mac|
45       ![c.mac_saddr, c.mac_daddr].include?(mac)
46     end
47   end
48 end
50 Then /^some network device leaked the real MAC address$/ do
51   assert_raise(FirewallAssertionFailedError) do
52     step 'no network device leaked the real MAC address'
53   end
54 end
56 Given /^macchanger will fail by not spoofing and always returns ([\S]+)$/ do |mode|
57   $vm.execute_successfully('mv /usr/bin/macchanger /usr/bin/macchanger.orig')
58   $vm.execute_successfully("ln -s /bin/#{mode} /usr/bin/macchanger")
59 end
61 Given /^no network interface modules can be unloaded$/ do
62   # Note that the real /sbin/modprobe is a symlink to /bin/kmod, and
63   # for it to run in modprobe compatibility mode the name must be
64   # exactly "modprobe", so we just move it somewhere our of the path
65   # instead of renaming it ".real" or whatever we usuablly do when
66   # diverting executables for wrappers.
67   modprobe_divert = '/usr/local/lib/modprobe'
68   $vm.execute_successfully(
69     "dpkg-divert --add --rename --divert '#{modprobe_divert}' /sbin/modprobe"
70   )
71   fake_modprobe_wrapper = <<~WRAPPER
72     #!/bin/sh
73     if echo "${@}" | grep -q -- -r; then
74         exit 1
75     fi
76     exec '#{modprobe_divert}' "${@}"
77   WRAPPER
78   $vm.file_append('/sbin/modprobe', fake_modprobe_wrapper)
79   $vm.execute_successfully('chmod a+rx /sbin/modprobe')
80 end
82 Then /^(\d+|no) network interface(?:s)? (?:is|are) enabled$/ do |expected_nr_nics|
83   # note that "no".to_i => 0 in Ruby.
84   expected_nr_nics = expected_nr_nics.to_i
85   nr_nics = all_ethernet_nics.size
86   assert_equal(expected_nr_nics, nr_nics)
87 end
89 Then /^the MAC spoofing panic mode disabled networking$/ do
90   nm_state = $vm.execute_successfully('systemctl show NetworkManager').stdout
91   nm_is_disabled = $vm.pidof('NetworkManager').empty? &&
92                    nm_state[/^LoadState=masked$/] &&
93                    nm_state[/^ActiveState=inactive$/]
94   assert(nm_is_disabled, 'NetworkManager was not disabled')
95   all_ethernet_nics.each do |nic|
96     ['nic_ipv4_addr', 'nic_ipv6_addr'].each do |function|
97       addr = $vm.execute_successfully(
98         "#{function} #{nic}", libs: 'hardware'
99       ).stdout.chomp
100       assert_equal('', addr, "NIC #{nic} was assigned address #{addr}")
101     end
102   end
105 When /^I hotplug a network device( and wait for it to be initialized)?$/ do |wait|
106   initial_nr_nics = wait ? all_ethernet_nics.size : nil
107   device = 'pcnet'
108   debug_log("Hotplugging a '#{device}' network device")
109   xml = <<-XML
110     <interface type='network'>
111       <alias name='net1'/>
112       <mac address='52:54:00:11:22:33'/>
113       <source network='TailsToasterNet'/>
114       <model type='#{device}'/>
115       <link state='up'/>
116     </interface>
117   XML
118   $vm.plug_device(xml)
119   if wait
120     try_for(30) do
121       all_ethernet_nics.size >= initial_nr_nics + 1
122     end
123   end