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/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_array<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 (std::memcmp(data + current_pos + kStunAttributeHeaderSize, 221 hmac, sizeof(hmac)) == 0); 222 } 223 224 bool StunMessage::AddMessageIntegrity(const std::string& password) { 225 return AddMessageIntegrity(password.c_str(), password.size()); 226 } 227 228 bool StunMessage::AddMessageIntegrity(const char* key, 229 size_t keylen) { 230 // Add the attribute with a dummy value. Since this is a known attribute, it 231 // can't fail. 232 StunByteStringAttribute* msg_integrity_attr = 233 new StunByteStringAttribute(STUN_ATTR_MESSAGE_INTEGRITY, 234 std::string(kStunMessageIntegritySize, '0')); 235 VERIFY(AddAttribute(msg_integrity_attr)); 236 237 // Calculate the HMAC for the message. 238 talk_base::ByteBuffer buf; 239 if (!Write(&buf)) 240 return false; 241 242 int msg_len_for_hmac = static_cast<int>( 243 buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); 244 char hmac[kStunMessageIntegritySize]; 245 size_t ret = talk_base::ComputeHmac(talk_base::DIGEST_SHA_1, 246 key, keylen, 247 buf.Data(), msg_len_for_hmac, 248 hmac, sizeof(hmac)); 249 ASSERT(ret == sizeof(hmac)); 250 if (ret != sizeof(hmac)) { 251 LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity " 252 << "has dummy value."; 253 return false; 254 } 255 256 // Insert correct HMAC into the attribute. 257 msg_integrity_attr->CopyBytes(hmac, sizeof(hmac)); 258 return true; 259 } 260 261 // Verifies a message is in fact a STUN message, by performing the checks 262 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed 263 // in section 15.5. 264 bool StunMessage::ValidateFingerprint(const char* data, size_t size) { 265 // Check the message length. 266 size_t fingerprint_attr_size = 267 kStunAttributeHeaderSize + StunUInt32Attribute::SIZE; 268 if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size) 269 return false; 270 271 // Skip the rest if the magic cookie isn't present. 272 const char* magic_cookie = 273 data + kStunTransactionIdOffset - kStunMagicCookieLength; 274 if (talk_base::GetBE32(magic_cookie) != kStunMagicCookie) 275 return false; 276 277 // Check the fingerprint type and length. 278 const char* fingerprint_attr_data = data + size - fingerprint_attr_size; 279 if (talk_base::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT || 280 talk_base::GetBE16(fingerprint_attr_data + sizeof(uint16)) != 281 StunUInt32Attribute::SIZE) 282 return false; 283 284 // Check the fingerprint value. 285 uint32 fingerprint = 286 talk_base::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize); 287 return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) == 288 talk_base::ComputeCrc32(data, size - fingerprint_attr_size)); 289 } 290 291 bool StunMessage::AddFingerprint() { 292 // Add the attribute with a dummy value. Since this is a known attribute, 293 // it can't fail. 294 StunUInt32Attribute* fingerprint_attr = 295 new StunUInt32Attribute(STUN_ATTR_FINGERPRINT, 0); 296 VERIFY(AddAttribute(fingerprint_attr)); 297 298 // Calculate the CRC-32 for the message and insert it. 299 talk_base::ByteBuffer buf; 300 if (!Write(&buf)) 301 return false; 302 303 int msg_len_for_crc32 = static_cast<int>( 304 buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length()); 305 uint32 c = talk_base::ComputeCrc32(buf.Data(), msg_len_for_crc32); 306 307 // Insert the correct CRC-32, XORed with a constant, into the attribute. 308 fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE); 309 return true; 310 } 311 312 bool StunMessage::Read(ByteBuffer* buf) { 313 if (!buf->ReadUInt16(&type_)) 314 return false; 315 316 if (type_ & 0x8000) { 317 // RTP and RTCP set the MSB of first byte, since first two bits are version, 318 // and version is always 2 (10). If set, this is not a STUN packet. 319 return false; 320 } 321 322 if (!buf->ReadUInt16(&length_)) 323 return false; 324 325 std::string magic_cookie; 326 if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) 327 return false; 328 329 std::string transaction_id; 330 if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) 331 return false; 332 333 uint32 magic_cookie_int = 334 *reinterpret_cast<const uint32*>(magic_cookie.data()); 335 if (talk_base::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) { 336 // If magic cookie is invalid it means that the peer implements 337 // RFC3489 instead of RFC5389. 338 transaction_id.insert(0, magic_cookie); 339 } 340 ASSERT(IsValidTransactionId(transaction_id)); 341 transaction_id_ = transaction_id; 342 343 if (length_ != buf->Length()) 344 return false; 345 346 attrs_->resize(0); 347 348 size_t rest = buf->Length() - length_; 349 while (buf->Length() > rest) { 350 uint16 attr_type, attr_length; 351 if (!buf->ReadUInt16(&attr_type)) 352 return false; 353 if (!buf->ReadUInt16(&attr_length)) 354 return false; 355 356 StunAttribute* attr = CreateAttribute(attr_type, attr_length); 357 if (!attr) { 358 // Skip any unknown or malformed attributes. 359 if ((attr_length % 4) != 0) { 360 attr_length += (4 - (attr_length % 4)); 361 } 362 if (!buf->Consume(attr_length)) 363 return false; 364 } else { 365 if (!attr->Read(buf)) 366 return false; 367 attrs_->push_back(attr); 368 } 369 } 370 371 ASSERT(buf->Length() == rest); 372 return true; 373 } 374 375 bool StunMessage::Write(ByteBuffer* buf) const { 376 buf->WriteUInt16(type_); 377 buf->WriteUInt16(length_); 378 if (!IsLegacy()) 379 buf->WriteUInt32(kStunMagicCookie); 380 buf->WriteString(transaction_id_); 381 382 for (size_t i = 0; i < attrs_->size(); ++i) { 383 buf->WriteUInt16((*attrs_)[i]->type()); 384 buf->WriteUInt16(static_cast<uint16>((*attrs_)[i]->length())); 385 if (!(*attrs_)[i]->Write(buf)) 386 return false; 387 } 388 389 return true; 390 } 391 392 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const { 393 switch (type) { 394 case STUN_ATTR_MAPPED_ADDRESS: return STUN_VALUE_ADDRESS; 395 case STUN_ATTR_USERNAME: return STUN_VALUE_BYTE_STRING; 396 case STUN_ATTR_MESSAGE_INTEGRITY: return STUN_VALUE_BYTE_STRING; 397 case STUN_ATTR_ERROR_CODE: return STUN_VALUE_ERROR_CODE; 398 case STUN_ATTR_UNKNOWN_ATTRIBUTES: return STUN_VALUE_UINT16_LIST; 399 case STUN_ATTR_REALM: return STUN_VALUE_BYTE_STRING; 400 case STUN_ATTR_NONCE: return STUN_VALUE_BYTE_STRING; 401 case STUN_ATTR_XOR_MAPPED_ADDRESS: return STUN_VALUE_XOR_ADDRESS; 402 case STUN_ATTR_SOFTWARE: return STUN_VALUE_BYTE_STRING; 403 case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_BYTE_STRING; 404 case STUN_ATTR_FINGERPRINT: return STUN_VALUE_UINT32; 405 case STUN_ATTR_RETRANSMIT_COUNT: return STUN_VALUE_UINT32; 406 default: return STUN_VALUE_UNKNOWN; 407 } 408 } 409 410 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ { 411 StunAttributeValueType value_type = GetAttributeValueType(type); 412 return StunAttribute::Create(value_type, type, 413 static_cast<uint16>(length), this); 414 } 415 416 const StunAttribute* StunMessage::GetAttribute(int type) const { 417 for (size_t i = 0; i < attrs_->size(); ++i) { 418 if ((*attrs_)[i]->type() == type) 419 return (*attrs_)[i]; 420 } 421 return NULL; 422 } 423 424 bool StunMessage::IsValidTransactionId(const std::string& transaction_id) { 425 return transaction_id.size() == kStunTransactionIdLength || 426 transaction_id.size() == kStunLegacyTransactionIdLength; 427 } 428 429 // StunAttribute 430 431 StunAttribute::StunAttribute(uint16 type, uint16 length) 432 : type_(type), length_(length) { 433 } 434 435 void StunAttribute::ConsumePadding(talk_base::ByteBuffer* buf) const { 436 int remainder = length_ % 4; 437 if (remainder > 0) { 438 buf->Consume(4 - remainder); 439 } 440 } 441 442 void StunAttribute::WritePadding(talk_base::ByteBuffer* buf) const { 443 int remainder = length_ % 4; 444 if (remainder > 0) { 445 char zeroes[4] = {0}; 446 buf->WriteBytes(zeroes, 4 - remainder); 447 } 448 } 449 450 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type, 451 uint16 type, uint16 length, 452 StunMessage* owner) { 453 switch (value_type) { 454 case STUN_VALUE_ADDRESS: 455 return new StunAddressAttribute(type, length); 456 case STUN_VALUE_XOR_ADDRESS: 457 return new StunXorAddressAttribute(type, length, owner); 458 case STUN_VALUE_UINT32: 459 return new StunUInt32Attribute(type); 460 case STUN_VALUE_UINT64: 461 return new StunUInt64Attribute(type); 462 case STUN_VALUE_BYTE_STRING: 463 return new StunByteStringAttribute(type, length); 464 case STUN_VALUE_ERROR_CODE: 465 return new StunErrorCodeAttribute(type, length); 466 case STUN_VALUE_UINT16_LIST: 467 return new StunUInt16ListAttribute(type, length); 468 default: 469 return NULL; 470 } 471 } 472 473 StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) { 474 return new StunAddressAttribute(type, 0); 475 } 476 477 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16 type) { 478 return new StunXorAddressAttribute(type, 0, NULL); 479 } 480 481 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16 type) { 482 return new StunUInt64Attribute(type); 483 } 484 485 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) { 486 return new StunUInt32Attribute(type); 487 } 488 489 StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) { 490 return new StunByteStringAttribute(type, 0); 491 } 492 493 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() { 494 return new StunErrorCodeAttribute( 495 STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE); 496 } 497 498 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() { 499 return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0); 500 } 501 502 StunAddressAttribute::StunAddressAttribute(uint16 type, 503 const talk_base::SocketAddress& addr) 504 : StunAttribute(type, 0) { 505 SetAddress(addr); 506 } 507 508 StunAddressAttribute::StunAddressAttribute(uint16 type, uint16 length) 509 : StunAttribute(type, length) { 510 } 511 512 bool StunAddressAttribute::Read(ByteBuffer* buf) { 513 uint8 dummy; 514 if (!buf->ReadUInt8(&dummy)) 515 return false; 516 517 uint8 stun_family; 518 if (!buf->ReadUInt8(&stun_family)) { 519 return false; 520 } 521 uint16 port; 522 if (!buf->ReadUInt16(&port)) 523 return false; 524 if (stun_family == STUN_ADDRESS_IPV4) { 525 in_addr v4addr; 526 if (length() != SIZE_IP4) { 527 return false; 528 } 529 if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) { 530 return false; 531 } 532 talk_base::IPAddress ipaddr(v4addr); 533 SetAddress(talk_base::SocketAddress(ipaddr, port)); 534 } else if (stun_family == STUN_ADDRESS_IPV6) { 535 in6_addr v6addr; 536 if (length() != SIZE_IP6) { 537 return false; 538 } 539 if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) { 540 return false; 541 } 542 talk_base::IPAddress ipaddr(v6addr); 543 SetAddress(talk_base::SocketAddress(ipaddr, port)); 544 } else { 545 return false; 546 } 547 return true; 548 } 549 550 bool StunAddressAttribute::Write(ByteBuffer* buf) const { 551 StunAddressFamily address_family = family(); 552 if (address_family == STUN_ADDRESS_UNDEF) { 553 LOG(LS_ERROR) << "Error writing address attribute: unknown family."; 554 return false; 555 } 556 buf->WriteUInt8(0); 557 buf->WriteUInt8(address_family); 558 buf->WriteUInt16(address_.port()); 559 switch (address_.family()) { 560 case AF_INET: { 561 in_addr v4addr = address_.ipaddr().ipv4_address(); 562 buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr)); 563 break; 564 } 565 case AF_INET6: { 566 in6_addr v6addr = address_.ipaddr().ipv6_address(); 567 buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr)); 568 break; 569 } 570 } 571 return true; 572 } 573 574 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type, 575 const talk_base::SocketAddress& addr) 576 : StunAddressAttribute(type, addr), owner_(NULL) { 577 } 578 579 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type, 580 uint16 length, 581 StunMessage* owner) 582 : StunAddressAttribute(type, length), owner_(owner) {} 583 584 talk_base::IPAddress StunXorAddressAttribute::GetXoredIP() const { 585 if (owner_) { 586 talk_base::IPAddress ip = ipaddr(); 587 switch (ip.family()) { 588 case AF_INET: { 589 in_addr v4addr = ip.ipv4_address(); 590 v4addr.s_addr = 591 (v4addr.s_addr ^ talk_base::HostToNetwork32(kStunMagicCookie)); 592 return talk_base::IPAddress(v4addr); 593 } 594 case AF_INET6: { 595 in6_addr v6addr = ip.ipv6_address(); 596 const std::string& transaction_id = owner_->transaction_id(); 597 if (transaction_id.length() == kStunTransactionIdLength) { 598 uint32 transactionid_as_ints[3]; 599 memcpy(&transactionid_as_ints[0], transaction_id.c_str(), 600 transaction_id.length()); 601 uint32* ip_as_ints = reinterpret_cast<uint32*>(&v6addr.s6_addr); 602 // Transaction ID is in network byte order, but magic cookie 603 // is stored in host byte order. 604 ip_as_ints[0] = 605 (ip_as_ints[0] ^ talk_base::HostToNetwork32(kStunMagicCookie)); 606 ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]); 607 ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]); 608 ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]); 609 return talk_base::IPAddress(v6addr); 610 } 611 break; 612 } 613 } 614 } 615 // Invalid ip family or transaction ID, or missing owner. 616 // Return an AF_UNSPEC address. 617 return talk_base::IPAddress(); 618 } 619 620 bool StunXorAddressAttribute::Read(ByteBuffer* buf) { 621 if (!StunAddressAttribute::Read(buf)) 622 return false; 623 uint16 xoredport = port() ^ (kStunMagicCookie >> 16); 624 talk_base::IPAddress xored_ip = GetXoredIP(); 625 SetAddress(talk_base::SocketAddress(xored_ip, xoredport)); 626 return true; 627 } 628 629 bool StunXorAddressAttribute::Write(ByteBuffer* buf) const { 630 StunAddressFamily address_family = family(); 631 if (address_family == STUN_ADDRESS_UNDEF) { 632 LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family."; 633 return false; 634 } 635 talk_base::IPAddress xored_ip = GetXoredIP(); 636 if (xored_ip.family() == AF_UNSPEC) { 637 return false; 638 } 639 buf->WriteUInt8(0); 640 buf->WriteUInt8(family()); 641 buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16)); 642 switch (xored_ip.family()) { 643 case AF_INET: { 644 in_addr v4addr = xored_ip.ipv4_address(); 645 buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr)); 646 break; 647 } 648 case AF_INET6: { 649 in6_addr v6addr = xored_ip.ipv6_address(); 650 buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr)); 651 break; 652 } 653 } 654 return true; 655 } 656 657 StunUInt32Attribute::StunUInt32Attribute(uint16 type, uint32 value) 658 : StunAttribute(type, SIZE), bits_(value) { 659 } 660 661 StunUInt32Attribute::StunUInt32Attribute(uint16 type) 662 : StunAttribute(type, SIZE), bits_(0) { 663 } 664 665 bool StunUInt32Attribute::GetBit(size_t index) const { 666 ASSERT(index < 32); 667 return static_cast<bool>((bits_ >> index) & 0x1); 668 } 669 670 void StunUInt32Attribute::SetBit(size_t index, bool value) { 671 ASSERT(index < 32); 672 bits_ &= ~(1 << index); 673 bits_ |= value ? (1 << index) : 0; 674 } 675 676 bool StunUInt32Attribute::Read(ByteBuffer* buf) { 677 if (length() != SIZE || !buf->ReadUInt32(&bits_)) 678 return false; 679 return true; 680 } 681 682 bool StunUInt32Attribute::Write(ByteBuffer* buf) const { 683 buf->WriteUInt32(bits_); 684 return true; 685 } 686 687 StunUInt64Attribute::StunUInt64Attribute(uint16 type, uint64 value) 688 : StunAttribute(type, SIZE), bits_(value) { 689 } 690 691 StunUInt64Attribute::StunUInt64Attribute(uint16 type) 692 : StunAttribute(type, SIZE), bits_(0) { 693 } 694 695 bool StunUInt64Attribute::Read(ByteBuffer* buf) { 696 if (length() != SIZE || !buf->ReadUInt64(&bits_)) 697 return false; 698 return true; 699 } 700 701 bool StunUInt64Attribute::Write(ByteBuffer* buf) const { 702 buf->WriteUInt64(bits_); 703 return true; 704 } 705 706 StunByteStringAttribute::StunByteStringAttribute(uint16 type) 707 : StunAttribute(type, 0), bytes_(NULL) { 708 } 709 710 StunByteStringAttribute::StunByteStringAttribute(uint16 type, 711 const std::string& str) 712 : StunAttribute(type, 0), bytes_(NULL) { 713 CopyBytes(str.c_str(), str.size()); 714 } 715 716 StunByteStringAttribute::StunByteStringAttribute(uint16 type, 717 const void* bytes, 718 size_t length) 719 : StunAttribute(type, 0), bytes_(NULL) { 720 CopyBytes(bytes, length); 721 } 722 723 StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length) 724 : StunAttribute(type, length), bytes_(NULL) { 725 } 726 727 StunByteStringAttribute::~StunByteStringAttribute() { 728 delete [] bytes_; 729 } 730 731 void StunByteStringAttribute::CopyBytes(const char* bytes) { 732 CopyBytes(bytes, strlen(bytes)); 733 } 734 735 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { 736 char* new_bytes = new char[length]; 737 std::memcpy(new_bytes, bytes, length); 738 SetBytes(new_bytes, length); 739 } 740 741 uint8 StunByteStringAttribute::GetByte(size_t index) const { 742 ASSERT(bytes_ != NULL); 743 ASSERT(index < length()); 744 return static_cast<uint8>(bytes_[index]); 745 } 746 747 void StunByteStringAttribute::SetByte(size_t index, uint8 value) { 748 ASSERT(bytes_ != NULL); 749 ASSERT(index < length()); 750 bytes_[index] = value; 751 } 752 753 bool StunByteStringAttribute::Read(ByteBuffer* buf) { 754 bytes_ = new char[length()]; 755 if (!buf->ReadBytes(bytes_, length())) { 756 return false; 757 } 758 759 ConsumePadding(buf); 760 return true; 761 } 762 763 bool StunByteStringAttribute::Write(ByteBuffer* buf) const { 764 buf->WriteBytes(bytes_, length()); 765 WritePadding(buf); 766 return true; 767 } 768 769 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) { 770 delete [] bytes_; 771 bytes_ = bytes; 772 SetLength(static_cast<uint16>(length)); 773 } 774 775 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, int code, 776 const std::string& reason) 777 : StunAttribute(type, 0) { 778 SetCode(code); 779 SetReason(reason); 780 } 781 782 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length) 783 : StunAttribute(type, length), class_(0), number_(0) { 784 } 785 786 StunErrorCodeAttribute::~StunErrorCodeAttribute() { 787 } 788 789 int StunErrorCodeAttribute::code() const { 790 return class_ * 100 + number_; 791 } 792 793 void StunErrorCodeAttribute::SetCode(int code) { 794 class_ = static_cast<uint8>(code / 100); 795 number_ = static_cast<uint8>(code % 100); 796 } 797 798 void StunErrorCodeAttribute::SetReason(const std::string& reason) { 799 SetLength(MIN_SIZE + static_cast<uint16>(reason.size())); 800 reason_ = reason; 801 } 802 803 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) { 804 uint32 val; 805 if (length() < MIN_SIZE || !buf->ReadUInt32(&val)) 806 return false; 807 808 if ((val >> 11) != 0) 809 LOG(LS_ERROR) << "error-code bits not zero"; 810 811 class_ = ((val >> 8) & 0x7); 812 number_ = (val & 0xff); 813 814 if (!buf->ReadString(&reason_, length() - 4)) 815 return false; 816 817 ConsumePadding(buf); 818 return true; 819 } 820 821 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const { 822 buf->WriteUInt32(class_ << 8 | number_); 823 buf->WriteString(reason_); 824 WritePadding(buf); 825 return true; 826 } 827 828 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length) 829 : StunAttribute(type, length) { 830 attr_types_ = new std::vector<uint16>(); 831 } 832 833 StunUInt16ListAttribute::~StunUInt16ListAttribute() { 834 delete attr_types_; 835 } 836 837 size_t StunUInt16ListAttribute::Size() const { 838 return attr_types_->size(); 839 } 840 841 uint16 StunUInt16ListAttribute::GetType(int index) const { 842 return (*attr_types_)[index]; 843 } 844 845 void StunUInt16ListAttribute::SetType(int index, uint16 value) { 846 (*attr_types_)[index] = value; 847 } 848 849 void StunUInt16ListAttribute::AddType(uint16 value) { 850 attr_types_->push_back(value); 851 SetLength(static_cast<uint16>(attr_types_->size() * 2)); 852 } 853 854 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) { 855 if (length() % 2) 856 return false; 857 858 for (size_t i = 0; i < length() / 2; i++) { 859 uint16 attr; 860 if (!buf->ReadUInt16(&attr)) 861 return false; 862 attr_types_->push_back(attr); 863 } 864 // Padding of these attributes is done in RFC 5389 style. This is 865 // slightly different from RFC3489, but it shouldn't be important. 866 // RFC3489 pads out to a 32 bit boundary by duplicating one of the 867 // entries in the list (not necessarily the last one - it's unspecified). 868 // RFC5389 pads on the end, and the bytes are always ignored. 869 ConsumePadding(buf); 870 return true; 871 } 872 873 bool StunUInt16ListAttribute::Write(ByteBuffer* buf) const { 874 for (size_t i = 0; i < attr_types_->size(); ++i) { 875 buf->WriteUInt16((*attr_types_)[i]); 876 } 877 WritePadding(buf); 878 return true; 879 } 880 881 int GetStunSuccessResponseType(int req_type) { 882 return IsStunRequestType(req_type) ? (req_type | 0x100) : -1; 883 } 884 885 int GetStunErrorResponseType(int req_type) { 886 return IsStunRequestType(req_type) ? (req_type | 0x110) : -1; 887 } 888 889 bool IsStunRequestType(int msg_type) { 890 return ((msg_type & kStunTypeMask) == 0x000); 891 } 892 893 bool IsStunIndicationType(int msg_type) { 894 return ((msg_type & kStunTypeMask) == 0x010); 895 } 896 897 bool IsStunSuccessResponseType(int msg_type) { 898 return ((msg_type & kStunTypeMask) == 0x100); 899 } 900 901 bool IsStunErrorResponseType(int msg_type) { 902 return ((msg_type & kStunTypeMask) == 0x110); 903 } 904 905 bool ComputeStunCredentialHash(const std::string& username, 906 const std::string& realm, 907 const std::string& password, 908 std::string* hash) { 909 // http://tools.ietf.org/html/rfc5389#section-15.4 910 // long-term credentials will be calculated using the key and key is 911 // key = MD5(username ":" realm ":" SASLprep(password)) 912 std::string input = username; 913 input += ':'; 914 input += realm; 915 input += ':'; 916 input += password; 917 918 char digest[talk_base::MessageDigest::kMaxSize]; 919 size_t size = talk_base::ComputeDigest( 920 talk_base::DIGEST_MD5, input.c_str(), input.size(), 921 digest, sizeof(digest)); 922 if (size == 0) { 923 return false; 924 } 925 926 *hash = std::string(digest, size); 927 return true; 928 } 929 930 } // namespace cricket 931