diff --git a/test_orc/modules/conn/conf/module_config.json b/test_orc/modules/conn/conf/module_config.json index 25145980e..0f599c5d3 100644 --- a/test_orc/modules/conn/conf/module_config.json +++ b/test_orc/modules/conn/conf/module_config.json @@ -22,15 +22,15 @@ "description": "The device under test hs a MAC address prefix that is registered against a known manufacturer.", "expected_behavior": "The MAC address prefix is registered in the IEEE Organizationally Unique Identifier database." }, + { + "name": "connection.single_ip", + "description": "The network switch port connected to the device reports only one IP address for the device under test.", + "expected_behavior": "The device under test does not behave as a network switch and only requets one IP address. This test is to avoid that devices implement network switches that allow connecting strings of daisy chained devices to one single network port, as this would not make 802.1x port based authentication possible." + }, { "name": "connection.target_ping", "description": "The device under test responds to an ICMP echo (ping) request.", "expected_behavior": "The device under test responds to an ICMP echo (ping) request." - }, - { - "name": "connection.mac_oui", - "description": "The device under test hs a MAC address prefix that is registered against a known manufacturer.", - "expected_behavior": "The MAC address prefix is registered in the IEEE Organizationally Unique Identifier database." } ] } diff --git a/test_orc/modules/conn/conn.Dockerfile b/test_orc/modules/conn/conn.Dockerfile index 10130933d..cf25d0f02 100644 --- a/test_orc/modules/conn/conn.Dockerfile +++ b/test_orc/modules/conn/conn.Dockerfile @@ -7,6 +7,12 @@ RUN apt-get install -y wget #Update the oui.txt file from ieee RUN wget http://standards-oui.ieee.org/oui.txt -P /usr/local/etc/ +#Load the requirements file +COPY modules/conn/python/requirements.txt /testrun/python + +#Install all python requirements for the module +RUN pip3 install -r /testrun/python/requirements.txt + # Copy over all configuration files COPY modules/conn/conf /testrun/conf diff --git a/test_orc/modules/conn/python/requirements.txt b/test_orc/modules/conn/python/requirements.txt new file mode 100644 index 000000000..93b351f44 --- /dev/null +++ b/test_orc/modules/conn/python/requirements.txt @@ -0,0 +1 @@ +scapy \ No newline at end of file diff --git a/test_orc/modules/conn/python/src/connection_module.py b/test_orc/modules/conn/python/src/connection_module.py index 48d134584..196c335d8 100644 --- a/test_orc/modules/conn/python/src/connection_module.py +++ b/test_orc/modules/conn/python/src/connection_module.py @@ -15,11 +15,15 @@ """Connection test module""" import util import sys +from scapy.all import * from test_module import TestModule LOG_NAME = "test_connection" LOGGER = None OUI_FILE="/usr/local/etc/oui.txt" +DHCP_SERVER_CAPTURE_FILE = '/runtime/network/dhcp-1.pcap' +STARTUP_CAPTURE_FILE = '/runtime/device/startup.pcap' +MONITOR_CAPTURE_FILE = '/runtime/device/monitor.pcap' class ConnectionModule(TestModule): @@ -30,19 +34,6 @@ def __init__(self, module): global LOGGER LOGGER = self._get_logger() - def _connection_target_ping(self): - LOGGER.info("Running connection.target_ping") - - # If the ipv4 address wasn't resolved yet, try again - if self._device_ipv4_addr is None: - self._device_ipv4_addr = self._get_device_ipv4(self) - - if self._device_ipv4_addr is None: - LOGGER.error("No device IP could be resolved") - sys.exit(1) - else: - return self._ping(self._device_ipv4_addr) - def _connection_mac_address(self): LOGGER.info("Running connection.mac_address") if self._device_mac is not None: @@ -62,6 +53,52 @@ def _connection_mac_oui(self): LOGGER.info("No OUI Manufacturer found for: " + self._device_mac) return False, "No OUI Manufacturer found for: " + self._device_mac + def _connection_single_ip(self): + LOGGER.info("Running connection.single_ip") + + result = None + if self._device_mac is None: + LOGGER.info("No MAC address found: ") + return result, "No MAC address found." + + # Read all the pcap files containing DHCP packet information + packets = rdpcap(DHCP_SERVER_CAPTURE_FILE) + packets.append(rdpcap(STARTUP_CAPTURE_FILE)) + packets.append(rdpcap(MONITOR_CAPTURE_FILE)) + + # Extract MAC addresses from DHCP packets + mac_addresses = set() + LOGGER.info("Inspecting: " + str(len(packets)) + " packets") + for packet in packets: + # Option[1] = message-type, option 3 = DHCPREQUEST + if DHCP in packet and packet[DHCP].options[0][1] == 3: + mac_address = packet[Ether].src + mac_addresses.add(mac_address.upper()) + + # Check if the device mac address is in the list of DHCPREQUESTs + result = self._device_mac.upper() in mac_addresses + LOGGER.info("DHCPREQUEST detected from device: " + str(result)) + + # Check the unique MAC addresses to see if they match the device + for mac_address in mac_addresses: + LOGGER.info("DHCPREQUEST from MAC address: " + mac_address) + result &= self._device_mac.upper() == mac_address + return result + + + def _connection_target_ping(self): + LOGGER.info("Running connection.target_ping") + + # If the ipv4 address wasn't resolved yet, try again + if self._device_ipv4_addr is None: + self._device_ipv4_addr = self._get_device_ipv4(self) + + if self._device_ipv4_addr is None: + LOGGER.error("No device IP could be resolved") + sys.exit(1) + else: + return self._ping(self._device_ipv4_addr) + def _get_oui_manufacturer(self,mac_address): # Do some quick fixes on the format of the mac_address # to match the oui file pattern