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 <cstring>
31
32 #include "talk/base/common.h"
33 #include "talk/base/logging.h"
34
35 using talk_base::ByteBuffer;
36
37 namespace cricket {
38
39 const std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST";
40 const std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED";
41 const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE";
42 const std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS";
43 const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE";
44 const std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME";
45 const std::string STUN_ERROR_REASON_USE_TLS = "USE TLS";
46 const std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR";
47 const std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE";
48
StunMessage()49 StunMessage::StunMessage() : type_(0), length_(0),
50 transaction_id_("0000000000000000") {
51 ASSERT(transaction_id_.size() == 16);
52 attrs_ = new std::vector<StunAttribute*>();
53 }
54
~StunMessage()55 StunMessage::~StunMessage() {
56 for (unsigned i = 0; i < attrs_->size(); i++)
57 delete (*attrs_)[i];
58 delete attrs_;
59 }
60
SetTransactionID(const std::string & str)61 void StunMessage::SetTransactionID(const std::string& str) {
62 ASSERT(str.size() == 16);
63 transaction_id_ = str;
64 }
65
AddAttribute(StunAttribute * attr)66 void StunMessage::AddAttribute(StunAttribute* attr) {
67 attrs_->push_back(attr);
68 length_ += attr->length() + 4;
69 }
70
71 const StunAddressAttribute*
GetAddress(StunAttributeType type) const72 StunMessage::GetAddress(StunAttributeType type) const {
73 switch (type) {
74 case STUN_ATTR_MAPPED_ADDRESS:
75 case STUN_ATTR_RESPONSE_ADDRESS:
76 case STUN_ATTR_SOURCE_ADDRESS:
77 case STUN_ATTR_CHANGED_ADDRESS:
78 case STUN_ATTR_REFLECTED_FROM:
79 case STUN_ATTR_ALTERNATE_SERVER:
80 case STUN_ATTR_DESTINATION_ADDRESS:
81 case STUN_ATTR_SOURCE_ADDRESS2:
82 return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type));
83
84 default:
85 ASSERT(0);
86 return 0;
87 }
88 }
89
90 const StunUInt32Attribute*
GetUInt32(StunAttributeType type) const91 StunMessage::GetUInt32(StunAttributeType type) const {
92 switch (type) {
93 case STUN_ATTR_CHANGE_REQUEST:
94 case STUN_ATTR_LIFETIME:
95 case STUN_ATTR_BANDWIDTH:
96 case STUN_ATTR_OPTIONS:
97 return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type));
98
99 default:
100 ASSERT(0);
101 return 0;
102 }
103 }
104
105 const StunByteStringAttribute*
GetByteString(StunAttributeType type) const106 StunMessage::GetByteString(StunAttributeType type) const {
107 switch (type) {
108 case STUN_ATTR_USERNAME:
109 case STUN_ATTR_PASSWORD:
110 case STUN_ATTR_MESSAGE_INTEGRITY:
111 case STUN_ATTR_DATA:
112 case STUN_ATTR_MAGIC_COOKIE:
113 return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type));
114
115 default:
116 ASSERT(0);
117 return 0;
118 }
119 }
120
GetErrorCode() const121 const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
122 return reinterpret_cast<const StunErrorCodeAttribute*>(
123 GetAttribute(STUN_ATTR_ERROR_CODE));
124 }
125
GetUnknownAttributes() const126 const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
127 return reinterpret_cast<const StunUInt16ListAttribute*>(
128 GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
129 }
130
GetTransportPrefs() const131 const StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const {
132 return reinterpret_cast<const StunTransportPrefsAttribute*>(
133 GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES));
134 }
135
GetAttribute(StunAttributeType type) const136 const StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const {
137 for (unsigned i = 0; i < attrs_->size(); i++) {
138 if ((*attrs_)[i]->type() == type)
139 return (*attrs_)[i];
140 }
141 return 0;
142 }
143
Read(ByteBuffer * buf)144 bool StunMessage::Read(ByteBuffer* buf) {
145 if (!buf->ReadUInt16(&type_))
146 return false;
147
148 if (type_ & 0x8000) {
149 // rtp and rtcp set MSB of first byte, since first two bits are version,
150 // and version is always 2 (10). If set, this is not a stun packet.
151 return false;
152 }
153
154 if (!buf->ReadUInt16(&length_))
155 return false;
156
157 std::string transaction_id;
158 if (!buf->ReadString(&transaction_id, 16))
159 return false;
160 ASSERT(transaction_id.size() == 16);
161 transaction_id_ = transaction_id;
162
163 if (length_ > buf->Length())
164 return false;
165
166 attrs_->resize(0);
167
168 size_t rest = buf->Length() - length_;
169 while (buf->Length() > rest) {
170 uint16 attr_type, attr_length;
171 if (!buf->ReadUInt16(&attr_type))
172 return false;
173 if (!buf->ReadUInt16(&attr_length))
174 return false;
175
176 StunAttribute* attr = StunAttribute::Create(attr_type, attr_length);
177 if (!attr || !attr->Read(buf))
178 return false;
179
180 attrs_->push_back(attr);
181 }
182
183 if (buf->Length() != rest) {
184 // fixme: shouldn't be doing this
185 LOG(LERROR) << "wrong message length (" << rest << " != " << buf->Length()
186 << ")";
187 return false;
188 }
189
190 return true;
191 }
192
Write(ByteBuffer * buf) const193 void StunMessage::Write(ByteBuffer* buf) const {
194 buf->WriteUInt16(type_);
195 buf->WriteUInt16(length_);
196 buf->WriteString(transaction_id_);
197
198 for (unsigned i = 0; i < attrs_->size(); i++) {
199 buf->WriteUInt16((*attrs_)[i]->type());
200 buf->WriteUInt16((*attrs_)[i]->length());
201 (*attrs_)[i]->Write(buf);
202 }
203 }
204
StunAttribute(uint16 type,uint16 length)205 StunAttribute::StunAttribute(uint16 type, uint16 length)
206 : type_(type), length_(length) {
207 }
208
Create(uint16 type,uint16 length)209 StunAttribute* StunAttribute::Create(uint16 type, uint16 length) {
210 switch (type) {
211 case STUN_ATTR_MAPPED_ADDRESS:
212 case STUN_ATTR_RESPONSE_ADDRESS:
213 case STUN_ATTR_SOURCE_ADDRESS:
214 case STUN_ATTR_CHANGED_ADDRESS:
215 case STUN_ATTR_REFLECTED_FROM:
216 case STUN_ATTR_ALTERNATE_SERVER:
217 case STUN_ATTR_DESTINATION_ADDRESS:
218 case STUN_ATTR_SOURCE_ADDRESS2:
219 if (length != StunAddressAttribute::SIZE)
220 return 0;
221 return new StunAddressAttribute(type);
222
223 case STUN_ATTR_CHANGE_REQUEST:
224 case STUN_ATTR_LIFETIME:
225 case STUN_ATTR_BANDWIDTH:
226 case STUN_ATTR_OPTIONS:
227 if (length != StunUInt32Attribute::SIZE)
228 return 0;
229 return new StunUInt32Attribute(type);
230
231 case STUN_ATTR_USERNAME:
232 case STUN_ATTR_PASSWORD:
233 case STUN_ATTR_MAGIC_COOKIE:
234 return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0;
235
236 case STUN_ATTR_MESSAGE_INTEGRITY:
237 return (length == 20) ? new StunByteStringAttribute(type, length) : 0;
238
239 case STUN_ATTR_DATA:
240 return new StunByteStringAttribute(type, length);
241
242 case STUN_ATTR_ERROR_CODE:
243 if (length < StunErrorCodeAttribute::MIN_SIZE)
244 return 0;
245 return new StunErrorCodeAttribute(type, length);
246
247 case STUN_ATTR_UNKNOWN_ATTRIBUTES:
248 return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0;
249
250 case STUN_ATTR_TRANSPORT_PREFERENCES:
251 if ((length != StunTransportPrefsAttribute::SIZE1) &&
252 (length != StunTransportPrefsAttribute::SIZE2))
253 return 0;
254 return new StunTransportPrefsAttribute(type, length);
255
256 default:
257 return 0;
258 }
259 }
260
CreateAddress(uint16 type)261 StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
262 switch (type) {
263 case STUN_ATTR_MAPPED_ADDRESS:
264 case STUN_ATTR_RESPONSE_ADDRESS:
265 case STUN_ATTR_SOURCE_ADDRESS:
266 case STUN_ATTR_CHANGED_ADDRESS:
267 case STUN_ATTR_REFLECTED_FROM:
268 case STUN_ATTR_ALTERNATE_SERVER:
269 case STUN_ATTR_DESTINATION_ADDRESS:
270 case STUN_ATTR_SOURCE_ADDRESS2:
271 return new StunAddressAttribute(type);
272
273 default:
274 ASSERT(false);
275 return 0;
276 }
277 }
278
CreateUInt32(uint16 type)279 StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
280 switch (type) {
281 case STUN_ATTR_CHANGE_REQUEST:
282 case STUN_ATTR_LIFETIME:
283 case STUN_ATTR_BANDWIDTH:
284 case STUN_ATTR_OPTIONS:
285 return new StunUInt32Attribute(type);
286
287 default:
288 ASSERT(false);
289 return 0;
290 }
291 }
292
CreateByteString(uint16 type)293 StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) {
294 switch (type) {
295 case STUN_ATTR_USERNAME:
296 case STUN_ATTR_PASSWORD:
297 case STUN_ATTR_MESSAGE_INTEGRITY:
298 case STUN_ATTR_DATA:
299 case STUN_ATTR_MAGIC_COOKIE:
300 return new StunByteStringAttribute(type, 0);
301
302 default:
303 ASSERT(false);
304 return 0;
305 }
306 }
307
CreateErrorCode()308 StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
309 return new StunErrorCodeAttribute(
310 STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
311 }
312
CreateUnknownAttributes()313 StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
314 return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
315 }
316
CreateTransportPrefs()317 StunTransportPrefsAttribute* StunAttribute::CreateTransportPrefs() {
318 return new StunTransportPrefsAttribute(
319 STUN_ATTR_TRANSPORT_PREFERENCES, StunTransportPrefsAttribute::SIZE1);
320 }
321
StunAddressAttribute(uint16 type)322 StunAddressAttribute::StunAddressAttribute(uint16 type)
323 : StunAttribute(type, SIZE), family_(0), port_(0), ip_(0) {
324 }
325
Read(ByteBuffer * buf)326 bool StunAddressAttribute::Read(ByteBuffer* buf) {
327 uint8 dummy;
328 if (!buf->ReadUInt8(&dummy))
329 return false;
330 if (!buf->ReadUInt8(&family_))
331 return false;
332 if (!buf->ReadUInt16(&port_))
333 return false;
334 if (!buf->ReadUInt32(&ip_))
335 return false;
336 return true;
337 }
338
Write(ByteBuffer * buf) const339 void StunAddressAttribute::Write(ByteBuffer* buf) const {
340 buf->WriteUInt8(0);
341 buf->WriteUInt8(family_);
342 buf->WriteUInt16(port_);
343 buf->WriteUInt32(ip_);
344 }
345
StunUInt32Attribute(uint16 type)346 StunUInt32Attribute::StunUInt32Attribute(uint16 type)
347 : StunAttribute(type, SIZE), bits_(0) {
348 }
349
GetBit(int index) const350 bool StunUInt32Attribute::GetBit(int index) const {
351 ASSERT((0 <= index) && (index < 32));
352 return static_cast<bool>((bits_ >> index) & 0x1);
353 }
354
SetBit(int index,bool value)355 void StunUInt32Attribute::SetBit(int index, bool value) {
356 ASSERT((0 <= index) && (index < 32));
357 bits_ &= ~(1 << index);
358 bits_ |= value ? (1 << index) : 0;
359 }
360
Read(ByteBuffer * buf)361 bool StunUInt32Attribute::Read(ByteBuffer* buf) {
362 if (!buf->ReadUInt32(&bits_))
363 return false;
364 return true;
365 }
366
Write(ByteBuffer * buf) const367 void StunUInt32Attribute::Write(ByteBuffer* buf) const {
368 buf->WriteUInt32(bits_);
369 }
370
StunByteStringAttribute(uint16 type,uint16 length)371 StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
372 : StunAttribute(type, length), bytes_(0) {
373 }
374
~StunByteStringAttribute()375 StunByteStringAttribute::~StunByteStringAttribute() {
376 delete [] bytes_;
377 }
378
SetBytes(char * bytes,uint16 length)379 void StunByteStringAttribute::SetBytes(char* bytes, uint16 length) {
380 delete [] bytes_;
381 bytes_ = bytes;
382 SetLength(length);
383 }
384
CopyBytes(const char * bytes)385 void StunByteStringAttribute::CopyBytes(const char* bytes) {
386 CopyBytes(bytes, static_cast<uint16>(strlen(bytes)));
387 }
388
CopyBytes(const void * bytes,uint16 length)389 void StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) {
390 char* new_bytes = new char[length];
391 std::memcpy(new_bytes, bytes, length);
392 SetBytes(new_bytes, length);
393 }
394
GetByte(int index) const395 uint8 StunByteStringAttribute::GetByte(int index) const {
396 ASSERT(bytes_ != NULL);
397 ASSERT((0 <= index) && (index < length()));
398 return static_cast<uint8>(bytes_[index]);
399 }
400
SetByte(int index,uint8 value)401 void StunByteStringAttribute::SetByte(int index, uint8 value) {
402 ASSERT(bytes_ != NULL);
403 ASSERT((0 <= index) && (index < length()));
404 bytes_[index] = value;
405 }
406
Read(ByteBuffer * buf)407 bool StunByteStringAttribute::Read(ByteBuffer* buf) {
408 bytes_ = new char[length()];
409 if (!buf->ReadBytes(bytes_, length()))
410 return false;
411 return true;
412 }
413
Write(ByteBuffer * buf) const414 void StunByteStringAttribute::Write(ByteBuffer* buf) const {
415 buf->WriteBytes(bytes_, length());
416 }
417
StunErrorCodeAttribute(uint16 type,uint16 length)418 StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
419 : StunAttribute(type, length), class_(0), number_(0) {
420 }
421
~StunErrorCodeAttribute()422 StunErrorCodeAttribute::~StunErrorCodeAttribute() {
423 }
424
SetErrorCode(uint32 code)425 void StunErrorCodeAttribute::SetErrorCode(uint32 code) {
426 class_ = (uint8)((code >> 8) & 0x7);
427 number_ = (uint8)(code & 0xff);
428 }
429
SetReason(const std::string & reason)430 void StunErrorCodeAttribute::SetReason(const std::string& reason) {
431 SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
432 reason_ = reason;
433 }
434
Read(ByteBuffer * buf)435 bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
436 uint32 val;
437 if (!buf->ReadUInt32(&val))
438 return false;
439
440 if ((val >> 11) != 0)
441 LOG(LERROR) << "error-code bits not zero";
442
443 SetErrorCode(val);
444
445 if (!buf->ReadString(&reason_, length() - 4))
446 return false;
447
448 return true;
449 }
450
Write(ByteBuffer * buf) const451 void StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
452 buf->WriteUInt32(error_code());
453 buf->WriteString(reason_);
454 }
455
StunUInt16ListAttribute(uint16 type,uint16 length)456 StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
457 : StunAttribute(type, length) {
458 attr_types_ = new std::vector<uint16>();
459 }
460
~StunUInt16ListAttribute()461 StunUInt16ListAttribute::~StunUInt16ListAttribute() {
462 delete attr_types_;
463 }
464
Size() const465 size_t StunUInt16ListAttribute::Size() const {
466 return attr_types_->size();
467 }
468
GetType(int index) const469 uint16 StunUInt16ListAttribute::GetType(int index) const {
470 return (*attr_types_)[index];
471 }
472
SetType(int index,uint16 value)473 void StunUInt16ListAttribute::SetType(int index, uint16 value) {
474 (*attr_types_)[index] = value;
475 }
476
AddType(uint16 value)477 void StunUInt16ListAttribute::AddType(uint16 value) {
478 attr_types_->push_back(value);
479 SetLength(static_cast<uint16>(attr_types_->size() * 2));
480 }
481
Read(ByteBuffer * buf)482 bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
483 for (int i = 0; i < length() / 2; i++) {
484 uint16 attr;
485 if (!buf->ReadUInt16(&attr))
486 return false;
487 attr_types_->push_back(attr);
488 }
489 return true;
490 }
491
Write(ByteBuffer * buf) const492 void StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
493 for (unsigned i = 0; i < attr_types_->size(); i++)
494 buf->WriteUInt16((*attr_types_)[i]);
495 }
496
StunTransportPrefsAttribute(uint16 type,uint16 length)497 StunTransportPrefsAttribute::StunTransportPrefsAttribute(
498 uint16 type, uint16 length)
499 : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) {
500 }
501
~StunTransportPrefsAttribute()502 StunTransportPrefsAttribute::~StunTransportPrefsAttribute() {
503 delete addr_;
504 }
505
SetPreallocateAddress(StunAddressAttribute * addr)506 void StunTransportPrefsAttribute::SetPreallocateAddress(
507 StunAddressAttribute* addr) {
508 if (!addr) {
509 preallocate_ = false;
510 addr_ = 0;
511 SetLength(SIZE1);
512 } else {
513 preallocate_ = true;
514 addr_ = addr;
515 SetLength(SIZE2);
516 }
517 }
518
Read(ByteBuffer * buf)519 bool StunTransportPrefsAttribute::Read(ByteBuffer* buf) {
520 uint32 val;
521 if (!buf->ReadUInt32(&val))
522 return false;
523
524 if ((val >> 3) != 0)
525 LOG(LERROR) << "transport-preferences bits not zero";
526
527 preallocate_ = static_cast<bool>((val >> 2) & 0x1);
528 prefs_ = (uint8)(val & 0x3);
529
530 if (preallocate_ && (prefs_ == 3))
531 LOG(LERROR) << "transport-preferences imcompatible P and Typ";
532
533 if (!preallocate_) {
534 if (length() != StunUInt32Attribute::SIZE)
535 return false;
536 } else {
537 if (length() != StunUInt32Attribute::SIZE + StunAddressAttribute::SIZE)
538 return false;
539
540 addr_ = new StunAddressAttribute(STUN_ATTR_SOURCE_ADDRESS);
541 addr_->Read(buf);
542 }
543
544 return true;
545 }
546
Write(ByteBuffer * buf) const547 void StunTransportPrefsAttribute::Write(ByteBuffer* buf) const {
548 buf->WriteUInt32((preallocate_ ? 4 : 0) | prefs_);
549
550 if (preallocate_)
551 addr_->Write(buf);
552 }
553
GetStunResponseType(StunMessageType request_type)554 StunMessageType GetStunResponseType(StunMessageType request_type) {
555 switch (request_type) {
556 case STUN_SHARED_SECRET_REQUEST:
557 return STUN_SHARED_SECRET_RESPONSE;
558 case STUN_ALLOCATE_REQUEST:
559 return STUN_ALLOCATE_RESPONSE;
560 case STUN_SEND_REQUEST:
561 return STUN_SEND_RESPONSE;
562 default:
563 return STUN_BINDING_RESPONSE;
564 }
565 }
566
GetStunErrorResponseType(StunMessageType request_type)567 StunMessageType GetStunErrorResponseType(StunMessageType request_type) {
568 switch (request_type) {
569 case STUN_SHARED_SECRET_REQUEST:
570 return STUN_SHARED_SECRET_ERROR_RESPONSE;
571 case STUN_ALLOCATE_REQUEST:
572 return STUN_ALLOCATE_ERROR_RESPONSE;
573 case STUN_SEND_REQUEST:
574 return STUN_SEND_ERROR_RESPONSE;
575 default:
576 return STUN_BINDING_ERROR_RESPONSE;
577 }
578 }
579
580 } // namespace cricket
581