WebKit Bugzilla
Attachment 339467 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]
PATCH
185266.diff (text/plain), 17.88 KB, created by
Basuke Suzuki
on 2018-05-03 14:28:22 PDT
(
hide
)
Description:
PATCH
Filename:
MIME Type:
Creator:
Basuke Suzuki
Created:
2018-05-03 14:28:22 PDT
Size:
17.88 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 84d3e7f8978..61c07608bf2 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,42 @@ >+2018-05-03 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 NOBODY (OOPS!). >+ >+ 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::getPort): >+ (WebCore::AuthenticationChallenge::authenticationSchemeFromCurlAuth): >+ (WebCore::AuthenticationChallenge::parseRealm): >+ * platform/network/curl/CurlContext.cpp: >+ (WebCore::CurlHandle::enableProxyIfExists): >+ (WebCore::CurlHandle::proxyUrl): >+ (WebCore::CurlHandle::getProxyAuthAvail): >+ (WebCore::CurlHandle::getPrimaryPort): Deleted. >+ * platform/network/curl/CurlContext.h: >+ (WebCore::CurlContext::setDefaultProxyAuthMethod): >+ (WebCore::CurlContext::setProxyAuthMethod): >+ * platform/network/curl/CurlProxySettings.cpp: >+ (WebCore::CurlProxySettings::setAuthMethod): >+ * 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-05-03 Zalan Bujtas <zalan@apple.com> > > [LFC] Box invalidation logic should go to dedicated classes. >diff --git a/Source/WebCore/platform/network/curl/AuthenticationChallenge.h b/Source/WebCore/platform/network/curl/AuthenticationChallenge.h >index 603c147c659..922bd4c80f7 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&); >+ int getPort(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 cee36b41b01..11ae990ad8c 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,78 @@ 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; >+ if (!response.isUnauthorized() && !response.isProxyAuthenticationRequired()) >+ return ProtectionSpace(); > >+ auto isProxyAuth = response.isProxyAuthenticationRequired(); >+ const auto& url = isProxyAuth ? curlResponse.proxyUrl : response.url(); >+ auto serverType = protectionSpaceServerTypeFromURI(url, isProxyAuth); >+ auto authenticationScheme = authenticationSchemeFromCurlAuth(isProxyAuth ? curlResponse.availableProxyAuth : curlResponse.availableHttpAuth); >+ >+ return ProtectionSpace(url.host(), getPort(url), serverType, parseRealm(response), authenticationScheme); >+} >+ >+int AuthenticationChallenge::getPort(const URL& url) >+{ >+ static const uint16_t socksPort = 1080; >+ >+ auto port = url.port(); >+ if (port) >+ return static_cast<int>(*port); >+ >+ port = defaultPortForProtocol(url.protocol()); >+ if (port) >+ return static_cast<int>(*port); >+ >+ auto protocol = url.protocol().toString(); >+ if (protocol == "socks4" || protocol == "socks4a" || protocol == "socks5" || protocol == "socks5h") >+ return socksPort; >+ >+ return 0; >+} >+ >+ProtectionSpaceAuthenticationScheme AuthenticationChallenge::authenticationSchemeFromCurlAuth(long curlAuth) >+{ > ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeUnknown; >- if (availableHttpAuth & CURLAUTH_BASIC) >+ if (curlAuth & CURLAUTH_BASIC) > scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; >- if (availableHttpAuth & CURLAUTH_DIGEST) >+ if (curlAuth & CURLAUTH_DIGEST) > scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; >- if (availableHttpAuth & CURLAUTH_NEGOTIATE) >+ if (curlAuth & CURLAUTH_NEGOTIATE) > scheme = ProtectionSpaceAuthenticationSchemeNegotiate; >- if (availableHttpAuth & CURLAUTH_NTLM) >+ if (curlAuth & CURLAUTH_NTLM) > scheme = ProtectionSpaceAuthenticationSchemeNTLM; >+ return scheme; >+} >+ >+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(), 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 24095c78f66..6833f8c8c53 100644 >--- a/Source/WebCore/platform/network/curl/CurlContext.cpp >+++ b/Source/WebCore/platform/network/curl/CurlContext.cpp >@@ -493,7 +493,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. >@@ -502,7 +502,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; > } > } >@@ -552,21 +552,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::proxyUrl() > { >- 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() >@@ -622,6 +614,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 0e63de8cf6c..7622a8f080a 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; } >@@ -266,11 +268,12 @@ public: > void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*); > > // Status >- std::optional<uint16_t> getPrimaryPort(); >+ std::optional<String> proxyUrl(); > 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..d4b83f270f3 100644 >--- a/Source/WebCore/platform/network/curl/CurlProxySettings.cpp >+++ b/Source/WebCore/platform/network/curl/CurlProxySettings.cpp >@@ -28,6 +28,12 @@ > > #if USE(CURL) > >+#if PLATFORM(WIN) >+#include <winsock2.h> >+#endif >+ >+#include <curl/curl.h> >+ > namespace WebCore { > > static const uint16_t SocksProxyPort = 1080; >@@ -61,6 +67,22 @@ void CurlProxySettings::setUserPass(const String& user, const String& password) > rebuildUrl(); > } > >+void CurlProxySettings::setAuthMethod(long authMethod) >+{ >+ long method = CURLAUTH_NONE; >+ if (authMethod & CURLAUTH_BASIC) >+ method = CURLAUTH_BASIC; >+ if (authMethod & CURLAUTH_NTLM) >+ method = CURLAUTH_NTLM; >+ if (authMethod & CURLAUTH_DIGEST) >+ method = CURLAUTH_DIGEST; >+ if (authMethod & CURLAUTH_NEGOTIATE) >+ method = CURLAUTH_NEGOTIATE; >+ >+ if (m_authMethod != method) >+ m_authMethod = method; >+} >+ > static 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..900f56b8719 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 CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) >+#define CURLAUTH_ANY (~CURLAUTH_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 = CURLAUTH_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>(CURLAUTH_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 >diff --git a/Source/WebCore/platform/network/curl/CurlRequest.cpp b/Source/WebCore/platform/network/curl/CurlRequest.cpp >index 0335a67b958..8e3cd34abcb 100644 >--- a/Source/WebCore/platform/network/curl/CurlRequest.cpp >+++ b/Source/WebCore/platform/network/curl/CurlRequest.cpp >@@ -317,18 +317,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->proxyUrl()) >+ 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