diff options
-rw-r--r-- | webrtc/p2p/base/port.cc | 16 | ||||
-rw-r--r-- | webrtc/p2p/base/port.h | 16 | ||||
-rw-r--r-- | webrtc/p2p/base/turnport.cc | 6 | ||||
-rw-r--r-- | webrtc/p2p/base/turnport.h | 1 | ||||
-rw-r--r-- | webrtc/p2p/base/turnport_unittest.cc | 51 | ||||
-rw-r--r-- | webrtc/p2p/base/turnserver.cc | 6 | ||||
-rw-r--r-- | webrtc/p2p/base/turnserver.h | 6 |
7 files changed, 85 insertions, 17 deletions
diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc index 90275aa141..ddf38dcb18 100644 --- a/webrtc/p2p/base/port.cc +++ b/webrtc/p2p/base/port.cc @@ -1008,6 +1008,11 @@ void Connection::Destroy() { port_->thread()->Post(this, MSG_DELETE); } +void Connection::FailAndDestroy() { + set_state(Connection::STATE_FAILED); + Destroy(); +} + void Connection::PrintPingsSinceLastResponse(std::string* s, size_t max) { std::ostringstream oss; oss << std::boolalpha; @@ -1242,8 +1247,7 @@ void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request, // This is not a valid connection. LOG_J(LS_ERROR, this) << "Received STUN error response, code=" << error_code << "; killing connection"; - set_state(STATE_FAILED); - Destroy(); + FailAndDestroy(); } } @@ -1390,10 +1394,10 @@ void Connection::MaybeAddPrflxCandidate(ConnectionRequest* request, SignalStateChange(this); } -ProxyConnection::ProxyConnection(Port* port, size_t index, - const Candidate& candidate) - : Connection(port, index, candidate), error_(0) { -} +ProxyConnection::ProxyConnection(Port* port, + size_t index, + const Candidate& remote_candidate) + : Connection(port, index, remote_candidate) {} int ProxyConnection::Send(const void* data, size_t size, const rtc::PacketOptions& options) { diff --git a/webrtc/p2p/base/port.h b/webrtc/p2p/base/port.h index 62ca3a50b7..f3d2110c3e 100644 --- a/webrtc/p2p/base/port.h +++ b/webrtc/p2p/base/port.h @@ -514,6 +514,9 @@ class Connection : public rtc::MessageHandler, // Makes the connection go away. void Destroy(); + // Makes the connection go away, in a failed state. + void FailAndDestroy(); + // Checks that the state of this connection is up-to-date. The argument is // the current time, which is compared against various timeouts. void UpdateState(uint32_t now); @@ -634,17 +637,18 @@ class Connection : public rtc::MessageHandler, friend class ConnectionRequest; }; -// ProxyConnection defers all the interesting work to the port +// ProxyConnection defers all the interesting work to the port. class ProxyConnection : public Connection { public: - ProxyConnection(Port* port, size_t index, const Candidate& candidate); + ProxyConnection(Port* port, size_t index, const Candidate& remote_candidate); - virtual int Send(const void* data, size_t size, - const rtc::PacketOptions& options); - virtual int GetError() { return error_; } + int Send(const void* data, + size_t size, + const rtc::PacketOptions& options) override; + int GetError() override { return error_; } private: - int error_; + int error_ = 0; }; } // namespace cricket diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc index 5e88365a83..20c2b6002f 100644 --- a/webrtc/p2p/base/turnport.cc +++ b/webrtc/p2p/base/turnport.cc @@ -1398,6 +1398,12 @@ void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) { } else { // Send signal with error code. port_->SignalCreatePermissionResult(port_, ext_addr_, code); + Connection* c = port_->GetConnection(ext_addr_); + if (c) { + LOG_J(LS_ERROR, c) << "Received TURN CreatePermission error response, " + << "code=" << code << "; killing connection."; + c->FailAndDestroy(); + } } } diff --git a/webrtc/p2p/base/turnport.h b/webrtc/p2p/base/turnport.h index db2a3ceeee..0cdc291101 100644 --- a/webrtc/p2p/base/turnport.h +++ b/webrtc/p2p/base/turnport.h @@ -133,7 +133,6 @@ class TurnPort : public Port { const rtc::SocketAddress&, const rtc::SocketAddress&> SignalResolvedServerAddress; - // This signal is only for testing purpose. sigslot::signal3<TurnPort*, const rtc::SocketAddress&, int> SignalCreatePermissionResult; // For testing only. diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc index dcc88bba14..d9353cc95b 100644 --- a/webrtc/p2p/base/turnport_unittest.cc +++ b/webrtc/p2p/base/turnport_unittest.cc @@ -100,6 +100,24 @@ class TurnPortTestVirtualSocketServer : public rtc::VirtualSocketServer { using rtc::VirtualSocketServer::LookupBinding; }; +class TestConnectionWrapper : public sigslot::has_slots<> { + public: + TestConnectionWrapper(Connection* conn) : connection_(conn) { + conn->SignalDestroyed.connect( + this, &TestConnectionWrapper::OnConnectionDestroyed); + } + + Connection* connection() { return connection_; } + + private: + void OnConnectionDestroyed(Connection* conn) { + ASSERT_TRUE(conn == connection_); + connection_ = nullptr; + } + + Connection* connection_; +}; + class TurnPortTest : public testing::Test, public sigslot::has_slots<>, public rtc::MessageHandler { @@ -256,11 +274,13 @@ class TurnPortTest : public testing::Test, turn_port_->SignalCreatePermissionResult.connect(this, &TurnPortTest::OnTurnCreatePermissionResult); } - void CreateUdpPort() { + + void CreateUdpPort() { CreateUdpPort(kLocalAddr2); } + + void CreateUdpPort(const SocketAddress& address) { udp_port_.reset(UDPPort::Create(main_, &socket_factory_, &network_, - kLocalAddr2.ipaddr(), 0, 0, - kIceUfrag2, kIcePwd2, - std::string(), false)); + address.ipaddr(), 0, 0, kIceUfrag2, + kIcePwd2, std::string(), false)); // UDP port will be controlled. udp_port_->SetIceRole(cricket::ICEROLE_CONTROLLED); udp_port_->SignalPortComplete.connect( @@ -849,6 +869,29 @@ TEST_F(TurnPortTest, TestOriginHeader) { EXPECT_EQ(kTestOrigin, turn_server_.FindAllocation(local_address)->origin()); } +// Test that a CreatePermission failure will result in the connection being +// destroyed. +TEST_F(TurnPortTest, TestConnectionDestroyedOnCreatePermissionFailure) { + turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.server()->set_reject_private_addresses(true); + CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); + turn_port_->PrepareAddress(); + ASSERT_TRUE_WAIT(turn_ready_, kTimeout); + + CreateUdpPort(SocketAddress("10.0.0.10", 0)); + udp_port_->PrepareAddress(); + ASSERT_TRUE_WAIT(udp_ready_, kTimeout); + // Create a connection. + TestConnectionWrapper conn(turn_port_->CreateConnection( + udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE)); + ASSERT_TRUE(conn.connection() != nullptr); + + // Asynchronously, CreatePermission request should be sent and fail, closing + // the connection. + EXPECT_TRUE_WAIT(conn.connection() == nullptr, kTimeout); + EXPECT_FALSE(turn_create_permission_success_); +} + // Test that a TURN allocation is released when the port is closed. TEST_F(TurnPortTest, TestTurnReleaseAllocation) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc index 8d40a9030c..1502cdd52e 100644 --- a/webrtc/p2p/base/turnserver.cc +++ b/webrtc/p2p/base/turnserver.cc @@ -698,6 +698,12 @@ void TurnServerAllocation::HandleCreatePermissionRequest( return; } + if (server_->reject_private_addresses_ && + rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) { + SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN); + return; + } + // Add this permission. AddPermission(peer_attr->GetAddress().ipaddr()); diff --git a/webrtc/p2p/base/turnserver.h b/webrtc/p2p/base/turnserver.h index d3bd77a866..113bd4c462 100644 --- a/webrtc/p2p/base/turnserver.h +++ b/webrtc/p2p/base/turnserver.h @@ -183,6 +183,11 @@ class TurnServer : public sigslot::has_slots<> { void set_enable_otu_nonce(bool enable) { enable_otu_nonce_ = enable; } + // If set to true, reject CreatePermission requests to RFC1918 addresses. + void set_reject_private_addresses(bool filter) { + reject_private_addresses_ = filter; + } + // Starts listening for packets from internal clients. void AddInternalSocket(rtc::AsyncPacketSocket* socket, ProtocolType proto); @@ -255,6 +260,7 @@ class TurnServer : public sigslot::has_slots<> { // otu - one-time-use. Server will respond with 438 if it's // sees the same nonce in next transaction. bool enable_otu_nonce_; + bool reject_private_addresses_ = false; InternalSocketMap server_sockets_; ServerSocketMap server_listen_sockets_; |