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