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