• 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 "webrtc/p2p/base/stun.h"
12 
13 #include <string.h>
14 
15 #include "webrtc/base/byteorder.h"
16 #include "webrtc/base/common.h"
17 #include "webrtc/base/crc32.h"
18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/messagedigest.h"
20 #include "webrtc/base/scoped_ptr.h"
21 #include "webrtc/base/stringencode.h"
22 
23 using rtc::ByteBuffer;
24 
25 namespace cricket {
26 
27 const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
28 const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
29 const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized";
30 const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden";
31 const char STUN_ERROR_REASON_STALE_CREDENTIALS[] = "Stale Credentials";
32 const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch";
33 const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce";
34 const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials";
35 const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol";
36 const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict";
37 const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error";
38 
39 const char TURN_MAGIC_COOKIE_VALUE[] = { '\x72', '\xC6', '\x4B', '\xC6' };
40 const char EMPTY_TRANSACTION_ID[] = "0000000000000000";
41 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E;
42 
43 // StunMessage
44 
StunMessage()45 StunMessage::StunMessage()
46     : type_(0),
47       length_(0),
48       transaction_id_(EMPTY_TRANSACTION_ID) {
49   ASSERT(IsValidTransactionId(transaction_id_));
50   attrs_ = new std::vector<StunAttribute*>();
51 }
52 
~StunMessage()53 StunMessage::~StunMessage() {
54   for (size_t i = 0; i < attrs_->size(); i++)
55     delete (*attrs_)[i];
56   delete attrs_;
57 }
58 
IsLegacy() const59 bool StunMessage::IsLegacy() const {
60   if (transaction_id_.size() == kStunLegacyTransactionIdLength)
61     return true;
62   ASSERT(transaction_id_.size() == kStunTransactionIdLength);
63   return false;
64 }
65 
SetTransactionID(const std::string & str)66 bool StunMessage::SetTransactionID(const std::string& str) {
67   if (!IsValidTransactionId(str)) {
68     return false;
69   }
70   transaction_id_ = str;
71   return true;
72 }
73 
AddAttribute(StunAttribute * attr)74 bool StunMessage::AddAttribute(StunAttribute* attr) {
75   // Fail any attributes that aren't valid for this type of message.
76   if (attr->value_type() != GetAttributeValueType(attr->type())) {
77     return false;
78   }
79   attrs_->push_back(attr);
80   attr->SetOwner(this);
81   size_t attr_length = attr->length();
82   if (attr_length % 4 != 0) {
83     attr_length += (4 - (attr_length % 4));
84   }
85   length_ += static_cast<uint16_t>(attr_length + 4);
86   return true;
87 }
88 
GetAddress(int type) const89 const StunAddressAttribute* StunMessage::GetAddress(int type) const {
90   switch (type) {
91     case STUN_ATTR_MAPPED_ADDRESS: {
92       // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is
93       // missing.
94       const StunAttribute* mapped_address =
95           GetAttribute(STUN_ATTR_MAPPED_ADDRESS);
96       if (!mapped_address)
97         mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS);
98       return reinterpret_cast<const StunAddressAttribute*>(mapped_address);
99     }
100 
101     default:
102       return static_cast<const StunAddressAttribute*>(GetAttribute(type));
103   }
104 }
105 
GetUInt32(int type) const106 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
107   return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
108 }
109 
GetUInt64(int type) const110 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
111   return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
112 }
113 
GetByteString(int type) const114 const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
115   return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
116 }
117 
GetErrorCode() const118 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
119   return static_cast<const StunErrorCodeAttribute*>(
120       GetAttribute(STUN_ATTR_ERROR_CODE));
121 }
122 
GetUnknownAttributes() const123 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
124   return static_cast<const StunUInt16ListAttribute*>(
125       GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
126 }
127 
128 // Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the
129 // procedure outlined in RFC 5389, section 15.4.
ValidateMessageIntegrity(const char * data,size_t size,const std::string & password)130 bool StunMessage::ValidateMessageIntegrity(const char* data, size_t size,
131                                            const std::string& password) {
132   // Verifying the size of the message.
133   if ((size % 4) != 0) {
134     return false;
135   }
136 
137   // Getting the message length from the STUN header.
138   uint16_t msg_length = rtc::GetBE16(&data[2]);
139   if (size != (msg_length + kStunHeaderSize)) {
140     return false;
141   }
142 
143   // Finding Message Integrity attribute in stun message.
144   size_t current_pos = kStunHeaderSize;
145   bool has_message_integrity_attr = false;
146   while (current_pos < size) {
147     uint16_t attr_type, attr_length;
148     // Getting attribute type and length.
149     attr_type = rtc::GetBE16(&data[current_pos]);
150     attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]);
151 
152     // If M-I, sanity check it, and break out.
153     if (attr_type == STUN_ATTR_MESSAGE_INTEGRITY) {
154       if (attr_length != kStunMessageIntegritySize ||
155           current_pos + attr_length > size) {
156         return false;
157       }
158       has_message_integrity_attr = true;
159       break;
160     }
161 
162     // Otherwise, skip to the next attribute.
163     current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length;
164     if ((attr_length % 4) != 0) {
165       current_pos += (4 - (attr_length % 4));
166     }
167   }
168 
169   if (!has_message_integrity_attr) {
170     return false;
171   }
172 
173   // Getting length of the message to calculate Message Integrity.
174   size_t mi_pos = current_pos;
175   rtc::scoped_ptr<char[]> temp_data(new char[current_pos]);
176   memcpy(temp_data.get(), data, current_pos);
177   if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) {
178     // Stun message has other attributes after message integrity.
179     // Adjust the length parameter in stun message to calculate HMAC.
180     size_t extra_offset = size -
181         (mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize);
182     size_t new_adjusted_len = size - extra_offset - kStunHeaderSize;
183 
184     // Writing new length of the STUN message @ Message Length in temp buffer.
185     //      0                   1                   2                   3
186     //      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
187     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
188     //     |0 0|     STUN Message Type     |         Message Length        |
189     //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
190     rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len));
191   }
192 
193   char hmac[kStunMessageIntegritySize];
194   size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1,
195                                       password.c_str(), password.size(),
196                                       temp_data.get(), mi_pos,
197                                       hmac, sizeof(hmac));
198   ASSERT(ret == sizeof(hmac));
199   if (ret != sizeof(hmac))
200     return false;
201 
202   // Comparing the calculated HMAC with the one present in the message.
203   return memcmp(data + current_pos + kStunAttributeHeaderSize,
204                 hmac,
205                 sizeof(hmac)) == 0;
206 }
207 
AddMessageIntegrity(const std::string & password)208 bool StunMessage::AddMessageIntegrity(const std::string& password) {
209   return AddMessageIntegrity(password.c_str(), password.size());
210 }
211 
AddMessageIntegrity(const char * key,size_t keylen)212 bool StunMessage::AddMessageIntegrity(const char* key,
213                                       size_t keylen) {
214   // Add the attribute with a dummy value. Since this is a known attribute, it
215   // can't fail.
216   StunByteStringAttribute* msg_integrity_attr =
217       new StunByteStringAttribute(STUN_ATTR_MESSAGE_INTEGRITY,
218           std::string(kStunMessageIntegritySize, '0'));
219   VERIFY(AddAttribute(msg_integrity_attr));
220 
221   // Calculate the HMAC for the message.
222   rtc::ByteBuffer buf;
223   if (!Write(&buf))
224     return false;
225 
226   int msg_len_for_hmac = static_cast<int>(
227       buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
228   char hmac[kStunMessageIntegritySize];
229   size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1,
230                                       key, keylen,
231                                       buf.Data(), msg_len_for_hmac,
232                                       hmac, sizeof(hmac));
233   ASSERT(ret == sizeof(hmac));
234   if (ret != sizeof(hmac)) {
235     LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity "
236                   << "has dummy value.";
237     return false;
238   }
239 
240   // Insert correct HMAC into the attribute.
241   msg_integrity_attr->CopyBytes(hmac, sizeof(hmac));
242   return true;
243 }
244 
245 // Verifies a message is in fact a STUN message, by performing the checks
246 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed
247 // in section 15.5.
ValidateFingerprint(const char * data,size_t size)248 bool StunMessage::ValidateFingerprint(const char* data, size_t size) {
249   // Check the message length.
250   size_t fingerprint_attr_size =
251       kStunAttributeHeaderSize + StunUInt32Attribute::SIZE;
252   if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size)
253     return false;
254 
255   // Skip the rest if the magic cookie isn't present.
256   const char* magic_cookie =
257       data + kStunTransactionIdOffset - kStunMagicCookieLength;
258   if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
259     return false;
260 
261   // Check the fingerprint type and length.
262   const char* fingerprint_attr_data = data + size - fingerprint_attr_size;
263   if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT ||
264       rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) !=
265           StunUInt32Attribute::SIZE)
266     return false;
267 
268   // Check the fingerprint value.
269   uint32_t fingerprint =
270       rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize);
271   return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) ==
272       rtc::ComputeCrc32(data, size - fingerprint_attr_size));
273 }
274 
AddFingerprint()275 bool StunMessage::AddFingerprint() {
276   // Add the attribute with a dummy value. Since this is a known attribute,
277   // it can't fail.
278   StunUInt32Attribute* fingerprint_attr =
279      new StunUInt32Attribute(STUN_ATTR_FINGERPRINT, 0);
280   VERIFY(AddAttribute(fingerprint_attr));
281 
282   // Calculate the CRC-32 for the message and insert it.
283   rtc::ByteBuffer buf;
284   if (!Write(&buf))
285     return false;
286 
287   int msg_len_for_crc32 = static_cast<int>(
288       buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length());
289   uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32);
290 
291   // Insert the correct CRC-32, XORed with a constant, into the attribute.
292   fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE);
293   return true;
294 }
295 
Read(ByteBuffer * buf)296 bool StunMessage::Read(ByteBuffer* buf) {
297   if (!buf->ReadUInt16(&type_))
298     return false;
299 
300   if (type_ & 0x8000) {
301     // RTP and RTCP set the MSB of first byte, since first two bits are version,
302     // and version is always 2 (10). If set, this is not a STUN packet.
303     return false;
304   }
305 
306   if (!buf->ReadUInt16(&length_))
307     return false;
308 
309   std::string magic_cookie;
310   if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength))
311     return false;
312 
313   std::string transaction_id;
314   if (!buf->ReadString(&transaction_id, kStunTransactionIdLength))
315     return false;
316 
317   uint32_t magic_cookie_int =
318       *reinterpret_cast<const uint32_t*>(magic_cookie.data());
319   if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
320     // If magic cookie is invalid it means that the peer implements
321     // RFC3489 instead of RFC5389.
322     transaction_id.insert(0, magic_cookie);
323   }
324   ASSERT(IsValidTransactionId(transaction_id));
325   transaction_id_ = transaction_id;
326 
327   if (length_ != buf->Length())
328     return false;
329 
330   attrs_->resize(0);
331 
332   size_t rest = buf->Length() - length_;
333   while (buf->Length() > rest) {
334     uint16_t attr_type, attr_length;
335     if (!buf->ReadUInt16(&attr_type))
336       return false;
337     if (!buf->ReadUInt16(&attr_length))
338       return false;
339 
340     StunAttribute* attr = CreateAttribute(attr_type, attr_length);
341     if (!attr) {
342       // Skip any unknown or malformed attributes.
343       if ((attr_length % 4) != 0) {
344         attr_length += (4 - (attr_length % 4));
345       }
346       if (!buf->Consume(attr_length))
347         return false;
348     } else {
349       if (!attr->Read(buf))
350         return false;
351       attrs_->push_back(attr);
352     }
353   }
354 
355   ASSERT(buf->Length() == rest);
356   return true;
357 }
358 
Write(ByteBuffer * buf) const359 bool StunMessage::Write(ByteBuffer* buf) const {
360   buf->WriteUInt16(type_);
361   buf->WriteUInt16(length_);
362   if (!IsLegacy())
363     buf->WriteUInt32(kStunMagicCookie);
364   buf->WriteString(transaction_id_);
365 
366   for (size_t i = 0; i < attrs_->size(); ++i) {
367     buf->WriteUInt16((*attrs_)[i]->type());
368     buf->WriteUInt16(static_cast<uint16_t>((*attrs_)[i]->length()));
369     if (!(*attrs_)[i]->Write(buf))
370       return false;
371   }
372 
373   return true;
374 }
375 
GetAttributeValueType(int type) const376 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
377   switch (type) {
378     case STUN_ATTR_MAPPED_ADDRESS:      return STUN_VALUE_ADDRESS;
379     case STUN_ATTR_USERNAME:            return STUN_VALUE_BYTE_STRING;
380     case STUN_ATTR_MESSAGE_INTEGRITY:   return STUN_VALUE_BYTE_STRING;
381     case STUN_ATTR_ERROR_CODE:          return STUN_VALUE_ERROR_CODE;
382     case STUN_ATTR_UNKNOWN_ATTRIBUTES:  return STUN_VALUE_UINT16_LIST;
383     case STUN_ATTR_REALM:               return STUN_VALUE_BYTE_STRING;
384     case STUN_ATTR_NONCE:               return STUN_VALUE_BYTE_STRING;
385     case STUN_ATTR_XOR_MAPPED_ADDRESS:  return STUN_VALUE_XOR_ADDRESS;
386     case STUN_ATTR_SOFTWARE:            return STUN_VALUE_BYTE_STRING;
387     case STUN_ATTR_ALTERNATE_SERVER:    return STUN_VALUE_ADDRESS;
388     case STUN_ATTR_FINGERPRINT:         return STUN_VALUE_UINT32;
389     case STUN_ATTR_ORIGIN:              return STUN_VALUE_BYTE_STRING;
390     case STUN_ATTR_RETRANSMIT_COUNT:    return STUN_VALUE_UINT32;
391     default:                            return STUN_VALUE_UNKNOWN;
392   }
393 }
394 
CreateAttribute(int type,size_t length)395 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ {
396   StunAttributeValueType value_type = GetAttributeValueType(type);
397   return StunAttribute::Create(value_type, type, static_cast<uint16_t>(length),
398                                this);
399 }
400 
GetAttribute(int type) const401 const StunAttribute* StunMessage::GetAttribute(int type) const {
402   for (size_t i = 0; i < attrs_->size(); ++i) {
403     if ((*attrs_)[i]->type() == type)
404       return (*attrs_)[i];
405   }
406   return NULL;
407 }
408 
IsValidTransactionId(const std::string & transaction_id)409 bool StunMessage::IsValidTransactionId(const std::string& transaction_id) {
410   return transaction_id.size() == kStunTransactionIdLength ||
411       transaction_id.size() == kStunLegacyTransactionIdLength;
412 }
413 
414 // StunAttribute
415 
StunAttribute(uint16_t type,uint16_t length)416 StunAttribute::StunAttribute(uint16_t type, uint16_t length)
417     : type_(type), length_(length) {
418 }
419 
ConsumePadding(rtc::ByteBuffer * buf) const420 void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const {
421   int remainder = length_ % 4;
422   if (remainder > 0) {
423     buf->Consume(4 - remainder);
424   }
425 }
426 
WritePadding(rtc::ByteBuffer * buf) const427 void StunAttribute::WritePadding(rtc::ByteBuffer* buf) const {
428   int remainder = length_ % 4;
429   if (remainder > 0) {
430     char zeroes[4] = {0};
431     buf->WriteBytes(zeroes, 4 - remainder);
432   }
433 }
434 
Create(StunAttributeValueType value_type,uint16_t type,uint16_t length,StunMessage * owner)435 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type,
436                                      uint16_t type,
437                                      uint16_t length,
438                                      StunMessage* owner) {
439   switch (value_type) {
440     case STUN_VALUE_ADDRESS:
441       return new StunAddressAttribute(type, length);
442     case STUN_VALUE_XOR_ADDRESS:
443       return new StunXorAddressAttribute(type, length, owner);
444     case STUN_VALUE_UINT32:
445       return new StunUInt32Attribute(type);
446     case STUN_VALUE_UINT64:
447       return new StunUInt64Attribute(type);
448     case STUN_VALUE_BYTE_STRING:
449       return new StunByteStringAttribute(type, length);
450     case STUN_VALUE_ERROR_CODE:
451       return new StunErrorCodeAttribute(type, length);
452     case STUN_VALUE_UINT16_LIST:
453       return new StunUInt16ListAttribute(type, length);
454     default:
455       return NULL;
456   }
457 }
458 
CreateAddress(uint16_t type)459 StunAddressAttribute* StunAttribute::CreateAddress(uint16_t type) {
460   return new StunAddressAttribute(type, 0);
461 }
462 
CreateXorAddress(uint16_t type)463 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16_t type) {
464   return new StunXorAddressAttribute(type, 0, NULL);
465 }
466 
CreateUInt64(uint16_t type)467 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16_t type) {
468   return new StunUInt64Attribute(type);
469 }
470 
CreateUInt32(uint16_t type)471 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16_t type) {
472   return new StunUInt32Attribute(type);
473 }
474 
CreateByteString(uint16_t type)475 StunByteStringAttribute* StunAttribute::CreateByteString(uint16_t type) {
476   return new StunByteStringAttribute(type, 0);
477 }
478 
CreateErrorCode()479 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
480   return new StunErrorCodeAttribute(
481       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
482 }
483 
CreateUnknownAttributes()484 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
485   return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
486 }
487 
StunAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)488 StunAddressAttribute::StunAddressAttribute(uint16_t type,
489                                            const rtc::SocketAddress& addr)
490     : StunAttribute(type, 0) {
491   SetAddress(addr);
492 }
493 
StunAddressAttribute(uint16_t type,uint16_t length)494 StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length)
495     : StunAttribute(type, length) {
496 }
497 
Read(ByteBuffer * buf)498 bool StunAddressAttribute::Read(ByteBuffer* buf) {
499   uint8_t dummy;
500   if (!buf->ReadUInt8(&dummy))
501     return false;
502 
503   uint8_t stun_family;
504   if (!buf->ReadUInt8(&stun_family)) {
505     return false;
506   }
507   uint16_t port;
508   if (!buf->ReadUInt16(&port))
509     return false;
510   if (stun_family == STUN_ADDRESS_IPV4) {
511     in_addr v4addr;
512     if (length() != SIZE_IP4) {
513       return false;
514     }
515     if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) {
516       return false;
517     }
518     rtc::IPAddress ipaddr(v4addr);
519     SetAddress(rtc::SocketAddress(ipaddr, port));
520   } else if (stun_family == STUN_ADDRESS_IPV6) {
521     in6_addr v6addr;
522     if (length() != SIZE_IP6) {
523       return false;
524     }
525     if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) {
526       return false;
527     }
528     rtc::IPAddress ipaddr(v6addr);
529     SetAddress(rtc::SocketAddress(ipaddr, port));
530   } else {
531     return false;
532   }
533   return true;
534 }
535 
Write(ByteBuffer * buf) const536 bool StunAddressAttribute::Write(ByteBuffer* buf) const {
537   StunAddressFamily address_family = family();
538   if (address_family == STUN_ADDRESS_UNDEF) {
539     LOG(LS_ERROR) << "Error writing address attribute: unknown family.";
540     return false;
541   }
542   buf->WriteUInt8(0);
543   buf->WriteUInt8(address_family);
544   buf->WriteUInt16(address_.port());
545   switch (address_.family()) {
546     case AF_INET: {
547       in_addr v4addr = address_.ipaddr().ipv4_address();
548       buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr));
549       break;
550     }
551     case AF_INET6: {
552       in6_addr v6addr = address_.ipaddr().ipv6_address();
553       buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr));
554       break;
555     }
556   }
557   return true;
558 }
559 
StunXorAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)560 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
561                                                  const rtc::SocketAddress& addr)
562     : StunAddressAttribute(type, addr), owner_(NULL) {
563 }
564 
StunXorAddressAttribute(uint16_t type,uint16_t length,StunMessage * owner)565 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
566                                                  uint16_t length,
567                                                  StunMessage* owner)
568     : StunAddressAttribute(type, length), owner_(owner) {
569 }
570 
GetXoredIP() const571 rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const {
572   if (owner_) {
573     rtc::IPAddress ip = ipaddr();
574     switch (ip.family()) {
575       case AF_INET: {
576         in_addr v4addr = ip.ipv4_address();
577         v4addr.s_addr =
578             (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie));
579         return rtc::IPAddress(v4addr);
580       }
581       case AF_INET6: {
582         in6_addr v6addr = ip.ipv6_address();
583         const std::string& transaction_id = owner_->transaction_id();
584         if (transaction_id.length() == kStunTransactionIdLength) {
585           uint32_t transactionid_as_ints[3];
586           memcpy(&transactionid_as_ints[0], transaction_id.c_str(),
587                  transaction_id.length());
588           uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
589           // Transaction ID is in network byte order, but magic cookie
590           // is stored in host byte order.
591           ip_as_ints[0] =
592               (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie));
593           ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]);
594           ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]);
595           ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]);
596           return rtc::IPAddress(v6addr);
597         }
598         break;
599       }
600     }
601   }
602   // Invalid ip family or transaction ID, or missing owner.
603   // Return an AF_UNSPEC address.
604   return rtc::IPAddress();
605 }
606 
Read(ByteBuffer * buf)607 bool StunXorAddressAttribute::Read(ByteBuffer* buf) {
608   if (!StunAddressAttribute::Read(buf))
609     return false;
610   uint16_t xoredport = port() ^ (kStunMagicCookie >> 16);
611   rtc::IPAddress xored_ip = GetXoredIP();
612   SetAddress(rtc::SocketAddress(xored_ip, xoredport));
613   return true;
614 }
615 
Write(ByteBuffer * buf) const616 bool StunXorAddressAttribute::Write(ByteBuffer* buf) const {
617   StunAddressFamily address_family = family();
618   if (address_family == STUN_ADDRESS_UNDEF) {
619     LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
620     return false;
621   }
622   rtc::IPAddress xored_ip = GetXoredIP();
623   if (xored_ip.family() == AF_UNSPEC) {
624     return false;
625   }
626   buf->WriteUInt8(0);
627   buf->WriteUInt8(family());
628   buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16));
629   switch (xored_ip.family()) {
630     case AF_INET: {
631       in_addr v4addr = xored_ip.ipv4_address();
632       buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr));
633       break;
634     }
635     case AF_INET6: {
636       in6_addr v6addr = xored_ip.ipv6_address();
637       buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr));
638       break;
639     }
640   }
641   return true;
642 }
643 
StunUInt32Attribute(uint16_t type,uint32_t value)644 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value)
645     : StunAttribute(type, SIZE), bits_(value) {
646 }
647 
StunUInt32Attribute(uint16_t type)648 StunUInt32Attribute::StunUInt32Attribute(uint16_t type)
649     : StunAttribute(type, SIZE), bits_(0) {
650 }
651 
GetBit(size_t index) const652 bool StunUInt32Attribute::GetBit(size_t index) const {
653   ASSERT(index < 32);
654   return static_cast<bool>((bits_ >> index) & 0x1);
655 }
656 
SetBit(size_t index,bool value)657 void StunUInt32Attribute::SetBit(size_t index, bool value) {
658   ASSERT(index < 32);
659   bits_ &= ~(1 << index);
660   bits_ |= value ? (1 << index) : 0;
661 }
662 
Read(ByteBuffer * buf)663 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
664   if (length() != SIZE || !buf->ReadUInt32(&bits_))
665     return false;
666   return true;
667 }
668 
Write(ByteBuffer * buf) const669 bool StunUInt32Attribute::Write(ByteBuffer* buf) const {
670   buf->WriteUInt32(bits_);
671   return true;
672 }
673 
StunUInt64Attribute(uint16_t type,uint64_t value)674 StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value)
675     : StunAttribute(type, SIZE), bits_(value) {
676 }
677 
StunUInt64Attribute(uint16_t type)678 StunUInt64Attribute::StunUInt64Attribute(uint16_t type)
679     : StunAttribute(type, SIZE), bits_(0) {
680 }
681 
Read(ByteBuffer * buf)682 bool StunUInt64Attribute::Read(ByteBuffer* buf) {
683   if (length() != SIZE || !buf->ReadUInt64(&bits_))
684     return false;
685   return true;
686 }
687 
Write(ByteBuffer * buf) const688 bool StunUInt64Attribute::Write(ByteBuffer* buf) const {
689   buf->WriteUInt64(bits_);
690   return true;
691 }
692 
StunByteStringAttribute(uint16_t type)693 StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
694     : StunAttribute(type, 0), bytes_(NULL) {
695 }
696 
StunByteStringAttribute(uint16_t type,const std::string & str)697 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
698                                                  const std::string& str)
699     : StunAttribute(type, 0), bytes_(NULL) {
700   CopyBytes(str.c_str(), str.size());
701 }
702 
StunByteStringAttribute(uint16_t type,const void * bytes,size_t length)703 StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
704                                                  const void* bytes,
705                                                  size_t length)
706     : StunAttribute(type, 0), bytes_(NULL) {
707   CopyBytes(bytes, length);
708 }
709 
StunByteStringAttribute(uint16_t type,uint16_t length)710 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length)
711     : StunAttribute(type, length), bytes_(NULL) {
712 }
713 
~StunByteStringAttribute()714 StunByteStringAttribute::~StunByteStringAttribute() {
715   delete [] bytes_;
716 }
717 
CopyBytes(const char * bytes)718 void StunByteStringAttribute::CopyBytes(const char* bytes) {
719   CopyBytes(bytes, strlen(bytes));
720 }
721 
CopyBytes(const void * bytes,size_t length)722 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {
723   char* new_bytes = new char[length];
724   memcpy(new_bytes, bytes, length);
725   SetBytes(new_bytes, length);
726 }
727 
GetByte(size_t index) const728 uint8_t StunByteStringAttribute::GetByte(size_t index) const {
729   ASSERT(bytes_ != NULL);
730   ASSERT(index < length());
731   return static_cast<uint8_t>(bytes_[index]);
732 }
733 
SetByte(size_t index,uint8_t value)734 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) {
735   ASSERT(bytes_ != NULL);
736   ASSERT(index < length());
737   bytes_[index] = value;
738 }
739 
Read(ByteBuffer * buf)740 bool StunByteStringAttribute::Read(ByteBuffer* buf) {
741   bytes_ = new char[length()];
742   if (!buf->ReadBytes(bytes_, length())) {
743     return false;
744   }
745 
746   ConsumePadding(buf);
747   return true;
748 }
749 
Write(ByteBuffer * buf) const750 bool StunByteStringAttribute::Write(ByteBuffer* buf) const {
751   buf->WriteBytes(bytes_, length());
752   WritePadding(buf);
753   return true;
754 }
755 
SetBytes(char * bytes,size_t length)756 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
757   delete [] bytes_;
758   bytes_ = bytes;
759   SetLength(static_cast<uint16_t>(length));
760 }
761 
StunErrorCodeAttribute(uint16_t type,int code,const std::string & reason)762 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type,
763                                                int code,
764                                                const std::string& reason)
765     : StunAttribute(type, 0) {
766   SetCode(code);
767   SetReason(reason);
768 }
769 
StunErrorCodeAttribute(uint16_t type,uint16_t length)770 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length)
771     : StunAttribute(type, length), class_(0), number_(0) {
772 }
773 
~StunErrorCodeAttribute()774 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
775 }
776 
code() const777 int StunErrorCodeAttribute::code() const {
778   return class_ * 100 + number_;
779 }
780 
SetCode(int code)781 void StunErrorCodeAttribute::SetCode(int code) {
782   class_ = static_cast<uint8_t>(code / 100);
783   number_ = static_cast<uint8_t>(code % 100);
784 }
785 
SetReason(const std::string & reason)786 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
787   SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size()));
788   reason_ = reason;
789 }
790 
Read(ByteBuffer * buf)791 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
792   uint32_t val;
793   if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
794     return false;
795 
796   if ((val >> 11) != 0)
797     LOG(LS_ERROR) << "error-code bits not zero";
798 
799   class_ = ((val >> 8) & 0x7);
800   number_ = (val & 0xff);
801 
802   if (!buf->ReadString(&reason_, length() - 4))
803     return false;
804 
805   ConsumePadding(buf);
806   return true;
807 }
808 
Write(ByteBuffer * buf) const809 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
810   buf->WriteUInt32(class_ << 8 | number_);
811   buf->WriteString(reason_);
812   WritePadding(buf);
813   return true;
814 }
815 
StunUInt16ListAttribute(uint16_t type,uint16_t length)816 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length)
817     : StunAttribute(type, length) {
818   attr_types_ = new std::vector<uint16_t>();
819 }
820 
~StunUInt16ListAttribute()821 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
822   delete attr_types_;
823 }
824 
Size() const825 size_t StunUInt16ListAttribute::Size() const {
826   return attr_types_->size();
827 }
828 
GetType(int index) const829 uint16_t StunUInt16ListAttribute::GetType(int index) const {
830   return (*attr_types_)[index];
831 }
832 
SetType(int index,uint16_t value)833 void StunUInt16ListAttribute::SetType(int index, uint16_t value) {
834   (*attr_types_)[index] = value;
835 }
836 
AddType(uint16_t value)837 void StunUInt16ListAttribute::AddType(uint16_t value) {
838   attr_types_->push_back(value);
839   SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
840 }
841 
Read(ByteBuffer * buf)842 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
843   if (length() % 2)
844     return false;
845 
846   for (size_t i = 0; i < length() / 2; i++) {
847     uint16_t attr;
848     if (!buf->ReadUInt16(&attr))
849       return false;
850     attr_types_->push_back(attr);
851   }
852   // Padding of these attributes is done in RFC 5389 style. This is
853   // slightly different from RFC3489, but it shouldn't be important.
854   // RFC3489 pads out to a 32 bit boundary by duplicating one of the
855   // entries in the list (not necessarily the last one - it's unspecified).
856   // RFC5389 pads on the end, and the bytes are always ignored.
857   ConsumePadding(buf);
858   return true;
859 }
860 
Write(ByteBuffer * buf) const861 bool StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
862   for (size_t i = 0; i < attr_types_->size(); ++i) {
863     buf->WriteUInt16((*attr_types_)[i]);
864   }
865   WritePadding(buf);
866   return true;
867 }
868 
GetStunSuccessResponseType(int req_type)869 int GetStunSuccessResponseType(int req_type) {
870   return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
871 }
872 
GetStunErrorResponseType(int req_type)873 int GetStunErrorResponseType(int req_type) {
874   return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
875 }
876 
IsStunRequestType(int msg_type)877 bool IsStunRequestType(int msg_type) {
878   return ((msg_type & kStunTypeMask) == 0x000);
879 }
880 
IsStunIndicationType(int msg_type)881 bool IsStunIndicationType(int msg_type) {
882   return ((msg_type & kStunTypeMask) == 0x010);
883 }
884 
IsStunSuccessResponseType(int msg_type)885 bool IsStunSuccessResponseType(int msg_type) {
886   return ((msg_type & kStunTypeMask) == 0x100);
887 }
888 
IsStunErrorResponseType(int msg_type)889 bool IsStunErrorResponseType(int msg_type) {
890   return ((msg_type & kStunTypeMask) == 0x110);
891 }
892 
ComputeStunCredentialHash(const std::string & username,const std::string & realm,const std::string & password,std::string * hash)893 bool ComputeStunCredentialHash(const std::string& username,
894                                const std::string& realm,
895                                const std::string& password,
896                                std::string* hash) {
897   // http://tools.ietf.org/html/rfc5389#section-15.4
898   // long-term credentials will be calculated using the key and key is
899   // key = MD5(username ":" realm ":" SASLprep(password))
900   std::string input = username;
901   input += ':';
902   input += realm;
903   input += ':';
904   input += password;
905 
906   char digest[rtc::MessageDigest::kMaxSize];
907   size_t size = rtc::ComputeDigest(
908       rtc::DIGEST_MD5, input.c_str(), input.size(),
909       digest, sizeof(digest));
910   if (size == 0) {
911     return false;
912   }
913 
914   *hash = std::string(digest, size);
915   return true;
916 }
917 
918 }  // namespace cricket
919