summaryrefslogtreecommitdiff
path: root/implementation/security/src/security_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/security/src/security_impl.cpp')
-rw-r--r--implementation/security/src/security_impl.cpp1196
1 files changed, 0 insertions, 1196 deletions
diff --git a/implementation/security/src/security_impl.cpp b/implementation/security/src/security_impl.cpp
deleted file mode 100644
index 377e310..0000000
--- a/implementation/security/src/security_impl.cpp
+++ /dev/null
@@ -1,1196 +0,0 @@
-// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <sstream>
-
-#ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #define NOMINMAX
- #include <windows.h>
- #include <stdlib.h>
-#endif
-
-#include <algorithm>
-
-#include <vsomeip/internal/policy_manager.hpp>
-#include "../include/security_impl.hpp"
-#include "../../configuration/include/configuration_element.hpp"
-#ifdef ANDROID
-#include "../../configuration/include/internal_android.hpp"
-#else
-#include "../../configuration/include/internal.hpp"
-#endif // ANDROID
-
-namespace vsomeip_v3 {
-
-template<typename T_>
-void read_data(const std::string &_in, T_ &_out) {
- std::stringstream its_converter;
-
- if (_in.size() > 2
- && _in[0] == '0'
- && (_in[1] == 'x' || _in[1] == 'X'))
- its_converter << std::hex << _in;
- else
- its_converter << std::dec << _in;
-
- its_converter >> _out;
-}
-
-security_impl::security_impl()
- : policy_enabled_(false),
- check_credentials_(false),
- check_routing_credentials_(false),
- allow_remote_clients_(true),
- check_whitelist_(false),
- is_configured_(false) {
-}
-
-void
-security_impl::load(const configuration_element &_element) {
- load_policies(_element);
- load_security_update_whitelist(_element);
- load_routing_credentials(_element);
-
- if (policy_enabled_ && check_credentials_)
- VSOMEIP_INFO << "Security configuration is active.";
-
- if (policy_enabled_ && !check_credentials_)
- VSOMEIP_INFO << "Security configuration is active but in audit mode (allow all)";
-}
-
-bool
-security_impl::is_enabled() const {
- return policy_enabled_;
-}
-
-bool
-security_impl::is_audit() const {
- return check_credentials_;
-}
-
-bool
-security_impl::check_credentials(client_t _client,
- uid_t _uid, gid_t _gid) {
-
- if (!policy_enabled_) {
- return true;
- }
-
- std::vector<std::shared_ptr<policy> > its_policies;
- bool has_id(false);
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- for (const auto &p : its_policies) {
- std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
-
- bool has_uid, has_gid(false);
-
- const auto found_uid = p->credentials_.find(_uid);
- has_uid = (found_uid != p->credentials_.end());
- if (has_uid) {
- const auto found_gid = found_uid->second.find(_gid);
- has_gid = (found_gid != found_uid->second.end());
- }
-
- has_id = (has_uid && has_gid);
-
- if ((has_id && p->allow_who_) || (!has_id && !p->allow_who_)) {
- if (!store_client_to_uid_gid_mapping(_client,_uid, _gid)) {
- std::string security_mode_text = "!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << _uid << "/" << _gid
- << " : Check credentials failed as existing credentials would be overwritten"
- << security_mode_text;
- return !check_credentials_;
- }
- store_uid_gid_to_client_mapping(_uid, _gid, _client);
- return true;
- }
- }
-
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << _uid << "/" << _gid
- << " : Check credentials failed" << security_mode_text;
-
- return !check_credentials_;
-}
-
-bool
-security_impl::is_client_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
- service_t _service, instance_t _instance, method_t _method,
- bool _is_request_service) const {
-
- if (!policy_enabled_) {
- return true;
- }
-
- uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
- std::vector<std::shared_ptr<policy> > its_policies;
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- if (_uid != ANY_UID && _gid != ANY_GID) {
- its_uid = _uid;
- its_gid = _gid;
- } else {
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
- << " for client 0x" << std::hex << _client << " is not valid"
- << ". Therefore it isn't allowed to communicate to service/instance "
- << _service << "/" << _instance
- << security_mode_text;
-
- return !check_credentials_;
- }
-
- for (const auto &p : its_policies) {
- std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
-
- bool has_uid, has_gid(false);
- bool is_matching(false);
-
- const auto found_uid = p->credentials_.find(_uid);
- has_uid = (found_uid != p->credentials_.end());
- if (has_uid) {
- const auto found_gid = found_uid->second.find(_gid);
- has_gid = (found_gid != found_uid->second.end());
- }
-
- const auto found_service = p->requests_.find(_service);
- if (found_service != p->requests_.end()) {
- const auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- if (!_is_request_service) {
- const auto found_method = found_instance->second.find(_method);
- is_matching = (found_method != found_instance->second.end());
- } else {
- // handle VSOMEIP_REQUEST_SERVICE
- is_matching = true;
- }
- }
- }
-
- if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
- if (p->allow_what_) {
- // allow policy
- if (is_matching) {
- return (true);
- }
- } else {
- // deny policy
- // allow client if the service / instance / !ANY_METHOD was not found
- if ((!is_matching && (_method != ANY_METHOD))
- // allow client if the service / instance / ANY_METHOD was not found
- // and it is a "deny nothing" policy
- || (!is_matching && (_method == ANY_METHOD) && p->requests_.empty())) {
- return (true);
- }
- }
- }
- }
-
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
- << " : Isn't allowed to communicate with service/instance/(method / event) " << std::hex
- << _service << "/" << _instance << "/" << _method
- << security_mode_text;
-
- return (!check_credentials_);
-}
-
-bool
-security_impl::is_offer_allowed(uint32_t _uid, uint32_t _gid, client_t _client, service_t _service,
- instance_t _instance) const {
- if (!policy_enabled_) {
- return true;
- }
-
- uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
- std::vector<std::shared_ptr<policy> > its_policies;
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- if (_uid != ANY_UID
- && _gid != ANY_GID) {
- its_uid = _uid;
- its_gid = _gid;
- } else {
- std::string security_mode_text = " ~> Skip offer!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
- << " for client 0x" << std::hex << _client << " is not valid"
- << ". Therefore it isn't allowed to offer service/instance "
- << _service << "/" << _instance
- << security_mode_text;
-
- return !check_credentials_;
- }
-
- for (const auto &p : its_policies) {
- std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
- bool has_uid, has_gid(false), has_offer(false);
-
- const auto found_uid = p->credentials_.find(_uid);
- has_uid = (found_uid != p->credentials_.end());
- if (has_uid) {
- const auto found_gid = found_uid->second.find(_gid);
- has_gid = (found_gid != found_uid->second.end());
- }
-
- const auto found_service = p->offers_.find(_service);
- if (found_service != p->offers_.end()) {
- const auto found_instance = found_service->second.find(_instance);
- has_offer = (found_instance != found_service->second.end());
- }
-
- if ((has_uid && has_gid && p->allow_who_)
- || ((!has_uid || !has_gid) && !p->allow_who_)) {
- if (p->allow_what_ == has_offer) {
- return (true);
- }
- }
- }
-
- std::string security_mode_text = " ~> Skip offer!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x"
- << std::hex << _client
- << " with UID/GID="
- << std::dec << its_uid << "/" << its_gid
- << " isn't allowed to offer service/instance "
- << std::hex << _service << "/" << _instance
- << security_mode_text;
-
- return (!check_credentials_);
-}
-
-bool
-security_impl::store_client_to_uid_gid_mapping(
- client_t _client, uint32_t _uid, uint32_t _gid) {
- {
- // store the client -> (uid, gid) mapping
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_client = ids_.find(_client);
- if (found_client != ids_.end()) {
- if (found_client->second != std::make_pair(_uid, _gid)) {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x"
- << std::hex << _client << " with UID/GID="
- << std::dec << _uid << "/" << _gid << " : Overwriting existing credentials UID/GID="
- << std::dec << std::get<0>(found_client->second) << "/"
- << std::get<1>(found_client->second);
- found_client->second = std::make_pair(_uid, _gid);
- return true;
- }
- } else {
- ids_[_client] = std::make_pair(_uid, _gid);
- }
- return true;
- }
-}
-
-bool
-security_impl::get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid) {
- {
- // get the UID / GID of the client
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- if (ids_.find(_client) != ids_.end()) {
- _uid_gid = ids_[_client];
- return true;
- }
- return false;
- }
-}
-
-bool
-security_impl::remove_client_to_uid_gid_mapping(client_t _client) {
- std::pair<uint32_t, uint32_t> its_uid_gid;
- bool client_removed(false);
- bool uid_gid_removed(false);
- {
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_client = ids_.find(_client);
- if (found_client != ids_.end()) {
- its_uid_gid = found_client->second;
- ids_.erase(found_client);
- client_removed = true;
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- if (client_removed) {
- auto found_uid_gid = uid_to_clients_.find(its_uid_gid);
- if (found_uid_gid != uid_to_clients_.end()) {
- auto its_client = found_uid_gid->second.find(_client);
- if (its_client != found_uid_gid->second.end()) {
- found_uid_gid->second.erase(its_client);
- if (found_uid_gid->second.empty()) {
- uid_to_clients_.erase(found_uid_gid);
- }
- uid_gid_removed = true;
- }
- }
- } else {
- for (auto its_uid_gid = uid_to_clients_.begin();
- its_uid_gid != uid_to_clients_.end(); ++its_uid_gid) {
- auto its_client = its_uid_gid->second.find(_client);
- if (its_client != its_uid_gid->second.end()) {
- its_uid_gid->second.erase(its_client);
- if (its_uid_gid->second.empty()) {
- uid_to_clients_.erase(its_uid_gid);
- }
- uid_gid_removed = true;
- break;
- }
- }
- }
- }
- return (client_removed && uid_gid_removed);
-}
-
-void
-security_impl::store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
- client_t _client) {
- {
- // store the uid gid to clients mapping
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- std::set<client_t> mapped_clients;
- if (uid_to_clients_.find(std::make_pair(_uid, _gid)) != uid_to_clients_.end()) {
- mapped_clients = uid_to_clients_[std::make_pair(_uid, _gid)];
- mapped_clients.insert(_client);
- uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
- } else {
- mapped_clients.insert(_client);
- uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
- }
- }
-}
-
-bool
-security_impl::get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
- std::set<client_t> &_clients) {
- {
- // get the clients corresponding to uid, gid
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- if (uid_to_clients_.find(_uid_gid) != uid_to_clients_.end()) {
- _clients = uid_to_clients_[_uid_gid];
- return true;
- }
- return false;
- }
-}
-
-bool
-security_impl::remove_security_policy(uint32_t _uid, uint32_t _gid) {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- bool was_removed(false);
- if (!any_client_policies_.empty()) {
- std::vector<std::shared_ptr<policy>>::iterator p_it = any_client_policies_.begin();
- while (p_it != any_client_policies_.end()) {
- bool is_matching(false);
- {
- std::lock_guard<std::mutex> its_policy_lock((*p_it)->mutex_);
- bool has_uid(false), has_gid(false);
- const auto found_uid = (*p_it)->credentials_.find(_uid);
- has_uid = (found_uid != (*p_it)->credentials_.end());
- if (has_uid) {
- const auto found_gid = found_uid->second.find(_gid);
- has_gid = (found_gid != found_uid->second.end());
- }
-
- // only remove "credentials allow" policies to prevent removal of
- // blacklist configured in file
- if (has_uid && has_gid && (*p_it)->allow_who_) {
- is_matching = true;
- }
- }
- if (is_matching) {
- was_removed = true;
- p_it = any_client_policies_.erase(p_it);
- } else {
- ++p_it;
- }
- }
- }
- return (was_removed);
-}
-
-void
-security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
- const std::shared_ptr<policy> &_policy) {
-
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- std::shared_ptr<policy> its_matching_policy;
- for (auto p : any_client_policies_) {
- if (p->credentials_.size() == 1) {
- const auto its_uids = *(p->credentials_.begin());
- if (its_uids.first.lower() == _uid
- && its_uids.first.upper() == _uid) {
- if (its_uids.second.size() == 1) {
- const auto its_gids = *(its_uids.second.begin());
- if (its_gids.lower() == _gid
- && its_gids.upper() == _gid) {
- if (p->allow_who_ == _policy->allow_who_) {
- its_matching_policy = p;
- break;
- }
- }
- }
- }
- }
- }
-
- if (its_matching_policy) {
- for (const auto &r : _policy->requests_) {
- service_t its_lower, its_upper;
- get_bounds(r.first, its_lower, its_upper);
- for (auto s = its_lower; s <= its_upper; s++) {
- boost::icl::discrete_interval<service_t> its_service(s, s,
- boost::icl::interval_bounds::closed());
- its_matching_policy->requests_ += std::make_pair(its_service, r.second);
- }
- }
- for (const auto &o : _policy->offers_) {
- service_t its_lower, its_upper;
- get_bounds(o.first, its_lower, its_upper);
- for (auto s = its_lower; s <= its_upper; s++) {
- boost::icl::discrete_interval<service_t> its_service(s, s,
- boost::icl::interval_bounds::closed());
- its_matching_policy->offers_ += std::make_pair(its_service, o.second);
- }
- }
- } else {
- any_client_policies_.push_back(_policy);
- }
-}
-
-void
-security_impl::add_security_credentials(uint32_t _uid, uint32_t _gid,
- const std::shared_ptr<policy> &_policy, client_t _client) {
-
- bool was_found(false);
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- for (const auto &p : any_client_policies_) {
- bool has_uid(false), has_gid(false);
-
- std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
- const auto found_uid = p->credentials_.find(_uid);
- has_uid = (found_uid != p->credentials_.end());
- if (has_uid) {
- const auto found_gid = found_uid->second.find(_gid);
- has_gid = (found_gid != found_uid->second.end());
- }
-
- if (has_uid && has_gid && p->allow_who_) {
- was_found = true;
- break;
- }
- }
-
- // Do not add the new (credentials-only-policy) if a allow
- // credentials policy with same credentials was found
- if (!was_found) {
- any_client_policies_.push_back(_policy);
- VSOMEIP_INFO << __func__ << " Added security credentials at client: 0x"
- << std::hex << _client << std::dec << " with UID: " << _uid << " GID: " << _gid;
- }
-}
-
-bool
-security_impl::is_remote_client_allowed() const {
- if (!check_credentials_) {
- return true;
- }
- return allow_remote_clients_;
-}
-
-bool
-security_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
-
- bool is_uid_allowed(false);
- {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- const auto found_uid = uid_whitelist_.find(_uid);
- is_uid_allowed = (found_uid != uid_whitelist_.end());
- }
-
- if (is_uid_allowed) {
- std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
- std::lock_guard<std::mutex> its_policy_lock(_policy->mutex_);
- for (auto its_request : _policy->requests_) {
- bool has_service(false);
-
- service_t its_service(0);
- for (its_service = its_request.first.lower();
- its_service <= its_request.first.upper();
- its_service++) {
-
- const auto found_service = service_interface_whitelist_.find(its_service);
- has_service = (found_service != service_interface_whitelist_.end());
- if (!has_service)
- break;
- }
-
- if (!has_service) {
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy update requesting service ID: "
- << std::hex << its_service
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy update requesting service ID: "
- << std::hex << its_service
- << " is not allowed! -> ignore update";
- }
- return (!check_whitelist_);
- }
- }
- return (true);
- } else {
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
- << " is not allowed! -> ignore update";
- }
- return (!check_whitelist_);
- }
-}
-
-bool
-security_impl::is_policy_removal_allowed(uint32_t _uid) const {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- for (auto its_uid_range : uid_whitelist_) {
- if (its_uid_range.lower() <= _uid && _uid <= its_uid_range.upper()) {
- return (true);
- }
- }
-
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy removal for UID: "
- << std::dec << _uid
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy removal for UID: "
- << std::dec << _uid
- << " is not allowed! -> ignore removal";
- }
- return (!check_whitelist_);
-}
-
-bool
-security_impl::check_routing_credentials(client_t _client,
- uint32_t _uid, uint32_t _gid) const {
-
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- if (routing_credentials_.first == _uid
- && routing_credentials_.second == _gid) {
-
- return (true);
- }
-
- std::string security_mode_text = "!";
- if (!check_routing_credentials_) {
-
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x"
- << std::hex << _client << " and UID/GID="
- << std::dec << _uid << "/" << _gid
- << " : Check routing credentials failed as "
- << "configured routing manager credentials "
- << "do not match with routing manager credentials"
- << security_mode_text;
-
- return (!check_routing_credentials_);
-}
-
-bool
-security_impl::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
- uint32_t &_uid, uint32_t &_gid, const std::shared_ptr<policy> &_policy) const {
-
- bool is_valid = _policy->deserialize(_buffer, _buffer_size);
- if (is_valid)
- is_valid = _policy->get_uid_gid(_uid, _gid);
- return is_valid;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Configuration
-///////////////////////////////////////////////////////////////////////////////
-void
-security_impl::load_policies(const configuration_element &_element) {
-#ifdef _WIN32
- return;
-#endif
- try {
- auto optional = _element.tree_.get_child_optional("security");
- if (!optional) {
- return;
- }
- policy_enabled_ = true;
- auto found_policy = _element.tree_.get_child("security");
- for (auto its_security = found_policy.begin();
- its_security != found_policy.end(); ++its_security) {
- if (its_security->first == "check_credentials") {
- if (its_security->second.data() == "true") {
- check_credentials_ = true;
- } else {
- check_credentials_ = false;
- }
- } else if (its_security->first == "allow_remote_clients") {
- if (its_security->second.data() == "true") {
- allow_remote_clients_ = true;
- } else {
- allow_remote_clients_ = false;
- }
- } else if (its_security->first == "policies") {
- for (auto its_policy = its_security->second.begin();
- its_policy != its_security->second.end(); ++its_policy) {
- load_policy(its_policy->second);
- }
- }
- }
- } catch (...) {
- }
-}
-
-void
-security_impl::load_policy(const boost::property_tree::ptree &_tree) {
-
- std::shared_ptr<policy> policy(std::make_shared<policy>());
- bool allow_deny_set(false);
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- if (i->first == "credentials") {
- boost::icl::interval_set<uid_t> its_uid_interval_set;
- boost::icl::interval_set<gid_t> its_gid_interval_set;
- boost::icl::discrete_interval<uid_t> its_uid_interval;
- boost::icl::discrete_interval<gid_t> its_gid_interval;
-
- bool has_uid(false), has_gid(false);
- bool has_uid_range(false), has_gid_range(false);
- for (auto n = i->second.begin();
- n != i->second.end(); ++n) {
- std::string its_key(n->first);
- std::string its_value(n->second.data());
- if (its_key == "uid") {
- if(n->second.data().empty()) {
- load_interval_set(n->second, its_uid_interval_set);
- has_uid_range = true;
- } else {
- if (its_value != "any") {
- uint32_t its_uid;
- read_data(its_value, its_uid);
- its_uid_interval = boost::icl::construct<
- boost::icl::discrete_interval<uid_t> >(
- its_uid, its_uid,
- boost::icl::interval_bounds::closed());
- } else {
- its_uid_interval = boost::icl::construct<
- boost::icl::discrete_interval<uid_t> >(
- std::numeric_limits<uid_t>::min(),
- std::numeric_limits<uid_t>::max(),
- boost::icl::interval_bounds::closed());
- }
- has_uid = true;
- }
- } else if (its_key == "gid") {
- if(n->second.data().empty()) {
- load_interval_set(n->second, its_gid_interval_set);
- has_gid_range = true;
- } else {
- if (its_value != "any") {
- uint32_t its_gid;
- read_data(its_value, its_gid);
- its_gid_interval = boost::icl::construct<
- boost::icl::discrete_interval<gid_t> >(
- its_gid, its_gid,
- boost::icl::interval_bounds::closed());
- } else {
- its_gid_interval = boost::icl::construct<
- boost::icl::discrete_interval<gid_t> >(
- std::numeric_limits<gid_t>::min(),
- std::numeric_limits<gid_t>::max(),
- boost::icl::interval_bounds::closed());
- }
- has_gid = true;
- }
- } else if (its_key == "allow" || its_key == "deny") {
- policy->allow_who_ = (its_key == "allow");
- load_credential(n->second, policy->credentials_);
- }
- }
-
- if (has_uid && has_gid) {
- its_gid_interval_set.insert(its_gid_interval);
-
- policy->credentials_ += std::make_pair(its_uid_interval, its_gid_interval_set);
- policy->allow_who_ = true;
- }
- if (has_uid_range && has_gid_range) {
- for (const auto& u : its_uid_interval_set)
- policy->credentials_ += std::make_pair(u, its_gid_interval_set);
- policy->allow_who_ = true;
- }
- } else if (i->first == "allow") {
- if (allow_deny_set) {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"allow\" tag overrides "
- << "already set \"deny\" tag. "
- << "Either \"deny\" or \"allow\" is allowed.";
- }
- allow_deny_set = true;
- policy->allow_what_ = true;
- load_policy_body(policy, i);
- } else if (i->first == "deny") {
- if (allow_deny_set) {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"deny\" tag overrides "
- << "already set \"allow\" tag. "
- << "Either \"deny\" or \"allow\" is allowed.";
- }
- allow_deny_set = true;
- policy->allow_what_ = false;
- load_policy_body(policy, i);
- }
- }
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- any_client_policies_.push_back(policy);
-}
-
-void
-security_impl::load_policy_body(std::shared_ptr<policy> &_policy,
- const boost::property_tree::ptree::const_iterator &_tree) {
-
- for (auto l = _tree->second.begin(); l != _tree->second.end(); ++l) {
- if (l->first == "requests") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t its_service = 0x0;
- instance_t its_instance = 0x0;
- boost::icl::interval_map<instance_t,
- boost::icl::interval_set<method_t> > its_instance_method_intervals;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- if (k->first == "service") {
- read_data(k->second.data(), its_service);
- } else if (k->first == "instance") { // legacy definition for instances
- boost::icl::interval_set<instance_t> its_instance_interval_set;
- boost::icl::interval_set<method_t> its_method_interval_set;
- boost::icl::discrete_interval<instance_t> all_instances(0x01, 0xFFFF,
- boost::icl::interval_bounds::closed());
- boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
- boost::icl::interval_bounds::closed());
-
- std::string its_value(k->second.data());
- if (its_value != "any") {
- read_data(its_value, its_instance);
- if (its_instance != 0x0) {
- its_instance_interval_set.insert(its_instance);
- its_method_interval_set.insert(all_methods);
- }
- } else {
- its_instance_interval_set.insert(all_instances);
- its_method_interval_set.insert(all_methods);
- }
- for (const auto& i : its_instance_interval_set) {
- its_instance_method_intervals
- += std::make_pair(i, its_method_interval_set);
- }
- } else if (k->first == "instances") { // new instances definition
- for (auto p = k->second.begin(); p != k->second.end(); ++p) {
- boost::icl::interval_set<instance_t> its_instance_interval_set;
- boost::icl::interval_set<method_t> its_method_interval_set;
- boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
- boost::icl::interval_bounds::closed());
- for (auto m = p->second.begin(); m != p->second.end(); ++m) {
- if (m->first == "ids") {
- load_interval_set(m->second, its_instance_interval_set);
- } else if (m->first == "methods") {
- load_interval_set(m->second, its_method_interval_set);
- }
- }
- if (its_method_interval_set.empty())
- its_method_interval_set.insert(all_methods);
- for (const auto& i : its_instance_interval_set) {
- its_instance_method_intervals
- += std::make_pair(i, its_method_interval_set);
- }
- }
-
- if (its_instance_method_intervals.empty()) {
- boost::icl::interval_set<instance_t> its_legacy_instance_interval_set;
- boost::icl::interval_set<method_t> its_legacy_method_interval_set;
- boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
- boost::icl::interval_bounds::closed());
- its_legacy_method_interval_set.insert(all_methods);
-
- // try to only load instance ranges with any method to be allowed
- load_interval_set(k->second, its_legacy_instance_interval_set);
- for (const auto& i : its_legacy_instance_interval_set) {
- its_instance_method_intervals
- += std::make_pair(i, its_legacy_method_interval_set);
- }
- }
- }
- }
- if (its_service != 0x0 && !its_instance_method_intervals.empty()) {
- _policy->requests_ += std::make_pair(
- boost::icl::discrete_interval<service_t>(
- its_service, its_service,
- boost::icl::interval_bounds::closed()),
- its_instance_method_intervals);
- }
- }
- } else if (l->first == "offers") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t its_service(0x0);
- instance_t its_instance(0x0);
- boost::icl::interval_set<instance_t> its_instance_interval_set;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- if (k->first == "service") {
- read_data(k->second.data(), its_service);
- } else if (k->first == "instance") { // legacy definition for instances
- std::string its_value(k->second.data());
- if (its_value != "any") {
- read_data(its_value, its_instance);
- if (its_instance != 0x0) {
- its_instance_interval_set.insert(its_instance);
- }
- } else {
- its_instance_interval_set.insert(
- boost::icl::discrete_interval<instance_t>(
- 0x0001, 0xFFFF));
- }
- } else if (k->first == "instances") { // new instances definition
- load_interval_set(k->second, its_instance_interval_set);
- }
- }
- if (its_service != 0x0 && !its_instance_interval_set.empty()) {
- _policy->offers_
- += std::make_pair(
- boost::icl::discrete_interval<service_t>(
- its_service, its_service,
- boost::icl::interval_bounds::closed()),
- its_instance_interval_set);
- }
- }
- }
- }
-}
-
-
-void
-security_impl::load_credential(
- const boost::property_tree::ptree &_tree,
- boost::icl::interval_map<uid_t,
- boost::icl::interval_set<gid_t> > &_credentials) {
-
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- boost::icl::interval_set<uid_t> its_uid_interval_set;
- boost::icl::interval_set<gid_t> its_gid_interval_set;
-
- for (auto j = i->second.begin(); j != i->second.end(); ++j) {
- std::string its_key(j->first);
- if (its_key == "uid") {
- load_interval_set(j->second, its_uid_interval_set);
- } else if (its_key == "gid") {
- load_interval_set(j->second, its_gid_interval_set);
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
- << "Malformed credential (contains illegal key \""
- << its_key << "\")";
- }
- }
-
- for (const auto& its_uid_interval : its_uid_interval_set) {
- _credentials
- += std::make_pair(its_uid_interval, its_gid_interval_set);
- }
- }
-}
-
-bool
-security_impl::load_routing_credentials(const configuration_element &_element) {
- try {
- auto its_routing_cred = _element.tree_.get_child("routing-credentials");
- if (is_configured_) {
- VSOMEIP_WARNING << "vSomeIP Security: Multiple definitions of routing-credentials."
- << " Ignoring definition from " << _element.name_;
- } else {
- for (auto i = its_routing_cred.begin();
- i != its_routing_cred.end();
- ++i) {
- std::string its_key(i->first);
- std::string its_value(i->second.data());
- if (its_key == "uid") {
- uint32_t its_uid(0);
- read_data(its_value, its_uid);
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- std::get<0>(routing_credentials_) = its_uid;
- } else if (its_key == "gid") {
- uint32_t its_gid(0);
- read_data(its_value, its_gid);
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- std::get<1>(routing_credentials_) = its_gid;
- }
- }
- check_routing_credentials_ = true;
- is_configured_ = true;
- }
- } catch (...) {
- return false;
- }
- return true;
-}
-
-
-void
-security_impl::load_security_update_whitelist(const configuration_element &_element) {
-#ifdef _WIN32
- return;
-#endif
- try {
- auto optional = _element.tree_.get_child_optional("security-update-whitelist");
- if (!optional) {
- return;
- }
- auto found_whitelist = _element.tree_.get_child("security-update-whitelist");
- for (auto its_whitelist = found_whitelist.begin();
- its_whitelist != found_whitelist.end(); ++its_whitelist) {
-
- if (its_whitelist->first == "uids") {
- {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- load_interval_set(its_whitelist->second, uid_whitelist_);
- }
- } else if (its_whitelist->first == "services") {
- {
- std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
- load_interval_set(its_whitelist->second, service_interface_whitelist_);
- }
- } else if (its_whitelist->first == "check-whitelist") {
- if (its_whitelist->second.data() == "true") {
- check_whitelist_ = true;
- } else {
- check_whitelist_ = false;
- }
- }
- }
- } catch (...) {
- }
-}
-
-template<typename T_>
-void security_impl::load_interval_set(
- const boost::property_tree::ptree &_tree,
- boost::icl::interval_set<T_> &_intervals, bool _exclude_margins) {
-
- boost::icl::interval_set<T_> its_intervals;
- T_ its_min = std::numeric_limits<T_>::min();
- T_ its_max = std::numeric_limits<T_>::max();
-
- if (_exclude_margins) {
- its_min++;
- its_max--;
- }
-
- const std::string its_key(_tree.data());
- if (its_key == "any") {
- its_intervals.insert(boost::icl::discrete_interval<T_>::closed(
- its_min, its_max));
- } else {
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- auto its_data = i->second;
- if (!its_data.data().empty()) {
- T_ its_id;
- read_data(its_data.data(), its_id);
- if (its_id >= its_min && its_id <= its_max)
- its_intervals.insert(its_id);
- } else {
- T_ its_first, its_last;
- bool has_first(false), has_last(false);
- for (auto j = its_data.begin(); j != its_data.end(); ++j) {
- std::string its_key(j->first);
- std::string its_value(j->second.data());
- if (its_key == "first") {
- if (its_value == "min") {
- its_first = its_min;
- } else {
- read_data(its_value, its_first);
- }
- has_first = true;
- } else if (its_key == "last") {
- if (its_value == "max") {
- its_last = its_max;
- } else {
- read_data(its_value, its_last);
- }
- has_last = true;
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
- << " Malformed range. Contains illegal key ("
- << its_key << ")";
- }
- }
- if (has_first && has_last && its_first <= its_last) {
- its_intervals.insert(
- boost::icl::discrete_interval<T_>::closed(its_first, its_last));
- }
- }
- }
- }
-
- _intervals = its_intervals;
-}
-
-void
-security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
- std::set<std::shared_ptr<policy> > &_requesters) const {
-
- std::vector<std::shared_ptr<policy> > its_policies;
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- std::lock_guard<std::mutex> its_lock(_policy->mutex_);
- for (const auto &o : _policy->offers_) {
- for (const auto &p : its_policies) {
- if (p == _policy)
- continue;
-
- std::lock_guard<std::mutex> its_lock(p->mutex_);
-
- auto its_policy = std::make_shared<policy>();
- its_policy->credentials_ = p->credentials_;
-
- for (const auto &r : p->requests_) {
- // o represents an offer by a service interval and its instances
- // (a set of intervals)
- // r represents a request by a service interval and its instances
- // and methods (instance intervals mapped to interval sets of methods)
- //
- // Thus, r matches o if their service identifiers as well as their
- // instances overlap. If r and o match, a new policy must be
- // created that contains the overlapping services/instances mapping
- // of r and o together with the methods from r
- service_t its_o_lower, its_o_upper, its_r_lower, its_r_upper;
- get_bounds(o.first, its_o_lower, its_o_upper);
- get_bounds(r.first, its_r_lower, its_r_upper);
-
- if (its_o_lower <= its_r_upper && its_r_lower <= its_o_upper) {
- auto its_service_min = std::max(its_o_lower, its_r_lower);
- auto its_service_max = std::min(its_r_upper, its_o_upper);
-
- for (const auto &i : o.second) {
- for (const auto &j : r.second) {
- for (const auto& k : j.second) {
- instance_t its_i_lower, its_i_upper, its_k_lower, its_k_upper;
- get_bounds(i, its_i_lower, its_i_upper);
- get_bounds(k, its_k_lower, its_k_upper);
-
- if (its_i_lower <= its_k_upper && its_k_lower <= its_i_upper) {
- auto its_instance_min = std::max(its_i_lower, its_k_lower);
- auto its_instance_max = std::min(its_i_upper, its_k_upper);
-
- boost::icl::interval_map<instance_t,
- boost::icl::interval_set<method_t> > its_instances_methods;
- its_instances_methods += std::make_pair(
- boost::icl::interval<instance_t>::closed(
- its_instance_min, its_instance_max),
- j.second);
-
- its_policy->requests_ += std::make_pair(
- boost::icl::interval<instance_t>::closed(
- its_service_min, its_service_max),
- its_instances_methods);
- }
- }
- }
- }
- }
- }
-
- if (!its_policy->requests_.empty()) {
- _requesters.insert(its_policy);
- its_policy->print();
- }
- }
- }
-}
-
-void
-security_impl::get_clients(uid_t _uid, gid_t _gid,
- std::unordered_set<client_t> &_clients) const {
-
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- for (const auto &i : ids_) {
- if (i.second.first == _uid && i.second.second == _gid)
- _clients.insert(i.first);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Manage the security object
-////////////////////////////////////////////////////////////////////////////////
-static std::shared_ptr<security_impl> *the_security_ptr__(nullptr);
-static std::mutex the_security_mutex__;
-
-std::shared_ptr<security_impl>
-security_impl::get() {
-#ifndef _WIN32
- std::lock_guard<std::mutex> its_lock(the_security_mutex__);
-#endif
- if(the_security_ptr__ == nullptr) {
- the_security_ptr__ = new std::shared_ptr<security_impl>();
- }
- if (the_security_ptr__ != nullptr) {
- if (!(*the_security_ptr__)) {
- *the_security_ptr__ = std::make_shared<security_impl>();
- }
- return (*the_security_ptr__);
- }
- return (nullptr);
-}
-
-#ifndef _WIN32
-static void security_teardown(void) __attribute__((destructor));
-static void security_teardown(void)
-{
- if (the_security_ptr__ != nullptr) {
- std::lock_guard<std::mutex> its_lock(the_security_mutex__);
- the_security_ptr__->reset();
- delete the_security_ptr__;
- the_security_ptr__ = nullptr;
- }
-}
-#endif
-
-} // namespace vsomeip_v3