• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "api/transport/stun.h"
12 
13 #include <string.h>
14 
15 #include <algorithm>
16 #include <cstdint>
17 #include <iterator>
18 #include <memory>
19 #include <utility>
20 
21 #include "rtc_base/byte_order.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/crc32.h"
24 #include "rtc_base/helpers.h"
25 #include "rtc_base/logging.h"
26 #include "rtc_base/message_digest.h"
27 #include "system_wrappers/include/metrics.h"
28 
29 using rtc::ByteBufferReader;
30 using rtc::ByteBufferWriter;
31 
32 namespace cricket {
33 
34 namespace {
35 
36 const int k127Utf8CharactersLengthInBytes = 508;
37 const int kMessageIntegrityAttributeLength = 20;
38 const int kTheoreticalMaximumAttributeLength = 65535;
39 
ReduceTransactionId(absl::string_view transaction_id)40 uint32_t ReduceTransactionId(absl::string_view transaction_id) {
41   RTC_DCHECK(transaction_id.length() == cricket::kStunTransactionIdLength ||
42              transaction_id.length() == cricket::kStunLegacyTransactionIdLength)
43       << transaction_id.length();
44   ByteBufferReader reader(transaction_id.data(), transaction_id.size());
45   uint32_t result = 0;
46   uint32_t next;
47   while (reader.ReadUInt32(&next)) {
48     result ^= next;
49   }
50   return result;
51 }
52 
53 // Check the maximum length of a BYTE_STRING attribute against specifications.
LengthValid(int type,int length)54 bool LengthValid(int type, int length) {
55   // "Less than 509 bytes" is intended to indicate a maximum of 127
56   // UTF-8 characters, which may take up to 4 bytes per character.
57   switch (type) {
58     case STUN_ATTR_USERNAME:
59       return length <=
60              k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.3
61     case STUN_ATTR_MESSAGE_INTEGRITY:
62       return length ==
63              kMessageIntegrityAttributeLength;  // RFC 8489 section 14.5
64     case STUN_ATTR_REALM:
65       return length <=
66              k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.9
67     case STUN_ATTR_NONCE:
68       return length <=
69              k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.10
70     case STUN_ATTR_SOFTWARE:
71       return length <=
72              k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.14
73     case STUN_ATTR_DATA:
74       // No length restriction in RFC; it's the content of an UDP datagram,
75       // which in theory can be up to 65.535 bytes.
76       // TODO(bugs.webrtc.org/12179): Write a test to find the real limit.
77       return length <= kTheoreticalMaximumAttributeLength;
78     default:
79       // Return an arbitrary restriction for all other types.
80       return length <= kTheoreticalMaximumAttributeLength;
81   }
82   RTC_DCHECK_NOTREACHED();
83   return true;
84 }
85 
86 }  // namespace
87 
88 const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
89 const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
90 const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized";
91 const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[] = "Unknown Attribute";
92 const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden";
93 const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch";
94 const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce";
95 const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials";
96 const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol";
97 const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict";
98 const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error";
99 
100 const char TURN_MAGIC_COOKIE_VALUE[] = {'\x72', '\xC6', '\x4B', '\xC6'};
101 const char EMPTY_TRANSACTION_ID[] = "0000000000000000";
102 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E;
103 const int SERVER_NOT_REACHABLE_ERROR = 701;
104 
105 // StunMessage
106 
StunMessage()107 StunMessage::StunMessage()
108     : StunMessage(STUN_INVALID_MESSAGE_TYPE, EMPTY_TRANSACTION_ID) {}
109 
StunMessage(uint16_t type)110 StunMessage::StunMessage(uint16_t type)
111     : StunMessage(type, GenerateTransactionId()) {}
112 
StunMessage(uint16_t type,absl::string_view transaction_id)113 StunMessage::StunMessage(uint16_t type, absl::string_view transaction_id)
114     : type_(type),
115       transaction_id_(transaction_id),
116       reduced_transaction_id_(ReduceTransactionId(transaction_id_)) {
117   RTC_DCHECK(IsValidTransactionId(transaction_id_));
118 }
119 
120 StunMessage::~StunMessage() = default;
121 
IsLegacy() const122 bool StunMessage::IsLegacy() const {
123   if (transaction_id_.size() == kStunLegacyTransactionIdLength)
124     return true;
125   RTC_DCHECK(transaction_id_.size() == kStunTransactionIdLength);
126   return false;
127 }
128 
DesignatedExpertRange(int attr_type)129 static bool DesignatedExpertRange(int attr_type) {
130   return (attr_type >= 0x4000 && attr_type <= 0x7FFF) ||
131          (attr_type >= 0xC000 && attr_type <= 0xFFFF);
132 }
133 
AddAttribute(std::unique_ptr<StunAttribute> attr)134 void StunMessage::AddAttribute(std::unique_ptr<StunAttribute> attr) {
135   // Fail any attributes that aren't valid for this type of message,
136   // but allow any type for the range that in the RFC is reserved for
137   // the "designated experts".
138   if (!DesignatedExpertRange(attr->type())) {
139     RTC_DCHECK_EQ(attr->value_type(), GetAttributeValueType(attr->type()));
140   }
141 
142   attr->SetOwner(this);
143   size_t attr_length = attr->length();
144   if (attr_length % 4 != 0) {
145     attr_length += (4 - (attr_length % 4));
146   }
147   length_ += static_cast<uint16_t>(attr_length + 4);
148 
149   attrs_.push_back(std::move(attr));
150 }
151 
RemoveAttribute(int type)152 std::unique_ptr<StunAttribute> StunMessage::RemoveAttribute(int type) {
153   std::unique_ptr<StunAttribute> attribute;
154   for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
155     if ((*it)->type() == type) {
156       attribute = std::move(*it);
157       attrs_.erase(std::next(it).base());
158       break;
159     }
160   }
161   if (attribute) {
162     attribute->SetOwner(nullptr);
163     size_t attr_length = attribute->length();
164     if (attr_length % 4 != 0) {
165       attr_length += (4 - (attr_length % 4));
166     }
167     length_ -= static_cast<uint16_t>(attr_length + 4);
168   }
169   return attribute;
170 }
171 
ClearAttributes()172 void StunMessage::ClearAttributes() {
173   for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
174     (*it)->SetOwner(nullptr);
175   }
176   attrs_.clear();
177   length_ = 0;
178 }
179 
GetNonComprehendedAttributes() const180 std::vector<uint16_t> StunMessage::GetNonComprehendedAttributes() const {
181   std::vector<uint16_t> unknown_attributes;
182   for (auto& attr : attrs_) {
183     // "comprehension-required" range is 0x0000-0x7FFF.
184     if (attr->type() >= 0x0000 && attr->type() <= 0x7FFF &&
185         GetAttributeValueType(attr->type()) == STUN_VALUE_UNKNOWN) {
186       unknown_attributes.push_back(attr->type());
187     }
188   }
189   return unknown_attributes;
190 }
191 
GetAddress(int type) const192 const StunAddressAttribute* StunMessage::GetAddress(int type) const {
193   switch (type) {
194     case STUN_ATTR_MAPPED_ADDRESS: {
195       // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is
196       // missing.
197       const StunAttribute* mapped_address =
198           GetAttribute(STUN_ATTR_MAPPED_ADDRESS);
199       if (!mapped_address)
200         mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS);
201       return reinterpret_cast<const StunAddressAttribute*>(mapped_address);
202     }
203 
204     default:
205       return static_cast<const StunAddressAttribute*>(GetAttribute(type));
206   }
207 }
208 
GetUInt32(int type) const209 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
210   return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
211 }
212 
GetUInt64(int type) const213 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
214   return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
215 }
216 
GetByteString(int type) const217 const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
218   return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
219 }
220 
GetUInt16List(int type) const221 const StunUInt16ListAttribute* StunMessage::GetUInt16List(int type) const {
222   return static_cast<const StunUInt16ListAttribute*>(GetAttribute(type));
223 }
224 
GetErrorCode() const225 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
226   return static_cast<const StunErrorCodeAttribute*>(
227       GetAttribute(STUN_ATTR_ERROR_CODE));
228 }
229 
GetErrorCodeValue() const230 int StunMessage::GetErrorCodeValue() const {
231   const StunErrorCodeAttribute* error_attribute = GetErrorCode();
232   return error_attribute ? error_attribute->code() : STUN_ERROR_GLOBAL_FAILURE;
233 }
234 
GetUnknownAttributes() const235 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
236   return static_cast<const StunUInt16ListAttribute*>(
237       GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
238 }
239 
ValidateMessageIntegrity(const std::string & password)240 StunMessage::IntegrityStatus StunMessage::ValidateMessageIntegrity(
241     const std::string& password) {
242   RTC_DCHECK(integrity_ == IntegrityStatus::kNotSet)
243       << "Usage error: Verification should only be done once";
244   password_ = password;
245   if (GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) {
246     if (ValidateMessageIntegrityOfType(
247             STUN_ATTR_MESSAGE_INTEGRITY, kStunMessageIntegritySize,
248             buffer_.c_str(), buffer_.size(), password)) {
249       integrity_ = IntegrityStatus::kIntegrityOk;
250     } else {
251       integrity_ = IntegrityStatus::kIntegrityBad;
252     }
253   } else if (GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32)) {
254     if (ValidateMessageIntegrityOfType(
255             STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, kStunMessageIntegrity32Size,
256             buffer_.c_str(), buffer_.size(), password)) {
257       integrity_ = IntegrityStatus::kIntegrityOk;
258     } else {
259       integrity_ = IntegrityStatus::kIntegrityBad;
260     }
261   } else {
262     integrity_ = IntegrityStatus::kNoIntegrity;
263   }
264   // Log the result of integrity checking. See crbug.com/1177125 for background.
265   // Convert args to integer for the benefit of the macros.
266   int bucket_count = static_cast<int>(IntegrityStatus::kMaxValue) + 1;
267   int integrity = static_cast<int>(integrity_);
268   if (IsStunRequestType(type_)) {
269     RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Request", integrity,
270                               bucket_count);
271   } else if (IsStunSuccessResponseType(type_)) {
272     RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Response", integrity,
273                               bucket_count);
274   } else if (IsStunIndicationType(type_)) {
275     RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Indication", integrity,
276                               bucket_count);
277   } else {
278     RTC_DCHECK(IsStunErrorResponseType(type_));
279     auto* error_attribute = GetErrorCode();
280     if (!error_attribute) {
281       RTC_HISTOGRAM_ENUMERATION(
282           "WebRTC.Stun.Integrity.ErrorResponse.NoErrorAttribute", integrity,
283           bucket_count);
284     } else {
285       switch (error_attribute->code()) {
286         case STUN_ERROR_TRY_ALTERNATE:
287           RTC_HISTOGRAM_ENUMERATION(
288               "WebRTC.Stun.Integrity.ErrorResponse.TryAlternate", integrity,
289               bucket_count);
290           break;
291         case STUN_ERROR_BAD_REQUEST:
292           RTC_HISTOGRAM_ENUMERATION(
293               "WebRTC.Stun.Integrity.ErrorResponse.BadRequest", integrity,
294               bucket_count);
295           break;
296         case STUN_ERROR_UNAUTHORIZED:
297           RTC_HISTOGRAM_ENUMERATION(
298               "WebRTC.Stun.Integrity.ErrorResponse.Unauthorized", integrity,
299               bucket_count);
300           break;
301         case STUN_ERROR_UNKNOWN_ATTRIBUTE:
302           RTC_HISTOGRAM_ENUMERATION(
303               "WebRTC.Stun.Integrity.ErrorResponse.UnknownAttribute", integrity,
304               bucket_count);
305           break;
306         case STUN_ERROR_STALE_NONCE:
307           RTC_HISTOGRAM_ENUMERATION(
308               "WebRTC.Stun.Integrity.ErrorResponse.StaleNonce", integrity,
309               bucket_count);
310           break;
311         case STUN_ERROR_SERVER_ERROR:
312           RTC_HISTOGRAM_ENUMERATION(
313               "WebRTC.Stun.Integrity.ErrorResponse.ServerError", integrity,
314               bucket_count);
315           break;
316         case STUN_ERROR_GLOBAL_FAILURE:
317           RTC_HISTOGRAM_ENUMERATION(
318               "WebRTC.Stun.Integrity.ErrorResponse.GlobalFailure", integrity,
319               bucket_count);
320           break;
321         default:
322           RTC_HISTOGRAM_ENUMERATION(
323               "WebRTC.Stun.Integrity.ErrorResponse.ErrorOther", integrity,
324               bucket_count);
325           break;
326       }
327     }
328   }
329   return integrity_;
330 }
331 
RevalidateMessageIntegrity(const std::string & password)332 StunMessage::IntegrityStatus StunMessage::RevalidateMessageIntegrity(
333     const std::string& password) {
334   RTC_LOG(LS_INFO) << "Message revalidation, old status was "
335                    << static_cast<int>(integrity_);
336   integrity_ = IntegrityStatus::kNotSet;
337   return ValidateMessageIntegrity(password);
338 }
339 
ValidateMessageIntegrityForTesting(const char * data,size_t size,const std::string & password)340 bool StunMessage::ValidateMessageIntegrityForTesting(
341     const char* data,
342     size_t size,
343     const std::string& password) {
344   return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
345                                         kStunMessageIntegritySize, data, size,
346                                         password);
347 }
348 
ValidateMessageIntegrity32ForTesting(const char * data,size_t size,const std::string & password)349 bool StunMessage::ValidateMessageIntegrity32ForTesting(
350     const char* data,
351     size_t size,
352     const std::string& password) {
353   return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
354                                         kStunMessageIntegrity32Size, data, size,
355                                         password);
356 }
357 
358 // Deprecated
ValidateMessageIntegrity(const char * data,size_t size,const std::string & password)359 bool StunMessage::ValidateMessageIntegrity(const char* data,
360                                            size_t size,
361                                            const std::string& password) {
362   return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
363                                         kStunMessageIntegritySize, data, size,
364                                         password);
365 }
366 
367 // Deprecated
ValidateMessageIntegrity32(const char * data,size_t size,const std::string & password)368 bool StunMessage::ValidateMessageIntegrity32(const char* data,
369                                              size_t size,
370                                              const std::string& password) {
371   return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
372                                         kStunMessageIntegrity32Size, data, size,
373                                         password);
374 }
375 
376 // Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the
377 // procedure outlined in RFC 5389, section 15.4.
ValidateMessageIntegrityOfType(int mi_attr_type,size_t mi_attr_size,const char * data,size_t size,const std::string & password)378 bool StunMessage::ValidateMessageIntegrityOfType(int mi_attr_type,
379                                                  size_t mi_attr_size,
380                                                  const char* data,
381                                                  size_t size,
382                                                  const std::string& password) {
383   RTC_DCHECK(mi_attr_size <= kStunMessageIntegritySize);
384 
385   // Verifying the size of the message.
386   if ((size % 4) != 0 || size < kStunHeaderSize) {
387     return false;
388   }
389 
390   // Getting the message length from the STUN header.
391   uint16_t msg_length = rtc::GetBE16(&data[2]);
392   if (size != (msg_length + kStunHeaderSize)) {
393     return false;
394   }
395 
396   // Finding Message Integrity attribute in stun message.
397   size_t current_pos = kStunHeaderSize;
398   bool has_message_integrity_attr = false;
399   while (current_pos + 4 <= size) {
400     uint16_t attr_type, attr_length;
401     // Getting attribute type and length.
402     attr_type = rtc::GetBE16(&data[current_pos]);
403     attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]);
404 
405     // If M-I, sanity check it, and break out.
406     if (attr_type == mi_attr_type) {
407       if (attr_length != mi_attr_size ||
408           current_pos + sizeof(attr_type) + sizeof(attr_length) + attr_length >
409               size) {
410         return false;
411       }
412       has_message_integrity_attr = true;
413       break;
414     }
415 
416     // Otherwise, skip to the next attribute.
417     current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length;
418     if ((attr_length % 4) != 0) {
419       current_pos += (4 - (attr_length % 4));
420     }
421   }
422 
423   if (!has_message_integrity_attr) {
424     return false;
425   }
426 
427   // Getting length of the message to calculate Message Integrity.
428   size_t mi_pos = current_pos;
429   std::unique_ptr<char[]> temp_data(new char[current_pos]);
430   memcpy(temp_data.get(), data, current_pos);
431   if (size > mi_pos + kStunAttributeHeaderSize + mi_attr_size) {
432     // Stun message has other attributes after message integrity.
433     // Adjust the length parameter in stun message to calculate HMAC.
434     size_t extra_offset =
435         size - (mi_pos + kStunAttributeHeaderSize + mi_attr_size);
436     size_t new_adjusted_len = size - extra_offset - kStunHeaderSize;
437 
438     // Writing new length of the STUN message @ Message Length in temp buffer.
439     //      0                   1                   2                   3
440     //      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
441     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
442     //     |0 0|     STUN Message Type     |         Message Length        |
443     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
444     rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len));
445   }
446 
447   char hmac[kStunMessageIntegritySize];
448   size_t ret =
449       rtc::ComputeHmac(rtc::DIGEST_SHA_1, password.c_str(), password.size(),
450                        temp_data.get(), mi_pos, hmac, sizeof(hmac));
451   RTC_DCHECK(ret == sizeof(hmac));
452   if (ret != sizeof(hmac)) {
453     return false;
454   }
455 
456   // Comparing the calculated HMAC with the one present in the message.
457   return memcmp(data + current_pos + kStunAttributeHeaderSize, hmac,
458                 mi_attr_size) == 0;
459 }
460 
AddMessageIntegrity(absl::string_view password)461 bool StunMessage::AddMessageIntegrity(absl::string_view password) {
462   return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
463                                    kStunMessageIntegritySize, password);
464 }
465 
AddMessageIntegrity32(absl::string_view password)466 bool StunMessage::AddMessageIntegrity32(absl::string_view password) {
467   return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
468                                    kStunMessageIntegrity32Size, password);
469 }
470 
AddMessageIntegrityOfType(int attr_type,size_t attr_size,absl::string_view key)471 bool StunMessage::AddMessageIntegrityOfType(int attr_type,
472                                             size_t attr_size,
473                                             absl::string_view key) {
474   // Add the attribute with a dummy value. Since this is a known attribute, it
475   // can't fail.
476   RTC_DCHECK(attr_size <= kStunMessageIntegritySize);
477   auto msg_integrity_attr_ptr = std::make_unique<StunByteStringAttribute>(
478       attr_type, std::string(attr_size, '0'));
479   auto* msg_integrity_attr = msg_integrity_attr_ptr.get();
480   AddAttribute(std::move(msg_integrity_attr_ptr));
481 
482   // Calculate the HMAC for the message.
483   ByteBufferWriter buf;
484   if (!Write(&buf))
485     return false;
486 
487   int msg_len_for_hmac = static_cast<int>(
488       buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
489   char hmac[kStunMessageIntegritySize];
490   size_t ret =
491       rtc::ComputeHmac(rtc::DIGEST_SHA_1, key.data(), key.size(), buf.Data(),
492                        msg_len_for_hmac, hmac, sizeof(hmac));
493   RTC_DCHECK(ret == sizeof(hmac));
494   if (ret != sizeof(hmac)) {
495     RTC_LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity "
496                          "has dummy value.";
497     return false;
498   }
499 
500   // Insert correct HMAC into the attribute.
501   msg_integrity_attr->CopyBytes(hmac, attr_size);
502   password_ = std::string(key);
503   integrity_ = IntegrityStatus::kIntegrityOk;
504   return true;
505 }
506 
507 // Verifies a message is in fact a STUN message, by performing the checks
508 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed
509 // in section 15.5.
ValidateFingerprint(const char * data,size_t size)510 bool StunMessage::ValidateFingerprint(const char* data, size_t size) {
511   // Check the message length.
512   size_t fingerprint_attr_size =
513       kStunAttributeHeaderSize + StunUInt32Attribute::SIZE;
514   if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size)
515     return false;
516 
517   // Skip the rest if the magic cookie isn't present.
518   const char* magic_cookie =
519       data + kStunTransactionIdOffset - kStunMagicCookieLength;
520   if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
521     return false;
522 
523   // Check the fingerprint type and length.
524   const char* fingerprint_attr_data = data + size - fingerprint_attr_size;
525   if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT ||
526       rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) !=
527           StunUInt32Attribute::SIZE)
528     return false;
529 
530   // Check the fingerprint value.
531   uint32_t fingerprint =
532       rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize);
533   return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) ==
534           rtc::ComputeCrc32(data, size - fingerprint_attr_size));
535 }
536 
537 // static
GenerateTransactionId()538 std::string StunMessage::GenerateTransactionId() {
539   return rtc::CreateRandomString(kStunTransactionIdLength);
540 }
541 
IsStunMethod(rtc::ArrayView<int> methods,const char * data,size_t size)542 bool StunMessage::IsStunMethod(rtc::ArrayView<int> methods,
543                                const char* data,
544                                size_t size) {
545   // Check the message length.
546   if (size % 4 != 0 || size < kStunHeaderSize)
547     return false;
548 
549   // Skip the rest if the magic cookie isn't present.
550   const char* magic_cookie =
551       data + kStunTransactionIdOffset - kStunMagicCookieLength;
552   if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
553     return false;
554 
555   int method = rtc::GetBE16(data);
556   for (int m : methods) {
557     if (m == method) {
558       return true;
559     }
560   }
561   return false;
562 }
563 
AddFingerprint()564 bool StunMessage::AddFingerprint() {
565   // Add the attribute with a dummy value. Since this is a known attribute,
566   // it can't fail.
567   auto fingerprint_attr_ptr =
568       std::make_unique<StunUInt32Attribute>(STUN_ATTR_FINGERPRINT, 0);
569   auto* fingerprint_attr = fingerprint_attr_ptr.get();
570   AddAttribute(std::move(fingerprint_attr_ptr));
571 
572   // Calculate the CRC-32 for the message and insert it.
573   ByteBufferWriter buf;
574   if (!Write(&buf))
575     return false;
576 
577   int msg_len_for_crc32 = static_cast<int>(
578       buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length());
579   uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32);
580 
581   // Insert the correct CRC-32, XORed with a constant, into the attribute.
582   fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE);
583   return true;
584 }
585 
Read(ByteBufferReader * buf)586 bool StunMessage::Read(ByteBufferReader* buf) {
587   // Keep a copy of the buffer data around for later verification.
588   buffer_.assign(buf->Data(), buf->Length());
589 
590   if (!buf->ReadUInt16(&type_)) {
591     return false;
592   }
593 
594   if (type_ & 0x8000) {
595     // RTP and RTCP set the MSB of first byte, since first two bits are version,
596     // and version is always 2 (10). If set, this is not a STUN packet.
597     return false;
598   }
599 
600   if (!buf->ReadUInt16(&length_)) {
601     return false;
602   }
603 
604   std::string magic_cookie;
605   if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) {
606     return false;
607   }
608 
609   std::string transaction_id;
610   if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) {
611     return false;
612   }
613 
614   uint32_t magic_cookie_int;
615   static_assert(sizeof(magic_cookie_int) == kStunMagicCookieLength,
616                 "Integer size mismatch: magic_cookie_int and kStunMagicCookie");
617   std::memcpy(&magic_cookie_int, magic_cookie.data(), sizeof(magic_cookie_int));
618   if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
619     // If magic cookie is invalid it means that the peer implements
620     // RFC3489 instead of RFC5389.
621     transaction_id.insert(0, magic_cookie);
622   }
623   RTC_DCHECK(IsValidTransactionId(transaction_id));
624   transaction_id_ = transaction_id;
625   reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
626 
627   if (length_ != buf->Length()) {
628     return false;
629   }
630 
631   attrs_.resize(0);
632 
633   size_t rest = buf->Length() - length_;
634   while (buf->Length() > rest) {
635     uint16_t attr_type, attr_length;
636     if (!buf->ReadUInt16(&attr_type))
637       return false;
638     if (!buf->ReadUInt16(&attr_length))
639       return false;
640 
641     std::unique_ptr<StunAttribute> attr(
642         CreateAttribute(attr_type, attr_length));
643     if (!attr) {
644       // Skip any unknown or malformed attributes.
645       if ((attr_length % 4) != 0) {
646         attr_length += (4 - (attr_length % 4));
647       }
648       if (!buf->Consume(attr_length)) {
649         return false;
650       }
651     } else {
652       if (!attr->Read(buf)) {
653         return false;
654       }
655       attrs_.push_back(std::move(attr));
656     }
657   }
658 
659   RTC_DCHECK(buf->Length() == rest);
660   return true;
661 }
662 
Write(ByteBufferWriter * buf) const663 bool StunMessage::Write(ByteBufferWriter* buf) const {
664   buf->WriteUInt16(type_);
665   buf->WriteUInt16(length_);
666   if (!IsLegacy())
667     buf->WriteUInt32(stun_magic_cookie_);
668   buf->WriteString(transaction_id_);
669 
670   for (const auto& attr : attrs_) {
671     buf->WriteUInt16(attr->type());
672     buf->WriteUInt16(static_cast<uint16_t>(attr->length()));
673     if (!attr->Write(buf)) {
674       return false;
675     }
676   }
677 
678   return true;
679 }
680 
CreateNew() const681 StunMessage* StunMessage::CreateNew() const {
682   return new StunMessage();
683 }
684 
SetStunMagicCookie(uint32_t val)685 void StunMessage::SetStunMagicCookie(uint32_t val) {
686   stun_magic_cookie_ = val;
687 }
688 
SetTransactionIdForTesting(absl::string_view transaction_id)689 void StunMessage::SetTransactionIdForTesting(absl::string_view transaction_id) {
690   RTC_DCHECK(IsValidTransactionId(transaction_id));
691   transaction_id_ = std::string(transaction_id);
692   reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
693 }
694 
GetAttributeValueType(int type) const695 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
696   switch (type) {
697     case STUN_ATTR_MAPPED_ADDRESS:
698       return STUN_VALUE_ADDRESS;
699     case STUN_ATTR_USERNAME:
700       return STUN_VALUE_BYTE_STRING;
701     case STUN_ATTR_MESSAGE_INTEGRITY:
702       return STUN_VALUE_BYTE_STRING;
703     case STUN_ATTR_ERROR_CODE:
704       return STUN_VALUE_ERROR_CODE;
705     case STUN_ATTR_UNKNOWN_ATTRIBUTES:
706       return STUN_VALUE_UINT16_LIST;
707     case STUN_ATTR_REALM:
708       return STUN_VALUE_BYTE_STRING;
709     case STUN_ATTR_NONCE:
710       return STUN_VALUE_BYTE_STRING;
711     case STUN_ATTR_XOR_MAPPED_ADDRESS:
712       return STUN_VALUE_XOR_ADDRESS;
713     case STUN_ATTR_SOFTWARE:
714       return STUN_VALUE_BYTE_STRING;
715     case STUN_ATTR_ALTERNATE_SERVER:
716       return STUN_VALUE_ADDRESS;
717     case STUN_ATTR_FINGERPRINT:
718       return STUN_VALUE_UINT32;
719     case STUN_ATTR_RETRANSMIT_COUNT:
720       return STUN_VALUE_UINT32;
721     case STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED:
722       return STUN_VALUE_BYTE_STRING;
723     case STUN_ATTR_GOOG_MISC_INFO:
724       return STUN_VALUE_UINT16_LIST;
725     default:
726       return STUN_VALUE_UNKNOWN;
727   }
728 }
729 
CreateAttribute(int type,size_t length)730 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ {
731   StunAttributeValueType value_type = GetAttributeValueType(type);
732   if (value_type != STUN_VALUE_UNKNOWN) {
733     return StunAttribute::Create(value_type, type,
734                                  static_cast<uint16_t>(length), this);
735   } else if (DesignatedExpertRange(type)) {
736     // Read unknown attributes as STUN_VALUE_BYTE_STRING
737     return StunAttribute::Create(STUN_VALUE_BYTE_STRING, type,
738                                  static_cast<uint16_t>(length), this);
739   } else {
740     return NULL;
741   }
742 }
743 
GetAttribute(int type) const744 const StunAttribute* StunMessage::GetAttribute(int type) const {
745   for (const auto& attr : attrs_) {
746     if (attr->type() == type) {
747       return attr.get();
748     }
749   }
750   return NULL;
751 }
752 
IsValidTransactionId(absl::string_view transaction_id)753 bool StunMessage::IsValidTransactionId(absl::string_view transaction_id) {
754   return transaction_id.size() == kStunTransactionIdLength ||
755          transaction_id.size() == kStunLegacyTransactionIdLength;
756 }
757 
EqualAttributes(const StunMessage * other,std::function<bool (int type)> attribute_type_mask) const758 bool StunMessage::EqualAttributes(
759     const StunMessage* other,
760     std::function<bool(int type)> attribute_type_mask) const {
761   RTC_DCHECK(other != nullptr);
762   rtc::ByteBufferWriter tmp_buffer_ptr1;
763   rtc::ByteBufferWriter tmp_buffer_ptr2;
764   for (const auto& attr : attrs_) {
765     if (attribute_type_mask(attr->type())) {
766       const StunAttribute* other_attr = other->GetAttribute(attr->type());
767       if (other_attr == nullptr) {
768         return false;
769       }
770       tmp_buffer_ptr1.Clear();
771       tmp_buffer_ptr2.Clear();
772       attr->Write(&tmp_buffer_ptr1);
773       other_attr->Write(&tmp_buffer_ptr2);
774       if (tmp_buffer_ptr1.Length() != tmp_buffer_ptr2.Length()) {
775         return false;
776       }
777       if (memcmp(tmp_buffer_ptr1.Data(), tmp_buffer_ptr2.Data(),
778                  tmp_buffer_ptr1.Length()) != 0) {
779         return false;
780       }
781     }
782   }
783 
784   for (const auto& attr : other->attrs_) {
785     if (attribute_type_mask(attr->type())) {
786       const StunAttribute* own_attr = GetAttribute(attr->type());
787       if (own_attr == nullptr) {
788         return false;
789       }
790       // we have already compared all values...
791     }
792   }
793   return true;
794 }
795 
796 // StunAttribute
797 
StunAttribute(uint16_t type,uint16_t length)798 StunAttribute::StunAttribute(uint16_t type, uint16_t length)
799     : type_(type), length_(length) {}
800 
ConsumePadding(ByteBufferReader * buf) const801 void StunAttribute::ConsumePadding(ByteBufferReader* buf) const {
802   int remainder = length_ % 4;
803   if (remainder > 0) {
804     buf->Consume(4 - remainder);
805   }
806 }
807 
WritePadding(ByteBufferWriter * buf) const808 void StunAttribute::WritePadding(ByteBufferWriter* buf) const {
809   int remainder = length_ % 4;
810   if (remainder > 0) {
811     char zeroes[4] = {0};
812     buf->WriteBytes(zeroes, 4 - remainder);
813   }
814 }
815 
Create(StunAttributeValueType value_type,uint16_t type,uint16_t length,StunMessage * owner)816 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type,
817                                      uint16_t type,
818                                      uint16_t length,
819                                      StunMessage* owner) {
820   switch (value_type) {
821     case STUN_VALUE_ADDRESS:
822       return new StunAddressAttribute(type, length);
823     case STUN_VALUE_XOR_ADDRESS:
824       return new StunXorAddressAttribute(type, length, owner);
825     case STUN_VALUE_UINT32:
826       return new StunUInt32Attribute(type);
827     case STUN_VALUE_UINT64:
828       return new StunUInt64Attribute(type);
829     case STUN_VALUE_BYTE_STRING:
830       return new StunByteStringAttribute(type, length);
831     case STUN_VALUE_ERROR_CODE:
832       return new StunErrorCodeAttribute(type, length);
833     case STUN_VALUE_UINT16_LIST:
834       return new StunUInt16ListAttribute(type, length);
835     default:
836       return NULL;
837   }
838 }
839 
CreateAddress(uint16_t type)840 std::unique_ptr<StunAddressAttribute> StunAttribute::CreateAddress(
841     uint16_t type) {
842   return std::make_unique<StunAddressAttribute>(type, 0);
843 }
844 
CreateXorAddress(uint16_t type)845 std::unique_ptr<StunXorAddressAttribute> StunAttribute::CreateXorAddress(
846     uint16_t type) {
847   return std::make_unique<StunXorAddressAttribute>(type, 0, nullptr);
848 }
849 
CreateUInt64(uint16_t type)850 std::unique_ptr<StunUInt64Attribute> StunAttribute::CreateUInt64(
851     uint16_t type) {
852   return std::make_unique<StunUInt64Attribute>(type);
853 }
854 
CreateUInt32(uint16_t type)855 std::unique_ptr<StunUInt32Attribute> StunAttribute::CreateUInt32(
856     uint16_t type) {
857   return std::make_unique<StunUInt32Attribute>(type);
858 }
859 
CreateByteString(uint16_t type)860 std::unique_ptr<StunByteStringAttribute> StunAttribute::CreateByteString(
861     uint16_t type) {
862   return std::make_unique<StunByteStringAttribute>(type, 0);
863 }
864 
CreateErrorCode()865 std::unique_ptr<StunErrorCodeAttribute> StunAttribute::CreateErrorCode() {
866   return std::make_unique<StunErrorCodeAttribute>(
867       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
868 }
869 
870 std::unique_ptr<StunUInt16ListAttribute>
CreateUInt16ListAttribute(uint16_t type)871 StunAttribute::CreateUInt16ListAttribute(uint16_t type) {
872   return std::make_unique<StunUInt16ListAttribute>(type, 0);
873 }
874 
875 std::unique_ptr<StunUInt16ListAttribute>
CreateUnknownAttributes()876 StunAttribute::CreateUnknownAttributes() {
877   return std::make_unique<StunUInt16ListAttribute>(STUN_ATTR_UNKNOWN_ATTRIBUTES,
878                                                    0);
879 }
880 
StunAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)881 StunAddressAttribute::StunAddressAttribute(uint16_t type,
882                                            const rtc::SocketAddress& addr)
883     : StunAttribute(type, 0) {
884   SetAddress(addr);
885 }
886 
StunAddressAttribute(uint16_t type,uint16_t length)887 StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length)
888     : StunAttribute(type, length) {}
889 
value_type() const890 StunAttributeValueType StunAddressAttribute::value_type() const {
891   return STUN_VALUE_ADDRESS;
892 }
893 
Read(ByteBufferReader * buf)894 bool StunAddressAttribute::Read(ByteBufferReader* buf) {
895   uint8_t dummy;
896   if (!buf->ReadUInt8(&dummy))
897     return false;
898 
899   uint8_t stun_family;
900   if (!buf->ReadUInt8(&stun_family)) {
901     return false;
902   }
903   uint16_t port;
904   if (!buf->ReadUInt16(&port))
905     return false;
906   if (stun_family == STUN_ADDRESS_IPV4) {
907     in_addr v4addr;
908     if (length() != SIZE_IP4) {
909       return false;
910     }
911     if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) {
912       return false;
913     }
914     rtc::IPAddress ipaddr(v4addr);
915     SetAddress(rtc::SocketAddress(ipaddr, port));
916   } else if (stun_family == STUN_ADDRESS_IPV6) {
917     in6_addr v6addr;
918     if (length() != SIZE_IP6) {
919       return false;
920     }
921     if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) {
922       return false;
923     }
924     rtc::IPAddress ipaddr(v6addr);
925     SetAddress(rtc::SocketAddress(ipaddr, port));
926   } else {
927     return false;
928   }
929   return true;
930 }
931 
Write(ByteBufferWriter * buf) const932 bool StunAddressAttribute::Write(ByteBufferWriter* buf) const {
933   StunAddressFamily address_family = family();
934   if (address_family == STUN_ADDRESS_UNDEF) {
935     RTC_LOG(LS_ERROR) << "Error writing address attribute: unknown family.";
936     return false;
937   }
938   buf->WriteUInt8(0);
939   buf->WriteUInt8(address_family);
940   buf->WriteUInt16(address_.port());
941   switch (address_.family()) {
942     case AF_INET: {
943       in_addr v4addr = address_.ipaddr().ipv4_address();
944       buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr));
945       break;
946     }
947     case AF_INET6: {
948       in6_addr v6addr = address_.ipaddr().ipv6_address();
949       buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr));
950       break;
951     }
952   }
953   return true;
954 }
955 
StunXorAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)956 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
957                                                  const rtc::SocketAddress& addr)
958     : StunAddressAttribute(type, addr), owner_(NULL) {}
959 
StunXorAddressAttribute(uint16_t type,uint16_t length,StunMessage * owner)960 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
961                                                  uint16_t length,
962                                                  StunMessage* owner)
963     : StunAddressAttribute(type, length), owner_(owner) {}
964 
value_type() const965 StunAttributeValueType StunXorAddressAttribute::value_type() const {
966   return STUN_VALUE_XOR_ADDRESS;
967 }
968 
SetOwner(StunMessage * owner)969 void StunXorAddressAttribute::SetOwner(StunMessage* owner) {
970   owner_ = owner;
971 }
972 
GetXoredIP() const973 rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const {
974   if (owner_) {
975     rtc::IPAddress ip = ipaddr();
976     switch (ip.family()) {
977       case AF_INET: {
978         in_addr v4addr = ip.ipv4_address();
979         v4addr.s_addr =
980             (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie));
981         return rtc::IPAddress(v4addr);
982       }
983       case AF_INET6: {
984         in6_addr v6addr = ip.ipv6_address();
985         const std::string& transaction_id = owner_->transaction_id();
986         if (transaction_id.length() == kStunTransactionIdLength) {
987           uint32_t transactionid_as_ints[3];
988           memcpy(&transactionid_as_ints[0], transaction_id.c_str(),
989                  transaction_id.length());
990           uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
991           // Transaction ID is in network byte order, but magic cookie
992           // is stored in host byte order.
993           ip_as_ints[0] =
994               (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie));
995           ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]);
996           ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]);
997           ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]);
998           return rtc::IPAddress(v6addr);
999         }
1000         break;
1001       }
1002     }
1003   }
1004   // Invalid ip family or transaction ID, or missing owner.
1005   // Return an AF_UNSPEC address.
1006   return rtc::IPAddress();
1007 }
1008 
Read(ByteBufferReader * buf)1009 bool StunXorAddressAttribute::Read(ByteBufferReader* buf) {
1010   if (!StunAddressAttribute::Read(buf))
1011     return false;
1012   uint16_t xoredport = port() ^ (kStunMagicCookie >> 16);
1013   rtc::IPAddress xored_ip = GetXoredIP();
1014   SetAddress(rtc::SocketAddress(xored_ip, xoredport));
1015   return true;
1016 }
1017 
Write(ByteBufferWriter * buf) const1018 bool StunXorAddressAttribute::Write(ByteBufferWriter* buf) const {
1019   StunAddressFamily address_family = family();
1020   if (address_family == STUN_ADDRESS_UNDEF) {
1021     RTC_LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
1022     return false;
1023   }
1024   rtc::IPAddress xored_ip = GetXoredIP();
1025   if (xored_ip.family() == AF_UNSPEC) {
1026     return false;
1027   }
1028   buf->WriteUInt8(0);
1029   buf->WriteUInt8(family());
1030   buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16));
1031   switch (xored_ip.family()) {
1032     case AF_INET: {
1033       in_addr v4addr = xored_ip.ipv4_address();
1034       buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr));
1035       break;
1036     }
1037     case AF_INET6: {
1038       in6_addr v6addr = xored_ip.ipv6_address();
1039       buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr));
1040       break;
1041     }
1042   }
1043   return true;
1044 }
1045 
StunUInt32Attribute(uint16_t type,uint32_t value)1046 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value)
1047     : StunAttribute(type, SIZE), bits_(value) {}
1048 
StunUInt32Attribute(uint16_t type)1049 StunUInt32Attribute::StunUInt32Attribute(uint16_t type)
1050     : StunAttribute(type, SIZE), bits_(0) {}
1051 
value_type() const1052 StunAttributeValueType StunUInt32Attribute::value_type() const {
1053   return STUN_VALUE_UINT32;
1054 }
1055 
GetBit(size_t index) const1056 bool StunUInt32Attribute::GetBit(size_t index) const {
1057   RTC_DCHECK(index < 32);
1058   return static_cast<bool>((bits_ >> index) & 0x1);
1059 }
1060 
SetBit(size_t index,bool value)1061 void StunUInt32Attribute::SetBit(size_t index, bool value) {
1062   RTC_DCHECK(index < 32);
1063   bits_ &= ~(1 << index);
1064   bits_ |= value ? (1 << index) : 0;
1065 }
1066 
Read(ByteBufferReader * buf)1067 bool StunUInt32Attribute::Read(ByteBufferReader* buf) {
1068   if (length() != SIZE || !buf->ReadUInt32(&bits_))
1069     return false;
1070   return true;
1071 }
1072 
Write(ByteBufferWriter * buf) const1073 bool StunUInt32Attribute::Write(ByteBufferWriter* buf) const {
1074   buf->WriteUInt32(bits_);
1075   return true;
1076 }
1077 
StunUInt64Attribute(uint16_t type,uint64_t value)1078 StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value)
1079     : StunAttribute(type, SIZE), bits_(value) {}
1080 
StunUInt64Attribute(uint16_t type)1081 StunUInt64Attribute::StunUInt64Attribute(uint16_t type)
1082     : StunAttribute(type, SIZE), bits_(0) {}
1083 
value_type() const1084 StunAttributeValueType StunUInt64Attribute::value_type() const {
1085   return STUN_VALUE_UINT64;
1086 }
1087 
Read(ByteBufferReader * buf)1088 bool StunUInt64Attribute::Read(ByteBufferReader* buf) {
1089   if (length() != SIZE || !buf->ReadUInt64(&bits_))
1090     return false;
1091   return true;
1092 }
1093 
Write(ByteBufferWriter * buf) const1094 bool StunUInt64Attribute::Write(ByteBufferWriter* buf) const {
1095   buf->WriteUInt64(bits_);
1096   return true;
1097 }
1098 
StunByteStringAttribute(uint16_t type)1099 StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
1100     : StunAttribute(type, 0), bytes_(NULL) {}
1101 
StunByteStringAttribute(uint16_t type,absl::string_view str)1102 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
1103                                                  absl::string_view str)
1104     : StunAttribute(type, 0), bytes_(NULL) {
1105   CopyBytes(str);
1106 }
1107 
StunByteStringAttribute(uint16_t type,const void * bytes,size_t length)1108 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
1109                                                  const void* bytes,
1110                                                  size_t length)
1111     : StunAttribute(type, 0), bytes_(NULL) {
1112   CopyBytes(bytes, length);
1113 }
1114 
StunByteStringAttribute(uint16_t type,uint16_t length)1115 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length)
1116     : StunAttribute(type, length), bytes_(NULL) {}
1117 
~StunByteStringAttribute()1118 StunByteStringAttribute::~StunByteStringAttribute() {
1119   delete[] bytes_;
1120 }
1121 
value_type() const1122 StunAttributeValueType StunByteStringAttribute::value_type() const {
1123   return STUN_VALUE_BYTE_STRING;
1124 }
1125 
CopyBytes(absl::string_view bytes)1126 void StunByteStringAttribute::CopyBytes(absl::string_view bytes) {
1127   char* new_bytes = new char[bytes.size()];
1128   memcpy(new_bytes, bytes.data(), bytes.size());
1129   SetBytes(new_bytes, bytes.size());
1130 }
1131 
CopyBytes(const void * bytes,size_t length)1132 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {
1133   char* new_bytes = new char[length];
1134   memcpy(new_bytes, bytes, length);
1135   SetBytes(new_bytes, length);
1136 }
1137 
GetByte(size_t index) const1138 uint8_t StunByteStringAttribute::GetByte(size_t index) const {
1139   RTC_DCHECK(bytes_ != NULL);
1140   RTC_DCHECK(index < length());
1141   return static_cast<uint8_t>(bytes_[index]);
1142 }
1143 
SetByte(size_t index,uint8_t value)1144 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) {
1145   RTC_DCHECK(bytes_ != NULL);
1146   RTC_DCHECK(index < length());
1147   bytes_[index] = value;
1148 }
1149 
Read(ByteBufferReader * buf)1150 bool StunByteStringAttribute::Read(ByteBufferReader* buf) {
1151   bytes_ = new char[length()];
1152   if (!buf->ReadBytes(bytes_, length())) {
1153     return false;
1154   }
1155 
1156   ConsumePadding(buf);
1157   return true;
1158 }
1159 
Write(ByteBufferWriter * buf) const1160 bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const {
1161   // Check that length is legal according to specs
1162   if (!LengthValid(type(), length())) {
1163     return false;
1164   }
1165   buf->WriteBytes(bytes_, length());
1166   WritePadding(buf);
1167   return true;
1168 }
1169 
SetBytes(char * bytes,size_t length)1170 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
1171   delete[] bytes_;
1172   bytes_ = bytes;
1173   SetLength(static_cast<uint16_t>(length));
1174 }
1175 
1176 const uint16_t StunErrorCodeAttribute::MIN_SIZE = 4;
1177 
StunErrorCodeAttribute(uint16_t type,int code,const std::string & reason)1178 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type,
1179                                                int code,
1180                                                const std::string& reason)
1181     : StunAttribute(type, 0) {
1182   SetCode(code);
1183   SetReason(reason);
1184 }
1185 
StunErrorCodeAttribute(uint16_t type,uint16_t length)1186 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length)
1187     : StunAttribute(type, length), class_(0), number_(0) {}
1188 
~StunErrorCodeAttribute()1189 StunErrorCodeAttribute::~StunErrorCodeAttribute() {}
1190 
value_type() const1191 StunAttributeValueType StunErrorCodeAttribute::value_type() const {
1192   return STUN_VALUE_ERROR_CODE;
1193 }
1194 
code() const1195 int StunErrorCodeAttribute::code() const {
1196   return class_ * 100 + number_;
1197 }
1198 
SetCode(int code)1199 void StunErrorCodeAttribute::SetCode(int code) {
1200   class_ = static_cast<uint8_t>(code / 100);
1201   number_ = static_cast<uint8_t>(code % 100);
1202 }
1203 
SetReason(const std::string & reason)1204 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
1205   SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size()));
1206   reason_ = reason;
1207 }
1208 
Read(ByteBufferReader * buf)1209 bool StunErrorCodeAttribute::Read(ByteBufferReader* buf) {
1210   uint32_t val;
1211   if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
1212     return false;
1213 
1214   if ((val >> 11) != 0)
1215     RTC_LOG(LS_ERROR) << "error-code bits not zero";
1216 
1217   class_ = ((val >> 8) & 0x7);
1218   number_ = (val & 0xff);
1219 
1220   if (!buf->ReadString(&reason_, length() - 4))
1221     return false;
1222 
1223   ConsumePadding(buf);
1224   return true;
1225 }
1226 
Write(ByteBufferWriter * buf) const1227 bool StunErrorCodeAttribute::Write(ByteBufferWriter* buf) const {
1228   buf->WriteUInt32(class_ << 8 | number_);
1229   buf->WriteString(reason_);
1230   WritePadding(buf);
1231   return true;
1232 }
1233 
StunUInt16ListAttribute(uint16_t type,uint16_t length)1234 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length)
1235     : StunAttribute(type, length) {
1236   attr_types_ = new std::vector<uint16_t>();
1237 }
1238 
~StunUInt16ListAttribute()1239 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
1240   delete attr_types_;
1241 }
1242 
value_type() const1243 StunAttributeValueType StunUInt16ListAttribute::value_type() const {
1244   return STUN_VALUE_UINT16_LIST;
1245 }
1246 
Size() const1247 size_t StunUInt16ListAttribute::Size() const {
1248   return attr_types_->size();
1249 }
1250 
GetType(int index) const1251 uint16_t StunUInt16ListAttribute::GetType(int index) const {
1252   return (*attr_types_)[index];
1253 }
1254 
SetType(int index,uint16_t value)1255 void StunUInt16ListAttribute::SetType(int index, uint16_t value) {
1256   (*attr_types_)[index] = value;
1257 }
1258 
AddType(uint16_t value)1259 void StunUInt16ListAttribute::AddType(uint16_t value) {
1260   attr_types_->push_back(value);
1261   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1262 }
1263 
AddTypeAtIndex(uint16_t index,uint16_t value)1264 void StunUInt16ListAttribute::AddTypeAtIndex(uint16_t index, uint16_t value) {
1265   if (attr_types_->size() < static_cast<size_t>(index + 1)) {
1266     attr_types_->resize(index + 1);
1267   }
1268   (*attr_types_)[index] = value;
1269   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1270 }
1271 
Read(ByteBufferReader * buf)1272 bool StunUInt16ListAttribute::Read(ByteBufferReader* buf) {
1273   if (length() % 2) {
1274     return false;
1275   }
1276 
1277   for (size_t i = 0; i < length() / 2; i++) {
1278     uint16_t attr;
1279     if (!buf->ReadUInt16(&attr))
1280       return false;
1281     attr_types_->push_back(attr);
1282   }
1283   // Padding of these attributes is done in RFC 5389 style. This is
1284   // slightly different from RFC3489, but it shouldn't be important.
1285   // RFC3489 pads out to a 32 bit boundary by duplicating one of the
1286   // entries in the list (not necessarily the last one - it's unspecified).
1287   // RFC5389 pads on the end, and the bytes are always ignored.
1288   ConsumePadding(buf);
1289   return true;
1290 }
1291 
Write(ByteBufferWriter * buf) const1292 bool StunUInt16ListAttribute::Write(ByteBufferWriter* buf) const {
1293   for (size_t i = 0; i < attr_types_->size(); ++i) {
1294     buf->WriteUInt16((*attr_types_)[i]);
1295   }
1296   WritePadding(buf);
1297   return true;
1298 }
1299 
StunMethodToString(int msg_type)1300 std::string StunMethodToString(int msg_type) {
1301   switch (msg_type) {
1302     case STUN_BINDING_REQUEST:
1303       return "STUN BINDING request";
1304     case STUN_BINDING_INDICATION:
1305       return "STUN BINDING indication";
1306     case STUN_BINDING_RESPONSE:
1307       return "STUN BINDING response";
1308     case STUN_BINDING_ERROR_RESPONSE:
1309       return "STUN BINDING error response";
1310     case GOOG_PING_REQUEST:
1311       return "GOOG PING request";
1312     case GOOG_PING_RESPONSE:
1313       return "GOOG PING response";
1314     case GOOG_PING_ERROR_RESPONSE:
1315       return "GOOG PING error response";
1316     case STUN_ALLOCATE_REQUEST:
1317       return "TURN ALLOCATE request";
1318     case STUN_ALLOCATE_RESPONSE:
1319       return "TURN ALLOCATE response";
1320     case STUN_ALLOCATE_ERROR_RESPONSE:
1321       return "TURN ALLOCATE error response";
1322     case TURN_REFRESH_REQUEST:
1323       return "TURN REFRESH request";
1324     case TURN_REFRESH_RESPONSE:
1325       return "TURN REFRESH response";
1326     case TURN_REFRESH_ERROR_RESPONSE:
1327       return "TURN REFRESH error response";
1328     case TURN_SEND_INDICATION:
1329       return "TURN SEND INDICATION";
1330     case TURN_DATA_INDICATION:
1331       return "TURN DATA INDICATION";
1332     case TURN_CREATE_PERMISSION_REQUEST:
1333       return "TURN CREATE PERMISSION request";
1334     case TURN_CREATE_PERMISSION_RESPONSE:
1335       return "TURN CREATE PERMISSION response";
1336     case TURN_CREATE_PERMISSION_ERROR_RESPONSE:
1337       return "TURN CREATE PERMISSION error response";
1338     case TURN_CHANNEL_BIND_REQUEST:
1339       return "TURN CHANNEL BIND request";
1340     case TURN_CHANNEL_BIND_RESPONSE:
1341       return "TURN CHANNEL BIND response";
1342     case TURN_CHANNEL_BIND_ERROR_RESPONSE:
1343       return "TURN CHANNEL BIND error response";
1344     default:
1345       return "UNKNOWN<" + std::to_string(msg_type) + ">";
1346   }
1347 }
1348 
GetStunSuccessResponseType(int req_type)1349 int GetStunSuccessResponseType(int req_type) {
1350   return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
1351 }
1352 
GetStunErrorResponseType(int req_type)1353 int GetStunErrorResponseType(int req_type) {
1354   return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
1355 }
1356 
IsStunRequestType(int msg_type)1357 bool IsStunRequestType(int msg_type) {
1358   return ((msg_type & kStunTypeMask) == 0x000);
1359 }
1360 
IsStunIndicationType(int msg_type)1361 bool IsStunIndicationType(int msg_type) {
1362   return ((msg_type & kStunTypeMask) == 0x010);
1363 }
1364 
IsStunSuccessResponseType(int msg_type)1365 bool IsStunSuccessResponseType(int msg_type) {
1366   return ((msg_type & kStunTypeMask) == 0x100);
1367 }
1368 
IsStunErrorResponseType(int msg_type)1369 bool IsStunErrorResponseType(int msg_type) {
1370   return ((msg_type & kStunTypeMask) == 0x110);
1371 }
1372 
ComputeStunCredentialHash(const std::string & username,const std::string & realm,const std::string & password,std::string * hash)1373 bool ComputeStunCredentialHash(const std::string& username,
1374                                const std::string& realm,
1375                                const std::string& password,
1376                                std::string* hash) {
1377   // http://tools.ietf.org/html/rfc5389#section-15.4
1378   // long-term credentials will be calculated using the key and key is
1379   // key = MD5(username ":" realm ":" SASLprep(password))
1380   std::string input = username;
1381   input += ':';
1382   input += realm;
1383   input += ':';
1384   input += password;
1385 
1386   char digest[rtc::MessageDigest::kMaxSize];
1387   size_t size = rtc::ComputeDigest(rtc::DIGEST_MD5, input.c_str(), input.size(),
1388                                    digest, sizeof(digest));
1389   if (size == 0) {
1390     return false;
1391   }
1392 
1393   *hash = std::string(digest, size);
1394   return true;
1395 }
1396 
CopyStunAttribute(const StunAttribute & attribute,rtc::ByteBufferWriter * tmp_buffer_ptr)1397 std::unique_ptr<StunAttribute> CopyStunAttribute(
1398     const StunAttribute& attribute,
1399     rtc::ByteBufferWriter* tmp_buffer_ptr) {
1400   ByteBufferWriter tmpBuffer;
1401   if (tmp_buffer_ptr == nullptr) {
1402     tmp_buffer_ptr = &tmpBuffer;
1403   }
1404 
1405   std::unique_ptr<StunAttribute> copy(StunAttribute::Create(
1406       attribute.value_type(), attribute.type(),
1407       static_cast<uint16_t>(attribute.length()), nullptr));
1408 
1409   if (!copy) {
1410     return nullptr;
1411   }
1412   tmp_buffer_ptr->Clear();
1413   if (!attribute.Write(tmp_buffer_ptr)) {
1414     return nullptr;
1415   }
1416   rtc::ByteBufferReader reader(*tmp_buffer_ptr);
1417   if (!copy->Read(&reader)) {
1418     return nullptr;
1419   }
1420 
1421   return copy;
1422 }
1423 
GetAttributeValueType(int type) const1424 StunAttributeValueType RelayMessage::GetAttributeValueType(int type) const {
1425   switch (type) {
1426     case STUN_ATTR_LIFETIME:
1427       return STUN_VALUE_UINT32;
1428     case STUN_ATTR_MAGIC_COOKIE:
1429       return STUN_VALUE_BYTE_STRING;
1430     case STUN_ATTR_BANDWIDTH:
1431       return STUN_VALUE_UINT32;
1432     case STUN_ATTR_DESTINATION_ADDRESS:
1433       return STUN_VALUE_ADDRESS;
1434     case STUN_ATTR_SOURCE_ADDRESS2:
1435       return STUN_VALUE_ADDRESS;
1436     case STUN_ATTR_DATA:
1437       return STUN_VALUE_BYTE_STRING;
1438     case STUN_ATTR_OPTIONS:
1439       return STUN_VALUE_UINT32;
1440     default:
1441       return StunMessage::GetAttributeValueType(type);
1442   }
1443 }
1444 
CreateNew() const1445 StunMessage* RelayMessage::CreateNew() const {
1446   return new RelayMessage();
1447 }
1448 
GetAttributeValueType(int type) const1449 StunAttributeValueType TurnMessage::GetAttributeValueType(int type) const {
1450   switch (type) {
1451     case STUN_ATTR_CHANNEL_NUMBER:
1452       return STUN_VALUE_UINT32;
1453     case STUN_ATTR_TURN_LIFETIME:
1454       return STUN_VALUE_UINT32;
1455     case STUN_ATTR_XOR_PEER_ADDRESS:
1456       return STUN_VALUE_XOR_ADDRESS;
1457     case STUN_ATTR_DATA:
1458       return STUN_VALUE_BYTE_STRING;
1459     case STUN_ATTR_XOR_RELAYED_ADDRESS:
1460       return STUN_VALUE_XOR_ADDRESS;
1461     case STUN_ATTR_EVEN_PORT:
1462       return STUN_VALUE_BYTE_STRING;
1463     case STUN_ATTR_REQUESTED_TRANSPORT:
1464       return STUN_VALUE_UINT32;
1465     case STUN_ATTR_DONT_FRAGMENT:
1466       return STUN_VALUE_BYTE_STRING;
1467     case STUN_ATTR_RESERVATION_TOKEN:
1468       return STUN_VALUE_BYTE_STRING;
1469     default:
1470       return StunMessage::GetAttributeValueType(type);
1471   }
1472 }
1473 
CreateNew() const1474 StunMessage* TurnMessage::CreateNew() const {
1475   return new TurnMessage();
1476 }
1477 
GetAttributeValueType(int type) const1478 StunAttributeValueType IceMessage::GetAttributeValueType(int type) const {
1479   switch (type) {
1480     case STUN_ATTR_PRIORITY:
1481     case STUN_ATTR_GOOG_NETWORK_INFO:
1482     case STUN_ATTR_NOMINATION:
1483       return STUN_VALUE_UINT32;
1484     case STUN_ATTR_USE_CANDIDATE:
1485       return STUN_VALUE_BYTE_STRING;
1486     case STUN_ATTR_ICE_CONTROLLED:
1487       return STUN_VALUE_UINT64;
1488     case STUN_ATTR_ICE_CONTROLLING:
1489       return STUN_VALUE_UINT64;
1490     default:
1491       return StunMessage::GetAttributeValueType(type);
1492   }
1493 }
1494 
CreateNew() const1495 StunMessage* IceMessage::CreateNew() const {
1496   return new IceMessage();
1497 }
1498 
Clone() const1499 std::unique_ptr<StunMessage> StunMessage::Clone() const {
1500   std::unique_ptr<StunMessage> copy(CreateNew());
1501   if (!copy) {
1502     return nullptr;
1503   }
1504   rtc::ByteBufferWriter buf;
1505   if (!Write(&buf)) {
1506     return nullptr;
1507   }
1508   rtc::ByteBufferReader reader(buf);
1509   if (!copy->Read(&reader)) {
1510     return nullptr;
1511   }
1512   return copy;
1513 }
1514 
1515 }  // namespace cricket
1516