summaryrefslogtreecommitdiff
path: root/implementation/routing/src/routing_manager_proxy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/routing/src/routing_manager_proxy.cpp')
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp584
1 files changed, 508 insertions, 76 deletions
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index 8d48b25..d439654 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -10,12 +10,6 @@
#include <future>
#include <forward_list>
-#ifndef _WIN32
-// for umask
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
#include <vsomeip/constants.hpp>
#include <vsomeip/runtime.hpp>
@@ -32,6 +26,10 @@
#include "../../service_discovery/include/runtime.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
+#include "../../configuration/include/policy.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
namespace vsomeip {
@@ -94,8 +92,10 @@ void routing_manager_proxy::stop() {
if (state_ == inner_state_type_e::ST_REGISTERING) {
register_application_timer_.cancel();
}
+
+ const std::chrono::milliseconds its_timeout(configuration_->get_shutdown_timeout());
while (state_ == inner_state_type_e::ST_REGISTERING) {
- std::cv_status status = state_condition_.wait_for(its_lock, std::chrono::milliseconds(1000));
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
if (status == std::cv_status::timeout) {
VSOMEIP_WARNING << std::hex << client_ << " registering timeout on stop";
break;
@@ -106,7 +106,7 @@ void routing_manager_proxy::stop() {
deregister_application();
// Waiting de-register acknowledge to synchronize shutdown
while (state_ == inner_state_type_e::ST_REGISTERED) {
- std::cv_status status = state_condition_.wait_for(its_lock, std::chrono::milliseconds(1000));
+ std::cv_status status = state_condition_.wait_for(its_lock, its_timeout);
if (status == std::cv_status::timeout) {
VSOMEIP_WARNING << std::hex << client_ << " couldn't deregister application - timeout";
break;
@@ -137,7 +137,7 @@ void routing_manager_proxy::stop() {
for (auto client: get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(client);
+ remove_local(client, true);
}
}
@@ -437,6 +437,27 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
event_t _event, subscription_type_e _subscription_type) {
{
+ if (_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(_client, _service, _instance, _eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(_client, _service,
+ _instance, _event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " : routing_manager_proxy::subscribe: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << _service << "/" << _instance
+ << "/" << _event;
+ return;
+ }
+ }
+
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED && is_available(_service, _instance, _major)) {
send_subscribe(_client, _service, _instance, _eventgroup, _major,
@@ -617,8 +638,12 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
bool _flush,
bool _reliable,
- bool _is_valid_crc) {
+ client_t _bound_client,
+ bool _is_valid_crc,
+ bool _sent_from_remote) {
(void)_client;
+ (void)_bound_client;
+ (void)_sent_from_remote;
bool is_sent(false);
bool has_remote_subscribers(false);
{
@@ -697,7 +722,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -741,7 +766,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
const uint16_t its_data_size
= uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, true, _instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
@@ -780,6 +805,7 @@ bool routing_manager_proxy::send_to(
void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) {
_endpoint->set_connected(true);
+ _endpoint->set_established(true);
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (_endpoint != sender_) {
@@ -864,7 +890,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
sizeof(its_length));
- if (configuration_->is_security_enabled() && _bound_client != routing_host_id &&
+ bool message_from_routing(false);
+ if (configuration_->is_security_enabled()) {
+ // if security is enabled, client ID of routing must be configured
+ // and credential passing is active. Otherwise bound client is zero by default
+ message_from_routing = (_bound_client == routing_host_id);
+ } else {
+ message_from_routing = (its_client == routing_host_id);
+ }
+
+ if (configuration_->is_security_enabled() && !message_from_routing &&
_bound_client != its_client) {
VSOMEIP_WARNING << std::hex << "Client " << std::setw(4) << std::setfill('0') << get_client()
<< " received a message with command " << (uint32_t)its_command
@@ -877,20 +912,34 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
switch (its_command) {
case VSOMEIP_SEND: {
+ if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command with too small size -> skip!";
+ break;
+ }
instance_t its_instance;
bool its_reliable;
- bool its_is_vslid_crc;
+ bool its_is_valid_crc;
std::memcpy(&its_instance,&_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
sizeof(instance_t));
std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
sizeof(its_reliable));
- std::memcpy(&its_is_vslid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
- sizeof(its_is_vslid_crc));
+ std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
+ sizeof(its_is_valid_crc));
// reduce by size of instance, flush, reliable, client and is_valid_crc flag
const std::uint32_t its_message_size = its_length -
(VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
+ if (its_message_size !=
+ VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
+ + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_WARNING << "Received a SEND command containing message with invalid size -> skip!";
+ break;
+ }
+
auto a_deserializer = get_deserializer();
a_deserializer->set_data(&_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
its_message_size);
@@ -901,36 +950,110 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
if (its_message) {
its_message->set_instance(its_instance);
its_message->set_reliable(its_reliable);
- its_message->set_is_valid_crc(its_is_vslid_crc);
- if (utility::is_notification(its_message->get_message_type())) {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
- its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
- << " isn't allow receive a notification from to service/instance "
- << its_message->get_service() << "/" << its_message->get_instance()
- << " respectively from client 0x" << its_client
- << " : Skip message!";
- return;
- }
- cache_event_payload(its_message);
- } else if (utility::is_request(its_message->get_message_type())) {
- if (!configuration_->is_client_allowed(its_message->get_client(),
- its_message->get_service(), its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << its_message->get_client()
- << " isn't allow to send a request to service/instance "
- << its_message->get_service() << "/" << its_message->get_instance()
- << " : Skip message!";
- return;
+ its_message->set_is_valid_crc(its_is_valid_crc);
+ if (!message_from_routing) {
+ if (utility::is_notification(its_message->get_message_type())) {
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a notification from client 0x" << _bound_client
+ << " which does not offer service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ cache_event_payload(its_message);
+ }
+ } else if (utility::is_request(its_message->get_message_type())) {
+ if (configuration_->is_security_enabled()
+ && its_message->get_client() != _bound_client) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Client 0x" << std::setw(4) << std::setfill('0') << get_client()
+ << " received a request from client 0x" << std::setw(4) << std::setfill('0')
+ << its_message->get_client() << " to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method() << " which doesn't match the bound client 0x"
+ << std::setw(4) << std::setfill('0') << _bound_client
+ << " ~> skip message!";
+ return;
+ }
+
+ if (!configuration_->is_client_allowed(its_message->get_client(),
+ its_message->get_service(), its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_message->get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "isn't allowed to send a request to service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ }
+ } else { // response
+ if (!is_response_allowed(_bound_client, its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a response from client 0x" << _bound_client
+ << " which does not offer service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " ~> Skip message!";
+ return;
+ } else {
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a response from service/instance/method "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from client 0x" << _bound_client
+ << " ~> Skip message!";
+ return;
+ }
+ }
}
- } else { // response
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
- its_message->get_instance())) {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
- << " isn't allow receive a response from to service/instance "
+ } else {
+ if (!configuration_->is_remote_client_allowed()) {
+ // if the message is from routing manager, check if
+ // policy allows remote requests.
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << std::hex << "Security: Remote clients via routing manager with client ID 0x" << its_client
+ << " are not allowed to communicate with service/instance/method "
<< its_message->get_service() << "/" << its_message->get_instance()
- << " respectively from client 0x" << its_client
- << " : Skip message!";
+ << "/" << its_message->get_method()
+ << " respectively with client 0x" << get_client()
+ << " ~> Skip message!";
return;
+ } else if (utility::is_notification(its_message->get_message_type())) {
+ // As subscription is sent on eventgroup level, incoming remote event ID's
+ // need to be checked as well if remote clients are allowed
+ // and the local policy only allows specific events in the eventgroup to be received.
+ if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to receive a notification from service/instance/event "
+ << its_message->get_service() << "/" << its_message->get_instance()
+ << "/" << its_message->get_method()
+ << " respectively from remote clients via routing manager with client ID 0x"
+ << routing_host_id
+ << " ~> Skip message!";
+ return;
+ }
}
}
#ifdef USE_DLT
@@ -938,10 +1061,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
&& (client_side_logging_filter_.empty()
|| (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), ANY_INSTANCE)))
|| (1 == client_side_logging_filter_.count(std::make_tuple(its_message->get_service(), its_message->get_instance()))))) {
- tc::trace_header its_header;
+ trace::header its_header;
if (its_header.prepare(nullptr, false, its_instance))
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
static_cast<std::uint16_t>(its_message_size));
}
#endif
@@ -950,20 +1073,29 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_ERROR << "Routing proxy: on_message: "
<< "SomeIP-Header deserialization failed!";
}
- }
break;
+ }
case VSOMEIP_ROUTING_INFO:
- if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "Received a ROUTING_INFO command with invalid size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
- VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
+ VSOMEIP_WARNING << "routing_manager_proxy::on_message: "
+ << std::hex << "Security: Client 0x" << get_client()
<< " received an routing info from a client which isn't the routing manager"
<< " : Skip message!";
}
break;
case VSOMEIP_PING:
+ if (_size != VSOMEIP_PING_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a PING command with wrong size ~> skip!";
+ break;
+ }
send_pong();
VSOMEIP_TRACE << "PING("
<< std::hex << std::setw(4) << std::setfill('0') << client_ << ")";
@@ -990,6 +1122,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
std::unique_lock<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
if (its_subscription_id != DEFAULT_SUBSCRIPTION) {
its_lock.unlock();
+ routing_manager_base::set_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
// Remote subscriber: Notify routing manager initially + count subscribes
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance, its_eventgroup,
@@ -1011,6 +1145,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
notify_remote_initially(its_service, its_instance, its_eventgroup,
its_already_subscribed_events);
}
+ send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true);
+
std::uint32_t its_count = get_remote_subscriber_count(
its_service, its_instance, its_eventgroup, true);
VSOMEIP_INFO << "SUBSCRIBE("
@@ -1022,19 +1158,51 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::dec << (uint16_t)its_major << "]"
<< (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " "
<< std::dec << its_count;
+
+ routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event);
});
} else if (is_client_known(its_client)) {
its_lock.unlock();
- if (!configuration_->is_client_allowed(its_client,
- its_service, its_instance)) {
- VSOMEIP_WARNING << "Security: Client " << std::hex
- << its_client << " subscribes to service/instance "
- << its_service << "/" << its_instance
- << " which violates the security policy ~> Skip subscribe!";
- return;
+ if (!message_from_routing) {
+ if (its_event == ANY_EVENT) {
+ if (!is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance << "/ANY_EVENT"
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ } else {
+ if (!configuration_->is_client_allowed(its_client,
+ its_service, its_instance, its_event)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << " subscribes to service/instance/event "
+ << its_service << "/" << its_instance << "/" << its_event
+ << " which violates the security policy ~> Skip subscribe!";
+ return;
+ }
+ }
+ } else {
+ if (!configuration_->is_remote_client_allowed()) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
+ << " : routing_manager_proxy::on_message: "
+ << std::hex << "Routing manager with client ID 0x"
+ << its_client
+ << " isn't allowed to subscribe to service/instance/event "
+ << its_service << "/" << its_instance
+ << "/" << its_event
+ << " respectively to client 0x" << get_client()
+ << " ~> Skip Subscribe!";
+ return;
+ }
}
// Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+ routing_manager_base::set_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
(void) find_or_create_local(its_client);
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance,
@@ -1053,6 +1221,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client);
}
+ routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
+ its_instance, its_eventgroup, its_event);
});
} else {
// Local & not yet known subscriber ~> set pending until subscriber gets known!
@@ -1182,7 +1352,11 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
break;
case VSOMEIP_OFFERED_SERVICES_RESPONSE:
- if (!configuration_->is_security_enabled() ||_bound_client == routing_host_id) {
+ if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_RESPONSE command with invalid size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
on_offered_services_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
@@ -1190,7 +1364,148 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< " : Skip message!";
}
break;
+ case VSOMEIP_RESEND_PROVIDED_EVENTS: {
+ if (_size != VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a RESEND_PROVIDED_EVENTS command with wrong size ~> skip!";
+ break;
+ }
+ pending_remote_offer_id_t its_pending_remote_offer_id(0);
+ std::memcpy(&its_pending_remote_offer_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_remote_offer_id_t));
+ resend_provided_event_registrations();
+ send_resend_provided_event_response(its_pending_remote_offer_id);
+ VSOMEIP_INFO << "RESEND_PROVIDED_EVENTS("
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_client << ")";
+ break;
+ }
+ case VSOMEIP_UPDATE_SECURITY_POLICY: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE + sizeof(pending_security_update_id_t) ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ pending_security_update_id_t its_update_id(0);
+ uint32_t its_uid(0);
+ uint32_t its_gid(0);
+
+ std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ const byte_t* buffer_ptr = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
+ sizeof(pending_security_update_id_t));
+ uint32_t its_size = uint32_t(_size - (VSOMEIP_COMMAND_PAYLOAD_POS
+ + sizeof(pending_security_update_id_t)));
+ utility::parse_policy(buffer_ptr, its_size, its_uid, its_gid, its_policy);
+
+ if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
+ configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ send_update_security_policy_response(its_update_id);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a security policy update from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_REMOVE_SECURITY_POLICY: {
+ if (_size != VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY command with wrong size ~> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ pending_security_update_id_t its_update_id(0);
+ uint32_t its_uid(0xffffffff);
+ uint32_t its_gid(0xffffffff);
+
+ std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(pending_security_update_id_t));
+ std::memcpy(&its_uid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
+ sizeof(uint32_t));
+ std::memcpy(&its_gid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(uint32_t));
+ if (configuration_->is_policy_removal_allowed(its_uid)) {
+ configuration_->remove_security_policy(its_uid, its_gid);
+ send_remove_security_policy_response(its_update_id);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "received a security policy removal from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_DISTRIBUTE_SECURITY_POLICIES: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_DISTRIBUTE_SECURITY_POLICIES command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ uint32_t its_policy_count(0);
+ uint32_t its_policy_size(0);
+ const byte_t* buffer_ptr = 0;
+
+ if (VSOMEIP_COMMAND_PAYLOAD_POS + sizeof(uint32_t) * 2 <= _size) {
+ std::memcpy(&its_policy_count, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
+ sizeof(uint32_t));
+
+ // skip policy count field
+ buffer_ptr = _data + (VSOMEIP_COMMAND_PAYLOAD_POS +
+ sizeof(uint32_t));
+
+ for (uint32_t i = 0; i < its_policy_count; i++) {
+ uint32_t its_uid(0);
+ uint32_t its_gid(0);
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ // length field of next (UID/GID + policy)
+ if (buffer_ptr + sizeof(uint32_t) <= _data + _size) {
+ std::memcpy(&its_policy_size, buffer_ptr,
+ sizeof(uint32_t));
+ buffer_ptr += sizeof(uint32_t);
+
+ if (buffer_ptr + its_policy_size <= _data + _size) {
+ if (utility::parse_policy(buffer_ptr, its_policy_size, its_uid, its_gid, its_policy)) {
+ if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
+ configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client() << " could not parse policy!";
+ }
+ }
+ }
+ }
+ }
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << " received a security policy distribution command from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
+ case VSOMEIP_UPDATE_SECURITY_CREDENTIALS: {
+ if (_size < VSOMEIP_COMMAND_HEADER_SIZE ||
+ _size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
+ VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_CREDENTIALS command with wrong size -> skip!";
+ break;
+ }
+ if (!configuration_->is_security_enabled() || message_from_routing) {
+ on_update_security_credentials(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_message: "
+ << "received a security credential update from a client which isn't the routing manager"
+ << " : Skip message!";
+ }
+ break;
+ }
default:
break;
}
@@ -1237,6 +1552,17 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< " is registered.";
+#ifndef _WIN32
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::on_routing_info: RIE_ADD_CLIENT: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ deregister_application();
+ host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
+ return;
+ }
+#endif
+
// inform host about its own registration state changes
host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_REGISTERED));
@@ -1257,6 +1583,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
known_clients_.erase(its_client);
}
if (its_client == get_client()) {
+ configuration_->remove_client_to_uid_gid_mapping(its_client);
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<< " is deregistered.";
@@ -1270,7 +1597,7 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
state_condition_.notify_one();
}
} else if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client);
+ remove_local(its_client, true);
}
}
@@ -1325,6 +1652,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
auto found_service = local_services_.find(its_service);
if (found_service != local_services_.end()) {
found_service->second.erase(its_instance);
+ // move previously offering client to history
+ local_services_history_[its_service][its_instance].insert(its_client);
if (found_service->second.size() == 0) {
local_services_.erase(its_service);
}
@@ -1374,6 +1703,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
}
}
for (const subscription_info &si : subscription_actions) {
+ routing_manager_base::set_incoming_subscription_state(si.client_id_, si.service_id_, si.instance_id_,
+ si.eventgroup_id_, si.event_, subscription_state_e::IS_SUBSCRIBING);
(void) find_or_create_local(si.client_id_);
auto self = shared_from_this();
host_->on_subscription(
@@ -1393,6 +1724,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
send_pending_notify_ones(si.service_id_,
si.instance_id_, si.eventgroup_id_, si.client_id_);
}
+ routing_manager_base::erase_incoming_subscription_state(si.client_id_, si.service_id_,
+ si.instance_id_, si.eventgroup_id_, si.event_);
{
std::lock_guard<std::recursive_mutex> its_lock2(incoming_subscriptions_mutex_);
pending_incoming_subscripitons_.erase(si.client_id_);
@@ -1469,12 +1802,26 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien
// Remove all local connections/endpoints
for (const auto its_client : _clients) {
if (its_client != VSOMEIP_ROUTING_CLIENT) {
- remove_local(its_client);
+ remove_local(its_client, true);
}
}
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
<<": Reconnecting to routing manager.";
+
+#ifndef _WIN32
+ if (!check_credentials(get_client(), getuid(), getgid())) {
+ VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
+ << " : routing_manager_proxy::reconnect: isn't allowed"
+ << " to use the server endpoint due to credential check failed!";
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->stop();
+ }
+ return;
+ }
+#endif
+
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
sender_->restart();
@@ -1509,14 +1856,10 @@ void routing_manager_proxy::register_application() {
}
void routing_manager_proxy::deregister_application() {
- uint32_t its_size = sizeof(client_);
-
- std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size);
+ std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE, 0);
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_DEREGISTER_APPLICATION;
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
if (is_connected_)
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
@@ -1558,7 +1901,7 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req
std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
sizeof(client_));
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
+ sizeof(std::uint32_t));
uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
+ sizeof(minor_version_t) + sizeof(bool));
@@ -1788,17 +2131,13 @@ void routing_manager_proxy::init_receiver() {
::_unlink(its_client.str().c_str());
int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
#else
- if (!check_credentials(get_client(), getuid(), getgid())) {
- VSOMEIP_ERROR << "routing_manager_proxy::init_receiver: "
- << std::hex << "Client " << get_client() << " isn't allow"
- << " to create a server endpoint due to credential check failed!";
- return;
- }
+ configuration_->store_client_to_uid_gid_mapping(get_client(), getuid(), getgid());
+ configuration_->store_uid_gid_to_client_mapping(getuid(), getgid(), get_client());
+
if (-1 == ::unlink(its_client.str().c_str()) && errno != ENOENT) {
VSOMEIP_ERROR << "routing_manager_proxy::init_receiver unlink failed ("
<< its_client.str() << "): "<< std::strerror(errno);
}
- const mode_t previous_mask(::umask(static_cast<mode_t>(configuration_->get_umask())));
#endif
try {
receiver_ = std::make_shared<local_server_endpoint_impl>(shared_from_this(),
@@ -1809,7 +2148,8 @@ void routing_manager_proxy::init_receiver() {
#endif
io_, configuration_->get_max_message_size_local(),
configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local());
+ configuration_->get_endpoint_queue_limit_local(),
+ configuration_->get_permissions_uds());
#ifdef _WIN32
VSOMEIP_INFO << "Listening at " << port;
#else
@@ -1819,9 +2159,6 @@ void routing_manager_proxy::init_receiver() {
host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
VSOMEIP_ERROR << "Client ID: " << std::hex << client_ << ": " << e.what();
}
-#ifndef _WIN32
- ::umask(previous_mask);
-#endif
}
void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance,
@@ -2008,7 +2345,7 @@ void routing_manager_proxy::handle_client_error(client_t _client) {
if (_client != VSOMEIP_ROUTING_CLIENT) {
VSOMEIP_INFO << "Client 0x" << std::hex << get_client()
<< " handles a client error(" << std::hex << _client << ")";
- remove_local(_client);
+ remove_local(_client, true);
} else {
bool should_reconnect(true);
{
@@ -2077,4 +2414,99 @@ void routing_manager_proxy::send_unsubscribe_ack(
}
}
+void routing_manager_proxy::resend_provided_event_registrations() {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ for (const event_data_t& ed : pending_event_registrations_) {
+ if (ed.is_provided_) {
+ send_register_event(client_, ed.service_, ed.instance_,
+ ed.event_, ed.eventgroups_,
+ ed.is_field_, ed.is_provided_);
+ }
+ }
+}
+
+void routing_manager_proxy::send_resend_provided_event_response(pending_remote_offer_id_t _id) {
+ byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_id,
+ sizeof(pending_remote_offer_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::send_update_security_policy_response(pending_security_update_id_t _update_id) {
+ byte_t its_command[VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
+ sizeof(pending_security_update_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::send_remove_security_policy_response(pending_security_update_id_t _update_id) {
+ byte_t its_command[VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE];
+ const std::uint32_t its_size = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE
+ - VSOMEIP_COMMAND_HEADER_SIZE;
+
+ const client_t its_client = get_client();
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &its_client,
+ sizeof(its_client));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_update_id,
+ sizeof(pending_security_update_id_t));
+ {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ sender_->send(its_command, sizeof(its_command));
+ }
+ }
+}
+
+void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, uint32_t _size) {
+ uint32_t i = 0;
+ while ( (i + sizeof(uint32_t) + sizeof(uint32_t)) <= _size) {
+ std::shared_ptr<policy> its_policy(std::make_shared<policy>());
+ ranges_t its_uid_ranges, its_gid_ranges;
+ uint32_t its_uid, its_gid;
+
+ std::memcpy(&its_uid, &_data[i], sizeof(uint32_t));
+ i += uint32_t(sizeof(uint32_t));
+ std::memcpy(&its_gid, &_data[i], sizeof(uint32_t));
+ i += uint32_t(sizeof(uint32_t));
+
+ its_uid_ranges.insert(std::make_pair(its_uid, its_uid));
+ its_gid_ranges.insert(std::make_pair(its_gid, its_gid));
+
+ its_policy->allow_who_ = true;
+ its_policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
+ configuration_->add_security_credentials(its_uid, its_gid, its_policy, get_client());
+ }
+}
+
} // namespace vsomeip