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