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