Limit cookie header access to Network process
[WebKit-https.git] / Source / WebCore / platform / network / soup / SocketStreamHandleImplSoup.cpp
1 /*
2  * Copyright (C) 2009, 2011 Google Inc.  All rights reserved.
3  * Copyright (C) 2012 Samsung Electronics Ltd. All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "SocketStreamHandleImpl.h"
34
35 #if USE(SOUP)
36
37 #include "DeprecatedGlobalSettings.h"
38 #include "Logging.h"
39 #include "SocketStreamError.h"
40 #include "SocketStreamHandleClient.h"
41 #include "URL.h"
42 #include <gio/gio.h>
43 #include <glib.h>
44 #include <wtf/Vector.h>
45 #include <wtf/glib/GUniquePtr.h>
46 #include <wtf/glib/RunLoopSourcePriority.h>
47 #include <wtf/text/CString.h>
48
49 #define READ_BUFFER_SIZE 1024
50
51 namespace WebCore {
52
53 static gboolean wssConnectionAcceptCertificateCallback(GTlsConnection*, GTlsCertificate*, GTlsCertificateFlags)
54 {
55     return TRUE;
56 }
57
58 #if SOUP_CHECK_VERSION(2, 61, 90)
59 static void wssSocketClientEventCallback(SoupSession*, GSocketClientEvent event, GIOStream* connection)
60 {
61     if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
62         return;
63
64     g_signal_connect(connection, "accept-certificate", G_CALLBACK(wssConnectionAcceptCertificateCallback), nullptr);
65 }
66 #else
67 static void wssSocketClientEventCallback(GSocketClient*, GSocketClientEvent event, GSocketConnectable*, GIOStream* connection)
68 {
69     if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING)
70         return;
71
72     g_signal_connect(connection, "accept-certificate", G_CALLBACK(wssConnectionAcceptCertificateCallback), nullptr);
73 }
74 #endif
75
76 Ref<SocketStreamHandleImpl> SocketStreamHandleImpl::create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String&, SourceApplicationAuditToken&&)
77 {
78     Ref<SocketStreamHandleImpl> socket = adoptRef(*new SocketStreamHandleImpl(url, client));
79
80     // FIXME: Using DeprecatedGlobalSettings from here is a layering violation.
81     bool allowsAnySSLCertificate = url.protocolIs("wss") && DeprecatedGlobalSettings::allowsAnySSLCertificate();
82
83 #if SOUP_CHECK_VERSION(2, 61, 90)
84     auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID);
85     if (!networkStorageSession)
86         return socket;
87
88     auto uri = url.createSoupURI();
89     Ref<SocketStreamHandle> protectedSocketStreamHandle = socket.copyRef();
90     soup_session_connect_async(networkStorageSession->getOrCreateSoupNetworkSession().soupSession(), uri.get(), socket->m_cancellable.get(),
91         allowsAnySSLCertificate ? reinterpret_cast<SoupSessionConnectProgressCallback>(wssSocketClientEventCallback) : nullptr,
92         reinterpret_cast<GAsyncReadyCallback>(connectedCallback), &protectedSocketStreamHandle.leakRef());
93 #else
94     UNUSED_PARAM(sessionID);
95     unsigned port = url.port() ? url.port().value() : (url.protocolIs("wss") ? 443 : 80);
96     GRefPtr<GSocketClient> socketClient = adoptGRef(g_socket_client_new());
97     if (url.protocolIs("wss")) {
98         g_socket_client_set_tls(socketClient.get(), TRUE);
99         if (allowsAnySSLCertificate)
100             g_signal_connect(socketClient.get(), "event", G_CALLBACK(wssSocketClientEventCallback), nullptr);
101     }
102     Ref<SocketStreamHandle> protectedSocketStreamHandle = socket.copyRef();
103     g_socket_client_connect_to_host_async(socketClient.get(), url.host().utf8().data(), port, socket->m_cancellable.get(),
104         reinterpret_cast<GAsyncReadyCallback>(connectedCallback), &protectedSocketStreamHandle.leakRef());
105 #endif
106
107     return socket;
108 }
109
110 SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client)
111     : SocketStreamHandle(url, client)
112     , m_cancellable(adoptGRef(g_cancellable_new()))
113 {
114     LOG(Network, "SocketStreamHandle %p new client %p", this, &m_client);
115 }
116
117 SocketStreamHandleImpl::~SocketStreamHandleImpl()
118 {
119     LOG(Network, "SocketStreamHandle %p delete", this);
120 }
121
122 void SocketStreamHandleImpl::connected(GRefPtr<GIOStream>&& stream)
123 {
124     m_stream = WTFMove(stream);
125     m_outputStream = G_POLLABLE_OUTPUT_STREAM(g_io_stream_get_output_stream(m_stream.get()));
126     m_inputStream = g_io_stream_get_input_stream(m_stream.get());
127     m_readBuffer = makeUniqueArray<char>(READ_BUFFER_SIZE);
128
129     RefPtr<SocketStreamHandleImpl> protectedThis(this);
130     g_input_stream_read_async(m_inputStream.get(), m_readBuffer.get(), READ_BUFFER_SIZE, RunLoopSourcePriority::AsyncIONetwork, m_cancellable.get(),
131         reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), protectedThis.leakRef());
132
133     m_state = Open;
134     m_client.didOpenSocketStream(*this);
135 }
136
137 void SocketStreamHandleImpl::connectedCallback(GObject* object, GAsyncResult* result, SocketStreamHandleImpl* handle)
138 {
139     RefPtr<SocketStreamHandle> protectedThis = adoptRef(handle);
140
141     // Always finish the connection, even if this SocketStreamHandle was cancelled earlier.
142     GUniqueOutPtr<GError> error;
143 #if SOUP_CHECK_VERSION(2, 61, 90)
144     GRefPtr<GIOStream> stream = adoptGRef(soup_session_connect_finish(SOUP_SESSION(object), result, &error.outPtr()));
145 #else
146     GRefPtr<GIOStream> stream = adoptGRef(G_IO_STREAM(g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(object), result, &error.outPtr())));
147 #endif
148
149     // The SocketStreamHandle has been cancelled, so just close the connection, ignoring errors.
150     if (g_cancellable_is_cancelled(handle->m_cancellable.get())) {
151         if (stream)
152             g_io_stream_close(stream.get(), nullptr, nullptr);
153         return;
154     }
155
156     if (error)
157         handle->didFail(SocketStreamError(error->code, { }, error->message));
158     else
159         handle->connected(WTFMove(stream));
160 }
161
162 void SocketStreamHandleImpl::readBytes(gssize bytesRead)
163 {
164     if (!bytesRead) {
165         close();
166         return;
167     }
168
169     // The client can close the handle, potentially removing the last reference.
170     RefPtr<SocketStreamHandle> protectedThis(this);
171     if (bytesRead == -1)
172         m_client.didFailToReceiveSocketStreamData(*this);
173     else
174         m_client.didReceiveSocketStreamData(*this, m_readBuffer.get(), static_cast<size_t>(bytesRead));
175
176     if (m_inputStream) {
177         g_input_stream_read_async(m_inputStream.get(), m_readBuffer.get(), READ_BUFFER_SIZE, RunLoopSourcePriority::AsyncIONetwork, m_cancellable.get(),
178             reinterpret_cast<GAsyncReadyCallback>(readReadyCallback), protectedThis.leakRef());
179     }
180 }
181
182 void SocketStreamHandleImpl::readReadyCallback(GInputStream* stream, GAsyncResult* result, SocketStreamHandleImpl* handle)
183 {
184     RefPtr<SocketStreamHandle> protectedThis = adoptRef(handle);
185
186     // Always finish the read, even if this SocketStreamHandle was cancelled earlier.
187     GUniqueOutPtr<GError> error;
188     gssize bytesRead = g_input_stream_read_finish(stream, result, &error.outPtr());
189
190     if (g_cancellable_is_cancelled(handle->m_cancellable.get()))
191         return;
192
193     if (error)
194         handle->didFail(SocketStreamError(error->code, String(), error->message));
195     else
196         handle->readBytes(bytesRead);
197 }
198
199 void SocketStreamHandleImpl::didFail(SocketStreamError&& error)
200 {
201     m_client.didFailSocketStream(*this, WTFMove(error));
202 }
203
204 void SocketStreamHandleImpl::writeReady()
205 {
206     // We no longer have buffered data, so stop waiting for the socket to be writable.
207     if (!bufferedAmount()) {
208         stopWaitingForSocketWritability();
209         return;
210     }
211
212     sendPendingData();
213 }
214
215 std::optional<size_t> SocketStreamHandleImpl::platformSendInternal(const uint8_t* data, size_t length)
216 {
217     LOG(Network, "SocketStreamHandle %p platformSend", this);
218     if (!m_outputStream || !data)
219         return 0;
220
221     GUniqueOutPtr<GError> error;
222     gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), reinterpret_cast<const char*>(data), length, m_cancellable.get(), &error.outPtr());
223     if (error) {
224         if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
225             beginWaitingForSocketWritability();
226         else
227             didFail(SocketStreamError(error->code, String(), error->message));
228         return std::nullopt;
229     }
230
231     // If we did not send all the bytes we were given, we know that
232     // SocketStreamHandle will need to send more in the future.
233     if (written == -1 || static_cast<size_t>(written) < length)
234         beginWaitingForSocketWritability();
235
236     if (written == -1)
237         return std::nullopt;
238
239     return static_cast<size_t>(written);
240 }
241
242 void SocketStreamHandleImpl::platformClose()
243 {
244     LOG(Network, "SocketStreamHandle %p platformClose", this);
245     // We cancel this handle first to disable all callbacks.
246     g_cancellable_cancel(m_cancellable.get());
247     stopWaitingForSocketWritability();
248
249     if (m_stream) {
250         GUniqueOutPtr<GError> error;
251         g_io_stream_close(m_stream.get(), nullptr, &error.outPtr());
252         if (error)
253             didFail(SocketStreamError(error->code, { }, error->message));
254         m_stream = nullptr;
255     }
256
257     m_outputStream = nullptr;
258     m_inputStream = nullptr;
259     m_readBuffer = nullptr;
260
261     m_client.didCloseSocketStream(*this);
262 }
263
264 void SocketStreamHandleImpl::beginWaitingForSocketWritability()
265 {
266     if (m_writeReadySource) // Already waiting.
267         return;
268
269     m_writeReadySource = adoptGRef(g_pollable_output_stream_create_source(m_outputStream.get(), m_cancellable.get()));
270     ref();
271     g_source_set_callback(m_writeReadySource.get(), reinterpret_cast<GSourceFunc>(writeReadyCallback), this, [](gpointer handle) { 
272         static_cast<SocketStreamHandleImpl*>(handle)->deref();
273     });
274     g_source_attach(m_writeReadySource.get(), g_main_context_get_thread_default());
275 }
276
277 void SocketStreamHandleImpl::stopWaitingForSocketWritability()
278 {
279     if (!m_writeReadySource) // Not waiting.
280         return;
281
282     g_source_destroy(m_writeReadySource.get());
283     m_writeReadySource = nullptr;
284 }
285
286 gboolean SocketStreamHandleImpl::writeReadyCallback(GPollableOutputStream*, SocketStreamHandleImpl* handle)
287 {
288     if (g_cancellable_is_cancelled(handle->m_cancellable.get()))
289         return G_SOURCE_REMOVE;
290
291     handle->writeReady();
292     return G_SOURCE_CONTINUE;
293 }
294
295 } // namespace WebCore
296
297 #endif