1 // Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6 #include <sstream>
7
8 #ifdef _WIN32
9 #define WIN32_LEAN_AND_MEAN
10 #define NOMINMAX
11 #include <windows.h>
12 #include <stdlib.h>
13 #endif
14
15 #include <algorithm>
16
17 #include <vsomeip/internal/policy_manager.hpp>
18 #include "../include/security_impl.hpp"
19 #include "../../configuration/include/configuration_element.hpp"
20 #ifdef ANDROID
21 #include "../../configuration/include/internal_android.hpp"
22 #else
23 #include "../../configuration/include/internal.hpp"
24 #endif // ANDROID
25
26 namespace vsomeip_v3 {
27
28 template<typename T_>
read_data(const std::string & _in,T_ & _out)29 void read_data(const std::string &_in, T_ &_out) {
30 std::stringstream its_converter;
31
32 if (_in.size() > 2
33 && _in[0] == '0'
34 && (_in[1] == 'x' || _in[1] == 'X'))
35 its_converter << std::hex << _in;
36 else
37 its_converter << std::dec << _in;
38
39 its_converter >> _out;
40 }
41
security_impl()42 security_impl::security_impl()
43 : policy_enabled_(false),
44 check_credentials_(false),
45 check_routing_credentials_(false),
46 allow_remote_clients_(true),
47 check_whitelist_(false),
48 is_configured_(false) {
49 }
50
51 void
load(const configuration_element & _element)52 security_impl::load(const configuration_element &_element) {
53 load_policies(_element);
54 load_security_update_whitelist(_element);
55 load_routing_credentials(_element);
56
57 if (policy_enabled_ && check_credentials_)
58 VSOMEIP_INFO << "Security configuration is active.";
59
60 if (policy_enabled_ && !check_credentials_)
61 VSOMEIP_INFO << "Security configuration is active but in audit mode (allow all)";
62 }
63
64 bool
is_enabled() const65 security_impl::is_enabled() const {
66 return policy_enabled_;
67 }
68
69 bool
is_audit() const70 security_impl::is_audit() const {
71 return check_credentials_;
72 }
73
74 bool
check_credentials(client_t _client,uid_t _uid,gid_t _gid)75 security_impl::check_credentials(client_t _client,
76 uid_t _uid, gid_t _gid) {
77
78 if (!policy_enabled_) {
79 return true;
80 }
81
82 std::vector<std::shared_ptr<policy> > its_policies;
83 bool has_id(false);
84 {
85 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
86 its_policies = any_client_policies_;
87 }
88
89 for (const auto &p : its_policies) {
90 std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
91
92 bool has_uid, has_gid(false);
93
94 const auto found_uid = p->credentials_.find(_uid);
95 has_uid = (found_uid != p->credentials_.end());
96 if (has_uid) {
97 const auto found_gid = found_uid->second.find(_gid);
98 has_gid = (found_gid != found_uid->second.end());
99 }
100
101 has_id = (has_uid && has_gid);
102
103 if ((has_id && p->allow_who_) || (!has_id && !p->allow_who_)) {
104 if (!store_client_to_uid_gid_mapping(_client,_uid, _gid)) {
105 std::string security_mode_text = "!";
106 if (!check_credentials_) {
107 security_mode_text = " but will be allowed due to audit mode is active!";
108 }
109 VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
110 << " with UID/GID=" << std::dec << _uid << "/" << _gid
111 << " : Check credentials failed as existing credentials would be overwritten"
112 << security_mode_text;
113 return !check_credentials_;
114 }
115 store_uid_gid_to_client_mapping(_uid, _gid, _client);
116 return true;
117 }
118 }
119
120 std::string security_mode_text = " ~> Skip!";
121 if (!check_credentials_) {
122 security_mode_text = " but will be allowed due to audit mode is active!";
123 }
124 VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
125 << " with UID/GID=" << std::dec << _uid << "/" << _gid
126 << " : Check credentials failed" << security_mode_text;
127
128 return !check_credentials_;
129 }
130
131 bool
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) const132 security_impl::is_client_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
133 service_t _service, instance_t _instance, method_t _method,
134 bool _is_request_service) const {
135
136 if (!policy_enabled_) {
137 return true;
138 }
139
140 uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
141 std::vector<std::shared_ptr<policy> > its_policies;
142 {
143 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
144 its_policies = any_client_policies_;
145 }
146
147 if (_uid != ANY_UID && _gid != ANY_GID) {
148 its_uid = _uid;
149 its_gid = _gid;
150 } else {
151 std::string security_mode_text = " ~> Skip!";
152 if (!check_credentials_) {
153 security_mode_text = " but will be allowed due to audit mode is active!";
154 }
155 VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
156 << " for client 0x" << std::hex << _client << " is not valid"
157 << ". Therefore it isn't allowed to communicate to service/instance "
158 << _service << "/" << _instance
159 << security_mode_text;
160
161 return !check_credentials_;
162 }
163
164 for (const auto &p : its_policies) {
165 std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
166
167 bool has_uid, has_gid(false);
168 bool is_matching(false);
169
170 const auto found_uid = p->credentials_.find(_uid);
171 has_uid = (found_uid != p->credentials_.end());
172 if (has_uid) {
173 const auto found_gid = found_uid->second.find(_gid);
174 has_gid = (found_gid != found_uid->second.end());
175 }
176
177 const auto found_service = p->requests_.find(_service);
178 if (found_service != p->requests_.end()) {
179 const auto found_instance = found_service->second.find(_instance);
180 if (found_instance != found_service->second.end()) {
181 if (!_is_request_service) {
182 const auto found_method = found_instance->second.find(_method);
183 is_matching = (found_method != found_instance->second.end());
184 } else {
185 // handle VSOMEIP_REQUEST_SERVICE
186 is_matching = true;
187 }
188 }
189 }
190
191 if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
192 if (p->allow_what_) {
193 // allow policy
194 if (is_matching) {
195 return (true);
196 }
197 } else {
198 // deny policy
199 // allow client if the service / instance / !ANY_METHOD was not found
200 if ((!is_matching && (_method != ANY_METHOD))
201 // allow client if the service / instance / ANY_METHOD was not found
202 // and it is a "deny nothing" policy
203 || (!is_matching && (_method == ANY_METHOD) && p->requests_.empty())) {
204 return (true);
205 }
206 }
207 }
208 }
209
210 std::string security_mode_text = " ~> Skip!";
211 if (!check_credentials_) {
212 security_mode_text = " but will be allowed due to audit mode is active!";
213 }
214
215 VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
216 << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
217 << " : Isn't allowed to communicate with service/instance/(method / event) " << std::hex
218 << _service << "/" << _instance << "/" << _method
219 << security_mode_text;
220
221 return (!check_credentials_);
222 }
223
224 bool
is_offer_allowed(uint32_t _uid,uint32_t _gid,client_t _client,service_t _service,instance_t _instance) const225 security_impl::is_offer_allowed(uint32_t _uid, uint32_t _gid, client_t _client, service_t _service,
226 instance_t _instance) const {
227 if (!policy_enabled_) {
228 return true;
229 }
230
231 uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
232 std::vector<std::shared_ptr<policy> > its_policies;
233 {
234 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
235 its_policies = any_client_policies_;
236 }
237
238 if (_uid != ANY_UID
239 && _gid != ANY_GID) {
240 its_uid = _uid;
241 its_gid = _gid;
242 } else {
243 std::string security_mode_text = " ~> Skip offer!";
244 if (!check_credentials_) {
245 security_mode_text = " but will be allowed due to audit mode is active!";
246 }
247 VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
248 << " for client 0x" << std::hex << _client << " is not valid"
249 << ". Therefore it isn't allowed to offer service/instance "
250 << _service << "/" << _instance
251 << security_mode_text;
252
253 return !check_credentials_;
254 }
255
256 for (const auto &p : its_policies) {
257 std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
258 bool has_uid, has_gid(false), has_offer(false);
259
260 const auto found_uid = p->credentials_.find(_uid);
261 has_uid = (found_uid != p->credentials_.end());
262 if (has_uid) {
263 const auto found_gid = found_uid->second.find(_gid);
264 has_gid = (found_gid != found_uid->second.end());
265 }
266
267 const auto found_service = p->offers_.find(_service);
268 if (found_service != p->offers_.end()) {
269 const auto found_instance = found_service->second.find(_instance);
270 has_offer = (found_instance != found_service->second.end());
271 }
272
273 if ((has_uid && has_gid && p->allow_who_)
274 || ((!has_uid || !has_gid) && !p->allow_who_)) {
275 if (p->allow_what_ == has_offer) {
276 return (true);
277 }
278 }
279 }
280
281 std::string security_mode_text = " ~> Skip offer!";
282 if (!check_credentials_) {
283 security_mode_text = " but will be allowed due to audit mode is active!";
284 }
285
286 VSOMEIP_INFO << "vSomeIP Security: Client 0x"
287 << std::hex << _client
288 << " with UID/GID="
289 << std::dec << its_uid << "/" << its_gid
290 << " isn't allowed to offer service/instance "
291 << std::hex << _service << "/" << _instance
292 << security_mode_text;
293
294 return (!check_credentials_);
295 }
296
297 bool
store_client_to_uid_gid_mapping(client_t _client,uint32_t _uid,uint32_t _gid)298 security_impl::store_client_to_uid_gid_mapping(
299 client_t _client, uint32_t _uid, uint32_t _gid) {
300 {
301 // store the client -> (uid, gid) mapping
302 std::lock_guard<std::mutex> its_lock(ids_mutex_);
303 auto found_client = ids_.find(_client);
304 if (found_client != ids_.end()) {
305 if (found_client->second != std::make_pair(_uid, _gid)) {
306 VSOMEIP_WARNING << "vSomeIP Security: Client 0x"
307 << std::hex << _client << " with UID/GID="
308 << std::dec << _uid << "/" << _gid << " : Overwriting existing credentials UID/GID="
309 << std::dec << std::get<0>(found_client->second) << "/"
310 << std::get<1>(found_client->second);
311 found_client->second = std::make_pair(_uid, _gid);
312 return true;
313 }
314 } else {
315 ids_[_client] = std::make_pair(_uid, _gid);
316 }
317 return true;
318 }
319 }
320
321 bool
get_client_to_uid_gid_mapping(client_t _client,std::pair<uint32_t,uint32_t> & _uid_gid)322 security_impl::get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid) {
323 {
324 // get the UID / GID of the client
325 std::lock_guard<std::mutex> its_lock(ids_mutex_);
326 if (ids_.find(_client) != ids_.end()) {
327 _uid_gid = ids_[_client];
328 return true;
329 }
330 return false;
331 }
332 }
333
334 bool
remove_client_to_uid_gid_mapping(client_t _client)335 security_impl::remove_client_to_uid_gid_mapping(client_t _client) {
336 std::pair<uint32_t, uint32_t> its_uid_gid;
337 bool client_removed(false);
338 bool uid_gid_removed(false);
339 {
340 std::lock_guard<std::mutex> its_lock(ids_mutex_);
341 auto found_client = ids_.find(_client);
342 if (found_client != ids_.end()) {
343 its_uid_gid = found_client->second;
344 ids_.erase(found_client);
345 client_removed = true;
346 }
347 }
348 {
349 std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
350 if (client_removed) {
351 auto found_uid_gid = uid_to_clients_.find(its_uid_gid);
352 if (found_uid_gid != uid_to_clients_.end()) {
353 auto its_client = found_uid_gid->second.find(_client);
354 if (its_client != found_uid_gid->second.end()) {
355 found_uid_gid->second.erase(its_client);
356 if (found_uid_gid->second.empty()) {
357 uid_to_clients_.erase(found_uid_gid);
358 }
359 uid_gid_removed = true;
360 }
361 }
362 } else {
363 for (auto its_uid_gid = uid_to_clients_.begin();
364 its_uid_gid != uid_to_clients_.end(); ++its_uid_gid) {
365 auto its_client = its_uid_gid->second.find(_client);
366 if (its_client != its_uid_gid->second.end()) {
367 its_uid_gid->second.erase(its_client);
368 if (its_uid_gid->second.empty()) {
369 uid_to_clients_.erase(its_uid_gid);
370 }
371 uid_gid_removed = true;
372 break;
373 }
374 }
375 }
376 }
377 return (client_removed && uid_gid_removed);
378 }
379
380 void
store_uid_gid_to_client_mapping(uint32_t _uid,uint32_t _gid,client_t _client)381 security_impl::store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
382 client_t _client) {
383 {
384 // store the uid gid to clients mapping
385 std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
386 std::set<client_t> mapped_clients;
387 if (uid_to_clients_.find(std::make_pair(_uid, _gid)) != uid_to_clients_.end()) {
388 mapped_clients = uid_to_clients_[std::make_pair(_uid, _gid)];
389 mapped_clients.insert(_client);
390 uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
391 } else {
392 mapped_clients.insert(_client);
393 uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
394 }
395 }
396 }
397
398 bool
get_uid_gid_to_client_mapping(std::pair<uint32_t,uint32_t> _uid_gid,std::set<client_t> & _clients)399 security_impl::get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
400 std::set<client_t> &_clients) {
401 {
402 // get the clients corresponding to uid, gid
403 std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
404 if (uid_to_clients_.find(_uid_gid) != uid_to_clients_.end()) {
405 _clients = uid_to_clients_[_uid_gid];
406 return true;
407 }
408 return false;
409 }
410 }
411
412 bool
remove_security_policy(uint32_t _uid,uint32_t _gid)413 security_impl::remove_security_policy(uint32_t _uid, uint32_t _gid) {
414 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
415 bool was_removed(false);
416 if (!any_client_policies_.empty()) {
417 std::vector<std::shared_ptr<policy>>::iterator p_it = any_client_policies_.begin();
418 while (p_it != any_client_policies_.end()) {
419 bool is_matching(false);
420 {
421 std::lock_guard<std::mutex> its_policy_lock((*p_it)->mutex_);
422 bool has_uid(false), has_gid(false);
423 const auto found_uid = (*p_it)->credentials_.find(_uid);
424 has_uid = (found_uid != (*p_it)->credentials_.end());
425 if (has_uid) {
426 const auto found_gid = found_uid->second.find(_gid);
427 has_gid = (found_gid != found_uid->second.end());
428 }
429
430 // only remove "credentials allow" policies to prevent removal of
431 // blacklist configured in file
432 if (has_uid && has_gid && (*p_it)->allow_who_) {
433 is_matching = true;
434 }
435 }
436 if (is_matching) {
437 was_removed = true;
438 p_it = any_client_policies_.erase(p_it);
439 } else {
440 ++p_it;
441 }
442 }
443 }
444 return (was_removed);
445 }
446
447 void
update_security_policy(uint32_t _uid,uint32_t _gid,const std::shared_ptr<policy> & _policy)448 security_impl::update_security_policy(uint32_t _uid, uint32_t _gid,
449 const std::shared_ptr<policy> &_policy) {
450
451 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
452 std::shared_ptr<policy> its_matching_policy;
453 for (auto p : any_client_policies_) {
454 if (p->credentials_.size() == 1) {
455 const auto its_uids = *(p->credentials_.begin());
456 if (its_uids.first.lower() == _uid
457 && its_uids.first.upper() == _uid) {
458 if (its_uids.second.size() == 1) {
459 const auto its_gids = *(its_uids.second.begin());
460 if (its_gids.lower() == _gid
461 && its_gids.upper() == _gid) {
462 if (p->allow_who_ == _policy->allow_who_) {
463 its_matching_policy = p;
464 break;
465 }
466 }
467 }
468 }
469 }
470 }
471
472 if (its_matching_policy) {
473 for (const auto &r : _policy->requests_) {
474 service_t its_lower, its_upper;
475 get_bounds(r.first, its_lower, its_upper);
476 for (auto s = its_lower; s <= its_upper; s++) {
477 boost::icl::discrete_interval<service_t> its_service(s, s,
478 boost::icl::interval_bounds::closed());
479 its_matching_policy->requests_ += std::make_pair(its_service, r.second);
480 }
481 }
482 for (const auto &o : _policy->offers_) {
483 service_t its_lower, its_upper;
484 get_bounds(o.first, its_lower, its_upper);
485 for (auto s = its_lower; s <= its_upper; s++) {
486 boost::icl::discrete_interval<service_t> its_service(s, s,
487 boost::icl::interval_bounds::closed());
488 its_matching_policy->offers_ += std::make_pair(its_service, o.second);
489 }
490 }
491 } else {
492 any_client_policies_.push_back(_policy);
493 }
494 }
495
496 void
add_security_credentials(uint32_t _uid,uint32_t _gid,const std::shared_ptr<policy> & _policy,client_t _client)497 security_impl::add_security_credentials(uint32_t _uid, uint32_t _gid,
498 const std::shared_ptr<policy> &_policy, client_t _client) {
499
500 bool was_found(false);
501 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
502 for (const auto &p : any_client_policies_) {
503 bool has_uid(false), has_gid(false);
504
505 std::lock_guard<std::mutex> its_policy_lock(p->mutex_);
506 const auto found_uid = p->credentials_.find(_uid);
507 has_uid = (found_uid != p->credentials_.end());
508 if (has_uid) {
509 const auto found_gid = found_uid->second.find(_gid);
510 has_gid = (found_gid != found_uid->second.end());
511 }
512
513 if (has_uid && has_gid && p->allow_who_) {
514 was_found = true;
515 break;
516 }
517 }
518
519 // Do not add the new (credentials-only-policy) if a allow
520 // credentials policy with same credentials was found
521 if (!was_found) {
522 any_client_policies_.push_back(_policy);
523 VSOMEIP_INFO << __func__ << " Added security credentials at client: 0x"
524 << std::hex << _client << std::dec << " with UID: " << _uid << " GID: " << _gid;
525 }
526 }
527
528 bool
is_remote_client_allowed() const529 security_impl::is_remote_client_allowed() const {
530 if (!check_credentials_) {
531 return true;
532 }
533 return allow_remote_clients_;
534 }
535
536 bool
is_policy_update_allowed(uint32_t _uid,std::shared_ptr<policy> & _policy) const537 security_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
538
539 bool is_uid_allowed(false);
540 {
541 std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
542 const auto found_uid = uid_whitelist_.find(_uid);
543 is_uid_allowed = (found_uid != uid_whitelist_.end());
544 }
545
546 if (is_uid_allowed) {
547 std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
548 std::lock_guard<std::mutex> its_policy_lock(_policy->mutex_);
549 for (auto its_request : _policy->requests_) {
550 bool has_service(false);
551
552 service_t its_service(0);
553 for (its_service = its_request.first.lower();
554 its_service <= its_request.first.upper();
555 its_service++) {
556
557 const auto found_service = service_interface_whitelist_.find(its_service);
558 has_service = (found_service != service_interface_whitelist_.end());
559 if (!has_service)
560 break;
561 }
562
563 if (!has_service) {
564 if (!check_whitelist_) {
565 VSOMEIP_INFO << "vSomeIP Security: Policy update requesting service ID: "
566 << std::hex << its_service
567 << " is not allowed, but will be allowed due to whitelist audit mode is active!";
568 } else {
569 VSOMEIP_WARNING << "vSomeIP Security: Policy update requesting service ID: "
570 << std::hex << its_service
571 << " is not allowed! -> ignore update";
572 }
573 return (!check_whitelist_);
574 }
575 }
576 return (true);
577 } else {
578 if (!check_whitelist_) {
579 VSOMEIP_INFO << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
580 << " is not allowed, but will be allowed due to whitelist audit mode is active!";
581 } else {
582 VSOMEIP_WARNING << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
583 << " is not allowed! -> ignore update";
584 }
585 return (!check_whitelist_);
586 }
587 }
588
589 bool
is_policy_removal_allowed(uint32_t _uid) const590 security_impl::is_policy_removal_allowed(uint32_t _uid) const {
591 std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
592 for (auto its_uid_range : uid_whitelist_) {
593 if (its_uid_range.lower() <= _uid && _uid <= its_uid_range.upper()) {
594 return (true);
595 }
596 }
597
598 if (!check_whitelist_) {
599 VSOMEIP_INFO << "vSomeIP Security: Policy removal for UID: "
600 << std::dec << _uid
601 << " is not allowed, but will be allowed due to whitelist audit mode is active!";
602 } else {
603 VSOMEIP_WARNING << "vSomeIP Security: Policy removal for UID: "
604 << std::dec << _uid
605 << " is not allowed! -> ignore removal";
606 }
607 return (!check_whitelist_);
608 }
609
610 bool
check_routing_credentials(client_t _client,uint32_t _uid,uint32_t _gid) const611 security_impl::check_routing_credentials(client_t _client,
612 uint32_t _uid, uint32_t _gid) const {
613
614 std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
615 if (routing_credentials_.first == _uid
616 && routing_credentials_.second == _gid) {
617
618 return (true);
619 }
620
621 std::string security_mode_text = "!";
622 if (!check_routing_credentials_) {
623
624 security_mode_text = " but will be allowed due to audit mode is active!";
625 }
626
627 VSOMEIP_INFO << "vSomeIP Security: Client 0x"
628 << std::hex << _client << " and UID/GID="
629 << std::dec << _uid << "/" << _gid
630 << " : Check routing credentials failed as "
631 << "configured routing manager credentials "
632 << "do not match with routing manager credentials"
633 << security_mode_text;
634
635 return (!check_routing_credentials_);
636 }
637
638 bool
parse_policy(const byte_t * & _buffer,uint32_t & _buffer_size,uint32_t & _uid,uint32_t & _gid,const std::shared_ptr<policy> & _policy) const639 security_impl::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
640 uint32_t &_uid, uint32_t &_gid, const std::shared_ptr<policy> &_policy) const {
641
642 bool is_valid = _policy->deserialize(_buffer, _buffer_size);
643 if (is_valid)
644 is_valid = _policy->get_uid_gid(_uid, _gid);
645 return is_valid;
646 }
647
648 ///////////////////////////////////////////////////////////////////////////////
649 // Configuration
650 ///////////////////////////////////////////////////////////////////////////////
651 void
load_policies(const configuration_element & _element)652 security_impl::load_policies(const configuration_element &_element) {
653 #ifdef _WIN32
654 return;
655 #endif
656 try {
657 auto optional = _element.tree_.get_child_optional("security");
658 if (!optional) {
659 return;
660 }
661 policy_enabled_ = true;
662 auto found_policy = _element.tree_.get_child("security");
663 for (auto its_security = found_policy.begin();
664 its_security != found_policy.end(); ++its_security) {
665 if (its_security->first == "check_credentials") {
666 if (its_security->second.data() == "true") {
667 check_credentials_ = true;
668 } else {
669 check_credentials_ = false;
670 }
671 } else if (its_security->first == "allow_remote_clients") {
672 if (its_security->second.data() == "true") {
673 allow_remote_clients_ = true;
674 } else {
675 allow_remote_clients_ = false;
676 }
677 } else if (its_security->first == "policies") {
678 for (auto its_policy = its_security->second.begin();
679 its_policy != its_security->second.end(); ++its_policy) {
680 load_policy(its_policy->second);
681 }
682 }
683 }
684 } catch (...) {
685 }
686 }
687
688 void
load_policy(const boost::property_tree::ptree & _tree)689 security_impl::load_policy(const boost::property_tree::ptree &_tree) {
690
691 std::shared_ptr<policy> policy(std::make_shared<policy>());
692 bool allow_deny_set(false);
693 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
694 if (i->first == "credentials") {
695 boost::icl::interval_set<uid_t> its_uid_interval_set;
696 boost::icl::interval_set<gid_t> its_gid_interval_set;
697 boost::icl::discrete_interval<uid_t> its_uid_interval;
698 boost::icl::discrete_interval<gid_t> its_gid_interval;
699
700 bool has_uid(false), has_gid(false);
701 bool has_uid_range(false), has_gid_range(false);
702 for (auto n = i->second.begin();
703 n != i->second.end(); ++n) {
704 std::string its_key(n->first);
705 std::string its_value(n->second.data());
706 if (its_key == "uid") {
707 if(n->second.data().empty()) {
708 load_interval_set(n->second, its_uid_interval_set);
709 has_uid_range = true;
710 } else {
711 if (its_value != "any") {
712 uint32_t its_uid;
713 read_data(its_value, its_uid);
714 its_uid_interval = boost::icl::construct<
715 boost::icl::discrete_interval<uid_t> >(
716 its_uid, its_uid,
717 boost::icl::interval_bounds::closed());
718 } else {
719 its_uid_interval = boost::icl::construct<
720 boost::icl::discrete_interval<uid_t> >(
721 std::numeric_limits<uid_t>::min(),
722 std::numeric_limits<uid_t>::max(),
723 boost::icl::interval_bounds::closed());
724 }
725 has_uid = true;
726 }
727 } else if (its_key == "gid") {
728 if(n->second.data().empty()) {
729 load_interval_set(n->second, its_gid_interval_set);
730 has_gid_range = true;
731 } else {
732 if (its_value != "any") {
733 uint32_t its_gid;
734 read_data(its_value, its_gid);
735 its_gid_interval = boost::icl::construct<
736 boost::icl::discrete_interval<gid_t> >(
737 its_gid, its_gid,
738 boost::icl::interval_bounds::closed());
739 } else {
740 its_gid_interval = boost::icl::construct<
741 boost::icl::discrete_interval<gid_t> >(
742 std::numeric_limits<gid_t>::min(),
743 std::numeric_limits<gid_t>::max(),
744 boost::icl::interval_bounds::closed());
745 }
746 has_gid = true;
747 }
748 } else if (its_key == "allow" || its_key == "deny") {
749 policy->allow_who_ = (its_key == "allow");
750 load_credential(n->second, policy->credentials_);
751 }
752 }
753
754 if (has_uid && has_gid) {
755 its_gid_interval_set.insert(its_gid_interval);
756
757 policy->credentials_ += std::make_pair(its_uid_interval, its_gid_interval_set);
758 policy->allow_who_ = true;
759 }
760 if (has_uid_range && has_gid_range) {
761 for (const auto& u : its_uid_interval_set)
762 policy->credentials_ += std::make_pair(u, its_gid_interval_set);
763 policy->allow_who_ = true;
764 }
765 } else if (i->first == "allow") {
766 if (allow_deny_set) {
767 VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"allow\" tag overrides "
768 << "already set \"deny\" tag. "
769 << "Either \"deny\" or \"allow\" is allowed.";
770 }
771 allow_deny_set = true;
772 policy->allow_what_ = true;
773 load_policy_body(policy, i);
774 } else if (i->first == "deny") {
775 if (allow_deny_set) {
776 VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"deny\" tag overrides "
777 << "already set \"allow\" tag. "
778 << "Either \"deny\" or \"allow\" is allowed.";
779 }
780 allow_deny_set = true;
781 policy->allow_what_ = false;
782 load_policy_body(policy, i);
783 }
784 }
785 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
786 any_client_policies_.push_back(policy);
787 }
788
789 void
load_policy_body(std::shared_ptr<policy> & _policy,const boost::property_tree::ptree::const_iterator & _tree)790 security_impl::load_policy_body(std::shared_ptr<policy> &_policy,
791 const boost::property_tree::ptree::const_iterator &_tree) {
792
793 for (auto l = _tree->second.begin(); l != _tree->second.end(); ++l) {
794 if (l->first == "requests") {
795 for (auto n = l->second.begin(); n != l->second.end(); ++n) {
796 service_t its_service = 0x0;
797 instance_t its_instance = 0x0;
798 boost::icl::interval_map<instance_t,
799 boost::icl::interval_set<method_t> > its_instance_method_intervals;
800 for (auto k = n->second.begin(); k != n->second.end(); ++k) {
801 if (k->first == "service") {
802 read_data(k->second.data(), its_service);
803 } else if (k->first == "instance") { // legacy definition for instances
804 boost::icl::interval_set<instance_t> its_instance_interval_set;
805 boost::icl::interval_set<method_t> its_method_interval_set;
806 boost::icl::discrete_interval<instance_t> all_instances(0x01, 0xFFFF,
807 boost::icl::interval_bounds::closed());
808 boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
809 boost::icl::interval_bounds::closed());
810
811 std::string its_value(k->second.data());
812 if (its_value != "any") {
813 read_data(its_value, its_instance);
814 if (its_instance != 0x0) {
815 its_instance_interval_set.insert(its_instance);
816 its_method_interval_set.insert(all_methods);
817 }
818 } else {
819 its_instance_interval_set.insert(all_instances);
820 its_method_interval_set.insert(all_methods);
821 }
822 for (const auto& i : its_instance_interval_set) {
823 its_instance_method_intervals
824 += std::make_pair(i, its_method_interval_set);
825 }
826 } else if (k->first == "instances") { // new instances definition
827 for (auto p = k->second.begin(); p != k->second.end(); ++p) {
828 boost::icl::interval_set<instance_t> its_instance_interval_set;
829 boost::icl::interval_set<method_t> its_method_interval_set;
830 boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
831 boost::icl::interval_bounds::closed());
832 for (auto m = p->second.begin(); m != p->second.end(); ++m) {
833 if (m->first == "ids") {
834 load_interval_set(m->second, its_instance_interval_set);
835 } else if (m->first == "methods") {
836 load_interval_set(m->second, its_method_interval_set);
837 }
838 }
839 if (its_method_interval_set.empty())
840 its_method_interval_set.insert(all_methods);
841 for (const auto& i : its_instance_interval_set) {
842 its_instance_method_intervals
843 += std::make_pair(i, its_method_interval_set);
844 }
845 }
846
847 if (its_instance_method_intervals.empty()) {
848 boost::icl::interval_set<instance_t> its_legacy_instance_interval_set;
849 boost::icl::interval_set<method_t> its_legacy_method_interval_set;
850 boost::icl::discrete_interval<method_t> all_methods(0x01, 0xFFFF,
851 boost::icl::interval_bounds::closed());
852 its_legacy_method_interval_set.insert(all_methods);
853
854 // try to only load instance ranges with any method to be allowed
855 load_interval_set(k->second, its_legacy_instance_interval_set);
856 for (const auto& i : its_legacy_instance_interval_set) {
857 its_instance_method_intervals
858 += std::make_pair(i, its_legacy_method_interval_set);
859 }
860 }
861 }
862 }
863 if (its_service != 0x0 && !its_instance_method_intervals.empty()) {
864 _policy->requests_ += std::make_pair(
865 boost::icl::discrete_interval<service_t>(
866 its_service, its_service,
867 boost::icl::interval_bounds::closed()),
868 its_instance_method_intervals);
869 }
870 }
871 } else if (l->first == "offers") {
872 for (auto n = l->second.begin(); n != l->second.end(); ++n) {
873 service_t its_service(0x0);
874 instance_t its_instance(0x0);
875 boost::icl::interval_set<instance_t> its_instance_interval_set;
876 for (auto k = n->second.begin(); k != n->second.end(); ++k) {
877 if (k->first == "service") {
878 read_data(k->second.data(), its_service);
879 } else if (k->first == "instance") { // legacy definition for instances
880 std::string its_value(k->second.data());
881 if (its_value != "any") {
882 read_data(its_value, its_instance);
883 if (its_instance != 0x0) {
884 its_instance_interval_set.insert(its_instance);
885 }
886 } else {
887 its_instance_interval_set.insert(
888 boost::icl::discrete_interval<instance_t>(
889 0x0001, 0xFFFF));
890 }
891 } else if (k->first == "instances") { // new instances definition
892 load_interval_set(k->second, its_instance_interval_set);
893 }
894 }
895 if (its_service != 0x0 && !its_instance_interval_set.empty()) {
896 _policy->offers_
897 += std::make_pair(
898 boost::icl::discrete_interval<service_t>(
899 its_service, its_service,
900 boost::icl::interval_bounds::closed()),
901 its_instance_interval_set);
902 }
903 }
904 }
905 }
906 }
907
908
909 void
load_credential(const boost::property_tree::ptree & _tree,boost::icl::interval_map<uid_t,boost::icl::interval_set<gid_t>> & _credentials)910 security_impl::load_credential(
911 const boost::property_tree::ptree &_tree,
912 boost::icl::interval_map<uid_t,
913 boost::icl::interval_set<gid_t> > &_credentials) {
914
915 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
916 boost::icl::interval_set<uid_t> its_uid_interval_set;
917 boost::icl::interval_set<gid_t> its_gid_interval_set;
918
919 for (auto j = i->second.begin(); j != i->second.end(); ++j) {
920 std::string its_key(j->first);
921 if (its_key == "uid") {
922 load_interval_set(j->second, its_uid_interval_set);
923 } else if (its_key == "gid") {
924 load_interval_set(j->second, its_gid_interval_set);
925 } else {
926 VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
927 << "Malformed credential (contains illegal key \""
928 << its_key << "\")";
929 }
930 }
931
932 for (const auto& its_uid_interval : its_uid_interval_set) {
933 _credentials
934 += std::make_pair(its_uid_interval, its_gid_interval_set);
935 }
936 }
937 }
938
939 bool
load_routing_credentials(const configuration_element & _element)940 security_impl::load_routing_credentials(const configuration_element &_element) {
941 try {
942 auto its_routing_cred = _element.tree_.get_child("routing-credentials");
943 if (is_configured_) {
944 VSOMEIP_WARNING << "vSomeIP Security: Multiple definitions of routing-credentials."
945 << " Ignoring definition from " << _element.name_;
946 } else {
947 for (auto i = its_routing_cred.begin();
948 i != its_routing_cred.end();
949 ++i) {
950 std::string its_key(i->first);
951 std::string its_value(i->second.data());
952 if (its_key == "uid") {
953 uint32_t its_uid(0);
954 read_data(its_value, its_uid);
955 std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
956 std::get<0>(routing_credentials_) = its_uid;
957 } else if (its_key == "gid") {
958 uint32_t its_gid(0);
959 read_data(its_value, its_gid);
960 std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
961 std::get<1>(routing_credentials_) = its_gid;
962 }
963 }
964 check_routing_credentials_ = true;
965 is_configured_ = true;
966 }
967 } catch (...) {
968 return false;
969 }
970 return true;
971 }
972
973
974 void
load_security_update_whitelist(const configuration_element & _element)975 security_impl::load_security_update_whitelist(const configuration_element &_element) {
976 #ifdef _WIN32
977 return;
978 #endif
979 try {
980 auto optional = _element.tree_.get_child_optional("security-update-whitelist");
981 if (!optional) {
982 return;
983 }
984 auto found_whitelist = _element.tree_.get_child("security-update-whitelist");
985 for (auto its_whitelist = found_whitelist.begin();
986 its_whitelist != found_whitelist.end(); ++its_whitelist) {
987
988 if (its_whitelist->first == "uids") {
989 {
990 std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
991 load_interval_set(its_whitelist->second, uid_whitelist_);
992 }
993 } else if (its_whitelist->first == "services") {
994 {
995 std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
996 load_interval_set(its_whitelist->second, service_interface_whitelist_);
997 }
998 } else if (its_whitelist->first == "check-whitelist") {
999 if (its_whitelist->second.data() == "true") {
1000 check_whitelist_ = true;
1001 } else {
1002 check_whitelist_ = false;
1003 }
1004 }
1005 }
1006 } catch (...) {
1007 }
1008 }
1009
1010 template<typename T_>
load_interval_set(const boost::property_tree::ptree & _tree,boost::icl::interval_set<T_> & _intervals,bool _exclude_margins)1011 void security_impl::load_interval_set(
1012 const boost::property_tree::ptree &_tree,
1013 boost::icl::interval_set<T_> &_intervals, bool _exclude_margins) {
1014
1015 boost::icl::interval_set<T_> its_intervals;
1016 T_ its_min = std::numeric_limits<T_>::min();
1017 T_ its_max = std::numeric_limits<T_>::max();
1018
1019 if (_exclude_margins) {
1020 its_min++;
1021 its_max--;
1022 }
1023
1024 const std::string its_key(_tree.data());
1025 if (its_key == "any") {
1026 its_intervals.insert(boost::icl::discrete_interval<T_>::closed(
1027 its_min, its_max));
1028 } else {
1029 for (auto i = _tree.begin(); i != _tree.end(); ++i) {
1030 auto its_data = i->second;
1031 if (!its_data.data().empty()) {
1032 T_ its_id;
1033 read_data(its_data.data(), its_id);
1034 if (its_id >= its_min && its_id <= its_max)
1035 its_intervals.insert(its_id);
1036 } else {
1037 T_ its_first, its_last;
1038 bool has_first(false), has_last(false);
1039 for (auto j = its_data.begin(); j != its_data.end(); ++j) {
1040 std::string its_key(j->first);
1041 std::string its_value(j->second.data());
1042 if (its_key == "first") {
1043 if (its_value == "min") {
1044 its_first = its_min;
1045 } else {
1046 read_data(its_value, its_first);
1047 }
1048 has_first = true;
1049 } else if (its_key == "last") {
1050 if (its_value == "max") {
1051 its_last = its_max;
1052 } else {
1053 read_data(its_value, its_last);
1054 }
1055 has_last = true;
1056 } else {
1057 VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
1058 << " Malformed range. Contains illegal key ("
1059 << its_key << ")";
1060 }
1061 }
1062 if (has_first && has_last && its_first <= its_last) {
1063 its_intervals.insert(
1064 boost::icl::discrete_interval<T_>::closed(its_first, its_last));
1065 }
1066 }
1067 }
1068 }
1069
1070 _intervals = its_intervals;
1071 }
1072
1073 void
get_requester_policies(const std::shared_ptr<policy> _policy,std::set<std::shared_ptr<policy>> & _requesters) const1074 security_impl::get_requester_policies(const std::shared_ptr<policy> _policy,
1075 std::set<std::shared_ptr<policy> > &_requesters) const {
1076
1077 std::vector<std::shared_ptr<policy> > its_policies;
1078 {
1079 std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
1080 its_policies = any_client_policies_;
1081 }
1082
1083 std::lock_guard<std::mutex> its_lock(_policy->mutex_);
1084 for (const auto &o : _policy->offers_) {
1085 for (const auto &p : its_policies) {
1086 if (p == _policy)
1087 continue;
1088
1089 std::lock_guard<std::mutex> its_lock(p->mutex_);
1090
1091 auto its_policy = std::make_shared<policy>();
1092 its_policy->credentials_ = p->credentials_;
1093
1094 for (const auto &r : p->requests_) {
1095 // o represents an offer by a service interval and its instances
1096 // (a set of intervals)
1097 // r represents a request by a service interval and its instances
1098 // and methods (instance intervals mapped to interval sets of methods)
1099 //
1100 // Thus, r matches o if their service identifiers as well as their
1101 // instances overlap. If r and o match, a new policy must be
1102 // created that contains the overlapping services/instances mapping
1103 // of r and o together with the methods from r
1104 service_t its_o_lower, its_o_upper, its_r_lower, its_r_upper;
1105 get_bounds(o.first, its_o_lower, its_o_upper);
1106 get_bounds(r.first, its_r_lower, its_r_upper);
1107
1108 if (its_o_lower <= its_r_upper && its_r_lower <= its_o_upper) {
1109 auto its_service_min = std::max(its_o_lower, its_r_lower);
1110 auto its_service_max = std::min(its_r_upper, its_o_upper);
1111
1112 for (const auto &i : o.second) {
1113 for (const auto &j : r.second) {
1114 for (const auto& k : j.second) {
1115 instance_t its_i_lower, its_i_upper, its_k_lower, its_k_upper;
1116 get_bounds(i, its_i_lower, its_i_upper);
1117 get_bounds(k, its_k_lower, its_k_upper);
1118
1119 if (its_i_lower <= its_k_upper && its_k_lower <= its_i_upper) {
1120 auto its_instance_min = std::max(its_i_lower, its_k_lower);
1121 auto its_instance_max = std::min(its_i_upper, its_k_upper);
1122
1123 boost::icl::interval_map<instance_t,
1124 boost::icl::interval_set<method_t> > its_instances_methods;
1125 its_instances_methods += std::make_pair(
1126 boost::icl::interval<instance_t>::closed(
1127 its_instance_min, its_instance_max),
1128 j.second);
1129
1130 its_policy->requests_ += std::make_pair(
1131 boost::icl::interval<instance_t>::closed(
1132 its_service_min, its_service_max),
1133 its_instances_methods);
1134 }
1135 }
1136 }
1137 }
1138 }
1139 }
1140
1141 if (!its_policy->requests_.empty()) {
1142 _requesters.insert(its_policy);
1143 its_policy->print();
1144 }
1145 }
1146 }
1147 }
1148
1149 void
get_clients(uid_t _uid,gid_t _gid,std::unordered_set<client_t> & _clients) const1150 security_impl::get_clients(uid_t _uid, gid_t _gid,
1151 std::unordered_set<client_t> &_clients) const {
1152
1153 std::lock_guard<std::mutex> its_lock(ids_mutex_);
1154 for (const auto &i : ids_) {
1155 if (i.second.first == _uid && i.second.second == _gid)
1156 _clients.insert(i.first);
1157 }
1158 }
1159
1160 ////////////////////////////////////////////////////////////////////////////////
1161 // Manage the security object
1162 ////////////////////////////////////////////////////////////////////////////////
1163 static std::shared_ptr<security_impl> *the_security_ptr__(nullptr);
1164 static std::mutex the_security_mutex__;
1165
1166 std::shared_ptr<security_impl>
get()1167 security_impl::get() {
1168 #ifndef _WIN32
1169 std::lock_guard<std::mutex> its_lock(the_security_mutex__);
1170 #endif
1171 if(the_security_ptr__ == nullptr) {
1172 the_security_ptr__ = new std::shared_ptr<security_impl>();
1173 }
1174 if (the_security_ptr__ != nullptr) {
1175 if (!(*the_security_ptr__)) {
1176 *the_security_ptr__ = std::make_shared<security_impl>();
1177 }
1178 return (*the_security_ptr__);
1179 }
1180 return (nullptr);
1181 }
1182
1183 #ifndef _WIN32
1184 static void security_teardown(void) __attribute__((destructor));
security_teardown(void)1185 static void security_teardown(void)
1186 {
1187 if (the_security_ptr__ != nullptr) {
1188 std::lock_guard<std::mutex> its_lock(the_security_mutex__);
1189 the_security_ptr__->reset();
1190 delete the_security_ptr__;
1191 the_security_ptr__ = nullptr;
1192 }
1193 }
1194 #endif
1195
1196 } // namespace vsomeip_v3
1197