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