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