OpenDDS  Snapshot(2023/04/28-20:55)
Stun.cpp
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Distributed under the OpenDDS License.
5  * See: http://www.opendds.org/license.html
6  */
7 
8 #ifdef OPENDDS_SECURITY
9 
10 #include "Stun.h"
11 
14 #include "dds/DCPS/RTPS/RtpsCoreC.h"
16 
18 
19 namespace OpenDDS {
20 namespace STUN {
21 
22 ACE_UINT16 Attribute::length() const
23 {
24  switch (type) {
25  case MAPPED_ADDRESS:
26 #if ACE_HAS_IPV6
27  if (mapped_address.get_type() == AF_INET6) {
28  return 20;
29  }
30 #endif
31  return 8;
32 
33  case USERNAME:
34  return static_cast<ACE_UINT16>(username.size());
35 
36  case MESSAGE_INTEGRITY:
37  return 20;
38 
39  case ERROR_CODE:
40  return static_cast<ACE_UINT16>(4 + error.reason.size());
41 
42  case UNKNOWN_ATTRIBUTES:
43  return static_cast<ACE_UINT16>(2 * unknown_attributes.size());
44 
45  case XOR_MAPPED_ADDRESS:
46 #if ACE_HAS_IPV6
47  if (mapped_address.get_type() == AF_INET6) {
48  return 20;
49  }
50 #endif
51  return 8;
52 
53  case PRIORITY:
54  return 4;
55 
56  case USE_CANDIDATE:
57  return 0;
58 
59  case FINGERPRINT:
60  return 4;
61 
62  case ICE_CONTROLLED:
63  case ICE_CONTROLLING:
64  return 8;
65 
66  case GUID_PREFIX:
67  return sizeof(DCPS::GuidPrefix_t);
68 
69  default:
70  break;
71  }
72 
73  return unknown_length;
74 }
75 
77 {
78  Attribute attribute;
79  attribute.type = MAPPED_ADDRESS;
80  attribute.mapped_address = addr;
81  return attribute;
82 }
83 
84 Attribute make_username(const std::string& username)
85 {
86  Attribute attribute;
87  attribute.type = USERNAME;
88  attribute.username = username;
89  return attribute;
90 }
91 
93 {
94  Attribute attribute;
95  attribute.type = MESSAGE_INTEGRITY;
96  return attribute;
97 }
98 
99 Attribute make_error_code(ACE_UINT16 code, const std::string& reason)
100 {
101  Attribute attribute;
102  attribute.type = ERROR_CODE;
103  attribute.error.code = code;
104  attribute.error.reason = reason;
105  return attribute;
106 }
107 
108 Attribute make_unknown_attributes(const std::vector<AttributeType>& unknown_attributes)
109 {
110  Attribute attribute;
111  attribute.type = UNKNOWN_ATTRIBUTES;
113  return attribute;
114 }
115 
117 {
118  Attribute attribute;
119  attribute.type = XOR_MAPPED_ADDRESS;
120  attribute.mapped_address = addr;
121  return attribute;
122 }
123 
125 {
126  Attribute attribute;
127  attribute.type = PRIORITY;
128  attribute.priority = priority;
129  return attribute;
130 }
131 
133 {
134  Attribute attribute;
135  attribute.type = USE_CANDIDATE;
136  return attribute;
137 }
138 
140 {
141  Attribute attribute;
142  attribute.type = FINGERPRINT;
143  return attribute;
144 }
145 
147 {
148  Attribute attribute;
149  attribute.type = ICE_CONTROLLING;
150  attribute.ice_tie_breaker = ice_tie_breaker;
151  return attribute;
152 }
153 
155 {
156  Attribute attribute;
157  attribute.type = ICE_CONTROLLED;
158  attribute.ice_tie_breaker = ice_tie_breaker;
159  return attribute;
160 }
161 
164 {
165  Attribute attribute;
166  attribute.type = GUID_PREFIX;
167  std::memcpy(attribute.guid_prefix, guid_prefix, sizeof(guid_prefix));
168  return attribute;
169 }
170 
172 {
173  Attribute attribute;
174  attribute.type = static_cast<AttributeType>(type);
175  attribute.unknown_length = length;
176  return attribute;
177 }
178 
179 bool operator>>(DCPS::Serializer& serializer, AttributeHolder& holder)
180 {
181  ACE_UINT16 attribute_type;
182  ACE_UINT16 attribute_length;
183 
184  if (!(serializer >> attribute_type)) {
185  return false;
186  }
187 
188  if (!(serializer >> attribute_length)) {
189  return false;
190  }
191 
192  switch (attribute_type) {
193  case MAPPED_ADDRESS: {
194  ACE_CDR::Char family;
195  ACE_UINT16 port;
196 
197  if (!serializer.skip(1)) {
198  return false;
199  }
200 
201  if (!(serializer >> family)) {
202  return false;
203  }
204 
205  if (!(serializer >> port)) {
206  return false;
207  }
208 
209  if (family == IPv4) {
210  if (attribute_length != 8) {
211  return false;
212  }
213 
214  ACE_UINT32 address;
215 
216  if (!(serializer >> address)) {
217  return false;
218  }
219 
220  holder.attribute = make_mapped_address(ACE_INET_Addr(port, address));
221  } else if (family == IPv6) {
222  if (attribute_length != 20) {
223  return false;
224  }
225 
226  ACE_CDR::Octet address[16];
227 
228  if (!(serializer.read_octet_array(address, 16))) {
229  return false;
230  }
231  ACE_INET_Addr addr;
232  addr.set_type(AF_INET6);
233  addr.set_address(reinterpret_cast<const char*>(address), 16, 0);
234  addr.set_port_number(port);
235 
236  holder.attribute = make_mapped_address(addr);
237  }
238  }
239  break;
240 
241  case USERNAME: {
242  if (attribute_length > 512) {
243  return false;
244  }
245 
246  unsigned char buffer[512];
247 
248  if (!serializer.read_octet_array(buffer, attribute_length)) {
249  return false;
250  }
251 
252  holder.attribute = make_username(std::string(reinterpret_cast<char*>(buffer), attribute_length));
253  }
254  break;
255 
256  case MESSAGE_INTEGRITY: {
258 
259  if (!serializer.read_octet_array(holder.attribute.message_integrity, sizeof(holder.attribute.message_integrity))) {
260  return false;
261  }
262  }
263  break;
264 
265  case ERROR_CODE: {
266  ACE_UINT32 x;
267 
268  if (!(serializer >> x)) {
269  return false;
270  }
271 
272  ACE_UINT32 class_ = (x & (0x7 << 8)) >> 8;
273 
274  if (class_ < 3 || class_ >= 7) {
275  return false;
276  }
277 
278  ACE_UINT32 num = x & 0xFF;
279 
280  if (num > 100) {
281  return false;
282  }
283 
284  ACE_UINT16 code = class_ * 100 + num;
285 
286  const ACE_CDR::ULong reason_length = attribute_length - 4;
287 
288  if (reason_length > 763) {
289  return false;
290  }
291 
292  unsigned char buffer[763];
293 
294  if (!serializer.read_octet_array(buffer, reason_length)) {
295  return false;
296  }
297 
298  holder.attribute = make_error_code(code, std::string(reinterpret_cast<char*>(buffer), reason_length));
299  }
300  break;
301 
302  case UNKNOWN_ATTRIBUTES: {
303  std::vector<AttributeType> unknown_attributes;
304 
305  for (size_t count = attribute_length / 2; count != 0; --count) {
306  ACE_UINT16 code;
307 
308  if (!(serializer >> code)) {
309  return false;
310  }
311 
312  unknown_attributes.push_back(static_cast<AttributeType>(code));
313  }
314 
315  holder.attribute = make_unknown_attributes(unknown_attributes);
316  }
317  break;
318 
319  case XOR_MAPPED_ADDRESS: {
320  ACE_CDR::Char family;
321  ACE_UINT16 port;
322 
323  if (!serializer.skip(1)) {
324  return false;
325  }
326 
327  if (!(serializer >> family)) {
328  return false;
329  }
330 
331  if (!(serializer >> port)) {
332  return false;
333  }
334 
335  port ^= MAGIC_COOKIE >> 16;
336 
337  if (family == IPv4) {
338  if (attribute_length != 8) {
339  return false;
340  }
341 
342  ACE_UINT32 address;
343 
344  if (!(serializer >> address)) {
345  return false;
346  }
347 
348  address ^= MAGIC_COOKIE;
349  holder.attribute = make_xor_mapped_address(ACE_INET_Addr(port, address));
350  } else if (family == IPv6) {
351  if (attribute_length != 20) {
352  return false;
353  }
354 
355  ACE_CDR::Octet address[16];
356 
357  if (!(serializer.read_octet_array(address, 16))) {
358  return false;
359  }
360 
361  address[0] ^= ((MAGIC_COOKIE & 0xFF000000) >> 24);
362  address[1] ^= ((MAGIC_COOKIE & 0x00FF0000) >> 16);
363  address[2] ^= ((MAGIC_COOKIE & 0x0000FF00) >> 8);
364  address[3] ^= ((MAGIC_COOKIE & 0x000000FF) >> 0);
365  address[4] ^= holder.tid.data[0];
366  address[5] ^= holder.tid.data[1];
367  address[6] ^= holder.tid.data[2];
368  address[7] ^= holder.tid.data[3];
369  address[8] ^= holder.tid.data[4];
370  address[9] ^= holder.tid.data[5];
371  address[10] ^= holder.tid.data[6];
372  address[11] ^= holder.tid.data[7];
373  address[12] ^= holder.tid.data[8];
374  address[13] ^= holder.tid.data[9];
375  address[14] ^= holder.tid.data[10];
376  address[15] ^= holder.tid.data[11];
377 
378  ACE_INET_Addr addr;
379  addr.set_type(AF_INET6);
380  addr.set_address(reinterpret_cast<const char*>(address), 16, 0);
381  addr.set_port_number(port);
382 
383  holder.attribute = make_xor_mapped_address(addr);
384  }
385  }
386  break;
387 
388  case PRIORITY: {
389  ACE_UINT32 priority;
390 
391  if (!(serializer >> priority)) {
392  return false;
393  }
394 
395  holder.attribute = make_priority(priority);
396  }
397  break;
398 
399  case USE_CANDIDATE:
400  holder.attribute = make_use_candidate();
401  break;
402 
403  case FINGERPRINT: {
404  holder.attribute = make_fingerprint();
405 
406  if (!(serializer >> holder.attribute.fingerprint)) {
407  return false;
408  }
409  }
410  break;
411 
412  case ICE_CONTROLLED: {
414 
415  if (!(serializer >> ice_tie_breaker)) {
416  return false;
417  }
418 
419  holder.attribute = make_ice_controlled(ice_tie_breaker);
420  }
421  break;
422 
423  case ICE_CONTROLLING: {
425 
426  if (!(serializer >> ice_tie_breaker)) {
427  return false;
428  }
429 
430  holder.attribute = make_ice_controlling(ice_tie_breaker);
431  }
432  break;
433 
434  case GUID_PREFIX: {
436  if (!(serializer.read_octet_array(guid_prefix, sizeof(guid_prefix)))) {
437  return false;
438  }
439 
440  holder.attribute = make_guid_prefix(guid_prefix);
441  }
442  break;
443 
444  default: {
445  if (!serializer.skip(attribute_length)) {
446  return false;
447  }
448 
449  holder.attribute = make_unknown_attribute(attribute_type, attribute_length);
450  }
451  break;
452  }
453 
454  // All attributes are aligned on 32-bit boundaries.
455  if (!serializer.skip((4 - (attribute_length & 0x3)) % 4)) {
456  return false;
457  }
458 
459  return true;
460 }
461 
463 {
464  ACE_UINT16 attribute_type = holder.attribute.type;
465  ACE_UINT16 attribute_length = holder.attribute.length();
466  serializer << attribute_type;
467  serializer << attribute_length;
468 
469  switch (attribute_type) {
470  case MAPPED_ADDRESS: {
471  serializer << static_cast<ACE_CDR::Char>(0);
472  if (holder.attribute.mapped_address.get_type() == AF_INET) {
473  serializer << static_cast<ACE_CDR::Char>(IPv4);
474  serializer << static_cast<ACE_UINT16>(holder.attribute.mapped_address.get_port_number());
475  serializer << holder.attribute.mapped_address.get_ip_address();
476  } else {
477  serializer << static_cast<ACE_CDR::Char>(IPv6);
478  serializer << static_cast<ACE_UINT16>(holder.attribute.mapped_address.get_port_number());
481  serializer.write_octet_array(a, 16);
482  }
483  }
484  break;
485 
486  case USERNAME: {
487  serializer.write_octet_array(reinterpret_cast<const ACE_CDR::Octet*>(holder.attribute.username.c_str()),
488  static_cast<ACE_CDR::ULong>(holder.attribute.username.size()));
489  }
490  break;
491 
492  case MESSAGE_INTEGRITY: {
493  serializer.write_octet_array(holder.attribute.message_integrity, sizeof(holder.attribute.message_integrity));
494  }
495  break;
496 
497  case ERROR_CODE: {
498  ACE_UINT8 class_ = holder.attribute.error.code / 100;
499  ACE_UINT8 num = holder.attribute.error.code % 100;
500  serializer << static_cast<ACE_CDR::Char>(0);
501  serializer << static_cast<ACE_CDR::Char>(0);
502  serializer << static_cast<ACE_CDR::Char>(class_);
503  serializer << static_cast<ACE_CDR::Char>(num);
504  serializer.write_octet_array(reinterpret_cast<const ACE_CDR::Octet*>(holder.attribute.error.reason.c_str()),
505  static_cast<ACE_CDR::ULong>(holder.attribute.error.reason.size()));
506  }
507  break;
508 
509  case UNKNOWN_ATTRIBUTES: {
510  for (std::vector<AttributeType>::const_iterator pos = holder.attribute.unknown_attributes.begin(),
511  limit = holder.attribute.unknown_attributes.end(); pos != limit; ++pos) {
512  serializer << static_cast<ACE_UINT16>(*pos);
513  }
514  }
515  break;
516 
517  case XOR_MAPPED_ADDRESS: {
518  serializer << static_cast<ACE_CDR::Char>(0);
519  if (holder.attribute.mapped_address.get_type() == AF_INET) {
520  serializer << static_cast<ACE_CDR::Char>(IPv4);
521  serializer << static_cast<ACE_UINT16>(holder.attribute.mapped_address.get_port_number() ^ (MAGIC_COOKIE >> 16));
522  serializer << (holder.attribute.mapped_address.get_ip_address() ^ MAGIC_COOKIE);
523  } else {
524  serializer << static_cast<ACE_CDR::Char>(IPv6);
525  serializer << static_cast<ACE_UINT16>(holder.attribute.mapped_address.get_port_number() ^ (MAGIC_COOKIE >> 16));
526 
529 
530  a[0] ^= ((MAGIC_COOKIE & 0xFF000000) >> 24);
531  a[1] ^= ((MAGIC_COOKIE & 0x00FF0000) >> 16);
532  a[2] ^= ((MAGIC_COOKIE & 0x0000FF00) >> 8);
533  a[3] ^= ((MAGIC_COOKIE & 0x000000FF) >> 0);
534  a[4] ^= holder.tid.data[0];
535  a[5] ^= holder.tid.data[1];
536  a[6] ^= holder.tid.data[2];
537  a[7] ^= holder.tid.data[3];
538  a[8] ^= holder.tid.data[4];
539  a[9] ^= holder.tid.data[5];
540  a[10] ^= holder.tid.data[6];
541  a[11] ^= holder.tid.data[7];
542  a[12] ^= holder.tid.data[8];
543  a[13] ^= holder.tid.data[9];
544  a[14] ^= holder.tid.data[10];
545  a[15] ^= holder.tid.data[11];
546 
547  serializer.write_octet_array(a, 16);
548  }
549  }
550  break;
551 
552  case PRIORITY: {
553  serializer << holder.attribute.priority;
554  }
555  break;
556 
557  case USE_CANDIDATE:
558  break;
559 
560  case FINGERPRINT: {
561  serializer << holder.attribute.fingerprint;
562  }
563  break;
564 
565  case ICE_CONTROLLED:
566  case ICE_CONTROLLING: {
567  serializer << holder.attribute.ice_tie_breaker;
568  }
569  break;
570 
571  case GUID_PREFIX: {
572  serializer.write_octet_array(holder.attribute.guid_prefix, sizeof(holder.attribute.guid_prefix));
573  }
574  break;
575 
576  default:
577  // Don't serialize attributes that are not understood.
578  return false;
579  break;
580  }
581 
582  // Align to 32 bits.
583  while (attribute_length % 4 != 0) {
584  serializer << static_cast<ACE_CDR::Char>(0);
585  attribute_length += 1;
586  }
587 
588  return true;
589 }
590 
591 bool TransactionId::operator<(const TransactionId& other) const
592 {
593  return (memcmp(this->data, other.data, sizeof(data)) < 0);
594 }
595 
596 bool TransactionId::operator==(const TransactionId& other) const
597 {
598  return (memcmp(this->data, other.data, sizeof(data)) == 0);
599 }
600 
601 bool TransactionId::operator!=(const TransactionId& other) const
602 {
603  return (memcmp(this->data, other.data, sizeof(data)) != 0);
604 }
605 
607 {
608  TheSecurityRegistry->builtin_config()->get_utility()->generate_random_bytes(transaction_id.data, sizeof(transaction_id.data));
609 }
610 
612 {
613  ACE_OS::memset(transaction_id.data, 0, sizeof(transaction_id.data));
614 }
615 
616 std::vector<AttributeType> Message::unknown_comprehension_required_attributes() const
617 {
618  std::vector<AttributeType> retval;
619 
620  for (AttributesType::const_iterator pos = attributes_.begin(), limit = attributes_.end(); pos != limit; ++pos) {
621  const AttributesType::value_type& attribute = *pos;
622  switch (attribute.type) {
623  case MAPPED_ADDRESS:
624  case USERNAME:
625  case MESSAGE_INTEGRITY:
626  case ERROR_CODE:
627  case UNKNOWN_ATTRIBUTES:
628  case XOR_MAPPED_ADDRESS:
629  case PRIORITY:
630  case USE_CANDIDATE:
631  break;
632 
633  default:
634  if (attribute.type < 0x8000) {
635  retval.push_back(attribute.type);
636  }
637  }
638  }
639 
640  return retval;
641 }
642 
644 {
645  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
646  if (pos->type == STUN::XOR_MAPPED_ADDRESS) {
647  address = pos->mapped_address;
648  return true;
649  }
650  }
651 
652  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
653  if (pos->type == STUN::MAPPED_ADDRESS) {
654  address = pos->mapped_address;
655  return true;
656  }
657  }
658 
659  return false;
660 }
661 
662 bool Message::get_priority(ACE_UINT32& priority) const
663 {
664  bool flag = false;
665 
666  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
667  if (pos->type == STUN::PRIORITY) {
668  flag = true;
669  priority = pos->priority;
670  // Use the last.
671  }
672  }
673 
674  return flag;
675 }
676 
677 bool Message::get_username(std::string& username) const
678 {
679  bool flag = false;
680 
681  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
682  if (pos->type == STUN::USERNAME) {
683  flag = true;
684  username = pos->username;
685  // Use the last.
686  }
687  }
688 
689  return flag;
690 }
691 
693 {
694  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
695  if (pos->type == STUN::MESSAGE_INTEGRITY) {
696  return true;
697  }
698  }
699 
700  return false;
701 }
702 
703 bool Message::verify_message_integrity(const std::string& password) const
704 {
705  bool verified = false;
706 
707  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
708  if (pos->type == STUN::MESSAGE_INTEGRITY) {
709  unsigned char computed_message_integrity[20];
710  compute_message_integrity(password, computed_message_integrity);
711  verified = memcmp(computed_message_integrity, pos->message_integrity, 20) == 0;
712  // Use the last.
713  }
714  }
715 
716  return verified;
717 }
718 
719 void Message::compute_message_integrity(const std::string& password, unsigned char message_integrity[20]) const
720 {
721  ACE_Message_Block* block = this->block->duplicate();
722  block->rd_ptr(block->base());
723  DCPS::Serializer serializer(block, encoding);
724 
725  // Write the length and resize for hashing.
726  block->wr_ptr(block->base() + 2);
727  ACE_UINT16 message_length = length_for_message_integrity();
728  serializer << message_length;
729  block->wr_ptr(block->base() + HEADER_SIZE + length_for_message_integrity() - 24);
730 
731  // Compute the SHA1.
732  TheSecurityRegistry->builtin_config()->get_utility()->hmac(message_integrity, block->rd_ptr(), block->length(), password);
733 
734  // Write the correct length.
735  block->wr_ptr(block->base() + 2);
736  message_length = length();
737  serializer << message_length;
738 
739  block->release();
740 }
741 
743 {
744  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
745  if (pos->type == STUN::ERROR_CODE) {
746  return true;
747  }
748  }
749 
750  return false;
751 }
752 
753 ACE_UINT16 Message::get_error_code() const
754 {
755  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
756  if (pos->type == STUN::ERROR_CODE) {
757  return pos->error.code;
758  }
759  }
760 
761  return 0;
762 }
763 
764 std::string Message::get_error_reason() const
765 {
766  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
767  if (pos->type == STUN::ERROR_CODE) {
768  return pos->error.reason;
769  }
770  }
771 
772  return std::string();
773 }
774 
776 {
777  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
778  if (pos->type == STUN::UNKNOWN_ATTRIBUTES) {
779  return true;
780  }
781  }
782 
783  return false;
784 }
785 
786 std::vector<AttributeType> Message::get_unknown_attributes() const
787 {
788  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
789  if (pos->type == STUN::UNKNOWN_ATTRIBUTES) {
790  return pos->unknown_attributes;
791  }
792  }
793 
794  return std::vector<AttributeType>();
795 }
796 
798 {
799  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
800  if (pos->type == STUN::FINGERPRINT) {
801  return true;
802  }
803  }
804 
805  return false;
806 }
807 
809 {
810  ACE_Message_Block* block = this->block->duplicate();
811  block->rd_ptr(block->base());
812  DCPS::Serializer serializer(block, encoding);
813 
814  // Resize for hashing.
815  block->wr_ptr(block->base() + HEADER_SIZE + length() - 8);
816 
817  // Compute the CRC-32
818  ACE_UINT32 crc = ACE::crc32(block->rd_ptr(), block->length());
819 
820  block->release();
821 
822  return crc ^ 0x5354554E;
823 }
824 
826 {
827  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
828  if (pos->type == STUN::ICE_CONTROLLED) {
829  return true;
830  }
831  }
832 
833  return false;
834 }
835 
837 {
838  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
839  if (pos->type == STUN::ICE_CONTROLLING) {
840  return true;
841  }
842  }
843 
844  return false;
845 }
846 
848 {
849  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
850  if (pos->type == STUN::USE_CANDIDATE) {
851  return true;
852  }
853  }
854 
855  return false;
856 }
857 
859 {
860  for (STUN::Message::const_iterator pos = begin(), limit = end(); pos != limit; ++pos) {
861  if (pos->type == STUN::GUID_PREFIX) {
862  std::memcpy(guid_prefix, pos->guid_prefix, sizeof(guid_prefix));
863  return true;
864  }
865  }
866 
867  return false;
868 }
869 
870 bool operator>>(DCPS::Serializer& serializer, Message& message)
871 {
872  ACE_UINT16 message_type;
873  ACE_UINT16 message_length;
874  ACE_UINT32 magic_cookie;
875 
876  if (!(serializer >> message_type)) {
877  return false;
878  }
879 
880  if (!(serializer >> message_length)) {
881  return false;
882  }
883 
884  if ((message_type & 0xC000) != 0) {
885  return false;
886  }
887 
888  if (message_length % 4 != 0) {
889  return false;
890  }
891 
892  message.class_ = static_cast<Class>(((message_type & (1 << 8)) >> 7) | ((message_type & (1 << 4)) >> 4));
893  message.method = static_cast<Method>(((message_type & 0x3E00) >> 2) | ((message_type & 0xE0) >> 1) | (message_type & 0xF));
894 
895  if (!(serializer >> magic_cookie)) {
896  return false;
897  }
898 
899  if (magic_cookie != MAGIC_COOKIE) {
900  return false;
901  }
902 
903  if (!serializer.read_octet_array(message.transaction_id.data, 12)) {
904  return false;
905  }
906 
907  // At this point there should be message.length bytes remaining.
908  if (serializer.length() != message_length) {
909  return false;
910  }
911 
912  bool have_integrity = false;
913  bool have_fingerprint = false;
914 
915  while (serializer.length() != 0) {
916  Attribute attribute;
917  AttributeHolder holder(attribute, message.transaction_id);
918 
919  if (!(serializer >> holder)) {
920  return false;
921  }
922 
923  message.append_attribute(attribute);
924 
925  if ((have_integrity && attribute.type != FINGERPRINT) || have_fingerprint) {
926  return false;
927  }
928 
929  if (attribute.type == FINGERPRINT && attribute.fingerprint != message.compute_fingerprint()) {
930  return false;
931  }
932 
933  if (message.length() > message_length) {
934  return false;
935  }
936 
937  have_integrity = have_integrity || attribute.type == MESSAGE_INTEGRITY;
938  have_fingerprint = have_fingerprint || attribute.type == FINGERPRINT;
939  }
940 
941  return true;
942 }
943 
944 bool operator<<(DCPS::Serializer& serializer, const Message& message)
945 {
946  ACE_UINT16 message_class = message.class_;
947  ACE_UINT16 message_method = message.method;
948  ACE_UINT16 message_type =
949  ((message_method & 0xF80) << 2) |
950  ((message_class & 0x2) << 7) |
951  ((message_method & 0x0070) << 1) |
952  ((message_class & 0x1) << 4) |
953  (message_method & 0x000F);
954  serializer << message_type;
955 
956  ACE_UINT16 message_length = message.length();
957  serializer << message_length;
958  serializer << MAGIC_COOKIE;
959  serializer.write_octet_array(message.transaction_id.data, sizeof(message.transaction_id.data));
960 
961  for (Message::const_iterator pos = message.begin(), limit = message.end();
962  pos != limit; ++pos) {
963  const Attribute& attribute = *pos;
964 
965  if (attribute.type == MESSAGE_INTEGRITY) {
966  // Compute the hash.
967  message.compute_message_integrity(message.password, const_cast<Attribute&>(attribute).message_integrity);
968  }
969 
970  else if (attribute.type == FINGERPRINT) {
971  // Compute the hash.
972  const_cast<Attribute&>(attribute).fingerprint = message.compute_fingerprint();
973  }
974 
975  ConstAttributeHolder holder(attribute, message.transaction_id);
976  serializer << holder;
977  }
978 
979  return true;
980 }
981 
982 } // namespace STUN
983 } // namespace OpenDDS
984 
986 #endif /* OPENDDS_SECURITY */
ACE_Byte Octet
std::vector< AttributeType > unknown_attributes
Definition: Stun.h:97
void address_to_bytes(DDS::OctetArray16 &dest, const ACE_INET_Addr &addr)
OpenDDS_Rtps_Export Attribute make_guid_prefix(const DCPS::GuidPrefix_t &guid_prefix)
Definition: Stun.cpp:163
bool operator==(const TransactionId &other) const
Definition: Stun.cpp:596
const ACE_UINT32 MAGIC_COOKIE
Definition: Stun.h:48
bool has_ice_controlled() const
Definition: Stun.cpp:825
bool operator<(const TransactionId &other) const
Definition: Stun.cpp:591
size_t length(void) const
bool get_mapped_address(ACE_INET_Addr &address) const
Definition: Stun.cpp:643
bool skip(size_t n, int size=1)
Definition: Serializer.inl:443
const_iterator begin() const
Definition: Stun.h:205
Attribute make_ice_controlled(ACE_UINT64 ice_tie_breaker)
Definition: Stun.cpp:154
bool has_message_integrity() const
Definition: Stun.cpp:692
Attribute make_username(const std::string &username)
Definition: Stun.cpp:84
bool operator!=(const TransactionId &other) const
Definition: Stun.cpp:601
bool get_priority(ACE_UINT32 &priority) const
Definition: Stun.cpp:662
Christopher Diggins *renamed files *fixing compilation errors *adding Visual C project file *removed make Max Lybbert *removed references to missing and unused as reported by Andy Elvey and Dan Kosecki *resynced with Christopher Diggins s branch as it exists in tree building code is back Christopher Diggins *resynced codebase with Chris s branch *removed tree building code
Definition: CHANGELOG.txt:8
Attribute make_xor_mapped_address(const ACE_INET_Addr &addr)
Definition: Stun.cpp:116
const size_t HEADER_SIZE
Definition: Stun.h:49
bool read_octet_array(ACE_CDR::Octet *x, ACE_CDR::ULong length)
Definition: Serializer.inl:558
void generate_transaction_id()
Definition: Stun.cpp:606
std::vector< AttributeType > get_unknown_attributes() const
Definition: Stun.cpp:786
Attribute make_use_candidate()
Definition: Stun.cpp:132
AttributeType
Definition: Stun.h:55
char * rd_ptr(void) const
int get_type(void) const
const TransactionId & tid
Definition: Stun.h:166
bool write_octet_array(const ACE_CDR::Octet *x, ACE_CDR::ULong length)
Definition: Serializer.inl:697
bool has_unknown_attributes() const
Definition: Stun.cpp:775
void set_type(int type)
ACE_UINT8 data[12]
Definition: Stun.h:144
Class to serialize and deserialize data for DDS.
Definition: Serializer.h:369
size_t length() const
Number of bytes left to read in message block chain.
Definition: Serializer.inl:437
char Char
#define OpenDDS_Rtps_Export
Definition: rtps_export.h:23
ACE_UINT16 get_error_code() const
Definition: Stun.cpp:753
ACE_UINT32 get_ip_address(void) const
virtual ACE_Message_Block * release(void)
int set_address(const char *ip_addr, int len, int encode=1, int map=0)
ACE_UINT32 fingerprint
Definition: Stun.h:87
#define TheSecurityRegistry
void compute_message_integrity(const std::string &password, unsigned char message_integrity[20]) const
Definition: Stun.cpp:719
virtual ACE_Message_Block * duplicate(void) const
bool get_username(std::string &username) const
Definition: Stun.cpp:677
#define AF_INET
Attribute make_ice_controlling(ACE_UINT64 ice_tie_breaker)
Definition: Stun.cpp:146
Attribute make_error_code(ACE_UINT16 code, const std::string &reason)
Definition: Stun.cpp:99
char * wr_ptr(void) const
ACE_UINT32 ULong
Attribute make_message_integrity()
Definition: Stun.cpp:92
std::string username
Definition: Stun.h:84
bool operator>>(DCPS::Serializer &serializer, AttributeHolder &holder)
Definition: Stun.cpp:179
ACE_UINT32 crc32(const char *str)
bool has_error_code() const
Definition: Stun.cpp:742
bool get_guid_prefix(DCPS::GuidPrefix_t &guid_pefix) const
Definition: Stun.cpp:858
Attribute make_fingerprint()
Definition: Stun.cpp:139
ACE_UINT16 length() const
Definition: Stun.h:213
unsigned char guid_prefix[sizeof(DCPS::GuidPrefix_t)]
Definition: Stun.h:90
unsigned long long ACE_UINT64
AttributeType type
Definition: Stun.h:81
ACE_UINT32 priority
Definition: Stun.h:88
void append_attribute(const Attribute &attribute)
Definition: Stun.h:195
const_iterator end() const
Definition: Stun.h:209
Attribute make_unknown_attribute(ACE_UINT16 type, ACE_UINT16 length)
Definition: Stun.cpp:171
u_short get_port_number(void) const
std::string get_error_reason() const
Definition: Stun.cpp:764
void * memset(void *s, int c, size_t len)
int memcmp(const void *t, const void *s, size_t len)
octet GuidPrefix_t[12]
Definition: DdsDcpsGuid.idl:19
Attribute make_unknown_attributes(const std::vector< AttributeType > &unknown_attributes)
Definition: Stun.cpp:108
AttributesType::const_iterator const_iterator
Definition: Stun.h:182
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
void set_port_number(u_short, int encode=1)
std::string password
Definition: Stun.h:242
const TransactionId & tid
Definition: Stun.h:156
bool verify_message_integrity(const std::string &password) const
Definition: Stun.cpp:703
ACE_UINT32 compute_fingerprint() const
Definition: Stun.cpp:808
unsigned char ACE_UINT8
Attribute make_mapped_address(const ACE_INET_Addr &addr)
Definition: Stun.cpp:76
unsigned char message_integrity[20]
Definition: Stun.h:86
const DCPS::Encoding encoding(DCPS::Encoding::KIND_UNALIGNED_CDR, DCPS::ENDIAN_BIG)
bool has_use_candidate() const
Definition: Stun.cpp:847
ACE_UINT64 ice_tie_breaker
Definition: Stun.h:89
bool has_ice_controlling() const
Definition: Stun.cpp:836
std::vector< AttributeType > unknown_comprehension_required_attributes() const
Definition: Stun.cpp:616
TransactionId transaction_id
Definition: Stun.h:186
char * base(void) const
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
ACE_UINT16 unknown_length
Definition: Stun.h:99
ACE_UINT16 length() const
Definition: Stun.cpp:22
Attribute make_priority(ACE_UINT32 priority)
Definition: Stun.cpp:124
const Attribute & attribute
Definition: Stun.h:165
octet OctetArray16[16]
ACE_INET_Addr mapped_address
Definition: Stun.h:83
bool operator<<(DCPS::Serializer &serializer, ConstAttributeHolder &holder)
Definition: Stun.cpp:462
struct OpenDDS::STUN::Attribute::Err error
void clear_transaction_id()
Definition: Stun.cpp:611
bool has_fingerprint() const
Definition: Stun.cpp:797