Home | History | Annotate | Download | only in base
      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 
     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 
     53 StunMessage::~StunMessage() {
     54   for (size_t i = 0; i < attrs_->size(); i++)
     55     delete (*attrs_)[i];
     56   delete attrs_;
     57 }
     58 
     59 bool StunMessage::IsLegacy() const {
     60   if (transaction_id_.size() == kStunLegacyTransactionIdLength)
     61     return true;
     62   ASSERT(transaction_id_.size() == kStunTransactionIdLength);
     63   return false;
     64 }
     65 
     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 
     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 
     89 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 
    106 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
    107   return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
    108 }
    109 
    110 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
    111   return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
    112 }
    113 
    114 const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
    115   return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
    116 }
    117 
    118 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
    119   return static_cast<const StunErrorCodeAttribute*>(
    120       GetAttribute(STUN_ATTR_ERROR_CODE));
    121 }
    122 
    123 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.
    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 
    208 bool StunMessage::AddMessageIntegrity(const std::string& password) {
    209   return AddMessageIntegrity(password.c_str(), password.size());
    210 }
    211 
    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.
    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 
    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 
    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 
    359 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 
    376 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 
    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 
    401 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 
    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 
    416 StunAttribute::StunAttribute(uint16_t type, uint16_t length)
    417     : type_(type), length_(length) {
    418 }
    419 
    420 void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const {
    421   int remainder = length_ % 4;
    422   if (remainder > 0) {
    423     buf->Consume(4 - remainder);
    424   }
    425 }
    426 
    427 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 
    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 
    459 StunAddressAttribute* StunAttribute::CreateAddress(uint16_t type) {
    460   return new StunAddressAttribute(type, 0);
    461 }
    462 
    463 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16_t type) {
    464   return new StunXorAddressAttribute(type, 0, NULL);
    465 }
    466 
    467 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16_t type) {
    468   return new StunUInt64Attribute(type);
    469 }
    470 
    471 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16_t type) {
    472   return new StunUInt32Attribute(type);
    473 }
    474 
    475 StunByteStringAttribute* StunAttribute::CreateByteString(uint16_t type) {
    476   return new StunByteStringAttribute(type, 0);
    477 }
    478 
    479 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
    480   return new StunErrorCodeAttribute(
    481       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
    482 }
    483 
    484 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
    485   return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
    486 }
    487 
    488 StunAddressAttribute::StunAddressAttribute(uint16_t type,
    489                                            const rtc::SocketAddress& addr)
    490     : StunAttribute(type, 0) {
    491   SetAddress(addr);
    492 }
    493 
    494 StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length)
    495     : StunAttribute(type, length) {
    496 }
    497 
    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 
    536 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 
    560 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
    561                                                  const rtc::SocketAddress& addr)
    562     : StunAddressAttribute(type, addr), owner_(NULL) {
    563 }
    564 
    565 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
    566                                                  uint16_t length,
    567                                                  StunMessage* owner)
    568     : StunAddressAttribute(type, length), owner_(owner) {
    569 }
    570 
    571 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 
    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 
    616 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 
    644 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value)
    645     : StunAttribute(type, SIZE), bits_(value) {
    646 }
    647 
    648 StunUInt32Attribute::StunUInt32Attribute(uint16_t type)
    649     : StunAttribute(type, SIZE), bits_(0) {
    650 }
    651 
    652 bool StunUInt32Attribute::GetBit(size_t index) const {
    653   ASSERT(index < 32);
    654   return static_cast<bool>((bits_ >> index) & 0x1);
    655 }
    656 
    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 
    663 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
    664   if (length() != SIZE || !buf->ReadUInt32(&bits_))
    665     return false;
    666   return true;
    667 }
    668 
    669 bool StunUInt32Attribute::Write(ByteBuffer* buf) const {
    670   buf->WriteUInt32(bits_);
    671   return true;
    672 }
    673 
    674 StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value)
    675     : StunAttribute(type, SIZE), bits_(value) {
    676 }
    677 
    678 StunUInt64Attribute::StunUInt64Attribute(uint16_t type)
    679     : StunAttribute(type, SIZE), bits_(0) {
    680 }
    681 
    682 bool StunUInt64Attribute::Read(ByteBuffer* buf) {
    683   if (length() != SIZE || !buf->ReadUInt64(&bits_))
    684     return false;
    685   return true;
    686 }
    687 
    688 bool StunUInt64Attribute::Write(ByteBuffer* buf) const {
    689   buf->WriteUInt64(bits_);
    690   return true;
    691 }
    692 
    693 StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
    694     : StunAttribute(type, 0), bytes_(NULL) {
    695 }
    696 
    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 
    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 
    710 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length)
    711     : StunAttribute(type, length), bytes_(NULL) {
    712 }
    713 
    714 StunByteStringAttribute::~StunByteStringAttribute() {
    715   delete [] bytes_;
    716 }
    717 
    718 void StunByteStringAttribute::CopyBytes(const char* bytes) {
    719   CopyBytes(bytes, strlen(bytes));
    720 }
    721 
    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 
    728 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 
    734 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) {
    735   ASSERT(bytes_ != NULL);
    736   ASSERT(index < length());
    737   bytes_[index] = value;
    738 }
    739 
    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 
    750 bool StunByteStringAttribute::Write(ByteBuffer* buf) const {
    751   buf->WriteBytes(bytes_, length());
    752   WritePadding(buf);
    753   return true;
    754 }
    755 
    756 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
    757   delete [] bytes_;
    758   bytes_ = bytes;
    759   SetLength(static_cast<uint16_t>(length));
    760 }
    761 
    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 
    770 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length)
    771     : StunAttribute(type, length), class_(0), number_(0) {
    772 }
    773 
    774 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
    775 }
    776 
    777 int StunErrorCodeAttribute::code() const {
    778   return class_ * 100 + number_;
    779 }
    780 
    781 void StunErrorCodeAttribute::SetCode(int code) {
    782   class_ = static_cast<uint8_t>(code / 100);
    783   number_ = static_cast<uint8_t>(code % 100);
    784 }
    785 
    786 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
    787   SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size()));
    788   reason_ = reason;
    789 }
    790 
    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 
    809 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
    810   buf->WriteUInt32(class_ << 8 | number_);
    811   buf->WriteString(reason_);
    812   WritePadding(buf);
    813   return true;
    814 }
    815 
    816 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length)
    817     : StunAttribute(type, length) {
    818   attr_types_ = new std::vector<uint16_t>();
    819 }
    820 
    821 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
    822   delete attr_types_;
    823 }
    824 
    825 size_t StunUInt16ListAttribute::Size() const {
    826   return attr_types_->size();
    827 }
    828 
    829 uint16_t StunUInt16ListAttribute::GetType(int index) const {
    830   return (*attr_types_)[index];
    831 }
    832 
    833 void StunUInt16ListAttribute::SetType(int index, uint16_t value) {
    834   (*attr_types_)[index] = value;
    835 }
    836 
    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 
    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 
    861 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 
    869 int GetStunSuccessResponseType(int req_type) {
    870   return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
    871 }
    872 
    873 int GetStunErrorResponseType(int req_type) {
    874   return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
    875 }
    876 
    877 bool IsStunRequestType(int msg_type) {
    878   return ((msg_type & kStunTypeMask) == 0x000);
    879 }
    880 
    881 bool IsStunIndicationType(int msg_type) {
    882   return ((msg_type & kStunTypeMask) == 0x010);
    883 }
    884 
    885 bool IsStunSuccessResponseType(int msg_type) {
    886   return ((msg_type & kStunTypeMask) == 0x100);
    887 }
    888 
    889 bool IsStunErrorResponseType(int msg_type) {
    890   return ((msg_type & kStunTypeMask) == 0x110);
    891 }
    892 
    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