• 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 <memory>
17 #include <utility>
18 
19 #include "rtc_base/byte_order.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/crc32.h"
22 #include "rtc_base/logging.h"
23 #include "rtc_base/message_digest.h"
24 
25 using rtc::ByteBufferReader;
26 using rtc::ByteBufferWriter;
27 
28 namespace {
29 
ReduceTransactionId(const std::string & transaction_id)30 uint32_t ReduceTransactionId(const std::string& transaction_id) {
31   RTC_DCHECK(transaction_id.length() == cricket::kStunTransactionIdLength ||
32              transaction_id.length() ==
33                  cricket::kStunLegacyTransactionIdLength);
34   ByteBufferReader reader(transaction_id.c_str(), transaction_id.length());
35   uint32_t result = 0;
36   uint32_t next;
37   while (reader.ReadUInt32(&next)) {
38     result ^= next;
39   }
40   return result;
41 }
42 
43 }  // namespace
44 
45 namespace cricket {
46 
47 const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
48 const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
49 const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized";
50 const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[] = "Unknown Attribute";
51 const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden";
52 const char STUN_ERROR_REASON_STALE_CREDENTIALS[] = "Stale Credentials";
53 const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch";
54 const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce";
55 const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials";
56 const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol";
57 const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict";
58 const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error";
59 
60 const char TURN_MAGIC_COOKIE_VALUE[] = {'\x72', '\xC6', '\x4B', '\xC6'};
61 const char EMPTY_TRANSACTION_ID[] = "0000000000000000";
62 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E;
63 const int SERVER_NOT_REACHABLE_ERROR = 701;
64 
65 // StunMessage
66 
StunMessage()67 StunMessage::StunMessage()
68     : type_(0),
69       length_(0),
70       transaction_id_(EMPTY_TRANSACTION_ID),
71       stun_magic_cookie_(kStunMagicCookie) {
72   RTC_DCHECK(IsValidTransactionId(transaction_id_));
73 }
74 
75 StunMessage::~StunMessage() = default;
76 
IsLegacy() const77 bool StunMessage::IsLegacy() const {
78   if (transaction_id_.size() == kStunLegacyTransactionIdLength)
79     return true;
80   RTC_DCHECK(transaction_id_.size() == kStunTransactionIdLength);
81   return false;
82 }
83 
SetTransactionID(const std::string & str)84 bool StunMessage::SetTransactionID(const std::string& str) {
85   if (!IsValidTransactionId(str)) {
86     return false;
87   }
88   transaction_id_ = str;
89   reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
90   return true;
91 }
92 
DesignatedExpertRange(int attr_type)93 static bool DesignatedExpertRange(int attr_type) {
94   return (attr_type >= 0x4000 && attr_type <= 0x7FFF) ||
95          (attr_type >= 0xC000 && attr_type <= 0xFFFF);
96 }
97 
AddAttribute(std::unique_ptr<StunAttribute> attr)98 void StunMessage::AddAttribute(std::unique_ptr<StunAttribute> attr) {
99   // Fail any attributes that aren't valid for this type of message,
100   // but allow any type for the range that in the RFC is reserved for
101   // the "designated experts".
102   if (!DesignatedExpertRange(attr->type())) {
103     RTC_DCHECK_EQ(attr->value_type(), GetAttributeValueType(attr->type()));
104   }
105 
106   attr->SetOwner(this);
107   size_t attr_length = attr->length();
108   if (attr_length % 4 != 0) {
109     attr_length += (4 - (attr_length % 4));
110   }
111   length_ += static_cast<uint16_t>(attr_length + 4);
112 
113   attrs_.push_back(std::move(attr));
114 }
115 
RemoveAttribute(int type)116 std::unique_ptr<StunAttribute> StunMessage::RemoveAttribute(int type) {
117   std::unique_ptr<StunAttribute> attribute;
118   for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
119     if ((*it)->type() == type) {
120       attribute = std::move(*it);
121       attrs_.erase(std::next(it).base());
122       break;
123     }
124   }
125   if (attribute) {
126     attribute->SetOwner(nullptr);
127     size_t attr_length = attribute->length();
128     if (attr_length % 4 != 0) {
129       attr_length += (4 - (attr_length % 4));
130     }
131     length_ -= static_cast<uint16_t>(attr_length + 4);
132   }
133   return attribute;
134 }
135 
ClearAttributes()136 void StunMessage::ClearAttributes() {
137   for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
138     (*it)->SetOwner(nullptr);
139   }
140   attrs_.clear();
141   length_ = 0;
142 }
143 
GetNonComprehendedAttributes() const144 std::vector<uint16_t> StunMessage::GetNonComprehendedAttributes() const {
145   std::vector<uint16_t> unknown_attributes;
146   for (auto& attr : attrs_) {
147     // "comprehension-required" range is 0x0000-0x7FFF.
148     if (attr->type() >= 0x0000 && attr->type() <= 0x7FFF &&
149         GetAttributeValueType(attr->type()) == STUN_VALUE_UNKNOWN) {
150       unknown_attributes.push_back(attr->type());
151     }
152   }
153   return unknown_attributes;
154 }
155 
GetAddress(int type) const156 const StunAddressAttribute* StunMessage::GetAddress(int type) const {
157   switch (type) {
158     case STUN_ATTR_MAPPED_ADDRESS: {
159       // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is
160       // missing.
161       const StunAttribute* mapped_address =
162           GetAttribute(STUN_ATTR_MAPPED_ADDRESS);
163       if (!mapped_address)
164         mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS);
165       return reinterpret_cast<const StunAddressAttribute*>(mapped_address);
166     }
167 
168     default:
169       return static_cast<const StunAddressAttribute*>(GetAttribute(type));
170   }
171 }
172 
GetUInt32(int type) const173 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
174   return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
175 }
176 
GetUInt64(int type) const177 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
178   return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
179 }
180 
GetByteString(int type) const181 const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
182   return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
183 }
184 
GetUInt16List(int type) const185 const StunUInt16ListAttribute* StunMessage::GetUInt16List(int type) const {
186   return static_cast<const StunUInt16ListAttribute*>(GetAttribute(type));
187 }
188 
GetErrorCode() const189 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
190   return static_cast<const StunErrorCodeAttribute*>(
191       GetAttribute(STUN_ATTR_ERROR_CODE));
192 }
193 
GetErrorCodeValue() const194 int StunMessage::GetErrorCodeValue() const {
195   const StunErrorCodeAttribute* error_attribute = GetErrorCode();
196   return error_attribute ? error_attribute->code() : STUN_ERROR_GLOBAL_FAILURE;
197 }
198 
GetUnknownAttributes() const199 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
200   return static_cast<const StunUInt16ListAttribute*>(
201       GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
202 }
203 
ValidateMessageIntegrity(const char * data,size_t size,const std::string & password)204 bool StunMessage::ValidateMessageIntegrity(const char* data,
205                                            size_t size,
206                                            const std::string& password) {
207   return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
208                                         kStunMessageIntegritySize, data, size,
209                                         password);
210 }
211 
ValidateMessageIntegrity32(const char * data,size_t size,const std::string & password)212 bool StunMessage::ValidateMessageIntegrity32(const char* data,
213                                              size_t size,
214                                              const std::string& password) {
215   return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
216                                         kStunMessageIntegrity32Size, data, size,
217                                         password);
218 }
219 
220 // Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the
221 // 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)222 bool StunMessage::ValidateMessageIntegrityOfType(int mi_attr_type,
223                                                  size_t mi_attr_size,
224                                                  const char* data,
225                                                  size_t size,
226                                                  const std::string& password) {
227   RTC_DCHECK(mi_attr_size <= kStunMessageIntegritySize);
228 
229   // Verifying the size of the message.
230   if ((size % 4) != 0 || size < kStunHeaderSize) {
231     return false;
232   }
233 
234   // Getting the message length from the STUN header.
235   uint16_t msg_length = rtc::GetBE16(&data[2]);
236   if (size != (msg_length + kStunHeaderSize)) {
237     return false;
238   }
239 
240   // Finding Message Integrity attribute in stun message.
241   size_t current_pos = kStunHeaderSize;
242   bool has_message_integrity_attr = false;
243   while (current_pos + 4 <= size) {
244     uint16_t attr_type, attr_length;
245     // Getting attribute type and length.
246     attr_type = rtc::GetBE16(&data[current_pos]);
247     attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]);
248 
249     // If M-I, sanity check it, and break out.
250     if (attr_type == mi_attr_type) {
251       if (attr_length != mi_attr_size ||
252           current_pos + sizeof(attr_type) + sizeof(attr_length) + attr_length >
253               size) {
254         return false;
255       }
256       has_message_integrity_attr = true;
257       break;
258     }
259 
260     // Otherwise, skip to the next attribute.
261     current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length;
262     if ((attr_length % 4) != 0) {
263       current_pos += (4 - (attr_length % 4));
264     }
265   }
266 
267   if (!has_message_integrity_attr) {
268     return false;
269   }
270 
271   // Getting length of the message to calculate Message Integrity.
272   size_t mi_pos = current_pos;
273   std::unique_ptr<char[]> temp_data(new char[current_pos]);
274   memcpy(temp_data.get(), data, current_pos);
275   if (size > mi_pos + kStunAttributeHeaderSize + mi_attr_size) {
276     // Stun message has other attributes after message integrity.
277     // Adjust the length parameter in stun message to calculate HMAC.
278     size_t extra_offset =
279         size - (mi_pos + kStunAttributeHeaderSize + mi_attr_size);
280     size_t new_adjusted_len = size - extra_offset - kStunHeaderSize;
281 
282     // Writing new length of the STUN message @ Message Length in temp buffer.
283     //      0                   1                   2                   3
284     //      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
285     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
286     //     |0 0|     STUN Message Type     |         Message Length        |
287     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
288     rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len));
289   }
290 
291   char hmac[kStunMessageIntegritySize];
292   size_t ret =
293       rtc::ComputeHmac(rtc::DIGEST_SHA_1, password.c_str(), password.size(),
294                        temp_data.get(), mi_pos, hmac, sizeof(hmac));
295   RTC_DCHECK(ret == sizeof(hmac));
296   if (ret != sizeof(hmac)) {
297     return false;
298   }
299 
300   // Comparing the calculated HMAC with the one present in the message.
301   return memcmp(data + current_pos + kStunAttributeHeaderSize, hmac,
302                 mi_attr_size) == 0;
303 }
304 
AddMessageIntegrity(const std::string & password)305 bool StunMessage::AddMessageIntegrity(const std::string& password) {
306   return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
307                                    kStunMessageIntegritySize, password.c_str(),
308                                    password.size());
309 }
310 
AddMessageIntegrity(const char * key,size_t keylen)311 bool StunMessage::AddMessageIntegrity(const char* key, size_t keylen) {
312   return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
313                                    kStunMessageIntegritySize, key, keylen);
314 }
315 
AddMessageIntegrity32(absl::string_view password)316 bool StunMessage::AddMessageIntegrity32(absl::string_view password) {
317   return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
318                                    kStunMessageIntegrity32Size, password.data(),
319                                    password.length());
320 }
321 
AddMessageIntegrityOfType(int attr_type,size_t attr_size,const char * key,size_t keylen)322 bool StunMessage::AddMessageIntegrityOfType(int attr_type,
323                                             size_t attr_size,
324                                             const char* key,
325                                             size_t keylen) {
326   // Add the attribute with a dummy value. Since this is a known attribute, it
327   // can't fail.
328   RTC_DCHECK(attr_size <= kStunMessageIntegritySize);
329   auto msg_integrity_attr_ptr = std::make_unique<StunByteStringAttribute>(
330       attr_type, std::string(attr_size, '0'));
331   auto* msg_integrity_attr = msg_integrity_attr_ptr.get();
332   AddAttribute(std::move(msg_integrity_attr_ptr));
333 
334   // Calculate the HMAC for the message.
335   ByteBufferWriter buf;
336   if (!Write(&buf))
337     return false;
338 
339   int msg_len_for_hmac = static_cast<int>(
340       buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
341   char hmac[kStunMessageIntegritySize];
342   size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, key, keylen, buf.Data(),
343                                 msg_len_for_hmac, hmac, sizeof(hmac));
344   RTC_DCHECK(ret == sizeof(hmac));
345   if (ret != sizeof(hmac)) {
346     RTC_LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity "
347                          "has dummy value.";
348     return false;
349   }
350 
351   // Insert correct HMAC into the attribute.
352   msg_integrity_attr->CopyBytes(hmac, attr_size);
353   return true;
354 }
355 
356 // Verifies a message is in fact a STUN message, by performing the checks
357 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed
358 // in section 15.5.
ValidateFingerprint(const char * data,size_t size)359 bool StunMessage::ValidateFingerprint(const char* data, size_t size) {
360   // Check the message length.
361   size_t fingerprint_attr_size =
362       kStunAttributeHeaderSize + StunUInt32Attribute::SIZE;
363   if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size)
364     return false;
365 
366   // Skip the rest if the magic cookie isn't present.
367   const char* magic_cookie =
368       data + kStunTransactionIdOffset - kStunMagicCookieLength;
369   if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
370     return false;
371 
372   // Check the fingerprint type and length.
373   const char* fingerprint_attr_data = data + size - fingerprint_attr_size;
374   if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT ||
375       rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) !=
376           StunUInt32Attribute::SIZE)
377     return false;
378 
379   // Check the fingerprint value.
380   uint32_t fingerprint =
381       rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize);
382   return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) ==
383           rtc::ComputeCrc32(data, size - fingerprint_attr_size));
384 }
385 
IsStunMethod(rtc::ArrayView<int> methods,const char * data,size_t size)386 bool StunMessage::IsStunMethod(rtc::ArrayView<int> methods,
387                                const char* data,
388                                size_t size) {
389   // Check the message length.
390   if (size % 4 != 0 || size < kStunHeaderSize)
391     return false;
392 
393   // Skip the rest if the magic cookie isn't present.
394   const char* magic_cookie =
395       data + kStunTransactionIdOffset - kStunMagicCookieLength;
396   if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
397     return false;
398 
399   int method = rtc::GetBE16(data);
400   for (int m : methods) {
401     if (m == method) {
402       return true;
403     }
404   }
405   return false;
406 }
407 
AddFingerprint()408 bool StunMessage::AddFingerprint() {
409   // Add the attribute with a dummy value. Since this is a known attribute,
410   // it can't fail.
411   auto fingerprint_attr_ptr =
412       std::make_unique<StunUInt32Attribute>(STUN_ATTR_FINGERPRINT, 0);
413   auto* fingerprint_attr = fingerprint_attr_ptr.get();
414   AddAttribute(std::move(fingerprint_attr_ptr));
415 
416   // Calculate the CRC-32 for the message and insert it.
417   ByteBufferWriter buf;
418   if (!Write(&buf))
419     return false;
420 
421   int msg_len_for_crc32 = static_cast<int>(
422       buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length());
423   uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32);
424 
425   // Insert the correct CRC-32, XORed with a constant, into the attribute.
426   fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE);
427   return true;
428 }
429 
Read(ByteBufferReader * buf)430 bool StunMessage::Read(ByteBufferReader* buf) {
431   if (!buf->ReadUInt16(&type_)) {
432     return false;
433   }
434 
435   if (type_ & 0x8000) {
436     // RTP and RTCP set the MSB of first byte, since first two bits are version,
437     // and version is always 2 (10). If set, this is not a STUN packet.
438     return false;
439   }
440 
441   if (!buf->ReadUInt16(&length_)) {
442     return false;
443   }
444 
445   std::string magic_cookie;
446   if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) {
447     return false;
448   }
449 
450   std::string transaction_id;
451   if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) {
452     return false;
453   }
454 
455   uint32_t magic_cookie_int;
456   static_assert(sizeof(magic_cookie_int) == kStunMagicCookieLength,
457                 "Integer size mismatch: magic_cookie_int and kStunMagicCookie");
458   std::memcpy(&magic_cookie_int, magic_cookie.data(), sizeof(magic_cookie_int));
459   if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
460     // If magic cookie is invalid it means that the peer implements
461     // RFC3489 instead of RFC5389.
462     transaction_id.insert(0, magic_cookie);
463   }
464   RTC_DCHECK(IsValidTransactionId(transaction_id));
465   transaction_id_ = transaction_id;
466   reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
467 
468   if (length_ != buf->Length()) {
469     return false;
470   }
471 
472   attrs_.resize(0);
473 
474   size_t rest = buf->Length() - length_;
475   while (buf->Length() > rest) {
476     uint16_t attr_type, attr_length;
477     if (!buf->ReadUInt16(&attr_type))
478       return false;
479     if (!buf->ReadUInt16(&attr_length))
480       return false;
481 
482     std::unique_ptr<StunAttribute> attr(
483         CreateAttribute(attr_type, attr_length));
484     if (!attr) {
485       // Skip any unknown or malformed attributes.
486       if ((attr_length % 4) != 0) {
487         attr_length += (4 - (attr_length % 4));
488       }
489       if (!buf->Consume(attr_length)) {
490         return false;
491       }
492     } else {
493       if (!attr->Read(buf)) {
494         return false;
495       }
496       attrs_.push_back(std::move(attr));
497     }
498   }
499 
500   RTC_DCHECK(buf->Length() == rest);
501   return true;
502 }
503 
Write(ByteBufferWriter * buf) const504 bool StunMessage::Write(ByteBufferWriter* buf) const {
505   buf->WriteUInt16(type_);
506   buf->WriteUInt16(length_);
507   if (!IsLegacy())
508     buf->WriteUInt32(stun_magic_cookie_);
509   buf->WriteString(transaction_id_);
510 
511   for (const auto& attr : attrs_) {
512     buf->WriteUInt16(attr->type());
513     buf->WriteUInt16(static_cast<uint16_t>(attr->length()));
514     if (!attr->Write(buf)) {
515       return false;
516     }
517   }
518 
519   return true;
520 }
521 
CreateNew() const522 StunMessage* StunMessage::CreateNew() const {
523   return new StunMessage();
524 }
525 
SetStunMagicCookie(uint32_t val)526 void StunMessage::SetStunMagicCookie(uint32_t val) {
527   stun_magic_cookie_ = val;
528 }
529 
GetAttributeValueType(int type) const530 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
531   switch (type) {
532     case STUN_ATTR_MAPPED_ADDRESS:
533       return STUN_VALUE_ADDRESS;
534     case STUN_ATTR_USERNAME:
535       return STUN_VALUE_BYTE_STRING;
536     case STUN_ATTR_MESSAGE_INTEGRITY:
537       return STUN_VALUE_BYTE_STRING;
538     case STUN_ATTR_ERROR_CODE:
539       return STUN_VALUE_ERROR_CODE;
540     case STUN_ATTR_UNKNOWN_ATTRIBUTES:
541       return STUN_VALUE_UINT16_LIST;
542     case STUN_ATTR_REALM:
543       return STUN_VALUE_BYTE_STRING;
544     case STUN_ATTR_NONCE:
545       return STUN_VALUE_BYTE_STRING;
546     case STUN_ATTR_XOR_MAPPED_ADDRESS:
547       return STUN_VALUE_XOR_ADDRESS;
548     case STUN_ATTR_SOFTWARE:
549       return STUN_VALUE_BYTE_STRING;
550     case STUN_ATTR_ALTERNATE_SERVER:
551       return STUN_VALUE_ADDRESS;
552     case STUN_ATTR_FINGERPRINT:
553       return STUN_VALUE_UINT32;
554     case STUN_ATTR_ORIGIN:
555       return STUN_VALUE_BYTE_STRING;
556     case STUN_ATTR_RETRANSMIT_COUNT:
557       return STUN_VALUE_UINT32;
558     case STUN_ATTR_LAST_ICE_CHECK_RECEIVED:
559       return STUN_VALUE_BYTE_STRING;
560     case STUN_ATTR_GOOG_MISC_INFO:
561       return STUN_VALUE_UINT16_LIST;
562     default:
563       return STUN_VALUE_UNKNOWN;
564   }
565 }
566 
CreateAttribute(int type,size_t length)567 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ {
568   StunAttributeValueType value_type = GetAttributeValueType(type);
569   if (value_type != STUN_VALUE_UNKNOWN) {
570     return StunAttribute::Create(value_type, type,
571                                  static_cast<uint16_t>(length), this);
572   } else if (DesignatedExpertRange(type)) {
573     // Read unknown attributes as STUN_VALUE_BYTE_STRING
574     return StunAttribute::Create(STUN_VALUE_BYTE_STRING, type,
575                                  static_cast<uint16_t>(length), this);
576   } else {
577     return NULL;
578   }
579 }
580 
GetAttribute(int type) const581 const StunAttribute* StunMessage::GetAttribute(int type) const {
582   for (const auto& attr : attrs_) {
583     if (attr->type() == type) {
584       return attr.get();
585     }
586   }
587   return NULL;
588 }
589 
IsValidTransactionId(const std::string & transaction_id)590 bool StunMessage::IsValidTransactionId(const std::string& transaction_id) {
591   return transaction_id.size() == kStunTransactionIdLength ||
592          transaction_id.size() == kStunLegacyTransactionIdLength;
593 }
594 
EqualAttributes(const StunMessage * other,std::function<bool (int type)> attribute_type_mask) const595 bool StunMessage::EqualAttributes(
596     const StunMessage* other,
597     std::function<bool(int type)> attribute_type_mask) const {
598   RTC_DCHECK(other != nullptr);
599   rtc::ByteBufferWriter tmp_buffer_ptr1;
600   rtc::ByteBufferWriter tmp_buffer_ptr2;
601   for (const auto& attr : attrs_) {
602     if (attribute_type_mask(attr->type())) {
603       const StunAttribute* other_attr = other->GetAttribute(attr->type());
604       if (other_attr == nullptr) {
605         return false;
606       }
607       tmp_buffer_ptr1.Clear();
608       tmp_buffer_ptr2.Clear();
609       attr->Write(&tmp_buffer_ptr1);
610       other_attr->Write(&tmp_buffer_ptr2);
611       if (tmp_buffer_ptr1.Length() != tmp_buffer_ptr2.Length()) {
612         return false;
613       }
614       if (memcmp(tmp_buffer_ptr1.Data(), tmp_buffer_ptr2.Data(),
615                  tmp_buffer_ptr1.Length()) != 0) {
616         return false;
617       }
618     }
619   }
620 
621   for (const auto& attr : other->attrs_) {
622     if (attribute_type_mask(attr->type())) {
623       const StunAttribute* own_attr = GetAttribute(attr->type());
624       if (own_attr == nullptr) {
625         return false;
626       }
627       // we have already compared all values...
628     }
629   }
630   return true;
631 }
632 
633 // StunAttribute
634 
StunAttribute(uint16_t type,uint16_t length)635 StunAttribute::StunAttribute(uint16_t type, uint16_t length)
636     : type_(type), length_(length) {}
637 
ConsumePadding(ByteBufferReader * buf) const638 void StunAttribute::ConsumePadding(ByteBufferReader* buf) const {
639   int remainder = length_ % 4;
640   if (remainder > 0) {
641     buf->Consume(4 - remainder);
642   }
643 }
644 
WritePadding(ByteBufferWriter * buf) const645 void StunAttribute::WritePadding(ByteBufferWriter* buf) const {
646   int remainder = length_ % 4;
647   if (remainder > 0) {
648     char zeroes[4] = {0};
649     buf->WriteBytes(zeroes, 4 - remainder);
650   }
651 }
652 
Create(StunAttributeValueType value_type,uint16_t type,uint16_t length,StunMessage * owner)653 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type,
654                                      uint16_t type,
655                                      uint16_t length,
656                                      StunMessage* owner) {
657   switch (value_type) {
658     case STUN_VALUE_ADDRESS:
659       return new StunAddressAttribute(type, length);
660     case STUN_VALUE_XOR_ADDRESS:
661       return new StunXorAddressAttribute(type, length, owner);
662     case STUN_VALUE_UINT32:
663       return new StunUInt32Attribute(type);
664     case STUN_VALUE_UINT64:
665       return new StunUInt64Attribute(type);
666     case STUN_VALUE_BYTE_STRING:
667       return new StunByteStringAttribute(type, length);
668     case STUN_VALUE_ERROR_CODE:
669       return new StunErrorCodeAttribute(type, length);
670     case STUN_VALUE_UINT16_LIST:
671       return new StunUInt16ListAttribute(type, length);
672     default:
673       return NULL;
674   }
675 }
676 
CreateAddress(uint16_t type)677 std::unique_ptr<StunAddressAttribute> StunAttribute::CreateAddress(
678     uint16_t type) {
679   return std::make_unique<StunAddressAttribute>(type, 0);
680 }
681 
CreateXorAddress(uint16_t type)682 std::unique_ptr<StunXorAddressAttribute> StunAttribute::CreateXorAddress(
683     uint16_t type) {
684   return std::make_unique<StunXorAddressAttribute>(type, 0, nullptr);
685 }
686 
CreateUInt64(uint16_t type)687 std::unique_ptr<StunUInt64Attribute> StunAttribute::CreateUInt64(
688     uint16_t type) {
689   return std::make_unique<StunUInt64Attribute>(type);
690 }
691 
CreateUInt32(uint16_t type)692 std::unique_ptr<StunUInt32Attribute> StunAttribute::CreateUInt32(
693     uint16_t type) {
694   return std::make_unique<StunUInt32Attribute>(type);
695 }
696 
CreateByteString(uint16_t type)697 std::unique_ptr<StunByteStringAttribute> StunAttribute::CreateByteString(
698     uint16_t type) {
699   return std::make_unique<StunByteStringAttribute>(type, 0);
700 }
701 
CreateErrorCode()702 std::unique_ptr<StunErrorCodeAttribute> StunAttribute::CreateErrorCode() {
703   return std::make_unique<StunErrorCodeAttribute>(
704       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
705 }
706 
707 std::unique_ptr<StunUInt16ListAttribute>
CreateUInt16ListAttribute(uint16_t type)708 StunAttribute::CreateUInt16ListAttribute(uint16_t type) {
709   return std::make_unique<StunUInt16ListAttribute>(type, 0);
710 }
711 
712 std::unique_ptr<StunUInt16ListAttribute>
CreateUnknownAttributes()713 StunAttribute::CreateUnknownAttributes() {
714   return std::make_unique<StunUInt16ListAttribute>(STUN_ATTR_UNKNOWN_ATTRIBUTES,
715                                                    0);
716 }
717 
StunAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)718 StunAddressAttribute::StunAddressAttribute(uint16_t type,
719                                            const rtc::SocketAddress& addr)
720     : StunAttribute(type, 0) {
721   SetAddress(addr);
722 }
723 
StunAddressAttribute(uint16_t type,uint16_t length)724 StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length)
725     : StunAttribute(type, length) {}
726 
value_type() const727 StunAttributeValueType StunAddressAttribute::value_type() const {
728   return STUN_VALUE_ADDRESS;
729 }
730 
Read(ByteBufferReader * buf)731 bool StunAddressAttribute::Read(ByteBufferReader* buf) {
732   uint8_t dummy;
733   if (!buf->ReadUInt8(&dummy))
734     return false;
735 
736   uint8_t stun_family;
737   if (!buf->ReadUInt8(&stun_family)) {
738     return false;
739   }
740   uint16_t port;
741   if (!buf->ReadUInt16(&port))
742     return false;
743   if (stun_family == STUN_ADDRESS_IPV4) {
744     in_addr v4addr;
745     if (length() != SIZE_IP4) {
746       return false;
747     }
748     if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) {
749       return false;
750     }
751     rtc::IPAddress ipaddr(v4addr);
752     SetAddress(rtc::SocketAddress(ipaddr, port));
753   } else if (stun_family == STUN_ADDRESS_IPV6) {
754     in6_addr v6addr;
755     if (length() != SIZE_IP6) {
756       return false;
757     }
758     if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) {
759       return false;
760     }
761     rtc::IPAddress ipaddr(v6addr);
762     SetAddress(rtc::SocketAddress(ipaddr, port));
763   } else {
764     return false;
765   }
766   return true;
767 }
768 
Write(ByteBufferWriter * buf) const769 bool StunAddressAttribute::Write(ByteBufferWriter* buf) const {
770   StunAddressFamily address_family = family();
771   if (address_family == STUN_ADDRESS_UNDEF) {
772     RTC_LOG(LS_ERROR) << "Error writing address attribute: unknown family.";
773     return false;
774   }
775   buf->WriteUInt8(0);
776   buf->WriteUInt8(address_family);
777   buf->WriteUInt16(address_.port());
778   switch (address_.family()) {
779     case AF_INET: {
780       in_addr v4addr = address_.ipaddr().ipv4_address();
781       buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr));
782       break;
783     }
784     case AF_INET6: {
785       in6_addr v6addr = address_.ipaddr().ipv6_address();
786       buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr));
787       break;
788     }
789   }
790   return true;
791 }
792 
StunXorAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)793 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
794                                                  const rtc::SocketAddress& addr)
795     : StunAddressAttribute(type, addr), owner_(NULL) {}
796 
StunXorAddressAttribute(uint16_t type,uint16_t length,StunMessage * owner)797 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
798                                                  uint16_t length,
799                                                  StunMessage* owner)
800     : StunAddressAttribute(type, length), owner_(owner) {}
801 
value_type() const802 StunAttributeValueType StunXorAddressAttribute::value_type() const {
803   return STUN_VALUE_XOR_ADDRESS;
804 }
805 
SetOwner(StunMessage * owner)806 void StunXorAddressAttribute::SetOwner(StunMessage* owner) {
807   owner_ = owner;
808 }
809 
GetXoredIP() const810 rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const {
811   if (owner_) {
812     rtc::IPAddress ip = ipaddr();
813     switch (ip.family()) {
814       case AF_INET: {
815         in_addr v4addr = ip.ipv4_address();
816         v4addr.s_addr =
817             (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie));
818         return rtc::IPAddress(v4addr);
819       }
820       case AF_INET6: {
821         in6_addr v6addr = ip.ipv6_address();
822         const std::string& transaction_id = owner_->transaction_id();
823         if (transaction_id.length() == kStunTransactionIdLength) {
824           uint32_t transactionid_as_ints[3];
825           memcpy(&transactionid_as_ints[0], transaction_id.c_str(),
826                  transaction_id.length());
827           uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
828           // Transaction ID is in network byte order, but magic cookie
829           // is stored in host byte order.
830           ip_as_ints[0] =
831               (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie));
832           ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]);
833           ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]);
834           ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]);
835           return rtc::IPAddress(v6addr);
836         }
837         break;
838       }
839     }
840   }
841   // Invalid ip family or transaction ID, or missing owner.
842   // Return an AF_UNSPEC address.
843   return rtc::IPAddress();
844 }
845 
Read(ByteBufferReader * buf)846 bool StunXorAddressAttribute::Read(ByteBufferReader* buf) {
847   if (!StunAddressAttribute::Read(buf))
848     return false;
849   uint16_t xoredport = port() ^ (kStunMagicCookie >> 16);
850   rtc::IPAddress xored_ip = GetXoredIP();
851   SetAddress(rtc::SocketAddress(xored_ip, xoredport));
852   return true;
853 }
854 
Write(ByteBufferWriter * buf) const855 bool StunXorAddressAttribute::Write(ByteBufferWriter* buf) const {
856   StunAddressFamily address_family = family();
857   if (address_family == STUN_ADDRESS_UNDEF) {
858     RTC_LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
859     return false;
860   }
861   rtc::IPAddress xored_ip = GetXoredIP();
862   if (xored_ip.family() == AF_UNSPEC) {
863     return false;
864   }
865   buf->WriteUInt8(0);
866   buf->WriteUInt8(family());
867   buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16));
868   switch (xored_ip.family()) {
869     case AF_INET: {
870       in_addr v4addr = xored_ip.ipv4_address();
871       buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr));
872       break;
873     }
874     case AF_INET6: {
875       in6_addr v6addr = xored_ip.ipv6_address();
876       buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr));
877       break;
878     }
879   }
880   return true;
881 }
882 
StunUInt32Attribute(uint16_t type,uint32_t value)883 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value)
884     : StunAttribute(type, SIZE), bits_(value) {}
885 
StunUInt32Attribute(uint16_t type)886 StunUInt32Attribute::StunUInt32Attribute(uint16_t type)
887     : StunAttribute(type, SIZE), bits_(0) {}
888 
value_type() const889 StunAttributeValueType StunUInt32Attribute::value_type() const {
890   return STUN_VALUE_UINT32;
891 }
892 
GetBit(size_t index) const893 bool StunUInt32Attribute::GetBit(size_t index) const {
894   RTC_DCHECK(index < 32);
895   return static_cast<bool>((bits_ >> index) & 0x1);
896 }
897 
SetBit(size_t index,bool value)898 void StunUInt32Attribute::SetBit(size_t index, bool value) {
899   RTC_DCHECK(index < 32);
900   bits_ &= ~(1 << index);
901   bits_ |= value ? (1 << index) : 0;
902 }
903 
Read(ByteBufferReader * buf)904 bool StunUInt32Attribute::Read(ByteBufferReader* buf) {
905   if (length() != SIZE || !buf->ReadUInt32(&bits_))
906     return false;
907   return true;
908 }
909 
Write(ByteBufferWriter * buf) const910 bool StunUInt32Attribute::Write(ByteBufferWriter* buf) const {
911   buf->WriteUInt32(bits_);
912   return true;
913 }
914 
StunUInt64Attribute(uint16_t type,uint64_t value)915 StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value)
916     : StunAttribute(type, SIZE), bits_(value) {}
917 
StunUInt64Attribute(uint16_t type)918 StunUInt64Attribute::StunUInt64Attribute(uint16_t type)
919     : StunAttribute(type, SIZE), bits_(0) {}
920 
value_type() const921 StunAttributeValueType StunUInt64Attribute::value_type() const {
922   return STUN_VALUE_UINT64;
923 }
924 
Read(ByteBufferReader * buf)925 bool StunUInt64Attribute::Read(ByteBufferReader* buf) {
926   if (length() != SIZE || !buf->ReadUInt64(&bits_))
927     return false;
928   return true;
929 }
930 
Write(ByteBufferWriter * buf) const931 bool StunUInt64Attribute::Write(ByteBufferWriter* buf) const {
932   buf->WriteUInt64(bits_);
933   return true;
934 }
935 
StunByteStringAttribute(uint16_t type)936 StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
937     : StunAttribute(type, 0), bytes_(NULL) {}
938 
StunByteStringAttribute(uint16_t type,const std::string & str)939 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
940                                                  const std::string& str)
941     : StunAttribute(type, 0), bytes_(NULL) {
942   CopyBytes(str.c_str(), str.size());
943 }
944 
StunByteStringAttribute(uint16_t type,const void * bytes,size_t length)945 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
946                                                  const void* bytes,
947                                                  size_t length)
948     : StunAttribute(type, 0), bytes_(NULL) {
949   CopyBytes(bytes, length);
950 }
951 
StunByteStringAttribute(uint16_t type,uint16_t length)952 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length)
953     : StunAttribute(type, length), bytes_(NULL) {}
954 
~StunByteStringAttribute()955 StunByteStringAttribute::~StunByteStringAttribute() {
956   delete[] bytes_;
957 }
958 
value_type() const959 StunAttributeValueType StunByteStringAttribute::value_type() const {
960   return STUN_VALUE_BYTE_STRING;
961 }
962 
CopyBytes(const char * bytes)963 void StunByteStringAttribute::CopyBytes(const char* bytes) {
964   CopyBytes(bytes, strlen(bytes));
965 }
966 
CopyBytes(const void * bytes,size_t length)967 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {
968   char* new_bytes = new char[length];
969   memcpy(new_bytes, bytes, length);
970   SetBytes(new_bytes, length);
971 }
972 
GetByte(size_t index) const973 uint8_t StunByteStringAttribute::GetByte(size_t index) const {
974   RTC_DCHECK(bytes_ != NULL);
975   RTC_DCHECK(index < length());
976   return static_cast<uint8_t>(bytes_[index]);
977 }
978 
SetByte(size_t index,uint8_t value)979 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) {
980   RTC_DCHECK(bytes_ != NULL);
981   RTC_DCHECK(index < length());
982   bytes_[index] = value;
983 }
984 
Read(ByteBufferReader * buf)985 bool StunByteStringAttribute::Read(ByteBufferReader* buf) {
986   bytes_ = new char[length()];
987   if (!buf->ReadBytes(bytes_, length())) {
988     return false;
989   }
990 
991   ConsumePadding(buf);
992   return true;
993 }
994 
Write(ByteBufferWriter * buf) const995 bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const {
996   buf->WriteBytes(bytes_, length());
997   WritePadding(buf);
998   return true;
999 }
1000 
SetBytes(char * bytes,size_t length)1001 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
1002   delete[] bytes_;
1003   bytes_ = bytes;
1004   SetLength(static_cast<uint16_t>(length));
1005 }
1006 
1007 const uint16_t StunErrorCodeAttribute::MIN_SIZE = 4;
1008 
StunErrorCodeAttribute(uint16_t type,int code,const std::string & reason)1009 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type,
1010                                                int code,
1011                                                const std::string& reason)
1012     : StunAttribute(type, 0) {
1013   SetCode(code);
1014   SetReason(reason);
1015 }
1016 
StunErrorCodeAttribute(uint16_t type,uint16_t length)1017 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length)
1018     : StunAttribute(type, length), class_(0), number_(0) {}
1019 
~StunErrorCodeAttribute()1020 StunErrorCodeAttribute::~StunErrorCodeAttribute() {}
1021 
value_type() const1022 StunAttributeValueType StunErrorCodeAttribute::value_type() const {
1023   return STUN_VALUE_ERROR_CODE;
1024 }
1025 
code() const1026 int StunErrorCodeAttribute::code() const {
1027   return class_ * 100 + number_;
1028 }
1029 
SetCode(int code)1030 void StunErrorCodeAttribute::SetCode(int code) {
1031   class_ = static_cast<uint8_t>(code / 100);
1032   number_ = static_cast<uint8_t>(code % 100);
1033 }
1034 
SetReason(const std::string & reason)1035 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
1036   SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size()));
1037   reason_ = reason;
1038 }
1039 
Read(ByteBufferReader * buf)1040 bool StunErrorCodeAttribute::Read(ByteBufferReader* buf) {
1041   uint32_t val;
1042   if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
1043     return false;
1044 
1045   if ((val >> 11) != 0)
1046     RTC_LOG(LS_ERROR) << "error-code bits not zero";
1047 
1048   class_ = ((val >> 8) & 0x7);
1049   number_ = (val & 0xff);
1050 
1051   if (!buf->ReadString(&reason_, length() - 4))
1052     return false;
1053 
1054   ConsumePadding(buf);
1055   return true;
1056 }
1057 
Write(ByteBufferWriter * buf) const1058 bool StunErrorCodeAttribute::Write(ByteBufferWriter* buf) const {
1059   buf->WriteUInt32(class_ << 8 | number_);
1060   buf->WriteString(reason_);
1061   WritePadding(buf);
1062   return true;
1063 }
1064 
StunUInt16ListAttribute(uint16_t type,uint16_t length)1065 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length)
1066     : StunAttribute(type, length) {
1067   attr_types_ = new std::vector<uint16_t>();
1068 }
1069 
~StunUInt16ListAttribute()1070 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
1071   delete attr_types_;
1072 }
1073 
value_type() const1074 StunAttributeValueType StunUInt16ListAttribute::value_type() const {
1075   return STUN_VALUE_UINT16_LIST;
1076 }
1077 
Size() const1078 size_t StunUInt16ListAttribute::Size() const {
1079   return attr_types_->size();
1080 }
1081 
GetType(int index) const1082 uint16_t StunUInt16ListAttribute::GetType(int index) const {
1083   return (*attr_types_)[index];
1084 }
1085 
SetType(int index,uint16_t value)1086 void StunUInt16ListAttribute::SetType(int index, uint16_t value) {
1087   (*attr_types_)[index] = value;
1088 }
1089 
AddType(uint16_t value)1090 void StunUInt16ListAttribute::AddType(uint16_t value) {
1091   attr_types_->push_back(value);
1092   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1093 }
1094 
AddTypeAtIndex(uint16_t index,uint16_t value)1095 void StunUInt16ListAttribute::AddTypeAtIndex(uint16_t index, uint16_t value) {
1096   if (attr_types_->size() < static_cast<size_t>(index + 1)) {
1097     attr_types_->resize(index + 1);
1098   }
1099   (*attr_types_)[index] = value;
1100   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1101 }
1102 
Read(ByteBufferReader * buf)1103 bool StunUInt16ListAttribute::Read(ByteBufferReader* buf) {
1104   if (length() % 2) {
1105     return false;
1106   }
1107 
1108   for (size_t i = 0; i < length() / 2; i++) {
1109     uint16_t attr;
1110     if (!buf->ReadUInt16(&attr))
1111       return false;
1112     attr_types_->push_back(attr);
1113   }
1114   // Padding of these attributes is done in RFC 5389 style. This is
1115   // slightly different from RFC3489, but it shouldn't be important.
1116   // RFC3489 pads out to a 32 bit boundary by duplicating one of the
1117   // entries in the list (not necessarily the last one - it's unspecified).
1118   // RFC5389 pads on the end, and the bytes are always ignored.
1119   ConsumePadding(buf);
1120   return true;
1121 }
1122 
Write(ByteBufferWriter * buf) const1123 bool StunUInt16ListAttribute::Write(ByteBufferWriter* buf) const {
1124   for (size_t i = 0; i < attr_types_->size(); ++i) {
1125     buf->WriteUInt16((*attr_types_)[i]);
1126   }
1127   WritePadding(buf);
1128   return true;
1129 }
1130 
StunMethodToString(int msg_type)1131 std::string StunMethodToString(int msg_type) {
1132   switch (msg_type) {
1133     case STUN_BINDING_REQUEST:
1134       return "STUN BINDING request";
1135     case STUN_BINDING_INDICATION:
1136       return "STUN BINDING indication";
1137     case STUN_BINDING_RESPONSE:
1138       return "STUN BINDING response";
1139     case STUN_BINDING_ERROR_RESPONSE:
1140       return "STUN BINDING error response";
1141     case GOOG_PING_REQUEST:
1142       return "GOOG PING request";
1143     case GOOG_PING_RESPONSE:
1144       return "GOOG PING response";
1145     case GOOG_PING_ERROR_RESPONSE:
1146       return "GOOG PING error response";
1147     case STUN_ALLOCATE_REQUEST:
1148       return "TURN ALLOCATE request";
1149     case STUN_ALLOCATE_RESPONSE:
1150       return "TURN ALLOCATE response";
1151     case STUN_ALLOCATE_ERROR_RESPONSE:
1152       return "TURN ALLOCATE error response";
1153     case TURN_REFRESH_REQUEST:
1154       return "TURN REFRESH request";
1155     case TURN_REFRESH_RESPONSE:
1156       return "TURN REFRESH response";
1157     case TURN_REFRESH_ERROR_RESPONSE:
1158       return "TURN REFRESH error response";
1159     case TURN_SEND_INDICATION:
1160       return "TURN SEND INDICATION";
1161     case TURN_DATA_INDICATION:
1162       return "TURN DATA INDICATION";
1163     case TURN_CREATE_PERMISSION_REQUEST:
1164       return "TURN CREATE PERMISSION request";
1165     case TURN_CREATE_PERMISSION_RESPONSE:
1166       return "TURN CREATE PERMISSION response";
1167     case TURN_CREATE_PERMISSION_ERROR_RESPONSE:
1168       return "TURN CREATE PERMISSION error response";
1169     case TURN_CHANNEL_BIND_REQUEST:
1170       return "TURN CHANNEL BIND request";
1171     case TURN_CHANNEL_BIND_RESPONSE:
1172       return "TURN CHANNEL BIND response";
1173     case TURN_CHANNEL_BIND_ERROR_RESPONSE:
1174       return "TURN CHANNEL BIND error response";
1175     default:
1176       return "UNKNOWN<" + std::to_string(msg_type) + ">";
1177   }
1178 }
1179 
GetStunSuccessResponseType(int req_type)1180 int GetStunSuccessResponseType(int req_type) {
1181   return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
1182 }
1183 
GetStunErrorResponseType(int req_type)1184 int GetStunErrorResponseType(int req_type) {
1185   return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
1186 }
1187 
IsStunRequestType(int msg_type)1188 bool IsStunRequestType(int msg_type) {
1189   return ((msg_type & kStunTypeMask) == 0x000);
1190 }
1191 
IsStunIndicationType(int msg_type)1192 bool IsStunIndicationType(int msg_type) {
1193   return ((msg_type & kStunTypeMask) == 0x010);
1194 }
1195 
IsStunSuccessResponseType(int msg_type)1196 bool IsStunSuccessResponseType(int msg_type) {
1197   return ((msg_type & kStunTypeMask) == 0x100);
1198 }
1199 
IsStunErrorResponseType(int msg_type)1200 bool IsStunErrorResponseType(int msg_type) {
1201   return ((msg_type & kStunTypeMask) == 0x110);
1202 }
1203 
ComputeStunCredentialHash(const std::string & username,const std::string & realm,const std::string & password,std::string * hash)1204 bool ComputeStunCredentialHash(const std::string& username,
1205                                const std::string& realm,
1206                                const std::string& password,
1207                                std::string* hash) {
1208   // http://tools.ietf.org/html/rfc5389#section-15.4
1209   // long-term credentials will be calculated using the key and key is
1210   // key = MD5(username ":" realm ":" SASLprep(password))
1211   std::string input = username;
1212   input += ':';
1213   input += realm;
1214   input += ':';
1215   input += password;
1216 
1217   char digest[rtc::MessageDigest::kMaxSize];
1218   size_t size = rtc::ComputeDigest(rtc::DIGEST_MD5, input.c_str(), input.size(),
1219                                    digest, sizeof(digest));
1220   if (size == 0) {
1221     return false;
1222   }
1223 
1224   *hash = std::string(digest, size);
1225   return true;
1226 }
1227 
CopyStunAttribute(const StunAttribute & attribute,rtc::ByteBufferWriter * tmp_buffer_ptr)1228 std::unique_ptr<StunAttribute> CopyStunAttribute(
1229     const StunAttribute& attribute,
1230     rtc::ByteBufferWriter* tmp_buffer_ptr) {
1231   ByteBufferWriter tmpBuffer;
1232   if (tmp_buffer_ptr == nullptr) {
1233     tmp_buffer_ptr = &tmpBuffer;
1234   }
1235 
1236   std::unique_ptr<StunAttribute> copy(StunAttribute::Create(
1237       attribute.value_type(), attribute.type(),
1238       static_cast<uint16_t>(attribute.length()), nullptr));
1239 
1240   if (!copy) {
1241     return nullptr;
1242   }
1243   tmp_buffer_ptr->Clear();
1244   if (!attribute.Write(tmp_buffer_ptr)) {
1245     return nullptr;
1246   }
1247   rtc::ByteBufferReader reader(*tmp_buffer_ptr);
1248   if (!copy->Read(&reader)) {
1249     return nullptr;
1250   }
1251 
1252   return copy;
1253 }
1254 
GetAttributeValueType(int type) const1255 StunAttributeValueType RelayMessage::GetAttributeValueType(int type) const {
1256   switch (type) {
1257     case STUN_ATTR_LIFETIME:
1258       return STUN_VALUE_UINT32;
1259     case STUN_ATTR_MAGIC_COOKIE:
1260       return STUN_VALUE_BYTE_STRING;
1261     case STUN_ATTR_BANDWIDTH:
1262       return STUN_VALUE_UINT32;
1263     case STUN_ATTR_DESTINATION_ADDRESS:
1264       return STUN_VALUE_ADDRESS;
1265     case STUN_ATTR_SOURCE_ADDRESS2:
1266       return STUN_VALUE_ADDRESS;
1267     case STUN_ATTR_DATA:
1268       return STUN_VALUE_BYTE_STRING;
1269     case STUN_ATTR_OPTIONS:
1270       return STUN_VALUE_UINT32;
1271     default:
1272       return StunMessage::GetAttributeValueType(type);
1273   }
1274 }
1275 
CreateNew() const1276 StunMessage* RelayMessage::CreateNew() const {
1277   return new RelayMessage();
1278 }
1279 
GetAttributeValueType(int type) const1280 StunAttributeValueType TurnMessage::GetAttributeValueType(int type) const {
1281   switch (type) {
1282     case STUN_ATTR_CHANNEL_NUMBER:
1283       return STUN_VALUE_UINT32;
1284     case STUN_ATTR_TURN_LIFETIME:
1285       return STUN_VALUE_UINT32;
1286     case STUN_ATTR_XOR_PEER_ADDRESS:
1287       return STUN_VALUE_XOR_ADDRESS;
1288     case STUN_ATTR_DATA:
1289       return STUN_VALUE_BYTE_STRING;
1290     case STUN_ATTR_XOR_RELAYED_ADDRESS:
1291       return STUN_VALUE_XOR_ADDRESS;
1292     case STUN_ATTR_EVEN_PORT:
1293       return STUN_VALUE_BYTE_STRING;
1294     case STUN_ATTR_REQUESTED_TRANSPORT:
1295       return STUN_VALUE_UINT32;
1296     case STUN_ATTR_DONT_FRAGMENT:
1297       return STUN_VALUE_BYTE_STRING;
1298     case STUN_ATTR_RESERVATION_TOKEN:
1299       return STUN_VALUE_BYTE_STRING;
1300     default:
1301       return StunMessage::GetAttributeValueType(type);
1302   }
1303 }
1304 
CreateNew() const1305 StunMessage* TurnMessage::CreateNew() const {
1306   return new TurnMessage();
1307 }
1308 
GetAttributeValueType(int type) const1309 StunAttributeValueType IceMessage::GetAttributeValueType(int type) const {
1310   switch (type) {
1311     case STUN_ATTR_PRIORITY:
1312     case STUN_ATTR_NETWORK_INFO:
1313     case STUN_ATTR_NOMINATION:
1314       return STUN_VALUE_UINT32;
1315     case STUN_ATTR_USE_CANDIDATE:
1316       return STUN_VALUE_BYTE_STRING;
1317     case STUN_ATTR_ICE_CONTROLLED:
1318       return STUN_VALUE_UINT64;
1319     case STUN_ATTR_ICE_CONTROLLING:
1320       return STUN_VALUE_UINT64;
1321     default:
1322       return StunMessage::GetAttributeValueType(type);
1323   }
1324 }
1325 
CreateNew() const1326 StunMessage* IceMessage::CreateNew() const {
1327   return new IceMessage();
1328 }
1329 
Clone() const1330 std::unique_ptr<StunMessage> StunMessage::Clone() const {
1331   std::unique_ptr<StunMessage> copy(CreateNew());
1332   if (!copy) {
1333     return nullptr;
1334   }
1335   rtc::ByteBufferWriter buf;
1336   if (!Write(&buf)) {
1337     return nullptr;
1338   }
1339   rtc::ByteBufferReader reader(buf);
1340   if (!copy->Read(&reader)) {
1341     return nullptr;
1342   }
1343   return copy;
1344 }
1345 
1346 }  // namespace cricket
1347