blob: 350ebd0119fbc1026e60e76d9f0e315b35663628 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "p2p/base/turnserver.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000012
Taylor Brandstetter734262c2016-08-01 16:37:14 -070013#include <tuple> // for std::tie
Steve Anton6c38cc72017-11-29 10:25:58 -080014#include <utility>
Taylor Brandstetter734262c2016-08-01 16:37:14 -070015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "p2p/base/asyncstuntcpsocket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "p2p/base/packetsocketfactory.h"
18#include "p2p/base/stun.h"
19#include "rtc_base/bind.h"
20#include "rtc_base/bytebuffer.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/helpers.h"
23#include "rtc_base/logging.h"
24#include "rtc_base/messagedigest.h"
25#include "rtc_base/ptr_util.h"
26#include "rtc_base/socketadapters.h"
27#include "rtc_base/stringencode.h"
28#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000029
30namespace cricket {
31
32// TODO(juberti): Move this all to a future turnmessage.h
Steve Anton6c38cc72017-11-29 10:25:58 -080033// static const int IPPROTO_UDP = 17;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000034static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes
35static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes
36static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes
37static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes
38
39static const int kMinChannelNumber = 0x4000;
40static const int kMaxChannelNumber = 0x7FFF;
41
42static const size_t kNonceKeySize = 16;
honghaiz34b11eb2016-03-16 08:55:44 -070043static const size_t kNonceSize = 48;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000044
45static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
46
47// TODO(mallinath) - Move these to a common place.
Peter Boström0c4e06b2015-10-07 12:23:21 +020048inline bool IsTurnChannelData(uint16_t msg_type) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000049 // The first two bits of a channel data message are 0b01.
50 return ((msg_type & 0xC000) == 0x4000);
51}
52
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000053// IDs used for posted messages for TurnServerAllocation.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000054enum {
55 MSG_ALLOCATION_TIMEOUT,
56};
57
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000058// Encapsulates a TURN permission.
59// The object is created when a create permission request is received by an
60// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000061class TurnServerAllocation::Permission : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062 public:
63 Permission(rtc::Thread* thread, const rtc::IPAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070064 ~Permission() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000065
66 const rtc::IPAddress& peer() const { return peer_; }
67 void Refresh();
68
69 sigslot::signal1<Permission*> SignalDestroyed;
70
71 private:
Steve Antonf2737d22017-10-31 16:27:34 -070072 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000073
74 rtc::Thread* thread_;
75 rtc::IPAddress peer_;
76};
77
78// Encapsulates a TURN channel binding.
79// The object is created when a channel bind request is received by an
80// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000081class TurnServerAllocation::Channel : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000082 public:
83 Channel(rtc::Thread* thread, int id,
84 const rtc::SocketAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070085 ~Channel() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000086
87 int id() const { return id_; }
88 const rtc::SocketAddress& peer() const { return peer_; }
89 void Refresh();
90
91 sigslot::signal1<Channel*> SignalDestroyed;
92
93 private:
Steve Antonf2737d22017-10-31 16:27:34 -070094 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000095
96 rtc::Thread* thread_;
97 int id_;
98 rtc::SocketAddress peer_;
99};
100
101static bool InitResponse(const StunMessage* req, StunMessage* resp) {
102 int resp_type = (req) ? GetStunSuccessResponseType(req->type()) : -1;
103 if (resp_type == -1)
104 return false;
105 resp->SetType(resp_type);
106 resp->SetTransactionID(req->transaction_id());
107 return true;
108}
109
110static bool InitErrorResponse(const StunMessage* req, int code,
111 const std::string& reason, StunMessage* resp) {
112 int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1;
113 if (resp_type == -1)
114 return false;
115 resp->SetType(resp_type);
116 resp->SetTransactionID(req->transaction_id());
zsteinf42cc9d2017-03-27 16:17:19 -0700117 resp->AddAttribute(rtc::MakeUnique<cricket::StunErrorCodeAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800118 STUN_ATTR_ERROR_CODE, code, reason));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000119 return true;
120}
121
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000122
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000123TurnServer::TurnServer(rtc::Thread* thread)
124 : thread_(thread),
125 nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
126 auth_hook_(NULL),
127 redirect_hook_(NULL),
128 enable_otu_nonce_(false) {
129}
130
131TurnServer::~TurnServer() {
Seth Hampsonaed71642018-06-11 07:41:32 -0700132 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000133 for (InternalSocketMap::iterator it = server_sockets_.begin();
134 it != server_sockets_.end(); ++it) {
135 rtc::AsyncPacketSocket* socket = it->first;
136 delete socket;
137 }
138
139 for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
140 it != server_listen_sockets_.end(); ++it) {
141 rtc::AsyncSocket* socket = it->first;
142 delete socket;
143 }
144}
145
146void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket,
147 ProtocolType proto) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700148 RTC_DCHECK(thread_checker_.CalledOnValidThread());
nisseede5da42017-01-12 05:15:36 -0800149 RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000150 server_sockets_[socket] = proto;
151 socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
152}
153
154void TurnServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
155 ProtocolType proto) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700156 RTC_DCHECK(thread_checker_.CalledOnValidThread());
nisseede5da42017-01-12 05:15:36 -0800157 RTC_DCHECK(server_listen_sockets_.end() ==
158 server_listen_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000159 server_listen_sockets_[socket] = proto;
160 socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
161}
162
163void TurnServer::SetExternalSocketFactory(
164 rtc::PacketSocketFactory* factory,
165 const rtc::SocketAddress& external_addr) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700166 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000167 external_socket_factory_.reset(factory);
168 external_addr_ = external_addr;
169}
170
171void TurnServer::OnNewInternalConnection(rtc::AsyncSocket* socket) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700172 RTC_DCHECK(thread_checker_.CalledOnValidThread());
nisseede5da42017-01-12 05:15:36 -0800173 RTC_DCHECK(server_listen_sockets_.find(socket) !=
174 server_listen_sockets_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000175 AcceptConnection(socket);
176}
177
178void TurnServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700179 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000180 // Check if someone is trying to connect to us.
181 rtc::SocketAddress accept_addr;
182 rtc::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr);
183 if (accepted_socket != NULL) {
184 ProtocolType proto = server_listen_sockets_[server_socket];
185 cricket::AsyncStunTCPSocket* tcp_socket =
186 new cricket::AsyncStunTCPSocket(accepted_socket, false);
187
188 tcp_socket->SignalClose.connect(this, &TurnServer::OnInternalSocketClose);
189 // Finally add the socket so it can start communicating with the client.
190 AddInternalSocket(tcp_socket, proto);
191 }
192}
193
194void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket,
195 int err) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700196 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000197 DestroyInternalSocket(socket);
198}
199
200void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket,
201 const char* data, size_t size,
202 const rtc::SocketAddress& addr,
203 const rtc::PacketTime& packet_time) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700204 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000205 // Fail if the packet is too small to even contain a channel header.
206 if (size < TURN_CHANNEL_HEADER_SIZE) {
Steve Anton6c38cc72017-11-29 10:25:58 -0800207 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000208 }
209 InternalSocketMap::iterator iter = server_sockets_.find(socket);
nisseede5da42017-01-12 05:15:36 -0800210 RTC_DCHECK(iter != server_sockets_.end());
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000211 TurnServerConnection conn(addr, iter->second, socket);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200212 uint16_t msg_type = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000213 if (!IsTurnChannelData(msg_type)) {
214 // This is a STUN message.
215 HandleStunMessage(&conn, data, size);
216 } else {
217 // This is a channel message; let the allocation handle it.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000218 TurnServerAllocation* allocation = FindAllocation(&conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000219 if (allocation) {
220 allocation->HandleChannelData(data, size);
221 }
Jonas Orelandbdcee282017-10-10 14:01:40 +0200222 if (stun_message_observer_ != nullptr) {
223 stun_message_observer_->ReceivedChannelData(data, size);
224 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000225 }
226}
227
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000228void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000229 size_t size) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700230 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000231 TurnMessage msg;
jbauchf1f87202016-03-30 06:43:37 -0700232 rtc::ByteBufferReader buf(data, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000233 if (!msg.Read(&buf) || (buf.Length() > 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100234 RTC_LOG(LS_WARNING) << "Received invalid STUN message";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000235 return;
236 }
237
Jonas Orelandbdcee282017-10-10 14:01:40 +0200238 if (stun_message_observer_ != nullptr) {
239 stun_message_observer_->ReceivedMessage(&msg);
240 }
241
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000242 // If it's a STUN binding request, handle that specially.
243 if (msg.type() == STUN_BINDING_REQUEST) {
244 HandleBindingRequest(conn, &msg);
245 return;
246 }
247
248 if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
249 rtc::SocketAddress address;
250 if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
251 SendErrorResponseWithAlternateServer(
252 conn, &msg, address);
253 return;
254 }
255 }
256
257 // Look up the key that we'll use to validate the M-I. If we have an
258 // existing allocation, the key will already be cached.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000259 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000260 std::string key;
261 if (!allocation) {
262 GetKey(&msg, &key);
263 } else {
264 key = allocation->key();
265 }
266
267 // Ensure the message is authorized; only needed for requests.
268 if (IsStunRequestType(msg.type())) {
269 if (!CheckAuthorization(conn, &msg, data, size, key)) {
270 return;
271 }
272 }
273
274 if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
275 HandleAllocateRequest(conn, &msg, key);
276 } else if (allocation &&
277 (msg.type() != STUN_ALLOCATE_REQUEST ||
278 msg.transaction_id() == allocation->transaction_id())) {
279 // This is a non-allocate request, or a retransmit of an allocate.
280 // Check that the username matches the previous username used.
281 if (IsStunRequestType(msg.type()) &&
282 msg.GetByteString(STUN_ATTR_USERNAME)->GetString() !=
283 allocation->username()) {
284 SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
285 STUN_ERROR_REASON_WRONG_CREDENTIALS);
286 return;
287 }
288 allocation->HandleTurnMessage(&msg);
289 } else {
290 // Allocation mismatch.
291 SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
292 STUN_ERROR_REASON_ALLOCATION_MISMATCH);
293 }
294}
295
296bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700297 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000298 const StunByteStringAttribute* username_attr =
299 msg->GetByteString(STUN_ATTR_USERNAME);
300 if (!username_attr) {
301 return false;
302 }
303
304 std::string username = username_attr->GetString();
305 return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
306}
307
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000308bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000309 const StunMessage* msg,
310 const char* data, size_t size,
311 const std::string& key) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700312 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000313 // RFC 5389, 10.2.2.
nisseede5da42017-01-12 05:15:36 -0800314 RTC_DCHECK(IsStunRequestType(msg->type()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000315 const StunByteStringAttribute* mi_attr =
316 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
317 const StunByteStringAttribute* username_attr =
318 msg->GetByteString(STUN_ATTR_USERNAME);
319 const StunByteStringAttribute* realm_attr =
320 msg->GetByteString(STUN_ATTR_REALM);
321 const StunByteStringAttribute* nonce_attr =
322 msg->GetByteString(STUN_ATTR_NONCE);
323
324 // Fail if no M-I.
325 if (!mi_attr) {
326 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
327 STUN_ERROR_REASON_UNAUTHORIZED);
328 return false;
329 }
330
331 // Fail if there is M-I but no username, nonce, or realm.
332 if (!username_attr || !realm_attr || !nonce_attr) {
333 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
334 STUN_ERROR_REASON_BAD_REQUEST);
335 return false;
336 }
337
338 // Fail if bad nonce.
339 if (!ValidateNonce(nonce_attr->GetString())) {
340 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
341 STUN_ERROR_REASON_STALE_NONCE);
342 return false;
343 }
344
345 // Fail if bad username or M-I.
346 // We need |data| and |size| for the call to ValidateMessageIntegrity.
347 if (key.empty() || !StunMessage::ValidateMessageIntegrity(data, size, key)) {
348 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
349 STUN_ERROR_REASON_UNAUTHORIZED);
350 return false;
351 }
352
353 // Fail if one-time-use nonce feature is enabled.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000354 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000355 if (enable_otu_nonce_ && allocation &&
356 allocation->last_nonce() == nonce_attr->GetString()) {
357 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
358 STUN_ERROR_REASON_STALE_NONCE);
359 return false;
360 }
361
362 if (allocation) {
363 allocation->set_last_nonce(nonce_attr->GetString());
364 }
365 // Success.
366 return true;
367}
368
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000369void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000370 const StunMessage* req) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700371 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000372 StunMessage response;
373 InitResponse(req, &response);
374
375 // Tell the user the address that we received their request from.
zsteinf42cc9d2017-03-27 16:17:19 -0700376 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000377 STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
zsteinf42cc9d2017-03-27 16:17:19 -0700378 response.AddAttribute(std::move(mapped_addr_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000379
380 SendStun(conn, &response);
381}
382
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000383void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000384 const TurnMessage* msg,
385 const std::string& key) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700386 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000387 // Check the parameters in the request.
388 const StunUInt32Attribute* transport_attr =
389 msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
390 if (!transport_attr) {
391 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
392 STUN_ERROR_REASON_BAD_REQUEST);
393 return;
394 }
395
396 // Only UDP is supported right now.
397 int proto = transport_attr->value() >> 24;
398 if (proto != IPPROTO_UDP) {
399 SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
400 STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
401 return;
402 }
403
404 // Create the allocation and let it send the success response.
405 // If the actual socket allocation fails, send an internal error.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000406 TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000407 if (alloc) {
408 alloc->HandleTurnMessage(msg);
409 } else {
410 SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
411 "Failed to allocate socket");
412 }
413}
414
honghaiz34b11eb2016-03-16 08:55:44 -0700415std::string TurnServer::GenerateNonce(int64_t now) const {
Seth Hampsonaed71642018-06-11 07:41:32 -0700416 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000417 // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000418 std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
419 std::string nonce = rtc::hex_encode(input.c_str(), input.size());
420 nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
nisseede5da42017-01-12 05:15:36 -0800421 RTC_DCHECK(nonce.size() == kNonceSize);
honghaiz34b11eb2016-03-16 08:55:44 -0700422
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000423 return nonce;
424}
425
426bool TurnServer::ValidateNonce(const std::string& nonce) const {
Seth Hampsonaed71642018-06-11 07:41:32 -0700427 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000428 // Check the size.
429 if (nonce.size() != kNonceSize) {
430 return false;
431 }
432
433 // Decode the timestamp.
honghaiz34b11eb2016-03-16 08:55:44 -0700434 int64_t then;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000435 char* p = reinterpret_cast<char*>(&then);
436 size_t len = rtc::hex_decode(p, sizeof(then),
437 nonce.substr(0, sizeof(then) * 2));
438 if (len != sizeof(then)) {
439 return false;
440 }
441
442 // Verify the HMAC.
443 if (nonce.substr(sizeof(then) * 2) != rtc::ComputeHmac(
444 rtc::DIGEST_MD5, nonce_key_, std::string(p, sizeof(then)))) {
445 return false;
446 }
447
448 // Validate the timestamp.
nisse1bffc1d2016-05-02 08:18:55 -0700449 return rtc::TimeMillis() - then < kNonceTimeout;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000450}
451
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000452TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700453 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000454 AllocationMap::const_iterator it = allocations_.find(*conn);
deadbeef97943662016-07-12 11:04:50 -0700455 return (it != allocations_.end()) ? it->second.get() : nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000456}
457
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000458TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
459 int proto,
460 const std::string& key) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700461 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000462 rtc::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
463 external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
464 if (!external_socket) {
465 return NULL;
466 }
467
468 // The Allocation takes ownership of the socket.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000469 TurnServerAllocation* allocation = new TurnServerAllocation(this,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000470 thread_, *conn, external_socket, key);
471 allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
deadbeef97943662016-07-12 11:04:50 -0700472 allocations_[*conn].reset(allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000473 return allocation;
474}
475
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000476void TurnServer::SendErrorResponse(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000477 const StunMessage* req,
478 int code, const std::string& reason) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700479 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000480 TurnMessage resp;
481 InitErrorResponse(req, code, reason, &resp);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100482 RTC_LOG(LS_INFO) << "Sending error response, type=" << resp.type()
483 << ", code=" << code << ", reason=" << reason;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000484 SendStun(conn, &resp);
485}
486
487void TurnServer::SendErrorResponseWithRealmAndNonce(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000488 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000489 int code, const std::string& reason) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700490 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000491 TurnMessage resp;
492 InitErrorResponse(msg, code, reason, &resp);
honghaizc463e202016-02-01 15:19:08 -0800493
nisse1bffc1d2016-05-02 08:18:55 -0700494 int64_t timestamp = rtc::TimeMillis();
honghaizc463e202016-02-01 15:19:08 -0800495 if (ts_for_next_nonce_) {
496 timestamp = ts_for_next_nonce_;
497 ts_for_next_nonce_ = 0;
498 }
zsteinf42cc9d2017-03-27 16:17:19 -0700499 resp.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
500 STUN_ATTR_NONCE, GenerateNonce(timestamp)));
nissecc99bc22017-02-02 01:31:30 -0800501 resp.AddAttribute(
zsteinf42cc9d2017-03-27 16:17:19 -0700502 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000503 SendStun(conn, &resp);
504}
505
506void TurnServer::SendErrorResponseWithAlternateServer(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000507 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000508 const rtc::SocketAddress& addr) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700509 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000510 TurnMessage resp;
511 InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
512 STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
zsteinf42cc9d2017-03-27 16:17:19 -0700513 resp.AddAttribute(
514 rtc::MakeUnique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000515 SendStun(conn, &resp);
516}
517
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000518void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700519 RTC_DCHECK(thread_checker_.CalledOnValidThread());
jbauchf1f87202016-03-30 06:43:37 -0700520 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000521 // Add a SOFTWARE attribute if one is set.
522 if (!software_.empty()) {
zsteinf42cc9d2017-03-27 16:17:19 -0700523 msg->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
524 STUN_ATTR_SOFTWARE, software_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000525 }
526 msg->Write(&buf);
527 Send(conn, buf);
528}
529
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000530void TurnServer::Send(TurnServerConnection* conn,
jbauchf1f87202016-03-30 06:43:37 -0700531 const rtc::ByteBufferWriter& buf) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700532 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000533 rtc::PacketOptions options;
534 conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
535}
536
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000537void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700538 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000539 // Removing the internal socket if the connection is not udp.
540 rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
541 InternalSocketMap::iterator iter = server_sockets_.find(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000542 // Skip if the socket serving this allocation is UDP, as this will be shared
543 // by all allocations.
Taylor Brandstetter716d07a2016-06-27 14:07:41 -0700544 // Note: We may not find a socket if it's a TCP socket that was closed, and
545 // the allocation is only now timing out.
546 if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000547 DestroyInternalSocket(socket);
548 }
549
550 AllocationMap::iterator it = allocations_.find(*(allocation->conn()));
deadbeef97943662016-07-12 11:04:50 -0700551 if (it != allocations_.end()) {
552 it->second.release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000553 allocations_.erase(it);
deadbeef97943662016-07-12 11:04:50 -0700554 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000555}
556
557void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
Seth Hampsonaed71642018-06-11 07:41:32 -0700558 RTC_DCHECK(thread_checker_.CalledOnValidThread());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000559 InternalSocketMap::iterator iter = server_sockets_.find(socket);
560 if (iter != server_sockets_.end()) {
561 rtc::AsyncPacketSocket* socket = iter->first;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000562 server_sockets_.erase(iter);
deadbeef824f5862016-08-24 15:06:53 -0700563 // We must destroy the socket async to avoid invalidating the sigslot
564 // callback list iterator inside a sigslot callback. (In other words,
565 // deleting an object from within a callback from that object).
566 sockets_to_delete_.push_back(
567 std::unique_ptr<rtc::AsyncPacketSocket>(socket));
568 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, rtc::Thread::Current(),
569 rtc::Bind(&TurnServer::FreeSockets, this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000570 }
571}
572
deadbeef824f5862016-08-24 15:06:53 -0700573void TurnServer::FreeSockets() {
Seth Hampsonaed71642018-06-11 07:41:32 -0700574 RTC_DCHECK(thread_checker_.CalledOnValidThread());
deadbeef824f5862016-08-24 15:06:53 -0700575 sockets_to_delete_.clear();
576}
577
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000578TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
579 ProtocolType proto,
580 rtc::AsyncPacketSocket* socket)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000581 : src_(src),
582 dst_(socket->GetRemoteAddress()),
583 proto_(proto),
584 socket_(socket) {
585}
586
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000587bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000588 return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
589}
590
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000591bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
Taylor Brandstetter734262c2016-08-01 16:37:14 -0700592 return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000593}
594
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000595std::string TurnServerConnection::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000596 const char* const kProtos[] = {
597 "unknown", "udp", "tcp", "ssltcp"
598 };
599 std::ostringstream ost;
600 ost << src_.ToString() << "-" << dst_.ToString() << ":"<< kProtos[proto_];
601 return ost.str();
602}
603
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000604TurnServerAllocation::TurnServerAllocation(TurnServer* server,
605 rtc::Thread* thread,
606 const TurnServerConnection& conn,
607 rtc::AsyncPacketSocket* socket,
608 const std::string& key)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000609 : server_(server),
610 thread_(thread),
611 conn_(conn),
612 external_socket_(socket),
613 key_(key) {
614 external_socket_->SignalReadPacket.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000615 this, &TurnServerAllocation::OnExternalPacket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000616}
617
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000618TurnServerAllocation::~TurnServerAllocation() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000619 for (ChannelList::iterator it = channels_.begin();
620 it != channels_.end(); ++it) {
621 delete *it;
622 }
623 for (PermissionList::iterator it = perms_.begin();
624 it != perms_.end(); ++it) {
625 delete *it;
626 }
627 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Jonas Olssond7d762d2018-03-28 09:47:51 +0200628 RTC_LOG(LS_INFO) << ToString() << ": Allocation destroyed";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000629}
630
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000631std::string TurnServerAllocation::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000632 std::ostringstream ost;
633 ost << "Alloc[" << conn_.ToString() << "]";
634 return ost.str();
635}
636
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000637void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
nisseede5da42017-01-12 05:15:36 -0800638 RTC_DCHECK(msg != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000639 switch (msg->type()) {
640 case STUN_ALLOCATE_REQUEST:
641 HandleAllocateRequest(msg);
642 break;
643 case TURN_REFRESH_REQUEST:
644 HandleRefreshRequest(msg);
645 break;
646 case TURN_SEND_INDICATION:
647 HandleSendIndication(msg);
648 break;
649 case TURN_CREATE_PERMISSION_REQUEST:
650 HandleCreatePermissionRequest(msg);
651 break;
652 case TURN_CHANNEL_BIND_REQUEST:
653 HandleChannelBindRequest(msg);
654 break;
655 default:
656 // Not sure what to do with this, just eat it.
Jonas Olssond7d762d2018-03-28 09:47:51 +0200657 RTC_LOG(LS_WARNING) << ToString()
658 << ": Invalid TURN message type received: "
659 << msg->type();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000660 }
661}
662
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000663void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000664 // Copy the important info from the allocate request.
665 transaction_id_ = msg->transaction_id();
666 const StunByteStringAttribute* username_attr =
667 msg->GetByteString(STUN_ATTR_USERNAME);
nisseede5da42017-01-12 05:15:36 -0800668 RTC_DCHECK(username_attr != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000669 username_ = username_attr->GetString();
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000670 const StunByteStringAttribute* origin_attr =
671 msg->GetByteString(STUN_ATTR_ORIGIN);
672 if (origin_attr) {
673 origin_ = origin_attr->GetString();
674 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000675
676 // Figure out the lifetime and start the allocation timer.
677 int lifetime_secs = ComputeLifetime(msg);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700678 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
679 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000680
Jonas Olssond7d762d2018-03-28 09:47:51 +0200681 RTC_LOG(LS_INFO) << ToString()
682 << ": Created allocation with lifetime=" << lifetime_secs;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000683
684 // We've already validated all the important bits; just send a response here.
685 TurnMessage response;
686 InitResponse(msg, &response);
687
zsteinf42cc9d2017-03-27 16:17:19 -0700688 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
689 STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
690 auto relayed_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
691 STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
692 auto lifetime_attr =
693 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
694 response.AddAttribute(std::move(mapped_addr_attr));
695 response.AddAttribute(std::move(relayed_addr_attr));
696 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000697
698 SendResponse(&response);
699}
700
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000701void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000702 // Figure out the new lifetime.
703 int lifetime_secs = ComputeLifetime(msg);
704
705 // Reset the expiration timer.
706 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700707 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
708 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000709
Jonas Olssond7d762d2018-03-28 09:47:51 +0200710 RTC_LOG(LS_INFO) << ToString()
711 << ": Refreshed allocation, lifetime=" << lifetime_secs;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000712
713 // Send a success response with a LIFETIME attribute.
714 TurnMessage response;
715 InitResponse(msg, &response);
716
zsteinf42cc9d2017-03-27 16:17:19 -0700717 auto lifetime_attr =
718 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
719 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000720
721 SendResponse(&response);
722}
723
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000724void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000725 // Check mandatory attributes.
726 const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
727 const StunAddressAttribute* peer_attr =
728 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
729 if (!data_attr || !peer_attr) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200730 RTC_LOG(LS_WARNING) << ToString()
731 << ": Received invalid send indication";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000732 return;
733 }
734
735 // If a permission exists, send the data on to the peer.
736 if (HasPermission(peer_attr->GetAddress().ipaddr())) {
737 SendExternal(data_attr->bytes(), data_attr->length(),
738 peer_attr->GetAddress());
739 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200740 RTC_LOG(LS_WARNING) << ToString()
741 << ": Received send indication without permission"
742 " peer="
Jonas Olssonabbe8412018-04-03 13:40:05 +0200743 << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000744 }
745}
746
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000747void TurnServerAllocation::HandleCreatePermissionRequest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000748 const TurnMessage* msg) {
749 // Check mandatory attributes.
750 const StunAddressAttribute* peer_attr =
751 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
752 if (!peer_attr) {
753 SendBadRequestResponse(msg);
754 return;
755 }
756
deadbeef376e1232015-11-25 09:00:08 -0800757 if (server_->reject_private_addresses_ &&
758 rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) {
759 SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN);
760 return;
761 }
762
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000763 // Add this permission.
764 AddPermission(peer_attr->GetAddress().ipaddr());
765
Jonas Olssond7d762d2018-03-28 09:47:51 +0200766 RTC_LOG(LS_INFO) << ToString()
Jonas Olssonabbe8412018-04-03 13:40:05 +0200767 << ": Created permission, peer="
768 << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000769
770 // Send a success response.
771 TurnMessage response;
772 InitResponse(msg, &response);
773 SendResponse(&response);
774}
775
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000776void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000777 // Check mandatory attributes.
778 const StunUInt32Attribute* channel_attr =
779 msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
780 const StunAddressAttribute* peer_attr =
781 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
782 if (!channel_attr || !peer_attr) {
783 SendBadRequestResponse(msg);
784 return;
785 }
786
787 // Check that channel id is valid.
788 int channel_id = channel_attr->value() >> 16;
789 if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
790 SendBadRequestResponse(msg);
791 return;
792 }
793
794 // Check that this channel id isn't bound to another transport address, and
795 // that this transport address isn't bound to another channel id.
796 Channel* channel1 = FindChannel(channel_id);
797 Channel* channel2 = FindChannel(peer_attr->GetAddress());
798 if (channel1 != channel2) {
799 SendBadRequestResponse(msg);
800 return;
801 }
802
803 // Add or refresh this channel.
804 if (!channel1) {
805 channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
806 channel1->SignalDestroyed.connect(this,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000807 &TurnServerAllocation::OnChannelDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000808 channels_.push_back(channel1);
809 } else {
810 channel1->Refresh();
811 }
812
813 // Channel binds also refresh permissions.
814 AddPermission(peer_attr->GetAddress().ipaddr());
815
Jonas Olssond7d762d2018-03-28 09:47:51 +0200816 RTC_LOG(LS_INFO) << ToString()
817 << ": Bound channel, id=" << channel_id
Jonas Olssonabbe8412018-04-03 13:40:05 +0200818 << ", peer=" << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000819
820 // Send a success response.
821 TurnMessage response;
822 InitResponse(msg, &response);
823 SendResponse(&response);
824}
825
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000826void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000827 // Extract the channel number from the data.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200828 uint16_t channel_id = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000829 Channel* channel = FindChannel(channel_id);
830 if (channel) {
831 // Send the data to the peer address.
832 SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
833 size - TURN_CHANNEL_HEADER_SIZE, channel->peer());
834 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200835 RTC_LOG(LS_WARNING) << ToString()
836 << ": Received channel data for invalid channel, id="
837 << channel_id;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000838 }
839}
840
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000841void TurnServerAllocation::OnExternalPacket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000842 rtc::AsyncPacketSocket* socket,
843 const char* data, size_t size,
844 const rtc::SocketAddress& addr,
845 const rtc::PacketTime& packet_time) {
nisseede5da42017-01-12 05:15:36 -0800846 RTC_DCHECK(external_socket_.get() == socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000847 Channel* channel = FindChannel(addr);
848 if (channel) {
849 // There is a channel bound to this address. Send as a channel message.
jbauchf1f87202016-03-30 06:43:37 -0700850 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 buf.WriteUInt16(channel->id());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200852 buf.WriteUInt16(static_cast<uint16_t>(size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000853 buf.WriteBytes(data, size);
854 server_->Send(&conn_, buf);
Taylor Brandstetteref184702016-06-23 17:35:47 -0700855 } else if (!server_->enable_permission_checks_ ||
856 HasPermission(addr.ipaddr())) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000857 // No channel, but a permission exists. Send as a data indication.
858 TurnMessage msg;
859 msg.SetType(TURN_DATA_INDICATION);
860 msg.SetTransactionID(
861 rtc::CreateRandomString(kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -0700862 msg.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800863 STUN_ATTR_XOR_PEER_ADDRESS, addr));
zsteinf42cc9d2017-03-27 16:17:19 -0700864 msg.AddAttribute(
865 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000866 server_->SendStun(&conn_, &msg);
867 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200868 RTC_LOG(LS_WARNING)
869 << ToString()
Jonas Olssonabbe8412018-04-03 13:40:05 +0200870 << ": Received external packet without permission, peer="
871 << addr.ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000872 }
873}
874
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000875int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000876 // Return the smaller of our default lifetime and the requested lifetime.
honghaiz34b11eb2016-03-16 08:55:44 -0700877 int lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000878 const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
honghaiz34b11eb2016-03-16 08:55:44 -0700879 if (lifetime_attr && static_cast<int>(lifetime_attr->value()) < lifetime) {
880 lifetime = static_cast<int>(lifetime_attr->value());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000881 }
882 return lifetime;
883}
884
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000885bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000886 return (FindPermission(addr) != NULL);
887}
888
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000889void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000890 Permission* perm = FindPermission(addr);
891 if (!perm) {
892 perm = new Permission(thread_, addr);
893 perm->SignalDestroyed.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000894 this, &TurnServerAllocation::OnPermissionDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000895 perms_.push_back(perm);
896 } else {
897 perm->Refresh();
898 }
899}
900
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000901TurnServerAllocation::Permission* TurnServerAllocation::FindPermission(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000902 const rtc::IPAddress& addr) const {
903 for (PermissionList::const_iterator it = perms_.begin();
904 it != perms_.end(); ++it) {
905 if ((*it)->peer() == addr)
906 return *it;
907 }
908 return NULL;
909}
910
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000911TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
912 int channel_id) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000913 for (ChannelList::const_iterator it = channels_.begin();
914 it != channels_.end(); ++it) {
915 if ((*it)->id() == channel_id)
916 return *it;
917 }
918 return NULL;
919}
920
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000921TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000922 const rtc::SocketAddress& addr) const {
923 for (ChannelList::const_iterator it = channels_.begin();
924 it != channels_.end(); ++it) {
925 if ((*it)->peer() == addr)
926 return *it;
927 }
928 return NULL;
929}
930
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000931void TurnServerAllocation::SendResponse(TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000932 // Success responses always have M-I.
933 msg->AddMessageIntegrity(key_);
934 server_->SendStun(&conn_, msg);
935}
936
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000937void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000938 SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
939}
940
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000941void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, int code,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000942 const std::string& reason) {
943 server_->SendErrorResponse(&conn_, req, code, reason);
944}
945
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000946void TurnServerAllocation::SendExternal(const void* data, size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000947 const rtc::SocketAddress& peer) {
948 rtc::PacketOptions options;
949 external_socket_->SendTo(data, size, peer, options);
950}
951
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000952void TurnServerAllocation::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800953 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000954 SignalDestroyed(this);
955 delete this;
956}
957
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000958void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000959 PermissionList::iterator it = std::find(perms_.begin(), perms_.end(), perm);
nisseede5da42017-01-12 05:15:36 -0800960 RTC_DCHECK(it != perms_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000961 perms_.erase(it);
962}
963
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000964void TurnServerAllocation::OnChannelDestroyed(Channel* channel) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 ChannelList::iterator it =
966 std::find(channels_.begin(), channels_.end(), channel);
nisseede5da42017-01-12 05:15:36 -0800967 RTC_DCHECK(it != channels_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000968 channels_.erase(it);
969}
970
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000971TurnServerAllocation::Permission::Permission(rtc::Thread* thread,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000972 const rtc::IPAddress& peer)
973 : thread_(thread), peer_(peer) {
974 Refresh();
975}
976
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000977TurnServerAllocation::Permission::~Permission() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000978 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
979}
980
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000981void TurnServerAllocation::Permission::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000982 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700983 thread_->PostDelayed(RTC_FROM_HERE, kPermissionTimeout, this,
984 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000985}
986
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000987void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800988 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000989 SignalDestroyed(this);
990 delete this;
991}
992
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000993TurnServerAllocation::Channel::Channel(rtc::Thread* thread, int id,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000994 const rtc::SocketAddress& peer)
995 : thread_(thread), id_(id), peer_(peer) {
996 Refresh();
997}
998
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000999TurnServerAllocation::Channel::~Channel() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001000 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
1001}
1002
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001003void TurnServerAllocation::Channel::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001004 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001005 thread_->PostDelayed(RTC_FROM_HERE, kChannelTimeout, this,
1006 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001007}
1008
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001009void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -08001010 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001011 SignalDestroyed(this);
1012 delete this;
1013}
1014
1015} // namespace cricket