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