henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 1 | /* |
| 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 Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 11 | #include "p2p/base/turn_server.h" |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 12 | |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 13 | #include <memory> |
Taylor Brandstetter | 734262c | 2016-08-01 16:37:14 -0700 | [diff] [blame] | 14 | #include <tuple> // for std::tie |
Steve Anton | 6c38cc7 | 2017-11-29 10:25:58 -0800 | [diff] [blame] | 15 | #include <utility> |
Taylor Brandstetter | 734262c | 2016-08-01 16:37:14 -0700 | [diff] [blame] | 16 | |
Steve Anton | ae226f6 | 2019-01-29 12:47:38 -0800 | [diff] [blame] | 17 | #include "absl/algorithm/container.h" |
Patrik Höglund | 7d00342 | 2019-09-17 12:16:35 +0200 | [diff] [blame] | 18 | #include "api/packet_socket_factory.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 19 | #include "p2p/base/async_stun_tcp_socket.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 20 | #include "p2p/base/stun.h" |
| 21 | #include "rtc_base/bind.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 22 | #include "rtc_base/byte_buffer.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 23 | #include "rtc_base/checks.h" |
| 24 | #include "rtc_base/helpers.h" |
| 25 | #include "rtc_base/logging.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 26 | #include "rtc_base/message_digest.h" |
| 27 | #include "rtc_base/socket_adapters.h" |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 28 | #include "rtc_base/strings/string_builder.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 29 | #include "rtc_base/thread.h" |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 30 | |
| 31 | namespace cricket { |
| 32 | |
| 33 | // TODO(juberti): Move this all to a future turnmessage.h |
Steve Anton | 6c38cc7 | 2017-11-29 10:25:58 -0800 | [diff] [blame] | 34 | // static const int IPPROTO_UDP = 17; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 35 | static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes |
| 36 | static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes |
| 37 | static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes |
| 38 | static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes |
| 39 | |
| 40 | static const int kMinChannelNumber = 0x4000; |
| 41 | static const int kMaxChannelNumber = 0x7FFF; |
| 42 | |
| 43 | static const size_t kNonceKeySize = 16; |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 44 | static const size_t kNonceSize = 48; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 45 | |
| 46 | static const size_t TURN_CHANNEL_HEADER_SIZE = 4U; |
| 47 | |
| 48 | // TODO(mallinath) - Move these to a common place. |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 49 | inline bool IsTurnChannelData(uint16_t msg_type) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 50 | // The first two bits of a channel data message are 0b01. |
| 51 | return ((msg_type & 0xC000) == 0x4000); |
| 52 | } |
| 53 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 54 | // IDs used for posted messages for TurnServerAllocation. |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 55 | enum { |
| 56 | MSG_ALLOCATION_TIMEOUT, |
| 57 | }; |
| 58 | |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 59 | // 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.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 62 | class TurnServerAllocation::Permission : public rtc::MessageHandler { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 63 | public: |
| 64 | Permission(rtc::Thread* thread, const rtc::IPAddress& peer); |
Steve Anton | f2737d2 | 2017-10-31 16:27:34 -0700 | [diff] [blame] | 65 | ~Permission() override; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 66 | |
| 67 | const rtc::IPAddress& peer() const { return peer_; } |
| 68 | void Refresh(); |
| 69 | |
| 70 | sigslot::signal1<Permission*> SignalDestroyed; |
| 71 | |
| 72 | private: |
Steve Anton | f2737d2 | 2017-10-31 16:27:34 -0700 | [diff] [blame] | 73 | void OnMessage(rtc::Message* msg) override; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 74 | |
| 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.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 82 | class TurnServerAllocation::Channel : public rtc::MessageHandler { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 83 | public: |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 84 | Channel(rtc::Thread* thread, int id, const rtc::SocketAddress& peer); |
Steve Anton | f2737d2 | 2017-10-31 16:27:34 -0700 | [diff] [blame] | 85 | ~Channel() override; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 86 | |
| 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 Anton | f2737d2 | 2017-10-31 16:27:34 -0700 | [diff] [blame] | 94 | void OnMessage(rtc::Message* msg) override; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 95 | |
| 96 | rtc::Thread* thread_; |
| 97 | int id_; |
| 98 | rtc::SocketAddress peer_; |
| 99 | }; |
| 100 | |
| 101 | static 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 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 110 | static bool InitErrorResponse(const StunMessage* req, |
| 111 | int code, |
| 112 | const std::string& reason, |
| 113 | StunMessage* resp) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 114 | int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1; |
| 115 | if (resp_type == -1) |
| 116 | return false; |
| 117 | resp->SetType(resp_type); |
| 118 | resp->SetTransactionID(req->transaction_id()); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 119 | resp->AddAttribute(std::make_unique<cricket::StunErrorCodeAttribute>( |
nisse | cc99bc2 | 2017-02-02 01:31:30 -0800 | [diff] [blame] | 120 | STUN_ATTR_ERROR_CODE, code, reason)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 121 | return true; |
| 122 | } |
| 123 | |
| 124 | TurnServer::TurnServer(rtc::Thread* thread) |
| 125 | : thread_(thread), |
| 126 | nonce_key_(rtc::CreateRandomString(kNonceKeySize)), |
| 127 | auth_hook_(NULL), |
| 128 | redirect_hook_(NULL), |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 129 | enable_otu_nonce_(false) {} |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 130 | |
| 131 | TurnServer::~TurnServer() { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 132 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 133 | 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 | |
| 146 | void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket, |
| 147 | ProtocolType proto) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 148 | RTC_DCHECK(thread_checker_.IsCurrent()); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 149 | RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 150 | server_sockets_[socket] = proto; |
| 151 | socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket); |
| 152 | } |
| 153 | |
| 154 | void TurnServer::AddInternalServerSocket(rtc::AsyncSocket* socket, |
| 155 | ProtocolType proto) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 156 | RTC_DCHECK(thread_checker_.IsCurrent()); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 157 | RTC_DCHECK(server_listen_sockets_.end() == |
| 158 | server_listen_sockets_.find(socket)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 159 | server_listen_sockets_[socket] = proto; |
| 160 | socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection); |
| 161 | } |
| 162 | |
| 163 | void TurnServer::SetExternalSocketFactory( |
| 164 | rtc::PacketSocketFactory* factory, |
| 165 | const rtc::SocketAddress& external_addr) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 166 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 167 | external_socket_factory_.reset(factory); |
| 168 | external_addr_ = external_addr; |
| 169 | } |
| 170 | |
| 171 | void TurnServer::OnNewInternalConnection(rtc::AsyncSocket* socket) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 172 | RTC_DCHECK(thread_checker_.IsCurrent()); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 173 | RTC_DCHECK(server_listen_sockets_.find(socket) != |
| 174 | server_listen_sockets_.end()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 175 | AcceptConnection(socket); |
| 176 | } |
| 177 | |
| 178 | void TurnServer::AcceptConnection(rtc::AsyncSocket* server_socket) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 179 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 180 | // 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 | |
| 194 | void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket, |
| 195 | int err) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 196 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 197 | DestroyInternalSocket(socket); |
| 198 | } |
| 199 | |
| 200 | void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket, |
Niels Möller | e693381 | 2018-11-05 13:01:41 +0100 | [diff] [blame] | 201 | const char* data, |
| 202 | size_t size, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 203 | const rtc::SocketAddress& addr, |
Niels Möller | e693381 | 2018-11-05 13:01:41 +0100 | [diff] [blame] | 204 | const int64_t& /* packet_time_us */) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 205 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 206 | // Fail if the packet is too small to even contain a channel header. |
| 207 | if (size < TURN_CHANNEL_HEADER_SIZE) { |
Steve Anton | 6c38cc7 | 2017-11-29 10:25:58 -0800 | [diff] [blame] | 208 | return; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 209 | } |
| 210 | InternalSocketMap::iterator iter = server_sockets_.find(socket); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 211 | RTC_DCHECK(iter != server_sockets_.end()); |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 212 | TurnServerConnection conn(addr, iter->second, socket); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 213 | uint16_t msg_type = rtc::GetBE16(data); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 214 | if (!IsTurnChannelData(msg_type)) { |
| 215 | // This is a STUN message. |
| 216 | HandleStunMessage(&conn, data, size); |
| 217 | } else { |
| 218 | // This is a channel message; let the allocation handle it. |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 219 | TurnServerAllocation* allocation = FindAllocation(&conn); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 220 | if (allocation) { |
| 221 | allocation->HandleChannelData(data, size); |
| 222 | } |
Jonas Oreland | bdcee28 | 2017-10-10 14:01:40 +0200 | [diff] [blame] | 223 | if (stun_message_observer_ != nullptr) { |
| 224 | stun_message_observer_->ReceivedChannelData(data, size); |
| 225 | } |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 226 | } |
| 227 | } |
| 228 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 229 | void TurnServer::HandleStunMessage(TurnServerConnection* conn, |
| 230 | const char* data, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 231 | size_t size) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 232 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 233 | TurnMessage msg; |
jbauch | f1f8720 | 2016-03-30 06:43:37 -0700 | [diff] [blame] | 234 | rtc::ByteBufferReader buf(data, size); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 235 | if (!msg.Read(&buf) || (buf.Length() > 0)) { |
Mirko Bonadei | 675513b | 2017-11-09 11:09:25 +0100 | [diff] [blame] | 236 | RTC_LOG(LS_WARNING) << "Received invalid STUN message"; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 237 | return; |
| 238 | } |
| 239 | |
Jonas Oreland | bdcee28 | 2017-10-10 14:01:40 +0200 | [diff] [blame] | 240 | if (stun_message_observer_ != nullptr) { |
| 241 | stun_message_observer_->ReceivedMessage(&msg); |
| 242 | } |
| 243 | |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 244 | // 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)) { |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 253 | SendErrorResponseWithAlternateServer(conn, &msg, address); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 254 | return; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | // Look up the key that we'll use to validate the M-I. If we have an |
| 259 | // existing allocation, the key will already be cached. |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 260 | TurnServerAllocation* allocation = FindAllocation(conn); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 261 | std::string key; |
| 262 | if (!allocation) { |
| 263 | GetKey(&msg, &key); |
| 264 | } else { |
| 265 | key = allocation->key(); |
| 266 | } |
| 267 | |
| 268 | // Ensure the message is authorized; only needed for requests. |
| 269 | if (IsStunRequestType(msg.type())) { |
| 270 | if (!CheckAuthorization(conn, &msg, data, size, key)) { |
| 271 | return; |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) { |
| 276 | HandleAllocateRequest(conn, &msg, key); |
| 277 | } else if (allocation && |
| 278 | (msg.type() != STUN_ALLOCATE_REQUEST || |
| 279 | msg.transaction_id() == allocation->transaction_id())) { |
| 280 | // This is a non-allocate request, or a retransmit of an allocate. |
| 281 | // Check that the username matches the previous username used. |
| 282 | if (IsStunRequestType(msg.type()) && |
| 283 | msg.GetByteString(STUN_ATTR_USERNAME)->GetString() != |
| 284 | allocation->username()) { |
| 285 | SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS, |
| 286 | STUN_ERROR_REASON_WRONG_CREDENTIALS); |
| 287 | return; |
| 288 | } |
| 289 | allocation->HandleTurnMessage(&msg); |
| 290 | } else { |
| 291 | // Allocation mismatch. |
| 292 | SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH, |
| 293 | STUN_ERROR_REASON_ALLOCATION_MISMATCH); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | bool TurnServer::GetKey(const StunMessage* msg, std::string* key) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 298 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 299 | const StunByteStringAttribute* username_attr = |
| 300 | msg->GetByteString(STUN_ATTR_USERNAME); |
| 301 | if (!username_attr) { |
| 302 | return false; |
| 303 | } |
| 304 | |
| 305 | std::string username = username_attr->GetString(); |
| 306 | return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key)); |
| 307 | } |
| 308 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 309 | bool TurnServer::CheckAuthorization(TurnServerConnection* conn, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 310 | const StunMessage* msg, |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 311 | const char* data, |
| 312 | size_t size, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 313 | const std::string& key) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 314 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 315 | // RFC 5389, 10.2.2. |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 316 | RTC_DCHECK(IsStunRequestType(msg->type())); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 317 | 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.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 356 | TurnServerAllocation* allocation = FindAllocation(conn); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 357 | 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.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 371 | void TurnServer::HandleBindingRequest(TurnServerConnection* conn, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 372 | const StunMessage* req) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 373 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 374 | StunMessage response; |
| 375 | InitResponse(req, &response); |
| 376 | |
| 377 | // Tell the user the address that we received their request from. |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 378 | auto mapped_addr_attr = std::make_unique<StunXorAddressAttribute>( |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 379 | STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src()); |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 380 | response.AddAttribute(std::move(mapped_addr_attr)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 381 | |
| 382 | SendStun(conn, &response); |
| 383 | } |
| 384 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 385 | void TurnServer::HandleAllocateRequest(TurnServerConnection* conn, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 386 | const TurnMessage* msg, |
| 387 | const std::string& key) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 388 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 389 | // 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.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 408 | TurnServerAllocation* alloc = CreateAllocation(conn, proto, key); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 409 | if (alloc) { |
| 410 | alloc->HandleTurnMessage(msg); |
| 411 | } else { |
| 412 | SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR, |
| 413 | "Failed to allocate socket"); |
| 414 | } |
| 415 | } |
| 416 | |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 417 | std::string TurnServer::GenerateNonce(int64_t now) const { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 418 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 419 | // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now)) |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 420 | 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); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 423 | RTC_DCHECK(nonce.size() == kNonceSize); |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 424 | |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 425 | return nonce; |
| 426 | } |
| 427 | |
| 428 | bool TurnServer::ValidateNonce(const std::string& nonce) const { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 429 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 430 | // Check the size. |
| 431 | if (nonce.size() != kNonceSize) { |
| 432 | return false; |
| 433 | } |
| 434 | |
| 435 | // Decode the timestamp. |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 436 | int64_t then; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 437 | char* p = reinterpret_cast<char*>(&then); |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 438 | size_t len = |
| 439 | rtc::hex_decode(p, sizeof(then), nonce.substr(0, sizeof(then) * 2)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 440 | if (len != sizeof(then)) { |
| 441 | return false; |
| 442 | } |
| 443 | |
| 444 | // Verify the HMAC. |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 445 | if (nonce.substr(sizeof(then) * 2) != |
| 446 | rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, |
| 447 | std::string(p, sizeof(then)))) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 448 | return false; |
| 449 | } |
| 450 | |
| 451 | // Validate the timestamp. |
nisse | 1bffc1d | 2016-05-02 08:18:55 -0700 | [diff] [blame] | 452 | return rtc::TimeMillis() - then < kNonceTimeout; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 453 | } |
| 454 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 455 | TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 456 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 457 | AllocationMap::const_iterator it = allocations_.find(*conn); |
deadbeef | 9794366 | 2016-07-12 11:04:50 -0700 | [diff] [blame] | 458 | return (it != allocations_.end()) ? it->second.get() : nullptr; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 459 | } |
| 460 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 461 | TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn, |
| 462 | int proto, |
| 463 | const std::string& key) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 464 | RTC_DCHECK(thread_checker_.IsCurrent()); |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 465 | rtc::AsyncPacketSocket* external_socket = |
| 466 | (external_socket_factory_) |
| 467 | ? external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) |
| 468 | : NULL; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 469 | if (!external_socket) { |
| 470 | return NULL; |
| 471 | } |
| 472 | |
| 473 | // The Allocation takes ownership of the socket. |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 474 | TurnServerAllocation* allocation = |
| 475 | new TurnServerAllocation(this, thread_, *conn, external_socket, key); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 476 | allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed); |
deadbeef | 9794366 | 2016-07-12 11:04:50 -0700 | [diff] [blame] | 477 | allocations_[*conn].reset(allocation); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 478 | return allocation; |
| 479 | } |
| 480 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 481 | void TurnServer::SendErrorResponse(TurnServerConnection* conn, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 482 | const StunMessage* req, |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 483 | int code, |
| 484 | const std::string& reason) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 485 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 486 | TurnMessage resp; |
| 487 | InitErrorResponse(req, code, reason, &resp); |
Mirko Bonadei | 675513b | 2017-11-09 11:09:25 +0100 | [diff] [blame] | 488 | RTC_LOG(LS_INFO) << "Sending error response, type=" << resp.type() |
| 489 | << ", code=" << code << ", reason=" << reason; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 490 | SendStun(conn, &resp); |
| 491 | } |
| 492 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 493 | void TurnServer::SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn, |
| 494 | const StunMessage* msg, |
| 495 | int code, |
| 496 | const std::string& reason) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 497 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 498 | TurnMessage resp; |
| 499 | InitErrorResponse(msg, code, reason, &resp); |
honghaiz | c463e20 | 2016-02-01 15:19:08 -0800 | [diff] [blame] | 500 | |
nisse | 1bffc1d | 2016-05-02 08:18:55 -0700 | [diff] [blame] | 501 | int64_t timestamp = rtc::TimeMillis(); |
honghaiz | c463e20 | 2016-02-01 15:19:08 -0800 | [diff] [blame] | 502 | if (ts_for_next_nonce_) { |
| 503 | timestamp = ts_for_next_nonce_; |
| 504 | ts_for_next_nonce_ = 0; |
| 505 | } |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 506 | resp.AddAttribute(std::make_unique<StunByteStringAttribute>( |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 507 | STUN_ATTR_NONCE, GenerateNonce(timestamp))); |
nisse | cc99bc2 | 2017-02-02 01:31:30 -0800 | [diff] [blame] | 508 | resp.AddAttribute( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 509 | std::make_unique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 510 | SendStun(conn, &resp); |
| 511 | } |
| 512 | |
| 513 | void TurnServer::SendErrorResponseWithAlternateServer( |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 514 | TurnServerConnection* conn, |
| 515 | const StunMessage* msg, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 516 | const rtc::SocketAddress& addr) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 517 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 518 | TurnMessage resp; |
| 519 | InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE, |
| 520 | STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 521 | resp.AddAttribute( |
| 522 | std::make_unique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 523 | SendStun(conn, &resp); |
| 524 | } |
| 525 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 526 | void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 527 | RTC_DCHECK(thread_checker_.IsCurrent()); |
jbauch | f1f8720 | 2016-03-30 06:43:37 -0700 | [diff] [blame] | 528 | rtc::ByteBufferWriter buf; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 529 | // Add a SOFTWARE attribute if one is set. |
| 530 | if (!software_.empty()) { |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 531 | msg->AddAttribute(std::make_unique<StunByteStringAttribute>( |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 532 | STUN_ATTR_SOFTWARE, software_)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 533 | } |
| 534 | msg->Write(&buf); |
| 535 | Send(conn, buf); |
| 536 | } |
| 537 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 538 | void TurnServer::Send(TurnServerConnection* conn, |
jbauch | f1f8720 | 2016-03-30 06:43:37 -0700 | [diff] [blame] | 539 | const rtc::ByteBufferWriter& buf) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 540 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 541 | rtc::PacketOptions options; |
| 542 | conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options); |
| 543 | } |
| 544 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 545 | void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 546 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 547 | // Removing the internal socket if the connection is not udp. |
| 548 | rtc::AsyncPacketSocket* socket = allocation->conn()->socket(); |
| 549 | InternalSocketMap::iterator iter = server_sockets_.find(socket); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 550 | // Skip if the socket serving this allocation is UDP, as this will be shared |
| 551 | // by all allocations. |
Taylor Brandstetter | 716d07a | 2016-06-27 14:07:41 -0700 | [diff] [blame] | 552 | // Note: We may not find a socket if it's a TCP socket that was closed, and |
| 553 | // the allocation is only now timing out. |
| 554 | if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 555 | DestroyInternalSocket(socket); |
| 556 | } |
| 557 | |
| 558 | AllocationMap::iterator it = allocations_.find(*(allocation->conn())); |
deadbeef | 9794366 | 2016-07-12 11:04:50 -0700 | [diff] [blame] | 559 | if (it != allocations_.end()) { |
| 560 | it->second.release(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 561 | allocations_.erase(it); |
deadbeef | 9794366 | 2016-07-12 11:04:50 -0700 | [diff] [blame] | 562 | } |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 563 | } |
| 564 | |
| 565 | void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 566 | RTC_DCHECK(thread_checker_.IsCurrent()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 567 | InternalSocketMap::iterator iter = server_sockets_.find(socket); |
| 568 | if (iter != server_sockets_.end()) { |
| 569 | rtc::AsyncPacketSocket* socket = iter->first; |
Qingsi Wang | 0ea7515 | 2018-07-02 10:48:25 -0700 | [diff] [blame] | 570 | socket->SignalReadPacket.disconnect(this); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 571 | server_sockets_.erase(iter); |
deadbeef | 824f586 | 2016-08-24 15:06:53 -0700 | [diff] [blame] | 572 | // We must destroy the socket async to avoid invalidating the sigslot |
| 573 | // callback list iterator inside a sigslot callback. (In other words, |
| 574 | // deleting an object from within a callback from that object). |
| 575 | sockets_to_delete_.push_back( |
| 576 | std::unique_ptr<rtc::AsyncPacketSocket>(socket)); |
| 577 | invoker_.AsyncInvoke<void>(RTC_FROM_HERE, rtc::Thread::Current(), |
| 578 | rtc::Bind(&TurnServer::FreeSockets, this)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 579 | } |
| 580 | } |
| 581 | |
deadbeef | 824f586 | 2016-08-24 15:06:53 -0700 | [diff] [blame] | 582 | void TurnServer::FreeSockets() { |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 583 | RTC_DCHECK(thread_checker_.IsCurrent()); |
deadbeef | 824f586 | 2016-08-24 15:06:53 -0700 | [diff] [blame] | 584 | sockets_to_delete_.clear(); |
| 585 | } |
| 586 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 587 | TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src, |
| 588 | ProtocolType proto, |
| 589 | rtc::AsyncPacketSocket* socket) |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 590 | : src_(src), |
| 591 | dst_(socket->GetRemoteAddress()), |
| 592 | proto_(proto), |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 593 | socket_(socket) {} |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 594 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 595 | bool TurnServerConnection::operator==(const TurnServerConnection& c) const { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 596 | return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_; |
| 597 | } |
| 598 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 599 | bool TurnServerConnection::operator<(const TurnServerConnection& c) const { |
Taylor Brandstetter | 734262c | 2016-08-01 16:37:14 -0700 | [diff] [blame] | 600 | return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 601 | } |
| 602 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 603 | std::string TurnServerConnection::ToString() const { |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 604 | const char* const kProtos[] = {"unknown", "udp", "tcp", "ssltcp"}; |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 605 | rtc::StringBuilder ost; |
Qingsi Wang | 20232a9 | 2019-09-06 12:51:17 -0700 | [diff] [blame] | 606 | ost << src_.ToSensitiveString() << "-" << dst_.ToSensitiveString() << ":" |
| 607 | << kProtos[proto_]; |
Jonas Olsson | 84df1c7 | 2018-09-14 16:59:32 +0200 | [diff] [blame] | 608 | return ost.Release(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 609 | } |
| 610 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 611 | TurnServerAllocation::TurnServerAllocation(TurnServer* server, |
| 612 | rtc::Thread* thread, |
| 613 | const TurnServerConnection& conn, |
| 614 | rtc::AsyncPacketSocket* socket, |
| 615 | const std::string& key) |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 616 | : server_(server), |
| 617 | thread_(thread), |
| 618 | conn_(conn), |
| 619 | external_socket_(socket), |
| 620 | key_(key) { |
| 621 | external_socket_->SignalReadPacket.connect( |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 622 | this, &TurnServerAllocation::OnExternalPacket); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 623 | } |
| 624 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 625 | TurnServerAllocation::~TurnServerAllocation() { |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 626 | for (ChannelList::iterator it = channels_.begin(); it != channels_.end(); |
| 627 | ++it) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 628 | delete *it; |
| 629 | } |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 630 | for (PermissionList::iterator it = perms_.begin(); it != perms_.end(); ++it) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 631 | delete *it; |
| 632 | } |
| 633 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 634 | RTC_LOG(LS_INFO) << ToString() << ": Allocation destroyed"; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 635 | } |
| 636 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 637 | std::string TurnServerAllocation::ToString() const { |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 638 | rtc::StringBuilder ost; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 639 | ost << "Alloc[" << conn_.ToString() << "]"; |
Jonas Olsson | 84df1c7 | 2018-09-14 16:59:32 +0200 | [diff] [blame] | 640 | return ost.Release(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 641 | } |
| 642 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 643 | void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 644 | RTC_DCHECK(msg != NULL); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 645 | switch (msg->type()) { |
| 646 | case STUN_ALLOCATE_REQUEST: |
| 647 | HandleAllocateRequest(msg); |
| 648 | break; |
| 649 | case TURN_REFRESH_REQUEST: |
| 650 | HandleRefreshRequest(msg); |
| 651 | break; |
| 652 | case TURN_SEND_INDICATION: |
| 653 | HandleSendIndication(msg); |
| 654 | break; |
| 655 | case TURN_CREATE_PERMISSION_REQUEST: |
| 656 | HandleCreatePermissionRequest(msg); |
| 657 | break; |
| 658 | case TURN_CHANNEL_BIND_REQUEST: |
| 659 | HandleChannelBindRequest(msg); |
| 660 | break; |
| 661 | default: |
| 662 | // Not sure what to do with this, just eat it. |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 663 | RTC_LOG(LS_WARNING) << ToString() |
| 664 | << ": Invalid TURN message type received: " |
| 665 | << msg->type(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 666 | } |
| 667 | } |
| 668 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 669 | void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 670 | // Copy the important info from the allocate request. |
| 671 | transaction_id_ = msg->transaction_id(); |
| 672 | const StunByteStringAttribute* username_attr = |
| 673 | msg->GetByteString(STUN_ATTR_USERNAME); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 674 | RTC_DCHECK(username_attr != NULL); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 675 | username_ = username_attr->GetString(); |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 676 | const StunByteStringAttribute* origin_attr = |
| 677 | msg->GetByteString(STUN_ATTR_ORIGIN); |
| 678 | if (origin_attr) { |
| 679 | origin_ = origin_attr->GetString(); |
| 680 | } |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 681 | |
| 682 | // Figure out the lifetime and start the allocation timer. |
| 683 | int lifetime_secs = ComputeLifetime(msg); |
Taylor Brandstetter | 5d97a9a | 2016-06-10 14:17:27 -0700 | [diff] [blame] | 684 | thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this, |
| 685 | MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 686 | |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 687 | RTC_LOG(LS_INFO) << ToString() |
| 688 | << ": Created allocation with lifetime=" << lifetime_secs; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 689 | |
| 690 | // We've already validated all the important bits; just send a response here. |
| 691 | TurnMessage response; |
| 692 | InitResponse(msg, &response); |
| 693 | |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 694 | auto mapped_addr_attr = std::make_unique<StunXorAddressAttribute>( |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 695 | STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src()); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 696 | auto relayed_addr_attr = std::make_unique<StunXorAddressAttribute>( |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 697 | STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress()); |
| 698 | auto lifetime_attr = |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 699 | std::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs); |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 700 | response.AddAttribute(std::move(mapped_addr_attr)); |
| 701 | response.AddAttribute(std::move(relayed_addr_attr)); |
| 702 | response.AddAttribute(std::move(lifetime_attr)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 703 | |
| 704 | SendResponse(&response); |
| 705 | } |
| 706 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 707 | void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 708 | // Figure out the new lifetime. |
| 709 | int lifetime_secs = ComputeLifetime(msg); |
| 710 | |
| 711 | // Reset the expiration timer. |
| 712 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
Taylor Brandstetter | 5d97a9a | 2016-06-10 14:17:27 -0700 | [diff] [blame] | 713 | thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this, |
| 714 | MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 715 | |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 716 | RTC_LOG(LS_INFO) << ToString() |
| 717 | << ": Refreshed allocation, lifetime=" << lifetime_secs; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 718 | |
| 719 | // Send a success response with a LIFETIME attribute. |
| 720 | TurnMessage response; |
| 721 | InitResponse(msg, &response); |
| 722 | |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 723 | auto lifetime_attr = |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 724 | std::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs); |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 725 | response.AddAttribute(std::move(lifetime_attr)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 726 | |
| 727 | SendResponse(&response); |
| 728 | } |
| 729 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 730 | void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 731 | // Check mandatory attributes. |
| 732 | const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA); |
| 733 | const StunAddressAttribute* peer_attr = |
| 734 | msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS); |
| 735 | if (!data_attr || !peer_attr) { |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 736 | RTC_LOG(LS_WARNING) << ToString() << ": Received invalid send indication"; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 737 | return; |
| 738 | } |
| 739 | |
| 740 | // If a permission exists, send the data on to the peer. |
| 741 | if (HasPermission(peer_attr->GetAddress().ipaddr())) { |
| 742 | SendExternal(data_attr->bytes(), data_attr->length(), |
| 743 | peer_attr->GetAddress()); |
| 744 | } else { |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 745 | RTC_LOG(LS_WARNING) << ToString() |
| 746 | << ": Received send indication without permission" |
| 747 | " peer=" |
Qingsi Wang | 20232a9 | 2019-09-06 12:51:17 -0700 | [diff] [blame] | 748 | << peer_attr->GetAddress().ToSensitiveString(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 749 | } |
| 750 | } |
| 751 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 752 | void TurnServerAllocation::HandleCreatePermissionRequest( |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 753 | const TurnMessage* msg) { |
| 754 | // Check mandatory attributes. |
| 755 | const StunAddressAttribute* peer_attr = |
| 756 | msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS); |
| 757 | if (!peer_attr) { |
| 758 | SendBadRequestResponse(msg); |
| 759 | return; |
| 760 | } |
| 761 | |
deadbeef | 376e123 | 2015-11-25 09:00:08 -0800 | [diff] [blame] | 762 | if (server_->reject_private_addresses_ && |
| 763 | rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) { |
| 764 | SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN); |
| 765 | return; |
| 766 | } |
| 767 | |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 768 | // Add this permission. |
| 769 | AddPermission(peer_attr->GetAddress().ipaddr()); |
| 770 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 771 | RTC_LOG(LS_INFO) << ToString() << ": Created permission, peer=" |
Qingsi Wang | 20232a9 | 2019-09-06 12:51:17 -0700 | [diff] [blame] | 772 | << peer_attr->GetAddress().ToSensitiveString(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 773 | |
| 774 | // Send a success response. |
| 775 | TurnMessage response; |
| 776 | InitResponse(msg, &response); |
| 777 | SendResponse(&response); |
| 778 | } |
| 779 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 780 | void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 781 | // Check mandatory attributes. |
| 782 | const StunUInt32Attribute* channel_attr = |
| 783 | msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER); |
| 784 | const StunAddressAttribute* peer_attr = |
| 785 | msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS); |
| 786 | if (!channel_attr || !peer_attr) { |
| 787 | SendBadRequestResponse(msg); |
| 788 | return; |
| 789 | } |
| 790 | |
| 791 | // Check that channel id is valid. |
| 792 | int channel_id = channel_attr->value() >> 16; |
| 793 | if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) { |
| 794 | SendBadRequestResponse(msg); |
| 795 | return; |
| 796 | } |
| 797 | |
| 798 | // Check that this channel id isn't bound to another transport address, and |
| 799 | // that this transport address isn't bound to another channel id. |
| 800 | Channel* channel1 = FindChannel(channel_id); |
| 801 | Channel* channel2 = FindChannel(peer_attr->GetAddress()); |
| 802 | if (channel1 != channel2) { |
| 803 | SendBadRequestResponse(msg); |
| 804 | return; |
| 805 | } |
| 806 | |
| 807 | // Add or refresh this channel. |
| 808 | if (!channel1) { |
| 809 | channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress()); |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 810 | channel1->SignalDestroyed.connect( |
| 811 | this, &TurnServerAllocation::OnChannelDestroyed); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 812 | channels_.push_back(channel1); |
| 813 | } else { |
| 814 | channel1->Refresh(); |
| 815 | } |
| 816 | |
| 817 | // Channel binds also refresh permissions. |
| 818 | AddPermission(peer_attr->GetAddress().ipaddr()); |
| 819 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 820 | RTC_LOG(LS_INFO) << ToString() << ": Bound channel, id=" << channel_id |
Qingsi Wang | 20232a9 | 2019-09-06 12:51:17 -0700 | [diff] [blame] | 821 | << ", peer=" << peer_attr->GetAddress().ToSensitiveString(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 822 | |
| 823 | // Send a success response. |
| 824 | TurnMessage response; |
| 825 | InitResponse(msg, &response); |
| 826 | SendResponse(&response); |
| 827 | } |
| 828 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 829 | void TurnServerAllocation::HandleChannelData(const char* data, size_t size) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 830 | // Extract the channel number from the data. |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 831 | uint16_t channel_id = rtc::GetBE16(data); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 832 | 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 Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 838 | RTC_LOG(LS_WARNING) << ToString() |
| 839 | << ": Received channel data for invalid channel, id=" |
| 840 | << channel_id; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 841 | } |
| 842 | } |
| 843 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 844 | void TurnServerAllocation::OnExternalPacket( |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 845 | rtc::AsyncPacketSocket* socket, |
Niels Möller | e693381 | 2018-11-05 13:01:41 +0100 | [diff] [blame] | 846 | const char* data, |
| 847 | size_t size, |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 848 | const rtc::SocketAddress& addr, |
Niels Möller | e693381 | 2018-11-05 13:01:41 +0100 | [diff] [blame] | 849 | const int64_t& /* packet_time_us */) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 850 | RTC_DCHECK(external_socket_.get() == socket); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 851 | Channel* channel = FindChannel(addr); |
| 852 | if (channel) { |
| 853 | // There is a channel bound to this address. Send as a channel message. |
jbauch | f1f8720 | 2016-03-30 06:43:37 -0700 | [diff] [blame] | 854 | rtc::ByteBufferWriter buf; |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 855 | buf.WriteUInt16(channel->id()); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 856 | buf.WriteUInt16(static_cast<uint16_t>(size)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 857 | buf.WriteBytes(data, size); |
| 858 | server_->Send(&conn_, buf); |
Taylor Brandstetter | ef18470 | 2016-06-23 17:35:47 -0700 | [diff] [blame] | 859 | } else if (!server_->enable_permission_checks_ || |
| 860 | HasPermission(addr.ipaddr())) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 861 | // No channel, but a permission exists. Send as a data indication. |
| 862 | TurnMessage msg; |
| 863 | msg.SetType(TURN_DATA_INDICATION); |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 864 | msg.SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength)); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 865 | msg.AddAttribute(std::make_unique<StunXorAddressAttribute>( |
nisse | cc99bc2 | 2017-02-02 01:31:30 -0800 | [diff] [blame] | 866 | STUN_ATTR_XOR_PEER_ADDRESS, addr)); |
zstein | f42cc9d | 2017-03-27 16:17:19 -0700 | [diff] [blame] | 867 | msg.AddAttribute( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 868 | std::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size)); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 869 | server_->SendStun(&conn_, &msg); |
| 870 | } else { |
Jonas Olsson | d7d762d | 2018-03-28 09:47:51 +0200 | [diff] [blame] | 871 | RTC_LOG(LS_WARNING) |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 872 | << ToString() << ": Received external packet without permission, peer=" |
Qingsi Wang | 20232a9 | 2019-09-06 12:51:17 -0700 | [diff] [blame] | 873 | << addr.ToSensitiveString(); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 874 | } |
| 875 | } |
| 876 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 877 | int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 878 | // Return the smaller of our default lifetime and the requested lifetime. |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 879 | int lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 880 | const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME); |
honghaiz | 34b11eb | 2016-03-16 08:55:44 -0700 | [diff] [blame] | 881 | if (lifetime_attr && static_cast<int>(lifetime_attr->value()) < lifetime) { |
| 882 | lifetime = static_cast<int>(lifetime_attr->value()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 883 | } |
| 884 | return lifetime; |
| 885 | } |
| 886 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 887 | bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 888 | return (FindPermission(addr) != NULL); |
| 889 | } |
| 890 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 891 | void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 892 | Permission* perm = FindPermission(addr); |
| 893 | if (!perm) { |
| 894 | perm = new Permission(thread_, addr); |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 895 | perm->SignalDestroyed.connect(this, |
| 896 | &TurnServerAllocation::OnPermissionDestroyed); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 897 | perms_.push_back(perm); |
| 898 | } else { |
| 899 | perm->Refresh(); |
| 900 | } |
| 901 | } |
| 902 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 903 | TurnServerAllocation::Permission* TurnServerAllocation::FindPermission( |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 904 | const rtc::IPAddress& addr) const { |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 905 | for (PermissionList::const_iterator it = perms_.begin(); it != perms_.end(); |
| 906 | ++it) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 907 | if ((*it)->peer() == addr) |
| 908 | return *it; |
| 909 | } |
| 910 | return NULL; |
| 911 | } |
| 912 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 913 | TurnServerAllocation::Channel* TurnServerAllocation::FindChannel( |
| 914 | int channel_id) const { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 915 | for (ChannelList::const_iterator it = channels_.begin(); |
| 916 | it != channels_.end(); ++it) { |
| 917 | if ((*it)->id() == channel_id) |
| 918 | return *it; |
| 919 | } |
| 920 | return NULL; |
| 921 | } |
| 922 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 923 | TurnServerAllocation::Channel* TurnServerAllocation::FindChannel( |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 924 | const rtc::SocketAddress& addr) const { |
| 925 | for (ChannelList::const_iterator it = channels_.begin(); |
| 926 | it != channels_.end(); ++it) { |
| 927 | if ((*it)->peer() == addr) |
| 928 | return *it; |
| 929 | } |
| 930 | return NULL; |
| 931 | } |
| 932 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 933 | void TurnServerAllocation::SendResponse(TurnMessage* msg) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 934 | // Success responses always have M-I. |
| 935 | msg->AddMessageIntegrity(key_); |
| 936 | server_->SendStun(&conn_, msg); |
| 937 | } |
| 938 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 939 | void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 940 | SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST); |
| 941 | } |
| 942 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 943 | void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, |
| 944 | int code, |
| 945 | const std::string& reason) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 946 | server_->SendErrorResponse(&conn_, req, code, reason); |
| 947 | } |
| 948 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 949 | void TurnServerAllocation::SendExternal(const void* data, |
| 950 | size_t size, |
| 951 | const rtc::SocketAddress& peer) { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 952 | rtc::PacketOptions options; |
| 953 | external_socket_->SendTo(data, size, peer, options); |
| 954 | } |
| 955 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 956 | void TurnServerAllocation::OnMessage(rtc::Message* msg) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 957 | RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 958 | SignalDestroyed(this); |
| 959 | delete this; |
| 960 | } |
| 961 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 962 | void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) { |
Steve Anton | ae226f6 | 2019-01-29 12:47:38 -0800 | [diff] [blame] | 963 | auto it = absl::c_find(perms_, perm); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 964 | RTC_DCHECK(it != perms_.end()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 965 | perms_.erase(it); |
| 966 | } |
| 967 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 968 | void TurnServerAllocation::OnChannelDestroyed(Channel* channel) { |
Steve Anton | ae226f6 | 2019-01-29 12:47:38 -0800 | [diff] [blame] | 969 | auto it = absl::c_find(channels_, channel); |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 970 | RTC_DCHECK(it != channels_.end()); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 971 | channels_.erase(it); |
| 972 | } |
| 973 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 974 | TurnServerAllocation::Permission::Permission(rtc::Thread* thread, |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 975 | const rtc::IPAddress& peer) |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 976 | : thread_(thread), peer_(peer) { |
| 977 | Refresh(); |
| 978 | } |
| 979 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 980 | TurnServerAllocation::Permission::~Permission() { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 981 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
| 982 | } |
| 983 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 984 | void TurnServerAllocation::Permission::Refresh() { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 985 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
Taylor Brandstetter | 5d97a9a | 2016-06-10 14:17:27 -0700 | [diff] [blame] | 986 | thread_->PostDelayed(RTC_FROM_HERE, kPermissionTimeout, this, |
| 987 | MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 988 | } |
| 989 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 990 | void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 991 | RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 992 | SignalDestroyed(this); |
| 993 | delete this; |
| 994 | } |
| 995 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 996 | TurnServerAllocation::Channel::Channel(rtc::Thread* thread, |
| 997 | int id, |
| 998 | const rtc::SocketAddress& peer) |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 999 | : thread_(thread), id_(id), peer_(peer) { |
| 1000 | Refresh(); |
| 1001 | } |
| 1002 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 1003 | TurnServerAllocation::Channel::~Channel() { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 1004 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
| 1005 | } |
| 1006 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 1007 | void TurnServerAllocation::Channel::Refresh() { |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 1008 | thread_->Clear(this, MSG_ALLOCATION_TIMEOUT); |
Taylor Brandstetter | 5d97a9a | 2016-06-10 14:17:27 -0700 | [diff] [blame] | 1009 | thread_->PostDelayed(RTC_FROM_HERE, kChannelTimeout, this, |
| 1010 | MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 1011 | } |
| 1012 | |
pthatcher@webrtc.org | 0ba1533 | 2015-01-10 00:47:02 +0000 | [diff] [blame] | 1013 | void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 1014 | RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT); |
henrike@webrtc.org | 269fb4b | 2014-10-28 22:20:11 +0000 | [diff] [blame] | 1015 | SignalDestroyed(this); |
| 1016 | delete this; |
| 1017 | } |
| 1018 | |
| 1019 | } // namespace cricket |