def test_ethernet_packet_parses(self): packed_message = bytes.fromhex("0180c2000003001906eab88c888e0100000501010005010000") message = EthernetPacket.parse(packed_message) self.assertEqual(message.src_mac, MacAddress.from_string("00:19:06:ea:b8:8c")) self.assertEqual(message.dst_mac, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(message.ethertype, 0x888e) self.assertEqual(message.data, bytes.fromhex("0100000501010005010000"))
def test_eapol_logoff_message_packs(self): expected_packed_message = build_byte_string( "0180c2000003001906eab88c888e01020000") message = EapolLogoffMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c")) packed_message = MessagePacker.pack( message, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_ethernet_packet_packs(self): expected_packed_message = bytes.fromhex( "0180c2000003001906eab88c888e0100000501010005010000") message = EthernetPacket(dst_mac=MacAddress.from_string("01:80:c2:00:00:03"), src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), ethertype=0x888e, data=bytes.fromhex("0100000501010005010000")) packed_message = message.pack() self.assertEqual(expected_packed_message, packed_message)
def test_failure_message_packs(self): expected_packed_message = build_byte_string( "000000000001001906eab88c888e0100000404ff0004") message = FailureMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), message_id=255) packed_message = MessagePacker.pack( message, MacAddress.from_string("00:00:00:00:00:01")) self.assertEqual(expected_packed_message, packed_message)
def test_success_message_packs(self): expected_packed_message = build_byte_string( "0180c2000003001906eab88c888e0100000403ff0004") message = SuccessMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), message_id=255) packed_message = MessagePacker.pack( message, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def setUp(self): src_mac = MacAddress.from_string("00:aa:bb:cc:dd:ee") self.state_machine = build_state_machine(src_mac) self.assertEqual(self.state_machine.state, "idle") message = EapolStartMessage(MacAddress.from_string("00:12:34:56:78:90")) self.state_machine.event(EventMessageReceived(message)) self.assertEqual(self.state_machine.state, "identity request sent") self.assertEqual(self.state_machine.output_messages.qsize(), 1) self.state_machine.output_messages.get()
def test_eapol_start_message_packs(self): expected_packed_message = bytes.fromhex( "0180c2000003001906eab88c888e01010000") message = EapolStartMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c")) packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("00:19:06:ea:b8:8c"), MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_tls_message_packs(self): expected_packed_message = bytes.fromhex("000000111101444444444444888e" "010000b2026900b20d0016030100a7010000a303038c8007fa4ffe8f11fbe62debce4a1385e70be51efe77b105d205d2dc9ae815a5000038c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000042000b000403000102000a000a0008001d0017001900180016000000170000000d0020001e060106020603050105020503040104020403030103020303020102020203") # pylint: disable=line-too-long message = TlsMessage(src_mac=MacAddress.from_string("44:44:44:44:44:44"), message_id=105, code=Eap.RESPONSE, flags=0x00, extra_data=bytes.fromhex('16030100a7010000a303038c8007fa4ffe8f11fbe62debce4a1385e70be51efe77b105d205d2dc9ae815a5000038c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000042000b000403000102000a000a0008001d0017001900180016000000170000000d0020001e060106020603050105020503040104020403030103020303020102020203')) # pylint: disable=line-too-long packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("44:44:44:44:44:44"), MacAddress.from_string("00:00:00:11:11:01")) self.assertEqual(expected_packed_message, packed_message)
def test_identity_request_message_packs(self): expected_packed_message = build_byte_string( "0180c2000003001906eab88c888e010000050101000501") message = IdentityMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), message_id=1, code=Eap.REQUEST, identity="") packed_message = MessagePacker.pack( message, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_from_string_invalid(self): """Test invalid mac address input.""" examples = [ '01:02:03:04:05', '01::03:04:05:06', '01:02:03:04:05: 6', '01:02:03:04:05:6\n', ' 1:02:03:04:05:06', '01:02:03:04:05:06:07', '0:0:0:0:0:007', '0a:0b:0c:0d:0e:0g', '0a:0b:0c:0d:0e:fff', '01-02-03-04-05-06', '0001:0002:0003', '000001:000002' ] for key in examples: with self.assertRaisesRegex(ValueError, r'%s.+MAC address' % key): MacAddress.from_string(key)
def test_identity_request_message_packs(self): # pylint: disable=invalid-name expected_packed_message = bytes.fromhex( "0180c2000003001906eab88c888e010000050101000501") message = IdentityMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), message_id=1, code=Eap.REQUEST, identity="") packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("00:19:06:ea:b8:8c"), MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_legacy_nak_message_packs(self): expected_packed_message = bytes.fromhex("0180c2000003000000111101888e" "01000006026800060315") message = LegacyNakMessage( src_mac=MacAddress.from_string("00:00:00:11:11:01"), message_id=104, code=Eap.RESPONSE, desired_auth_types=[(21).to_bytes(length=1, byteorder='big')]) packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("00:00:00:11:11:01"), MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_identity_response_message_packs(self): expected_packed_message = build_byte_string( "0180c2000003001422e9545e888e0100001102000011014a6f686e2e4d63477569726b" ) message = IdentityMessage( src_mac=MacAddress.from_string("00:14:22:e9:54:5e"), message_id=0, code=Eap.RESPONSE, identity="John.McGuirk") packed_message = MessagePacker.pack( message, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_md5_challenge_response_message_packs(self): # pylint: disable=invalid-name expected_packed_message = bytes.fromhex( "0180c2000003001422e9545e888e010000220201002204103a535f0ee8c6b34fe714aa7dad9a0e154a6f686e2e4d63477569726b") # pylint: disable=line-too-long message = Md5ChallengeMessage( src_mac=MacAddress.from_string("00:14:22:e9:54:5e"), message_id=1, code=Eap.RESPONSE, challenge=bytes.fromhex("3a535f0ee8c6b34fe714aa7dad9a0e15"), extra_data=b"John.McGuirk") packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("00:14:22:e9:54:5e"), MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_md5_challenge_request_message_packs(self): expected_packed_message = build_byte_string( "0180c2000003001906eab88c888e01000016010100160410824788d693e2adac6ce15641418228cf" ) message = Md5ChallengeMessage( src_mac=MacAddress.from_string("00:19:06:ea:b8:8c"), message_id=1, code=Eap.REQUEST, challenge=build_byte_string("824788d693e2adac6ce15641418228cf"), extra_data=b"") packed_message = MessagePacker.pack( message, MacAddress.from_string("01:80:c2:00:00:03")) self.assertEqual(expected_packed_message, packed_message)
def test_ttls_message_packs(self): expected_packed_message = bytes.fromhex("000000111101444444444444888e" "01000006016900061520") message = TtlsMessage( src_mac=MacAddress.from_string("44:44:44:44:44:44"), message_id=105, code=Eap.REQUEST, flags=0x20, extra_data=b'') packed_message = MessagePacker.ethernet_pack( message, MacAddress.from_string("44:44:44:44:44:44"), MacAddress.from_string("00:00:00:11:11:01")) self.assertEqual(expected_packed_message, packed_message)
def test_logoff_dot1x(self): """Test logoff""" self.chewie.get_state_machine(MacAddress.from_string('02:42:ac:17:00:6f'), MacAddress.from_string('00:00:00:00:00:01')) FROM_SUPPLICANT.put_nowait(bytes.fromhex("0000000000010242ac17006f888e01010000")) pool = eventlet.GreenPool() pool.spawn(self.chewie.run) eventlet.sleep(SHORT_SLEEP) self.assertEqual( self.chewie.get_state_machine('02:42:ac:17:00:6f', '00:00:00:00:00:01').state, FullEAPStateMachine.LOGOFF2)
def setUp(self): logger = logging.getLogger() logger.level = logging.DEBUG self.log_file = tempfile.NamedTemporaryFile() logger.addHandler(logging.FileHandler(self.log_file.name)) self.eap_output_queue = Queue() self.radius_output_queue = Queue() self.timer_scheduler = FakeTimerScheduler() self.src_mac = MacAddress.from_string("00:12:34:56:78:90") log_prefix = "chewie.SM - port: %s, client: %s" % (self.src_mac, self.PORT_ID_MAC) self.sm = FullEAPStateMachine(self.eap_output_queue, self.radius_output_queue, self.src_mac, self.timer_scheduler, self.auth_handler, self.failure_handler, self.logoff_handler, log_prefix) # find ways to inject these - overriding consts isn't ideal self.MAX_RETRANSMITS = 3 self.sm.MAX_RETRANS = self.MAX_RETRANSMITS self.sm.DEFAULT_TIMEOUT = 0.1 self.sm.port_enabled = True self.sm.eap_restart = True self.auth_counter = 0 self.failure_counter = 0 self.logoff_counter = 0
def test_radius_with_extra_attributes_packs(self): # pylint: disable=invalid-name packed_message = bytes.fromhex("010a0073" "be5df1f3b3366c69b977e56a7da47cba" "010675736572" "1f1330323a34323a61633a31373a30303a3666" "1e1434342d34342d34342d34342d34342d34343a" "3d060000000f" "4f08027100061500" "1812f51d90b0f76c85835ed4ac882e522748501201531ea8051d136941fece17473f6b4a") # pylint: disable=line-too-long src_mac = MacAddress.from_string("02:42:ac:17:00:6f") username = "******" radius_packet_id = 10 request_authenticator = bytes.fromhex( "be5df1f3b3366c69b977e56a7da47cba") state = State.create(bytes.fromhex("f51d90b0f76c85835ed4ac882e522748")) secret = "SECRET" extra_attributes = [] extra_attributes.append(CalledStationId.create('44-44-44-44-44-44:')) extra_attributes.append(NASPortType.create(15)) eap_message = TtlsMessage(src_mac, 113, Eap.RESPONSE, 0, b'') packed_radius = MessagePacker.radius_pack( eap_message, src_mac, username, radius_packet_id, request_authenticator, state, secret, extra_attributes=extra_attributes) self.assertEqual(packed_message, packed_radius)
def test_eapol_logoff_message_parses(self): packed_message = build_byte_string( "0180c2000003001906eab88c888e01020000") message = MessageParser.parse(packed_message) self.assertEqual(MacAddress.from_string("00:19:06:ea:b8:8c"), message.src_mac) self.assertTrue(isinstance(message, EapolLogoffMessage))
def test_successful_managed_port_smoke(self): port_id = MacAddress.from_string('02:42:ac:17:00:6f') self.managed_port = ManagedPort(port_id, self.logger.name, self.timer_scheduler, self.eap_output_messages, self.radius_output_messages) self.assertIsNotNone(self.managed_port)
class PromiscuousSocket(ABC): """Abstract Raw Socket in Promiscuous Mode""" SIOCGIFINDEX = 0x8933 PACKET_MR_PROMISC = 1 SOL_PACKET = 263 PACKET_ADD_MEMBERSHIP = 1 EAP_ADDRESS = MacAddress.from_string("01:80:c2:00:00:03") @abstractmethod def send(self, data): # pylint: disable=missing-docstring pass @abstractmethod def receive(self): # pylint: disable=missing-docstring pass @abstractmethod def setup(self): # pylint: disable=missing-docstring pass def __init__(self, interface_name, log_prefix): self.socket = None self.interface_index = None self.interface_name = interface_name self.logger = get_logger(log_prefix) def _setup(self, socket_filter): """Set up the socket""" self.logger.info("Setting up socket on interface: %s", self.interface_name) try: self.open(socket_filter) self.get_interface_index() self.set_interface_promiscuous() except socket.error as err: self.logger.error("Unable to setup socket: %s", str(err)) raise err def open(self, socket_filter): """Setup EAP socket""" self.socket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket_filter) self.socket.bind((self.interface_name, 0)) def get_interface_index(self): """Get the interface index of the EAP Socket""" # http://man7.org/linux/man-pages/man7/netdevice.7.html request = struct.pack('16sI', self.interface_name.encode("utf-8"), 0) response = ioctl(self.socket, self.SIOCGIFINDEX, request) _ifname, self.interface_index = struct.unpack('16sI', response) def set_interface_promiscuous(self): """Sets the EAP interface to be able to receive EAP messages""" request = struct.pack("IHH8s", self.interface_index, self.PACKET_MR_PROMISC, len(self.EAP_ADDRESS.address), self.EAP_ADDRESS.address) self.socket.setsockopt(self.SOL_PACKET, self.PACKET_ADD_MEMBERSHIP, request)
def test_success_message_parses(self): packed_message = build_byte_string( "0180c2000003001906eab88c888e0100000403ff0004") message = MessageParser.parse(packed_message) self.assertEqual(MacAddress.from_string("00:19:06:ea:b8:8c"), message.src_mac) self.assertEqual(255, message.message_id) self.assertTrue(isinstance(message, SuccessMessage))
def test_failure_message_parses(self): packed_message = bytes.fromhex( "0180c2000003001906eab88c888e0100000404ff0004") message = MessageParser.ethernet_parse(packed_message)[0] self.assertEqual(MacAddress.from_string("00:19:06:ea:b8:8c"), message.src_mac) self.assertEqual(255, message.message_id) self.assertTrue(isinstance(message, FailureMessage))
def test_ttls_message_parses(self): packed_message = bytes.fromhex("000000111101444444444444888e" "01000006016900061520") message = MessageParser.ethernet_parse(packed_message)[0] self.assertEqual(MacAddress.from_string("44:44:44:44:44:44"), message.src_mac) self.assertEqual(105, message.message_id) self.assertIsInstance(message, TtlsMessage)
def test_legacy_nak_message_parses(self): packed_message = bytes.fromhex("0180c2000003000000111101888e" "01000006026800060315") message = MessageParser.ethernet_parse(packed_message)[0] self.assertEqual(MacAddress.from_string("00:00:00:11:11:01"), message.src_mac) self.assertEqual(104, message.message_id) self.assertIsInstance(message, LegacyNakMessage)
def test_identity_request_message_parses(self): # pylint: disable=invalid-name packed_message = bytes.fromhex( "0180c2000003001906eab88c888e010000050101000501000000") message = MessageParser.ethernet_parse(packed_message)[0] self.assertEqual(MacAddress.from_string("00:19:06:ea:b8:8c"), message.src_mac) self.assertEqual(1, message.message_id) self.assertEqual(Eap.REQUEST, message.code) self.assertEqual("", message.identity)
def test_struct_unpack_error_converts_to_message_parse_error(self): # pylint: disable=invalid-name data = bytes.fromhex("01001000") try: MessageParser.eap_parse( data, MacAddress.from_string("00:00:00:12:34:56")) except MessageParseError as exception: self.assertIsInstance(exception.__cause__, struct.error) return self.fail()
def test_peap_message_parses(self): packed_message = bytes.fromhex("000000111101444444444444888e" "010000b2026900b2190016030100a7010000a303038c8007fa4ffe8f11fbe62debce4a1385e70be51efe77b105d205d2dc9ae815a5000038c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000042000b000403000102000a000a0008001d0017001900180016000000170000000d0020001e060106020603050105020503040104020403030103020303020102020203") # pylint: disable=line-too-long message = MessageParser.ethernet_parse(packed_message)[0] self.assertEqual(MacAddress.from_string("44:44:44:44:44:44"), message.src_mac) self.assertEqual(105, message.message_id) self.assertEqual(0, message.flags) self.assertIsInstance(message, PeapMessage)
def test_identity_request_message_parses(self): packed_message = build_byte_string( "0180c2000003001906eab88c888e010000050101000501000000") message = MessageParser.parse(packed_message) self.assertEqual(MacAddress.from_string("00:19:06:ea:b8:8c"), message.src_mac) self.assertEqual(1, message.message_id) self.assertEqual(Eap.REQUEST, message.code) self.assertEqual("", message.identity)