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