diff --git a/tests/active_tests/include/active_test.h b/tests/active_tests/include/active_test.h index 3c7d265..f4ffd39 100644 --- a/tests/active_tests/include/active_test.h +++ b/tests/active_tests/include/active_test.h @@ -66,8 +66,10 @@ public: void validate(PacketCapturer::PacketStorage& packets); virtual std::string name() const = 0; protected: - const PacketSenderPtr& packet_sender() const; - const ConfigurationPtr& configuration() const; + Tins::PacketSender& packet_sender(); + const Tins::PacketSender& packet_sender() const; + Configuration& configuration(); + const Configuration& configuration() const; virtual bool test_matches_packet(const Tins::PDU& pdu) const = 0; virtual void execute_test() = 0; virtual void validate_packet(const Tins::PDU& pdu) = 0; diff --git a/tests/active_tests/include/tcp_tests.h b/tests/active_tests/include/tcp_tests.h index fa4858a..36375dc 100644 --- a/tests/active_tests/include/tcp_tests.h +++ b/tests/active_tests/include/tcp_tests.h @@ -37,16 +37,40 @@ class TCPSynTest : public ActiveTest { public: TCPSynTest(const PacketSenderPtr& packet_sender, - const ConfigurationPtr& configuration); - - std::string name() const; + const ConfigurationPtr& configuration, + uint16_t target_port); private: void execute_test(); void validate_packet(const Tins::PDU& pdu); bool test_matches_packet(const Tins::PDU& pdu) const; + virtual void send_packet(Tins::PDU& pdu) = 0; Tins::IPv4Address target_address_; uint32_t sequence_number_; + uint16_t target_port_; }; +// Sends a SYN using IP as the lowest layer +class Layer3TCPSynTest : public TCPSynTest { +public: + Layer3TCPSynTest(const PacketSenderPtr& packet_sender, + const ConfigurationPtr& configuration); + + std::string name() const; +private: + void send_packet(Tins::PDU& pdu); +}; + +// Sends a SYN using Ethernet as the lowest layer +class Layer2TCPSynTest : public TCPSynTest { +public: + Layer2TCPSynTest(const PacketSenderPtr& packet_sender, + const ConfigurationPtr& configuration); + + std::string name() const; +private: + void send_packet(Tins::PDU& pdu); +}; + + #endif // TINS_ACTIVE_TCP_TESTS_H diff --git a/tests/active_tests/include/test_utils.h b/tests/active_tests/include/test_utils.h new file mode 100644 index 0000000..5d1302b --- /dev/null +++ b/tests/active_tests/include/test_utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_TEST_UTILS_H +#define TINS_TEST_UTILS_H + +#include +#include "tins/ip_address.h" + +Tins::IPv4Address get_gateway_v4_address(const std::string& interface_name); + +#endif // TINS_TEST_UTILS_H diff --git a/tests/active_tests/src/active_test.cpp b/tests/active_tests/src/active_test.cpp index 6084102..6fac5aa 100644 --- a/tests/active_tests/src/active_test.cpp +++ b/tests/active_tests/src/active_test.cpp @@ -37,6 +37,7 @@ using std::endl; using std::string; using Tins::PDU; +using Tins::PacketSender; using Tins::pdu_not_found; using Tins::option_not_found; @@ -96,12 +97,20 @@ void ActiveTest::validate(PacketCapturer::PacketStorage& packets) { } } -const ActiveTest::PacketSenderPtr& ActiveTest::packet_sender() const { - return packet_sender_; +PacketSender& ActiveTest::packet_sender() { + return *packet_sender_; } -const ActiveTest::ConfigurationPtr& ActiveTest::configuration() const { - return configuration_; +const PacketSender& ActiveTest::packet_sender() const { + return *packet_sender_; +} + +Configuration& ActiveTest::configuration() { + return *configuration_; +} + +const Configuration& ActiveTest::configuration() const { + return *configuration_; } void ActiveTest::disable_on_platform(Configuration::Platform platform) { diff --git a/tests/active_tests/src/ipv4_tests.cpp b/tests/active_tests/src/ipv4_tests.cpp index c8a21ff..6d22d4c 100644 --- a/tests/active_tests/src/ipv4_tests.cpp +++ b/tests/active_tests/src/ipv4_tests.cpp @@ -59,8 +59,8 @@ string IPv4SourceAddressTest::name() const { } void IPv4SourceAddressTest::execute_test() { - PacketSender& sender = *packet_sender(); - Configuration& config = *configuration(); + PacketSender& sender = packet_sender(); + Configuration& config = configuration(); auto packet = IP("8.8.8.8"); packet /= UDP(config.destination_port(), config.source_port()); packet /= RawPDU(name()); @@ -69,7 +69,7 @@ void IPv4SourceAddressTest::execute_test() { void IPv4SourceAddressTest::validate_packet(const PDU& pdu) { const IP& ip = pdu.rfind_pdu(); - const NetworkInterface& iface = configuration()->interface(); + const NetworkInterface& iface = configuration().interface(); // The source address should be the same as the default interface's if (iface.ipv4_address() != ip.src_addr()) { ostringstream oss; @@ -98,8 +98,8 @@ string IPv4FragmentationTest::name() const { } void IPv4FragmentationTest::execute_test() { - PacketSender& sender = *packet_sender(); - Configuration& config = *configuration(); + PacketSender& sender = packet_sender(); + Configuration& config = configuration(); auto packet = IP("8.8.8.8"); packet /= UDP(config.destination_port(), config.source_port()); packet /= RawPDU(name()); diff --git a/tests/active_tests/src/main.cpp b/tests/active_tests/src/main.cpp index 380df16..4f9100d 100644 --- a/tests/active_tests/src/main.cpp +++ b/tests/active_tests/src/main.cpp @@ -53,7 +53,8 @@ int main() { ActiveTestRunner runner(config); runner.add_test(); runner.add_test(); - runner.add_test(); + runner.add_test(); + runner.add_test(); runner.add_test(); if (!runner.validate_tests()) { diff --git a/tests/active_tests/src/tcp_tests.cpp b/tests/active_tests/src/tcp_tests.cpp index 4fcfbd7..57f4484 100644 --- a/tests/active_tests/src/tcp_tests.cpp +++ b/tests/active_tests/src/tcp_tests.cpp @@ -32,7 +32,9 @@ #include "tcp_tests.h" #include "tins/tcp.h" #include "tins/ip.h" +#include "tins/ethernetII.h" #include "tins/utils.h" +#include "test_utils.h" using std::string; using std::cout; @@ -42,16 +44,16 @@ using std::random_device; using Tins::PDU; using Tins::TCP; using Tins::IP; +using Tins::IPv4Address; +using Tins::NetworkInterface; +using Tins::EthernetII; using Tins::Utils::resolve_domain; TCPSynTest::TCPSynTest(const PacketSenderPtr& packet_sender, - const ConfigurationPtr& configuration) -: ActiveTest(packet_sender, configuration) { - disable_on_platform(Configuration::WINDOWS); -} + const ConfigurationPtr& configuration, + uint16_t target_port) +: ActiveTest(packet_sender, configuration), target_port_(target_port) { -string TCPSynTest::name() const { - return "tcp_syn_test"; } void TCPSynTest::execute_test() { @@ -60,11 +62,11 @@ void TCPSynTest::execute_test() { sequence_number_ = static_cast(rnd()); cout << log_prefix() << "Resolved target address to " << target_address_ << endl; - auto packet = IP(target_address_) / TCP(80, configuration()->source_port()); + auto packet = IP(target_address_) / TCP(target_port_, configuration().source_port()); TCP& tcp = packet.rfind_pdu(); tcp.seq(sequence_number_); tcp.flags(TCP::SYN); - packet_sender()->send(packet); + send_packet(packet); } void TCPSynTest::validate_packet(const PDU& pdu) { @@ -79,9 +81,48 @@ bool TCPSynTest::test_matches_packet(const PDU& pdu) const { return false; } const TCP& tcp = pdu.rfind_pdu(); - if (tcp.sport() != 80) { + if (tcp.sport() != target_port_) { return false; } return tcp.ack_seq() == sequence_number_ + 1; } + +// Layer 3 + +Layer3TCPSynTest::Layer3TCPSynTest(const PacketSenderPtr& packet_sender, + const ConfigurationPtr& configuration) +: TCPSynTest(packet_sender, configuration, 80) { + disable_on_platform(Configuration::WINDOWS); +} + +string Layer3TCPSynTest::name() const { + return "tcp_layer3_syn_test"; +} + +void Layer3TCPSynTest::send_packet(PDU& pdu) { + packet_sender().send(pdu); +} + +// Layer 2 + +Layer2TCPSynTest::Layer2TCPSynTest(const PacketSenderPtr& packet_sender, + const ConfigurationPtr& configuration) +: TCPSynTest(packet_sender, configuration, 443) { + +} + +string Layer2TCPSynTest::name() const { + return "tcp_layer2_syn_test"; +} + +void Layer2TCPSynTest::send_packet(PDU& pdu) { + const NetworkInterface& iface = configuration().interface(); + IPv4Address gateway_address = get_gateway_v4_address(iface.name()); + auto gateway_hwaddress = Tins::Utils::resolve_hwaddr(iface, gateway_address, + packet_sender()); + EthernetII eth = EthernetII(gateway_hwaddress, iface.hw_address()) / pdu; + eth.rfind_pdu().src_addr(iface.ipv4_address()); + packet_sender().send(eth); +} + diff --git a/tests/active_tests/src/test_utils.cpp b/tests/active_tests/src/test_utils.cpp new file mode 100644 index 0000000..2370149 --- /dev/null +++ b/tests/active_tests/src/test_utils.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Matias Fontanini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "test_utils.h" +#include "tins/utils.h" + +using std::string; +using std::vector; +using std::numeric_limits; + +using Tins::IPv4Address; +using Tins::Utils::RouteEntry; + +IPv4Address get_gateway_v4_address(const string& interface_name) { + vector entries = Tins::Utils::route_entries(); + int current_metric = numeric_limits::max(); + IPv4Address address; + for (const auto& entry : entries) { + if (entry.interface == interface_name && entry.gateway != "0.0.0.0" && entry.metric < current_metric) { + address = entry.gateway; + current_metric = entry.metric; + } + } + return address; +} \ No newline at end of file diff --git a/tests/active_tests/src/utils_test.cpp b/tests/active_tests/src/utils_test.cpp index 98e059c..e9fa257 100644 --- a/tests/active_tests/src/utils_test.cpp +++ b/tests/active_tests/src/utils_test.cpp @@ -34,6 +34,7 @@ #include "tins/ethernetII.h" #include "tins/arp.h" #include "tins/utils.h" +#include "test_utils.h" using std::cout; using std::endl; @@ -52,16 +53,7 @@ using Tins::Utils::RouteEntry; ResolveHWAddressTest::ResolveHWAddressTest(const PacketSenderPtr& packet_sender, const ConfigurationPtr& configuration) : ActiveTest(packet_sender, configuration) { - vector entries = Tins::Utils::route_entries(); - string interface_name = configuration->interface().name(); - int current_metric = numeric_limits::max(); - for (const auto& entry : entries) { - if (entry.interface == interface_name && entry.gateway != "0.0.0.0" && entry.metric < current_metric) { - target_address_ = entry.gateway; - current_metric = entry.metric; - } - } - disable_on_platform(Configuration::WINDOWS); + target_address_ = get_gateway_v4_address(configuration->interface().name()); } string ResolveHWAddressTest::name() const { @@ -75,14 +67,14 @@ bool ResolveHWAddressTest::test_matches_packet(const PDU& pdu) const { void ResolveHWAddressTest::execute_test() { cout << log_prefix() << "trying to resolve " << target_address_ << endl; - resolved_address_ = Tins::Utils::resolve_hwaddr(configuration()->interface(), + resolved_address_ = Tins::Utils::resolve_hwaddr(configuration().interface(), target_address_, - *packet_sender()); + packet_sender()); cout << log_prefix() << "address resolved to " << resolved_address_ << endl; - auto local_ip_address = configuration()->interface().ipv4_address(); - auto local_hw_address = configuration()->interface().hw_address(); + auto local_ip_address = configuration().interface().ipv4_address(); + auto local_hw_address = configuration().interface().hw_address(); auto packet = ARP::make_arp_request(target_address_, local_ip_address, local_hw_address); - packet_sender()->send(packet); + packet_sender().send(packet); } void ResolveHWAddressTest::validate_packet(const PDU& pdu) {