Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: content/browser/renderer_host/p2p_socket_host_udp_unittest.cc

Issue 6800023: Security restrictions for P2P UDP Sockets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/p2p_socket_host_udp.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "build/build_config.h"
6
7 #if defined(OS_WIN)
8 #include <winsock2.h> // for htonl
9 #else
10 #include <arpa/inet.h>
11 #endif
12
13 #include <deque>
14 #include <vector>
15
16 #include "content/browser/renderer_host/p2p_socket_host_udp.h"
17 #include "content/common/p2p_messages.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/udp/datagram_server_socket.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using ::testing::_;
26 using ::testing::DeleteArg;
27 using ::testing::DoAll;
28 using ::testing::Return;
29
30 namespace {
31
32 const char kTestLocalIpAddress[] = "123.44.22.4";
33 const char kTestIpAddress1[] = "123.44.22.31";
34 const int kTestPort1 = 234;
35 const char kTestIpAddress2[] = "133.11.22.33";
36 const int kTestPort2 = 543;
37
38 const int kStunHeaderSize = 20;
39 const uint16 kStunBindingRequest = 0x0001;
40 const uint16 kStunBindingResponse = 0x0102;
41 const uint16 kStunBindingError = 0x0111;
42 const uint32 kStunMagicCookie = 0x2112A442;
43
44 class FakeDatagramServerSocket : public net::DatagramServerSocket {
45 public:
46 typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket;
47
48 // P2PSocketHostUdp destroyes a socket on errors so sent packets
49 // need to be stored outside of this object.
50 explicit FakeDatagramServerSocket(std::deque<UDPPacket>* sent_packets)
51 : sent_packets_(sent_packets), recv_callback_(NULL) {
52 }
53
54 virtual void Close() OVERRIDE {
55 }
56
57 virtual int GetPeerAddress(net::IPEndPoint* address) const OVERRIDE {
58 NOTREACHED();
59 return net::ERR_SOCKET_NOT_CONNECTED;
60 }
61
62 virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE {
63 *address = address_;
64 return 0;
65 }
66
67 virtual int Listen(const net::IPEndPoint& address) OVERRIDE {
68 address_ = address;
69 return 0;
70 }
71
72 virtual int RecvFrom(net::IOBuffer* buf, int buf_len,
73 net::IPEndPoint* address,
74 net::CompletionCallback* callback) OVERRIDE {
75 CHECK(!recv_callback_);
76 if (incoming_packets_.size() > 0) {
77 scoped_refptr<net::IOBuffer> buffer(buf);
78 int size = std::min(
79 static_cast<int>(incoming_packets_.front().second.size()), buf_len);
80 memcpy(buffer->data(), &*incoming_packets_.front().second.begin(), size);
81 *address = incoming_packets_.front().first;
82 incoming_packets_.pop_front();
83 return size;
84 } else {
85 recv_callback_ = callback;
86 recv_buffer_ = buf;
87 recv_size_ = buf_len;
88 recv_address_ = address;
89 return net::ERR_IO_PENDING;
90 }
91 }
92
93 virtual int SendTo(net::IOBuffer* buf, int buf_len,
94 const net::IPEndPoint& address,
95 net::CompletionCallback* callback) OVERRIDE {
96 scoped_refptr<net::IOBuffer> buffer(buf);
97 std::vector<char> data_vector(buffer->data(), buffer->data() + buf_len);
98 sent_packets_->push_back(UDPPacket(address, data_vector));
99 return buf_len;
100 }
101
102 void ReceivePacket(const net::IPEndPoint& address, std::vector<char> data) {
103 if (recv_callback_) {
104 int size = std::min(recv_size_, static_cast<int>(data.size()));
105 memcpy(recv_buffer_->data(), &*data.begin(), size);
106 *recv_address_ = address;
107 net::CompletionCallback* cb = recv_callback_;
108 recv_callback_ = NULL;
109 recv_buffer_ = NULL;
110 cb->Run(size);
111 } else {
112 incoming_packets_.push_back(UDPPacket(address, data));
113 }
114 }
115
116 private:
117 net::IPEndPoint address_;
118 std::deque<UDPPacket>* sent_packets_;
119 std::deque<UDPPacket> incoming_packets_;
120
121 scoped_refptr<net::IOBuffer> recv_buffer_;
122 net::IPEndPoint* recv_address_;
123 int recv_size_;
124 net::CompletionCallback* recv_callback_;
125 };
126
127 class MockIPCSender : public IPC::Message::Sender {
128 public:
129 MOCK_METHOD1(Send, bool(IPC::Message* msg));
130 };
131
132 MATCHER_P(MatchMessage, type, "") {
133 return arg->type() == type;
134 }
135
136 } // namespace
137
138 class P2PSocketHostUdpTest : public testing::Test {
139 protected:
140 void SetUp() OVERRIDE {
141 EXPECT_CALL(sender_, Send(
142 MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
143 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
144
145 socket_host_.reset(new P2PSocketHostUdp(&sender_, 0, 0));
146 socket_ = new FakeDatagramServerSocket(&sent_packets_);
147 socket_host_->socket_.reset(socket_);
148
149 net::IPAddressNumber local_ip;
150 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestLocalIpAddress, &local_ip));
151 local_address_ = net::IPEndPoint(local_ip, kTestPort1);
152 socket_host_->Init(local_address_);
153
154 net::IPAddressNumber ip1;
155 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress1, &ip1));
156 dest1_ = net::IPEndPoint(ip1, kTestPort1);
157 net::IPAddressNumber ip2;
158 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress2, &ip2));
159 dest2_ = net::IPEndPoint(ip2, kTestPort2);
160 }
161
162 void CreateRandomPacket(std::vector<char>* packet) {
163 size_t size = kStunHeaderSize + rand() % 1000;
164 packet->resize(size);
165 for (size_t i = 0; i < size; i++) {
166 (*packet)[i] = rand() % 256;
167 }
168 // Always set the first bit to ensure that generated packet is not
169 // valid STUN packet.
170 (*packet)[0] = (*packet)[0] | 0x80;
171 }
172
173 void CreateStunPacket(std::vector<char>* packet, uint16 type) {
174 CreateRandomPacket(packet);
175 *reinterpret_cast<uint16*>(&*packet->begin()) = htons(type);
176 *reinterpret_cast<uint16*>(&*packet->begin() + 2) =
177 htons(packet->size() - kStunHeaderSize);
178 *reinterpret_cast<uint32*>(&*packet->begin() + 4) = htonl(kStunMagicCookie);
179 }
180
181 void CreateStunRequest(std::vector<char>* packet) {
182 CreateStunPacket(packet, kStunBindingRequest);
183 }
184
185 void CreateStunResponse(std::vector<char>* packet) {
186 CreateStunPacket(packet, kStunBindingResponse);
187 }
188
189 void CreateStunError(std::vector<char>* packet) {
190 CreateStunPacket(packet, kStunBindingError);
191 }
192
193 std::deque<FakeDatagramServerSocket::UDPPacket> sent_packets_;
194 FakeDatagramServerSocket* socket_; // Owned by |socket_host_|.
195 scoped_ptr<P2PSocketHostUdp> socket_host_;
196 MockIPCSender sender_;
197
198 net::IPEndPoint local_address_;
199
200 net::IPEndPoint dest1_;
201 net::IPEndPoint dest2_;
202 };
203
204 // Verify that we can send STUN messages before we receive anything
205 // from the other side.
206 TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) {
207 std::vector<char> packet1;
208 CreateStunRequest(&packet1);
209 socket_host_->Send(dest1_, packet1);
210
211 std::vector<char> packet2;
212 CreateStunResponse(&packet2);
213 socket_host_->Send(dest1_, packet2);
214
215 std::vector<char> packet3;
216 CreateStunError(&packet3);
217 socket_host_->Send(dest1_, packet3);
218
219 ASSERT_EQ(sent_packets_.size(), 3U);
220 ASSERT_EQ(sent_packets_[0].second, packet1);
221 ASSERT_EQ(sent_packets_[1].second, packet2);
222 ASSERT_EQ(sent_packets_[2].second, packet3);
223 }
224
225 // Verify that no data packets can be sent before STUN binding has
226 // finished.
227 TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) {
228 EXPECT_CALL(sender_, Send(
229 MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
230 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
231
232 std::vector<char> packet;
233 CreateRandomPacket(&packet);
234 socket_host_->Send(dest1_, packet);
235
236 ASSERT_EQ(sent_packets_.size(), 0U);
237 }
238
239 // Verify that we can send data after we've received STUN request
240 // from the other side.
241 TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) {
242 EXPECT_CALL(sender_, Send(
243 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID))))
244 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
245
246 // Receive packet from |dest1_|.
247 std::vector<char> request_packet;
248 CreateStunRequest(&request_packet);
249 socket_->ReceivePacket(dest1_, request_packet);
250
251 // Now we should be able to send any data to |dest1_|.
252 std::vector<char> packet;
253 CreateRandomPacket(&packet);
254 socket_host_->Send(dest1_, packet);
255
256 ASSERT_EQ(1U, sent_packets_.size());
257 ASSERT_EQ(dest1_, sent_packets_[0].first);
258 }
259
260 // Verify that we can send data after we've received STUN response
261 // from the other side.
262 TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) {
263 EXPECT_CALL(sender_, Send(
264 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID))))
265 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
266
267 // Receive packet from |dest1_|.
268 std::vector<char> request_packet;
269 CreateStunRequest(&request_packet);
270 socket_->ReceivePacket(dest1_, request_packet);
271
272 // Now we should be able to send any data to |dest1_|.
273 std::vector<char> packet;
274 CreateRandomPacket(&packet);
275 socket_host_->Send(dest1_, packet);
276
277 ASSERT_EQ(1U, sent_packets_.size());
278 ASSERT_EQ(dest1_, sent_packets_[0].first);
279 }
280
281 // Verify messages still cannot be sent to an unathorized host after
282 // successful binding with different host.
283 TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
284 EXPECT_CALL(sender_, Send(
285 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID))))
286 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
287
288 // Receive packet from |dest1_|.
289 std::vector<char> request_packet;
290 CreateStunRequest(&request_packet);
291 socket_->ReceivePacket(dest1_, request_packet);
292
293 // Should fail when trying to send the same packet to |dest2_|.
294 std::vector<char> packet;
295 CreateRandomPacket(&packet);
296 EXPECT_CALL(sender_, Send(
297 MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
298 .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
299 socket_host_->Send(dest2_, packet);
300 }
OLDNEW
« no previous file with comments | « content/browser/renderer_host/p2p_socket_host_udp.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698