1 // Copyright (C) 2020 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 <iomanip>
7
8 #include <vsomeip/internal/logger.hpp>
9
10 #include "../include/policy.hpp"
11 #include "../../utility/include/byteorder.hpp"
12
13 namespace vsomeip_v3 {
14
15 bool
get_uid_gid(uid_t & _uid,gid_t & _gid) const16 policy::get_uid_gid(uid_t &_uid, gid_t &_gid) const {
17
18 if (credentials_.size() != 1)
19 return (false);
20
21 const auto its_uids = credentials_.begin()->first;
22 const auto its_gids = credentials_.begin()->second;
23
24 if (its_gids.size() != 1)
25 return (false);
26
27 if (its_uids.lower() != its_uids.upper()
28 || its_gids.begin()->lower() != its_gids.begin()->upper())
29 return (false);
30
31 _uid = its_uids.lower();
32 _gid = its_gids.begin()->lower();
33
34 return (true);
35 }
36
37 bool
deserialize_uid_gid(const byte_t * & _data,uint32_t & _size,uid_t & _uid,gid_t & _gid) const38 policy::deserialize_uid_gid(const byte_t * &_data, uint32_t &_size,
39 uid_t &_uid, gid_t &_gid) const {
40
41 bool its_result;
42
43 its_result = deserialize_u32(_data, _size, _uid);
44 if (its_result == false)
45 return (false);
46
47 its_result = deserialize_u32(_data, _size, _gid);
48 if (its_result == false)
49 return (false);
50
51 return (true);
52 }
53
54 bool
deserialize(const byte_t * & _data,uint32_t & _size)55 policy::deserialize(const byte_t * &_data, uint32_t &_size) {
56
57 bool its_result;
58 uid_t its_uid;
59 gid_t its_gid;
60
61 std::lock_guard<std::mutex> its_lock(mutex_);
62
63 its_result = deserialize_uid_gid(_data, _size, its_uid, its_gid);
64 if (its_result == false)
65 return (false);
66
67 // Fill policy uid/gid
68 const auto its_uid_interval
69 = boost::icl::interval<uid_t>::closed(its_uid, its_uid);
70 boost::icl::interval_set<gid_t> its_gid_set;
71 its_gid_set.insert(its_gid);
72 credentials_ += std::make_pair(its_uid_interval, its_gid_set);
73
74 // Deserialized policies are always "Allow" - policies
75 allow_who_ = true;
76 allow_what_ = true;
77
78 // Deserialize requests array length
79 uint32_t its_requests_length;
80 its_result = deserialize_u32(_data, _size, its_requests_length);
81 if (its_result == false)
82 return (false);
83
84 // Deserialize requests
85 while (0 < its_requests_length) {
86
87 uint32_t its_current_size(_size);
88
89 uint16_t its_service;
90 its_result = deserialize_u16(_data, _size, its_service);
91 if (its_result == false)
92 return (false);
93
94 if (its_service == 0x0000 || its_service == 0xffff) {
95 VSOMEIP_WARNING << "vSomeIP Security: Policy with service ID: 0x"
96 << std::hex << its_service << " is not allowed!";
97 return (false);
98 }
99
100 const auto its_service_interval
101 = boost::icl::interval<service_t>::closed(its_service, its_service);
102
103 boost::icl::interval_map<instance_t,
104 boost::icl::interval_set<method_t> > its_ids;
105 its_result = deserialize_ids(_data, _size, its_ids);
106 if (its_result == false)
107 return (false);
108
109 requests_ += std::make_pair(its_service_interval, its_ids);
110
111 its_requests_length -= (its_current_size - _size);
112 }
113
114 // Deserialize offers array length
115 uint32_t its_offers_length;
116 its_result = deserialize_u32(_data, _size, its_offers_length);
117 if (its_result == false)
118 return (false);
119
120 while (0 < its_offers_length) {
121
122 uint32_t its_current_size(_size);
123
124 uint16_t its_service;
125 its_result = deserialize_u16(_data, _size, its_service);
126 if (its_result == false)
127 return (false);
128
129 if (its_service == 0x0000 || its_service == 0xFFFF) {
130 VSOMEIP_WARNING << "vSomeIP Security: Policy with service ID: 0x"
131 << std::hex << its_service << " is not allowed!";
132 return false;
133 }
134
135 const auto its_service_interval
136 = boost::icl::interval<service_t>::closed(its_service, its_service);
137
138 boost::icl::interval_set<instance_t> its_instance_interval_set;
139 its_result = deserialize_id_item_list(_data, _size,
140 its_instance_interval_set);
141 if (its_result == false)
142 return (false);
143
144 offers_ += std::make_pair(its_service_interval, its_instance_interval_set);
145
146 its_offers_length -= (its_current_size - _size);
147 }
148
149 return (true);
150 }
151
152 bool
deserialize_ids(const byte_t * & _data,uint32_t & _size,boost::icl::interval_map<uint16_t,boost::icl::interval_set<uint16_t>> & _ids) const153 policy::deserialize_ids(const byte_t * &_data, uint32_t &_size,
154 boost::icl::interval_map<uint16_t,
155 boost::icl::interval_set<uint16_t> > &_ids) const {
156
157 boost::icl::interval_map<uint16_t,
158 boost::icl::interval_set<uint16_t> > its_ids;
159 uint32_t its_array_length;
160 bool its_result;
161
162 its_result = deserialize_u32(_data, _size, its_array_length);
163 if (its_result == false)
164 return (false);
165
166 while (0 < its_array_length) {
167 uint32_t its_current_size(_size);
168
169 boost::icl::interval_set<uint16_t> its_instances, its_methods;
170 its_result = deserialize_id_item_list(_data, _size, its_instances);
171 if (its_result == false)
172 return (false);
173
174 its_result = deserialize_id_item_list(_data, _size, its_methods);
175 if (its_result == false)
176 return (false);
177
178 for (const auto& i : its_instances)
179 its_ids += std::make_pair(i, its_methods);
180
181 its_array_length -= (its_current_size - _size);
182 }
183
184 _ids = std::move(its_ids);
185
186 return (true);
187 }
188
189 bool
deserialize_id_item_list(const byte_t * & _data,uint32_t & _size,boost::icl::interval_set<uint16_t> & _intervals) const190 policy::deserialize_id_item_list(const byte_t * &_data, uint32_t &_size,
191 boost::icl::interval_set<uint16_t> &_intervals) const {
192
193 boost::icl::interval_set<uint16_t> its_intervals;
194 uint32_t its_length;
195 bool its_result;
196
197 its_result = deserialize_u32(_data, _size, its_length);
198 if (its_result == false)
199 return (its_result);
200
201 while (0 < its_length) {
202
203 uint32_t its_current_size(_size);
204
205 uint16_t its_low, its_high;
206 its_result = deserialize_id_item(_data, _size, its_low, its_high);
207 if (its_result == false)
208 return (false);
209
210 its_intervals.insert(boost::icl::interval<uint16_t>::closed(its_low, its_high));
211
212 its_length -= (its_current_size - _size);
213 }
214
215 _intervals = std::move(its_intervals);
216
217 return (true);
218 }
219
220 bool
deserialize_id_item(const byte_t * & _data,uint32_t & _size,uint16_t & _low,uint16_t & _high) const221 policy::deserialize_id_item(const byte_t * &_data, uint32_t &_size,
222 uint16_t &_low, uint16_t &_high) const {
223
224 uint32_t its_length, its_type;
225 bool its_result;
226
227 its_result = deserialize_u32(_data, _size, its_length);
228 if (its_result == false)
229 return (false);
230
231 its_result = deserialize_u32(_data, _size, its_type);
232 if (its_result == false)
233 return (false);
234
235 if (its_type == 1 && its_length == sizeof(uint16_t)) {
236 its_result = deserialize_u16(_data, _size, _low);
237 if (its_result == false)
238 return (false);
239
240 _high = _low;
241 } else if (its_type == 2
242 && its_length == sizeof(uint16_t) + sizeof(uint16_t)) {
243 its_result = deserialize_u16(_data, _size, _low);
244 if (its_result == false)
245 return (false);
246
247 its_result = deserialize_u16(_data, _size, _high);
248 if (its_result == false)
249 return (false);
250
251 if (_low > _high)
252 return (false);
253 }
254
255 // handle ANY_METHOD configuration
256 if (_low == ANY_METHOD && _high == ANY_METHOD) {
257 _low = 0x01;
258 }
259
260 return (_low != 0x0000);
261 }
262
263 bool
deserialize_u16(const byte_t * & _data,uint32_t & _size,uint16_t & _value) const264 policy::deserialize_u16(const byte_t * &_data, uint32_t &_size,
265 uint16_t &_value) const {
266
267 if (_size < sizeof(uint16_t))
268 return (false);
269
270 _value = VSOMEIP_BYTES_TO_WORD(_data[0], _data[1]);
271
272 _data += sizeof(uint16_t);
273 _size -= static_cast<uint16_t>(sizeof(uint16_t));
274
275 return (true);
276 }
277
278 bool
deserialize_u32(const byte_t * & _data,uint32_t & _size,uint32_t & _value) const279 policy::deserialize_u32(const byte_t * &_data, uint32_t &_size,
280 uint32_t &_value) const {
281
282 if (_size < sizeof(uint32_t))
283 return (false);
284
285 _value = VSOMEIP_BYTES_TO_LONG(_data[0], _data[1], _data[2], _data[3]);
286
287 _data += sizeof(uint32_t);
288 _size -= static_cast<uint32_t>(sizeof(uint32_t));
289
290 return (true);
291 }
292
293 bool
serialize(std::vector<byte_t> & _data) const294 policy::serialize(std::vector<byte_t> &_data) const {
295
296 bool its_result;
297
298 std::lock_guard<std::mutex> its_lock(mutex_);
299
300 its_result = serialize_uid_gid(_data);
301 if (!its_result)
302 return (false);
303
304 size_t its_requests_pos = _data.size();
305 uint32_t its_requests_size(0);
306 serialize_u32(its_requests_size, _data);
307
308 for (const auto &its_request : requests_) {
309 for (auto its_service = its_request.first.lower();
310 its_service <= its_request.first.upper();
311 its_service++) {
312
313 serialize_u16(its_service, _data);
314
315 size_t its_pos = _data.size();
316 uint32_t its_instances_size(0);
317 serialize_u32(its_instances_size, _data);
318
319 for (const auto &i : its_request.second) {
320 boost::icl::interval_set<instance_t> its_instances;
321 its_instances.insert(i.first);
322 serialize_interval_set(its_instances, _data);
323 serialize_interval_set(i.second, _data);
324 }
325
326 its_instances_size = static_cast<uint32_t>(_data.size() - its_pos - sizeof(uint32_t));
327 serialize_u32_at(its_instances_size, _data, its_pos);
328 }
329 }
330
331 its_requests_size = static_cast<uint32_t>(_data.size() - its_requests_pos - sizeof(uint32_t));
332 serialize_u32_at(its_requests_size, _data, its_requests_pos);
333
334 uint32_t its_offers_size = 0;
335 serialize_u32(its_offers_size, _data);
336
337 return (true);
338 }
339
340 bool
serialize_uid_gid(std::vector<byte_t> & _data) const341 policy::serialize_uid_gid(std::vector<byte_t> &_data) const {
342
343 if (credentials_.size() != 1) {
344 VSOMEIP_ERROR << "Unserializable policy (ids).";
345 return (false);
346 }
347
348 auto its_credential = *(credentials_.begin());
349 if (its_credential.second.size() != 1) {
350 VSOMEIP_ERROR << "Unserializable policy (intervals).";
351 return (false);
352 }
353
354 auto its_uid_interval = its_credential.first;
355 if (its_uid_interval.lower() != its_uid_interval.upper()) {
356 VSOMEIP_ERROR << "Unserializable policy (uid).";
357 return (false);
358 }
359
360 auto its_gid_interval = *(its_credential.second.begin());
361 if (its_gid_interval.lower() != its_gid_interval.upper()) {
362 VSOMEIP_ERROR << "Unserializable policy (gid).";
363 return (false);
364 }
365
366 serialize_u32(its_uid_interval.lower(), _data);
367 serialize_u32(its_gid_interval.lower(), _data);
368
369 return (true);
370 }
371
372 void
serialize_interval_set(const boost::icl::interval_set<uint16_t> & _intervals,std::vector<byte_t> & _data) const373 policy::serialize_interval_set(
374 const boost::icl::interval_set<uint16_t> &_intervals,
375 std::vector<byte_t> &_data) const {
376
377 size_t its_pos(_data.size());
378 uint32_t its_interval_set_size(0);
379 serialize_u32(its_interval_set_size, _data);
380
381 for (const auto& i : _intervals)
382 serialize_interval(i, _data);
383
384 its_interval_set_size = static_cast<uint32_t>(_data.size()
385 - its_pos - sizeof(uint32_t));
386 serialize_u32_at(its_interval_set_size, _data, its_pos);
387 }
388
389 void
serialize_interval(const boost::icl::discrete_interval<uint16_t> & _interval,std::vector<byte_t> & _data) const390 policy::serialize_interval(
391 const boost::icl::discrete_interval<uint16_t> &_interval,
392 std::vector<byte_t> &_data) const {
393
394 uint32_t its_union_length, its_union_type;
395
396 if (_interval.lower() == _interval.upper()) { // single value
397 its_union_length = static_cast<uint32_t>(sizeof(uint16_t));
398 its_union_type = 1;
399
400 serialize_u32(its_union_length, _data);
401 serialize_u32(its_union_type, _data);
402
403 serialize_u16(_interval.lower(), _data);
404 } else { // value interval
405 its_union_type = 2;
406 its_union_length = static_cast<uint32_t>(
407 sizeof(uint16_t) + sizeof(uint16_t));
408
409 serialize_u32(its_union_length, _data);
410 serialize_u32(its_union_type, _data);
411
412 serialize_u16(_interval.lower(), _data);
413 serialize_u16(_interval.upper(), _data);
414 }
415 }
416
417 void
serialize_u16(uint16_t _value,std::vector<byte_t> & _data) const418 policy::serialize_u16(uint16_t _value,
419 std::vector<byte_t> &_data) const {
420
421 _data.push_back(VSOMEIP_WORD_BYTE1(_value));
422 _data.push_back(VSOMEIP_WORD_BYTE0(_value));
423 }
424
425 void
serialize_u32(uint32_t _value,std::vector<byte_t> & _data) const426 policy::serialize_u32(uint32_t _value,
427 std::vector<byte_t> &_data) const {
428
429 _data.push_back(VSOMEIP_LONG_BYTE3(_value));
430 _data.push_back(VSOMEIP_LONG_BYTE2(_value));
431 _data.push_back(VSOMEIP_LONG_BYTE1(_value));
432 _data.push_back(VSOMEIP_LONG_BYTE0(_value));
433 }
434
435 void
serialize_u32_at(uint32_t _value,std::vector<byte_t> & _data,size_t _pos) const436 policy::serialize_u32_at(uint32_t _value,
437 std::vector<byte_t> &_data, size_t _pos) const {
438
439 _data[_pos] = VSOMEIP_LONG_BYTE3(_value);
440 _data[_pos+1] = VSOMEIP_LONG_BYTE2(_value);
441 _data[_pos+2] = VSOMEIP_LONG_BYTE1(_value);
442 _data[_pos+3] = VSOMEIP_LONG_BYTE0(_value);
443 }
444
445 void
print() const446 policy::print() const {
447
448 for (auto its_credential : credentials_) {
449 auto its_uid_interval = its_credential.first;
450 if (its_uid_interval.lower() == std::numeric_limits<uint32_t>::max()) {
451 VSOMEIP_INFO << "policy::print Security configuration: UID: any";
452 } else {
453 VSOMEIP_INFO << "policy::print Security configuration: UID: "
454 << std::dec << its_uid_interval.lower();
455 }
456 for (auto its_gid_interval : its_credential.second) {
457 if (its_gid_interval.lower() == std::numeric_limits<uint32_t>::max()) {
458 VSOMEIP_INFO << " policy::print Security configuration: GID: any";
459 } else {
460 VSOMEIP_INFO << " policy::print Security configuration: GID: "
461 << std::dec << its_gid_interval.lower();
462 }
463 }
464 }
465
466 VSOMEIP_INFO << "policy::print Security configuration: REQUESTS POLICY SIZE: "
467 << std::dec << requests_.size();
468 for (auto its_request : requests_) {
469 VSOMEIP_INFO << "policy::print ALLOWED REQUESTS Services:"
470 << std::hex << its_request.first;
471 for (auto its_instance : its_request.second) {
472 VSOMEIP_INFO << "policy::print Instances: ";
473 VSOMEIP_INFO << "policy::print first: 0x"
474 << std::hex << its_instance.first.lower()
475 << " last: 0x" << its_instance.first.upper();
476 VSOMEIP_INFO << "policy::print Methods: ";
477 for (auto its_method : its_instance.second) {
478 VSOMEIP_INFO << "policy::print first: 0x"
479 << std::hex << its_method.lower()
480 << " last: 0x" << its_method.upper();
481 }
482 }
483 }
484
485 VSOMEIP_INFO << "policy::print Security configuration: OFFER POLICY SIZE: "
486 << std::dec << offers_.size();
487 for (auto its_offer : offers_) {
488 VSOMEIP_INFO << "policy::print ALLOWED OFFERS Services:"
489 << std::hex << its_offer.first;
490 for (auto its_instance : its_offer.second) {
491 VSOMEIP_INFO << "policy::print Instances: ";
492 VSOMEIP_INFO << "policy::print first: 0x"
493 << std::hex << its_instance.lower()
494 << " last: 0x" << its_instance.upper();
495 }
496 }
497 }
498
499 } // namespace vsomeip_v3
500