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 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>(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 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 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,
191 static_cast<uint16>(new_adjusted_len));
192 }
193
194 char hmac[kStunMessageIntegritySize];
195 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1,
196 password.c_str(), password.size(),
197 temp_data.get(), mi_pos,
198 hmac, sizeof(hmac));
199 ASSERT(ret == sizeof(hmac));
200 if (ret != sizeof(hmac))
201 return false;
202
203 // Comparing the calculated HMAC with the one present in the message.
204 return memcmp(data + current_pos + kStunAttributeHeaderSize,
205 hmac,
206 sizeof(hmac)) == 0;
207 }
208
AddMessageIntegrity(const std::string & password)209 bool StunMessage::AddMessageIntegrity(const std::string& password) {
210 return AddMessageIntegrity(password.c_str(), password.size());
211 }
212
AddMessageIntegrity(const char * key,size_t keylen)213 bool StunMessage::AddMessageIntegrity(const char* key,
214 size_t keylen) {
215 // Add the attribute with a dummy value. Since this is a known attribute, it
216 // can't fail.
217 StunByteStringAttribute* msg_integrity_attr =
218 new StunByteStringAttribute(STUN_ATTR_MESSAGE_INTEGRITY,
219 std::string(kStunMessageIntegritySize, '0'));
220 VERIFY(AddAttribute(msg_integrity_attr));
221
222 // Calculate the HMAC for the message.
223 rtc::ByteBuffer buf;
224 if (!Write(&buf))
225 return false;
226
227 int msg_len_for_hmac = static_cast<int>(
228 buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
229 char hmac[kStunMessageIntegritySize];
230 size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1,
231 key, keylen,
232 buf.Data(), msg_len_for_hmac,
233 hmac, sizeof(hmac));
234 ASSERT(ret == sizeof(hmac));
235 if (ret != sizeof(hmac)) {
236 LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity "
237 << "has dummy value.";
238 return false;
239 }
240
241 // Insert correct HMAC into the attribute.
242 msg_integrity_attr->CopyBytes(hmac, sizeof(hmac));
243 return true;
244 }
245
246 // Verifies a message is in fact a STUN message, by performing the checks
247 // outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed
248 // in section 15.5.
ValidateFingerprint(const char * data,size_t size)249 bool StunMessage::ValidateFingerprint(const char* data, size_t size) {
250 // Check the message length.
251 size_t fingerprint_attr_size =
252 kStunAttributeHeaderSize + StunUInt32Attribute::SIZE;
253 if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size)
254 return false;
255
256 // Skip the rest if the magic cookie isn't present.
257 const char* magic_cookie =
258 data + kStunTransactionIdOffset - kStunMagicCookieLength;
259 if (rtc::GetBE32(magic_cookie) != kStunMagicCookie)
260 return false;
261
262 // Check the fingerprint type and length.
263 const char* fingerprint_attr_data = data + size - fingerprint_attr_size;
264 if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT ||
265 rtc::GetBE16(fingerprint_attr_data + sizeof(uint16)) !=
266 StunUInt32Attribute::SIZE)
267 return false;
268
269 // Check the fingerprint value.
270 uint32 fingerprint =
271 rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize);
272 return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) ==
273 rtc::ComputeCrc32(data, size - fingerprint_attr_size));
274 }
275
AddFingerprint()276 bool StunMessage::AddFingerprint() {
277 // Add the attribute with a dummy value. Since this is a known attribute,
278 // it can't fail.
279 StunUInt32Attribute* fingerprint_attr =
280 new StunUInt32Attribute(STUN_ATTR_FINGERPRINT, 0);
281 VERIFY(AddAttribute(fingerprint_attr));
282
283 // Calculate the CRC-32 for the message and insert it.
284 rtc::ByteBuffer buf;
285 if (!Write(&buf))
286 return false;
287
288 int msg_len_for_crc32 = static_cast<int>(
289 buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length());
290 uint32 c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32);
291
292 // Insert the correct CRC-32, XORed with a constant, into the attribute.
293 fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE);
294 return true;
295 }
296
Read(ByteBuffer * buf)297 bool StunMessage::Read(ByteBuffer* buf) {
298 if (!buf->ReadUInt16(&type_))
299 return false;
300
301 if (type_ & 0x8000) {
302 // RTP and RTCP set the MSB of first byte, since first two bits are version,
303 // and version is always 2 (10). If set, this is not a STUN packet.
304 return false;
305 }
306
307 if (!buf->ReadUInt16(&length_))
308 return false;
309
310 std::string magic_cookie;
311 if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength))
312 return false;
313
314 std::string transaction_id;
315 if (!buf->ReadString(&transaction_id, kStunTransactionIdLength))
316 return false;
317
318 uint32 magic_cookie_int =
319 *reinterpret_cast<const uint32*>(magic_cookie.data());
320 if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
321 // If magic cookie is invalid it means that the peer implements
322 // RFC3489 instead of RFC5389.
323 transaction_id.insert(0, magic_cookie);
324 }
325 ASSERT(IsValidTransactionId(transaction_id));
326 transaction_id_ = transaction_id;
327
328 if (length_ != buf->Length())
329 return false;
330
331 attrs_->resize(0);
332
333 size_t rest = buf->Length() - length_;
334 while (buf->Length() > rest) {
335 uint16 attr_type, attr_length;
336 if (!buf->ReadUInt16(&attr_type))
337 return false;
338 if (!buf->ReadUInt16(&attr_length))
339 return false;
340
341 StunAttribute* attr = CreateAttribute(attr_type, attr_length);
342 if (!attr) {
343 // Skip any unknown or malformed attributes.
344 if ((attr_length % 4) != 0) {
345 attr_length += (4 - (attr_length % 4));
346 }
347 if (!buf->Consume(attr_length))
348 return false;
349 } else {
350 if (!attr->Read(buf))
351 return false;
352 attrs_->push_back(attr);
353 }
354 }
355
356 ASSERT(buf->Length() == rest);
357 return true;
358 }
359
Write(ByteBuffer * buf) const360 bool StunMessage::Write(ByteBuffer* buf) const {
361 buf->WriteUInt16(type_);
362 buf->WriteUInt16(length_);
363 if (!IsLegacy())
364 buf->WriteUInt32(kStunMagicCookie);
365 buf->WriteString(transaction_id_);
366
367 for (size_t i = 0; i < attrs_->size(); ++i) {
368 buf->WriteUInt16((*attrs_)[i]->type());
369 buf->WriteUInt16(static_cast<uint16>((*attrs_)[i]->length()));
370 if (!(*attrs_)[i]->Write(buf))
371 return false;
372 }
373
374 return true;
375 }
376
GetAttributeValueType(int type) const377 StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
378 switch (type) {
379 case STUN_ATTR_MAPPED_ADDRESS: return STUN_VALUE_ADDRESS;
380 case STUN_ATTR_USERNAME: return STUN_VALUE_BYTE_STRING;
381 case STUN_ATTR_MESSAGE_INTEGRITY: return STUN_VALUE_BYTE_STRING;
382 case STUN_ATTR_ERROR_CODE: return STUN_VALUE_ERROR_CODE;
383 case STUN_ATTR_UNKNOWN_ATTRIBUTES: return STUN_VALUE_UINT16_LIST;
384 case STUN_ATTR_REALM: return STUN_VALUE_BYTE_STRING;
385 case STUN_ATTR_NONCE: return STUN_VALUE_BYTE_STRING;
386 case STUN_ATTR_XOR_MAPPED_ADDRESS: return STUN_VALUE_XOR_ADDRESS;
387 case STUN_ATTR_SOFTWARE: return STUN_VALUE_BYTE_STRING;
388 case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_ADDRESS;
389 case STUN_ATTR_FINGERPRINT: return STUN_VALUE_UINT32;
390 case STUN_ATTR_ORIGIN: return STUN_VALUE_BYTE_STRING;
391 case STUN_ATTR_RETRANSMIT_COUNT: return STUN_VALUE_UINT32;
392 default: return STUN_VALUE_UNKNOWN;
393 }
394 }
395
CreateAttribute(int type,size_t length)396 StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ {
397 StunAttributeValueType value_type = GetAttributeValueType(type);
398 return StunAttribute::Create(value_type, type,
399 static_cast<uint16>(length), this);
400 }
401
GetAttribute(int type) const402 const StunAttribute* StunMessage::GetAttribute(int type) const {
403 for (size_t i = 0; i < attrs_->size(); ++i) {
404 if ((*attrs_)[i]->type() == type)
405 return (*attrs_)[i];
406 }
407 return NULL;
408 }
409
IsValidTransactionId(const std::string & transaction_id)410 bool StunMessage::IsValidTransactionId(const std::string& transaction_id) {
411 return transaction_id.size() == kStunTransactionIdLength ||
412 transaction_id.size() == kStunLegacyTransactionIdLength;
413 }
414
415 // StunAttribute
416
StunAttribute(uint16 type,uint16 length)417 StunAttribute::StunAttribute(uint16 type, uint16 length)
418 : type_(type), length_(length) {
419 }
420
ConsumePadding(rtc::ByteBuffer * buf) const421 void StunAttribute::ConsumePadding(rtc::ByteBuffer* buf) const {
422 int remainder = length_ % 4;
423 if (remainder > 0) {
424 buf->Consume(4 - remainder);
425 }
426 }
427
WritePadding(rtc::ByteBuffer * buf) const428 void StunAttribute::WritePadding(rtc::ByteBuffer* buf) const {
429 int remainder = length_ % 4;
430 if (remainder > 0) {
431 char zeroes[4] = {0};
432 buf->WriteBytes(zeroes, 4 - remainder);
433 }
434 }
435
Create(StunAttributeValueType value_type,uint16 type,uint16 length,StunMessage * owner)436 StunAttribute* StunAttribute::Create(StunAttributeValueType value_type,
437 uint16 type, uint16 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 type)459 StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
460 return new StunAddressAttribute(type, 0);
461 }
462
CreateXorAddress(uint16 type)463 StunXorAddressAttribute* StunAttribute::CreateXorAddress(uint16 type) {
464 return new StunXorAddressAttribute(type, 0, NULL);
465 }
466
CreateUInt64(uint16 type)467 StunUInt64Attribute* StunAttribute::CreateUInt64(uint16 type) {
468 return new StunUInt64Attribute(type);
469 }
470
CreateUInt32(uint16 type)471 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
472 return new StunUInt32Attribute(type);
473 }
474
CreateByteString(uint16 type)475 StunByteStringAttribute* StunAttribute::CreateByteString(uint16 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 type,const rtc::SocketAddress & addr)488 StunAddressAttribute::StunAddressAttribute(uint16 type,
489 const rtc::SocketAddress& addr)
490 : StunAttribute(type, 0) {
491 SetAddress(addr);
492 }
493
StunAddressAttribute(uint16 type,uint16 length)494 StunAddressAttribute::StunAddressAttribute(uint16 type, uint16 length)
495 : StunAttribute(type, length) {
496 }
497
Read(ByteBuffer * buf)498 bool StunAddressAttribute::Read(ByteBuffer* buf) {
499 uint8 dummy;
500 if (!buf->ReadUInt8(&dummy))
501 return false;
502
503 uint8 stun_family;
504 if (!buf->ReadUInt8(&stun_family)) {
505 return false;
506 }
507 uint16 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 type,const rtc::SocketAddress & addr)560 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type,
561 const rtc::SocketAddress& addr)
562 : StunAddressAttribute(type, addr), owner_(NULL) {
563 }
564
StunXorAddressAttribute(uint16 type,uint16 length,StunMessage * owner)565 StunXorAddressAttribute::StunXorAddressAttribute(uint16 type,
566 uint16 length,
567 StunMessage* owner)
568 : StunAddressAttribute(type, length), owner_(owner) {}
569
GetXoredIP() const570 rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const {
571 if (owner_) {
572 rtc::IPAddress ip = ipaddr();
573 switch (ip.family()) {
574 case AF_INET: {
575 in_addr v4addr = ip.ipv4_address();
576 v4addr.s_addr =
577 (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie));
578 return rtc::IPAddress(v4addr);
579 }
580 case AF_INET6: {
581 in6_addr v6addr = ip.ipv6_address();
582 const std::string& transaction_id = owner_->transaction_id();
583 if (transaction_id.length() == kStunTransactionIdLength) {
584 uint32 transactionid_as_ints[3];
585 memcpy(&transactionid_as_ints[0], transaction_id.c_str(),
586 transaction_id.length());
587 uint32* ip_as_ints = reinterpret_cast<uint32*>(&v6addr.s6_addr);
588 // Transaction ID is in network byte order, but magic cookie
589 // is stored in host byte order.
590 ip_as_ints[0] =
591 (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie));
592 ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]);
593 ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]);
594 ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]);
595 return rtc::IPAddress(v6addr);
596 }
597 break;
598 }
599 }
600 }
601 // Invalid ip family or transaction ID, or missing owner.
602 // Return an AF_UNSPEC address.
603 return rtc::IPAddress();
604 }
605
Read(ByteBuffer * buf)606 bool StunXorAddressAttribute::Read(ByteBuffer* buf) {
607 if (!StunAddressAttribute::Read(buf))
608 return false;
609 uint16 xoredport = port() ^ (kStunMagicCookie >> 16);
610 rtc::IPAddress xored_ip = GetXoredIP();
611 SetAddress(rtc::SocketAddress(xored_ip, xoredport));
612 return true;
613 }
614
Write(ByteBuffer * buf) const615 bool StunXorAddressAttribute::Write(ByteBuffer* buf) const {
616 StunAddressFamily address_family = family();
617 if (address_family == STUN_ADDRESS_UNDEF) {
618 LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family.";
619 return false;
620 }
621 rtc::IPAddress xored_ip = GetXoredIP();
622 if (xored_ip.family() == AF_UNSPEC) {
623 return false;
624 }
625 buf->WriteUInt8(0);
626 buf->WriteUInt8(family());
627 buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16));
628 switch (xored_ip.family()) {
629 case AF_INET: {
630 in_addr v4addr = xored_ip.ipv4_address();
631 buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr));
632 break;
633 }
634 case AF_INET6: {
635 in6_addr v6addr = xored_ip.ipv6_address();
636 buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr));
637 break;
638 }
639 }
640 return true;
641 }
642
StunUInt32Attribute(uint16 type,uint32 value)643 StunUInt32Attribute::StunUInt32Attribute(uint16 type, uint32 value)
644 : StunAttribute(type, SIZE), bits_(value) {
645 }
646
StunUInt32Attribute(uint16 type)647 StunUInt32Attribute::StunUInt32Attribute(uint16 type)
648 : StunAttribute(type, SIZE), bits_(0) {
649 }
650
GetBit(size_t index) const651 bool StunUInt32Attribute::GetBit(size_t index) const {
652 ASSERT(index < 32);
653 return static_cast<bool>((bits_ >> index) & 0x1);
654 }
655
SetBit(size_t index,bool value)656 void StunUInt32Attribute::SetBit(size_t index, bool value) {
657 ASSERT(index < 32);
658 bits_ &= ~(1 << index);
659 bits_ |= value ? (1 << index) : 0;
660 }
661
Read(ByteBuffer * buf)662 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
663 if (length() != SIZE || !buf->ReadUInt32(&bits_))
664 return false;
665 return true;
666 }
667
Write(ByteBuffer * buf) const668 bool StunUInt32Attribute::Write(ByteBuffer* buf) const {
669 buf->WriteUInt32(bits_);
670 return true;
671 }
672
StunUInt64Attribute(uint16 type,uint64 value)673 StunUInt64Attribute::StunUInt64Attribute(uint16 type, uint64 value)
674 : StunAttribute(type, SIZE), bits_(value) {
675 }
676
StunUInt64Attribute(uint16 type)677 StunUInt64Attribute::StunUInt64Attribute(uint16 type)
678 : StunAttribute(type, SIZE), bits_(0) {
679 }
680
Read(ByteBuffer * buf)681 bool StunUInt64Attribute::Read(ByteBuffer* buf) {
682 if (length() != SIZE || !buf->ReadUInt64(&bits_))
683 return false;
684 return true;
685 }
686
Write(ByteBuffer * buf) const687 bool StunUInt64Attribute::Write(ByteBuffer* buf) const {
688 buf->WriteUInt64(bits_);
689 return true;
690 }
691
StunByteStringAttribute(uint16 type)692 StunByteStringAttribute::StunByteStringAttribute(uint16 type)
693 : StunAttribute(type, 0), bytes_(NULL) {
694 }
695
StunByteStringAttribute(uint16 type,const std::string & str)696 StunByteStringAttribute::StunByteStringAttribute(uint16 type,
697 const std::string& str)
698 : StunAttribute(type, 0), bytes_(NULL) {
699 CopyBytes(str.c_str(), str.size());
700 }
701
StunByteStringAttribute(uint16 type,const void * bytes,size_t length)702 StunByteStringAttribute::StunByteStringAttribute(uint16 type,
703 const void* bytes,
704 size_t length)
705 : StunAttribute(type, 0), bytes_(NULL) {
706 CopyBytes(bytes, length);
707 }
708
StunByteStringAttribute(uint16 type,uint16 length)709 StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
710 : StunAttribute(type, length), bytes_(NULL) {
711 }
712
~StunByteStringAttribute()713 StunByteStringAttribute::~StunByteStringAttribute() {
714 delete [] bytes_;
715 }
716
CopyBytes(const char * bytes)717 void StunByteStringAttribute::CopyBytes(const char* bytes) {
718 CopyBytes(bytes, strlen(bytes));
719 }
720
CopyBytes(const void * bytes,size_t length)721 void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {
722 char* new_bytes = new char[length];
723 memcpy(new_bytes, bytes, length);
724 SetBytes(new_bytes, length);
725 }
726
GetByte(size_t index) const727 uint8 StunByteStringAttribute::GetByte(size_t index) const {
728 ASSERT(bytes_ != NULL);
729 ASSERT(index < length());
730 return static_cast<uint8>(bytes_[index]);
731 }
732
SetByte(size_t index,uint8 value)733 void StunByteStringAttribute::SetByte(size_t index, uint8 value) {
734 ASSERT(bytes_ != NULL);
735 ASSERT(index < length());
736 bytes_[index] = value;
737 }
738
Read(ByteBuffer * buf)739 bool StunByteStringAttribute::Read(ByteBuffer* buf) {
740 bytes_ = new char[length()];
741 if (!buf->ReadBytes(bytes_, length())) {
742 return false;
743 }
744
745 ConsumePadding(buf);
746 return true;
747 }
748
Write(ByteBuffer * buf) const749 bool StunByteStringAttribute::Write(ByteBuffer* buf) const {
750 buf->WriteBytes(bytes_, length());
751 WritePadding(buf);
752 return true;
753 }
754
SetBytes(char * bytes,size_t length)755 void StunByteStringAttribute::SetBytes(char* bytes, size_t length) {
756 delete [] bytes_;
757 bytes_ = bytes;
758 SetLength(static_cast<uint16>(length));
759 }
760
StunErrorCodeAttribute(uint16 type,int code,const std::string & reason)761 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, int code,
762 const std::string& reason)
763 : StunAttribute(type, 0) {
764 SetCode(code);
765 SetReason(reason);
766 }
767
StunErrorCodeAttribute(uint16 type,uint16 length)768 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
769 : StunAttribute(type, length), class_(0), number_(0) {
770 }
771
~StunErrorCodeAttribute()772 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
773 }
774
code() const775 int StunErrorCodeAttribute::code() const {
776 return class_ * 100 + number_;
777 }
778
SetCode(int code)779 void StunErrorCodeAttribute::SetCode(int code) {
780 class_ = static_cast<uint8>(code / 100);
781 number_ = static_cast<uint8>(code % 100);
782 }
783
SetReason(const std::string & reason)784 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
785 SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
786 reason_ = reason;
787 }
788
Read(ByteBuffer * buf)789 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
790 uint32 val;
791 if (length() < MIN_SIZE || !buf->ReadUInt32(&val))
792 return false;
793
794 if ((val >> 11) != 0)
795 LOG(LS_ERROR) << "error-code bits not zero";
796
797 class_ = ((val >> 8) & 0x7);
798 number_ = (val & 0xff);
799
800 if (!buf->ReadString(&reason_, length() - 4))
801 return false;
802
803 ConsumePadding(buf);
804 return true;
805 }
806
Write(ByteBuffer * buf) const807 bool StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
808 buf->WriteUInt32(class_ << 8 | number_);
809 buf->WriteString(reason_);
810 WritePadding(buf);
811 return true;
812 }
813
StunUInt16ListAttribute(uint16 type,uint16 length)814 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
815 : StunAttribute(type, length) {
816 attr_types_ = new std::vector<uint16>();
817 }
818
~StunUInt16ListAttribute()819 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
820 delete attr_types_;
821 }
822
Size() const823 size_t StunUInt16ListAttribute::Size() const {
824 return attr_types_->size();
825 }
826
GetType(int index) const827 uint16 StunUInt16ListAttribute::GetType(int index) const {
828 return (*attr_types_)[index];
829 }
830
SetType(int index,uint16 value)831 void StunUInt16ListAttribute::SetType(int index, uint16 value) {
832 (*attr_types_)[index] = value;
833 }
834
AddType(uint16 value)835 void StunUInt16ListAttribute::AddType(uint16 value) {
836 attr_types_->push_back(value);
837 SetLength(static_cast<uint16>(attr_types_->size() * 2));
838 }
839
Read(ByteBuffer * buf)840 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
841 if (length() % 2)
842 return false;
843
844 for (size_t i = 0; i < length() / 2; i++) {
845 uint16 attr;
846 if (!buf->ReadUInt16(&attr))
847 return false;
848 attr_types_->push_back(attr);
849 }
850 // Padding of these attributes is done in RFC 5389 style. This is
851 // slightly different from RFC3489, but it shouldn't be important.
852 // RFC3489 pads out to a 32 bit boundary by duplicating one of the
853 // entries in the list (not necessarily the last one - it's unspecified).
854 // RFC5389 pads on the end, and the bytes are always ignored.
855 ConsumePadding(buf);
856 return true;
857 }
858
Write(ByteBuffer * buf) const859 bool StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
860 for (size_t i = 0; i < attr_types_->size(); ++i) {
861 buf->WriteUInt16((*attr_types_)[i]);
862 }
863 WritePadding(buf);
864 return true;
865 }
866
GetStunSuccessResponseType(int req_type)867 int GetStunSuccessResponseType(int req_type) {
868 return IsStunRequestType(req_type) ? (req_type | 0x100) : -1;
869 }
870
GetStunErrorResponseType(int req_type)871 int GetStunErrorResponseType(int req_type) {
872 return IsStunRequestType(req_type) ? (req_type | 0x110) : -1;
873 }
874
IsStunRequestType(int msg_type)875 bool IsStunRequestType(int msg_type) {
876 return ((msg_type & kStunTypeMask) == 0x000);
877 }
878
IsStunIndicationType(int msg_type)879 bool IsStunIndicationType(int msg_type) {
880 return ((msg_type & kStunTypeMask) == 0x010);
881 }
882
IsStunSuccessResponseType(int msg_type)883 bool IsStunSuccessResponseType(int msg_type) {
884 return ((msg_type & kStunTypeMask) == 0x100);
885 }
886
IsStunErrorResponseType(int msg_type)887 bool IsStunErrorResponseType(int msg_type) {
888 return ((msg_type & kStunTypeMask) == 0x110);
889 }
890
ComputeStunCredentialHash(const std::string & username,const std::string & realm,const std::string & password,std::string * hash)891 bool ComputeStunCredentialHash(const std::string& username,
892 const std::string& realm,
893 const std::string& password,
894 std::string* hash) {
895 // http://tools.ietf.org/html/rfc5389#section-15.4
896 // long-term credentials will be calculated using the key and key is
897 // key = MD5(username ":" realm ":" SASLprep(password))
898 std::string input = username;
899 input += ':';
900 input += realm;
901 input += ':';
902 input += password;
903
904 char digest[rtc::MessageDigest::kMaxSize];
905 size_t size = rtc::ComputeDigest(
906 rtc::DIGEST_MD5, input.c_str(), input.size(),
907 digest, sizeof(digest));
908 if (size == 0) {
909 return false;
910 }
911
912 *hash = std::string(digest, size);
913 return true;
914 }
915
916 } // namespace cricket
917