| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/p2p/base/stun.h" | 11 #include "webrtc/p2p/base/stun.h" |
| 12 | 12 |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 | 14 |
| 15 #include <memory> | 15 #include <memory> |
| 16 | 16 |
| 17 #include "webrtc/base/byteorder.h" | 17 #include "webrtc/base/byteorder.h" |
| 18 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/base/common.h" | 19 #include "webrtc/base/common.h" |
| 19 #include "webrtc/base/crc32.h" | 20 #include "webrtc/base/crc32.h" |
| 20 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
| 21 #include "webrtc/base/messagedigest.h" | 22 #include "webrtc/base/messagedigest.h" |
| 22 #include "webrtc/base/stringencode.h" | 23 #include "webrtc/base/stringencode.h" |
| 23 | 24 |
| 24 using rtc::ByteBufferReader; | 25 using rtc::ByteBufferReader; |
| 25 using rtc::ByteBufferWriter; | 26 using rtc::ByteBufferWriter; |
| 26 | 27 |
| 27 namespace cricket { | 28 namespace cricket { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 41 const char TURN_MAGIC_COOKIE_VALUE[] = { '\x72', '\xC6', '\x4B', '\xC6' }; | 42 const char TURN_MAGIC_COOKIE_VALUE[] = { '\x72', '\xC6', '\x4B', '\xC6' }; |
| 42 const char EMPTY_TRANSACTION_ID[] = "0000000000000000"; | 43 const char EMPTY_TRANSACTION_ID[] = "0000000000000000"; |
| 43 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E; | 44 const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E; |
| 44 | 45 |
| 45 // StunMessage | 46 // StunMessage |
| 46 | 47 |
| 47 StunMessage::StunMessage() | 48 StunMessage::StunMessage() |
| 48 : type_(0), | 49 : type_(0), |
| 49 length_(0), | 50 length_(0), |
| 50 transaction_id_(EMPTY_TRANSACTION_ID) { | 51 transaction_id_(EMPTY_TRANSACTION_ID) { |
| 51 ASSERT(IsValidTransactionId(transaction_id_)); | 52 RTC_DCHECK(IsValidTransactionId(transaction_id_)); |
| 52 attrs_ = new std::vector<StunAttribute*>(); | 53 attrs_ = new std::vector<StunAttribute*>(); |
| 53 } | 54 } |
| 54 | 55 |
| 55 StunMessage::~StunMessage() { | 56 StunMessage::~StunMessage() { |
| 56 for (size_t i = 0; i < attrs_->size(); i++) | 57 for (size_t i = 0; i < attrs_->size(); i++) |
| 57 delete (*attrs_)[i]; | 58 delete (*attrs_)[i]; |
| 58 delete attrs_; | 59 delete attrs_; |
| 59 } | 60 } |
| 60 | 61 |
| 61 bool StunMessage::IsLegacy() const { | 62 bool StunMessage::IsLegacy() const { |
| 62 if (transaction_id_.size() == kStunLegacyTransactionIdLength) | 63 if (transaction_id_.size() == kStunLegacyTransactionIdLength) |
| 63 return true; | 64 return true; |
| 64 ASSERT(transaction_id_.size() == kStunTransactionIdLength); | 65 RTC_DCHECK(transaction_id_.size() == kStunTransactionIdLength); |
| 65 return false; | 66 return false; |
| 66 } | 67 } |
| 67 | 68 |
| 68 bool StunMessage::SetTransactionID(const std::string& str) { | 69 bool StunMessage::SetTransactionID(const std::string& str) { |
| 69 if (!IsValidTransactionId(str)) { | 70 if (!IsValidTransactionId(str)) { |
| 70 return false; | 71 return false; |
| 71 } | 72 } |
| 72 transaction_id_ = str; | 73 transaction_id_ = str; |
| 73 return true; | 74 return true; |
| 74 } | 75 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 // |0 0| STUN Message Type | Message Length | | 192 // |0 0| STUN Message Type | Message Length | |
| 192 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 193 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 193 rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len)); | 194 rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len)); |
| 194 } | 195 } |
| 195 | 196 |
| 196 char hmac[kStunMessageIntegritySize]; | 197 char hmac[kStunMessageIntegritySize]; |
| 197 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, | 198 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, |
| 198 password.c_str(), password.size(), | 199 password.c_str(), password.size(), |
| 199 temp_data.get(), mi_pos, | 200 temp_data.get(), mi_pos, |
| 200 hmac, sizeof(hmac)); | 201 hmac, sizeof(hmac)); |
| 201 ASSERT(ret == sizeof(hmac)); | 202 RTC_DCHECK(ret == sizeof(hmac)); |
| 202 if (ret != sizeof(hmac)) | 203 if (ret != sizeof(hmac)) |
| 203 return false; | 204 return false; |
| 204 | 205 |
| 205 // Comparing the calculated HMAC with the one present in the message. | 206 // Comparing the calculated HMAC with the one present in the message. |
| 206 return memcmp(data + current_pos + kStunAttributeHeaderSize, | 207 return memcmp(data + current_pos + kStunAttributeHeaderSize, |
| 207 hmac, | 208 hmac, |
| 208 sizeof(hmac)) == 0; | 209 sizeof(hmac)) == 0; |
| 209 } | 210 } |
| 210 | 211 |
| 211 bool StunMessage::AddMessageIntegrity(const std::string& password) { | 212 bool StunMessage::AddMessageIntegrity(const std::string& password) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 226 if (!Write(&buf)) | 227 if (!Write(&buf)) |
| 227 return false; | 228 return false; |
| 228 | 229 |
| 229 int msg_len_for_hmac = static_cast<int>( | 230 int msg_len_for_hmac = static_cast<int>( |
| 230 buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); | 231 buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); |
| 231 char hmac[kStunMessageIntegritySize]; | 232 char hmac[kStunMessageIntegritySize]; |
| 232 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, | 233 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, |
| 233 key, keylen, | 234 key, keylen, |
| 234 buf.Data(), msg_len_for_hmac, | 235 buf.Data(), msg_len_for_hmac, |
| 235 hmac, sizeof(hmac)); | 236 hmac, sizeof(hmac)); |
| 236 ASSERT(ret == sizeof(hmac)); | 237 RTC_DCHECK(ret == sizeof(hmac)); |
| 237 if (ret != sizeof(hmac)) { | 238 if (ret != sizeof(hmac)) { |
| 238 LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity " | 239 LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity " |
| 239 << "has dummy value."; | 240 << "has dummy value."; |
| 240 return false; | 241 return false; |
| 241 } | 242 } |
| 242 | 243 |
| 243 // Insert correct HMAC into the attribute. | 244 // Insert correct HMAC into the attribute. |
| 244 msg_integrity_attr->CopyBytes(hmac, sizeof(hmac)); | 245 msg_integrity_attr->CopyBytes(hmac, sizeof(hmac)); |
| 245 return true; | 246 return true; |
| 246 } | 247 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) | 318 if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) |
| 318 return false; | 319 return false; |
| 319 | 320 |
| 320 uint32_t magic_cookie_int = | 321 uint32_t magic_cookie_int = |
| 321 *reinterpret_cast<const uint32_t*>(magic_cookie.data()); | 322 *reinterpret_cast<const uint32_t*>(magic_cookie.data()); |
| 322 if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) { | 323 if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) { |
| 323 // If magic cookie is invalid it means that the peer implements | 324 // If magic cookie is invalid it means that the peer implements |
| 324 // RFC3489 instead of RFC5389. | 325 // RFC3489 instead of RFC5389. |
| 325 transaction_id.insert(0, magic_cookie); | 326 transaction_id.insert(0, magic_cookie); |
| 326 } | 327 } |
| 327 ASSERT(IsValidTransactionId(transaction_id)); | 328 RTC_DCHECK(IsValidTransactionId(transaction_id)); |
| 328 transaction_id_ = transaction_id; | 329 transaction_id_ = transaction_id; |
| 329 | 330 |
| 330 if (length_ != buf->Length()) | 331 if (length_ != buf->Length()) |
| 331 return false; | 332 return false; |
| 332 | 333 |
| 333 attrs_->resize(0); | 334 attrs_->resize(0); |
| 334 | 335 |
| 335 size_t rest = buf->Length() - length_; | 336 size_t rest = buf->Length() - length_; |
| 336 while (buf->Length() > rest) { | 337 while (buf->Length() > rest) { |
| 337 uint16_t attr_type, attr_length; | 338 uint16_t attr_type, attr_length; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 350 if (!buf->Consume(attr_length)) | 351 if (!buf->Consume(attr_length)) |
| 351 return false; | 352 return false; |
| 352 } else { | 353 } else { |
| 353 if (!attr->Read(buf)) | 354 if (!attr->Read(buf)) |
| 354 return false; | 355 return false; |
| 355 // TODO(honghaiz): Change |attrs_| to be a vector of unique_ptrs. | 356 // TODO(honghaiz): Change |attrs_| to be a vector of unique_ptrs. |
| 356 attrs_->push_back(attr.release()); | 357 attrs_->push_back(attr.release()); |
| 357 } | 358 } |
| 358 } | 359 } |
| 359 | 360 |
| 360 ASSERT(buf->Length() == rest); | 361 RTC_DCHECK(buf->Length() == rest); |
| 361 return true; | 362 return true; |
| 362 } | 363 } |
| 363 | 364 |
| 364 bool StunMessage::Write(ByteBufferWriter* buf) const { | 365 bool StunMessage::Write(ByteBufferWriter* buf) const { |
| 365 buf->WriteUInt16(type_); | 366 buf->WriteUInt16(type_); |
| 366 buf->WriteUInt16(length_); | 367 buf->WriteUInt16(length_); |
| 367 if (!IsLegacy()) | 368 if (!IsLegacy()) |
| 368 buf->WriteUInt32(kStunMagicCookie); | 369 buf->WriteUInt32(kStunMagicCookie); |
| 369 buf->WriteString(transaction_id_); | 370 buf->WriteString(transaction_id_); |
| 370 | 371 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 | 649 |
| 649 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value) | 650 StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value) |
| 650 : StunAttribute(type, SIZE), bits_(value) { | 651 : StunAttribute(type, SIZE), bits_(value) { |
| 651 } | 652 } |
| 652 | 653 |
| 653 StunUInt32Attribute::StunUInt32Attribute(uint16_t type) | 654 StunUInt32Attribute::StunUInt32Attribute(uint16_t type) |
| 654 : StunAttribute(type, SIZE), bits_(0) { | 655 : StunAttribute(type, SIZE), bits_(0) { |
| 655 } | 656 } |
| 656 | 657 |
| 657 bool StunUInt32Attribute::GetBit(size_t index) const { | 658 bool StunUInt32Attribute::GetBit(size_t index) const { |
| 658 ASSERT(index < 32); | 659 RTC_DCHECK(index < 32); |
| 659 return static_cast<bool>((bits_ >> index) & 0x1); | 660 return static_cast<bool>((bits_ >> index) & 0x1); |
| 660 } | 661 } |
| 661 | 662 |
| 662 void StunUInt32Attribute::SetBit(size_t index, bool value) { | 663 void StunUInt32Attribute::SetBit(size_t index, bool value) { |
| 663 ASSERT(index < 32); | 664 RTC_DCHECK(index < 32); |
| 664 bits_ &= ~(1 << index); | 665 bits_ &= ~(1 << index); |
| 665 bits_ |= value ? (1 << index) : 0; | 666 bits_ |= value ? (1 << index) : 0; |
| 666 } | 667 } |
| 667 | 668 |
| 668 bool StunUInt32Attribute::Read(ByteBufferReader* buf) { | 669 bool StunUInt32Attribute::Read(ByteBufferReader* buf) { |
| 669 if (length() != SIZE || !buf->ReadUInt32(&bits_)) | 670 if (length() != SIZE || !buf->ReadUInt32(&bits_)) |
| 670 return false; | 671 return false; |
| 671 return true; | 672 return true; |
| 672 } | 673 } |
| 673 | 674 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 CopyBytes(bytes, strlen(bytes)); | 725 CopyBytes(bytes, strlen(bytes)); |
| 725 } | 726 } |
| 726 | 727 |
| 727 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { | 728 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { |
| 728 char* new_bytes = new char[length]; | 729 char* new_bytes = new char[length]; |
| 729 memcpy(new_bytes, bytes, length); | 730 memcpy(new_bytes, bytes, length); |
| 730 SetBytes(new_bytes, length); | 731 SetBytes(new_bytes, length); |
| 731 } | 732 } |
| 732 | 733 |
| 733 uint8_t StunByteStringAttribute::GetByte(size_t index) const { | 734 uint8_t StunByteStringAttribute::GetByte(size_t index) const { |
| 734 ASSERT(bytes_ != NULL); | 735 RTC_DCHECK(bytes_ != NULL); |
| 735 ASSERT(index < length()); | 736 RTC_DCHECK(index < length()); |
| 736 return static_cast<uint8_t>(bytes_[index]); | 737 return static_cast<uint8_t>(bytes_[index]); |
| 737 } | 738 } |
| 738 | 739 |
| 739 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) { | 740 void StunByteStringAttribute::SetByte(size_t index, uint8_t value) { |
| 740 ASSERT(bytes_ != NULL); | 741 RTC_DCHECK(bytes_ != NULL); |
| 741 ASSERT(index < length()); | 742 RTC_DCHECK(index < length()); |
| 742 bytes_[index] = value; | 743 bytes_[index] = value; |
| 743 } | 744 } |
| 744 | 745 |
| 745 bool StunByteStringAttribute::Read(ByteBufferReader* buf) { | 746 bool StunByteStringAttribute::Read(ByteBufferReader* buf) { |
| 746 bytes_ = new char[length()]; | 747 bytes_ = new char[length()]; |
| 747 if (!buf->ReadBytes(bytes_, length())) { | 748 if (!buf->ReadBytes(bytes_, length())) { |
| 748 return false; | 749 return false; |
| 749 } | 750 } |
| 750 | 751 |
| 751 ConsumePadding(buf); | 752 ConsumePadding(buf); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 digest, sizeof(digest)); | 915 digest, sizeof(digest)); |
| 915 if (size == 0) { | 916 if (size == 0) { |
| 916 return false; | 917 return false; |
| 917 } | 918 } |
| 918 | 919 |
| 919 *hash = std::string(digest, size); | 920 *hash = std::string(digest, size); |
| 920 return true; | 921 return true; |
| 921 } | 922 } |
| 922 | 923 |
| 923 } // namespace cricket | 924 } // namespace cricket |
| OLD | NEW |