1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/p2p/base/stun.h" 12 13 #include <string.h> 14 15 #include "webrtc/base/byteorder.h" 16 #include "webrtc/base/common.h" 17 #include "webrtc/base/crc32.h" 18 #include "webrtc/base/logging.h" 19 #include "webrtc/base/messagedigest.h" 20 #include "webrtc/base/scoped_ptr.h" 21 #include "webrtc/base/stringencode.h" 22 23 using rtc::ByteBuffer; 24 25 namespace cricket { 26 27 const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server"; 28 const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request"; 29 const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized"; 30 const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden"; 31 const char STUN_ERROR_REASON_STALE_CREDENTIALS[] = "Stale Credentials"; 32 const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch"; 33 const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce"; 34 const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials"; 35 const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol"; 36 const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict"; 37 const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error"; 38 39 const char TURN_MAGIC_COOKIE_VALUE[] = { '\x72', '\xC6', '\x4B', '\xC6' }; 40 const char EMPTY_TRANSACTION_ID[] = "0000000000000000"; 41 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E; 42 43 // StunMessage 44 45 StunMessage::StunMessage() 46 : type_(0), 47 length_(0), 48 transaction_id_(EMPTY_TRANSACTION_ID) { 49 ASSERT(IsValidTransactionId(transaction_id_)); 50 attrs_ = new std::vector<StunAttribute*>(); 51 } 52 53 StunMessage::~StunMessage() { 54 for (size_t i = 0; i < attrs_->size(); i++) 55 delete (*attrs_)[i]; 56 delete attrs_; 57 } 58 59 bool StunMessage::IsLegacy() const { 60 if (transaction_id_.size() == kStunLegacyTransactionIdLength) 61 return true; 62 ASSERT(transaction_id_.size() == kStunTransactionIdLength); 63 return false; 64 } 65 66 bool StunMessage::SetTransactionID(const std::string& str) { 67 if (!IsValidTransactionId(str)) { 68 return false; 69 } 70 transaction_id_ = str; 71 return true; 72 } 73 74 bool StunMessage::AddAttribute(StunAttribute* attr) { 75 // Fail any attributes that aren't valid for this type of message. 76 if (attr->value_type() != GetAttributeValueType(attr->type())) { 77 return false; 78 } 79 attrs_->push_back(attr); 80 attr->SetOwner(this); 81 size_t attr_length = attr->length(); 82 if (attr_length % 4 != 0) { 83 attr_length += (4 - (attr_length % 4)); 84 } 85 length_ += static_cast<uint16_t>(attr_length + 4); 86 return true; 87 } 88 89 const StunAddressAttribute* StunMessage::GetAddress(int type) const { 90 switch (type) { 91 case STUN_ATTR_MAPPED_ADDRESS: { 92 // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is 93 // missing. 94 const StunAttribute* mapped_address = 95 GetAttribute(STUN_ATTR_MAPPED_ADDRESS); 96 if (!mapped_address) 97 mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS); 98 return reinterpret_cast<const StunAddressAttribute*>(mapped_address); 99 } 100 101 default: 102 return static_cast<const StunAddressAttribute*>(GetAttribute(type)); 103 } 104 } 105 106 const StunUInt32Attribute* StunMessage::GetUInt32(int type) const { 107 return static_cast<const StunUInt32Attribute*>(GetAttribute(type)); 108 } 109 110 const StunUInt64Attribute* StunMessage::GetUInt64(int type) const { 111 return static_cast<const StunUInt64Attribute*>(GetAttribute(type)); 112 } 113 114 const StunByteStringAttribute* StunMessage::GetByteString(int type) const { 115 return static_cast<const StunByteStringAttribute*>(GetAttribute(type)); 116 } 117 118 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const { 119 return static_cast<const StunErrorCodeAttribute*>( 120 GetAttribute(STUN_ATTR_ERROR_CODE)); 121 } 122 123 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const { 124 return static_cast<const StunUInt16ListAttribute*>( 125 GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES)); 126 } 127 128 // Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the 129 // procedure outlined in RFC 5389, section 15.4. 130 bool StunMessage::ValidateMessageIntegrity(const char* data, size_t size, 131 const std::string& password) { 132 // Verifying the size of the message. 133 if ((size % 4) != 0) { 134 return false; 135 } 136 137 // Getting the message length from the STUN header. 138 uint16_t msg_length = rtc::GetBE16(&data[2]); 139 if (size != (msg_length + kStunHeaderSize)) { 140 return false; 141 } 142 143 // Finding Message Integrity attribute in stun message. 144 size_t current_pos = kStunHeaderSize; 145 bool has_message_integrity_attr = false; 146 while (current_pos < size) { 147 uint16_t attr_type, attr_length; 148 // Getting attribute type and length. 149 attr_type = rtc::GetBE16(&data[current_pos]); 150 attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]); 151 152 // If M-I, sanity check it, and break out. 153 if (attr_type == STUN_ATTR_MESSAGE_INTEGRITY) { 154 if (attr_length != kStunMessageIntegritySize || 155 current_pos + attr_length > size) { 156 return false; 157 } 158 has_message_integrity_attr = true; 159 break; 160 } 161 162 // Otherwise, skip to the next attribute. 163 current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length; 164 if ((attr_length % 4) != 0) { 165 current_pos += (4 - (attr_length % 4)); 166 } 167 } 168 169 if (!has_message_integrity_attr) { 170 return false; 171 } 172 173 // Getting length of the message to calculate Message Integrity. 174 size_t mi_pos = current_pos; 175 rtc::scoped_ptr<char[]> temp_data(new char[current_pos]); 176 memcpy(temp_data.get(), data, current_pos); 177 if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) { 178 // Stun message has other attributes after message integrity. 179 // Adjust the length parameter in stun message to calculate HMAC. 180 size_t extra_offset = size - 181 (mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize); 182 size_t new_adjusted_len = size - extra_offset - kStunHeaderSize; 183 184 // Writing new length of the STUN message @ Message Length in temp buffer. 185 // 0 1 2 3 186 // 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 187 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 188 // |0 0| STUN Message Type | Message Length | 189 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 190 rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len)); 191 } 192 193 char hmac[kStunMessageIntegritySize]; 194 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, 195 password.c_str(), password.size(), 196 temp_data.get(), mi_pos, 197 hmac, sizeof(hmac)); 198 ASSERT(ret == sizeof(hmac)); 199 if (ret != sizeof(hmac)) 200 return false; 201 202 // Comparing the calculated HMAC with the one present in the message. 203 return memcmp(data + current_pos + kStunAttributeHeaderSize, 204 hmac, 205 sizeof(hmac)) == 0; 206 } 207 208 bool StunMessage::AddMessageIntegrity(const std::string& password) { 209 return AddMessageIntegrity(password.c_str(), password.size()); 210 } 211 212 bool StunMessage::AddMessageIntegrity(const char* key, 213 size_t keylen) { 214 // Add the attribute with a dummy value. Since this is a known attribute, it 215 // can't fail. 216 StunByteStringAttribute* msg_integrity_attr = 217 new StunByteStringAttribute(STUN_ATTR_MESSAGE_INTEGRITY, 218 std::string(kStunMessageIntegritySize, '0')); 219 VERIFY(AddAttribute(msg_integrity_attr)); 220 221 // Calculate the HMAC for the message. 222 rtc::ByteBuffer buf; 223 if (!Write(&buf)) 224 return false; 225 226 int msg_len_for_hmac = static_cast<int>( 227 buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); 228 char hmac[kStunMessageIntegritySize]; 229 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, 230 key, keylen, 231 buf.Data(), msg_len_for_hmac, 232 hmac, sizeof(hmac)); 233 ASSERT(ret == sizeof(hmac)); 234 if (ret != sizeof(hmac)) { 235 LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity " 236 << "has dummy value."; 237 return false; 238 } 239 240 // Insert correct HMAC into the attribute. 241 msg_integrity_attr->CopyBytes(hmac, sizeof(hmac)); 242 return true; 243 } 244 245 // Verifies a message is in fact a STUN message, by performing the checks 246 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed 247 // in section 15.5. 248 bool StunMessage::ValidateFingerprint(const char* data, size_t size) { 249 // Check the message length. 250 size_t fingerprint_attr_size = 251 kStunAttributeHeaderSize + StunUInt32Attribute::SIZE; 252 if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size) 253 return false; 254 255 // Skip the rest if the magic cookie isn't present. 256 const char* magic_cookie = 257 data + kStunTransactionIdOffset - kStunMagicCookieLength; 258 if (rtc::GetBE32(magic_cookie) != kStunMagicCookie) 259 return false; 260 261 // Check the fingerprint type and length. 262 const char* fingerprint_attr_data = data + size - fingerprint_attr_size; 263 if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT || 264 rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) != 265 StunUInt32Attribute::SIZE) 266 return false; 267 268 // Check the fingerprint value. 269 uint32_t fingerprint = 270 rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize); 271 return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) == 272 rtc::ComputeCrc32(data, size - fingerprint_attr_size)); 273 } 274 275 bool StunMessage::AddFingerprint() { 276 // Add the attribute with a dummy value. Since this is a known attribute, 277 // it can't fail. 278 StunUInt32Attribute* fingerprint_attr = 279 new StunUInt32Attribute(STUN_ATTR_FINGERPRINT, 0); 280 VERIFY(AddAttribute(fingerprint_attr)); 281 282 // Calculate the CRC-32 for the message and insert it. 283 rtc::ByteBuffer buf; 284 if (!Write(&buf)) 285 return false; 286 287 int msg_len_for_crc32 = static_cast<int>( 288 buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length()); 289 uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32); 290 291 // Insert the correct CRC-32, XORed with a constant, into the attribute. 292 fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE); 293 return true; 294 } 295 296 bool StunMessage::Read(ByteBuffer* buf) { 297 if (!buf->ReadUInt16(&type_)) 298 return false; 299 300 if (type_ & 0x8000) { 301 // RTP and RTCP set the MSB of first byte, since first two bits are version, 302 // and version is always 2 (10). If set, this is not a STUN packet. 303 return false; 304 } 305 306 if (!buf->ReadUInt16(&length_)) 307 return false; 308 309 std::string magic_cookie; 310 if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) 311 return false; 312 313 std::string transaction_id; 314 if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) 315 return false; 316 317 uint32_t magic_cookie_int = 318 *reinterpret_cast<const uint32_t*>(magic_cookie.data()); 319 if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) { 320 // If magic cookie is invalid it means that the peer implements 321 // RFC3489 instead of RFC5389. 322 transaction_id.insert(0, magic_cookie); 323 } 324 ASSERT(IsValidTransactionId(transaction_id)); 325 transaction_id_ = transaction_id; 326 327 if (length_ != buf->Length()) 328 return false; 329 330 attrs_->resize(0); 331 332 size_t rest = buf->Length() - length_; 333 while (buf->Length() > rest) { 334 uint16_t attr_type, attr_length; 335 if (!buf->ReadUInt16(&attr_type)) 336 return false; 337 if (!buf->ReadUInt16(&attr_length)) 338 return false; 339 340 StunAttribute* attr = CreateAttribute(attr_type, attr_length); 341 if (!attr) { 342 // Skip any unknown or malformed attributes. 343 if ((attr_length % 4) != 0) { 344 attr_length += (4 - (attr_length % 4)); 345 } 346 if (!buf->Consume(attr_length)) 347 return false; 348 } else { 349 if (!attr->Read(buf)) 350 return false; 351 attrs_->push_back(attr); 352 } 353 } 354 355 ASSERT(buf->Length() == rest); 356 return true; 357 } 358 359 bool StunMessage::Write(ByteBuffer* buf) const { 360 buf->WriteUInt16(type_); 361 buf->WriteUInt16(length_); 362 if (!IsLegacy()) 363 buf->WriteUInt32(kStunMagicCookie); 364 buf->WriteString(transaction_id_); 365 366 for (size_t i = 0; i < attrs_->size(); ++i) { 367 buf->WriteUInt16((*attrs_)[i]->type()); 368 buf->WriteUInt16(static_cast<uint16_t>((*attrs_)[i]->length())); 369 if (!(*attrs_)[i]->Write(buf)) 370 return false; 371 } 372 373 return true; 374 } 375 376 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const { 377 switch (type) { 378 case STUN_ATTR_MAPPED_ADDRESS: return STUN_VALUE_ADDRESS; 379 case STUN_ATTR_USERNAME: return STUN_VALUE_BYTE_STRING; 380 case STUN_ATTR_MESSAGE_INTEGRITY: return STUN_VALUE_BYTE_STRING; 381 case STUN_ATTR_ERROR_CODE: return STUN_VALUE_ERROR_CODE; 382 case STUN_ATTR_UNKNOWN_ATTRIBUTES: return STUN_VALUE_UINT16_LIST; 383 case STUN_ATTR_REALM: return STUN_VALUE_BYTE_STRING; 384 case STUN_ATTR_NONCE: return STUN_VALUE_BYTE_STRING; 385 case STUN_ATTR_XOR_MAPPED_ADDRESS: return STUN_VALUE_XOR_ADDRESS; 386 case STUN_ATTR_SOFTWARE: return STUN_VALUE_BYTE_STRING; 387 case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_ADDRESS; 388 case STUN_ATTR_FINGERPRINT: return STUN_VALUE_UINT32; 389 case STUN_ATTR_ORIGIN: return STUN_VALUE_BYTE_STRING; 390 case STUN_ATTR_RETRANSMIT_COUNT: return STUN_VALUE_UINT32; 391 default: return STUN_VALUE_UNKNOWN; 392 } 393 } 394 395 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ { 396 StunAttributeValueType value_type = GetAttributeValueType(type); 397 return StunAttribute::Create(value_type, type, static_cast<uint16_t>(length), 398 this); 399 } 400 401 const StunAttribute* StunMessage::GetAttribute(int type) const { 402 for (size_t i = 0; i < attrs_->size(); ++i) { 403 if ((*attrs_)[i]->type() == type) 404 return (*attrs_)[i]; 405 } 406 return NULL; 407 } 408 409 bool StunMessage::IsValidTransactionId(const std::string& transaction_id) { 410 return transaction_id.size() == kStunTransactionIdLength || 411 transaction_id.size() == kStunLegacyTransactionIdLength; 412 } 413 414 // StunAttribute 415 416 StunAttribute::StunAttribute(uint16_t type, uint16_t length) 417 : type_(type), length_(length) { 418 } 419 420 void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const { 421 int remainder = length_ % 4; 422 if (remainder > 0) { 423 buf->Consume(4 - remainder); 424 } 425 } 426 427 void StunAttribute::WritePadding(rtc::ByteBuffer* buf) const { 428 int remainder = length_ % 4; 429 if (remainder > 0) { 430 char zeroes[4] = {0}; 431 buf->WriteBytes(zeroes, 4 - remainder); 432 } 433 } 434 435 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type, 436 uint16_t type, 437 uint16_t length, 438 StunMessage* owner) { 439 switch (value_type) { 440 case STUN_VALUE_ADDRESS: 441 return new StunAddressAttribute(type, length); 442 case STUN_VALUE_XOR_ADDRESS: 443 return new StunXorAddressAttribute(type, length, owner); 444 case STUN_VALUE_UINT32: 445 return new StunUInt32Attribute(type); 446 case STUN_VALUE_UINT64: 447 return new StunUInt64Attribute(type); 448 case STUN_VALUE_BYTE_STRING: 449 return new StunByteStringAttribute(type, length); 450 case STUN_VALUE_ERROR_CODE: 451 return new StunErrorCodeAttribute(type, length); 452 case STUN_VALUE_UINT16_LIST: 453 return new StunUInt16ListAttribute(type, length); 454 default: 455 return NULL; 456 } 457 } 458 459 StunAddressAttribute* StunAttribute::CreateAddress(uint16_t type) { 460 return new StunAddressAttribute(type, 0); 461 } 462 463 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16_t type) { 464 return new StunXorAddressAttribute(type, 0, NULL); 465 } 466 467 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16_t type) { 468 return new StunUInt64Attribute(type); 469 } 470 471 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16_t type) { 472 return new StunUInt32Attribute(type); 473 } 474 475 StunByteStringAttribute* StunAttribute::CreateByteString(uint16_t type) { 476 return new StunByteStringAttribute(type, 0); 477 } 478 479 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() { 480 return new StunErrorCodeAttribute( 481 STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE); 482 } 483 484 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() { 485 return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0); 486 } 487 488 StunAddressAttribute::StunAddressAttribute(uint16_t type, 489 const rtc::SocketAddress& addr) 490 : StunAttribute(type, 0) { 491 SetAddress(addr); 492 } 493 494 StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length) 495 : StunAttribute(type, length) { 496 } 497 498 bool StunAddressAttribute::Read(ByteBuffer* buf) { 499 uint8_t dummy; 500 if (!buf->ReadUInt8(&dummy)) 501 return false; 502 503 uint8_t stun_family; 504 if (!buf->ReadUInt8(&stun_family)) { 505 return false; 506 } 507 uint16_t port; 508 if (!buf->ReadUInt16(&port)) 509 return false; 510 if (stun_family == STUN_ADDRESS_IPV4) { 511 in_addr v4addr; 512 if (length() != SIZE_IP4) { 513 return false; 514 } 515 if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) { 516 return false; 517 } 518 rtc::IPAddress ipaddr(v4addr); 519 SetAddress(rtc::SocketAddress(ipaddr, port)); 520 } else if (stun_family == STUN_ADDRESS_IPV6) { 521 in6_addr v6addr; 522 if (length() != SIZE_IP6) { 523 return false; 524 } 525 if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) { 526 return false; 527 } 528 rtc::IPAddress ipaddr(v6addr); 529 SetAddress(rtc::SocketAddress(ipaddr, port)); 530 } else { 531 return false; 532 } 533 return true; 534 } 535 536 bool StunAddressAttribute::Write(ByteBuffer* buf) const { 537 StunAddressFamily address_family = family(); 538 if (address_family == STUN_ADDRESS_UNDEF) { 539 LOG(LS_ERROR) << "Error writing address attribute: unknown family."; 540 return false; 541 } 542 buf->WriteUInt8(0); 543 buf->WriteUInt8(address_family); 544 buf->WriteUInt16(address_.port()); 545 switch (address_.family()) { 546 case AF_INET: { 547 in_addr v4addr = address_.ipaddr().ipv4_address(); 548 buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr)); 549 break; 550 } 551 case AF_INET6: { 552 in6_addr v6addr = address_.ipaddr().ipv6_address(); 553 buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr)); 554 break; 555 } 556 } 557 return true; 558 } 559 560 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type, 561 const rtc::SocketAddress& addr) 562 : StunAddressAttribute(type, addr), owner_(NULL) { 563 } 564 565 StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type, 566 uint16_t length, 567 StunMessage* owner) 568 : StunAddressAttribute(type, length), owner_(owner) { 569 } 570 571 rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const { 572 if (owner_) { 573 rtc::IPAddress ip = ipaddr(); 574 switch (ip.family()) { 575 case AF_INET: { 576 in_addr v4addr = ip.ipv4_address(); 577 v4addr.s_addr = 578 (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie)); 579 return rtc::IPAddress(v4addr); 580 } 581 case AF_INET6: { 582 in6_addr v6addr = ip.ipv6_address(); 583 const std::string& transaction_id = owner_->transaction_id(); 584 if (transaction_id.length() == kStunTransactionIdLength) { 585 uint32_t transactionid_as_ints[3]; 586 memcpy(&transactionid_as_ints[0], transaction_id.c_str(), 587 transaction_id.length()); 588 uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr); 589 // Transaction ID is in network byte order, but magic cookie 590 // is stored in host byte order. 591 ip_as_ints[0] = 592 (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie)); 593 ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]); 594 ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]); 595 ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]); 596 return rtc::IPAddress(v6addr); 597 } 598 break; 599 } 600 } 601 } 602 // Invalid ip family or transaction ID, or missing owner. 603 // Return an AF_UNSPEC address. 604 return rtc::IPAddress(); 605 } 606 607 bool StunXorAddressAttribute::Read(ByteBuffer* buf) { 608 if (!StunAddressAttribute::Read(buf)) 609 return false; 610 uint16_t xoredport = port() ^ (kStunMagicCookie >> 16); 611 rtc::IPAddress xored_ip = GetXoredIP(); 612 SetAddress(rtc::SocketAddress(xored_ip, xoredport)); 613 return true; 614 } 615 616 bool StunXorAddressAttribute::Write(ByteBuffer* buf) const { 617 StunAddressFamily address_family = family(); 618 if (address_family == STUN_ADDRESS_UNDEF) { 619 LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family."; 620 return false; 621 } 622 rtc::IPAddress xored_ip = GetXoredIP(); 623 if (xored_ip.family() == AF_UNSPEC) { 624 return false; 625 } 626 buf->WriteUInt8(0); 627 buf->WriteUInt8(family()); 628 buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16)); 629 switch (xored_ip.family()) { 630 case AF_INET: { 631 in_addr v4addr = xored_ip.ipv4_address(); 632 buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr)); 633 break; 634 } 635 case AF_INET6: { 636 in6_addr v6addr = xored_ip.ipv6_address(); 637 buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr)); 638 break; 639 } 640 } 641 return true; 642 } 643 644 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value) 645 : StunAttribute(type, SIZE), bits_(value) { 646 } 647 648 StunUInt32Attribute::StunUInt32Attribute(uint16_t type) 649 : StunAttribute(type, SIZE), bits_(0) { 650 } 651 652 bool StunUInt32Attribute::GetBit(size_t index) const { 653 ASSERT(index < 32); 654 return static_cast<bool>((bits_ >> index) & 0x1); 655 } 656 657 void StunUInt32Attribute::SetBit(size_t index, bool value) { 658 ASSERT(index < 32); 659 bits_ &= ~(1 << index); 660 bits_ |= value ? (1 << index) : 0; 661 } 662 663 bool StunUInt32Attribute::Read(ByteBuffer* buf) { 664 if (length() != SIZE || !buf->ReadUInt32(&bits_)) 665 return false; 666 return true; 667 } 668 669 bool StunUInt32Attribute::Write(ByteBuffer* buf) const { 670 buf->WriteUInt32(bits_); 671 return true; 672 } 673 674 StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value) 675 : StunAttribute(type, SIZE), bits_(value) { 676 } 677 678 StunUInt64Attribute::StunUInt64Attribute(uint16_t type) 679 : StunAttribute(type, SIZE), bits_(0) { 680 } 681 682 bool StunUInt64Attribute::Read(ByteBuffer* buf) { 683 if (length() != SIZE || !buf->ReadUInt64(&bits_)) 684 return false; 685 return true; 686 } 687 688 bool StunUInt64Attribute::Write(ByteBuffer* buf) const { 689 buf->WriteUInt64(bits_); 690 return true; 691 } 692 693 StunByteStringAttribute::StunByteStringAttribute(uint16_t type) 694 : StunAttribute(type, 0), bytes_(NULL) { 695 } 696 697 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, 698 const std::string& str) 699 : StunAttribute(type, 0), bytes_(NULL) { 700 CopyBytes(str.c_str(), str.size()); 701 } 702 703 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, 704 const void* bytes, 705 size_t length) 706 : StunAttribute(type, 0), bytes_(NULL) { 707 CopyBytes(bytes, length); 708 } 709 710 StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length) 711 : StunAttribute(type, length), bytes_(NULL) { 712 } 713 714 StunByteStringAttribute::~StunByteStringAttribute() { 715 delete [] bytes_; 716 } 717 718 void StunByteStringAttribute::CopyBytes(const char* bytes) { 719 CopyBytes(bytes, strlen(bytes)); 720 } 721 722 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { 723 char* new_bytes = new char[length]; 724 memcpy(new_bytes, bytes, length); 725 SetBytes(new_bytes, length); 726 } 727 728 uint8_t StunByteStringAttribute::GetByte(size_t index) const { 729 ASSERT(bytes_ != NULL); 730 ASSERT(index < length()); 731 return static_cast<uint8_t>(bytes_[index]); 732 } 733 734 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) { 735 ASSERT(bytes_ != NULL); 736 ASSERT(index < length()); 737 bytes_[index] = value; 738 } 739 740 bool StunByteStringAttribute::Read(ByteBuffer* buf) { 741 bytes_ = new char[length()]; 742 if (!buf->ReadBytes(bytes_, length())) { 743 return false; 744 } 745 746 ConsumePadding(buf); 747 return true; 748 } 749 750 bool StunByteStringAttribute::Write(ByteBuffer* buf) const { 751 buf->WriteBytes(bytes_, length()); 752 WritePadding(buf); 753 return true; 754 } 755 756 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) { 757 delete [] bytes_; 758 bytes_ = bytes; 759 SetLength(static_cast<uint16_t>(length)); 760 } 761 762 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, 763 int code, 764 const std::string& reason) 765 : StunAttribute(type, 0) { 766 SetCode(code); 767 SetReason(reason); 768 } 769 770 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length) 771 : StunAttribute(type, length), class_(0), number_(0) { 772 } 773 774 StunErrorCodeAttribute::~StunErrorCodeAttribute() { 775 } 776 777 int StunErrorCodeAttribute::code() const { 778 return class_ * 100 + number_; 779 } 780 781 void StunErrorCodeAttribute::SetCode(int code) { 782 class_ = static_cast<uint8_t>(code / 100); 783 number_ = static_cast<uint8_t>(code % 100); 784 } 785 786 void StunErrorCodeAttribute::SetReason(const std::string& reason) { 787 SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size())); 788 reason_ = reason; 789 } 790 791 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) { 792 uint32_t val; 793 if (length() < MIN_SIZE || !buf->ReadUInt32(&val)) 794 return false; 795 796 if ((val >> 11) != 0) 797 LOG(LS_ERROR) << "error-code bits not zero"; 798 799 class_ = ((val >> 8) & 0x7); 800 number_ = (val & 0xff); 801 802 if (!buf->ReadString(&reason_, length() - 4)) 803 return false; 804 805 ConsumePadding(buf); 806 return true; 807 } 808 809 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const { 810 buf->WriteUInt32(class_ << 8 | number_); 811 buf->WriteString(reason_); 812 WritePadding(buf); 813 return true; 814 } 815 816 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length) 817 : StunAttribute(type, length) { 818 attr_types_ = new std::vector<uint16_t>(); 819 } 820 821 StunUInt16ListAttribute::~StunUInt16ListAttribute() { 822 delete attr_types_; 823 } 824 825 size_t StunUInt16ListAttribute::Size() const { 826 return attr_types_->size(); 827 } 828 829 uint16_t StunUInt16ListAttribute::GetType(int index) const { 830 return (*attr_types_)[index]; 831 } 832 833 void StunUInt16ListAttribute::SetType(int index, uint16_t value) { 834 (*attr_types_)[index] = value; 835 } 836 837 void StunUInt16ListAttribute::AddType(uint16_t value) { 838 attr_types_->push_back(value); 839 SetLength(static_cast<uint16_t>(attr_types_->size() * 2)); 840 } 841 842 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) { 843 if (length() % 2) 844 return false; 845 846 for (size_t i = 0; i < length() / 2; i++) { 847 uint16_t attr; 848 if (!buf->ReadUInt16(&attr)) 849 return false; 850 attr_types_->push_back(attr); 851 } 852 // Padding of these attributes is done in RFC 5389 style. This is 853 // slightly different from RFC3489, but it shouldn't be important. 854 // RFC3489 pads out to a 32 bit boundary by duplicating one of the 855 // entries in the list (not necessarily the last one - it's unspecified). 856 // RFC5389 pads on the end, and the bytes are always ignored. 857 ConsumePadding(buf); 858 return true; 859 } 860 861 bool StunUInt16ListAttribute::Write(ByteBuffer* buf) const { 862 for (size_t i = 0; i < attr_types_->size(); ++i) { 863 buf->WriteUInt16((*attr_types_)[i]); 864 } 865 WritePadding(buf); 866 return true; 867 } 868 869 int GetStunSuccessResponseType(int req_type) { 870 return IsStunRequestType(req_type) ? (req_type | 0x100) : -1; 871 } 872 873 int GetStunErrorResponseType(int req_type) { 874 return IsStunRequestType(req_type) ? (req_type | 0x110) : -1; 875 } 876 877 bool IsStunRequestType(int msg_type) { 878 return ((msg_type & kStunTypeMask) == 0x000); 879 } 880 881 bool IsStunIndicationType(int msg_type) { 882 return ((msg_type & kStunTypeMask) == 0x010); 883 } 884 885 bool IsStunSuccessResponseType(int msg_type) { 886 return ((msg_type & kStunTypeMask) == 0x100); 887 } 888 889 bool IsStunErrorResponseType(int msg_type) { 890 return ((msg_type & kStunTypeMask) == 0x110); 891 } 892 893 bool ComputeStunCredentialHash(const std::string& username, 894 const std::string& realm, 895 const std::string& password, 896 std::string* hash) { 897 // http://tools.ietf.org/html/rfc5389#section-15.4 898 // long-term credentials will be calculated using the key and key is 899 // key = MD5(username ":" realm ":" SASLprep(password)) 900 std::string input = username; 901 input += ':'; 902 input += realm; 903 input += ':'; 904 input += password; 905 906 char digest[rtc::MessageDigest::kMaxSize]; 907 size_t size = rtc::ComputeDigest( 908 rtc::DIGEST_MD5, input.c_str(), input.size(), 909 digest, sizeof(digest)); 910 if (size == 0) { 911 return false; 912 } 913 914 *hash = std::string(digest, size); 915 return true; 916 } 917 918 } // namespace cricket 919