1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "api/transport/stun.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <string.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
16*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
17*d9f75844SAndroid Build Coastguard Worker #include <iterator>
18*d9f75844SAndroid Build Coastguard Worker #include <memory>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_order.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/crc32.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/message_digest.h"
27*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker using rtc::ByteBufferReader;
30*d9f75844SAndroid Build Coastguard Worker using rtc::ByteBufferWriter;
31*d9f75844SAndroid Build Coastguard Worker
32*d9f75844SAndroid Build Coastguard Worker namespace cricket {
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker namespace {
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker const int k127Utf8CharactersLengthInBytes = 508;
37*d9f75844SAndroid Build Coastguard Worker const int kMessageIntegrityAttributeLength = 20;
38*d9f75844SAndroid Build Coastguard Worker const int kTheoreticalMaximumAttributeLength = 65535;
39*d9f75844SAndroid Build Coastguard Worker
ReduceTransactionId(absl::string_view transaction_id)40*d9f75844SAndroid Build Coastguard Worker uint32_t ReduceTransactionId(absl::string_view transaction_id) {
41*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(transaction_id.length() == cricket::kStunTransactionIdLength ||
42*d9f75844SAndroid Build Coastguard Worker transaction_id.length() == cricket::kStunLegacyTransactionIdLength)
43*d9f75844SAndroid Build Coastguard Worker << transaction_id.length();
44*d9f75844SAndroid Build Coastguard Worker ByteBufferReader reader(transaction_id.data(), transaction_id.size());
45*d9f75844SAndroid Build Coastguard Worker uint32_t result = 0;
46*d9f75844SAndroid Build Coastguard Worker uint32_t next;
47*d9f75844SAndroid Build Coastguard Worker while (reader.ReadUInt32(&next)) {
48*d9f75844SAndroid Build Coastguard Worker result ^= next;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker return result;
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker // Check the maximum length of a BYTE_STRING attribute against specifications.
LengthValid(int type,int length)54*d9f75844SAndroid Build Coastguard Worker bool LengthValid(int type, int length) {
55*d9f75844SAndroid Build Coastguard Worker // "Less than 509 bytes" is intended to indicate a maximum of 127
56*d9f75844SAndroid Build Coastguard Worker // UTF-8 characters, which may take up to 4 bytes per character.
57*d9f75844SAndroid Build Coastguard Worker switch (type) {
58*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_USERNAME:
59*d9f75844SAndroid Build Coastguard Worker return length <=
60*d9f75844SAndroid Build Coastguard Worker k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.3
61*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_MESSAGE_INTEGRITY:
62*d9f75844SAndroid Build Coastguard Worker return length ==
63*d9f75844SAndroid Build Coastguard Worker kMessageIntegrityAttributeLength; // RFC 8489 section 14.5
64*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_REALM:
65*d9f75844SAndroid Build Coastguard Worker return length <=
66*d9f75844SAndroid Build Coastguard Worker k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.9
67*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_NONCE:
68*d9f75844SAndroid Build Coastguard Worker return length <=
69*d9f75844SAndroid Build Coastguard Worker k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.10
70*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_SOFTWARE:
71*d9f75844SAndroid Build Coastguard Worker return length <=
72*d9f75844SAndroid Build Coastguard Worker k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.14
73*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_DATA:
74*d9f75844SAndroid Build Coastguard Worker // No length restriction in RFC; it's the content of an UDP datagram,
75*d9f75844SAndroid Build Coastguard Worker // which in theory can be up to 65.535 bytes.
76*d9f75844SAndroid Build Coastguard Worker // TODO(bugs.webrtc.org/12179): Write a test to find the real limit.
77*d9f75844SAndroid Build Coastguard Worker return length <= kTheoreticalMaximumAttributeLength;
78*d9f75844SAndroid Build Coastguard Worker default:
79*d9f75844SAndroid Build Coastguard Worker // Return an arbitrary restriction for all other types.
80*d9f75844SAndroid Build Coastguard Worker return length <= kTheoreticalMaximumAttributeLength;
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
83*d9f75844SAndroid Build Coastguard Worker return true;
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker } // namespace
87*d9f75844SAndroid Build Coastguard Worker
88*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
89*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
90*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized";
91*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[] = "Unknown Attribute";
92*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden";
93*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch";
94*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce";
95*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials";
96*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol";
97*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict";
98*d9f75844SAndroid Build Coastguard Worker const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error";
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker const char TURN_MAGIC_COOKIE_VALUE[] = {'\x72', '\xC6', '\x4B', '\xC6'};
101*d9f75844SAndroid Build Coastguard Worker const char EMPTY_TRANSACTION_ID[] = "0000000000000000";
102*d9f75844SAndroid Build Coastguard Worker const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E;
103*d9f75844SAndroid Build Coastguard Worker const int SERVER_NOT_REACHABLE_ERROR = 701;
104*d9f75844SAndroid Build Coastguard Worker
105*d9f75844SAndroid Build Coastguard Worker // StunMessage
106*d9f75844SAndroid Build Coastguard Worker
StunMessage()107*d9f75844SAndroid Build Coastguard Worker StunMessage::StunMessage()
108*d9f75844SAndroid Build Coastguard Worker : StunMessage(STUN_INVALID_MESSAGE_TYPE, EMPTY_TRANSACTION_ID) {}
109*d9f75844SAndroid Build Coastguard Worker
StunMessage(uint16_t type)110*d9f75844SAndroid Build Coastguard Worker StunMessage::StunMessage(uint16_t type)
111*d9f75844SAndroid Build Coastguard Worker : StunMessage(type, GenerateTransactionId()) {}
112*d9f75844SAndroid Build Coastguard Worker
StunMessage(uint16_t type,absl::string_view transaction_id)113*d9f75844SAndroid Build Coastguard Worker StunMessage::StunMessage(uint16_t type, absl::string_view transaction_id)
114*d9f75844SAndroid Build Coastguard Worker : type_(type),
115*d9f75844SAndroid Build Coastguard Worker transaction_id_(transaction_id),
116*d9f75844SAndroid Build Coastguard Worker reduced_transaction_id_(ReduceTransactionId(transaction_id_)) {
117*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsValidTransactionId(transaction_id_));
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker StunMessage::~StunMessage() = default;
121*d9f75844SAndroid Build Coastguard Worker
IsLegacy() const122*d9f75844SAndroid Build Coastguard Worker bool StunMessage::IsLegacy() const {
123*d9f75844SAndroid Build Coastguard Worker if (transaction_id_.size() == kStunLegacyTransactionIdLength)
124*d9f75844SAndroid Build Coastguard Worker return true;
125*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(transaction_id_.size() == kStunTransactionIdLength);
126*d9f75844SAndroid Build Coastguard Worker return false;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker
DesignatedExpertRange(int attr_type)129*d9f75844SAndroid Build Coastguard Worker static bool DesignatedExpertRange(int attr_type) {
130*d9f75844SAndroid Build Coastguard Worker return (attr_type >= 0x4000 && attr_type <= 0x7FFF) ||
131*d9f75844SAndroid Build Coastguard Worker (attr_type >= 0xC000 && attr_type <= 0xFFFF);
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker
AddAttribute(std::unique_ptr<StunAttribute> attr)134*d9f75844SAndroid Build Coastguard Worker void StunMessage::AddAttribute(std::unique_ptr<StunAttribute> attr) {
135*d9f75844SAndroid Build Coastguard Worker // Fail any attributes that aren't valid for this type of message,
136*d9f75844SAndroid Build Coastguard Worker // but allow any type for the range that in the RFC is reserved for
137*d9f75844SAndroid Build Coastguard Worker // the "designated experts".
138*d9f75844SAndroid Build Coastguard Worker if (!DesignatedExpertRange(attr->type())) {
139*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(attr->value_type(), GetAttributeValueType(attr->type()));
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker
142*d9f75844SAndroid Build Coastguard Worker attr->SetOwner(this);
143*d9f75844SAndroid Build Coastguard Worker size_t attr_length = attr->length();
144*d9f75844SAndroid Build Coastguard Worker if (attr_length % 4 != 0) {
145*d9f75844SAndroid Build Coastguard Worker attr_length += (4 - (attr_length % 4));
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker length_ += static_cast<uint16_t>(attr_length + 4);
148*d9f75844SAndroid Build Coastguard Worker
149*d9f75844SAndroid Build Coastguard Worker attrs_.push_back(std::move(attr));
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker
RemoveAttribute(int type)152*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAttribute> StunMessage::RemoveAttribute(int type) {
153*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAttribute> attribute;
154*d9f75844SAndroid Build Coastguard Worker for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
155*d9f75844SAndroid Build Coastguard Worker if ((*it)->type() == type) {
156*d9f75844SAndroid Build Coastguard Worker attribute = std::move(*it);
157*d9f75844SAndroid Build Coastguard Worker attrs_.erase(std::next(it).base());
158*d9f75844SAndroid Build Coastguard Worker break;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker }
161*d9f75844SAndroid Build Coastguard Worker if (attribute) {
162*d9f75844SAndroid Build Coastguard Worker attribute->SetOwner(nullptr);
163*d9f75844SAndroid Build Coastguard Worker size_t attr_length = attribute->length();
164*d9f75844SAndroid Build Coastguard Worker if (attr_length % 4 != 0) {
165*d9f75844SAndroid Build Coastguard Worker attr_length += (4 - (attr_length % 4));
166*d9f75844SAndroid Build Coastguard Worker }
167*d9f75844SAndroid Build Coastguard Worker length_ -= static_cast<uint16_t>(attr_length + 4);
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker return attribute;
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker
ClearAttributes()172*d9f75844SAndroid Build Coastguard Worker void StunMessage::ClearAttributes() {
173*d9f75844SAndroid Build Coastguard Worker for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) {
174*d9f75844SAndroid Build Coastguard Worker (*it)->SetOwner(nullptr);
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker attrs_.clear();
177*d9f75844SAndroid Build Coastguard Worker length_ = 0;
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker
GetNonComprehendedAttributes() const180*d9f75844SAndroid Build Coastguard Worker std::vector<uint16_t> StunMessage::GetNonComprehendedAttributes() const {
181*d9f75844SAndroid Build Coastguard Worker std::vector<uint16_t> unknown_attributes;
182*d9f75844SAndroid Build Coastguard Worker for (auto& attr : attrs_) {
183*d9f75844SAndroid Build Coastguard Worker // "comprehension-required" range is 0x0000-0x7FFF.
184*d9f75844SAndroid Build Coastguard Worker if (attr->type() >= 0x0000 && attr->type() <= 0x7FFF &&
185*d9f75844SAndroid Build Coastguard Worker GetAttributeValueType(attr->type()) == STUN_VALUE_UNKNOWN) {
186*d9f75844SAndroid Build Coastguard Worker unknown_attributes.push_back(attr->type());
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker }
189*d9f75844SAndroid Build Coastguard Worker return unknown_attributes;
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker
GetAddress(int type) const192*d9f75844SAndroid Build Coastguard Worker const StunAddressAttribute* StunMessage::GetAddress(int type) const {
193*d9f75844SAndroid Build Coastguard Worker switch (type) {
194*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_MAPPED_ADDRESS: {
195*d9f75844SAndroid Build Coastguard Worker // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is
196*d9f75844SAndroid Build Coastguard Worker // missing.
197*d9f75844SAndroid Build Coastguard Worker const StunAttribute* mapped_address =
198*d9f75844SAndroid Build Coastguard Worker GetAttribute(STUN_ATTR_MAPPED_ADDRESS);
199*d9f75844SAndroid Build Coastguard Worker if (!mapped_address)
200*d9f75844SAndroid Build Coastguard Worker mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS);
201*d9f75844SAndroid Build Coastguard Worker return reinterpret_cast<const StunAddressAttribute*>(mapped_address);
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker
204*d9f75844SAndroid Build Coastguard Worker default:
205*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunAddressAttribute*>(GetAttribute(type));
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker }
208*d9f75844SAndroid Build Coastguard Worker
GetUInt32(int type) const209*d9f75844SAndroid Build Coastguard Worker const StunUInt32Attribute* StunMessage::GetUInt32(int type) const {
210*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunUInt32Attribute*>(GetAttribute(type));
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker
GetUInt64(int type) const213*d9f75844SAndroid Build Coastguard Worker const StunUInt64Attribute* StunMessage::GetUInt64(int type) const {
214*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunUInt64Attribute*>(GetAttribute(type));
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker
GetByteString(int type) const217*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* StunMessage::GetByteString(int type) const {
218*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunByteStringAttribute*>(GetAttribute(type));
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker
GetUInt16List(int type) const221*d9f75844SAndroid Build Coastguard Worker const StunUInt16ListAttribute* StunMessage::GetUInt16List(int type) const {
222*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunUInt16ListAttribute*>(GetAttribute(type));
223*d9f75844SAndroid Build Coastguard Worker }
224*d9f75844SAndroid Build Coastguard Worker
GetErrorCode() const225*d9f75844SAndroid Build Coastguard Worker const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
226*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunErrorCodeAttribute*>(
227*d9f75844SAndroid Build Coastguard Worker GetAttribute(STUN_ATTR_ERROR_CODE));
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker
GetErrorCodeValue() const230*d9f75844SAndroid Build Coastguard Worker int StunMessage::GetErrorCodeValue() const {
231*d9f75844SAndroid Build Coastguard Worker const StunErrorCodeAttribute* error_attribute = GetErrorCode();
232*d9f75844SAndroid Build Coastguard Worker return error_attribute ? error_attribute->code() : STUN_ERROR_GLOBAL_FAILURE;
233*d9f75844SAndroid Build Coastguard Worker }
234*d9f75844SAndroid Build Coastguard Worker
GetUnknownAttributes() const235*d9f75844SAndroid Build Coastguard Worker const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
236*d9f75844SAndroid Build Coastguard Worker return static_cast<const StunUInt16ListAttribute*>(
237*d9f75844SAndroid Build Coastguard Worker GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
238*d9f75844SAndroid Build Coastguard Worker }
239*d9f75844SAndroid Build Coastguard Worker
ValidateMessageIntegrity(const std::string & password)240*d9f75844SAndroid Build Coastguard Worker StunMessage::IntegrityStatus StunMessage::ValidateMessageIntegrity(
241*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
242*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(integrity_ == IntegrityStatus::kNotSet)
243*d9f75844SAndroid Build Coastguard Worker << "Usage error: Verification should only be done once";
244*d9f75844SAndroid Build Coastguard Worker password_ = password;
245*d9f75844SAndroid Build Coastguard Worker if (GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) {
246*d9f75844SAndroid Build Coastguard Worker if (ValidateMessageIntegrityOfType(
247*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_MESSAGE_INTEGRITY, kStunMessageIntegritySize,
248*d9f75844SAndroid Build Coastguard Worker buffer_.c_str(), buffer_.size(), password)) {
249*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kIntegrityOk;
250*d9f75844SAndroid Build Coastguard Worker } else {
251*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kIntegrityBad;
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker } else if (GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32)) {
254*d9f75844SAndroid Build Coastguard Worker if (ValidateMessageIntegrityOfType(
255*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, kStunMessageIntegrity32Size,
256*d9f75844SAndroid Build Coastguard Worker buffer_.c_str(), buffer_.size(), password)) {
257*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kIntegrityOk;
258*d9f75844SAndroid Build Coastguard Worker } else {
259*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kIntegrityBad;
260*d9f75844SAndroid Build Coastguard Worker }
261*d9f75844SAndroid Build Coastguard Worker } else {
262*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kNoIntegrity;
263*d9f75844SAndroid Build Coastguard Worker }
264*d9f75844SAndroid Build Coastguard Worker // Log the result of integrity checking. See crbug.com/1177125 for background.
265*d9f75844SAndroid Build Coastguard Worker // Convert args to integer for the benefit of the macros.
266*d9f75844SAndroid Build Coastguard Worker int bucket_count = static_cast<int>(IntegrityStatus::kMaxValue) + 1;
267*d9f75844SAndroid Build Coastguard Worker int integrity = static_cast<int>(integrity_);
268*d9f75844SAndroid Build Coastguard Worker if (IsStunRequestType(type_)) {
269*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Request", integrity,
270*d9f75844SAndroid Build Coastguard Worker bucket_count);
271*d9f75844SAndroid Build Coastguard Worker } else if (IsStunSuccessResponseType(type_)) {
272*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Response", integrity,
273*d9f75844SAndroid Build Coastguard Worker bucket_count);
274*d9f75844SAndroid Build Coastguard Worker } else if (IsStunIndicationType(type_)) {
275*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Indication", integrity,
276*d9f75844SAndroid Build Coastguard Worker bucket_count);
277*d9f75844SAndroid Build Coastguard Worker } else {
278*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsStunErrorResponseType(type_));
279*d9f75844SAndroid Build Coastguard Worker auto* error_attribute = GetErrorCode();
280*d9f75844SAndroid Build Coastguard Worker if (!error_attribute) {
281*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
282*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.NoErrorAttribute", integrity,
283*d9f75844SAndroid Build Coastguard Worker bucket_count);
284*d9f75844SAndroid Build Coastguard Worker } else {
285*d9f75844SAndroid Build Coastguard Worker switch (error_attribute->code()) {
286*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_TRY_ALTERNATE:
287*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
288*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.TryAlternate", integrity,
289*d9f75844SAndroid Build Coastguard Worker bucket_count);
290*d9f75844SAndroid Build Coastguard Worker break;
291*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_BAD_REQUEST:
292*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
293*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.BadRequest", integrity,
294*d9f75844SAndroid Build Coastguard Worker bucket_count);
295*d9f75844SAndroid Build Coastguard Worker break;
296*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_UNAUTHORIZED:
297*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
298*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.Unauthorized", integrity,
299*d9f75844SAndroid Build Coastguard Worker bucket_count);
300*d9f75844SAndroid Build Coastguard Worker break;
301*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_UNKNOWN_ATTRIBUTE:
302*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
303*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.UnknownAttribute", integrity,
304*d9f75844SAndroid Build Coastguard Worker bucket_count);
305*d9f75844SAndroid Build Coastguard Worker break;
306*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_STALE_NONCE:
307*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
308*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.StaleNonce", integrity,
309*d9f75844SAndroid Build Coastguard Worker bucket_count);
310*d9f75844SAndroid Build Coastguard Worker break;
311*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_SERVER_ERROR:
312*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
313*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.ServerError", integrity,
314*d9f75844SAndroid Build Coastguard Worker bucket_count);
315*d9f75844SAndroid Build Coastguard Worker break;
316*d9f75844SAndroid Build Coastguard Worker case STUN_ERROR_GLOBAL_FAILURE:
317*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
318*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.GlobalFailure", integrity,
319*d9f75844SAndroid Build Coastguard Worker bucket_count);
320*d9f75844SAndroid Build Coastguard Worker break;
321*d9f75844SAndroid Build Coastguard Worker default:
322*d9f75844SAndroid Build Coastguard Worker RTC_HISTOGRAM_ENUMERATION(
323*d9f75844SAndroid Build Coastguard Worker "WebRTC.Stun.Integrity.ErrorResponse.ErrorOther", integrity,
324*d9f75844SAndroid Build Coastguard Worker bucket_count);
325*d9f75844SAndroid Build Coastguard Worker break;
326*d9f75844SAndroid Build Coastguard Worker }
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker }
329*d9f75844SAndroid Build Coastguard Worker return integrity_;
330*d9f75844SAndroid Build Coastguard Worker }
331*d9f75844SAndroid Build Coastguard Worker
RevalidateMessageIntegrity(const std::string & password)332*d9f75844SAndroid Build Coastguard Worker StunMessage::IntegrityStatus StunMessage::RevalidateMessageIntegrity(
333*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
334*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Message revalidation, old status was "
335*d9f75844SAndroid Build Coastguard Worker << static_cast<int>(integrity_);
336*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kNotSet;
337*d9f75844SAndroid Build Coastguard Worker return ValidateMessageIntegrity(password);
338*d9f75844SAndroid Build Coastguard Worker }
339*d9f75844SAndroid Build Coastguard Worker
ValidateMessageIntegrityForTesting(const char * data,size_t size,const std::string & password)340*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateMessageIntegrityForTesting(
341*d9f75844SAndroid Build Coastguard Worker const char* data,
342*d9f75844SAndroid Build Coastguard Worker size_t size,
343*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
344*d9f75844SAndroid Build Coastguard Worker return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
345*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegritySize, data, size,
346*d9f75844SAndroid Build Coastguard Worker password);
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker
ValidateMessageIntegrity32ForTesting(const char * data,size_t size,const std::string & password)349*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateMessageIntegrity32ForTesting(
350*d9f75844SAndroid Build Coastguard Worker const char* data,
351*d9f75844SAndroid Build Coastguard Worker size_t size,
352*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
353*d9f75844SAndroid Build Coastguard Worker return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
354*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegrity32Size, data, size,
355*d9f75844SAndroid Build Coastguard Worker password);
356*d9f75844SAndroid Build Coastguard Worker }
357*d9f75844SAndroid Build Coastguard Worker
358*d9f75844SAndroid Build Coastguard Worker // Deprecated
ValidateMessageIntegrity(const char * data,size_t size,const std::string & password)359*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateMessageIntegrity(const char* data,
360*d9f75844SAndroid Build Coastguard Worker size_t size,
361*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
362*d9f75844SAndroid Build Coastguard Worker return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
363*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegritySize, data, size,
364*d9f75844SAndroid Build Coastguard Worker password);
365*d9f75844SAndroid Build Coastguard Worker }
366*d9f75844SAndroid Build Coastguard Worker
367*d9f75844SAndroid Build Coastguard Worker // Deprecated
ValidateMessageIntegrity32(const char * data,size_t size,const std::string & password)368*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateMessageIntegrity32(const char* data,
369*d9f75844SAndroid Build Coastguard Worker size_t size,
370*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
371*d9f75844SAndroid Build Coastguard Worker return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
372*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegrity32Size, data, size,
373*d9f75844SAndroid Build Coastguard Worker password);
374*d9f75844SAndroid Build Coastguard Worker }
375*d9f75844SAndroid Build Coastguard Worker
376*d9f75844SAndroid Build Coastguard Worker // Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the
377*d9f75844SAndroid Build Coastguard Worker // procedure outlined in RFC 5389, section 15.4.
ValidateMessageIntegrityOfType(int mi_attr_type,size_t mi_attr_size,const char * data,size_t size,const std::string & password)378*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateMessageIntegrityOfType(int mi_attr_type,
379*d9f75844SAndroid Build Coastguard Worker size_t mi_attr_size,
380*d9f75844SAndroid Build Coastguard Worker const char* data,
381*d9f75844SAndroid Build Coastguard Worker size_t size,
382*d9f75844SAndroid Build Coastguard Worker const std::string& password) {
383*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(mi_attr_size <= kStunMessageIntegritySize);
384*d9f75844SAndroid Build Coastguard Worker
385*d9f75844SAndroid Build Coastguard Worker // Verifying the size of the message.
386*d9f75844SAndroid Build Coastguard Worker if ((size % 4) != 0 || size < kStunHeaderSize) {
387*d9f75844SAndroid Build Coastguard Worker return false;
388*d9f75844SAndroid Build Coastguard Worker }
389*d9f75844SAndroid Build Coastguard Worker
390*d9f75844SAndroid Build Coastguard Worker // Getting the message length from the STUN header.
391*d9f75844SAndroid Build Coastguard Worker uint16_t msg_length = rtc::GetBE16(&data[2]);
392*d9f75844SAndroid Build Coastguard Worker if (size != (msg_length + kStunHeaderSize)) {
393*d9f75844SAndroid Build Coastguard Worker return false;
394*d9f75844SAndroid Build Coastguard Worker }
395*d9f75844SAndroid Build Coastguard Worker
396*d9f75844SAndroid Build Coastguard Worker // Finding Message Integrity attribute in stun message.
397*d9f75844SAndroid Build Coastguard Worker size_t current_pos = kStunHeaderSize;
398*d9f75844SAndroid Build Coastguard Worker bool has_message_integrity_attr = false;
399*d9f75844SAndroid Build Coastguard Worker while (current_pos + 4 <= size) {
400*d9f75844SAndroid Build Coastguard Worker uint16_t attr_type, attr_length;
401*d9f75844SAndroid Build Coastguard Worker // Getting attribute type and length.
402*d9f75844SAndroid Build Coastguard Worker attr_type = rtc::GetBE16(&data[current_pos]);
403*d9f75844SAndroid Build Coastguard Worker attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]);
404*d9f75844SAndroid Build Coastguard Worker
405*d9f75844SAndroid Build Coastguard Worker // If M-I, sanity check it, and break out.
406*d9f75844SAndroid Build Coastguard Worker if (attr_type == mi_attr_type) {
407*d9f75844SAndroid Build Coastguard Worker if (attr_length != mi_attr_size ||
408*d9f75844SAndroid Build Coastguard Worker current_pos + sizeof(attr_type) + sizeof(attr_length) + attr_length >
409*d9f75844SAndroid Build Coastguard Worker size) {
410*d9f75844SAndroid Build Coastguard Worker return false;
411*d9f75844SAndroid Build Coastguard Worker }
412*d9f75844SAndroid Build Coastguard Worker has_message_integrity_attr = true;
413*d9f75844SAndroid Build Coastguard Worker break;
414*d9f75844SAndroid Build Coastguard Worker }
415*d9f75844SAndroid Build Coastguard Worker
416*d9f75844SAndroid Build Coastguard Worker // Otherwise, skip to the next attribute.
417*d9f75844SAndroid Build Coastguard Worker current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length;
418*d9f75844SAndroid Build Coastguard Worker if ((attr_length % 4) != 0) {
419*d9f75844SAndroid Build Coastguard Worker current_pos += (4 - (attr_length % 4));
420*d9f75844SAndroid Build Coastguard Worker }
421*d9f75844SAndroid Build Coastguard Worker }
422*d9f75844SAndroid Build Coastguard Worker
423*d9f75844SAndroid Build Coastguard Worker if (!has_message_integrity_attr) {
424*d9f75844SAndroid Build Coastguard Worker return false;
425*d9f75844SAndroid Build Coastguard Worker }
426*d9f75844SAndroid Build Coastguard Worker
427*d9f75844SAndroid Build Coastguard Worker // Getting length of the message to calculate Message Integrity.
428*d9f75844SAndroid Build Coastguard Worker size_t mi_pos = current_pos;
429*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<char[]> temp_data(new char[current_pos]);
430*d9f75844SAndroid Build Coastguard Worker memcpy(temp_data.get(), data, current_pos);
431*d9f75844SAndroid Build Coastguard Worker if (size > mi_pos + kStunAttributeHeaderSize + mi_attr_size) {
432*d9f75844SAndroid Build Coastguard Worker // Stun message has other attributes after message integrity.
433*d9f75844SAndroid Build Coastguard Worker // Adjust the length parameter in stun message to calculate HMAC.
434*d9f75844SAndroid Build Coastguard Worker size_t extra_offset =
435*d9f75844SAndroid Build Coastguard Worker size - (mi_pos + kStunAttributeHeaderSize + mi_attr_size);
436*d9f75844SAndroid Build Coastguard Worker size_t new_adjusted_len = size - extra_offset - kStunHeaderSize;
437*d9f75844SAndroid Build Coastguard Worker
438*d9f75844SAndroid Build Coastguard Worker // Writing new length of the STUN message @ Message Length in temp buffer.
439*d9f75844SAndroid Build Coastguard Worker // 0 1 2 3
440*d9f75844SAndroid Build Coastguard Worker // 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
441*d9f75844SAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
442*d9f75844SAndroid Build Coastguard Worker // |0 0| STUN Message Type | Message Length |
443*d9f75844SAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
444*d9f75844SAndroid Build Coastguard Worker rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len));
445*d9f75844SAndroid Build Coastguard Worker }
446*d9f75844SAndroid Build Coastguard Worker
447*d9f75844SAndroid Build Coastguard Worker char hmac[kStunMessageIntegritySize];
448*d9f75844SAndroid Build Coastguard Worker size_t ret =
449*d9f75844SAndroid Build Coastguard Worker rtc::ComputeHmac(rtc::DIGEST_SHA_1, password.c_str(), password.size(),
450*d9f75844SAndroid Build Coastguard Worker temp_data.get(), mi_pos, hmac, sizeof(hmac));
451*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ret == sizeof(hmac));
452*d9f75844SAndroid Build Coastguard Worker if (ret != sizeof(hmac)) {
453*d9f75844SAndroid Build Coastguard Worker return false;
454*d9f75844SAndroid Build Coastguard Worker }
455*d9f75844SAndroid Build Coastguard Worker
456*d9f75844SAndroid Build Coastguard Worker // Comparing the calculated HMAC with the one present in the message.
457*d9f75844SAndroid Build Coastguard Worker return memcmp(data + current_pos + kStunAttributeHeaderSize, hmac,
458*d9f75844SAndroid Build Coastguard Worker mi_attr_size) == 0;
459*d9f75844SAndroid Build Coastguard Worker }
460*d9f75844SAndroid Build Coastguard Worker
AddMessageIntegrity(absl::string_view password)461*d9f75844SAndroid Build Coastguard Worker bool StunMessage::AddMessageIntegrity(absl::string_view password) {
462*d9f75844SAndroid Build Coastguard Worker return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
463*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegritySize, password);
464*d9f75844SAndroid Build Coastguard Worker }
465*d9f75844SAndroid Build Coastguard Worker
AddMessageIntegrity32(absl::string_view password)466*d9f75844SAndroid Build Coastguard Worker bool StunMessage::AddMessageIntegrity32(absl::string_view password) {
467*d9f75844SAndroid Build Coastguard Worker return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
468*d9f75844SAndroid Build Coastguard Worker kStunMessageIntegrity32Size, password);
469*d9f75844SAndroid Build Coastguard Worker }
470*d9f75844SAndroid Build Coastguard Worker
AddMessageIntegrityOfType(int attr_type,size_t attr_size,absl::string_view key)471*d9f75844SAndroid Build Coastguard Worker bool StunMessage::AddMessageIntegrityOfType(int attr_type,
472*d9f75844SAndroid Build Coastguard Worker size_t attr_size,
473*d9f75844SAndroid Build Coastguard Worker absl::string_view key) {
474*d9f75844SAndroid Build Coastguard Worker // Add the attribute with a dummy value. Since this is a known attribute, it
475*d9f75844SAndroid Build Coastguard Worker // can't fail.
476*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(attr_size <= kStunMessageIntegritySize);
477*d9f75844SAndroid Build Coastguard Worker auto msg_integrity_attr_ptr = std::make_unique<StunByteStringAttribute>(
478*d9f75844SAndroid Build Coastguard Worker attr_type, std::string(attr_size, '0'));
479*d9f75844SAndroid Build Coastguard Worker auto* msg_integrity_attr = msg_integrity_attr_ptr.get();
480*d9f75844SAndroid Build Coastguard Worker AddAttribute(std::move(msg_integrity_attr_ptr));
481*d9f75844SAndroid Build Coastguard Worker
482*d9f75844SAndroid Build Coastguard Worker // Calculate the HMAC for the message.
483*d9f75844SAndroid Build Coastguard Worker ByteBufferWriter buf;
484*d9f75844SAndroid Build Coastguard Worker if (!Write(&buf))
485*d9f75844SAndroid Build Coastguard Worker return false;
486*d9f75844SAndroid Build Coastguard Worker
487*d9f75844SAndroid Build Coastguard Worker int msg_len_for_hmac = static_cast<int>(
488*d9f75844SAndroid Build Coastguard Worker buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
489*d9f75844SAndroid Build Coastguard Worker char hmac[kStunMessageIntegritySize];
490*d9f75844SAndroid Build Coastguard Worker size_t ret =
491*d9f75844SAndroid Build Coastguard Worker rtc::ComputeHmac(rtc::DIGEST_SHA_1, key.data(), key.size(), buf.Data(),
492*d9f75844SAndroid Build Coastguard Worker msg_len_for_hmac, hmac, sizeof(hmac));
493*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ret == sizeof(hmac));
494*d9f75844SAndroid Build Coastguard Worker if (ret != sizeof(hmac)) {
495*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity "
496*d9f75844SAndroid Build Coastguard Worker "has dummy value.";
497*d9f75844SAndroid Build Coastguard Worker return false;
498*d9f75844SAndroid Build Coastguard Worker }
499*d9f75844SAndroid Build Coastguard Worker
500*d9f75844SAndroid Build Coastguard Worker // Insert correct HMAC into the attribute.
501*d9f75844SAndroid Build Coastguard Worker msg_integrity_attr->CopyBytes(hmac, attr_size);
502*d9f75844SAndroid Build Coastguard Worker password_ = std::string(key);
503*d9f75844SAndroid Build Coastguard Worker integrity_ = IntegrityStatus::kIntegrityOk;
504*d9f75844SAndroid Build Coastguard Worker return true;
505*d9f75844SAndroid Build Coastguard Worker }
506*d9f75844SAndroid Build Coastguard Worker
507*d9f75844SAndroid Build Coastguard Worker // Verifies a message is in fact a STUN message, by performing the checks
508*d9f75844SAndroid Build Coastguard Worker // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed
509*d9f75844SAndroid Build Coastguard Worker // in section 15.5.
ValidateFingerprint(const char * data,size_t size)510*d9f75844SAndroid Build Coastguard Worker bool StunMessage::ValidateFingerprint(const char* data, size_t size) {
511*d9f75844SAndroid Build Coastguard Worker // Check the message length.
512*d9f75844SAndroid Build Coastguard Worker size_t fingerprint_attr_size =
513*d9f75844SAndroid Build Coastguard Worker kStunAttributeHeaderSize + StunUInt32Attribute::SIZE;
514*d9f75844SAndroid Build Coastguard Worker if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size)
515*d9f75844SAndroid Build Coastguard Worker return false;
516*d9f75844SAndroid Build Coastguard Worker
517*d9f75844SAndroid Build Coastguard Worker // Skip the rest if the magic cookie isn't present.
518*d9f75844SAndroid Build Coastguard Worker const char* magic_cookie =
519*d9f75844SAndroid Build Coastguard Worker data + kStunTransactionIdOffset - kStunMagicCookieLength;
520*d9f75844SAndroid Build Coastguard Worker if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
521*d9f75844SAndroid Build Coastguard Worker return false;
522*d9f75844SAndroid Build Coastguard Worker
523*d9f75844SAndroid Build Coastguard Worker // Check the fingerprint type and length.
524*d9f75844SAndroid Build Coastguard Worker const char* fingerprint_attr_data = data + size - fingerprint_attr_size;
525*d9f75844SAndroid Build Coastguard Worker if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT ||
526*d9f75844SAndroid Build Coastguard Worker rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) !=
527*d9f75844SAndroid Build Coastguard Worker StunUInt32Attribute::SIZE)
528*d9f75844SAndroid Build Coastguard Worker return false;
529*d9f75844SAndroid Build Coastguard Worker
530*d9f75844SAndroid Build Coastguard Worker // Check the fingerprint value.
531*d9f75844SAndroid Build Coastguard Worker uint32_t fingerprint =
532*d9f75844SAndroid Build Coastguard Worker rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize);
533*d9f75844SAndroid Build Coastguard Worker return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) ==
534*d9f75844SAndroid Build Coastguard Worker rtc::ComputeCrc32(data, size - fingerprint_attr_size));
535*d9f75844SAndroid Build Coastguard Worker }
536*d9f75844SAndroid Build Coastguard Worker
537*d9f75844SAndroid Build Coastguard Worker // static
GenerateTransactionId()538*d9f75844SAndroid Build Coastguard Worker std::string StunMessage::GenerateTransactionId() {
539*d9f75844SAndroid Build Coastguard Worker return rtc::CreateRandomString(kStunTransactionIdLength);
540*d9f75844SAndroid Build Coastguard Worker }
541*d9f75844SAndroid Build Coastguard Worker
IsStunMethod(rtc::ArrayView<int> methods,const char * data,size_t size)542*d9f75844SAndroid Build Coastguard Worker bool StunMessage::IsStunMethod(rtc::ArrayView<int> methods,
543*d9f75844SAndroid Build Coastguard Worker const char* data,
544*d9f75844SAndroid Build Coastguard Worker size_t size) {
545*d9f75844SAndroid Build Coastguard Worker // Check the message length.
546*d9f75844SAndroid Build Coastguard Worker if (size % 4 != 0 || size < kStunHeaderSize)
547*d9f75844SAndroid Build Coastguard Worker return false;
548*d9f75844SAndroid Build Coastguard Worker
549*d9f75844SAndroid Build Coastguard Worker // Skip the rest if the magic cookie isn't present.
550*d9f75844SAndroid Build Coastguard Worker const char* magic_cookie =
551*d9f75844SAndroid Build Coastguard Worker data + kStunTransactionIdOffset - kStunMagicCookieLength;
552*d9f75844SAndroid Build Coastguard Worker if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
553*d9f75844SAndroid Build Coastguard Worker return false;
554*d9f75844SAndroid Build Coastguard Worker
555*d9f75844SAndroid Build Coastguard Worker int method = rtc::GetBE16(data);
556*d9f75844SAndroid Build Coastguard Worker for (int m : methods) {
557*d9f75844SAndroid Build Coastguard Worker if (m == method) {
558*d9f75844SAndroid Build Coastguard Worker return true;
559*d9f75844SAndroid Build Coastguard Worker }
560*d9f75844SAndroid Build Coastguard Worker }
561*d9f75844SAndroid Build Coastguard Worker return false;
562*d9f75844SAndroid Build Coastguard Worker }
563*d9f75844SAndroid Build Coastguard Worker
AddFingerprint()564*d9f75844SAndroid Build Coastguard Worker bool StunMessage::AddFingerprint() {
565*d9f75844SAndroid Build Coastguard Worker // Add the attribute with a dummy value. Since this is a known attribute,
566*d9f75844SAndroid Build Coastguard Worker // it can't fail.
567*d9f75844SAndroid Build Coastguard Worker auto fingerprint_attr_ptr =
568*d9f75844SAndroid Build Coastguard Worker std::make_unique<StunUInt32Attribute>(STUN_ATTR_FINGERPRINT, 0);
569*d9f75844SAndroid Build Coastguard Worker auto* fingerprint_attr = fingerprint_attr_ptr.get();
570*d9f75844SAndroid Build Coastguard Worker AddAttribute(std::move(fingerprint_attr_ptr));
571*d9f75844SAndroid Build Coastguard Worker
572*d9f75844SAndroid Build Coastguard Worker // Calculate the CRC-32 for the message and insert it.
573*d9f75844SAndroid Build Coastguard Worker ByteBufferWriter buf;
574*d9f75844SAndroid Build Coastguard Worker if (!Write(&buf))
575*d9f75844SAndroid Build Coastguard Worker return false;
576*d9f75844SAndroid Build Coastguard Worker
577*d9f75844SAndroid Build Coastguard Worker int msg_len_for_crc32 = static_cast<int>(
578*d9f75844SAndroid Build Coastguard Worker buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length());
579*d9f75844SAndroid Build Coastguard Worker uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32);
580*d9f75844SAndroid Build Coastguard Worker
581*d9f75844SAndroid Build Coastguard Worker // Insert the correct CRC-32, XORed with a constant, into the attribute.
582*d9f75844SAndroid Build Coastguard Worker fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE);
583*d9f75844SAndroid Build Coastguard Worker return true;
584*d9f75844SAndroid Build Coastguard Worker }
585*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)586*d9f75844SAndroid Build Coastguard Worker bool StunMessage::Read(ByteBufferReader* buf) {
587*d9f75844SAndroid Build Coastguard Worker // Keep a copy of the buffer data around for later verification.
588*d9f75844SAndroid Build Coastguard Worker buffer_.assign(buf->Data(), buf->Length());
589*d9f75844SAndroid Build Coastguard Worker
590*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&type_)) {
591*d9f75844SAndroid Build Coastguard Worker return false;
592*d9f75844SAndroid Build Coastguard Worker }
593*d9f75844SAndroid Build Coastguard Worker
594*d9f75844SAndroid Build Coastguard Worker if (type_ & 0x8000) {
595*d9f75844SAndroid Build Coastguard Worker // RTP and RTCP set the MSB of first byte, since first two bits are version,
596*d9f75844SAndroid Build Coastguard Worker // and version is always 2 (10). If set, this is not a STUN packet.
597*d9f75844SAndroid Build Coastguard Worker return false;
598*d9f75844SAndroid Build Coastguard Worker }
599*d9f75844SAndroid Build Coastguard Worker
600*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&length_)) {
601*d9f75844SAndroid Build Coastguard Worker return false;
602*d9f75844SAndroid Build Coastguard Worker }
603*d9f75844SAndroid Build Coastguard Worker
604*d9f75844SAndroid Build Coastguard Worker std::string magic_cookie;
605*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) {
606*d9f75844SAndroid Build Coastguard Worker return false;
607*d9f75844SAndroid Build Coastguard Worker }
608*d9f75844SAndroid Build Coastguard Worker
609*d9f75844SAndroid Build Coastguard Worker std::string transaction_id;
610*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) {
611*d9f75844SAndroid Build Coastguard Worker return false;
612*d9f75844SAndroid Build Coastguard Worker }
613*d9f75844SAndroid Build Coastguard Worker
614*d9f75844SAndroid Build Coastguard Worker uint32_t magic_cookie_int;
615*d9f75844SAndroid Build Coastguard Worker static_assert(sizeof(magic_cookie_int) == kStunMagicCookieLength,
616*d9f75844SAndroid Build Coastguard Worker "Integer size mismatch: magic_cookie_int and kStunMagicCookie");
617*d9f75844SAndroid Build Coastguard Worker std::memcpy(&magic_cookie_int, magic_cookie.data(), sizeof(magic_cookie_int));
618*d9f75844SAndroid Build Coastguard Worker if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
619*d9f75844SAndroid Build Coastguard Worker // If magic cookie is invalid it means that the peer implements
620*d9f75844SAndroid Build Coastguard Worker // RFC3489 instead of RFC5389.
621*d9f75844SAndroid Build Coastguard Worker transaction_id.insert(0, magic_cookie);
622*d9f75844SAndroid Build Coastguard Worker }
623*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsValidTransactionId(transaction_id));
624*d9f75844SAndroid Build Coastguard Worker transaction_id_ = transaction_id;
625*d9f75844SAndroid Build Coastguard Worker reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
626*d9f75844SAndroid Build Coastguard Worker
627*d9f75844SAndroid Build Coastguard Worker if (length_ != buf->Length()) {
628*d9f75844SAndroid Build Coastguard Worker return false;
629*d9f75844SAndroid Build Coastguard Worker }
630*d9f75844SAndroid Build Coastguard Worker
631*d9f75844SAndroid Build Coastguard Worker attrs_.resize(0);
632*d9f75844SAndroid Build Coastguard Worker
633*d9f75844SAndroid Build Coastguard Worker size_t rest = buf->Length() - length_;
634*d9f75844SAndroid Build Coastguard Worker while (buf->Length() > rest) {
635*d9f75844SAndroid Build Coastguard Worker uint16_t attr_type, attr_length;
636*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&attr_type))
637*d9f75844SAndroid Build Coastguard Worker return false;
638*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&attr_length))
639*d9f75844SAndroid Build Coastguard Worker return false;
640*d9f75844SAndroid Build Coastguard Worker
641*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAttribute> attr(
642*d9f75844SAndroid Build Coastguard Worker CreateAttribute(attr_type, attr_length));
643*d9f75844SAndroid Build Coastguard Worker if (!attr) {
644*d9f75844SAndroid Build Coastguard Worker // Skip any unknown or malformed attributes.
645*d9f75844SAndroid Build Coastguard Worker if ((attr_length % 4) != 0) {
646*d9f75844SAndroid Build Coastguard Worker attr_length += (4 - (attr_length % 4));
647*d9f75844SAndroid Build Coastguard Worker }
648*d9f75844SAndroid Build Coastguard Worker if (!buf->Consume(attr_length)) {
649*d9f75844SAndroid Build Coastguard Worker return false;
650*d9f75844SAndroid Build Coastguard Worker }
651*d9f75844SAndroid Build Coastguard Worker } else {
652*d9f75844SAndroid Build Coastguard Worker if (!attr->Read(buf)) {
653*d9f75844SAndroid Build Coastguard Worker return false;
654*d9f75844SAndroid Build Coastguard Worker }
655*d9f75844SAndroid Build Coastguard Worker attrs_.push_back(std::move(attr));
656*d9f75844SAndroid Build Coastguard Worker }
657*d9f75844SAndroid Build Coastguard Worker }
658*d9f75844SAndroid Build Coastguard Worker
659*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(buf->Length() == rest);
660*d9f75844SAndroid Build Coastguard Worker return true;
661*d9f75844SAndroid Build Coastguard Worker }
662*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const663*d9f75844SAndroid Build Coastguard Worker bool StunMessage::Write(ByteBufferWriter* buf) const {
664*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(type_);
665*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(length_);
666*d9f75844SAndroid Build Coastguard Worker if (!IsLegacy())
667*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt32(stun_magic_cookie_);
668*d9f75844SAndroid Build Coastguard Worker buf->WriteString(transaction_id_);
669*d9f75844SAndroid Build Coastguard Worker
670*d9f75844SAndroid Build Coastguard Worker for (const auto& attr : attrs_) {
671*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(attr->type());
672*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(static_cast<uint16_t>(attr->length()));
673*d9f75844SAndroid Build Coastguard Worker if (!attr->Write(buf)) {
674*d9f75844SAndroid Build Coastguard Worker return false;
675*d9f75844SAndroid Build Coastguard Worker }
676*d9f75844SAndroid Build Coastguard Worker }
677*d9f75844SAndroid Build Coastguard Worker
678*d9f75844SAndroid Build Coastguard Worker return true;
679*d9f75844SAndroid Build Coastguard Worker }
680*d9f75844SAndroid Build Coastguard Worker
CreateNew() const681*d9f75844SAndroid Build Coastguard Worker StunMessage* StunMessage::CreateNew() const {
682*d9f75844SAndroid Build Coastguard Worker return new StunMessage();
683*d9f75844SAndroid Build Coastguard Worker }
684*d9f75844SAndroid Build Coastguard Worker
SetStunMagicCookie(uint32_t val)685*d9f75844SAndroid Build Coastguard Worker void StunMessage::SetStunMagicCookie(uint32_t val) {
686*d9f75844SAndroid Build Coastguard Worker stun_magic_cookie_ = val;
687*d9f75844SAndroid Build Coastguard Worker }
688*d9f75844SAndroid Build Coastguard Worker
SetTransactionIdForTesting(absl::string_view transaction_id)689*d9f75844SAndroid Build Coastguard Worker void StunMessage::SetTransactionIdForTesting(absl::string_view transaction_id) {
690*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsValidTransactionId(transaction_id));
691*d9f75844SAndroid Build Coastguard Worker transaction_id_ = std::string(transaction_id);
692*d9f75844SAndroid Build Coastguard Worker reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
693*d9f75844SAndroid Build Coastguard Worker }
694*d9f75844SAndroid Build Coastguard Worker
GetAttributeValueType(int type) const695*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
696*d9f75844SAndroid Build Coastguard Worker switch (type) {
697*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_MAPPED_ADDRESS:
698*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ADDRESS;
699*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_USERNAME:
700*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
701*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_MESSAGE_INTEGRITY:
702*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
703*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_ERROR_CODE:
704*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ERROR_CODE;
705*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_UNKNOWN_ATTRIBUTES:
706*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT16_LIST;
707*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_REALM:
708*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
709*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_NONCE:
710*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
711*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_XOR_MAPPED_ADDRESS:
712*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_XOR_ADDRESS;
713*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_SOFTWARE:
714*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
715*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_ALTERNATE_SERVER:
716*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ADDRESS;
717*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_FINGERPRINT:
718*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
719*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_RETRANSMIT_COUNT:
720*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
721*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED:
722*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
723*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_GOOG_MISC_INFO:
724*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT16_LIST;
725*d9f75844SAndroid Build Coastguard Worker default:
726*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UNKNOWN;
727*d9f75844SAndroid Build Coastguard Worker }
728*d9f75844SAndroid Build Coastguard Worker }
729*d9f75844SAndroid Build Coastguard Worker
CreateAttribute(int type,size_t length)730*d9f75844SAndroid Build Coastguard Worker StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ {
731*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType value_type = GetAttributeValueType(type);
732*d9f75844SAndroid Build Coastguard Worker if (value_type != STUN_VALUE_UNKNOWN) {
733*d9f75844SAndroid Build Coastguard Worker return StunAttribute::Create(value_type, type,
734*d9f75844SAndroid Build Coastguard Worker static_cast<uint16_t>(length), this);
735*d9f75844SAndroid Build Coastguard Worker } else if (DesignatedExpertRange(type)) {
736*d9f75844SAndroid Build Coastguard Worker // Read unknown attributes as STUN_VALUE_BYTE_STRING
737*d9f75844SAndroid Build Coastguard Worker return StunAttribute::Create(STUN_VALUE_BYTE_STRING, type,
738*d9f75844SAndroid Build Coastguard Worker static_cast<uint16_t>(length), this);
739*d9f75844SAndroid Build Coastguard Worker } else {
740*d9f75844SAndroid Build Coastguard Worker return NULL;
741*d9f75844SAndroid Build Coastguard Worker }
742*d9f75844SAndroid Build Coastguard Worker }
743*d9f75844SAndroid Build Coastguard Worker
GetAttribute(int type) const744*d9f75844SAndroid Build Coastguard Worker const StunAttribute* StunMessage::GetAttribute(int type) const {
745*d9f75844SAndroid Build Coastguard Worker for (const auto& attr : attrs_) {
746*d9f75844SAndroid Build Coastguard Worker if (attr->type() == type) {
747*d9f75844SAndroid Build Coastguard Worker return attr.get();
748*d9f75844SAndroid Build Coastguard Worker }
749*d9f75844SAndroid Build Coastguard Worker }
750*d9f75844SAndroid Build Coastguard Worker return NULL;
751*d9f75844SAndroid Build Coastguard Worker }
752*d9f75844SAndroid Build Coastguard Worker
IsValidTransactionId(absl::string_view transaction_id)753*d9f75844SAndroid Build Coastguard Worker bool StunMessage::IsValidTransactionId(absl::string_view transaction_id) {
754*d9f75844SAndroid Build Coastguard Worker return transaction_id.size() == kStunTransactionIdLength ||
755*d9f75844SAndroid Build Coastguard Worker transaction_id.size() == kStunLegacyTransactionIdLength;
756*d9f75844SAndroid Build Coastguard Worker }
757*d9f75844SAndroid Build Coastguard Worker
EqualAttributes(const StunMessage * other,std::function<bool (int type)> attribute_type_mask) const758*d9f75844SAndroid Build Coastguard Worker bool StunMessage::EqualAttributes(
759*d9f75844SAndroid Build Coastguard Worker const StunMessage* other,
760*d9f75844SAndroid Build Coastguard Worker std::function<bool(int type)> attribute_type_mask) const {
761*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(other != nullptr);
762*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter tmp_buffer_ptr1;
763*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter tmp_buffer_ptr2;
764*d9f75844SAndroid Build Coastguard Worker for (const auto& attr : attrs_) {
765*d9f75844SAndroid Build Coastguard Worker if (attribute_type_mask(attr->type())) {
766*d9f75844SAndroid Build Coastguard Worker const StunAttribute* other_attr = other->GetAttribute(attr->type());
767*d9f75844SAndroid Build Coastguard Worker if (other_attr == nullptr) {
768*d9f75844SAndroid Build Coastguard Worker return false;
769*d9f75844SAndroid Build Coastguard Worker }
770*d9f75844SAndroid Build Coastguard Worker tmp_buffer_ptr1.Clear();
771*d9f75844SAndroid Build Coastguard Worker tmp_buffer_ptr2.Clear();
772*d9f75844SAndroid Build Coastguard Worker attr->Write(&tmp_buffer_ptr1);
773*d9f75844SAndroid Build Coastguard Worker other_attr->Write(&tmp_buffer_ptr2);
774*d9f75844SAndroid Build Coastguard Worker if (tmp_buffer_ptr1.Length() != tmp_buffer_ptr2.Length()) {
775*d9f75844SAndroid Build Coastguard Worker return false;
776*d9f75844SAndroid Build Coastguard Worker }
777*d9f75844SAndroid Build Coastguard Worker if (memcmp(tmp_buffer_ptr1.Data(), tmp_buffer_ptr2.Data(),
778*d9f75844SAndroid Build Coastguard Worker tmp_buffer_ptr1.Length()) != 0) {
779*d9f75844SAndroid Build Coastguard Worker return false;
780*d9f75844SAndroid Build Coastguard Worker }
781*d9f75844SAndroid Build Coastguard Worker }
782*d9f75844SAndroid Build Coastguard Worker }
783*d9f75844SAndroid Build Coastguard Worker
784*d9f75844SAndroid Build Coastguard Worker for (const auto& attr : other->attrs_) {
785*d9f75844SAndroid Build Coastguard Worker if (attribute_type_mask(attr->type())) {
786*d9f75844SAndroid Build Coastguard Worker const StunAttribute* own_attr = GetAttribute(attr->type());
787*d9f75844SAndroid Build Coastguard Worker if (own_attr == nullptr) {
788*d9f75844SAndroid Build Coastguard Worker return false;
789*d9f75844SAndroid Build Coastguard Worker }
790*d9f75844SAndroid Build Coastguard Worker // we have already compared all values...
791*d9f75844SAndroid Build Coastguard Worker }
792*d9f75844SAndroid Build Coastguard Worker }
793*d9f75844SAndroid Build Coastguard Worker return true;
794*d9f75844SAndroid Build Coastguard Worker }
795*d9f75844SAndroid Build Coastguard Worker
796*d9f75844SAndroid Build Coastguard Worker // StunAttribute
797*d9f75844SAndroid Build Coastguard Worker
StunAttribute(uint16_t type,uint16_t length)798*d9f75844SAndroid Build Coastguard Worker StunAttribute::StunAttribute(uint16_t type, uint16_t length)
799*d9f75844SAndroid Build Coastguard Worker : type_(type), length_(length) {}
800*d9f75844SAndroid Build Coastguard Worker
ConsumePadding(ByteBufferReader * buf) const801*d9f75844SAndroid Build Coastguard Worker void StunAttribute::ConsumePadding(ByteBufferReader* buf) const {
802*d9f75844SAndroid Build Coastguard Worker int remainder = length_ % 4;
803*d9f75844SAndroid Build Coastguard Worker if (remainder > 0) {
804*d9f75844SAndroid Build Coastguard Worker buf->Consume(4 - remainder);
805*d9f75844SAndroid Build Coastguard Worker }
806*d9f75844SAndroid Build Coastguard Worker }
807*d9f75844SAndroid Build Coastguard Worker
WritePadding(ByteBufferWriter * buf) const808*d9f75844SAndroid Build Coastguard Worker void StunAttribute::WritePadding(ByteBufferWriter* buf) const {
809*d9f75844SAndroid Build Coastguard Worker int remainder = length_ % 4;
810*d9f75844SAndroid Build Coastguard Worker if (remainder > 0) {
811*d9f75844SAndroid Build Coastguard Worker char zeroes[4] = {0};
812*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(zeroes, 4 - remainder);
813*d9f75844SAndroid Build Coastguard Worker }
814*d9f75844SAndroid Build Coastguard Worker }
815*d9f75844SAndroid Build Coastguard Worker
Create(StunAttributeValueType value_type,uint16_t type,uint16_t length,StunMessage * owner)816*d9f75844SAndroid Build Coastguard Worker StunAttribute* StunAttribute::Create(StunAttributeValueType value_type,
817*d9f75844SAndroid Build Coastguard Worker uint16_t type,
818*d9f75844SAndroid Build Coastguard Worker uint16_t length,
819*d9f75844SAndroid Build Coastguard Worker StunMessage* owner) {
820*d9f75844SAndroid Build Coastguard Worker switch (value_type) {
821*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_ADDRESS:
822*d9f75844SAndroid Build Coastguard Worker return new StunAddressAttribute(type, length);
823*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_XOR_ADDRESS:
824*d9f75844SAndroid Build Coastguard Worker return new StunXorAddressAttribute(type, length, owner);
825*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_UINT32:
826*d9f75844SAndroid Build Coastguard Worker return new StunUInt32Attribute(type);
827*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_UINT64:
828*d9f75844SAndroid Build Coastguard Worker return new StunUInt64Attribute(type);
829*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_BYTE_STRING:
830*d9f75844SAndroid Build Coastguard Worker return new StunByteStringAttribute(type, length);
831*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_ERROR_CODE:
832*d9f75844SAndroid Build Coastguard Worker return new StunErrorCodeAttribute(type, length);
833*d9f75844SAndroid Build Coastguard Worker case STUN_VALUE_UINT16_LIST:
834*d9f75844SAndroid Build Coastguard Worker return new StunUInt16ListAttribute(type, length);
835*d9f75844SAndroid Build Coastguard Worker default:
836*d9f75844SAndroid Build Coastguard Worker return NULL;
837*d9f75844SAndroid Build Coastguard Worker }
838*d9f75844SAndroid Build Coastguard Worker }
839*d9f75844SAndroid Build Coastguard Worker
CreateAddress(uint16_t type)840*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAddressAttribute> StunAttribute::CreateAddress(
841*d9f75844SAndroid Build Coastguard Worker uint16_t type) {
842*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunAddressAttribute>(type, 0);
843*d9f75844SAndroid Build Coastguard Worker }
844*d9f75844SAndroid Build Coastguard Worker
CreateXorAddress(uint16_t type)845*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunXorAddressAttribute> StunAttribute::CreateXorAddress(
846*d9f75844SAndroid Build Coastguard Worker uint16_t type) {
847*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunXorAddressAttribute>(type, 0, nullptr);
848*d9f75844SAndroid Build Coastguard Worker }
849*d9f75844SAndroid Build Coastguard Worker
CreateUInt64(uint16_t type)850*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunUInt64Attribute> StunAttribute::CreateUInt64(
851*d9f75844SAndroid Build Coastguard Worker uint16_t type) {
852*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunUInt64Attribute>(type);
853*d9f75844SAndroid Build Coastguard Worker }
854*d9f75844SAndroid Build Coastguard Worker
CreateUInt32(uint16_t type)855*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunUInt32Attribute> StunAttribute::CreateUInt32(
856*d9f75844SAndroid Build Coastguard Worker uint16_t type) {
857*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunUInt32Attribute>(type);
858*d9f75844SAndroid Build Coastguard Worker }
859*d9f75844SAndroid Build Coastguard Worker
CreateByteString(uint16_t type)860*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunByteStringAttribute> StunAttribute::CreateByteString(
861*d9f75844SAndroid Build Coastguard Worker uint16_t type) {
862*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunByteStringAttribute>(type, 0);
863*d9f75844SAndroid Build Coastguard Worker }
864*d9f75844SAndroid Build Coastguard Worker
CreateErrorCode()865*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunErrorCodeAttribute> StunAttribute::CreateErrorCode() {
866*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunErrorCodeAttribute>(
867*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
868*d9f75844SAndroid Build Coastguard Worker }
869*d9f75844SAndroid Build Coastguard Worker
870*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunUInt16ListAttribute>
CreateUInt16ListAttribute(uint16_t type)871*d9f75844SAndroid Build Coastguard Worker StunAttribute::CreateUInt16ListAttribute(uint16_t type) {
872*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunUInt16ListAttribute>(type, 0);
873*d9f75844SAndroid Build Coastguard Worker }
874*d9f75844SAndroid Build Coastguard Worker
875*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunUInt16ListAttribute>
CreateUnknownAttributes()876*d9f75844SAndroid Build Coastguard Worker StunAttribute::CreateUnknownAttributes() {
877*d9f75844SAndroid Build Coastguard Worker return std::make_unique<StunUInt16ListAttribute>(STUN_ATTR_UNKNOWN_ATTRIBUTES,
878*d9f75844SAndroid Build Coastguard Worker 0);
879*d9f75844SAndroid Build Coastguard Worker }
880*d9f75844SAndroid Build Coastguard Worker
StunAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)881*d9f75844SAndroid Build Coastguard Worker StunAddressAttribute::StunAddressAttribute(uint16_t type,
882*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr)
883*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, 0) {
884*d9f75844SAndroid Build Coastguard Worker SetAddress(addr);
885*d9f75844SAndroid Build Coastguard Worker }
886*d9f75844SAndroid Build Coastguard Worker
StunAddressAttribute(uint16_t type,uint16_t length)887*d9f75844SAndroid Build Coastguard Worker StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length)
888*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, length) {}
889*d9f75844SAndroid Build Coastguard Worker
value_type() const890*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunAddressAttribute::value_type() const {
891*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ADDRESS;
892*d9f75844SAndroid Build Coastguard Worker }
893*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)894*d9f75844SAndroid Build Coastguard Worker bool StunAddressAttribute::Read(ByteBufferReader* buf) {
895*d9f75844SAndroid Build Coastguard Worker uint8_t dummy;
896*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt8(&dummy))
897*d9f75844SAndroid Build Coastguard Worker return false;
898*d9f75844SAndroid Build Coastguard Worker
899*d9f75844SAndroid Build Coastguard Worker uint8_t stun_family;
900*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt8(&stun_family)) {
901*d9f75844SAndroid Build Coastguard Worker return false;
902*d9f75844SAndroid Build Coastguard Worker }
903*d9f75844SAndroid Build Coastguard Worker uint16_t port;
904*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&port))
905*d9f75844SAndroid Build Coastguard Worker return false;
906*d9f75844SAndroid Build Coastguard Worker if (stun_family == STUN_ADDRESS_IPV4) {
907*d9f75844SAndroid Build Coastguard Worker in_addr v4addr;
908*d9f75844SAndroid Build Coastguard Worker if (length() != SIZE_IP4) {
909*d9f75844SAndroid Build Coastguard Worker return false;
910*d9f75844SAndroid Build Coastguard Worker }
911*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) {
912*d9f75844SAndroid Build Coastguard Worker return false;
913*d9f75844SAndroid Build Coastguard Worker }
914*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress ipaddr(v4addr);
915*d9f75844SAndroid Build Coastguard Worker SetAddress(rtc::SocketAddress(ipaddr, port));
916*d9f75844SAndroid Build Coastguard Worker } else if (stun_family == STUN_ADDRESS_IPV6) {
917*d9f75844SAndroid Build Coastguard Worker in6_addr v6addr;
918*d9f75844SAndroid Build Coastguard Worker if (length() != SIZE_IP6) {
919*d9f75844SAndroid Build Coastguard Worker return false;
920*d9f75844SAndroid Build Coastguard Worker }
921*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) {
922*d9f75844SAndroid Build Coastguard Worker return false;
923*d9f75844SAndroid Build Coastguard Worker }
924*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress ipaddr(v6addr);
925*d9f75844SAndroid Build Coastguard Worker SetAddress(rtc::SocketAddress(ipaddr, port));
926*d9f75844SAndroid Build Coastguard Worker } else {
927*d9f75844SAndroid Build Coastguard Worker return false;
928*d9f75844SAndroid Build Coastguard Worker }
929*d9f75844SAndroid Build Coastguard Worker return true;
930*d9f75844SAndroid Build Coastguard Worker }
931*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const932*d9f75844SAndroid Build Coastguard Worker bool StunAddressAttribute::Write(ByteBufferWriter* buf) const {
933*d9f75844SAndroid Build Coastguard Worker StunAddressFamily address_family = family();
934*d9f75844SAndroid Build Coastguard Worker if (address_family == STUN_ADDRESS_UNDEF) {
935*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Error writing address attribute: unknown family.";
936*d9f75844SAndroid Build Coastguard Worker return false;
937*d9f75844SAndroid Build Coastguard Worker }
938*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt8(0);
939*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt8(address_family);
940*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(address_.port());
941*d9f75844SAndroid Build Coastguard Worker switch (address_.family()) {
942*d9f75844SAndroid Build Coastguard Worker case AF_INET: {
943*d9f75844SAndroid Build Coastguard Worker in_addr v4addr = address_.ipaddr().ipv4_address();
944*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr));
945*d9f75844SAndroid Build Coastguard Worker break;
946*d9f75844SAndroid Build Coastguard Worker }
947*d9f75844SAndroid Build Coastguard Worker case AF_INET6: {
948*d9f75844SAndroid Build Coastguard Worker in6_addr v6addr = address_.ipaddr().ipv6_address();
949*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr));
950*d9f75844SAndroid Build Coastguard Worker break;
951*d9f75844SAndroid Build Coastguard Worker }
952*d9f75844SAndroid Build Coastguard Worker }
953*d9f75844SAndroid Build Coastguard Worker return true;
954*d9f75844SAndroid Build Coastguard Worker }
955*d9f75844SAndroid Build Coastguard Worker
StunXorAddressAttribute(uint16_t type,const rtc::SocketAddress & addr)956*d9f75844SAndroid Build Coastguard Worker StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
957*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr)
958*d9f75844SAndroid Build Coastguard Worker : StunAddressAttribute(type, addr), owner_(NULL) {}
959*d9f75844SAndroid Build Coastguard Worker
StunXorAddressAttribute(uint16_t type,uint16_t length,StunMessage * owner)960*d9f75844SAndroid Build Coastguard Worker StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type,
961*d9f75844SAndroid Build Coastguard Worker uint16_t length,
962*d9f75844SAndroid Build Coastguard Worker StunMessage* owner)
963*d9f75844SAndroid Build Coastguard Worker : StunAddressAttribute(type, length), owner_(owner) {}
964*d9f75844SAndroid Build Coastguard Worker
value_type() const965*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunXorAddressAttribute::value_type() const {
966*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_XOR_ADDRESS;
967*d9f75844SAndroid Build Coastguard Worker }
968*d9f75844SAndroid Build Coastguard Worker
SetOwner(StunMessage * owner)969*d9f75844SAndroid Build Coastguard Worker void StunXorAddressAttribute::SetOwner(StunMessage* owner) {
970*d9f75844SAndroid Build Coastguard Worker owner_ = owner;
971*d9f75844SAndroid Build Coastguard Worker }
972*d9f75844SAndroid Build Coastguard Worker
GetXoredIP() const973*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const {
974*d9f75844SAndroid Build Coastguard Worker if (owner_) {
975*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress ip = ipaddr();
976*d9f75844SAndroid Build Coastguard Worker switch (ip.family()) {
977*d9f75844SAndroid Build Coastguard Worker case AF_INET: {
978*d9f75844SAndroid Build Coastguard Worker in_addr v4addr = ip.ipv4_address();
979*d9f75844SAndroid Build Coastguard Worker v4addr.s_addr =
980*d9f75844SAndroid Build Coastguard Worker (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie));
981*d9f75844SAndroid Build Coastguard Worker return rtc::IPAddress(v4addr);
982*d9f75844SAndroid Build Coastguard Worker }
983*d9f75844SAndroid Build Coastguard Worker case AF_INET6: {
984*d9f75844SAndroid Build Coastguard Worker in6_addr v6addr = ip.ipv6_address();
985*d9f75844SAndroid Build Coastguard Worker const std::string& transaction_id = owner_->transaction_id();
986*d9f75844SAndroid Build Coastguard Worker if (transaction_id.length() == kStunTransactionIdLength) {
987*d9f75844SAndroid Build Coastguard Worker uint32_t transactionid_as_ints[3];
988*d9f75844SAndroid Build Coastguard Worker memcpy(&transactionid_as_ints[0], transaction_id.c_str(),
989*d9f75844SAndroid Build Coastguard Worker transaction_id.length());
990*d9f75844SAndroid Build Coastguard Worker uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr);
991*d9f75844SAndroid Build Coastguard Worker // Transaction ID is in network byte order, but magic cookie
992*d9f75844SAndroid Build Coastguard Worker // is stored in host byte order.
993*d9f75844SAndroid Build Coastguard Worker ip_as_ints[0] =
994*d9f75844SAndroid Build Coastguard Worker (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie));
995*d9f75844SAndroid Build Coastguard Worker ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]);
996*d9f75844SAndroid Build Coastguard Worker ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]);
997*d9f75844SAndroid Build Coastguard Worker ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]);
998*d9f75844SAndroid Build Coastguard Worker return rtc::IPAddress(v6addr);
999*d9f75844SAndroid Build Coastguard Worker }
1000*d9f75844SAndroid Build Coastguard Worker break;
1001*d9f75844SAndroid Build Coastguard Worker }
1002*d9f75844SAndroid Build Coastguard Worker }
1003*d9f75844SAndroid Build Coastguard Worker }
1004*d9f75844SAndroid Build Coastguard Worker // Invalid ip family or transaction ID, or missing owner.
1005*d9f75844SAndroid Build Coastguard Worker // Return an AF_UNSPEC address.
1006*d9f75844SAndroid Build Coastguard Worker return rtc::IPAddress();
1007*d9f75844SAndroid Build Coastguard Worker }
1008*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1009*d9f75844SAndroid Build Coastguard Worker bool StunXorAddressAttribute::Read(ByteBufferReader* buf) {
1010*d9f75844SAndroid Build Coastguard Worker if (!StunAddressAttribute::Read(buf))
1011*d9f75844SAndroid Build Coastguard Worker return false;
1012*d9f75844SAndroid Build Coastguard Worker uint16_t xoredport = port() ^ (kStunMagicCookie >> 16);
1013*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress xored_ip = GetXoredIP();
1014*d9f75844SAndroid Build Coastguard Worker SetAddress(rtc::SocketAddress(xored_ip, xoredport));
1015*d9f75844SAndroid Build Coastguard Worker return true;
1016*d9f75844SAndroid Build Coastguard Worker }
1017*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1018*d9f75844SAndroid Build Coastguard Worker bool StunXorAddressAttribute::Write(ByteBufferWriter* buf) const {
1019*d9f75844SAndroid Build Coastguard Worker StunAddressFamily address_family = family();
1020*d9f75844SAndroid Build Coastguard Worker if (address_family == STUN_ADDRESS_UNDEF) {
1021*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
1022*d9f75844SAndroid Build Coastguard Worker return false;
1023*d9f75844SAndroid Build Coastguard Worker }
1024*d9f75844SAndroid Build Coastguard Worker rtc::IPAddress xored_ip = GetXoredIP();
1025*d9f75844SAndroid Build Coastguard Worker if (xored_ip.family() == AF_UNSPEC) {
1026*d9f75844SAndroid Build Coastguard Worker return false;
1027*d9f75844SAndroid Build Coastguard Worker }
1028*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt8(0);
1029*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt8(family());
1030*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16));
1031*d9f75844SAndroid Build Coastguard Worker switch (xored_ip.family()) {
1032*d9f75844SAndroid Build Coastguard Worker case AF_INET: {
1033*d9f75844SAndroid Build Coastguard Worker in_addr v4addr = xored_ip.ipv4_address();
1034*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr));
1035*d9f75844SAndroid Build Coastguard Worker break;
1036*d9f75844SAndroid Build Coastguard Worker }
1037*d9f75844SAndroid Build Coastguard Worker case AF_INET6: {
1038*d9f75844SAndroid Build Coastguard Worker in6_addr v6addr = xored_ip.ipv6_address();
1039*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr));
1040*d9f75844SAndroid Build Coastguard Worker break;
1041*d9f75844SAndroid Build Coastguard Worker }
1042*d9f75844SAndroid Build Coastguard Worker }
1043*d9f75844SAndroid Build Coastguard Worker return true;
1044*d9f75844SAndroid Build Coastguard Worker }
1045*d9f75844SAndroid Build Coastguard Worker
StunUInt32Attribute(uint16_t type,uint32_t value)1046*d9f75844SAndroid Build Coastguard Worker StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value)
1047*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, SIZE), bits_(value) {}
1048*d9f75844SAndroid Build Coastguard Worker
StunUInt32Attribute(uint16_t type)1049*d9f75844SAndroid Build Coastguard Worker StunUInt32Attribute::StunUInt32Attribute(uint16_t type)
1050*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, SIZE), bits_(0) {}
1051*d9f75844SAndroid Build Coastguard Worker
value_type() const1052*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunUInt32Attribute::value_type() const {
1053*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1054*d9f75844SAndroid Build Coastguard Worker }
1055*d9f75844SAndroid Build Coastguard Worker
GetBit(size_t index) const1056*d9f75844SAndroid Build Coastguard Worker bool StunUInt32Attribute::GetBit(size_t index) const {
1057*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(index < 32);
1058*d9f75844SAndroid Build Coastguard Worker return static_cast<bool>((bits_ >> index) & 0x1);
1059*d9f75844SAndroid Build Coastguard Worker }
1060*d9f75844SAndroid Build Coastguard Worker
SetBit(size_t index,bool value)1061*d9f75844SAndroid Build Coastguard Worker void StunUInt32Attribute::SetBit(size_t index, bool value) {
1062*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(index < 32);
1063*d9f75844SAndroid Build Coastguard Worker bits_ &= ~(1 << index);
1064*d9f75844SAndroid Build Coastguard Worker bits_ |= value ? (1 << index) : 0;
1065*d9f75844SAndroid Build Coastguard Worker }
1066*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1067*d9f75844SAndroid Build Coastguard Worker bool StunUInt32Attribute::Read(ByteBufferReader* buf) {
1068*d9f75844SAndroid Build Coastguard Worker if (length() != SIZE || !buf->ReadUInt32(&bits_))
1069*d9f75844SAndroid Build Coastguard Worker return false;
1070*d9f75844SAndroid Build Coastguard Worker return true;
1071*d9f75844SAndroid Build Coastguard Worker }
1072*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1073*d9f75844SAndroid Build Coastguard Worker bool StunUInt32Attribute::Write(ByteBufferWriter* buf) const {
1074*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt32(bits_);
1075*d9f75844SAndroid Build Coastguard Worker return true;
1076*d9f75844SAndroid Build Coastguard Worker }
1077*d9f75844SAndroid Build Coastguard Worker
StunUInt64Attribute(uint16_t type,uint64_t value)1078*d9f75844SAndroid Build Coastguard Worker StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value)
1079*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, SIZE), bits_(value) {}
1080*d9f75844SAndroid Build Coastguard Worker
StunUInt64Attribute(uint16_t type)1081*d9f75844SAndroid Build Coastguard Worker StunUInt64Attribute::StunUInt64Attribute(uint16_t type)
1082*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, SIZE), bits_(0) {}
1083*d9f75844SAndroid Build Coastguard Worker
value_type() const1084*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunUInt64Attribute::value_type() const {
1085*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT64;
1086*d9f75844SAndroid Build Coastguard Worker }
1087*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1088*d9f75844SAndroid Build Coastguard Worker bool StunUInt64Attribute::Read(ByteBufferReader* buf) {
1089*d9f75844SAndroid Build Coastguard Worker if (length() != SIZE || !buf->ReadUInt64(&bits_))
1090*d9f75844SAndroid Build Coastguard Worker return false;
1091*d9f75844SAndroid Build Coastguard Worker return true;
1092*d9f75844SAndroid Build Coastguard Worker }
1093*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1094*d9f75844SAndroid Build Coastguard Worker bool StunUInt64Attribute::Write(ByteBufferWriter* buf) const {
1095*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt64(bits_);
1096*d9f75844SAndroid Build Coastguard Worker return true;
1097*d9f75844SAndroid Build Coastguard Worker }
1098*d9f75844SAndroid Build Coastguard Worker
StunByteStringAttribute(uint16_t type)1099*d9f75844SAndroid Build Coastguard Worker StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
1100*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, 0), bytes_(NULL) {}
1101*d9f75844SAndroid Build Coastguard Worker
StunByteStringAttribute(uint16_t type,absl::string_view str)1102*d9f75844SAndroid Build Coastguard Worker StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
1103*d9f75844SAndroid Build Coastguard Worker absl::string_view str)
1104*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, 0), bytes_(NULL) {
1105*d9f75844SAndroid Build Coastguard Worker CopyBytes(str);
1106*d9f75844SAndroid Build Coastguard Worker }
1107*d9f75844SAndroid Build Coastguard Worker
StunByteStringAttribute(uint16_t type,const void * bytes,size_t length)1108*d9f75844SAndroid Build Coastguard Worker StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
1109*d9f75844SAndroid Build Coastguard Worker const void* bytes,
1110*d9f75844SAndroid Build Coastguard Worker size_t length)
1111*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, 0), bytes_(NULL) {
1112*d9f75844SAndroid Build Coastguard Worker CopyBytes(bytes, length);
1113*d9f75844SAndroid Build Coastguard Worker }
1114*d9f75844SAndroid Build Coastguard Worker
StunByteStringAttribute(uint16_t type,uint16_t length)1115*d9f75844SAndroid Build Coastguard Worker StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length)
1116*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, length), bytes_(NULL) {}
1117*d9f75844SAndroid Build Coastguard Worker
~StunByteStringAttribute()1118*d9f75844SAndroid Build Coastguard Worker StunByteStringAttribute::~StunByteStringAttribute() {
1119*d9f75844SAndroid Build Coastguard Worker delete[] bytes_;
1120*d9f75844SAndroid Build Coastguard Worker }
1121*d9f75844SAndroid Build Coastguard Worker
value_type() const1122*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunByteStringAttribute::value_type() const {
1123*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1124*d9f75844SAndroid Build Coastguard Worker }
1125*d9f75844SAndroid Build Coastguard Worker
CopyBytes(absl::string_view bytes)1126*d9f75844SAndroid Build Coastguard Worker void StunByteStringAttribute::CopyBytes(absl::string_view bytes) {
1127*d9f75844SAndroid Build Coastguard Worker char* new_bytes = new char[bytes.size()];
1128*d9f75844SAndroid Build Coastguard Worker memcpy(new_bytes, bytes.data(), bytes.size());
1129*d9f75844SAndroid Build Coastguard Worker SetBytes(new_bytes, bytes.size());
1130*d9f75844SAndroid Build Coastguard Worker }
1131*d9f75844SAndroid Build Coastguard Worker
CopyBytes(const void * bytes,size_t length)1132*d9f75844SAndroid Build Coastguard Worker void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {
1133*d9f75844SAndroid Build Coastguard Worker char* new_bytes = new char[length];
1134*d9f75844SAndroid Build Coastguard Worker memcpy(new_bytes, bytes, length);
1135*d9f75844SAndroid Build Coastguard Worker SetBytes(new_bytes, length);
1136*d9f75844SAndroid Build Coastguard Worker }
1137*d9f75844SAndroid Build Coastguard Worker
GetByte(size_t index) const1138*d9f75844SAndroid Build Coastguard Worker uint8_t StunByteStringAttribute::GetByte(size_t index) const {
1139*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(bytes_ != NULL);
1140*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(index < length());
1141*d9f75844SAndroid Build Coastguard Worker return static_cast<uint8_t>(bytes_[index]);
1142*d9f75844SAndroid Build Coastguard Worker }
1143*d9f75844SAndroid Build Coastguard Worker
SetByte(size_t index,uint8_t value)1144*d9f75844SAndroid Build Coastguard Worker void StunByteStringAttribute::SetByte(size_t index, uint8_t value) {
1145*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(bytes_ != NULL);
1146*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(index < length());
1147*d9f75844SAndroid Build Coastguard Worker bytes_[index] = value;
1148*d9f75844SAndroid Build Coastguard Worker }
1149*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1150*d9f75844SAndroid Build Coastguard Worker bool StunByteStringAttribute::Read(ByteBufferReader* buf) {
1151*d9f75844SAndroid Build Coastguard Worker bytes_ = new char[length()];
1152*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadBytes(bytes_, length())) {
1153*d9f75844SAndroid Build Coastguard Worker return false;
1154*d9f75844SAndroid Build Coastguard Worker }
1155*d9f75844SAndroid Build Coastguard Worker
1156*d9f75844SAndroid Build Coastguard Worker ConsumePadding(buf);
1157*d9f75844SAndroid Build Coastguard Worker return true;
1158*d9f75844SAndroid Build Coastguard Worker }
1159*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1160*d9f75844SAndroid Build Coastguard Worker bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const {
1161*d9f75844SAndroid Build Coastguard Worker // Check that length is legal according to specs
1162*d9f75844SAndroid Build Coastguard Worker if (!LengthValid(type(), length())) {
1163*d9f75844SAndroid Build Coastguard Worker return false;
1164*d9f75844SAndroid Build Coastguard Worker }
1165*d9f75844SAndroid Build Coastguard Worker buf->WriteBytes(bytes_, length());
1166*d9f75844SAndroid Build Coastguard Worker WritePadding(buf);
1167*d9f75844SAndroid Build Coastguard Worker return true;
1168*d9f75844SAndroid Build Coastguard Worker }
1169*d9f75844SAndroid Build Coastguard Worker
SetBytes(char * bytes,size_t length)1170*d9f75844SAndroid Build Coastguard Worker void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
1171*d9f75844SAndroid Build Coastguard Worker delete[] bytes_;
1172*d9f75844SAndroid Build Coastguard Worker bytes_ = bytes;
1173*d9f75844SAndroid Build Coastguard Worker SetLength(static_cast<uint16_t>(length));
1174*d9f75844SAndroid Build Coastguard Worker }
1175*d9f75844SAndroid Build Coastguard Worker
1176*d9f75844SAndroid Build Coastguard Worker const uint16_t StunErrorCodeAttribute::MIN_SIZE = 4;
1177*d9f75844SAndroid Build Coastguard Worker
StunErrorCodeAttribute(uint16_t type,int code,const std::string & reason)1178*d9f75844SAndroid Build Coastguard Worker StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type,
1179*d9f75844SAndroid Build Coastguard Worker int code,
1180*d9f75844SAndroid Build Coastguard Worker const std::string& reason)
1181*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, 0) {
1182*d9f75844SAndroid Build Coastguard Worker SetCode(code);
1183*d9f75844SAndroid Build Coastguard Worker SetReason(reason);
1184*d9f75844SAndroid Build Coastguard Worker }
1185*d9f75844SAndroid Build Coastguard Worker
StunErrorCodeAttribute(uint16_t type,uint16_t length)1186*d9f75844SAndroid Build Coastguard Worker StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length)
1187*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, length), class_(0), number_(0) {}
1188*d9f75844SAndroid Build Coastguard Worker
~StunErrorCodeAttribute()1189*d9f75844SAndroid Build Coastguard Worker StunErrorCodeAttribute::~StunErrorCodeAttribute() {}
1190*d9f75844SAndroid Build Coastguard Worker
value_type() const1191*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunErrorCodeAttribute::value_type() const {
1192*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ERROR_CODE;
1193*d9f75844SAndroid Build Coastguard Worker }
1194*d9f75844SAndroid Build Coastguard Worker
code() const1195*d9f75844SAndroid Build Coastguard Worker int StunErrorCodeAttribute::code() const {
1196*d9f75844SAndroid Build Coastguard Worker return class_ * 100 + number_;
1197*d9f75844SAndroid Build Coastguard Worker }
1198*d9f75844SAndroid Build Coastguard Worker
SetCode(int code)1199*d9f75844SAndroid Build Coastguard Worker void StunErrorCodeAttribute::SetCode(int code) {
1200*d9f75844SAndroid Build Coastguard Worker class_ = static_cast<uint8_t>(code / 100);
1201*d9f75844SAndroid Build Coastguard Worker number_ = static_cast<uint8_t>(code % 100);
1202*d9f75844SAndroid Build Coastguard Worker }
1203*d9f75844SAndroid Build Coastguard Worker
SetReason(const std::string & reason)1204*d9f75844SAndroid Build Coastguard Worker void StunErrorCodeAttribute::SetReason(const std::string& reason) {
1205*d9f75844SAndroid Build Coastguard Worker SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size()));
1206*d9f75844SAndroid Build Coastguard Worker reason_ = reason;
1207*d9f75844SAndroid Build Coastguard Worker }
1208*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1209*d9f75844SAndroid Build Coastguard Worker bool StunErrorCodeAttribute::Read(ByteBufferReader* buf) {
1210*d9f75844SAndroid Build Coastguard Worker uint32_t val;
1211*d9f75844SAndroid Build Coastguard Worker if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
1212*d9f75844SAndroid Build Coastguard Worker return false;
1213*d9f75844SAndroid Build Coastguard Worker
1214*d9f75844SAndroid Build Coastguard Worker if ((val >> 11) != 0)
1215*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "error-code bits not zero";
1216*d9f75844SAndroid Build Coastguard Worker
1217*d9f75844SAndroid Build Coastguard Worker class_ = ((val >> 8) & 0x7);
1218*d9f75844SAndroid Build Coastguard Worker number_ = (val & 0xff);
1219*d9f75844SAndroid Build Coastguard Worker
1220*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadString(&reason_, length() - 4))
1221*d9f75844SAndroid Build Coastguard Worker return false;
1222*d9f75844SAndroid Build Coastguard Worker
1223*d9f75844SAndroid Build Coastguard Worker ConsumePadding(buf);
1224*d9f75844SAndroid Build Coastguard Worker return true;
1225*d9f75844SAndroid Build Coastguard Worker }
1226*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1227*d9f75844SAndroid Build Coastguard Worker bool StunErrorCodeAttribute::Write(ByteBufferWriter* buf) const {
1228*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt32(class_ << 8 | number_);
1229*d9f75844SAndroid Build Coastguard Worker buf->WriteString(reason_);
1230*d9f75844SAndroid Build Coastguard Worker WritePadding(buf);
1231*d9f75844SAndroid Build Coastguard Worker return true;
1232*d9f75844SAndroid Build Coastguard Worker }
1233*d9f75844SAndroid Build Coastguard Worker
StunUInt16ListAttribute(uint16_t type,uint16_t length)1234*d9f75844SAndroid Build Coastguard Worker StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length)
1235*d9f75844SAndroid Build Coastguard Worker : StunAttribute(type, length) {
1236*d9f75844SAndroid Build Coastguard Worker attr_types_ = new std::vector<uint16_t>();
1237*d9f75844SAndroid Build Coastguard Worker }
1238*d9f75844SAndroid Build Coastguard Worker
~StunUInt16ListAttribute()1239*d9f75844SAndroid Build Coastguard Worker StunUInt16ListAttribute::~StunUInt16ListAttribute() {
1240*d9f75844SAndroid Build Coastguard Worker delete attr_types_;
1241*d9f75844SAndroid Build Coastguard Worker }
1242*d9f75844SAndroid Build Coastguard Worker
value_type() const1243*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType StunUInt16ListAttribute::value_type() const {
1244*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT16_LIST;
1245*d9f75844SAndroid Build Coastguard Worker }
1246*d9f75844SAndroid Build Coastguard Worker
Size() const1247*d9f75844SAndroid Build Coastguard Worker size_t StunUInt16ListAttribute::Size() const {
1248*d9f75844SAndroid Build Coastguard Worker return attr_types_->size();
1249*d9f75844SAndroid Build Coastguard Worker }
1250*d9f75844SAndroid Build Coastguard Worker
GetType(int index) const1251*d9f75844SAndroid Build Coastguard Worker uint16_t StunUInt16ListAttribute::GetType(int index) const {
1252*d9f75844SAndroid Build Coastguard Worker return (*attr_types_)[index];
1253*d9f75844SAndroid Build Coastguard Worker }
1254*d9f75844SAndroid Build Coastguard Worker
SetType(int index,uint16_t value)1255*d9f75844SAndroid Build Coastguard Worker void StunUInt16ListAttribute::SetType(int index, uint16_t value) {
1256*d9f75844SAndroid Build Coastguard Worker (*attr_types_)[index] = value;
1257*d9f75844SAndroid Build Coastguard Worker }
1258*d9f75844SAndroid Build Coastguard Worker
AddType(uint16_t value)1259*d9f75844SAndroid Build Coastguard Worker void StunUInt16ListAttribute::AddType(uint16_t value) {
1260*d9f75844SAndroid Build Coastguard Worker attr_types_->push_back(value);
1261*d9f75844SAndroid Build Coastguard Worker SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1262*d9f75844SAndroid Build Coastguard Worker }
1263*d9f75844SAndroid Build Coastguard Worker
AddTypeAtIndex(uint16_t index,uint16_t value)1264*d9f75844SAndroid Build Coastguard Worker void StunUInt16ListAttribute::AddTypeAtIndex(uint16_t index, uint16_t value) {
1265*d9f75844SAndroid Build Coastguard Worker if (attr_types_->size() < static_cast<size_t>(index + 1)) {
1266*d9f75844SAndroid Build Coastguard Worker attr_types_->resize(index + 1);
1267*d9f75844SAndroid Build Coastguard Worker }
1268*d9f75844SAndroid Build Coastguard Worker (*attr_types_)[index] = value;
1269*d9f75844SAndroid Build Coastguard Worker SetLength(static_cast<uint16_t>(attr_types_->size() * 2));
1270*d9f75844SAndroid Build Coastguard Worker }
1271*d9f75844SAndroid Build Coastguard Worker
Read(ByteBufferReader * buf)1272*d9f75844SAndroid Build Coastguard Worker bool StunUInt16ListAttribute::Read(ByteBufferReader* buf) {
1273*d9f75844SAndroid Build Coastguard Worker if (length() % 2) {
1274*d9f75844SAndroid Build Coastguard Worker return false;
1275*d9f75844SAndroid Build Coastguard Worker }
1276*d9f75844SAndroid Build Coastguard Worker
1277*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < length() / 2; i++) {
1278*d9f75844SAndroid Build Coastguard Worker uint16_t attr;
1279*d9f75844SAndroid Build Coastguard Worker if (!buf->ReadUInt16(&attr))
1280*d9f75844SAndroid Build Coastguard Worker return false;
1281*d9f75844SAndroid Build Coastguard Worker attr_types_->push_back(attr);
1282*d9f75844SAndroid Build Coastguard Worker }
1283*d9f75844SAndroid Build Coastguard Worker // Padding of these attributes is done in RFC 5389 style. This is
1284*d9f75844SAndroid Build Coastguard Worker // slightly different from RFC3489, but it shouldn't be important.
1285*d9f75844SAndroid Build Coastguard Worker // RFC3489 pads out to a 32 bit boundary by duplicating one of the
1286*d9f75844SAndroid Build Coastguard Worker // entries in the list (not necessarily the last one - it's unspecified).
1287*d9f75844SAndroid Build Coastguard Worker // RFC5389 pads on the end, and the bytes are always ignored.
1288*d9f75844SAndroid Build Coastguard Worker ConsumePadding(buf);
1289*d9f75844SAndroid Build Coastguard Worker return true;
1290*d9f75844SAndroid Build Coastguard Worker }
1291*d9f75844SAndroid Build Coastguard Worker
Write(ByteBufferWriter * buf) const1292*d9f75844SAndroid Build Coastguard Worker bool StunUInt16ListAttribute::Write(ByteBufferWriter* buf) const {
1293*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < attr_types_->size(); ++i) {
1294*d9f75844SAndroid Build Coastguard Worker buf->WriteUInt16((*attr_types_)[i]);
1295*d9f75844SAndroid Build Coastguard Worker }
1296*d9f75844SAndroid Build Coastguard Worker WritePadding(buf);
1297*d9f75844SAndroid Build Coastguard Worker return true;
1298*d9f75844SAndroid Build Coastguard Worker }
1299*d9f75844SAndroid Build Coastguard Worker
StunMethodToString(int msg_type)1300*d9f75844SAndroid Build Coastguard Worker std::string StunMethodToString(int msg_type) {
1301*d9f75844SAndroid Build Coastguard Worker switch (msg_type) {
1302*d9f75844SAndroid Build Coastguard Worker case STUN_BINDING_REQUEST:
1303*d9f75844SAndroid Build Coastguard Worker return "STUN BINDING request";
1304*d9f75844SAndroid Build Coastguard Worker case STUN_BINDING_INDICATION:
1305*d9f75844SAndroid Build Coastguard Worker return "STUN BINDING indication";
1306*d9f75844SAndroid Build Coastguard Worker case STUN_BINDING_RESPONSE:
1307*d9f75844SAndroid Build Coastguard Worker return "STUN BINDING response";
1308*d9f75844SAndroid Build Coastguard Worker case STUN_BINDING_ERROR_RESPONSE:
1309*d9f75844SAndroid Build Coastguard Worker return "STUN BINDING error response";
1310*d9f75844SAndroid Build Coastguard Worker case GOOG_PING_REQUEST:
1311*d9f75844SAndroid Build Coastguard Worker return "GOOG PING request";
1312*d9f75844SAndroid Build Coastguard Worker case GOOG_PING_RESPONSE:
1313*d9f75844SAndroid Build Coastguard Worker return "GOOG PING response";
1314*d9f75844SAndroid Build Coastguard Worker case GOOG_PING_ERROR_RESPONSE:
1315*d9f75844SAndroid Build Coastguard Worker return "GOOG PING error response";
1316*d9f75844SAndroid Build Coastguard Worker case STUN_ALLOCATE_REQUEST:
1317*d9f75844SAndroid Build Coastguard Worker return "TURN ALLOCATE request";
1318*d9f75844SAndroid Build Coastguard Worker case STUN_ALLOCATE_RESPONSE:
1319*d9f75844SAndroid Build Coastguard Worker return "TURN ALLOCATE response";
1320*d9f75844SAndroid Build Coastguard Worker case STUN_ALLOCATE_ERROR_RESPONSE:
1321*d9f75844SAndroid Build Coastguard Worker return "TURN ALLOCATE error response";
1322*d9f75844SAndroid Build Coastguard Worker case TURN_REFRESH_REQUEST:
1323*d9f75844SAndroid Build Coastguard Worker return "TURN REFRESH request";
1324*d9f75844SAndroid Build Coastguard Worker case TURN_REFRESH_RESPONSE:
1325*d9f75844SAndroid Build Coastguard Worker return "TURN REFRESH response";
1326*d9f75844SAndroid Build Coastguard Worker case TURN_REFRESH_ERROR_RESPONSE:
1327*d9f75844SAndroid Build Coastguard Worker return "TURN REFRESH error response";
1328*d9f75844SAndroid Build Coastguard Worker case TURN_SEND_INDICATION:
1329*d9f75844SAndroid Build Coastguard Worker return "TURN SEND INDICATION";
1330*d9f75844SAndroid Build Coastguard Worker case TURN_DATA_INDICATION:
1331*d9f75844SAndroid Build Coastguard Worker return "TURN DATA INDICATION";
1332*d9f75844SAndroid Build Coastguard Worker case TURN_CREATE_PERMISSION_REQUEST:
1333*d9f75844SAndroid Build Coastguard Worker return "TURN CREATE PERMISSION request";
1334*d9f75844SAndroid Build Coastguard Worker case TURN_CREATE_PERMISSION_RESPONSE:
1335*d9f75844SAndroid Build Coastguard Worker return "TURN CREATE PERMISSION response";
1336*d9f75844SAndroid Build Coastguard Worker case TURN_CREATE_PERMISSION_ERROR_RESPONSE:
1337*d9f75844SAndroid Build Coastguard Worker return "TURN CREATE PERMISSION error response";
1338*d9f75844SAndroid Build Coastguard Worker case TURN_CHANNEL_BIND_REQUEST:
1339*d9f75844SAndroid Build Coastguard Worker return "TURN CHANNEL BIND request";
1340*d9f75844SAndroid Build Coastguard Worker case TURN_CHANNEL_BIND_RESPONSE:
1341*d9f75844SAndroid Build Coastguard Worker return "TURN CHANNEL BIND response";
1342*d9f75844SAndroid Build Coastguard Worker case TURN_CHANNEL_BIND_ERROR_RESPONSE:
1343*d9f75844SAndroid Build Coastguard Worker return "TURN CHANNEL BIND error response";
1344*d9f75844SAndroid Build Coastguard Worker default:
1345*d9f75844SAndroid Build Coastguard Worker return "UNKNOWN<" + std::to_string(msg_type) + ">";
1346*d9f75844SAndroid Build Coastguard Worker }
1347*d9f75844SAndroid Build Coastguard Worker }
1348*d9f75844SAndroid Build Coastguard Worker
GetStunSuccessResponseType(int req_type)1349*d9f75844SAndroid Build Coastguard Worker int GetStunSuccessResponseType(int req_type) {
1350*d9f75844SAndroid Build Coastguard Worker return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
1351*d9f75844SAndroid Build Coastguard Worker }
1352*d9f75844SAndroid Build Coastguard Worker
GetStunErrorResponseType(int req_type)1353*d9f75844SAndroid Build Coastguard Worker int GetStunErrorResponseType(int req_type) {
1354*d9f75844SAndroid Build Coastguard Worker return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
1355*d9f75844SAndroid Build Coastguard Worker }
1356*d9f75844SAndroid Build Coastguard Worker
IsStunRequestType(int msg_type)1357*d9f75844SAndroid Build Coastguard Worker bool IsStunRequestType(int msg_type) {
1358*d9f75844SAndroid Build Coastguard Worker return ((msg_type & kStunTypeMask) == 0x000);
1359*d9f75844SAndroid Build Coastguard Worker }
1360*d9f75844SAndroid Build Coastguard Worker
IsStunIndicationType(int msg_type)1361*d9f75844SAndroid Build Coastguard Worker bool IsStunIndicationType(int msg_type) {
1362*d9f75844SAndroid Build Coastguard Worker return ((msg_type & kStunTypeMask) == 0x010);
1363*d9f75844SAndroid Build Coastguard Worker }
1364*d9f75844SAndroid Build Coastguard Worker
IsStunSuccessResponseType(int msg_type)1365*d9f75844SAndroid Build Coastguard Worker bool IsStunSuccessResponseType(int msg_type) {
1366*d9f75844SAndroid Build Coastguard Worker return ((msg_type & kStunTypeMask) == 0x100);
1367*d9f75844SAndroid Build Coastguard Worker }
1368*d9f75844SAndroid Build Coastguard Worker
IsStunErrorResponseType(int msg_type)1369*d9f75844SAndroid Build Coastguard Worker bool IsStunErrorResponseType(int msg_type) {
1370*d9f75844SAndroid Build Coastguard Worker return ((msg_type & kStunTypeMask) == 0x110);
1371*d9f75844SAndroid Build Coastguard Worker }
1372*d9f75844SAndroid Build Coastguard Worker
ComputeStunCredentialHash(const std::string & username,const std::string & realm,const std::string & password,std::string * hash)1373*d9f75844SAndroid Build Coastguard Worker bool ComputeStunCredentialHash(const std::string& username,
1374*d9f75844SAndroid Build Coastguard Worker const std::string& realm,
1375*d9f75844SAndroid Build Coastguard Worker const std::string& password,
1376*d9f75844SAndroid Build Coastguard Worker std::string* hash) {
1377*d9f75844SAndroid Build Coastguard Worker // http://tools.ietf.org/html/rfc5389#section-15.4
1378*d9f75844SAndroid Build Coastguard Worker // long-term credentials will be calculated using the key and key is
1379*d9f75844SAndroid Build Coastguard Worker // key = MD5(username ":" realm ":" SASLprep(password))
1380*d9f75844SAndroid Build Coastguard Worker std::string input = username;
1381*d9f75844SAndroid Build Coastguard Worker input += ':';
1382*d9f75844SAndroid Build Coastguard Worker input += realm;
1383*d9f75844SAndroid Build Coastguard Worker input += ':';
1384*d9f75844SAndroid Build Coastguard Worker input += password;
1385*d9f75844SAndroid Build Coastguard Worker
1386*d9f75844SAndroid Build Coastguard Worker char digest[rtc::MessageDigest::kMaxSize];
1387*d9f75844SAndroid Build Coastguard Worker size_t size = rtc::ComputeDigest(rtc::DIGEST_MD5, input.c_str(), input.size(),
1388*d9f75844SAndroid Build Coastguard Worker digest, sizeof(digest));
1389*d9f75844SAndroid Build Coastguard Worker if (size == 0) {
1390*d9f75844SAndroid Build Coastguard Worker return false;
1391*d9f75844SAndroid Build Coastguard Worker }
1392*d9f75844SAndroid Build Coastguard Worker
1393*d9f75844SAndroid Build Coastguard Worker *hash = std::string(digest, size);
1394*d9f75844SAndroid Build Coastguard Worker return true;
1395*d9f75844SAndroid Build Coastguard Worker }
1396*d9f75844SAndroid Build Coastguard Worker
CopyStunAttribute(const StunAttribute & attribute,rtc::ByteBufferWriter * tmp_buffer_ptr)1397*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAttribute> CopyStunAttribute(
1398*d9f75844SAndroid Build Coastguard Worker const StunAttribute& attribute,
1399*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter* tmp_buffer_ptr) {
1400*d9f75844SAndroid Build Coastguard Worker ByteBufferWriter tmpBuffer;
1401*d9f75844SAndroid Build Coastguard Worker if (tmp_buffer_ptr == nullptr) {
1402*d9f75844SAndroid Build Coastguard Worker tmp_buffer_ptr = &tmpBuffer;
1403*d9f75844SAndroid Build Coastguard Worker }
1404*d9f75844SAndroid Build Coastguard Worker
1405*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunAttribute> copy(StunAttribute::Create(
1406*d9f75844SAndroid Build Coastguard Worker attribute.value_type(), attribute.type(),
1407*d9f75844SAndroid Build Coastguard Worker static_cast<uint16_t>(attribute.length()), nullptr));
1408*d9f75844SAndroid Build Coastguard Worker
1409*d9f75844SAndroid Build Coastguard Worker if (!copy) {
1410*d9f75844SAndroid Build Coastguard Worker return nullptr;
1411*d9f75844SAndroid Build Coastguard Worker }
1412*d9f75844SAndroid Build Coastguard Worker tmp_buffer_ptr->Clear();
1413*d9f75844SAndroid Build Coastguard Worker if (!attribute.Write(tmp_buffer_ptr)) {
1414*d9f75844SAndroid Build Coastguard Worker return nullptr;
1415*d9f75844SAndroid Build Coastguard Worker }
1416*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferReader reader(*tmp_buffer_ptr);
1417*d9f75844SAndroid Build Coastguard Worker if (!copy->Read(&reader)) {
1418*d9f75844SAndroid Build Coastguard Worker return nullptr;
1419*d9f75844SAndroid Build Coastguard Worker }
1420*d9f75844SAndroid Build Coastguard Worker
1421*d9f75844SAndroid Build Coastguard Worker return copy;
1422*d9f75844SAndroid Build Coastguard Worker }
1423*d9f75844SAndroid Build Coastguard Worker
GetAttributeValueType(int type) const1424*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType RelayMessage::GetAttributeValueType(int type) const {
1425*d9f75844SAndroid Build Coastguard Worker switch (type) {
1426*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_LIFETIME:
1427*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1428*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_MAGIC_COOKIE:
1429*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1430*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_BANDWIDTH:
1431*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1432*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_DESTINATION_ADDRESS:
1433*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ADDRESS;
1434*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_SOURCE_ADDRESS2:
1435*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_ADDRESS;
1436*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_DATA:
1437*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1438*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_OPTIONS:
1439*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1440*d9f75844SAndroid Build Coastguard Worker default:
1441*d9f75844SAndroid Build Coastguard Worker return StunMessage::GetAttributeValueType(type);
1442*d9f75844SAndroid Build Coastguard Worker }
1443*d9f75844SAndroid Build Coastguard Worker }
1444*d9f75844SAndroid Build Coastguard Worker
CreateNew() const1445*d9f75844SAndroid Build Coastguard Worker StunMessage* RelayMessage::CreateNew() const {
1446*d9f75844SAndroid Build Coastguard Worker return new RelayMessage();
1447*d9f75844SAndroid Build Coastguard Worker }
1448*d9f75844SAndroid Build Coastguard Worker
GetAttributeValueType(int type) const1449*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType TurnMessage::GetAttributeValueType(int type) const {
1450*d9f75844SAndroid Build Coastguard Worker switch (type) {
1451*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_CHANNEL_NUMBER:
1452*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1453*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_TURN_LIFETIME:
1454*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1455*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_XOR_PEER_ADDRESS:
1456*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_XOR_ADDRESS;
1457*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_DATA:
1458*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1459*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_XOR_RELAYED_ADDRESS:
1460*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_XOR_ADDRESS;
1461*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_EVEN_PORT:
1462*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1463*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_REQUESTED_TRANSPORT:
1464*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1465*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_DONT_FRAGMENT:
1466*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1467*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_RESERVATION_TOKEN:
1468*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1469*d9f75844SAndroid Build Coastguard Worker default:
1470*d9f75844SAndroid Build Coastguard Worker return StunMessage::GetAttributeValueType(type);
1471*d9f75844SAndroid Build Coastguard Worker }
1472*d9f75844SAndroid Build Coastguard Worker }
1473*d9f75844SAndroid Build Coastguard Worker
CreateNew() const1474*d9f75844SAndroid Build Coastguard Worker StunMessage* TurnMessage::CreateNew() const {
1475*d9f75844SAndroid Build Coastguard Worker return new TurnMessage();
1476*d9f75844SAndroid Build Coastguard Worker }
1477*d9f75844SAndroid Build Coastguard Worker
GetAttributeValueType(int type) const1478*d9f75844SAndroid Build Coastguard Worker StunAttributeValueType IceMessage::GetAttributeValueType(int type) const {
1479*d9f75844SAndroid Build Coastguard Worker switch (type) {
1480*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_PRIORITY:
1481*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_GOOG_NETWORK_INFO:
1482*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_NOMINATION:
1483*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT32;
1484*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_USE_CANDIDATE:
1485*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_BYTE_STRING;
1486*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_ICE_CONTROLLED:
1487*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT64;
1488*d9f75844SAndroid Build Coastguard Worker case STUN_ATTR_ICE_CONTROLLING:
1489*d9f75844SAndroid Build Coastguard Worker return STUN_VALUE_UINT64;
1490*d9f75844SAndroid Build Coastguard Worker default:
1491*d9f75844SAndroid Build Coastguard Worker return StunMessage::GetAttributeValueType(type);
1492*d9f75844SAndroid Build Coastguard Worker }
1493*d9f75844SAndroid Build Coastguard Worker }
1494*d9f75844SAndroid Build Coastguard Worker
CreateNew() const1495*d9f75844SAndroid Build Coastguard Worker StunMessage* IceMessage::CreateNew() const {
1496*d9f75844SAndroid Build Coastguard Worker return new IceMessage();
1497*d9f75844SAndroid Build Coastguard Worker }
1498*d9f75844SAndroid Build Coastguard Worker
Clone() const1499*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunMessage> StunMessage::Clone() const {
1500*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunMessage> copy(CreateNew());
1501*d9f75844SAndroid Build Coastguard Worker if (!copy) {
1502*d9f75844SAndroid Build Coastguard Worker return nullptr;
1503*d9f75844SAndroid Build Coastguard Worker }
1504*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter buf;
1505*d9f75844SAndroid Build Coastguard Worker if (!Write(&buf)) {
1506*d9f75844SAndroid Build Coastguard Worker return nullptr;
1507*d9f75844SAndroid Build Coastguard Worker }
1508*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferReader reader(buf);
1509*d9f75844SAndroid Build Coastguard Worker if (!copy->Read(&reader)) {
1510*d9f75844SAndroid Build Coastguard Worker return nullptr;
1511*d9f75844SAndroid Build Coastguard Worker }
1512*d9f75844SAndroid Build Coastguard Worker return copy;
1513*d9f75844SAndroid Build Coastguard Worker }
1514*d9f75844SAndroid Build Coastguard Worker
1515*d9f75844SAndroid Build Coastguard Worker } // namespace cricket
1516