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