blob: bc15b870c132c653fa108f756e4179152637c7c9 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 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
11#if defined(_MSC_VER) && _MSC_VER < 1300
12#pragma warning(disable:4786)
13#endif
14
15#include <time.h>
16#include <errno.h>
17
18#if defined(WEBRTC_WIN)
19#define WIN32_LEAN_AND_MEAN
20#include <windows.h>
21#include <winsock2.h>
22#include <ws2tcpip.h>
23#define SECURITY_WIN32
24#include <security.h>
25#endif
26
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000027#include <algorithm>
28
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029#include "webrtc/base/bytebuffer.h"
nissec80e7412017-01-11 05:56:46 -080030#include "webrtc/base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031#include "webrtc/base/logging.h"
32#include "webrtc/base/socketadapters.h"
33#include "webrtc/base/stringencode.h"
34#include "webrtc/base/stringutils.h"
35
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036namespace rtc {
37
38BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t size)
39 : AsyncSocketAdapter(socket), buffer_size_(size),
40 data_len_(0), buffering_(false) {
41 buffer_ = new char[buffer_size_];
42}
43
44BufferedReadAdapter::~BufferedReadAdapter() {
45 delete [] buffer_;
46}
47
48int BufferedReadAdapter::Send(const void *pv, size_t cb) {
49 if (buffering_) {
50 // TODO: Spoof error better; Signal Writeable
51 socket_->SetError(EWOULDBLOCK);
52 return -1;
53 }
54 return AsyncSocketAdapter::Send(pv, cb);
55}
56
Stefan Holmer9131efd2016-05-23 18:19:26 +020057int BufferedReadAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000058 if (buffering_) {
59 socket_->SetError(EWOULDBLOCK);
60 return -1;
61 }
62
63 size_t read = 0;
64
65 if (data_len_) {
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000066 read = std::min(cb, data_len_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000067 memcpy(pv, buffer_, read);
68 data_len_ -= read;
69 if (data_len_ > 0) {
70 memmove(buffer_, buffer_ + read, data_len_);
71 }
72 pv = static_cast<char *>(pv) + read;
73 cb -= read;
74 }
75
76 // FIX: If cb == 0, we won't generate another read event
77
Stefan Holmer9131efd2016-05-23 18:19:26 +020078 int res = AsyncSocketAdapter::Recv(pv, cb, timestamp);
deadbeefc5d0d952015-07-16 10:22:21 -070079 if (res >= 0) {
80 // Read from socket and possibly buffer; return combined length
81 return res + static_cast<int>(read);
82 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000083
deadbeefc5d0d952015-07-16 10:22:21 -070084 if (read > 0) {
85 // Failed to read from socket, but still read something from buffer
86 return static_cast<int>(read);
87 }
88
89 // Didn't read anything; return error from socket
90 return res;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000091}
92
93void BufferedReadAdapter::BufferInput(bool on) {
94 buffering_ = on;
95}
96
97void BufferedReadAdapter::OnReadEvent(AsyncSocket * socket) {
nisseede5da42017-01-12 05:15:36 -080098 RTC_DCHECK(socket == socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000099
100 if (!buffering_) {
101 AsyncSocketAdapter::OnReadEvent(socket);
102 return;
103 }
104
105 if (data_len_ >= buffer_size_) {
106 LOG(INFO) << "Input buffer overflow";
nissec80e7412017-01-11 05:56:46 -0800107 RTC_NOTREACHED();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000108 data_len_ = 0;
109 }
110
Stefan Holmer9131efd2016-05-23 18:19:26 +0200111 int len =
112 socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000113 if (len < 0) {
114 // TODO: Do something better like forwarding the error to the user.
115 LOG_ERR(INFO) << "Recv";
116 return;
117 }
118
119 data_len_ += len;
120
121 ProcessInput(buffer_, &data_len_);
122}
123
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000124AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
125 size_t buffer_size)
126 : BufferedReadAdapter(socket, buffer_size) {
127}
128
129AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
130
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000131///////////////////////////////////////////////////////////////////////////////
132
133// This is a SSL v2 CLIENT_HELLO message.
134// TODO: Should this have a session id? The response doesn't have a
135// certificate, so the hello should have a session id.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200136static const uint8_t kSslClientHello[] = {
137 0x80, 0x46, // msg len
138 0x01, // CLIENT_HELLO
139 0x03, 0x01, // SSL 3.1
140 0x00, 0x2d, // ciphersuite len
141 0x00, 0x00, // session id len
142 0x00, 0x10, // challenge len
143 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0, // ciphersuites
144 0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80, //
145 0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, //
146 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, //
147 0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, //
148 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc, // challenge
149 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea //
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000150};
151
152// This is a TLSv1 SERVER_HELLO message.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200153static const uint8_t kSslServerHello[] = {
154 0x16, // handshake message
155 0x03, 0x01, // SSL 3.1
156 0x00, 0x4a, // message len
157 0x02, // SERVER_HELLO
158 0x00, 0x00, 0x46, // handshake len
159 0x03, 0x01, // SSL 3.1
160 0x42, 0x85, 0x45, 0xa7, 0x27, 0xa9, 0x5d, 0xa0, // server random
161 0xb3, 0xc5, 0xe7, 0x53, 0xda, 0x48, 0x2b, 0x3f, //
162 0xc6, 0x5a, 0xca, 0x89, 0xc1, 0x58, 0x52, 0xa1, //
163 0x78, 0x3c, 0x5b, 0x17, 0x46, 0x00, 0x85, 0x3f, //
164 0x20, // session id len
165 0x0e, 0xd3, 0x06, 0x72, 0x5b, 0x5b, 0x1b, 0x5f, // session id
166 0x15, 0xac, 0x13, 0xf9, 0x88, 0x53, 0x9d, 0x9b, //
167 0xe8, 0x3d, 0x7b, 0x0c, 0x30, 0x32, 0x6e, 0x38, //
168 0x4d, 0xa2, 0x75, 0x57, 0x41, 0x6c, 0x34, 0x5c, //
169 0x00, 0x04, // RSA/RC4-128/MD5
170 0x00 // null compression
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000171};
172
173AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
174 : BufferedReadAdapter(socket, 1024) {
175}
176
177int AsyncSSLSocket::Connect(const SocketAddress& addr) {
178 // Begin buffering before we connect, so that there isn't a race condition
179 // between potential senders and receiving the OnConnectEvent signal
180 BufferInput(true);
181 return BufferedReadAdapter::Connect(addr);
182}
183
184void AsyncSSLSocket::OnConnectEvent(AsyncSocket * socket) {
nisseede5da42017-01-12 05:15:36 -0800185 RTC_DCHECK(socket == socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000186 // TODO: we could buffer output too...
nissec16fa5e2017-02-07 07:18:43 -0800187 const int res = DirectSend(kSslClientHello, sizeof(kSslClientHello));
188 RTC_DCHECK_EQ(sizeof(kSslClientHello), res);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000189}
190
191void AsyncSSLSocket::ProcessInput(char* data, size_t* len) {
192 if (*len < sizeof(kSslServerHello))
193 return;
194
195 if (memcmp(kSslServerHello, data, sizeof(kSslServerHello)) != 0) {
196 Close();
197 SignalCloseEvent(this, 0); // TODO: error code?
198 return;
199 }
200
201 *len -= sizeof(kSslServerHello);
202 if (*len > 0) {
203 memmove(data, data + sizeof(kSslServerHello), *len);
204 }
205
206 bool remainder = (*len > 0);
207 BufferInput(false);
208 SignalConnectEvent(this);
209
210 // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
211 if (remainder)
212 SignalReadEvent(this);
213}
214
215AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
216 : BufferedReadAdapter(socket, 1024) {
217 BufferInput(true);
218}
219
220void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
221 // We only accept client hello messages.
222 if (*len < sizeof(kSslClientHello)) {
223 return;
224 }
225
226 if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) {
227 Close();
228 SignalCloseEvent(this, 0);
229 return;
230 }
231
232 *len -= sizeof(kSslClientHello);
233
234 // Clients should not send more data until the handshake is completed.
nisseede5da42017-01-12 05:15:36 -0800235 RTC_DCHECK(*len == 0);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000236
237 // Send a server hello back to the client.
238 DirectSend(kSslServerHello, sizeof(kSslServerHello));
239
240 // Handshake completed for us, redirect input to our parent.
241 BufferInput(false);
242}
243
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000244} // namespace rtc