WebKit Bugzilla
Attachment 343116 Details for
Bug 185266
: [Curl] Enable Proxy Authentication.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
FIX
185266.diff (text/plain), 18.65 KB, created by
Basuke Suzuki
on 2018-06-19 15:40:35 PDT
(
hide
)
Description:
FIX
Filename:
MIME Type:
Creator:
Basuke Suzuki
Created:
2018-06-19 15:40:35 PDT
Size:
18.65 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index f835922d78b..42da00b19f2 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,44 @@ >+2018-06-19 Basuke Suzuki <Basuke.Suzuki@sony.com> >+ >+ [Curl] Enable Proxy Authentication. >+ https://bugs.webkit.org/show_bug.cgi?id=185266 >+ >+ Add support for Proxy Authentication to curl network layer. >+ >+ Reviewed by Alex Christensen. >+ >+ No new tests in public. Tested internally. >+ >+ * platform/network/curl/AuthenticationChallenge.h: >+ * platform/network/curl/AuthenticationChallengeCurl.cpp: >+ (WebCore::AuthenticationChallenge::protectionSpaceServerTypeFromURI): >+ (WebCore::AuthenticationChallenge::protectionSpaceFromHandle): >+ (WebCore::AuthenticationChallenge::determineProxyPort): >+ (WebCore::AuthenticationChallenge::authenticationSchemeFromCurlAuth): >+ (WebCore::AuthenticationChallenge::parseRealm): >+ * platform/network/curl/CurlContext.cpp: >+ (WebCore::CurlHandle::enableProxyIfExists): >+ (WebCore::CurlHandle::getProxyUrl): >+ (WebCore::CurlHandle::getProxyAuthAvail): >+ (WebCore::CurlHandle::getPrimaryPort): Deleted. >+ * platform/network/curl/CurlContext.h: >+ (WebCore::CurlContext::setDefaultProxyAuthMethod): >+ (WebCore::CurlContext::setProxyAuthMethod): >+ * platform/network/curl/CurlProxySettings.cpp: >+ (WebCore::determineAuthMethod): >+ (WebCore::CurlProxySettings::setAuthMethod): >+ (WebCore::protocolIsInSocksFamily): >+ * platform/network/curl/CurlProxySettings.h: >+ (WebCore::CurlProxySettings::setDefaultAuthMethod): >+ (WebCore::CurlProxySettings::authMethod const): >+ * platform/network/curl/CurlRequest.cpp: >+ (WebCore::CurlRequest::didReceiveHeader): >+ * platform/network/curl/CurlResponse.h: >+ (WebCore::CurlResponse::isolatedCopy const): >+ * platform/network/curl/ResourceResponse.h: >+ * platform/network/curl/ResourceResponseCurl.cpp: >+ (WebCore::ResourceResponse::isProxyAuthenticationRequired const): >+ > 2018-06-19 Chris Dumez <cdumez@apple.com> > > WebCoreNSURLSessionDataTaskClient::redirectReceived() calls WebCore on non-main thread >diff --git a/Source/WebCore/platform/network/curl/AuthenticationChallenge.h b/Source/WebCore/platform/network/curl/AuthenticationChallenge.h >index 603c147c659..54de3d6b29d 100644 >--- a/Source/WebCore/platform/network/curl/AuthenticationChallenge.h >+++ b/Source/WebCore/platform/network/curl/AuthenticationChallenge.h >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2007 Apple Inc. All rights reserved. >- * Copyright (C) 2017 Sony Interactive Entertainment Inc. >+ * Copyright (C) 2018 Sony Interactive Entertainment Inc. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -48,8 +48,11 @@ public: > AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); } > > private: >- ProtectionSpaceServerType protectionSpaceServerTypeFromURI(const URL&); >+ ProtectionSpaceServerType protectionSpaceServerTypeFromURI(const URL&, bool isForProxy); > ProtectionSpace protectionSpaceFromHandle(const CurlResponse&, const ResourceResponse&); >+ std::optional<uint16_t> determineProxyPort(const URL&); >+ ProtectionSpaceAuthenticationScheme authenticationSchemeFromCurlAuth(long); >+ String parseRealm(const ResourceResponse&); > void removeLeadingAndTrailingQuotes(String&); > > RefPtr<AuthenticationClient> m_authenticationClient; >diff --git a/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp b/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp >index a3069e53a1a..eb99b9787b3 100644 >--- a/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp >+++ b/Source/WebCore/platform/network/curl/AuthenticationChallengeCurl.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2017 Sony Interactive Entertainment Inc. >+ * Copyright (C) 2018 Sony Interactive Entertainment Inc. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -40,43 +40,75 @@ AuthenticationChallenge::AuthenticationChallenge(const CurlResponse& curlRespons > { > } > >-ProtectionSpaceServerType AuthenticationChallenge::protectionSpaceServerTypeFromURI(const URL& url) >+ProtectionSpaceServerType AuthenticationChallenge::protectionSpaceServerTypeFromURI(const URL& url, bool isForProxy) > { > if (url.protocolIs("https")) >- return ProtectionSpaceServerHTTPS; >+ return isForProxy ? ProtectionSpaceProxyHTTPS : ProtectionSpaceServerHTTPS; > if (url.protocolIs("http")) >- return ProtectionSpaceServerHTTP; >+ return isForProxy ? ProtectionSpaceProxyHTTP : ProtectionSpaceServerHTTP; > if (url.protocolIs("ftp")) >- return ProtectionSpaceServerFTP; >- return ProtectionSpaceServerHTTP; >+ return isForProxy ? ProtectionSpaceProxyFTP : ProtectionSpaceServerFTP; >+ return isForProxy ? ProtectionSpaceProxyHTTP : ProtectionSpaceServerHTTP; > } > > ProtectionSpace AuthenticationChallenge::protectionSpaceFromHandle(const CurlResponse& curlResponse, const ResourceResponse& response) > { >- auto port = curlResponse.connectPort; >- auto availableHttpAuth = curlResponse.availableHttpAuth; >- >- ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeUnknown; >- if (availableHttpAuth & CURLAUTH_BASIC) >- scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; >- if (availableHttpAuth & CURLAUTH_DIGEST) >- scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; >- if (availableHttpAuth & CURLAUTH_NEGOTIATE) >- scheme = ProtectionSpaceAuthenticationSchemeNegotiate; >- if (availableHttpAuth & CURLAUTH_NTLM) >- scheme = ProtectionSpaceAuthenticationSchemeNTLM; >+ if (!response.isUnauthorized() && !response.isProxyAuthenticationRequired()) >+ return ProtectionSpace(); >+ >+ auto isProxyAuth = response.isProxyAuthenticationRequired(); >+ const auto& url = isProxyAuth ? curlResponse.proxyUrl : response.url(); >+ auto port = determineProxyPort(url); >+ auto serverType = protectionSpaceServerTypeFromURI(url, isProxyAuth); >+ auto authenticationScheme = authenticationSchemeFromCurlAuth(isProxyAuth ? curlResponse.availableProxyAuth : curlResponse.availableHttpAuth); >+ >+ return ProtectionSpace(url.host().toString(), static_cast<int>(port ? *port : 0), serverType, parseRealm(response), authenticationScheme); >+} >+ >+std::optional<uint16_t> AuthenticationChallenge::determineProxyPort(const URL& url) >+{ >+ static const uint16_t socksPort = 1080; >+ >+ if (auto port = url.port()) >+ return *port; >+ >+ if (auto port = defaultPortForProtocol(url.protocol())) >+ return *port; >+ >+ if (protocolIsInSocksFamily(url)) >+ return socksPort; >+ >+ return std::nullopt; >+} >+ >+ProtectionSpaceAuthenticationScheme AuthenticationChallenge::authenticationSchemeFromCurlAuth(long curlAuth) >+{ >+ if (curlAuth & CURLAUTH_NTLM) >+ return ProtectionSpaceAuthenticationSchemeNTLM; >+ if (curlAuth & CURLAUTH_NEGOTIATE) >+ return ProtectionSpaceAuthenticationSchemeNegotiate; >+ if (curlAuth & CURLAUTH_DIGEST) >+ return ProtectionSpaceAuthenticationSchemeHTTPDigest; >+ if (curlAuth & CURLAUTH_BASIC) >+ return ProtectionSpaceAuthenticationSchemeHTTPBasic; >+ return ProtectionSpaceAuthenticationSchemeUnknown; >+} >+ >+String AuthenticationChallenge::parseRealm(const ResourceResponse& response) >+{ >+ static NeverDestroyed<String> wwwAuthenticate(MAKE_STATIC_STRING_IMPL("www-authenticate")); >+ static NeverDestroyed<String> proxyAuthenticate(MAKE_STATIC_STRING_IMPL("proxy-authenticate")); >+ static NeverDestroyed<String> realmString(MAKE_STATIC_STRING_IMPL("realm=")); > > String realm; >- const String realmString("realm="); >- auto authHeader = response.httpHeaderField(String("www-authenticate")); >+ auto authHeader = response.httpHeaderField(response.isUnauthorized() ? wwwAuthenticate : proxyAuthenticate); > auto realmPos = authHeader.findIgnoringASCIICase(realmString); > if (realmPos != notFound) { >- realm = authHeader.substring(realmPos + realmString.length()); >+ realm = authHeader.substring(realmPos + realmString.get().length()); > realm = realm.left(realm.find(',')); > removeLeadingAndTrailingQuotes(realm); > } >- >- return ProtectionSpace(response.url().host().toString(), static_cast<int>(port), protectionSpaceServerTypeFromURI(response.url()), realm, scheme); >+ return realm; > } > > void AuthenticationChallenge::removeLeadingAndTrailingQuotes(String& value) >diff --git a/Source/WebCore/platform/network/curl/CurlContext.cpp b/Source/WebCore/platform/network/curl/CurlContext.cpp >index 1639496a339..1f0ac274f43 100644 >--- a/Source/WebCore/platform/network/curl/CurlContext.cpp >+++ b/Source/WebCore/platform/network/curl/CurlContext.cpp >@@ -501,7 +501,7 @@ void CurlHandle::enableProxyIfExists() > curl_easy_setopt(m_handle, CURLOPT_PROXYUSERNAME, proxy.user().utf8().data()); > if (!proxy.password().isEmpty()) > curl_easy_setopt(m_handle, CURLOPT_PROXYPASSWORD, proxy.password().utf8().data()); >- curl_easy_setopt(m_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); >+ curl_easy_setopt(m_handle, CURLOPT_PROXYAUTH, proxy.authMethod()); > break; > case CurlProxySettings::Mode::NoProxy : > // Disable the use of a proxy, even if there is an environment variable set for it. >@@ -510,7 +510,7 @@ void CurlHandle::enableProxyIfExists() > case CurlProxySettings::Mode::Custom : > curl_easy_setopt(m_handle, CURLOPT_PROXY, proxy.url().utf8().data()); > curl_easy_setopt(m_handle, CURLOPT_NOPROXY, proxy.ignoreHosts().utf8().data()); >- curl_easy_setopt(m_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); >+ curl_easy_setopt(m_handle, CURLOPT_PROXYAUTH, proxy.authMethod()); > break; > } > } >@@ -560,21 +560,13 @@ void CurlHandle::setSslCtxCallbackFunction(curl_ssl_ctx_callback callbackFunc, v > curl_easy_setopt(m_handle, CURLOPT_SSL_CTX_FUNCTION, callbackFunc); > } > >-std::optional<uint16_t> CurlHandle::getPrimaryPort() >+std::optional<String> CurlHandle::getProxyUrl() > { >- if (!m_handle) >- return std::nullopt; >- >- long port; >- CURLcode errorCode = curl_easy_getinfo(m_handle, CURLINFO_PRIMARY_PORT, &port); >- if (errorCode != CURLE_OK) >+ auto& proxy = CurlContext::singleton().proxySettings(); >+ if (proxy.mode() == CurlProxySettings::Mode::Default) > return std::nullopt; > >- /* >- * https://github.com/curl/curl/blob/master/lib/connect.c#L612-L660 >- * confirmed that `port` is originally unsigned short. >- */ >- return static_cast<uint16_t>(port); >+ return proxy.url(); > } > > std::optional<long> CurlHandle::getResponseCode() >@@ -630,6 +622,19 @@ std::optional<long> CurlHandle::getHttpAuthAvail() > return httpAuthAvailable; > } > >+std::optional<long> CurlHandle::getProxyAuthAvail() >+{ >+ if (!m_handle) >+ return std::nullopt; >+ >+ long proxyAuthAvailable; >+ CURLcode errorCode = curl_easy_getinfo(m_handle, CURLINFO_PROXYAUTH_AVAIL, &proxyAuthAvailable); >+ if (errorCode != CURLE_OK) >+ return std::nullopt; >+ >+ return proxyAuthAvailable; >+} >+ > std::optional<long> CurlHandle::getHttpVersion() > { > if (!m_handle) >diff --git a/Source/WebCore/platform/network/curl/CurlContext.h b/Source/WebCore/platform/network/curl/CurlContext.h >index 9677e0a31f8..4fcf9be9bd5 100644 >--- a/Source/WebCore/platform/network/curl/CurlContext.h >+++ b/Source/WebCore/platform/network/curl/CurlContext.h >@@ -106,6 +106,8 @@ public: > const CurlProxySettings& proxySettings() const { return m_proxySettings; } > void setProxySettings(const CurlProxySettings& settings) { m_proxySettings = settings; } > void setProxyUserPass(const String& user, const String& password) { m_proxySettings.setUserPass(user, password); } >+ void setDefaultProxyAuthMethod() { m_proxySettings.setDefaultAuthMethod(); } >+ void setProxyAuthMethod(long authMethod) { m_proxySettings.setAuthMethod(authMethod); } > > // SSL > CurlSSLHandle& sslHandle() { return m_sslHandle; } >@@ -267,11 +269,12 @@ public: > void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*); > > // Status >- std::optional<uint16_t> getPrimaryPort(); >+ std::optional<String> getProxyUrl(); > std::optional<long> getResponseCode(); > std::optional<long> getHttpConnectCode(); > std::optional<long long> getContentLength(); > std::optional<long> getHttpAuthAvail(); >+ std::optional<long> getProxyAuthAvail(); > std::optional<long> getHttpVersion(); > std::optional<NetworkLoadMetrics> getNetworkLoadMetrics(); > >diff --git a/Source/WebCore/platform/network/curl/CurlProxySettings.cpp b/Source/WebCore/platform/network/curl/CurlProxySettings.cpp >index 2b0ffc51d8a..4caf0ad34a6 100644 >--- a/Source/WebCore/platform/network/curl/CurlProxySettings.cpp >+++ b/Source/WebCore/platform/network/curl/CurlProxySettings.cpp >@@ -28,11 +28,16 @@ > > #if USE(CURL) > >+#if PLATFORM(WIN) >+#include <winsock2.h> >+#endif >+ >+#include <curl/curl.h> >+ > namespace WebCore { > > static const uint16_t SocksProxyPort = 1080; > >-static bool protocolIsInSocksFamily(const URL&); > static std::optional<uint16_t> getProxyPort(const URL&); > static std::optional<String> createProxyUrl(const URL&); > >@@ -61,7 +66,25 @@ void CurlProxySettings::setUserPass(const String& user, const String& password) > rebuildUrl(); > } > >-static bool protocolIsInSocksFamily(const URL& url) >+static long determineAuthMethod(long authMethod) >+{ >+ if (authMethod & CURLAUTH_NEGOTIATE) >+ return CURLAUTH_NEGOTIATE; >+ if (authMethod & CURLAUTH_DIGEST) >+ return CURLAUTH_DIGEST; >+ if (authMethod & CURLAUTH_NTLM) >+ return CURLAUTH_NTLM; >+ if (authMethod & CURLAUTH_BASIC) >+ return CURLAUTH_BASIC; >+ return CURLAUTH_NONE; >+} >+ >+void CurlProxySettings::setAuthMethod(long authMethod) >+{ >+ m_authMethod = determineAuthMethod(authMethod); >+} >+ >+bool protocolIsInSocksFamily(const URL& url) > { > return url.protocolIs("socks4") || url.protocolIs("socks4a") || url.protocolIs("socks5") || url.protocolIs("socks5h"); > } >diff --git a/Source/WebCore/platform/network/curl/CurlProxySettings.h b/Source/WebCore/platform/network/curl/CurlProxySettings.h >index f11deb95e01..a61c6ec2262 100644 >--- a/Source/WebCore/platform/network/curl/CurlProxySettings.h >+++ b/Source/WebCore/platform/network/curl/CurlProxySettings.h >@@ -28,6 +28,9 @@ > #include "URL.h" > #include <wtf/text/WTFString.h> > >+#define kCURLAUTH_DIGEST_IE (((unsigned long) 1) << 4) >+#define kCURLAUTH_ANY (~kCURLAUTH_DIGEST_IE) >+ > namespace WebCore { > > class CurlProxySettings { >@@ -55,10 +58,15 @@ public: > const String user() const { return m_url.user(); } > const String password() const { return m_url.pass(); } > >+ void setDefaultAuthMethod() { m_authMethod = kCURLAUTH_ANY; } >+ void setAuthMethod(long); >+ long authMethod() const { return m_authMethod; } >+ > private: > Mode m_mode { Mode::Default }; > URL m_url; > String m_ignoreHosts; >+ long m_authMethod { static_cast<long>(kCURLAUTH_ANY) }; > > // We can't simply use m_url.string() because we need to explicitly indicate the port number > // to libcurl. URLParser omit the default port while parsing, but libcurl assume 1080 as a >@@ -68,4 +76,6 @@ private: > void rebuildUrl(); > }; > >+bool protocolIsInSocksFamily(const URL&); >+ > } // namespace WebCore >diff --git a/Source/WebCore/platform/network/curl/CurlRequest.cpp b/Source/WebCore/platform/network/curl/CurlRequest.cpp >index 5aa728c9706..6e07060ad84 100644 >--- a/Source/WebCore/platform/network/curl/CurlRequest.cpp >+++ b/Source/WebCore/platform/network/curl/CurlRequest.cpp >@@ -333,18 +333,24 @@ size_t CurlRequest::didReceiveHeader(String&& header) > if (auto length = m_curlHandle->getContentLength()) > m_response.expectedContentLength = *length; > >- if (auto port = m_curlHandle->getPrimaryPort()) >- m_response.connectPort = *port; >+ if (auto proxyUrl = m_curlHandle->getProxyUrl()) >+ m_response.proxyUrl = URL(URL(), *proxyUrl); > > if (auto auth = m_curlHandle->getHttpAuthAvail()) > m_response.availableHttpAuth = *auth; > >+ if (auto auth = m_curlHandle->getProxyAuthAvail()) >+ m_response.availableProxyAuth = *auth; >+ > if (auto version = m_curlHandle->getHttpVersion()) > m_response.httpVersion = *version; > > if (auto metrics = m_curlHandle->getNetworkLoadMetrics()) > m_networkLoadMetrics = *metrics; > >+ if (m_response.availableProxyAuth) >+ CurlContext::singleton().setProxyAuthMethod(m_response.availableProxyAuth); >+ > if (m_enableMultipart) > m_multipartHandle = CurlMultipartHandle::createIfNeeded(*this, m_response); > >diff --git a/Source/WebCore/platform/network/curl/CurlResponse.h b/Source/WebCore/platform/network/curl/CurlResponse.h >index c6a5027b7d1..373661bd35a 100644 >--- a/Source/WebCore/platform/network/curl/CurlResponse.h >+++ b/Source/WebCore/platform/network/curl/CurlResponse.h >@@ -45,8 +45,9 @@ public: > for (const auto& header : headers) > copy.headers.append(header.isolatedCopy()); > >- copy.connectPort = connectPort; >+ copy.proxyUrl = proxyUrl.isolatedCopy(); > copy.availableHttpAuth = availableHttpAuth; >+ copy.availableProxyAuth = availableProxyAuth; > copy.httpVersion = httpVersion; > > return copy; >@@ -58,8 +59,9 @@ public: > long long expectedContentLength { 0 }; > Vector<String> headers; > >- uint16_t connectPort { 0 }; >+ URL proxyUrl; > long availableHttpAuth { 0 }; >+ long availableProxyAuth { 0 }; > long httpVersion { 0 }; > }; > >diff --git a/Source/WebCore/platform/network/curl/ResourceResponse.h b/Source/WebCore/platform/network/curl/ResourceResponse.h >index 7049ec5f847..4fa04e45210 100644 >--- a/Source/WebCore/platform/network/curl/ResourceResponse.h >+++ b/Source/WebCore/platform/network/curl/ResourceResponse.h >@@ -58,6 +58,7 @@ public: > bool isSeeOther() const; > bool isNotModified() const; > bool isUnauthorized() const; >+ bool isProxyAuthenticationRequired() const; > > // Needed for compatibility. > CFURLResponseRef cfURLResponse() const { return 0; } >diff --git a/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp b/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp >index b331dd5502d..ac45ba2b7a9 100644 >--- a/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp >+++ b/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp >@@ -188,6 +188,11 @@ bool ResourceResponse::isUnauthorized() const > return httpStatusCode() == 401; > } > >+bool ResourceResponse::isProxyAuthenticationRequired() const >+{ >+ return httpStatusCode() == 407; >+} >+ > } > > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185266
:
339467
|
343088
| 343116