blob: ca856448b3f902deaca1e4e5ec459d932b39ae58 [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#ifndef P2P_BASE_TURN_SERVER_H_
12#define P2P_BASE_TURN_SERVER_H_
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
14#include <list>
15#include <map>
kwiberg3ec46792016-04-27 07:22:53 -070016#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000017#include <set>
18#include <string>
Steve Anton6c38cc72017-11-29 10:25:58 -080019#include <utility>
deadbeef824f5862016-08-24 15:06:53 -070020#include <vector>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021
Steve Anton10542f22019-01-11 09:11:00 -080022#include "p2p/base/port_interface.h"
23#include "rtc_base/async_invoker.h"
24#include "rtc_base/async_packet_socket.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/socket_address.h"
Artem Titove41c4332018-07-25 15:04:28 +020026#include "rtc_base/third_party/sigslot/sigslot.h"
Sebastian Jansson4db28b52020-01-08 14:07:15 +010027#include "rtc_base/thread.h"
Seth Hampsonaed71642018-06-11 07:41:32 -070028#include "rtc_base/thread_checker.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000029
30namespace rtc {
jbauchf1f87202016-03-30 06:43:37 -070031class ByteBufferWriter;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000032class PacketSocketFactory;
Jonas Olssona4d87372019-07-05 19:08:33 +020033} // namespace rtc
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000034
35namespace cricket {
36
37class StunMessage;
38class TurnMessage;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000039class TurnServer;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000040
41// The default server port for TURN, as specified in RFC5766.
42const int TURN_SERVER_PORT = 3478;
43
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000044// Encapsulates the client's connection to the server.
45class TurnServerConnection {
46 public:
47 TurnServerConnection() : proto_(PROTO_UDP), socket_(NULL) {}
48 TurnServerConnection(const rtc::SocketAddress& src,
49 ProtocolType proto,
50 rtc::AsyncPacketSocket* socket);
51 const rtc::SocketAddress& src() const { return src_; }
52 rtc::AsyncPacketSocket* socket() { return socket_; }
53 bool operator==(const TurnServerConnection& t) const;
54 bool operator<(const TurnServerConnection& t) const;
55 std::string ToString() const;
56
57 private:
58 rtc::SocketAddress src_;
59 rtc::SocketAddress dst_;
60 cricket::ProtocolType proto_;
61 rtc::AsyncPacketSocket* socket_;
62};
63
64// Encapsulates a TURN allocation.
65// The object is created when an allocation request is received, and then
66// handles TURN messages (via HandleTurnMessage) and channel data messages
67// (via HandleChannelData) for this allocation when received by the server.
68// The object self-deletes and informs the server if its lifetime timer expires.
Tomas Gunnarssonabdb4702020-09-05 18:43:36 +020069class TurnServerAllocation : public rtc::MessageHandlerAutoCleanup,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000070 public sigslot::has_slots<> {
71 public:
72 TurnServerAllocation(TurnServer* server_,
73 rtc::Thread* thread,
74 const TurnServerConnection& conn,
75 rtc::AsyncPacketSocket* server_socket,
76 const std::string& key);
Steve Antonf2737d22017-10-31 16:27:34 -070077 ~TurnServerAllocation() override;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000078
79 TurnServerConnection* conn() { return &conn_; }
80 const std::string& key() const { return key_; }
81 const std::string& transaction_id() const { return transaction_id_; }
82 const std::string& username() const { return username_; }
83 const std::string& origin() const { return origin_; }
84 const std::string& last_nonce() const { return last_nonce_; }
85 void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
86
87 std::string ToString() const;
88
89 void HandleTurnMessage(const TurnMessage* msg);
90 void HandleChannelData(const char* data, size_t size);
91
92 sigslot::signal1<TurnServerAllocation*> SignalDestroyed;
93
94 private:
95 class Channel;
96 class Permission;
97 typedef std::list<Permission*> PermissionList;
98 typedef std::list<Channel*> ChannelList;
99
100 void HandleAllocateRequest(const TurnMessage* msg);
101 void HandleRefreshRequest(const TurnMessage* msg);
102 void HandleSendIndication(const TurnMessage* msg);
103 void HandleCreatePermissionRequest(const TurnMessage* msg);
104 void HandleChannelBindRequest(const TurnMessage* msg);
105
106 void OnExternalPacket(rtc::AsyncPacketSocket* socket,
Niels Möllere6933812018-11-05 13:01:41 +0100107 const char* data,
108 size_t size,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000109 const rtc::SocketAddress& addr,
Niels Möllere6933812018-11-05 13:01:41 +0100110 const int64_t& packet_time_us);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000111
112 static int ComputeLifetime(const TurnMessage* msg);
113 bool HasPermission(const rtc::IPAddress& addr);
114 void AddPermission(const rtc::IPAddress& addr);
115 Permission* FindPermission(const rtc::IPAddress& addr) const;
116 Channel* FindChannel(int channel_id) const;
117 Channel* FindChannel(const rtc::SocketAddress& addr) const;
118
119 void SendResponse(TurnMessage* msg);
120 void SendBadRequestResponse(const TurnMessage* req);
Jonas Olssona4d87372019-07-05 19:08:33 +0200121 void SendErrorResponse(const TurnMessage* req,
122 int code,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000123 const std::string& reason);
Jonas Olssona4d87372019-07-05 19:08:33 +0200124 void SendExternal(const void* data,
125 size_t size,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000126 const rtc::SocketAddress& peer);
127
128 void OnPermissionDestroyed(Permission* perm);
129 void OnChannelDestroyed(Channel* channel);
Steve Antonf2737d22017-10-31 16:27:34 -0700130 void OnMessage(rtc::Message* msg) override;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000131
132 TurnServer* server_;
133 rtc::Thread* thread_;
134 TurnServerConnection conn_;
kwiberg3ec46792016-04-27 07:22:53 -0700135 std::unique_ptr<rtc::AsyncPacketSocket> external_socket_;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000136 std::string key_;
137 std::string transaction_id_;
138 std::string username_;
139 std::string origin_;
140 std::string last_nonce_;
141 PermissionList perms_;
142 ChannelList channels_;
143};
144
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000145// An interface through which the MD5 credential hash can be retrieved.
146class TurnAuthInterface {
147 public:
148 // Gets HA1 for the specified user and realm.
149 // HA1 = MD5(A1) = MD5(username:realm:password).
150 // Return true if the given username and realm are valid, or false if not.
Jonas Olssona4d87372019-07-05 19:08:33 +0200151 virtual bool GetKey(const std::string& username,
152 const std::string& realm,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000153 std::string* key) = 0;
Henrik Kjellander3fe372d2016-05-12 08:10:52 +0200154 virtual ~TurnAuthInterface() = default;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000155};
156
157// An interface enables Turn Server to control redirection behavior.
158class TurnRedirectInterface {
159 public:
160 virtual bool ShouldRedirect(const rtc::SocketAddress& address,
161 rtc::SocketAddress* out) = 0;
162 virtual ~TurnRedirectInterface() {}
163};
164
Jonas Orelandbdcee282017-10-10 14:01:40 +0200165class StunMessageObserver {
166 public:
167 virtual void ReceivedMessage(const TurnMessage* msg) = 0;
168 virtual void ReceivedChannelData(const char* data, size_t size) = 0;
169 virtual ~StunMessageObserver() {}
170};
171
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000172// The core TURN server class. Give it a socket to listen on via
173// AddInternalServerSocket, and a factory to create external sockets via
174// SetExternalSocketFactory, and it's ready to go.
175// Not yet wired up: TCP support.
176class TurnServer : public sigslot::has_slots<> {
177 public:
deadbeef97943662016-07-12 11:04:50 -0700178 typedef std::map<TurnServerConnection, std::unique_ptr<TurnServerAllocation>>
179 AllocationMap;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000180
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000181 explicit TurnServer(rtc::Thread* thread);
Steve Antonf2737d22017-10-31 16:27:34 -0700182 ~TurnServer() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000183
184 // Gets/sets the realm value to use for the server.
Seth Hampsonaed71642018-06-11 07:41:32 -0700185 const std::string& realm() const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200186 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700187 return realm_;
188 }
189 void set_realm(const std::string& realm) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200190 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700191 realm_ = realm;
192 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000193
194 // Gets/sets the value for the SOFTWARE attribute for TURN messages.
Seth Hampsonaed71642018-06-11 07:41:32 -0700195 const std::string& software() const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200196 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700197 return software_;
198 }
199 void set_software(const std::string& software) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200200 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700201 software_ = software;
202 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000203
Seth Hampsonaed71642018-06-11 07:41:32 -0700204 const AllocationMap& allocations() const {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200205 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700206 return allocations_;
207 }
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000208
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000209 // Sets the authentication callback; does not take ownership.
Seth Hampsonaed71642018-06-11 07:41:32 -0700210 void set_auth_hook(TurnAuthInterface* auth_hook) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200211 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700212 auth_hook_ = auth_hook;
213 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000214
215 void set_redirect_hook(TurnRedirectInterface* redirect_hook) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200216 RTC_DCHECK(thread_checker_.IsCurrent());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000217 redirect_hook_ = redirect_hook;
218 }
219
Seth Hampsonaed71642018-06-11 07:41:32 -0700220 void set_enable_otu_nonce(bool enable) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200221 RTC_DCHECK(thread_checker_.IsCurrent());
Seth Hampsonaed71642018-06-11 07:41:32 -0700222 enable_otu_nonce_ = enable;
223 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000224
deadbeef376e1232015-11-25 09:00:08 -0800225 // If set to true, reject CreatePermission requests to RFC1918 addresses.
226 void set_reject_private_addresses(bool filter) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200227 RTC_DCHECK(thread_checker_.IsCurrent());
deadbeef376e1232015-11-25 09:00:08 -0800228 reject_private_addresses_ = filter;
229 }
230
Taylor Brandstetteref184702016-06-23 17:35:47 -0700231 void set_enable_permission_checks(bool enable) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200232 RTC_DCHECK(thread_checker_.IsCurrent());
Taylor Brandstetteref184702016-06-23 17:35:47 -0700233 enable_permission_checks_ = enable;
234 }
235
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000236 // Starts listening for packets from internal clients.
Jonas Olssona4d87372019-07-05 19:08:33 +0200237 void AddInternalSocket(rtc::AsyncPacketSocket* socket, ProtocolType proto);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000238 // Starts listening for the connections on this socket. When someone tries
239 // to connect, the connection will be accepted and a new internal socket
240 // will be added.
Jonas Olssona4d87372019-07-05 19:08:33 +0200241 void AddInternalServerSocket(rtc::AsyncSocket* socket, ProtocolType proto);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000242 // Specifies the factory to use for creating external sockets.
243 void SetExternalSocketFactory(rtc::PacketSocketFactory* factory,
244 const rtc::SocketAddress& address);
honghaizc463e202016-02-01 15:19:08 -0800245 // For testing only.
honghaiz34b11eb2016-03-16 08:55:44 -0700246 std::string SetTimestampForNextNonce(int64_t timestamp) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200247 RTC_DCHECK(thread_checker_.IsCurrent());
honghaizc463e202016-02-01 15:19:08 -0800248 ts_for_next_nonce_ = timestamp;
249 return GenerateNonce(timestamp);
250 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251
Jonas Olssona4d87372019-07-05 19:08:33 +0200252 void SetStunMessageObserver(std::unique_ptr<StunMessageObserver> observer) {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200253 RTC_DCHECK(thread_checker_.IsCurrent());
Jonas Orelandbdcee282017-10-10 14:01:40 +0200254 stun_message_observer_ = std::move(observer);
255 }
256
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000257 private:
honghaiz34b11eb2016-03-16 08:55:44 -0700258 std::string GenerateNonce(int64_t now) const;
Niels Möllere6933812018-11-05 13:01:41 +0100259 void OnInternalPacket(rtc::AsyncPacketSocket* socket,
260 const char* data,
261 size_t size,
262 const rtc::SocketAddress& address,
263 const int64_t& packet_time_us);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000264
265 void OnNewInternalConnection(rtc::AsyncSocket* socket);
266
267 // Accept connections on this server socket.
268 void AcceptConnection(rtc::AsyncSocket* server_socket);
269 void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
270
Jonas Olssona4d87372019-07-05 19:08:33 +0200271 void HandleStunMessage(TurnServerConnection* conn,
272 const char* data,
273 size_t size);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000274 void HandleBindingRequest(TurnServerConnection* conn, const StunMessage* msg);
Jonas Olssona4d87372019-07-05 19:08:33 +0200275 void HandleAllocateRequest(TurnServerConnection* conn,
276 const TurnMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000277 const std::string& key);
278
279 bool GetKey(const StunMessage* msg, std::string* key);
Jonas Olssona4d87372019-07-05 19:08:33 +0200280 bool CheckAuthorization(TurnServerConnection* conn,
281 const StunMessage* msg,
282 const char* data,
283 size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000284 const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000285 bool ValidateNonce(const std::string& nonce) const;
286
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000287 TurnServerAllocation* FindAllocation(TurnServerConnection* conn);
Jonas Olssona4d87372019-07-05 19:08:33 +0200288 TurnServerAllocation* CreateAllocation(TurnServerConnection* conn,
289 int proto,
290 const std::string& key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000291
Jonas Olssona4d87372019-07-05 19:08:33 +0200292 void SendErrorResponse(TurnServerConnection* conn,
293 const StunMessage* req,
294 int code,
295 const std::string& reason);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000296
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000297 void SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000298 const StunMessage* req,
299 int code,
300 const std::string& reason);
301
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000302 void SendErrorResponseWithAlternateServer(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000303 const StunMessage* req,
304 const rtc::SocketAddress& addr);
305
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000306 void SendStun(TurnServerConnection* conn, StunMessage* msg);
jbauchf1f87202016-03-30 06:43:37 -0700307 void Send(TurnServerConnection* conn, const rtc::ByteBufferWriter& buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000308
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000309 void OnAllocationDestroyed(TurnServerAllocation* allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000310 void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
311
deadbeef824f5862016-08-24 15:06:53 -0700312 // Just clears |sockets_to_delete_|; called asynchronously.
313 void FreeSockets();
314
Jonas Olssona4d87372019-07-05 19:08:33 +0200315 typedef std::map<rtc::AsyncPacketSocket*, ProtocolType> InternalSocketMap;
316 typedef std::map<rtc::AsyncSocket*, ProtocolType> ServerSocketMap;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000317
318 rtc::Thread* thread_;
Seth Hampsonaed71642018-06-11 07:41:32 -0700319 rtc::ThreadChecker thread_checker_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000320 std::string nonce_key_;
321 std::string realm_;
322 std::string software_;
323 TurnAuthInterface* auth_hook_;
324 TurnRedirectInterface* redirect_hook_;
325 // otu - one-time-use. Server will respond with 438 if it's
326 // sees the same nonce in next transaction.
327 bool enable_otu_nonce_;
deadbeef376e1232015-11-25 09:00:08 -0800328 bool reject_private_addresses_ = false;
Taylor Brandstetteref184702016-06-23 17:35:47 -0700329 // Check for permission when receiving an external packet.
330 bool enable_permission_checks_ = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000331
332 InternalSocketMap server_sockets_;
333 ServerSocketMap server_listen_sockets_;
deadbeef824f5862016-08-24 15:06:53 -0700334 // Used when we need to delete a socket asynchronously.
335 std::vector<std::unique_ptr<rtc::AsyncPacketSocket>> sockets_to_delete_;
kwiberg3ec46792016-04-27 07:22:53 -0700336 std::unique_ptr<rtc::PacketSocketFactory> external_socket_factory_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000337 rtc::SocketAddress external_addr_;
338
339 AllocationMap allocations_;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000340
deadbeef824f5862016-08-24 15:06:53 -0700341 rtc::AsyncInvoker invoker_;
342
honghaizc463e202016-02-01 15:19:08 -0800343 // For testing only. If this is non-zero, the next NONCE will be generated
344 // from this value, and it will be reset to 0 after generating the NONCE.
honghaiz34b11eb2016-03-16 08:55:44 -0700345 int64_t ts_for_next_nonce_ = 0;
honghaizc463e202016-02-01 15:19:08 -0800346
Jonas Orelandbdcee282017-10-10 14:01:40 +0200347 // For testing only. Used to observe STUN messages received.
348 std::unique_ptr<StunMessageObserver> stun_message_observer_;
349
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000350 friend class TurnServerAllocation;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000351};
352
353} // namespace cricket
354
Steve Anton10542f22019-01-11 09:11:00 -0800355#endif // P2P_BASE_TURN_SERVER_H_