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 <cstring>
     31 
     32 #include "talk/base/common.h"
     33 #include "talk/base/logging.h"
     34 
     35 using talk_base::ByteBuffer;
     36 
     37 namespace cricket {
     38 
     39 const std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST";
     40 const std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED";
     41 const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE";
     42 const std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS";
     43 const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE";
     44 const std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME";
     45 const std::string STUN_ERROR_REASON_USE_TLS = "USE TLS";
     46 const std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR";
     47 const std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE";
     48 
     49 StunMessage::StunMessage() : type_(0), length_(0),
     50     transaction_id_("0000000000000000") {
     51   ASSERT(transaction_id_.size() == 16);
     52   attrs_ = new std::vector<StunAttribute*>();
     53 }
     54 
     55 StunMessage::~StunMessage() {
     56   for (unsigned i = 0; i < attrs_->size(); i++)
     57     delete (*attrs_)[i];
     58   delete attrs_;
     59 }
     60 
     61 void StunMessage::SetTransactionID(const std::string& str) {
     62   ASSERT(str.size() == 16);
     63   transaction_id_ = str;
     64 }
     65 
     66 void StunMessage::AddAttribute(StunAttribute* attr) {
     67   attrs_->push_back(attr);
     68   length_ += attr->length() + 4;
     69 }
     70 
     71 const StunAddressAttribute*
     72 StunMessage::GetAddress(StunAttributeType type) const {
     73   switch (type) {
     74   case STUN_ATTR_MAPPED_ADDRESS:
     75   case STUN_ATTR_RESPONSE_ADDRESS:
     76   case STUN_ATTR_SOURCE_ADDRESS:
     77   case STUN_ATTR_CHANGED_ADDRESS:
     78   case STUN_ATTR_REFLECTED_FROM:
     79   case STUN_ATTR_ALTERNATE_SERVER:
     80   case STUN_ATTR_DESTINATION_ADDRESS:
     81   case STUN_ATTR_SOURCE_ADDRESS2:
     82     return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type));
     83 
     84   default:
     85     ASSERT(0);
     86     return 0;
     87   }
     88 }
     89 
     90 const StunUInt32Attribute*
     91 StunMessage::GetUInt32(StunAttributeType type) const {
     92   switch (type) {
     93   case STUN_ATTR_CHANGE_REQUEST:
     94   case STUN_ATTR_LIFETIME:
     95   case STUN_ATTR_BANDWIDTH:
     96   case STUN_ATTR_OPTIONS:
     97     return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type));
     98 
     99   default:
    100     ASSERT(0);
    101     return 0;
    102   }
    103 }
    104 
    105 const StunByteStringAttribute*
    106 StunMessage::GetByteString(StunAttributeType type) const {
    107   switch (type) {
    108   case STUN_ATTR_USERNAME:
    109   case STUN_ATTR_PASSWORD:
    110   case STUN_ATTR_MESSAGE_INTEGRITY:
    111   case STUN_ATTR_DATA:
    112   case STUN_ATTR_MAGIC_COOKIE:
    113     return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type));
    114 
    115   default:
    116     ASSERT(0);
    117     return 0;
    118   }
    119 }
    120 
    121 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
    122   return reinterpret_cast<const StunErrorCodeAttribute*>(
    123       GetAttribute(STUN_ATTR_ERROR_CODE));
    124 }
    125 
    126 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
    127   return reinterpret_cast<const StunUInt16ListAttribute*>(
    128       GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
    129 }
    130 
    131 const StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const {
    132   return reinterpret_cast<const StunTransportPrefsAttribute*>(
    133       GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES));
    134 }
    135 
    136 const StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const {
    137   for (unsigned i = 0; i < attrs_->size(); i++) {
    138     if ((*attrs_)[i]->type() == type)
    139       return (*attrs_)[i];
    140   }
    141   return 0;
    142 }
    143 
    144 bool StunMessage::Read(ByteBuffer* buf) {
    145   if (!buf->ReadUInt16(&type_))
    146     return false;
    147 
    148   if (type_ & 0x8000) {
    149     // rtp and rtcp set MSB of first byte, since first two bits are version,
    150     // and version is always 2 (10).  If set, this is not a stun packet.
    151     return false;
    152   }
    153 
    154   if (!buf->ReadUInt16(&length_))
    155     return false;
    156 
    157   std::string transaction_id;
    158   if (!buf->ReadString(&transaction_id, 16))
    159     return false;
    160   ASSERT(transaction_id.size() == 16);
    161   transaction_id_ = transaction_id;
    162 
    163   if (length_ > buf->Length())
    164     return false;
    165 
    166   attrs_->resize(0);
    167 
    168   size_t rest = buf->Length() - length_;
    169   while (buf->Length() > rest) {
    170     uint16 attr_type, attr_length;
    171     if (!buf->ReadUInt16(&attr_type))
    172       return false;
    173     if (!buf->ReadUInt16(&attr_length))
    174       return false;
    175 
    176     StunAttribute* attr = StunAttribute::Create(attr_type, attr_length);
    177     if (!attr || !attr->Read(buf))
    178       return false;
    179 
    180     attrs_->push_back(attr);
    181   }
    182 
    183   if (buf->Length() != rest) {
    184     // fixme: shouldn't be doing this
    185     LOG(LERROR) << "wrong message length (" << rest << " != " << buf->Length()
    186                 << ")";
    187     return false;
    188   }
    189 
    190   return true;
    191 }
    192 
    193 void StunMessage::Write(ByteBuffer* buf) const {
    194   buf->WriteUInt16(type_);
    195   buf->WriteUInt16(length_);
    196   buf->WriteString(transaction_id_);
    197 
    198   for (unsigned i = 0; i < attrs_->size(); i++) {
    199     buf->WriteUInt16((*attrs_)[i]->type());
    200     buf->WriteUInt16((*attrs_)[i]->length());
    201     (*attrs_)[i]->Write(buf);
    202   }
    203 }
    204 
    205 StunAttribute::StunAttribute(uint16 type, uint16 length)
    206     : type_(type), length_(length) {
    207 }
    208 
    209 StunAttribute* StunAttribute::Create(uint16 type, uint16 length) {
    210   switch (type) {
    211   case STUN_ATTR_MAPPED_ADDRESS:
    212   case STUN_ATTR_RESPONSE_ADDRESS:
    213   case STUN_ATTR_SOURCE_ADDRESS:
    214   case STUN_ATTR_CHANGED_ADDRESS:
    215   case STUN_ATTR_REFLECTED_FROM:
    216   case STUN_ATTR_ALTERNATE_SERVER:
    217   case STUN_ATTR_DESTINATION_ADDRESS:
    218   case STUN_ATTR_SOURCE_ADDRESS2:
    219     if (length != StunAddressAttribute::SIZE)
    220       return 0;
    221     return new StunAddressAttribute(type);
    222 
    223   case STUN_ATTR_CHANGE_REQUEST:
    224   case STUN_ATTR_LIFETIME:
    225   case STUN_ATTR_BANDWIDTH:
    226   case STUN_ATTR_OPTIONS:
    227     if (length != StunUInt32Attribute::SIZE)
    228       return 0;
    229     return new StunUInt32Attribute(type);
    230 
    231   case STUN_ATTR_USERNAME:
    232   case STUN_ATTR_PASSWORD:
    233   case STUN_ATTR_MAGIC_COOKIE:
    234     return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0;
    235 
    236   case STUN_ATTR_MESSAGE_INTEGRITY:
    237     return (length == 20) ? new StunByteStringAttribute(type, length) : 0;
    238 
    239   case STUN_ATTR_DATA:
    240     return new StunByteStringAttribute(type, length);
    241 
    242   case STUN_ATTR_ERROR_CODE:
    243     if (length < StunErrorCodeAttribute::MIN_SIZE)
    244       return 0;
    245     return new StunErrorCodeAttribute(type, length);
    246 
    247   case STUN_ATTR_UNKNOWN_ATTRIBUTES:
    248     return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0;
    249 
    250   case STUN_ATTR_TRANSPORT_PREFERENCES:
    251     if ((length != StunTransportPrefsAttribute::SIZE1) &&
    252         (length != StunTransportPrefsAttribute::SIZE2))
    253       return 0;
    254     return new StunTransportPrefsAttribute(type, length);
    255 
    256   default:
    257     return 0;
    258   }
    259 }
    260 
    261 StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
    262   switch (type) {
    263   case STUN_ATTR_MAPPED_ADDRESS:
    264   case STUN_ATTR_RESPONSE_ADDRESS:
    265   case STUN_ATTR_SOURCE_ADDRESS:
    266   case STUN_ATTR_CHANGED_ADDRESS:
    267   case STUN_ATTR_REFLECTED_FROM:
    268   case STUN_ATTR_ALTERNATE_SERVER:
    269   case STUN_ATTR_DESTINATION_ADDRESS:
    270   case STUN_ATTR_SOURCE_ADDRESS2:
    271     return new StunAddressAttribute(type);
    272 
    273   default:
    274     ASSERT(false);
    275     return 0;
    276   }
    277 }
    278 
    279 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
    280   switch (type) {
    281   case STUN_ATTR_CHANGE_REQUEST:
    282   case STUN_ATTR_LIFETIME:
    283   case STUN_ATTR_BANDWIDTH:
    284   case STUN_ATTR_OPTIONS:
    285     return new StunUInt32Attribute(type);
    286 
    287   default:
    288     ASSERT(false);
    289     return 0;
    290   }
    291 }
    292 
    293 StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) {
    294   switch (type) {
    295   case STUN_ATTR_USERNAME:
    296   case STUN_ATTR_PASSWORD:
    297   case STUN_ATTR_MESSAGE_INTEGRITY:
    298   case STUN_ATTR_DATA:
    299   case STUN_ATTR_MAGIC_COOKIE:
    300     return new StunByteStringAttribute(type, 0);
    301 
    302   default:
    303     ASSERT(false);
    304     return 0;
    305   }
    306 }
    307 
    308 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
    309   return new StunErrorCodeAttribute(
    310       STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
    311 }
    312 
    313 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
    314   return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
    315 }
    316 
    317 StunTransportPrefsAttribute* StunAttribute::CreateTransportPrefs() {
    318   return new StunTransportPrefsAttribute(
    319       STUN_ATTR_TRANSPORT_PREFERENCES, StunTransportPrefsAttribute::SIZE1);
    320 }
    321 
    322 StunAddressAttribute::StunAddressAttribute(uint16 type)
    323     : StunAttribute(type, SIZE), family_(0), port_(0), ip_(0) {
    324 }
    325 
    326 bool StunAddressAttribute::Read(ByteBuffer* buf) {
    327   uint8 dummy;
    328   if (!buf->ReadUInt8(&dummy))
    329     return false;
    330   if (!buf->ReadUInt8(&family_))
    331     return false;
    332   if (!buf->ReadUInt16(&port_))
    333     return false;
    334   if (!buf->ReadUInt32(&ip_))
    335     return false;
    336   return true;
    337 }
    338 
    339 void StunAddressAttribute::Write(ByteBuffer* buf) const {
    340   buf->WriteUInt8(0);
    341   buf->WriteUInt8(family_);
    342   buf->WriteUInt16(port_);
    343   buf->WriteUInt32(ip_);
    344 }
    345 
    346 StunUInt32Attribute::StunUInt32Attribute(uint16 type)
    347     : StunAttribute(type, SIZE), bits_(0) {
    348 }
    349 
    350 bool StunUInt32Attribute::GetBit(int index) const {
    351   ASSERT((0 <= index) && (index < 32));
    352   return static_cast<bool>((bits_ >> index) & 0x1);
    353 }
    354 
    355 void StunUInt32Attribute::SetBit(int index, bool value) {
    356   ASSERT((0 <= index) && (index < 32));
    357   bits_ &= ~(1 << index);
    358   bits_ |= value ? (1 << index) : 0;
    359 }
    360 
    361 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
    362   if (!buf->ReadUInt32(&bits_))
    363     return false;
    364   return true;
    365 }
    366 
    367 void StunUInt32Attribute::Write(ByteBuffer* buf) const {
    368   buf->WriteUInt32(bits_);
    369 }
    370 
    371 StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
    372     : StunAttribute(type, length), bytes_(0) {
    373 }
    374 
    375 StunByteStringAttribute::~StunByteStringAttribute() {
    376   delete [] bytes_;
    377 }
    378 
    379 void StunByteStringAttribute::SetBytes(char* bytes, uint16 length) {
    380   delete [] bytes_;
    381   bytes_ = bytes;
    382   SetLength(length);
    383 }
    384 
    385 void StunByteStringAttribute::CopyBytes(const char* bytes) {
    386   CopyBytes(bytes, static_cast<uint16>(strlen(bytes)));
    387 }
    388 
    389 void StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) {
    390   char* new_bytes = new char[length];
    391   std::memcpy(new_bytes, bytes, length);
    392   SetBytes(new_bytes, length);
    393 }
    394 
    395 uint8 StunByteStringAttribute::GetByte(int index) const {
    396   ASSERT(bytes_ != NULL);
    397   ASSERT((0 <= index) && (index < length()));
    398   return static_cast<uint8>(bytes_[index]);
    399 }
    400 
    401 void StunByteStringAttribute::SetByte(int index, uint8 value) {
    402   ASSERT(bytes_ != NULL);
    403   ASSERT((0 <= index) && (index < length()));
    404   bytes_[index] = value;
    405 }
    406 
    407 bool StunByteStringAttribute::Read(ByteBuffer* buf) {
    408   bytes_ = new char[length()];
    409   if (!buf->ReadBytes(bytes_, length()))
    410     return false;
    411   return true;
    412 }
    413 
    414 void StunByteStringAttribute::Write(ByteBuffer* buf) const {
    415   buf->WriteBytes(bytes_, length());
    416 }
    417 
    418 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
    419     : StunAttribute(type, length), class_(0), number_(0) {
    420 }
    421 
    422 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
    423 }
    424 
    425 void StunErrorCodeAttribute::SetErrorCode(uint32 code) {
    426   class_ = (uint8)((code >> 8) & 0x7);
    427   number_ = (uint8)(code & 0xff);
    428 }
    429 
    430 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
    431   SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
    432   reason_ = reason;
    433 }
    434 
    435 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
    436   uint32 val;
    437   if (!buf->ReadUInt32(&val))
    438     return false;
    439 
    440   if ((val >> 11) != 0)
    441     LOG(LERROR) << "error-code bits not zero";
    442 
    443   SetErrorCode(val);
    444 
    445   if (!buf->ReadString(&reason_, length() - 4))
    446     return false;
    447 
    448   return true;
    449 }
    450 
    451 void StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
    452   buf->WriteUInt32(error_code());
    453   buf->WriteString(reason_);
    454 }
    455 
    456 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
    457     : StunAttribute(type, length) {
    458   attr_types_ = new std::vector<uint16>();
    459 }
    460 
    461 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
    462   delete attr_types_;
    463 }
    464 
    465 size_t StunUInt16ListAttribute::Size() const {
    466   return attr_types_->size();
    467 }
    468 
    469 uint16 StunUInt16ListAttribute::GetType(int index) const {
    470   return (*attr_types_)[index];
    471 }
    472 
    473 void StunUInt16ListAttribute::SetType(int index, uint16 value) {
    474   (*attr_types_)[index] = value;
    475 }
    476 
    477 void StunUInt16ListAttribute::AddType(uint16 value) {
    478   attr_types_->push_back(value);
    479   SetLength(static_cast<uint16>(attr_types_->size() * 2));
    480 }
    481 
    482 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
    483   for (int i = 0; i < length() / 2; i++) {
    484     uint16 attr;
    485     if (!buf->ReadUInt16(&attr))
    486       return false;
    487     attr_types_->push_back(attr);
    488   }
    489   return true;
    490 }
    491 
    492 void StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
    493   for (unsigned i = 0; i < attr_types_->size(); i++)
    494     buf->WriteUInt16((*attr_types_)[i]);
    495 }
    496 
    497 StunTransportPrefsAttribute::StunTransportPrefsAttribute(
    498     uint16 type, uint16 length)
    499     : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) {
    500 }
    501 
    502 StunTransportPrefsAttribute::~StunTransportPrefsAttribute() {
    503   delete addr_;
    504 }
    505 
    506 void StunTransportPrefsAttribute::SetPreallocateAddress(
    507     StunAddressAttribute* addr) {
    508   if (!addr) {
    509     preallocate_ = false;
    510     addr_ = 0;
    511     SetLength(SIZE1);
    512   } else {
    513     preallocate_ = true;
    514     addr_ = addr;
    515     SetLength(SIZE2);
    516   }
    517 }
    518 
    519 bool StunTransportPrefsAttribute::Read(ByteBuffer* buf) {
    520   uint32 val;
    521   if (!buf->ReadUInt32(&val))
    522     return false;
    523 
    524   if ((val >> 3) != 0)
    525     LOG(LERROR) << "transport-preferences bits not zero";
    526 
    527   preallocate_ = static_cast<bool>((val >> 2) & 0x1);
    528   prefs_ = (uint8)(val & 0x3);
    529 
    530   if (preallocate_ && (prefs_ == 3))
    531     LOG(LERROR) << "transport-preferences imcompatible P and Typ";
    532 
    533   if (!preallocate_) {
    534     if (length() != StunUInt32Attribute::SIZE)
    535       return false;
    536   } else {
    537     if (length() != StunUInt32Attribute::SIZE + StunAddressAttribute::SIZE)
    538       return false;
    539 
    540     addr_ = new StunAddressAttribute(STUN_ATTR_SOURCE_ADDRESS);
    541     addr_->Read(buf);
    542   }
    543 
    544   return true;
    545 }
    546 
    547 void StunTransportPrefsAttribute::Write(ByteBuffer* buf) const {
    548   buf->WriteUInt32((preallocate_ ? 4 : 0) | prefs_);
    549 
    550   if (preallocate_)
    551     addr_->Write(buf);
    552 }
    553 
    554 StunMessageType GetStunResponseType(StunMessageType request_type) {
    555   switch (request_type) {
    556   case STUN_SHARED_SECRET_REQUEST:
    557     return STUN_SHARED_SECRET_RESPONSE;
    558   case STUN_ALLOCATE_REQUEST:
    559     return STUN_ALLOCATE_RESPONSE;
    560   case STUN_SEND_REQUEST:
    561     return STUN_SEND_RESPONSE;
    562   default:
    563     return STUN_BINDING_RESPONSE;
    564   }
    565 }
    566 
    567 StunMessageType GetStunErrorResponseType(StunMessageType request_type) {
    568   switch (request_type) {
    569   case STUN_SHARED_SECRET_REQUEST:
    570     return STUN_SHARED_SECRET_ERROR_RESPONSE;
    571   case STUN_ALLOCATE_REQUEST:
    572     return STUN_ALLOCATE_ERROR_RESPONSE;
    573   case STUN_SEND_REQUEST:
    574     return STUN_SEND_ERROR_RESPONSE;
    575   default:
    576     return STUN_BINDING_ERROR_RESPONSE;
    577   }
    578 }
    579 
    580 } // namespace cricket
    581