Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/http/TunnelUtils.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_net_TLSFilterTransaction_h
8
#define mozilla_net_TLSFilterTransaction_h
9
10
#include "mozilla/Attributes.h"
11
#include "mozilla/UniquePtr.h"
12
#include "nsAHttpTransaction.h"
13
#include "nsIAsyncInputStream.h"
14
#include "nsIAsyncOutputStream.h"
15
#include "nsINamed.h"
16
#include "nsISocketTransport.h"
17
#include "nsITimer.h"
18
#include "NullHttpTransaction.h"
19
#include "mozilla/TimeStamp.h"
20
#include "prio.h"
21
22
// a TLSFilterTransaction wraps another nsAHttpTransaction but
23
// applies a encode/decode filter of TLS onto the ReadSegments
24
// and WriteSegments data. It is not used for basic https://
25
// but it is used for supplemental TLS tunnels - such as those
26
// needed by CONNECT tunnels in HTTP/2 or even CONNECT tunnels when
27
// the underlying proxy connection is already running TLS
28
//
29
// HTTP/2 CONNECT tunnels cannot use pushed IO layers because of
30
// the multiplexing involved on the base stream. i.e. the base stream
31
// once it is decrypted may have parts that are encrypted with a
32
// variety of keys, or none at all
33
34
/* ************************************************************************
35
The input path of http over a spdy CONNECT tunnel once it is established as a stream
36
37
note the "real http transaction" can be either a http/1 transaction or another spdy session
38
inside the tunnel.
39
40
  nsHttpConnection::OnInputStreamReady (real socket)
41
  nsHttpConnection::OnSocketReadable()
42
  SpdySession::WriteSegment()
43
  SpdyStream::WriteSegment (tunnel stream)
44
  SpdyConnectTransaction::WriteSegment
45
  SpdyStream::OnWriteSegment(tunnel stream)
46
  SpdySession::OnWriteSegment()
47
  SpdySession::NetworkRead()
48
  nsHttpConnection::OnWriteSegment (real socket)
49
  realSocketIn->Read() return data from network
50
51
now pop the stack back up to SpdyConnectTransaction::WriteSegment, the data
52
that has been read is stored mInputData
53
54
  SpdyConnectTransaction.mTunneledConn::OnInputStreamReady(mTunnelStreamIn)
55
  SpdyConnectTransaction.mTunneledConn::OnSocketReadable()
56
  TLSFilterTransaction::WriteSegment()
57
  nsHttpTransaction::WriteSegment(real http transaction)
58
  TLSFilterTransaction::OnWriteSegment() removes tls on way back up stack
59
  SpdyConnectTransaction.mTunneledConn::OnWriteSegment()
60
  SpdyConnectTransaction.mTunneledConn.mTunnelStreamIn->Read() // gets data from mInputData
61
62
The output path works similarly:
63
  nsHttpConnection::OnOutputStreamReady (real socket)
64
  nsHttpConnection::OnSocketWritable()
65
  SpdySession::ReadSegments (locates tunnel)
66
  SpdyStream::ReadSegments (tunnel stream)
67
  SpdyConnectTransaction::ReadSegments()
68
  SpdyConnectTransaction.mTunneledConn::OnOutputStreamReady (tunnel connection)
69
  SpdyConnectTransaction.mTunneledConn::OnSocketWritable (tunnel connection)
70
  TLSFilterTransaction::ReadSegment()
71
  nsHttpTransaction::ReadSegment (real http transaction generates plaintext on way down)
72
  TLSFilterTransaction::OnReadSegment (BUF and LEN gets encrypted here on way down)
73
  SpdyConnectTransaction.mTunneledConn::OnReadSegment (BUF and LEN) (tunnel connection)
74
  SpdyConnectTransaction.mTunneledConn.mTunnelStreamOut->Write(BUF, LEN) .. get stored in mOutputData
75
76
Now pop the stack back up to SpdyConnectTransaction::ReadSegment(), where it has
77
the encrypted text available in mOutputData
78
79
  SpdyStream->OnReadSegment(BUF,LEN) from mOutputData. Tunnel stream
80
  SpdySession->OnReadSegment() // encrypted data gets put in a data frame
81
  nsHttpConnection->OnReadSegment()
82
  realSocketOut->write() writes data to network
83
84
**************************************************************************/
85
86
struct PRSocketOptionData;
87
88
namespace mozilla { namespace net {
89
90
class nsHttpRequestHead;
91
class NullHttpTransaction;
92
class TLSFilterTransaction;
93
94
class NudgeTunnelCallback : public nsISupports
95
{
96
public:
97
  virtual void OnTunnelNudged(TLSFilterTransaction *) = 0;
98
};
99
100
#define NS_DECL_NUDGETUNNELCALLBACK void OnTunnelNudged(TLSFilterTransaction *) override;
101
102
class TLSFilterTransaction final
103
  : public nsAHttpTransaction
104
  , public nsAHttpSegmentReader
105
  , public nsAHttpSegmentWriter
106
  , public nsITimerCallback
107
  , public nsINamed
108
{
109
  ~TLSFilterTransaction();
110
public:
111
  NS_DECL_THREADSAFE_ISUPPORTS
112
  NS_DECL_NSAHTTPTRANSACTION
113
  NS_DECL_NSAHTTPSEGMENTREADER
114
  NS_DECL_NSAHTTPSEGMENTWRITER
115
  NS_DECL_NSITIMERCALLBACK
116
  NS_DECL_NSINAMED
117
118
  TLSFilterTransaction(nsAHttpTransaction *aWrappedTransaction,
119
                       const char *tlsHost, int32_t tlsPort,
120
                       nsAHttpSegmentReader *reader,
121
                       nsAHttpSegmentWriter *writer);
122
123
0
  const nsAHttpTransaction *Transaction() const { return mTransaction.get(); }
124
  MOZ_MUST_USE nsresult CommitToSegmentSize(uint32_t size,
125
                                            bool forceCommitment) override;
126
  MOZ_MUST_USE nsresult GetTransactionSecurityInfo(nsISupports **) override;
127
  MOZ_MUST_USE nsresult NudgeTunnel(NudgeTunnelCallback *callback);
128
  MOZ_MUST_USE nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans);
129
  void     newIODriver(nsIAsyncInputStream *aSocketIn,
130
                       nsIAsyncOutputStream *aSocketOut,
131
                       nsIAsyncInputStream **outSocketIn,
132
                       nsIAsyncOutputStream **outSocketOut);
133
134
  // nsAHttpTransaction overloads
135
  bool IsNullTransaction() override;
136
  NullHttpTransaction *QueryNullTransaction() override;
137
  nsHttpTransaction *QueryHttpTransaction() override;
138
  SpdyConnectTransaction *QuerySpdyConnectTransaction() override;
139
140
private:
141
  MOZ_MUST_USE nsresult StartTimerCallback();
142
  void Cleanup();
143
  int32_t FilterOutput(const char *aBuf, int32_t aAmount);
144
  int32_t FilterInput(char *aBuf, int32_t aAmount);
145
146
  static PRStatus GetPeerName(PRFileDesc *fd, PRNetAddr*addr);
147
  static PRStatus GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data);
148
  static PRStatus SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data);
149
  static int32_t FilterWrite(PRFileDesc *fd, const void *buf, int32_t amount);
150
  static int32_t FilterRead(PRFileDesc *fd, void *buf, int32_t amount);
151
  static int32_t FilterSend(PRFileDesc *fd, const void *buf, int32_t amount, int flags,
152
                             PRIntervalTime timeout);
153
  static int32_t FilterRecv(PRFileDesc *fd, void *buf, int32_t amount, int flags,
154
                             PRIntervalTime timeout);
155
  static PRStatus FilterClose(PRFileDesc *fd);
156
157
private:
158
  RefPtr<nsAHttpTransaction> mTransaction;
159
  nsCOMPtr<nsISupports> mSecInfo;
160
  nsCOMPtr<nsITimer> mTimer;
161
  RefPtr<NudgeTunnelCallback> mNudgeCallback;
162
163
  // buffered network output, after encryption
164
  UniquePtr<char[]> mEncryptedText;
165
  uint32_t mEncryptedTextUsed;
166
  uint32_t mEncryptedTextSize;
167
168
  PRFileDesc *mFD;
169
  nsAHttpSegmentReader *mSegmentReader;
170
  nsAHttpSegmentWriter *mSegmentWriter;
171
172
  nsresult mFilterReadCode;
173
  bool mForce;
174
  bool mReadSegmentBlocked;
175
  uint32_t mNudgeCounter;
176
};
177
178
class SocketTransportShim;
179
class InputStreamShim;
180
class OutputStreamShim;
181
class nsHttpConnection;
182
183
class SpdyConnectTransaction final : public NullHttpTransaction
184
{
185
public:
186
  SpdyConnectTransaction(nsHttpConnectionInfo *ci,
187
                         nsIInterfaceRequestor *callbacks,
188
                         uint32_t caps,
189
                         nsHttpTransaction *trans,
190
                         nsAHttpConnection *session);
191
  ~SpdyConnectTransaction();
192
193
0
  SpdyConnectTransaction *QuerySpdyConnectTransaction() override { return this; }
194
195
  // A transaction is forced into plaintext when it is intended to be used as a CONNECT
196
  // tunnel but the setup fails. The plaintext only carries the CONNECT error.
197
  void ForcePlainText();
198
  void MapStreamToHttpConnection(nsISocketTransport *aTransport,
199
                                 nsHttpConnectionInfo *aConnInfo);
200
201
  MOZ_MUST_USE nsresult ReadSegments(nsAHttpSegmentReader *reader,
202
                                     uint32_t count,
203
                                     uint32_t *countRead) final;
204
  MOZ_MUST_USE nsresult WriteSegments(nsAHttpSegmentWriter *writer,
205
                                      uint32_t count,
206
                                      uint32_t *countWritten) final;
207
  nsHttpRequestHead *RequestHead() final;
208
  void Close(nsresult reason) final;
209
210
  // ConnectedReadyForInput() tests whether the spdy connect transaction is attached to
211
  // an nsHttpConnection that can properly deal with flow control, etc..
212
  bool ConnectedReadyForInput();
213
214
private:
215
  friend class InputStreamShim;
216
  friend class OutputStreamShim;
217
218
  MOZ_MUST_USE nsresult Flush(uint32_t count, uint32_t *countRead);
219
  void CreateShimError(nsresult code);
220
221
  nsCString             mConnectString;
222
  uint32_t              mConnectStringOffset;
223
224
  nsAHttpConnection    *mSession;
225
  nsAHttpSegmentReader *mSegmentReader;
226
227
  UniquePtr<char[]>   mInputData;
228
  uint32_t             mInputDataSize;
229
  uint32_t             mInputDataUsed;
230
  uint32_t             mInputDataOffset;
231
232
  UniquePtr<char[]>    mOutputData;
233
  uint32_t             mOutputDataSize;
234
  uint32_t             mOutputDataUsed;
235
  uint32_t             mOutputDataOffset;
236
237
  bool                           mForcePlainText;
238
  TimeStamp                      mTimestampSyn;
239
  RefPtr<nsHttpConnectionInfo> mConnInfo;
240
241
  // mTunneledConn, mTunnelTransport, mTunnelStreamIn, mTunnelStreamOut
242
  // are the connectors to the "real" http connection. They are created
243
  // together when the tunnel setup is complete and a static reference is held
244
  // for the lifetime of the tunnel.
245
  RefPtr<nsHttpConnection>     mTunneledConn;
246
  RefPtr<SocketTransportShim>  mTunnelTransport;
247
  RefPtr<InputStreamShim>      mTunnelStreamIn;
248
  RefPtr<OutputStreamShim>     mTunnelStreamOut;
249
  RefPtr<nsHttpTransaction>    mDrivingTransaction;
250
};
251
252
} // namespace net
253
} // namespace mozilla
254
255
#endif // mozilla_net_TLSFilterTransaction_h