Home | History | Annotate | Download | only in base
      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 
     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 
     70 StunMessage::~StunMessage() {
     71   for (size_t i = 0; i < attrs_->size(); i++)
     72     delete (*attrs_)[i];
     73   delete attrs_;
     74 }
     75 
     76 bool StunMessage::IsLegacy() const {
     77   if (transaction_id_.size() == kStunLegacyTransactionIdLength)
     78     return true;
     79   ASSERT(transaction_id_.size() == kStunTransactionIdLength);
     80   return false;
     81 }
     82 
     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 
     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 
    106 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 
    123 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
    124   return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
    125 }
    126 
    127 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
    128   return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
    129 }
    130 
    131 const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
    132   return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
    133 }
    134 
    135 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
    136   return static_cast<const StunErrorCodeAttribute*>(
    137       GetAttribute(STUN_ATTR_ERROR_CODE));
    138 }
    139 
    140 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.
    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 
    226 bool StunMessage::AddMessageIntegrity(const std::string& password) {
    227   return AddMessageIntegrity(password.c_str(), password.size());
    228 }
    229 
    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.
    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 
    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 
    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 
    377 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 
    394 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 
    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 
    418 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 
    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 
    433 StunAttribute::StunAttribute(uint16 type, uint16 length)
    434     : type_(type), length_(length) {
    435 }
    436 
    437 void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const {
    438   int remainder = length_ % 4;
    439   if (remainder > 0) {
    440     buf->Consume(4 - remainder);
    441   }
    442 }
    443 
    444 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 
    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 
    475 StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
    476   return new StunAddressAttribute(type, 0);
    477 }
    478 
    479 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16 type) {
    480   return new StunXorAddressAttribute(type, 0, NULL);
    481 }
    482 
    483 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16 type) {
    484   return new StunUInt64Attribute(type);
    485 }
    486 
    487 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
    488   return new StunUInt32Attribute(type);
    489 }
    490 
    491 StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) {
    492   return new StunByteStringAttribute(type, 0);
    493 }
    494 
    495 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
    496   return new StunErrorCodeAttribute(
    497       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
    498 }
    499 
    500 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
    501   return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
    502 }
    503 
    504 StunAddressAttribute::StunAddressAttribute(uint16 type,
    505    const rtc::SocketAddress& addr)
    506    : StunAttribute(type, 0) {
    507   SetAddress(addr);
    508 }
    509 
    510 StunAddressAttribute::StunAddressAttribute(uint16 type, uint16 length)
    511     : StunAttribute(type, length) {
    512 }
    513 
    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 
    552 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 
    576 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type,
    577     const rtc::SocketAddress& addr)
    578     : StunAddressAttribute(type, addr), owner_(NULL) {
    579 }
    580 
    581 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type,
    582                                                  uint16 length,
    583                                                  StunMessage* owner)
    584     : StunAddressAttribute(type, length), owner_(owner) {}
    585 
    586 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 
    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 
    631 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 
    659 StunUInt32Attribute::StunUInt32Attribute(uint16 type, uint32 value)
    660     : StunAttribute(type, SIZE), bits_(value) {
    661 }
    662 
    663 StunUInt32Attribute::StunUInt32Attribute(uint16 type)
    664     : StunAttribute(type, SIZE), bits_(0) {
    665 }
    666 
    667 bool StunUInt32Attribute::GetBit(size_t index) const {
    668   ASSERT(index < 32);
    669   return static_cast<bool>((bits_ >> index) & 0x1);
    670 }
    671 
    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 
    678 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
    679   if (length() != SIZE || !buf->ReadUInt32(&bits_))
    680     return false;
    681   return true;
    682 }
    683 
    684 bool StunUInt32Attribute::Write(ByteBuffer* buf) const {
    685   buf->WriteUInt32(bits_);
    686   return true;
    687 }
    688 
    689 StunUInt64Attribute::StunUInt64Attribute(uint16 type, uint64 value)
    690     : StunAttribute(type, SIZE), bits_(value) {
    691 }
    692 
    693 StunUInt64Attribute::StunUInt64Attribute(uint16 type)
    694     : StunAttribute(type, SIZE), bits_(0) {
    695 }
    696 
    697 bool StunUInt64Attribute::Read(ByteBuffer* buf) {
    698   if (length() != SIZE || !buf->ReadUInt64(&bits_))
    699     return false;
    700   return true;
    701 }
    702 
    703 bool StunUInt64Attribute::Write(ByteBuffer* buf) const {
    704   buf->WriteUInt64(bits_);
    705   return true;
    706 }
    707 
    708 StunByteStringAttribute::StunByteStringAttribute(uint16 type)
    709     : StunAttribute(type, 0), bytes_(NULL) {
    710 }
    711 
    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 
    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 
    725 StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
    726     : StunAttribute(type, length), bytes_(NULL) {
    727 }
    728 
    729 StunByteStringAttribute::~StunByteStringAttribute() {
    730   delete [] bytes_;
    731 }
    732 
    733 void StunByteStringAttribute::CopyBytes(const char* bytes) {
    734   CopyBytes(bytes, strlen(bytes));
    735 }
    736 
    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 
    743 uint8 StunByteStringAttribute::GetByte(size_t index) const {
    744   ASSERT(bytes_ != NULL);
    745   ASSERT(index < length());
    746   return static_cast<uint8>(bytes_[index]);
    747 }
    748 
    749 void StunByteStringAttribute::SetByte(size_t index, uint8 value) {
    750   ASSERT(bytes_ != NULL);
    751   ASSERT(index < length());
    752   bytes_[index] = value;
    753 }
    754 
    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 
    765 bool StunByteStringAttribute::Write(ByteBuffer* buf) const {
    766   buf->WriteBytes(bytes_, length());
    767   WritePadding(buf);
    768   return true;
    769 }
    770 
    771 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
    772   delete [] bytes_;
    773   bytes_ = bytes;
    774   SetLength(static_cast<uint16>(length));
    775 }
    776 
    777 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, int code,
    778                                                const std::string& reason)
    779     : StunAttribute(type, 0) {
    780   SetCode(code);
    781   SetReason(reason);
    782 }
    783 
    784 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
    785     : StunAttribute(type, length), class_(0), number_(0) {
    786 }
    787 
    788 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
    789 }
    790 
    791 int StunErrorCodeAttribute::code() const {
    792   return class_ * 100 + number_;
    793 }
    794 
    795 void StunErrorCodeAttribute::SetCode(int code) {
    796   class_ = static_cast<uint8>(code / 100);
    797   number_ = static_cast<uint8>(code % 100);
    798 }
    799 
    800 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
    801   SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
    802   reason_ = reason;
    803 }
    804 
    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 
    823 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
    824   buf->WriteUInt32(class_ << 8 | number_);
    825   buf->WriteString(reason_);
    826   WritePadding(buf);
    827   return true;
    828 }
    829 
    830 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
    831     : StunAttribute(type, length) {
    832   attr_types_ = new std::vector<uint16>();
    833 }
    834 
    835 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
    836   delete attr_types_;
    837 }
    838 
    839 size_t StunUInt16ListAttribute::Size() const {
    840   return attr_types_->size();
    841 }
    842 
    843 uint16 StunUInt16ListAttribute::GetType(int index) const {
    844   return (*attr_types_)[index];
    845 }
    846 
    847 void StunUInt16ListAttribute::SetType(int index, uint16 value) {
    848   (*attr_types_)[index] = value;
    849 }
    850 
    851 void StunUInt16ListAttribute::AddType(uint16 value) {
    852   attr_types_->push_back(value);
    853   SetLength(static_cast<uint16>(attr_types_->size() * 2));
    854 }
    855 
    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 
    875 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 
    883 int GetStunSuccessResponseType(int req_type) {
    884   return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
    885 }
    886 
    887 int GetStunErrorResponseType(int req_type) {
    888   return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
    889 }
    890 
    891 bool IsStunRequestType(int msg_type) {
    892   return ((msg_type & kStunTypeMask) == 0x000);
    893 }
    894 
    895 bool IsStunIndicationType(int msg_type) {
    896   return ((msg_type & kStunTypeMask) == 0x010);
    897 }
    898 
    899 bool IsStunSuccessResponseType(int msg_type) {
    900   return ((msg_type & kStunTypeMask) == 0x100);
    901 }
    902 
    903 bool IsStunErrorResponseType(int msg_type) {
    904   return ((msg_type & kStunTypeMask) == 0x110);
    905 }
    906 
    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