summaryrefslogtreecommitdiff
path: root/test/malicious_data_tests
diff options
context:
space:
mode:
Diffstat (limited to 'test/malicious_data_tests')
-rwxr-xr-xtest/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in18
-rw-r--r--test/malicious_data_tests/malicious_data_test_globals.hpp9
-rw-r--r--test/malicious_data_tests/malicious_data_test_msg_sender.cpp1318
-rw-r--r--test/malicious_data_tests/malicious_data_test_service.cpp25
4 files changed, 1350 insertions, 20 deletions
diff --git a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
index 199f318..5072632 100755
--- a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
+++ b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
@@ -12,12 +12,22 @@
FAIL=0
+if [ $# -lt 1 ]
+then
+ echo "Please pass a test mode to this script."
+ echo "For example: $0 MALICIOUS_EVENTS"
+ echo "Valid subscription types include:"
+ echo " [MALICIOUS_EVENTS, PROTOCOL_VERSION, MESSAGE_TYPE, RETURN_CODE, WRONG_HEADER_FIELDS_UDP]"
+ exit 1
+fi
+TESTMODE=$1
+
export VSOMEIP_CONFIGURATION=malicious_data_test_master.json
# start daemon
../daemon/./vsomeipd &
PID_VSOMEIPD=$!
# Start the services
-./malicious_data_test_service &
+./malicious_data_test_service $TESTMODE &
PID_SERIVCE=$!
sleep 1
@@ -26,16 +36,16 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@" &
+ docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
else
cat <<End-of-message
*******************************************************************************
*******************************************************************************
** Please now run:
-** malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@
+** malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE
** from an external host to successfully complete this test.
**
** You probably will need to adapt the 'unicast' settings in
diff --git a/test/malicious_data_tests/malicious_data_test_globals.hpp b/test/malicious_data_tests/malicious_data_test_globals.hpp
index f6336a4..de14d5e 100644
--- a/test/malicious_data_tests/malicious_data_test_globals.hpp
+++ b/test/malicious_data_tests/malicious_data_test_globals.hpp
@@ -21,10 +21,11 @@ struct service_info {
struct service_info service = { 0x3344, 0x1, 0x1111, 0x8002, 0x1, 0x1404, 0x4242 };
enum test_mode_e {
- SUBSCRIBE,
- SUBSCRIBE_UNSUBSCRIBE,
- UNSUBSCRIBE,
- SUBSCRIBE_UNSUBSCRIBE_NACK
+ MALICIOUS_EVENTS,
+ PROTOCOL_VERSION,
+ MESSAGE_TYPE,
+ RETURN_CODE,
+ WRONG_HEADER_FIELDS_UDP
};
}
diff --git a/test/malicious_data_tests/malicious_data_test_msg_sender.cpp b/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
index 27a62c2..84d09bf 100644
--- a/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
+++ b/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
@@ -23,7 +23,10 @@
#include "../../implementation/service_discovery/include/constants.hpp"
#include "../../implementation/service_discovery/include/enumeration_types.hpp"
#include "../../implementation/service_discovery/include/eventgroupentry_impl.hpp"
+#include "../../implementation/service_discovery/include/serviceentry_impl.hpp"
#include "../../implementation/message/include/message_impl.hpp"
+#include "../../implementation/service_discovery/include/option_impl.hpp"
+#include "../../implementation/service_discovery/include/ipv4_option_impl.hpp"
#include "malicious_data_test_globals.hpp"
static char* remote_address;
@@ -258,31 +261,1330 @@ TEST_F(malicious_data, send_malicious_events)
30001);
udp_socket.send_to(boost::asio::buffer(shutdown_call), target_service);
} catch (const std::exception& _e) {
- std::cout << "catched exception: " << _e.what();
- ASSERT_FALSE(true);
+ ADD_FAILURE() << "catched exception: " << _e.what();
}
});
send_thread.join();
receive_thread.join();
- udp_socket.shutdown(boost::asio::socket_base::shutdown_both);
- tcp_socket.shutdown(boost::asio::socket_base::shutdown_both);
- udp_socket.close();
- tcp_socket.close();
+ boost::system::error_code ec;
+ udp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket.close(ec);
+ tcp_socket.close(ec);
}
+/*
+ * @test Send a message with an invalid protocol version to the test master
+ * two times as client and two time as service. Ensure that message with the
+ * WRONG_PROTOCOL_VERSION is sent back in both cases and that the client
+ * reestablishes the TCP connection after the service sent an message with an
+ * invalid protocol version back
+ */
+TEST_F(malicious_data, send_wrong_protocol_version)
+{
+ std::promise<void> remote_client_subscribed;
+ std::promise<void> offer_received;
+
+ boost::asio::ip::tcp::socket tcp_socket(io_);
+ boost::asio::ip::udp::socket udp_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.24.1
+ udp_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.24.1").to_v4()));
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (auto e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(1u, its_casted_entry->get_eventgroup());
+ }
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(2,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id + 1u, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(2u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ try {
+ std::promise<void> client_connected;
+ boost::asio::ip::tcp::socket::endpoint_type local(
+ boost::asio::ip::address::from_string(std::string(local_address)),
+ 40001);
+ boost::asio::ip::tcp::acceptor its_acceptor(io_);
+ boost::system::error_code ec;
+ its_acceptor.open(local.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "acceptor open");
+ its_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "acceptor set_option");
+ its_acceptor.bind(local, ec);
+ boost::asio::detail::throw_error(ec, "acceptor bind");
+ its_acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ boost::asio::detail::throw_error(ec, "acceptor listen");
+ its_acceptor.async_accept(tcp_socket, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_connected.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk: " << _error.message();
+ }
+ });
+
+
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x33, 0x44, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x06, 0x9c, 0x41,
+ };
+ boost::asio::ip::address its_local_address =
+ boost::asio::ip::address::from_string(std::string(local_address));
+ std::memcpy(&its_offer_service_message[48], &its_local_address.to_v4().to_bytes()[0], 4);
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30490);
+ udp_socket.send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+
+ // wait until client established TCP connection
+ if (std::future_status::timeout == client_connected.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't connect within time";
+ }
+
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ }
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ }
+
+ std::atomic<std::uint32_t> fin_as_service_received(0);
+ std::promise<void> client_reconnected1;
+
+ std::thread tcp_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ tcp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error == boost::asio::error::eof) {
+ EXPECT_EQ(boost::asio::error::eof, error);
+ fin_as_service_received++;
+ keep_receiving = false;
+ } else {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << ":" << __LINE__ << " error: " << error.message();
+ return;
+ }
+ }
+ });
+
+ boost::asio::ip::tcp::socket tcp_socket3(io_);
+ its_acceptor.async_accept(tcp_socket3, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket3.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_reconnected1.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk2: " << _error.message();
+ }
+ });
+ // send malicious data as server (too long length and wrong protocol version)
+ std::uint8_t its_malicious_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xBB, 0xBB, 0xCA, 0xFE,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ tcp_socket.send(boost::asio::buffer(its_malicious_data));
+
+ // wait until client reestablished TCP connection
+ if (std::future_status::timeout == client_reconnected1.get_future().wait_for(std::chrono::seconds(10))) {
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+ ADD_FAILURE() << "Client didn't reconnect within time 1";
+ }
+
+ tcp_receive_thread.join();
+
+ EXPECT_EQ(1u, fin_as_service_received);
+
+ std::thread tcp_receive_thread2([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ tcp_socket3.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error == boost::asio::error::eof) {
+ EXPECT_EQ(boost::asio::error::eof, error);
+ fin_as_service_received++;
+ // client must sent back error response before closing the connection
+ EXPECT_EQ(2u, fin_as_service_received);
+ if (fin_as_service_received == 2) {
+ keep_receiving = false;
+ }
+ } else {
+ keep_receiving = false;
+ return;
+ }
+ }
+ });
+
+ // send malicious data as server (wrong protocol version)
+ std::uint8_t its_malicious_data_correct_length[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xBB, 0xBB, 0xCA, 0xFE,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ tcp_socket3.send(boost::asio::buffer(its_malicious_data_correct_length));
+
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+
+
+ tcp_receive_thread2.join();
+ EXPECT_EQ(2u, fin_as_service_received);
+
+ // establish second tcp connection as client and send malicious data as well
+ std::atomic<std::uint32_t> error_response_as_client_received(0);
+ std::atomic<std::uint32_t> fin_as_client_received(0);
+
+ boost::asio::ip::tcp::socket tcp_socket2(io_);
+ boost::asio::ip::tcp::socket::endpoint_type remote(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 40001);
+ tcp_socket2.open(remote.protocol());
+ tcp_socket2.connect(remote);
+
+
+ std::thread tcp_service_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = tcp_socket2.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (!error) {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ std::shared_ptr<vsomeip::message> its_message(its_deserializer.deserialize_message());
+ EXPECT_EQ(0x3345, its_message->get_service());
+ EXPECT_EQ(0x1, its_message->get_method());
+ EXPECT_EQ(0xCCCC, its_message->get_client());
+ EXPECT_EQ(0xDDDD, its_message->get_session());
+ EXPECT_EQ(vsomeip::return_code_e::E_WRONG_PROTOCOL_VERSION, its_message->get_return_code());
+ EXPECT_EQ(vsomeip::message_type_e::MT_ERROR, its_message->get_message_type());
+ error_response_as_client_received++;
+ // service must sent back error response before closing the connection
+ EXPECT_EQ(error_response_as_client_received - 1u, fin_as_client_received);
+ } else {
+ EXPECT_EQ(boost::asio::error::eof, error);
+ fin_as_client_received++;
+ // service must sent back error response before closing the connection
+ EXPECT_EQ(error_response_as_client_received, fin_as_client_received);
+ if (fin_as_client_received == 1) {
+ keep_receiving = false;
+ }
+ }
+ }
+ });
+
+ // send malicious data as client (too long length and wrong protocol version)
+ std::uint8_t its_malicious_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ tcp_socket2.send(boost::asio::buffer(its_malicious_client_data));
+ tcp_service_receive_thread.join();
+ EXPECT_EQ(1u, error_response_as_client_received);
+ EXPECT_EQ(1u, fin_as_client_received);
+
+ tcp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket2.close(ec);
+
+ // establish a tcp connection as client again and send wrong protocol
+ // version in message with a correct length field
+ boost::asio::ip::tcp::socket tcp_socket5(io_);
+ tcp_socket5.open(remote.protocol());
+ tcp_socket5.connect(remote);
+
+ std::thread tcp_service_receive_thread2([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = tcp_socket5.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (!error) {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ std::shared_ptr<vsomeip::message> its_message(its_deserializer.deserialize_message());
+ EXPECT_EQ(0x3345, its_message->get_service());
+ EXPECT_EQ(0x1, its_message->get_method());
+ EXPECT_EQ(0xCCCC, its_message->get_client());
+ EXPECT_EQ(0xDDDD, its_message->get_session());
+ EXPECT_EQ(vsomeip::return_code_e::E_WRONG_PROTOCOL_VERSION, its_message->get_return_code());
+ EXPECT_EQ(vsomeip::message_type_e::MT_ERROR, its_message->get_message_type());
+ error_response_as_client_received++;
+ // service must sent back error response before closing the connection
+ EXPECT_EQ(error_response_as_client_received - 1u, fin_as_client_received);
+ if (error_response_as_client_received == 2) {
+ keep_receiving = false;
+ }
+ }
+ }
+ });
+
+ // send malicious data as client (wrong protocol version)
+ std::uint8_t its_malicious_client_data_correct_length[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ tcp_socket5.send(boost::asio::buffer(its_malicious_client_data_correct_length));
+ tcp_service_receive_thread2.join();
+ EXPECT_EQ(2u, error_response_as_client_received);
+ EXPECT_EQ(1u, fin_as_client_received);
+
+ tcp_socket5.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket5.close(ec);
+
+ // call shutdown method
+ std::uint8_t shutdown_call[] = {
+ 0x33, 0x45, 0x14, 0x04,
+ 0x00, 0x00, 0x00, 0x08,
+ 0x22, 0x22, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ boost::system::error_code ec;
+ udp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket.close(ec);
+ tcp_socket.close(ec);
+
+}
+
+/*
+ * @test Send a message with an invalid message type to the test master
+ * one time as client and one time as service. Ensure that the client
+ * reestablishes the TCP connection after the service sent an message with an
+ * invalid protocol version back
+ */
+TEST_F(malicious_data, send_wrong_message_type)
+{
+ std::promise<void> remote_client_subscribed;
+ std::promise<void> offer_received;
+
+ boost::asio::ip::tcp::socket tcp_socket(io_);
+ boost::asio::ip::udp::socket udp_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.24.1
+ udp_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.24.1").to_v4()));
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (auto e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(1u, its_casted_entry->get_eventgroup());
+ }
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(2,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id + 1u, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(2u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ try {
+ std::promise<void> client_connected;
+ boost::asio::ip::tcp::socket::endpoint_type local(
+ boost::asio::ip::address::from_string(std::string(local_address)),
+ 40001);
+ boost::asio::ip::tcp::acceptor its_acceptor(io_);
+ boost::system::error_code ec;
+ its_acceptor.open(local.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "acceptor open");
+ its_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "acceptor set_option");
+ its_acceptor.bind(local, ec);
+ boost::asio::detail::throw_error(ec, "acceptor bind");
+ its_acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ boost::asio::detail::throw_error(ec, "acceptor listen");
+ its_acceptor.async_accept(tcp_socket, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_connected.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk: " << _error.message();
+ }
+ });
+
+
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x33, 0x44, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x06, 0x9c, 0x41,
+ };
+ boost::asio::ip::address its_local_address =
+ boost::asio::ip::address::from_string(std::string(local_address));
+ std::memcpy(&its_offer_service_message[48], &its_local_address.to_v4().to_bytes()[0], 4);
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30490);
+ udp_socket.send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+
+ // wait until client established TCP connection
+ if (std::future_status::timeout == client_connected.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't connect within time";
+ }
+
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ }
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ }
+
+ std::atomic<bool> fin_as_service_received(false);
+ std::promise<void> client_reconnected;
+
+ std::thread tcp_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ tcp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (!error) {
+ ADD_FAILURE() << __func__ << ":" << __LINE__
+ << " received a non-error:" << error.message();
+ } else if (error == boost::asio::error::eof) {
+ EXPECT_EQ(boost::asio::error::eof, error);
+ fin_as_service_received = true;
+ keep_receiving = false;
+ } else {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << ":" << __LINE__ << " error: " << error.message();
+ return;
+ }
+ }
+ });
+
+ boost::asio::ip::tcp::socket tcp_socket3(io_);
+ its_acceptor.async_accept(tcp_socket3, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_reconnected.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk2: " << _error.message();
+ }
+ });
+ // send malicious data as server (too long length and wrong message type)
+ std::uint8_t its_malicious_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xBB, 0xBB, 0xCA, 0xFE,
+ 0x01, 0x00, 0xAA, 0x00 // message type set to 0xAA
+ };
+ tcp_socket.send(boost::asio::buffer(its_malicious_data));
+
+ // wait until client reestablished TCP connection
+ if (std::future_status::timeout == client_reconnected.get_future().wait_for(std::chrono::seconds(10))) {
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+ ADD_FAILURE() << "Client didn't reconnect within time";
+ } else {
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+ }
+
+ tcp_receive_thread.join();
+
+ EXPECT_TRUE(fin_as_service_received);
+
+
+ // establish second tcp connection as client and send malicious data as well
+ std::atomic<bool> fin_as_client_received(false);
+
+ boost::asio::ip::tcp::socket tcp_socket2(io_);
+ boost::asio::ip::tcp::socket::endpoint_type remote(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 40001);
+ tcp_socket2.open(remote.protocol());
+ tcp_socket2.connect(remote);
+
+
+ std::thread tcp_service_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::function<void()> receive;
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ auto receive_cbk = [&](const boost::system::error_code& _error,
+ std::size_t bytes_transferred) {
+ (void)bytes_transferred;
+ if (!_error) {
+ ADD_FAILURE() << __func__ << ":" << __LINE__
+ << " received a non-error:" << _error.message();
+ } else {
+ EXPECT_EQ(boost::asio::error::eof, _error);
+ fin_as_client_received = true;
+ keep_receiving = false;
+
+ }
+ };
+
+ receive = [&]() {
+ tcp_socket2.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
+ receive_cbk);
+ };
+
+ while (keep_receiving) {
+ receive();
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ });
+
+ // send malicious data as client (too long length and wrong message type)
+ std::uint8_t its_malicious_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0x01, 0x00, 0xAA, 0x00 // protocol version set to 0xAA
+ };
+ tcp_socket2.send(boost::asio::buffer(its_malicious_client_data));
+ tcp_service_receive_thread.join();
+ EXPECT_TRUE(fin_as_client_received);
+
+ tcp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket2.close(ec);
+
+ // call shutdown method
+ std::uint8_t shutdown_call[] = {
+ 0x33, 0x45, 0x14, 0x04,
+ 0x00, 0x00, 0x00, 0x08,
+ 0x22, 0x22, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ boost::system::error_code ec;
+ udp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket.close(ec);
+ tcp_socket.close(ec);
+
+}
+
+/*
+ * @test Send a message with an invalid return code to the test master
+ * one time as client and one time as service. Ensure that the client
+ * reestablishes the TCP connection after the service sent an message with an
+ * invalid protocol version back
+ */
+TEST_F(malicious_data, send_wrong_return_code)
+{
+ std::promise<void> remote_client_subscribed;
+ std::promise<void> offer_received;
+
+ boost::asio::ip::tcp::socket tcp_socket(io_);
+ boost::asio::ip::udp::socket udp_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.24.1
+ udp_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.24.1").to_v4()));
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (auto e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(1u, its_casted_entry->get_eventgroup());
+ }
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(2,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id + 1u, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(2u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ try {
+ std::promise<void> client_connected;
+ boost::asio::ip::tcp::socket::endpoint_type local(
+ boost::asio::ip::address::from_string(std::string(local_address)),
+ 40001);
+ boost::asio::ip::tcp::acceptor its_acceptor(io_);
+ boost::system::error_code ec;
+ its_acceptor.open(local.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "acceptor open");
+ its_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "acceptor set_option");
+ its_acceptor.bind(local, ec);
+ boost::asio::detail::throw_error(ec, "acceptor bind");
+ its_acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ boost::asio::detail::throw_error(ec, "acceptor listen");
+ its_acceptor.async_accept(tcp_socket, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_connected.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk: " << _error.message();
+ }
+ });
+
+
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x33, 0x44, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x06, 0x9c, 0x41,
+ };
+ boost::asio::ip::address its_local_address =
+ boost::asio::ip::address::from_string(std::string(local_address));
+ std::memcpy(&its_offer_service_message[48], &its_local_address.to_v4().to_bytes()[0], 4);
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30490);
+ udp_socket.send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+
+ // wait until client established TCP connection
+ if (std::future_status::timeout == client_connected.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't connect within time";
+ }
+
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ }
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ }
+
+ std::atomic<bool> fin_as_service_received(false);
+ std::promise<void> client_reconnected;
+
+ std::thread tcp_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ tcp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (!error) {
+ ADD_FAILURE() << __func__ << ":" << __LINE__
+ << " received a non-error:" << error.message();
+ } else if (error == boost::asio::error::eof) {
+ EXPECT_EQ(boost::asio::error::eof, error);
+ fin_as_service_received = true;
+ keep_receiving = false;
+ } else {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << ":" << __LINE__ << " error: " << error.message();
+ return;
+ }
+ }
+ });
+
+ boost::asio::ip::tcp::socket tcp_socket3(io_);
+ its_acceptor.async_accept(tcp_socket3, [&](boost::system::error_code _error) {
+ if (!_error) {
+ // Nagle algorithm off
+ tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true));
+ client_reconnected.set_value();
+ } else {
+ ADD_FAILURE() << "accept_cbk2: " << _error.message();
+ }
+ });
+ // send malicious data as server (too long length and wrong return code)
+ std::uint8_t its_malicious_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xBB, 0xBB, 0xCA, 0xFE,
+ 0x01, 0x00, 0x00, 0xAA // return code set to 0xAA
+ };
+ tcp_socket.send(boost::asio::buffer(its_malicious_data));
+
+ // wait until client reestablished TCP connection
+ if (std::future_status::timeout == client_reconnected.get_future().wait_for(std::chrono::seconds(10))) {
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+ ADD_FAILURE() << "Client didn't reconnect within time";
+ } else {
+ tcp_socket3.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket3.close(ec);
+ }
+
+ tcp_receive_thread.join();
+
+ EXPECT_TRUE(fin_as_service_received);
+
+
+ // establish second tcp connection as client and send malicious data as well
+ std::atomic<bool> fin_as_client_received(false);
+
+ boost::asio::ip::tcp::socket tcp_socket2(io_);
+ boost::asio::ip::tcp::socket::endpoint_type remote(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 40001);
+ tcp_socket2.open(remote.protocol());
+ tcp_socket2.connect(remote);
+
+
+ std::thread tcp_service_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::function<void()> receive;
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ auto receive_cbk = [&](const boost::system::error_code& _error,
+ std::size_t bytes_transferred) {
+ (void)bytes_transferred;
+ if (!_error) {
+ ADD_FAILURE() << __func__ << ":" << __LINE__
+ << " received a non-error:" << _error.message();
+ } else {
+ EXPECT_EQ(boost::asio::error::eof, _error);
+ fin_as_client_received = true;
+ keep_receiving = false;
+
+ }
+ };
+
+ receive = [&]() {
+ tcp_socket2.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
+ receive_cbk);
+ };
+
+ while (keep_receiving) {
+ receive();
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ });
+
+ // send malicious data as client (too long length and wrong return code)
+ std::uint8_t its_malicious_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x07, 0x7f,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0x01, 0x00, 0x00, 0xAA // return version set to 0xAA
+ };
+ tcp_socket2.send(boost::asio::buffer(its_malicious_client_data));
+ tcp_service_receive_thread.join();
+ EXPECT_TRUE(fin_as_client_received);
+
+ tcp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket2.close(ec);
+
+ // call shutdown method
+ std::uint8_t shutdown_call[] = {
+ 0x33, 0x45, 0x14, 0x04,
+ 0x00, 0x00, 0x00, 0x08,
+ 0x22, 0x22, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ boost::system::error_code ec;
+ udp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ tcp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket.close(ec);
+ tcp_socket.close(ec);
+
+}
+
+/*
+ * @test Send a message with an invalid protocol version, invalid message type
+ * and invalid return code via UDP to the test master
+ * one time as client and one time as service. Ensure that message with the
+ * WRONG_PROTOCOL_VERSION is sent back in both cases
+ */
+TEST_F(malicious_data, wrong_header_fields_udp)
+{
+ std::promise<void> remote_client_subscribed;
+ std::promise<void> offer_received;
+
+ boost::asio::ip::udp::socket udp_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+ boost::asio::ip::udp::socket udp_socket_service(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 40001));
+
+ boost::asio::ip::udp::endpoint udp_client_info;
+ boost::asio::ip::udp::endpoint udp_service_info;
+
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.24.1
+ udp_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.24.1").to_v4()));
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (auto e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(1u, its_casted_entry->get_eventgroup());
+ }
+ std::shared_ptr<vsomeip::sd::option_impl> op = sd_msg.get_options().front();
+ EXPECT_EQ(op->get_type(), vsomeip::sd::option_type_e::IP4_ENDPOINT);
+ EXPECT_EQ(op->get_length(), 9u);
+ if (op->get_type() == vsomeip::sd::option_type_e::IP4_ENDPOINT) {
+ std::shared_ptr<vsomeip::sd::ipv4_option_impl> ip_op
+ = std::static_pointer_cast<vsomeip::sd::ipv4_option_impl>(op);
+ EXPECT_EQ(vsomeip::sd::layer_four_protocol_e::UDP, ip_op->get_layer_four_protocol());
+ udp_client_info = boost::asio::ip::udp::endpoint(
+ boost::asio::ip::address_v4(ip_op->get_address()),
+ ip_op->get_port());
+ }
+
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(2,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(malicious_data_test::service.service_id + 1u, e->get_service());
+ EXPECT_EQ(malicious_data_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(2u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ for (const auto op : sd_msg.get_options()) {
+ EXPECT_EQ(op->get_type(), vsomeip::sd::option_type_e::IP4_ENDPOINT);
+ EXPECT_EQ(op->get_length(), 9u);
+ if (op->get_type() == vsomeip::sd::option_type_e::IP4_ENDPOINT) {
+ std::shared_ptr<vsomeip::sd::ipv4_option_impl> ip_op
+ = std::static_pointer_cast<vsomeip::sd::ipv4_option_impl>(op);
+ if (ip_op->get_layer_four_protocol() == vsomeip::sd::layer_four_protocol_e::UDP) {
+ EXPECT_EQ(vsomeip::sd::layer_four_protocol_e::UDP, ip_op->get_layer_four_protocol());
+ udp_service_info = boost::asio::ip::udp::endpoint(
+ boost::asio::ip::address_v4(ip_op->get_address()),
+ ip_op->get_port());
+ }
+ }
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ try {
+ boost::system::error_code ec;
+ udp_socket_service.set_option(boost::asio::socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "udp_socket_service set_option");
+
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x33, 0x44, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x11, 0x9c, 0x41, // offer via udp
+ };
+ boost::asio::ip::address its_local_address =
+ boost::asio::ip::address::from_string(std::string(local_address));
+ std::memcpy(&its_offer_service_message[48], &its_local_address.to_v4().to_bytes()[0], 4);
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30490);
+ udp_socket.send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ }
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ }
+
+ // send malicious data as server (wrong protocol version)
+ std::uint8_t wrong_protocol_data[] = {
+ 0x33, 0x44, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xAA, 0xAA, 0xCA, 0xFE,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ udp_socket_service.send_to(boost::asio::buffer(wrong_protocol_data), udp_client_info);
+
+ std::uint8_t wrong_message_type_data[] = {
+ 0x33, 0x44, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xBB, 0xBB, 0xCA, 0xFE,
+ 0x01, 0x00, 0xBB, 0x00 // message type set to 0xBB
+ };
+ udp_socket_service.send_to(boost::asio::buffer(wrong_message_type_data), udp_client_info);
+
+ std::uint8_t wrong_return_code_data[] = {
+ 0x33, 0x44, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xCA, 0xFE,
+ 0x01, 0x00, 0x00, 0xCC // return code set to 0xCC
+ };
+ udp_socket_service.send_to(boost::asio::buffer(wrong_return_code_data), udp_client_info);
+
+ std::uint8_t all_wrong_data[] = {
+ 0x33, 0x44, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xAA, 0xAA, 0xCA, 0xFE,
+ 0xAA, 0x00, 0xBB, 0xCC
+ };
+ udp_socket_service.send_to(boost::asio::buffer(all_wrong_data), udp_client_info);
+
+ udp_socket_service.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket_service.close(ec);
+
+ // establish second UDP connection as client and send malicious data as well
+ std::atomic<bool> error_response_as_client_received(false);
+
+ boost::asio::ip::udp::socket udp_socket_client(io_);
+ boost::asio::ip::udp::socket::endpoint_type remote(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30001);
+ udp_socket_client.open(remote.protocol());
+ udp_socket_client.connect(remote);
+
+
+ std::thread udp_client_receive_thread([&]() {
+ std::atomic<bool> keep_receiving(true);
+ std::function<void()> receive;
+ std::vector<std::uint8_t> receive_buffer(4096);
+
+ auto receive_cbk = [&](const boost::system::error_code& _error,
+ std::size_t bytes_transferred) {
+ if (!_error) {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ std::shared_ptr<vsomeip::message> its_message(its_deserializer.deserialize_message());
+ EXPECT_EQ(0x3345, its_message->get_service());
+ EXPECT_EQ(0x1, its_message->get_method());
+ EXPECT_EQ(0xCCCC, its_message->get_client());
+ EXPECT_EQ(0xDDDD, its_message->get_session());
+ EXPECT_EQ(vsomeip::return_code_e::E_WRONG_PROTOCOL_VERSION, its_message->get_return_code());
+ EXPECT_EQ(vsomeip::message_type_e::MT_ERROR, its_message->get_message_type());
+ error_response_as_client_received = true;
+ keep_receiving = false;
+ } else {
+ ADD_FAILURE() << __func__ << ":" << __LINE__ << " error: " << _error.message();
+ return;
+ }
+ };
+
+ receive = [&]() {
+ udp_socket_client.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
+ receive_cbk);
+ };
+
+ while (keep_receiving) {
+ receive();
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ });
+
+ // send malicious data as client (too long length and wrong protocol version)
+ std::uint8_t wrong_protocol_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0xAA, 0x00, 0x00, 0x00 // protocol version set to 0xAA
+ };
+ udp_socket_client.send_to(boost::asio::buffer(wrong_protocol_client_data), udp_service_info);
+
+ std::uint8_t wrong_message_type_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0x01, 0x00, 0xBB, 0x00 // message type set to 0xBB
+ };
+ udp_socket_client.send_to(boost::asio::buffer(wrong_message_type_client_data), udp_service_info);
+
+ std::uint8_t wrong_return_code_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0x01, 0x00, 0x00, 0xCC // return code set to 0xCC
+ };
+ udp_socket_client.send_to(boost::asio::buffer(wrong_return_code_client_data), udp_service_info);
+
+ std::uint8_t all_wrong_client_data[] = {
+ 0x33, 0x45, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xCC, 0xCC, 0xDD, 0xDD,
+ 0xAA, 0x00, 0xBB, 0xCC
+ };
+ udp_socket_client.send_to(boost::asio::buffer(all_wrong_client_data), udp_service_info);
+
+
+ udp_client_receive_thread.join();
+ EXPECT_TRUE(error_response_as_client_received);
+
+ udp_socket_client.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket_client.close(ec);
+
+ // call shutdown method
+ std::uint8_t shutdown_call[] = {
+ 0x33, 0x45, 0x14, 0x04,
+ 0x00, 0x00, 0x00, 0x08,
+ 0x22, 0x22, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(
+ boost::asio::ip::address::from_string(std::string(remote_address)),
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ boost::system::error_code ec;
+ udp_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket.close(ec);
+}
+
#ifndef _WIN32
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if(argc < 3) {
- std::cerr << "Please pass an target and local IP address to this binary like: "
- << argv[0] << " 10.0.3.1 10.0.3.202" << std::endl;
+ std::cerr << "Please pass an target, local IP address and test mode to this binary like: "
+ << argv[0] << " 10.0.3.1 10.0.3.202 EVENTS" << std::endl;
exit(1);
}
remote_address = argv[1];
local_address = argv[2];
+ std::string its_testmode = argv[3];
+ if (its_testmode == std::string("MALICIOUS_EVENTS")) {
+ ::testing::GTEST_FLAG(filter) = "*send_malicious_events";
+ } else if (its_testmode == std::string("PROTOCOL_VERSION")) {
+ ::testing::GTEST_FLAG(filter) = "*send_wrong_protocol_version";
+ } else if (its_testmode == std::string("MESSAGE_TYPE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_wrong_message_type";
+ } else if (its_testmode == std::string("RETURN_CODE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_wrong_return_code";
+ } else if (its_testmode == std::string("WRONG_HEADER_FIELDS_UDP")) {
+ ::testing::GTEST_FLAG(filter) = "*wrong_header_fields_udp";
+ }
return RUN_ALL_TESTS();
}
#endif
diff --git a/test/malicious_data_tests/malicious_data_test_service.cpp b/test/malicious_data_tests/malicious_data_test_service.cpp
index 17a4bb8..cc4999e 100644
--- a/test/malicious_data_tests/malicious_data_test_service.cpp
+++ b/test/malicious_data_tests/malicious_data_test_service.cpp
@@ -61,15 +61,20 @@ public:
// request service of client
app_->request_service(service_info_.service_id, service_info_.instance_id);
app_->subscribe(service_info_.service_id, service_info_.instance_id,
- service_info_.eventgroup_id, 0, vsomeip::subscription_type_e::SU_RELIABLE,
+ service_info_.eventgroup_id, 0,
+ (testmode_ == malicious_data_test::test_mode_e::WRONG_HEADER_FIELDS_UDP) ?
+ vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE :
+ vsomeip::subscription_type_e::SU_RELIABLE,
service_info_.event_id);
app_->start();
}
~malicious_data_test_service() {
- EXPECT_EQ(9u, received_events_);
- EXPECT_EQ(9u, received_methodcalls_);
+ if (testmode_ == malicious_data_test::test_mode_e::MALICIOUS_EVENTS) {
+ EXPECT_EQ(9u, received_events_);
+ EXPECT_EQ(9u, received_methodcalls_);
+ }
offer_thread_.join();
}
@@ -153,7 +158,7 @@ private:
std::thread offer_thread_;
};
-malicious_data_test::test_mode_e its_testmode(malicious_data_test::test_mode_e::SUBSCRIBE);
+malicious_data_test::test_mode_e its_testmode(malicious_data_test::test_mode_e::MALICIOUS_EVENTS);
TEST(someip_malicious_data_test, block_subscription_handler)
{
@@ -165,6 +170,18 @@ TEST(someip_malicious_data_test, block_subscription_handler)
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
+ std::string its_passed_testmode = argv[1];
+ if (its_passed_testmode == std::string("MALICIOUS_EVENTS")) {
+ its_testmode = malicious_data_test::test_mode_e::MALICIOUS_EVENTS;
+ } else if (its_passed_testmode == std::string("PROTOCOL_VERSION")) {
+ its_testmode = malicious_data_test::test_mode_e::PROTOCOL_VERSION;
+ } else if (its_passed_testmode == std::string("MESSAGE_TYPE")) {
+ its_testmode = malicious_data_test::test_mode_e::MESSAGE_TYPE;
+ } else if (its_passed_testmode == std::string("RETURN_CODE")) {
+ its_testmode = malicious_data_test::test_mode_e::RETURN_CODE;
+ } else if (its_passed_testmode == std::string("WRONG_HEADER_FIELDS_UDP")) {
+ its_testmode = malicious_data_test::test_mode_e::WRONG_HEADER_FIELDS_UDP;
+ }
return RUN_ALL_TESTS();
}
#endif