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