1# Copyright (c) 2017, The MITRE Corporation. All rights reserved. 2# See LICENSE.txt for complete terms. 3 4import unittest 5 6from mixbox.vendor.six import u 7 8from cybox.bindings.cybox_core import parseString 9from cybox.core import Observables 10from cybox.objects.address_object import Address 11from cybox.objects.network_packet_object import ( 12 ARP, EthernetInterface, ICMPv4Packet, ICMPv6Packet, IPv4Packet, 13 IPv6Packet, NDP, NDPPrefixInfo, NDPLinkAddr, NetworkPacket, TCP, TCPFlags, UDP) 14from cybox.test import EntityTestCase 15from cybox.test.objects import ObjectTestCase 16 17 18class TestNetworkPacket(ObjectTestCase, unittest.TestCase): 19 object_type = "NetworkPacketObjectType" 20 klass = NetworkPacket 21 22 _full_dict = { 23 'custom_properties': [ 24 {'name': "Prop1", 'description': "Property1", 'value': "Value1"}, 25 {'name': "Prop2", 'description': "Property2", 'value': "Value2"}, 26 ], 27 'link_layer': { 28 'physical_interface': { 29 'ethernet': {'ethernet_header': {'checksum': "fa10"}}, 30 }, 31 'logical_protocols': { 32 'arp_rarp': {'hardware_addr_type': "Ethernet(1)"}, 33 'ndp': {'icmpv6_header': {'checksum': "06BC"}}, 34 }, 35 }, 36 'internet_layer': { 37 # These are tested thoroughly below 38 'ipv4': {'ipv4_header': {'ip_version': "IPv4(4)"}}, 39 'icmpv4': {'icmpv4_header': {'type': "01"}}, 40 'ipv6': {'ipv6_header': {'ip_version': 'IPv6(6)'}}, 41 'icmpv6': {'icmpv6_header': {'type': "01"}}, 42 }, 43 'transport_layer': { 44 'tcp': {'data': {'data_segment': "GET /index.html http/1.1"}}, 45 'udp': {'data': {'data_segment': "whois example.com"}}, 46 }, 47 'xsi:type': object_type, 48 } 49 50 # https://github.com/CybOXProject/python-cybox/issues/181 51 def test_round_trip_xml(self): 52 np = NetworkPacket.from_dict(self._full_dict) 53 xml = Observables(np).to_xml(encoding=None) 54 55 new_obj = Observables.from_obj(parseString(xml)) 56 new_dict = new_obj.observables[0].object_.properties.to_dict() 57 58 self.maxDiff = None 59 self.assertEqual(self._full_dict, new_dict) 60 61 62class TestEthernetInterface(EntityTestCase, unittest.TestCase): 63 klass = EthernetInterface 64 65 _full_dict = { 66 'ethernet_header': { 67 'destination_mac_addr': {'address_value': u("00:11:22:33:44:55"), 68 'category': Address.CAT_MAC, 69 'xsi:type': 'AddressObjectType'}, 70 'source_mac_addr': {'address_value': u("aa:bb:cc:dd:ee:ff"), 71 'category': Address.CAT_MAC, 72 'xsi:type': 'AddressObjectType'}, 73 'type_or_length': {'length': u("1abf"), 74 'internet_layer_type': u("IPv4(0x0800)")}, 75 'checksum': u("fa10"), 76 } 77 } 78 79 80class TestARP(EntityTestCase, unittest.TestCase): 81 klass = ARP 82 83 _full_dict = { 84 'hardware_addr_type': u("Ethernet(1)"), 85 'proto_addr_type': u("IPv4(0x0800)"), 86 'hardware_addr_size': u("6"), 87 'proto_addr_size': u("4"), 88 'op_type': u("ARP request(1)"), 89 'sender_hardware_addr': {'address_value': u("01:12:23:34:45:56"), 90 'category': Address.CAT_MAC, 91 'xsi:type': 'AddressObjectType'}, 92 'sender_protocol_addr': {'address_value': u("1.2.3.4"), 93 'category': Address.CAT_IPV4, 94 'xsi:type': 'AddressObjectType'}, 95 'recip_hardware_addr': {'address_value': u("a0:b0:c0:d0:e0:f0"), 96 'category': Address.CAT_MAC, 97 'xsi:type': 'AddressObjectType'}, 98 'recip_protocol_addr': {'address_value': u("9.10.11.12"), 99 'category': Address.CAT_IPV4, 100 'xsi:type': 'AddressObjectType'}, 101 } 102 103 104class TestNDPLinkAddr(EntityTestCase, unittest.TestCase): 105 klass = NDPLinkAddr 106 _full_dict = { 107 'length': u('14'), 108 'link_layer_mac_addr': {'address_value': u("80:70:60:50:40:30"), 109 'category': Address.CAT_MAC, 110 'xsi:type': 'AddressObjectType'}, 111 } 112 113 114class TestNDPPrefixInfo(EntityTestCase, unittest.TestCase): 115 klass = NDPPrefixInfo 116 117 _full_dict = { 118 'link_flag': False, 119 'addr_config_flag': True, 120 'length': u("14"), 121 'prefix_length': 7, 122 'valid_lifetime': 123455, 123 'preferred_lifetime': 1000, 124 'prefix': { 125 'ipv6_addr': {'address_value': u("2001:db8::ff00:42:832"), 126 'category': Address.CAT_IPV6, 127 'xsi:type': 'AddressObjectType'}, 128 'ip_addr_prefix': {'address_value': u("2001:0db8:85a3"), 129 'category': Address.CAT_IPV6, 130 'xsi:type': 'AddressObjectType'}, 131 } 132 } 133 134 135class TestNDP(EntityTestCase, unittest.TestCase): 136 klass = NDP 137 138 _full_dict = { 139 'icmpv6_header': { 140 'type': u("01"), 141 'code': u("07"), 142 'checksum': u("06BC"), 143 }, 144 # This is normally a choice, but we can currently just check 145 # them all at once. For X_link_addr, we are checking them above, 146 # so we only use a length here. 147 'router_solicitation': { 148 'options': [{'src_link_addr': {'length': u("16")}}], 149 }, 150 'router_advertisement': { 151 'managed_address_config_flag': True, 152 'other_config_flag': False, 153 'cur_hop_limit': 16, 154 'reachable_time': 1000, 155 'retrans_timer': 5000, 156 'options': { 157 'src_link_addr': {'length': u("8")}, 158 'mtu': {'length': 8, 'mtu': 1500}, 159 'prefix_info': {'link_flag': True, 'length': u("44")}, 160 } 161 }, 162 'neighbor_solicitation': { 163 'target_ipv6_addr': {'address_value': u("2001:db99::ff00:832"), 164 'category': Address.CAT_IPV6, 165 'xsi:type': 'AddressObjectType'}, 166 'options': {'src_link_addr': {'length': u("99")}}, 167 }, 168 'neighbor_advertisement': { 169 'router_flag': True, 170 'solicited_flag': False, 171 'override_flag': True, 172 'target_ipv6_addr': {'address_value': u("::1"), 173 'category': Address.CAT_IPV6, 174 'xsi:type': 'AddressObjectType'}, 175 'options': {'target_link_addr': {'length': u("48")}}, 176 }, 177 'redirect': { 178 'target_ipv6_addr': {'address_value': u("2001::1"), 179 'category': Address.CAT_IPV6, 180 'xsi:type': 'AddressObjectType'}, 181 'dest_ipv6_addr': {'address_value': u("2001::dd88:1"), 182 'category': Address.CAT_IPV6, 183 'xsi:type': 'AddressObjectType'}, 184 'options': { 185 'target_link_addr': {'length': u("48")}, 186 'redirected_header': { 187 'length': u("77"), 188 'ipheader_and_data': '3bda4659ace', 189 }, 190 }, 191 }, 192 } 193 194 195class TestIPv4Packet(EntityTestCase, unittest.TestCase): 196 klass = IPv4Packet 197 198 _full_dict = { 199 'ipv4_header': { 200 'ip_version': u("IPv4(4)"), 201 'header_length': 32, 202 'dscp': u("5fc1"), 203 'ecn': u("4ca6"), 204 'total_length': u("ffff"), 205 'identification': 10, 206 'flags': { 207 'reserved': 0, 208 'do_not_fragment': u("donotfragment(1)"), 209 'more_fragments': u("lastfragment(0)"), 210 }, 211 'fragment_offset': u("7c"), 212 'ttl': u("fa"), 213 'protocol': u("TPC(6)"), 214 'checksum': u("0fca"), 215 'src_ipv4_addr': {'address_value': u("172.16.21.50"), 216 'category': Address.CAT_IPV4, 217 'xsi:type': 'AddressObjectType'}, 218 'dest_ipv4_addr': {'address_value': u("172.16.21.1"), 219 'category': Address.CAT_IPV4, 220 'xsi:type': 'AddressObjectType'}, 221 'option': [ 222 {'copy_flag': u("donotcopy(0)"), 'class': u("control(0)")}, 223 {'class': u("reserved(3)"), 'option': u("security(2)")}, 224 ] 225 }, 226 'data': u("04fc3a3f67e4"), 227 } 228 229 230class TestICMPv4(EntityTestCase, unittest.TestCase): 231 klass = ICMPv4Packet 232 233 _full_dict = { 234 'icmpv4_header': { 235 'type': u("02"), 236 'code': u("06"), 'checksum': u("06BC"), }, 237 'error_msg': { 238 'destination_unreachable': { 239 'destination_network_unreachable': True, 240 'destination_host_unreachable': True, 241 'destination_protocol_unreachable': True, 242 'destination_port_unreachable': True, 243 'fragmentation_required': { 244 'fragmentation_required': True, 245 'next_hop_mtu': u("a150"), 246 }, 247 'source_route_failed': True, 248 'destination_network_unknown': True, 249 'destination_host_unknown': True, 250 'source_host_isolated': True, 251 'network_administratively_prohibited': True, 252 'host_administratively_prohibited': True, 253 'network_unreachable_for_tos': True, 254 'host_unreachable_for_tos': True, 255 'communication_administratively_prohibited': True, 256 'host_precedence_violation': True, 257 'precedence_cutoff_in_effect': True, 258 }, 259 'source_quench': { 260 'source_quench': True, 261 }, 262 'redirect_message': { 263 'network_redirect': True, 264 'host_redirect': True, 265 'tos_network_redirect': True, 266 'tos_host_redirect': True, 267 'ip_address': {'address_value': u("10.3.4.5"), 268 'category': Address.CAT_IPV4, 269 'xsi:type': 'AddressObjectType'}, 270 }, 271 'time_exceeded': { 272 'ttl_exceeded_in_transit': True, 273 'frag_reassembly_time_exceeded': True, 274 }, 275 'error_msg_content': { 276 'ip_header': {'ip_version': u("IPv4(4)")}, 277 'first_eight_bytes': u("0123456789abcdef"), 278 }, 279 }, 280 'info_msg': { 281 'echo_reply': { 282 'echo_reply': True, 283 'data': u("5f3dce41") 284 }, 285 'echo_request': { 286 'echo_request': True, 287 'data': u("14ecd3f5") 288 }, 289 'timestamp_request': { 290 'timestamp': True, 291 'originate_timestamp': 4567812, 292 }, 293 'timestamp_reply': { 294 'timestamp_reply': True, 295 'originate_timestamp': 4567811, 296 'receive_timestamp': 4567814, 297 'transmit_timestamp': 4567819, 298 }, 299 'address_mask_request': { 300 'address_mask_request': True, 301 'address_mask': {'address_value': u("255.255.0.0"), 302 'category': Address.CAT_IPV4_NETMASK, 303 'xsi:type': 'AddressObjectType'}, 304 }, 305 'address_mask_reply': { 306 'address_mask_reply': True, 307 'address_mask': {'address_value': u("255.255.255.0"), 308 'category': Address.CAT_IPV4_NETMASK, 309 'xsi:type': 'AddressObjectType'}, 310 }, 311 'info_msg_content': { 312 'identifier': u("f198"), 313 'sequence_number': u("1dc9"), 314 }, 315 }, 316 'traceroute': { 317 'outbound_packet_forward_success': True, 318 'outbound_packet_no_route': True, 319 'identifier': u("1234"), 320 'outbound_hop_count': u("001f"), 321 'return_hop_count': u("001c"), 322 'output_link_speed': u("000f42f0"), 323 'output_link_mtu': u("00000000"), 324 }, 325 } 326 327 328class TestIPv6(EntityTestCase, unittest.TestCase): 329 klass = IPv6Packet 330 331 _full_dict = { 332 'ipv6_header': { 333 'ip_version': u("IPv6(6)"), 334 'traffic_class': u("ff"), 335 'flow_label': u("abcde"), 336 'payload_length': u("1000"), 337 'next_header': u("TCP(6)"), 338 'ttl': u('fa'), 339 'src_ipv6_addr': {'address_value': u("2001:85a3::8a2e:370:734"), 340 'category': Address.CAT_IPV6, 341 'xsi:type': 'AddressObjectType'}, 342 'dest_ipv6_addr': {'address_value': u("2001:3a58::8a2e:370:734"), 343 'category': Address.CAT_IPV6, 344 'xsi:type': 'AddressObjectType'}, 345 }, 346 'ext_headers': [ 347 { 348 'hop_by_hop_options': { 349 'next_header': u("IPv6routingheader(43)"), 350 'header_ext_len': u("1f"), 351 'option_data': [ 352 { 353 'option_type': { 354 'do_not_recogn_action': u("skipoption(00)"), 355 'packet_change': u("change(1)"), 356 'option_byte': u("04"), 357 }, 358 'option_data_len': u("0100"), 359 'pad1': {'octet': u("00")}, 360 'padn': {'octet': u("01"), 361 'option_data_length': 42, 362 'option_data': 00} 363 }, 364 { 365 'option_type': {'option_byte': u("02")}, 366 'option_data_len': u("007f"), 367 'pad1': {'octet': u("00")}, 368 }, 369 ] 370 }, 371 }, 372 { 373 'routing': { 374 'next_header': u("IPv6routingheader(43)"), 375 'header_ext_len': 32, 376 'routing_type': u("4a"), 377 'segments_left': 13, 378 'type_specific_data': u("AAAAAAAA") 379 }, 380 }, 381 { 382 'fragment': { 383 'fragment_header': { 384 'next_header': u("IPv6routingheader(43)"), 385 'fragment_offset': u("01fb"), 386 'm_flag': u("lastfragment(0)"), 387 'identification': u("aa"), 388 }, 389 'fragment': u("bc27648fbace") 390 }, 391 }, 392 { 393 'destination_options': [ 394 { 395 'next_header': u("IPv6routingheader(43)"), 396 'header_ext_len': u("1f"), 397 'option_data': [ 398 { 399 'option_data_len': u("0100"), 400 'pad1': {'octet': u("00")}, 401 }, 402 { 403 'option_type': {'option_byte': u("02")}, 404 }, 405 ] 406 }, 407 { 408 'header_ext_len': u("1f"), 409 }, 410 ], 411 }, 412 { 413 'authentication_header': { 414 'next_header': u("IPv6routingheader(43)"), 415 'header_ext_len': u("1f"), 416 'security_parameters_index': u("deadbeef"), 417 'sequence_number': u("feedbacc"), 418 'authentication_data': u("abcd0123fedc4567"), 419 }, 420 }, 421 { 422 'encapsulating_security_payload': { 423 'security_parameters_index': u("deadbeef"), 424 'sequence_number': u("feedbacc"), 425 'payload_data': u("777788889999aaaa"), 426 'padding': u("0000000"), 427 'padding_len': u("7"), 428 'next_header': u("IPv6routingheader(43)"), 429 'authentication_data': u("abcd0123fedc4567"), 430 }, 431 }, 432 ], 433 } 434 435 436class TestICMPv6(EntityTestCase, unittest.TestCase): 437 klass = ICMPv6Packet 438 439 _full_dict = { 440 'icmpv6_header': { 441 'type': u("02"), 442 'code': u("06"), 443 'checksum': u("06BC"), 444 }, 445 'error_msg': { 446 'destination_unreachable': { 447 'no_route': True, 448 'comm_prohibited': True, 449 'beyond_scope': True, 450 'address_unreachable': True, 451 'port_unreachable': True, 452 'src_addr_failed_policy': True, 453 'reject_route': True, 454 }, 455 'packet_too_big': { 456 'packet_too_big': True, 457 'mtu': u("1f00"), 458 }, 459 'time_exceeded': { 460 'hop_limit_exceeded': True, 461 'fragment_reassem_time_exceeded': True, 462 }, 463 'parameter_problem': { 464 'erroneous_header_field': True, 465 'unrecognized_next_header_type': True, 466 'unrecognized_ipv6_option': True, 467 'pointer': u("7fffaabb"), 468 }, 469 'invoking_packet': u("0f1e2d3c4b5a9687"), 470 }, 471 'info_msg': { 472 'echo_request': { 473 'echo_request': True, 474 'data': u("2468ace0") 475 }, 476 'echo_reply': { 477 'echo_reply': True, 478 'data': u("0eca8642") 479 }, 480 'info_msg_content': { 481 'identifier': u("f198"), 482 'sequence_number': u("1dc9"), 483 }, 484 }, 485 } 486 487 488class TestTCPFlags(EntityTestCase, unittest.TestCase): 489 klass = TCPFlags 490 491 _full_dict = { 492 'ns': True, 493 'cwr': True, 494 'ece': True, 495 'urg': True, 496 'ack': True, 497 'psh': True, 498 'rst': True, 499 'syn': True, 500 'fin': True, 501 } 502 503 504class TestTCP(EntityTestCase, unittest.TestCase): 505 klass = TCP 506 507 _full_dict = { 508 'tcp_header': { 509 'src_port': {'port_value': 1444, 510 'layer4_protocol': u('TCP'), 511 'xsi:type': 'PortObjectType'}, 512 'dest_port': {'port_value': 80, 513 'layer4_protocol': u('TCP'), 514 'xsi:type': 'PortObjectType'}, 515 'seq_num': u("148f3b44"), 516 'ack_num': u("664d012a"), 517 'data_offset': u("20"), 518 'reserved': 1, 519 'tcp_flags': TestTCPFlags._full_dict, 520 'window': u("1460"), 521 'checksum': u("1fc1"), 522 'urg_ptr': u("0001") 523 }, 524 'options': u("010305"), 525 'data': { 526 'data_format': "Text", 527 'data_size': {"value": u("100"), 'units': "Kilobytes"}, 528 'data_segment': u("A long, long time ago..."), 529 'offset': 100, 530 'search_distance': 200, 531 'search_within': 40, 532 } 533 } 534 535 536class TestUDP(EntityTestCase, unittest.TestCase): 537 klass = UDP 538 539 _full_dict = { 540 'udp_header': { 541 'srcport': {'port_value': 1664, 542 'layer4_protocol': u('UDP'), 543 'xsi:type': 'PortObjectType'}, 544 'destport': {'port_value': 53, 545 'layer4_protocol': u('UDP'), 546 'xsi:type': 'PortObjectType'}, 547 'length': 0x18, 548 'checksum': u("1fc1"), 549 }, 550 'data': { 551 'data_format': "Hex", 552 'data_size': {"value": u("16"), 'units': "Bytes"}, 553 'data_segment': u("000102030405060708090a0b0c0d0e0f"), 554 } 555 } 556 557 558if __name__ == "__main__": 559 unittest.main() 560