[Curl] Add TLS debugging feature to log encryption keys
[WebKit.git] / Source / WebCore / platform / network / curl / CurlContext.h
1 /*
2  * Copyright (C) 2013 Apple Inc.  All rights reserved.
3  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "CurlProxySettings.h"
30 #include "CurlSSLHandle.h"
31
32 #include <wtf/Lock.h>
33 #include <wtf/NeverDestroyed.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Seconds.h>
36 #include <wtf/Threading.h>
37 #include <wtf/URL.h>
38
39 #if OS(WINDOWS)
40 #include <windows.h>
41 #include <winsock2.h>
42 #endif
43
44 #include <curl/curl.h>
45
46 namespace WebCore {
47
48 // Values taken from http://www.browserscope.org/ following
49 // the rule "Do What Every Other Modern Browser Is Doing".
50 const long CurlDefaultMaxConnects { -1 }; // -1 : Does not set CURLMOPT_MAXCONNECTS
51 const long CurlDefaultMaxTotalConnections { 17 };
52 const long CurlDefaultMaxHostConnections { 6 };
53
54 // CurlGlobal --------------------------------------------
55 // to make the initialization of libcurl happen before other initialization of CurlContext
56
57 class CurlGlobal {
58 protected:
59     CurlGlobal()
60     {
61         curl_global_init(CURL_GLOBAL_ALL);
62     }
63     
64     virtual ~CurlGlobal()
65     {
66         curl_global_cleanup();
67     }
68 };
69
70 // CurlShareHandle --------------------------------------------
71
72 class CurlShareHandle {
73     WTF_MAKE_NONCOPYABLE(CurlShareHandle);
74
75 public:
76     CurlShareHandle();
77     ~CurlShareHandle();
78
79     CURLSH* handle() const { return m_shareHandle; }
80
81 private:
82     static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
83     static void unlockCallback(CURL*, curl_lock_data, void*);
84     static Lock* mutexFor(curl_lock_data);
85
86     CURLSH* m_shareHandle { nullptr };
87 };
88
89 // CurlContext --------------------------------------------
90
91 class CurlRequestScheduler;
92 class CurlStreamScheduler;
93
94 class CurlContext : public CurlGlobal {
95     WTF_MAKE_NONCOPYABLE(CurlContext);
96     friend NeverDestroyed<CurlContext>;
97 public:
98     WEBCORE_EXPORT static CurlContext& singleton();
99
100     virtual ~CurlContext();
101
102     const CurlShareHandle& shareHandle() { return m_shareHandle; }
103
104     CurlRequestScheduler& scheduler() { return *m_scheduler; }
105     CurlStreamScheduler& streamScheduler();
106
107     // Proxy
108     const CurlProxySettings& proxySettings() const { return m_proxySettings; }
109     void setProxySettings(CurlProxySettings&& settings) { m_proxySettings = WTFMove(settings); }
110     void setProxyUserPass(const String& user, const String& password) { m_proxySettings.setUserPass(user, password); }
111     void setDefaultProxyAuthMethod() { m_proxySettings.setDefaultAuthMethod(); }
112     void setProxyAuthMethod(long authMethod) { m_proxySettings.setAuthMethod(authMethod); }
113
114     // SSL
115     CurlSSLHandle& sslHandle() { return m_sslHandle; }
116
117     // HTTP/2
118     bool isHttp2Enabled() const;
119
120     // Timeout
121     Seconds dnsCacheTimeout() const { return m_dnsCacheTimeout; }
122     Seconds connectTimeout() const { return m_connectTimeout; }
123     Seconds defaultTimeoutInterval() const { return m_defaultTimeoutInterval; }
124
125 #ifndef NDEBUG
126     FILE* getLogFile() const { return m_logFile; }
127     bool isVerbose() const { return m_verbose; }
128 #endif
129
130 #if ENABLE(TLS_DEBUG)
131     bool shouldLogTLSKey() const { return !m_tlsKeyLogFilePath.isEmpty(); }
132     const String& tlsKeyLogFilePath() const { return m_tlsKeyLogFilePath; }
133 #endif
134
135 private:
136     CurlContext();
137     void initShareHandle();
138
139     CurlProxySettings m_proxySettings;
140     CurlShareHandle m_shareHandle;
141     CurlSSLHandle m_sslHandle;
142     std::unique_ptr<CurlRequestScheduler> m_scheduler;
143
144     Seconds m_dnsCacheTimeout { Seconds::fromMinutes(5) };
145     Seconds m_connectTimeout { 30.0 };
146     Seconds m_defaultTimeoutInterval { 60.0 };
147
148 #ifndef NDEBUG
149     FILE* m_logFile { nullptr };
150     bool m_verbose { false };
151 #endif
152
153 #if ENABLE(TLS_DEBUG)
154     String m_tlsKeyLogFilePath;
155 #endif
156 };
157
158 // CurlMultiHandle --------------------------------------------
159
160 class CurlMultiHandle {
161     WTF_MAKE_FAST_ALLOCATED;
162     WTF_MAKE_NONCOPYABLE(CurlMultiHandle);
163
164 public:
165     CurlMultiHandle();
166     ~CurlMultiHandle();
167
168     void setMaxConnects(long);
169     void setMaxTotalConnections(long);
170     void setMaxHostConnections(long);
171
172     CURLMcode addHandle(CURL*);
173     CURLMcode removeHandle(CURL*);
174
175     CURLMcode getFdSet(fd_set&, fd_set&, fd_set&, int&);
176     CURLMcode perform(int&);
177     CURLMsg* readInfo(int&);
178
179 private:
180     CURLM* m_multiHandle { nullptr };
181 };
182
183 // CurlSList -------------------------------------------------
184
185 class CurlSList {
186 public:
187     CurlSList() { }
188     ~CurlSList() { clear(); }
189
190     operator struct curl_slist** () { return &m_list; }
191
192     const struct curl_slist* head() const { return m_list; }
193     bool isEmpty() const { return !m_list; }
194     void clear()
195     {
196         if (m_list) {
197             curl_slist_free_all(m_list);
198             m_list = nullptr;
199         }
200     }
201
202     void append(const char* str) { m_list = curl_slist_append(m_list, str); }
203     void append(const String& str) { append(str.latin1().data()); }
204
205 private:
206     struct curl_slist* m_list { nullptr };
207 };
208
209 // CurlHandle -------------------------------------------------
210
211 class CertificateInfo;
212 class CurlSSLVerifier;
213 class HTTPHeaderMap;
214 class NetworkLoadMetrics;
215
216 class CurlHandle {
217     WTF_MAKE_FAST_ALLOCATED;
218     WTF_MAKE_NONCOPYABLE(CurlHandle);
219
220 public:
221     enum class VerifyPeer {
222         Disable = 0L,
223         Enable = 1L
224     };
225
226     enum class VerifyHost {
227         LooseNameCheck = 0,
228         StrictNameCheck = 2
229     };
230
231     CurlHandle();
232     virtual ~CurlHandle();
233
234     CURL* handle() const { return m_handle; }
235     const URL& url() const { return m_url; }
236
237     CURLcode perform();
238     CURLcode pause(int);
239
240     static const String errorDescription(CURLcode);
241
242     void enableShareHandle();
243
244     void setUrl(const URL&);
245     void enableSSLForHost(const String&);
246
247     void appendRequestHeaders(const HTTPHeaderMap&);
248     void appendRequestHeader(const String& name, const String& value);
249     void appendRequestHeader(const String& name);
250     void removeRequestHeader(const String& name);
251
252     void enableHttp();
253     void enableHttpGetRequest();
254     void enableHttpHeadRequest();
255     void enableHttpPostRequest();
256     void setPostFields(const char*, long);
257     void setPostFieldLarge(curl_off_t);
258     void enableHttpPutRequest();
259     void setInFileSizeLarge(curl_off_t);
260     void setHttpCustomRequest(const String&);
261
262     void enableConnectionOnly();
263
264     void enableAcceptEncoding();
265     void enableAllowedProtocols();
266
267     void setHttpAuthUserPass(const String&, const String&, long authType = CURLAUTH_ANY);
268
269     void disableServerTrustEvaluation();
270     void setCACertPath(const char*);
271     void setSslVerifyPeer(VerifyPeer);
272     void setSslVerifyHost(VerifyHost);
273     void setSslCert(const char*);
274     void setSslCertType(const char*);
275     void setSslKeyPassword(const char*);
276     void setSslCipherList(const char*);
277
278     void enableProxyIfExists();
279
280     void setDnsCacheTimeout(Seconds);
281     void setConnectTimeout(Seconds);
282     void setTimeout(Seconds);
283
284     // Callback function
285     void setHeaderCallbackFunction(curl_write_callback, void*);
286     void setWriteCallbackFunction(curl_write_callback, void*);
287     void setReadCallbackFunction(curl_read_callback, void*);
288     void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
289     void setDebugCallbackFunction(curl_debug_callback, void*);
290
291     // Status
292     Optional<String> getProxyUrl();
293     Optional<long> getResponseCode();
294     Optional<long> getHttpConnectCode();
295     Optional<long long> getContentLength();
296     Optional<long> getHttpAuthAvail();
297     Optional<long> getProxyAuthAvail();
298     Optional<long> getHttpVersion();
299     Optional<NetworkLoadMetrics> getNetworkLoadMetrics(const WTF::Seconds& domainLookupStart);
300     void addExtraNetworkLoadMetrics(NetworkLoadMetrics&);
301
302     int sslErrors() const;
303     Optional<CertificateInfo> certificateInfo() const;
304
305     static long long maxCurlOffT();
306
307     // socket
308     Expected<curl_socket_t, CURLcode> getActiveSocket();
309     CURLcode send(const uint8_t*, size_t, size_t&);
310     CURLcode receive(uint8_t*, size_t, size_t&);
311
312 #ifndef NDEBUG
313     void enableVerboseIfUsed();
314     void enableStdErrIfUsed();
315 #endif
316
317 private:
318     void enableRequestHeaders();
319     static int expectedSizeOfCurlOffT();
320
321     static CURLcode willSetupSslCtxCallback(CURL*, void* sslCtx, void* userData);
322     CURLcode willSetupSslCtx(void* sslCtx);
323
324     CURL* m_handle { nullptr };
325     char m_errorBuffer[CURL_ERROR_SIZE] { };
326
327     URL m_url;
328     CurlSList m_requestHeaders;
329     std::unique_ptr<CurlSSLVerifier> m_sslVerifier;
330 };
331
332 } // namespace WebCore