• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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