blob: 8f482a309b146d88b49e18712846f87c4db6171e [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "p2p/base/turn_server.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
Steve Antonae226f62019-01-29 12:47:38 -080016#include "absl/algorithm/container.h"
Karl Wiberg918f50c2018-07-05 11:40:33 +020017#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "p2p/base/async_stun_tcp_socket.h"
19#include "p2p/base/packet_socket_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "p2p/base/stun.h"
21#include "rtc_base/bind.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/byte_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/checks.h"
24#include "rtc_base/helpers.h"
25#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/message_digest.h"
27#include "rtc_base/socket_adapters.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020028#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030
31namespace cricket {
32
33// TODO(juberti): Move this all to a future turnmessage.h
Steve Anton6c38cc72017-11-29 10:25:58 -080034// static const int IPPROTO_UDP = 17;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000035static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes
36static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes
37static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes
38static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes
39
40static const int kMinChannelNumber = 0x4000;
41static const int kMaxChannelNumber = 0x7FFF;
42
43static const size_t kNonceKeySize = 16;
honghaiz34b11eb2016-03-16 08:55:44 -070044static const size_t kNonceSize = 48;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000045
46static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
47
48// TODO(mallinath) - Move these to a common place.
Peter Boström0c4e06b2015-10-07 12:23:21 +020049inline bool IsTurnChannelData(uint16_t msg_type) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 // The first two bits of a channel data message are 0b01.
51 return ((msg_type & 0xC000) == 0x4000);
52}
53
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000054// IDs used for posted messages for TurnServerAllocation.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055enum {
56 MSG_ALLOCATION_TIMEOUT,
57};
58
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059// Encapsulates a TURN permission.
60// The object is created when a create permission request is received by an
61// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000062class TurnServerAllocation::Permission : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000063 public:
64 Permission(rtc::Thread* thread, const rtc::IPAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070065 ~Permission() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066
67 const rtc::IPAddress& peer() const { return peer_; }
68 void Refresh();
69
70 sigslot::signal1<Permission*> SignalDestroyed;
71
72 private:
Steve Antonf2737d22017-10-31 16:27:34 -070073 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000074
75 rtc::Thread* thread_;
76 rtc::IPAddress peer_;
77};
78
79// Encapsulates a TURN channel binding.
80// The object is created when a channel bind request is received by an
81// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000082class TurnServerAllocation::Channel : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083 public:
84 Channel(rtc::Thread* thread, int id,
85 const rtc::SocketAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070086 ~Channel() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000087
88 int id() const { return id_; }
89 const rtc::SocketAddress& peer() const { return peer_; }
90 void Refresh();
91
92 sigslot::signal1<Channel*> SignalDestroyed;
93
94 private:
Steve Antonf2737d22017-10-31 16:27:34 -070095 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000096
97 rtc::Thread* thread_;
98 int id_;
99 rtc::SocketAddress peer_;
100};
101
102static bool InitResponse(const StunMessage* req, StunMessage* resp) {
103 int resp_type = (req) ? GetStunSuccessResponseType(req->type()) : -1;
104 if (resp_type == -1)
105 return false;
106 resp->SetType(resp_type);
107 resp->SetTransactionID(req->transaction_id());
108 return true;
109}
110
111static bool InitErrorResponse(const StunMessage* req, int code,
112 const std::string& reason, StunMessage* resp) {
113 int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1;
114 if (resp_type == -1)
115 return false;
116 resp->SetType(resp_type);
117 resp->SetTransactionID(req->transaction_id());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200118 resp->AddAttribute(absl::make_unique<cricket::StunErrorCodeAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800119 STUN_ATTR_ERROR_CODE, code, reason));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000120 return true;
121}
122
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000123
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000124TurnServer::TurnServer(rtc::Thread* thread)
125 : thread_(thread),
126 nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
127 auth_hook_(NULL),
128 redirect_hook_(NULL),
129 enable_otu_nonce_(false) {
130}
131
132TurnServer::~TurnServer() {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200133 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000134 for (InternalSocketMap::iterator it = server_sockets_.begin();
135 it != server_sockets_.end(); ++it) {
136 rtc::AsyncPacketSocket* socket = it->first;
137 delete socket;
138 }
139
140 for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
141 it != server_listen_sockets_.end(); ++it) {
142 rtc::AsyncSocket* socket = it->first;
143 delete socket;
144 }
145}
146
147void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket,
148 ProtocolType proto) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200149 RTC_DCHECK(thread_checker_.IsCurrent());
nisseede5da42017-01-12 05:15:36 -0800150 RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000151 server_sockets_[socket] = proto;
152 socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
153}
154
155void TurnServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
156 ProtocolType proto) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200157 RTC_DCHECK(thread_checker_.IsCurrent());
nisseede5da42017-01-12 05:15:36 -0800158 RTC_DCHECK(server_listen_sockets_.end() ==
159 server_listen_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160 server_listen_sockets_[socket] = proto;
161 socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
162}
163
164void TurnServer::SetExternalSocketFactory(
165 rtc::PacketSocketFactory* factory,
166 const rtc::SocketAddress& external_addr) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200167 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000168 external_socket_factory_.reset(factory);
169 external_addr_ = external_addr;
170}
171
172void TurnServer::OnNewInternalConnection(rtc::AsyncSocket* socket) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200173 RTC_DCHECK(thread_checker_.IsCurrent());
nisseede5da42017-01-12 05:15:36 -0800174 RTC_DCHECK(server_listen_sockets_.find(socket) !=
175 server_listen_sockets_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000176 AcceptConnection(socket);
177}
178
179void TurnServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200180 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000181 // Check if someone is trying to connect to us.
182 rtc::SocketAddress accept_addr;
183 rtc::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr);
184 if (accepted_socket != NULL) {
185 ProtocolType proto = server_listen_sockets_[server_socket];
186 cricket::AsyncStunTCPSocket* tcp_socket =
187 new cricket::AsyncStunTCPSocket(accepted_socket, false);
188
189 tcp_socket->SignalClose.connect(this, &TurnServer::OnInternalSocketClose);
190 // Finally add the socket so it can start communicating with the client.
191 AddInternalSocket(tcp_socket, proto);
192 }
193}
194
195void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket,
196 int err) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200197 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000198 DestroyInternalSocket(socket);
199}
200
201void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket,
Niels Möllere6933812018-11-05 13:01:41 +0100202 const char* data,
203 size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000204 const rtc::SocketAddress& addr,
Niels Möllere6933812018-11-05 13:01:41 +0100205 const int64_t& /* packet_time_us */) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200206 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000207 // Fail if the packet is too small to even contain a channel header.
208 if (size < TURN_CHANNEL_HEADER_SIZE) {
Steve Anton6c38cc72017-11-29 10:25:58 -0800209 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000210 }
211 InternalSocketMap::iterator iter = server_sockets_.find(socket);
nisseede5da42017-01-12 05:15:36 -0800212 RTC_DCHECK(iter != server_sockets_.end());
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000213 TurnServerConnection conn(addr, iter->second, socket);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200214 uint16_t msg_type = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000215 if (!IsTurnChannelData(msg_type)) {
216 // This is a STUN message.
217 HandleStunMessage(&conn, data, size);
218 } else {
219 // This is a channel message; let the allocation handle it.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000220 TurnServerAllocation* allocation = FindAllocation(&conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000221 if (allocation) {
222 allocation->HandleChannelData(data, size);
223 }
Jonas Orelandbdcee282017-10-10 14:01:40 +0200224 if (stun_message_observer_ != nullptr) {
225 stun_message_observer_->ReceivedChannelData(data, size);
226 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000227 }
228}
229
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000230void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000231 size_t size) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200232 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000233 TurnMessage msg;
jbauchf1f87202016-03-30 06:43:37 -0700234 rtc::ByteBufferReader buf(data, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000235 if (!msg.Read(&buf) || (buf.Length() > 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100236 RTC_LOG(LS_WARNING) << "Received invalid STUN message";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000237 return;
238 }
239
Jonas Orelandbdcee282017-10-10 14:01:40 +0200240 if (stun_message_observer_ != nullptr) {
241 stun_message_observer_->ReceivedMessage(&msg);
242 }
243
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000244 // If it's a STUN binding request, handle that specially.
245 if (msg.type() == STUN_BINDING_REQUEST) {
246 HandleBindingRequest(conn, &msg);
247 return;
248 }
249
250 if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
251 rtc::SocketAddress address;
252 if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
253 SendErrorResponseWithAlternateServer(
254 conn, &msg, address);
255 return;
256 }
257 }
258
259 // Look up the key that we'll use to validate the M-I. If we have an
260 // existing allocation, the key will already be cached.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000261 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000262 std::string key;
263 if (!allocation) {
264 GetKey(&msg, &key);
265 } else {
266 key = allocation->key();
267 }
268
269 // Ensure the message is authorized; only needed for requests.
270 if (IsStunRequestType(msg.type())) {
271 if (!CheckAuthorization(conn, &msg, data, size, key)) {
272 return;
273 }
274 }
275
276 if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
277 HandleAllocateRequest(conn, &msg, key);
278 } else if (allocation &&
279 (msg.type() != STUN_ALLOCATE_REQUEST ||
280 msg.transaction_id() == allocation->transaction_id())) {
281 // This is a non-allocate request, or a retransmit of an allocate.
282 // Check that the username matches the previous username used.
283 if (IsStunRequestType(msg.type()) &&
284 msg.GetByteString(STUN_ATTR_USERNAME)->GetString() !=
285 allocation->username()) {
286 SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
287 STUN_ERROR_REASON_WRONG_CREDENTIALS);
288 return;
289 }
290 allocation->HandleTurnMessage(&msg);
291 } else {
292 // Allocation mismatch.
293 SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
294 STUN_ERROR_REASON_ALLOCATION_MISMATCH);
295 }
296}
297
298bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200299 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000300 const StunByteStringAttribute* username_attr =
301 msg->GetByteString(STUN_ATTR_USERNAME);
302 if (!username_attr) {
303 return false;
304 }
305
306 std::string username = username_attr->GetString();
307 return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
308}
309
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000310bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000311 const StunMessage* msg,
312 const char* data, size_t size,
313 const std::string& key) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200314 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000315 // RFC 5389, 10.2.2.
nisseede5da42017-01-12 05:15:36 -0800316 RTC_DCHECK(IsStunRequestType(msg->type()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000317 const StunByteStringAttribute* mi_attr =
318 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
319 const StunByteStringAttribute* username_attr =
320 msg->GetByteString(STUN_ATTR_USERNAME);
321 const StunByteStringAttribute* realm_attr =
322 msg->GetByteString(STUN_ATTR_REALM);
323 const StunByteStringAttribute* nonce_attr =
324 msg->GetByteString(STUN_ATTR_NONCE);
325
326 // Fail if no M-I.
327 if (!mi_attr) {
328 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
329 STUN_ERROR_REASON_UNAUTHORIZED);
330 return false;
331 }
332
333 // Fail if there is M-I but no username, nonce, or realm.
334 if (!username_attr || !realm_attr || !nonce_attr) {
335 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
336 STUN_ERROR_REASON_BAD_REQUEST);
337 return false;
338 }
339
340 // Fail if bad nonce.
341 if (!ValidateNonce(nonce_attr->GetString())) {
342 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
343 STUN_ERROR_REASON_STALE_NONCE);
344 return false;
345 }
346
347 // Fail if bad username or M-I.
348 // We need |data| and |size| for the call to ValidateMessageIntegrity.
349 if (key.empty() || !StunMessage::ValidateMessageIntegrity(data, size, key)) {
350 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
351 STUN_ERROR_REASON_UNAUTHORIZED);
352 return false;
353 }
354
355 // Fail if one-time-use nonce feature is enabled.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000356 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000357 if (enable_otu_nonce_ && allocation &&
358 allocation->last_nonce() == nonce_attr->GetString()) {
359 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
360 STUN_ERROR_REASON_STALE_NONCE);
361 return false;
362 }
363
364 if (allocation) {
365 allocation->set_last_nonce(nonce_attr->GetString());
366 }
367 // Success.
368 return true;
369}
370
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000371void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000372 const StunMessage* req) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200373 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000374 StunMessage response;
375 InitResponse(req, &response);
376
377 // Tell the user the address that we received their request from.
Karl Wiberg918f50c2018-07-05 11:40:33 +0200378 auto mapped_addr_attr = absl::make_unique<StunXorAddressAttribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000379 STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
zsteinf42cc9d2017-03-27 16:17:19 -0700380 response.AddAttribute(std::move(mapped_addr_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000381
382 SendStun(conn, &response);
383}
384
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000385void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000386 const TurnMessage* msg,
387 const std::string& key) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200388 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000389 // Check the parameters in the request.
390 const StunUInt32Attribute* transport_attr =
391 msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
392 if (!transport_attr) {
393 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
394 STUN_ERROR_REASON_BAD_REQUEST);
395 return;
396 }
397
398 // Only UDP is supported right now.
399 int proto = transport_attr->value() >> 24;
400 if (proto != IPPROTO_UDP) {
401 SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
402 STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
403 return;
404 }
405
406 // Create the allocation and let it send the success response.
407 // If the actual socket allocation fails, send an internal error.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000408 TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409 if (alloc) {
410 alloc->HandleTurnMessage(msg);
411 } else {
412 SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
413 "Failed to allocate socket");
414 }
415}
416
honghaiz34b11eb2016-03-16 08:55:44 -0700417std::string TurnServer::GenerateNonce(int64_t now) const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200418 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000419 // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000420 std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
421 std::string nonce = rtc::hex_encode(input.c_str(), input.size());
422 nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
nisseede5da42017-01-12 05:15:36 -0800423 RTC_DCHECK(nonce.size() == kNonceSize);
honghaiz34b11eb2016-03-16 08:55:44 -0700424
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000425 return nonce;
426}
427
428bool TurnServer::ValidateNonce(const std::string& nonce) const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200429 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000430 // Check the size.
431 if (nonce.size() != kNonceSize) {
432 return false;
433 }
434
435 // Decode the timestamp.
honghaiz34b11eb2016-03-16 08:55:44 -0700436 int64_t then;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000437 char* p = reinterpret_cast<char*>(&then);
438 size_t len = rtc::hex_decode(p, sizeof(then),
439 nonce.substr(0, sizeof(then) * 2));
440 if (len != sizeof(then)) {
441 return false;
442 }
443
444 // Verify the HMAC.
445 if (nonce.substr(sizeof(then) * 2) != rtc::ComputeHmac(
446 rtc::DIGEST_MD5, nonce_key_, std::string(p, sizeof(then)))) {
447 return false;
448 }
449
450 // Validate the timestamp.
nisse1bffc1d2016-05-02 08:18:55 -0700451 return rtc::TimeMillis() - then < kNonceTimeout;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000452}
453
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000454TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200455 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000456 AllocationMap::const_iterator it = allocations_.find(*conn);
deadbeef97943662016-07-12 11:04:50 -0700457 return (it != allocations_.end()) ? it->second.get() : nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000458}
459
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000460TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
461 int proto,
462 const std::string& key) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200463 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000464 rtc::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
465 external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
466 if (!external_socket) {
467 return NULL;
468 }
469
470 // The Allocation takes ownership of the socket.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000471 TurnServerAllocation* allocation = new TurnServerAllocation(this,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000472 thread_, *conn, external_socket, key);
473 allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
deadbeef97943662016-07-12 11:04:50 -0700474 allocations_[*conn].reset(allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000475 return allocation;
476}
477
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000478void TurnServer::SendErrorResponse(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000479 const StunMessage* req,
480 int code, const std::string& reason) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200481 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000482 TurnMessage resp;
483 InitErrorResponse(req, code, reason, &resp);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100484 RTC_LOG(LS_INFO) << "Sending error response, type=" << resp.type()
485 << ", code=" << code << ", reason=" << reason;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000486 SendStun(conn, &resp);
487}
488
489void TurnServer::SendErrorResponseWithRealmAndNonce(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000490 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000491 int code, const std::string& reason) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200492 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000493 TurnMessage resp;
494 InitErrorResponse(msg, code, reason, &resp);
honghaizc463e202016-02-01 15:19:08 -0800495
nisse1bffc1d2016-05-02 08:18:55 -0700496 int64_t timestamp = rtc::TimeMillis();
honghaizc463e202016-02-01 15:19:08 -0800497 if (ts_for_next_nonce_) {
498 timestamp = ts_for_next_nonce_;
499 ts_for_next_nonce_ = 0;
500 }
Karl Wiberg918f50c2018-07-05 11:40:33 +0200501 resp.AddAttribute(absl::make_unique<StunByteStringAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -0700502 STUN_ATTR_NONCE, GenerateNonce(timestamp)));
nissecc99bc22017-02-02 01:31:30 -0800503 resp.AddAttribute(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200504 absl::make_unique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000505 SendStun(conn, &resp);
506}
507
508void TurnServer::SendErrorResponseWithAlternateServer(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000509 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000510 const rtc::SocketAddress& addr) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200511 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000512 TurnMessage resp;
513 InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
514 STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
Karl Wiberg918f50c2018-07-05 11:40:33 +0200515 resp.AddAttribute(absl::make_unique<StunAddressAttribute>(
516 STUN_ATTR_ALTERNATE_SERVER, addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000517 SendStun(conn, &resp);
518}
519
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000520void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200521 RTC_DCHECK(thread_checker_.IsCurrent());
jbauchf1f87202016-03-30 06:43:37 -0700522 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000523 // Add a SOFTWARE attribute if one is set.
524 if (!software_.empty()) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200525 msg->AddAttribute(absl::make_unique<StunByteStringAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -0700526 STUN_ATTR_SOFTWARE, software_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000527 }
528 msg->Write(&buf);
529 Send(conn, buf);
530}
531
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000532void TurnServer::Send(TurnServerConnection* conn,
jbauchf1f87202016-03-30 06:43:37 -0700533 const rtc::ByteBufferWriter& buf) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200534 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000535 rtc::PacketOptions options;
536 conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
537}
538
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000539void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200540 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000541 // Removing the internal socket if the connection is not udp.
542 rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
543 InternalSocketMap::iterator iter = server_sockets_.find(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000544 // Skip if the socket serving this allocation is UDP, as this will be shared
545 // by all allocations.
Taylor Brandstetter716d07a2016-06-27 14:07:41 -0700546 // Note: We may not find a socket if it's a TCP socket that was closed, and
547 // the allocation is only now timing out.
548 if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000549 DestroyInternalSocket(socket);
550 }
551
552 AllocationMap::iterator it = allocations_.find(*(allocation->conn()));
deadbeef97943662016-07-12 11:04:50 -0700553 if (it != allocations_.end()) {
554 it->second.release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000555 allocations_.erase(it);
deadbeef97943662016-07-12 11:04:50 -0700556 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000557}
558
559void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200560 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000561 InternalSocketMap::iterator iter = server_sockets_.find(socket);
562 if (iter != server_sockets_.end()) {
563 rtc::AsyncPacketSocket* socket = iter->first;
Qingsi Wang0ea75152018-07-02 10:48:25 -0700564 socket->SignalReadPacket.disconnect(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000565 server_sockets_.erase(iter);
deadbeef824f5862016-08-24 15:06:53 -0700566 // We must destroy the socket async to avoid invalidating the sigslot
567 // callback list iterator inside a sigslot callback. (In other words,
568 // deleting an object from within a callback from that object).
569 sockets_to_delete_.push_back(
570 std::unique_ptr<rtc::AsyncPacketSocket>(socket));
571 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, rtc::Thread::Current(),
572 rtc::Bind(&TurnServer::FreeSockets, this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000573 }
574}
575
deadbeef824f5862016-08-24 15:06:53 -0700576void TurnServer::FreeSockets() {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200577 RTC_DCHECK(thread_checker_.IsCurrent());
deadbeef824f5862016-08-24 15:06:53 -0700578 sockets_to_delete_.clear();
579}
580
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000581TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
582 ProtocolType proto,
583 rtc::AsyncPacketSocket* socket)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000584 : src_(src),
585 dst_(socket->GetRemoteAddress()),
586 proto_(proto),
587 socket_(socket) {
588}
589
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000590bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000591 return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
592}
593
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000594bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
Taylor Brandstetter734262c2016-08-01 16:37:14 -0700595 return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000596}
597
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000598std::string TurnServerConnection::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000599 const char* const kProtos[] = {
600 "unknown", "udp", "tcp", "ssltcp"
601 };
Jonas Olsson366a50c2018-09-06 13:41:30 +0200602 rtc::StringBuilder ost;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000603 ost << src_.ToString() << "-" << dst_.ToString() << ":"<< kProtos[proto_];
Jonas Olsson84df1c72018-09-14 16:59:32 +0200604 return ost.Release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000605}
606
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000607TurnServerAllocation::TurnServerAllocation(TurnServer* server,
608 rtc::Thread* thread,
609 const TurnServerConnection& conn,
610 rtc::AsyncPacketSocket* socket,
611 const std::string& key)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000612 : server_(server),
613 thread_(thread),
614 conn_(conn),
615 external_socket_(socket),
616 key_(key) {
617 external_socket_->SignalReadPacket.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000618 this, &TurnServerAllocation::OnExternalPacket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000619}
620
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000621TurnServerAllocation::~TurnServerAllocation() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000622 for (ChannelList::iterator it = channels_.begin();
623 it != channels_.end(); ++it) {
624 delete *it;
625 }
626 for (PermissionList::iterator it = perms_.begin();
627 it != perms_.end(); ++it) {
628 delete *it;
629 }
630 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Jonas Olssond7d762d2018-03-28 09:47:51 +0200631 RTC_LOG(LS_INFO) << ToString() << ": Allocation destroyed";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000632}
633
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000634std::string TurnServerAllocation::ToString() const {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200635 rtc::StringBuilder ost;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000636 ost << "Alloc[" << conn_.ToString() << "]";
Jonas Olsson84df1c72018-09-14 16:59:32 +0200637 return ost.Release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000638}
639
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000640void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
nisseede5da42017-01-12 05:15:36 -0800641 RTC_DCHECK(msg != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000642 switch (msg->type()) {
643 case STUN_ALLOCATE_REQUEST:
644 HandleAllocateRequest(msg);
645 break;
646 case TURN_REFRESH_REQUEST:
647 HandleRefreshRequest(msg);
648 break;
649 case TURN_SEND_INDICATION:
650 HandleSendIndication(msg);
651 break;
652 case TURN_CREATE_PERMISSION_REQUEST:
653 HandleCreatePermissionRequest(msg);
654 break;
655 case TURN_CHANNEL_BIND_REQUEST:
656 HandleChannelBindRequest(msg);
657 break;
658 default:
659 // Not sure what to do with this, just eat it.
Jonas Olssond7d762d2018-03-28 09:47:51 +0200660 RTC_LOG(LS_WARNING) << ToString()
661 << ": Invalid TURN message type received: "
662 << msg->type();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000663 }
664}
665
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000666void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000667 // Copy the important info from the allocate request.
668 transaction_id_ = msg->transaction_id();
669 const StunByteStringAttribute* username_attr =
670 msg->GetByteString(STUN_ATTR_USERNAME);
nisseede5da42017-01-12 05:15:36 -0800671 RTC_DCHECK(username_attr != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000672 username_ = username_attr->GetString();
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000673 const StunByteStringAttribute* origin_attr =
674 msg->GetByteString(STUN_ATTR_ORIGIN);
675 if (origin_attr) {
676 origin_ = origin_attr->GetString();
677 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000678
679 // Figure out the lifetime and start the allocation timer.
680 int lifetime_secs = ComputeLifetime(msg);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700681 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
682 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000683
Jonas Olssond7d762d2018-03-28 09:47:51 +0200684 RTC_LOG(LS_INFO) << ToString()
685 << ": Created allocation with lifetime=" << lifetime_secs;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000686
687 // We've already validated all the important bits; just send a response here.
688 TurnMessage response;
689 InitResponse(msg, &response);
690
Karl Wiberg918f50c2018-07-05 11:40:33 +0200691 auto mapped_addr_attr = absl::make_unique<StunXorAddressAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -0700692 STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200693 auto relayed_addr_attr = absl::make_unique<StunXorAddressAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -0700694 STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
695 auto lifetime_attr =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200696 absl::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
zsteinf42cc9d2017-03-27 16:17:19 -0700697 response.AddAttribute(std::move(mapped_addr_attr));
698 response.AddAttribute(std::move(relayed_addr_attr));
699 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000700
701 SendResponse(&response);
702}
703
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000704void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000705 // Figure out the new lifetime.
706 int lifetime_secs = ComputeLifetime(msg);
707
708 // Reset the expiration timer.
709 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700710 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
711 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000712
Jonas Olssond7d762d2018-03-28 09:47:51 +0200713 RTC_LOG(LS_INFO) << ToString()
714 << ": Refreshed allocation, lifetime=" << lifetime_secs;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000715
716 // Send a success response with a LIFETIME attribute.
717 TurnMessage response;
718 InitResponse(msg, &response);
719
zsteinf42cc9d2017-03-27 16:17:19 -0700720 auto lifetime_attr =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200721 absl::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
zsteinf42cc9d2017-03-27 16:17:19 -0700722 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000723
724 SendResponse(&response);
725}
726
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000727void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000728 // Check mandatory attributes.
729 const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
730 const StunAddressAttribute* peer_attr =
731 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
732 if (!data_attr || !peer_attr) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200733 RTC_LOG(LS_WARNING) << ToString()
734 << ": Received invalid send indication";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000735 return;
736 }
737
738 // If a permission exists, send the data on to the peer.
739 if (HasPermission(peer_attr->GetAddress().ipaddr())) {
740 SendExternal(data_attr->bytes(), data_attr->length(),
741 peer_attr->GetAddress());
742 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200743 RTC_LOG(LS_WARNING) << ToString()
744 << ": Received send indication without permission"
745 " peer="
Jonas Olssonabbe8412018-04-03 13:40:05 +0200746 << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000747 }
748}
749
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000750void TurnServerAllocation::HandleCreatePermissionRequest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000751 const TurnMessage* msg) {
752 // Check mandatory attributes.
753 const StunAddressAttribute* peer_attr =
754 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
755 if (!peer_attr) {
756 SendBadRequestResponse(msg);
757 return;
758 }
759
deadbeef376e1232015-11-25 09:00:08 -0800760 if (server_->reject_private_addresses_ &&
761 rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) {
762 SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN);
763 return;
764 }
765
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000766 // Add this permission.
767 AddPermission(peer_attr->GetAddress().ipaddr());
768
Jonas Olssond7d762d2018-03-28 09:47:51 +0200769 RTC_LOG(LS_INFO) << ToString()
Jonas Olssonabbe8412018-04-03 13:40:05 +0200770 << ": Created permission, peer="
771 << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000772
773 // Send a success response.
774 TurnMessage response;
775 InitResponse(msg, &response);
776 SendResponse(&response);
777}
778
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000779void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000780 // Check mandatory attributes.
781 const StunUInt32Attribute* channel_attr =
782 msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
783 const StunAddressAttribute* peer_attr =
784 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
785 if (!channel_attr || !peer_attr) {
786 SendBadRequestResponse(msg);
787 return;
788 }
789
790 // Check that channel id is valid.
791 int channel_id = channel_attr->value() >> 16;
792 if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
793 SendBadRequestResponse(msg);
794 return;
795 }
796
797 // Check that this channel id isn't bound to another transport address, and
798 // that this transport address isn't bound to another channel id.
799 Channel* channel1 = FindChannel(channel_id);
800 Channel* channel2 = FindChannel(peer_attr->GetAddress());
801 if (channel1 != channel2) {
802 SendBadRequestResponse(msg);
803 return;
804 }
805
806 // Add or refresh this channel.
807 if (!channel1) {
808 channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
809 channel1->SignalDestroyed.connect(this,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000810 &TurnServerAllocation::OnChannelDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000811 channels_.push_back(channel1);
812 } else {
813 channel1->Refresh();
814 }
815
816 // Channel binds also refresh permissions.
817 AddPermission(peer_attr->GetAddress().ipaddr());
818
Jonas Olssond7d762d2018-03-28 09:47:51 +0200819 RTC_LOG(LS_INFO) << ToString()
820 << ": Bound channel, id=" << channel_id
Jonas Olssonabbe8412018-04-03 13:40:05 +0200821 << ", peer=" << peer_attr->GetAddress().ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000822
823 // Send a success response.
824 TurnMessage response;
825 InitResponse(msg, &response);
826 SendResponse(&response);
827}
828
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000829void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000830 // Extract the channel number from the data.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200831 uint16_t channel_id = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000832 Channel* channel = FindChannel(channel_id);
833 if (channel) {
834 // Send the data to the peer address.
835 SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
836 size - TURN_CHANNEL_HEADER_SIZE, channel->peer());
837 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200838 RTC_LOG(LS_WARNING) << ToString()
839 << ": Received channel data for invalid channel, id="
840 << channel_id;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000841 }
842}
843
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000844void TurnServerAllocation::OnExternalPacket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000845 rtc::AsyncPacketSocket* socket,
Niels Möllere6933812018-11-05 13:01:41 +0100846 const char* data,
847 size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000848 const rtc::SocketAddress& addr,
Niels Möllere6933812018-11-05 13:01:41 +0100849 const int64_t& /* packet_time_us */) {
nisseede5da42017-01-12 05:15:36 -0800850 RTC_DCHECK(external_socket_.get() == socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 Channel* channel = FindChannel(addr);
852 if (channel) {
853 // There is a channel bound to this address. Send as a channel message.
jbauchf1f87202016-03-30 06:43:37 -0700854 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000855 buf.WriteUInt16(channel->id());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200856 buf.WriteUInt16(static_cast<uint16_t>(size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000857 buf.WriteBytes(data, size);
858 server_->Send(&conn_, buf);
Taylor Brandstetteref184702016-06-23 17:35:47 -0700859 } else if (!server_->enable_permission_checks_ ||
860 HasPermission(addr.ipaddr())) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000861 // No channel, but a permission exists. Send as a data indication.
862 TurnMessage msg;
863 msg.SetType(TURN_DATA_INDICATION);
864 msg.SetTransactionID(
865 rtc::CreateRandomString(kStunTransactionIdLength));
Karl Wiberg918f50c2018-07-05 11:40:33 +0200866 msg.AddAttribute(absl::make_unique<StunXorAddressAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800867 STUN_ATTR_XOR_PEER_ADDRESS, addr));
zsteinf42cc9d2017-03-27 16:17:19 -0700868 msg.AddAttribute(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200869 absl::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000870 server_->SendStun(&conn_, &msg);
871 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200872 RTC_LOG(LS_WARNING)
873 << ToString()
Jonas Olssonabbe8412018-04-03 13:40:05 +0200874 << ": Received external packet without permission, peer="
875 << addr.ToString();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000876 }
877}
878
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000879int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880 // Return the smaller of our default lifetime and the requested lifetime.
honghaiz34b11eb2016-03-16 08:55:44 -0700881 int lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000882 const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
honghaiz34b11eb2016-03-16 08:55:44 -0700883 if (lifetime_attr && static_cast<int>(lifetime_attr->value()) < lifetime) {
884 lifetime = static_cast<int>(lifetime_attr->value());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000885 }
886 return lifetime;
887}
888
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000889bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000890 return (FindPermission(addr) != NULL);
891}
892
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000893void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000894 Permission* perm = FindPermission(addr);
895 if (!perm) {
896 perm = new Permission(thread_, addr);
897 perm->SignalDestroyed.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000898 this, &TurnServerAllocation::OnPermissionDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000899 perms_.push_back(perm);
900 } else {
901 perm->Refresh();
902 }
903}
904
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000905TurnServerAllocation::Permission* TurnServerAllocation::FindPermission(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 const rtc::IPAddress& addr) const {
907 for (PermissionList::const_iterator it = perms_.begin();
908 it != perms_.end(); ++it) {
909 if ((*it)->peer() == addr)
910 return *it;
911 }
912 return NULL;
913}
914
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000915TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
916 int channel_id) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000917 for (ChannelList::const_iterator it = channels_.begin();
918 it != channels_.end(); ++it) {
919 if ((*it)->id() == channel_id)
920 return *it;
921 }
922 return NULL;
923}
924
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000925TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000926 const rtc::SocketAddress& addr) const {
927 for (ChannelList::const_iterator it = channels_.begin();
928 it != channels_.end(); ++it) {
929 if ((*it)->peer() == addr)
930 return *it;
931 }
932 return NULL;
933}
934
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000935void TurnServerAllocation::SendResponse(TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 // Success responses always have M-I.
937 msg->AddMessageIntegrity(key_);
938 server_->SendStun(&conn_, msg);
939}
940
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000941void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000942 SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
943}
944
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000945void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, int code,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000946 const std::string& reason) {
947 server_->SendErrorResponse(&conn_, req, code, reason);
948}
949
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000950void TurnServerAllocation::SendExternal(const void* data, size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000951 const rtc::SocketAddress& peer) {
952 rtc::PacketOptions options;
953 external_socket_->SendTo(data, size, peer, options);
954}
955
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000956void TurnServerAllocation::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800957 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000958 SignalDestroyed(this);
959 delete this;
960}
961
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000962void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) {
Steve Antonae226f62019-01-29 12:47:38 -0800963 auto it = absl::c_find(perms_, perm);
nisseede5da42017-01-12 05:15:36 -0800964 RTC_DCHECK(it != perms_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 perms_.erase(it);
966}
967
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000968void TurnServerAllocation::OnChannelDestroyed(Channel* channel) {
Steve Antonae226f62019-01-29 12:47:38 -0800969 auto it = absl::c_find(channels_, channel);
nisseede5da42017-01-12 05:15:36 -0800970 RTC_DCHECK(it != channels_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000971 channels_.erase(it);
972}
973
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000974TurnServerAllocation::Permission::Permission(rtc::Thread* thread,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000975 const rtc::IPAddress& peer)
976 : thread_(thread), peer_(peer) {
977 Refresh();
978}
979
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000980TurnServerAllocation::Permission::~Permission() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000981 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
982}
983
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000984void TurnServerAllocation::Permission::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000985 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700986 thread_->PostDelayed(RTC_FROM_HERE, kPermissionTimeout, this,
987 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000988}
989
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000990void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800991 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000992 SignalDestroyed(this);
993 delete this;
994}
995
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000996TurnServerAllocation::Channel::Channel(rtc::Thread* thread, int id,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000997 const rtc::SocketAddress& peer)
998 : thread_(thread), id_(id), peer_(peer) {
999 Refresh();
1000}
1001
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001002TurnServerAllocation::Channel::~Channel() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001003 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
1004}
1005
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001006void TurnServerAllocation::Channel::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001007 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001008 thread_->PostDelayed(RTC_FROM_HERE, kChannelTimeout, this,
1009 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001010}
1011
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001012void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -08001013 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001014 SignalDestroyed(this);
1015 delete this;
1016}
1017
1018} // namespace cricket