Title: [198347] trunk/Source/WebKit2
Revision
198347
Author
achristen...@apple.com
Date
2016-03-17 12:28:24 -0700 (Thu, 17 Mar 2016)

Log Message

Support manually accepting invalid SSL certificates with NetworkSession
https://bugs.webkit.org/show_bug.cgi?id=155442
<rdar://problem/24847398>

Reviewed by Darin Adler.

When we click continue after getting a warning about an invalid SSL certificate, we call
NSURLRequest setAllowsSpecificHTTPSCertificate in NetworkProcess::allowSpecificHTTPSCertificateForHost,
which stores information in CFNetwork about the specific invalid SSL certificate we want to accept.
If we see such a certificate during a server trust evaluation, we want to tell CFNetwork to accept it.
This fixes a loop when going to https://badssl.com, clicking on expired, and clicking continue.

* NetworkProcess/NetworkDataTask.h:
* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::didReceiveChallenge):
(WebKit::NetworkLoad::continueCanAuthenticateAgainstProtectionSpace):
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTask::transferSandboxExtensionToDownload):
(WebKit::certificatesMatch):
(WebKit::NetworkDataTask::allowsSpecificHTTPSCertificateForHost):
(WebKit::NetworkDataTask::suggestedFilename):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (198346 => 198347)


--- trunk/Source/WebKit2/ChangeLog	2016-03-17 19:07:19 UTC (rev 198346)
+++ trunk/Source/WebKit2/ChangeLog	2016-03-17 19:28:24 UTC (rev 198347)
@@ -1,3 +1,27 @@
+2016-03-17  Alex Christensen  <achristen...@webkit.org>
+
+        Support manually accepting invalid SSL certificates with NetworkSession
+        https://bugs.webkit.org/show_bug.cgi?id=155442
+        <rdar://problem/24847398>
+
+        Reviewed by Darin Adler.
+
+        When we click continue after getting a warning about an invalid SSL certificate, we call
+        NSURLRequest setAllowsSpecificHTTPSCertificate in NetworkProcess::allowSpecificHTTPSCertificateForHost,
+        which stores information in CFNetwork about the specific invalid SSL certificate we want to accept.
+        If we see such a certificate during a server trust evaluation, we want to tell CFNetwork to accept it.
+        This fixes a loop when going to https://badssl.com, clicking on expired, and clicking continue.
+
+        * NetworkProcess/NetworkDataTask.h:
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::didReceiveChallenge):
+        (WebKit::NetworkLoad::continueCanAuthenticateAgainstProtectionSpace):
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTask::transferSandboxExtensionToDownload):
+        (WebKit::certificatesMatch):
+        (WebKit::NetworkDataTask::allowsSpecificHTTPSCertificateForHost):
+        (WebKit::NetworkDataTask::suggestedFilename):
+
 2016-03-17  Csaba Osztrogonác  <o...@webkit.org>
 
         [Mac][cmake] Unreviewed buildfix after r198070. Just for fun.

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h (198346 => 198347)


--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h	2016-03-17 19:07:19 UTC (rev 198346)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h	2016-03-17 19:28:24 UTC (rev 198347)
@@ -127,6 +127,7 @@
     String suggestedFilename();
     void willPerformHTTPRedirection(const WebCore::ResourceResponse&, WebCore::ResourceRequest&&, RedirectCompletionHandler);
     void transferSandboxExtensionToDownload(Download&);
+    bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&);
     
 private:
     NetworkDataTask(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect);

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp (198346 => 198347)


--- trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp	2016-03-17 19:07:19 UTC (rev 198346)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp	2016-03-17 19:28:24 UTC (rev 198347)
@@ -206,7 +206,10 @@
     // Handle server trust evaluation at platform-level if requested, for performance reasons.
     if (challenge.protectionSpace().authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested
         && !NetworkProcess::singleton().canHandleHTTPSServerTrustEvaluation()) {
-        completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, Credential());
+        if (m_task && m_task->allowsSpecificHTTPSCertificateForHost(challenge))
+            completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(challenge));
+        else
+            completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, { });
         return;
     }
 
@@ -344,7 +347,10 @@
     ASSERT(m_challengeCompletionHandler);
     auto completionHandler = WTFMove(m_challengeCompletionHandler);
     if (!result) {
-        completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, Credential());
+        if (m_task && m_task->allowsSpecificHTTPSCertificateForHost(m_challenge))
+            completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(m_challenge));
+        else
+            completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, { });
         return;
     }
     
@@ -354,7 +360,7 @@
     }
     
     if (m_parameters.clientCredentialPolicy == DoNotAskClientForAnyCredentials) {
-        completionHandler(AuthenticationChallengeDisposition::UseCredential, Credential());
+        completionHandler(AuthenticationChallengeDisposition::UseCredential, { });
         return;
     }
     

Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (198346 => 198347)


--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm	2016-03-17 19:07:19 UTC (rev 198346)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm	2016-03-17 19:28:24 UTC (rev 198347)
@@ -327,6 +327,42 @@
     download.setSandboxExtension(WTFMove(m_sandboxExtension));
 }
 
+static bool certificatesMatch(SecTrustRef trust1, SecTrustRef trust2)
+{
+    if (!trust1 || !trust2)
+        return false;
+
+    CFIndex count1 = SecTrustGetCertificateCount(trust1);
+    CFIndex count2 = SecTrustGetCertificateCount(trust2);
+    if (count1 != count2)
+        return false;
+
+    for (CFIndex i = 0; i < count1; i++) {
+        if (!CFEqual(SecTrustGetCertificateAtIndex(trust1, i), SecTrustGetCertificateAtIndex(trust2, i)))
+            return false;
+    }
+
+    return true;
+}
+
+bool NetworkDataTask::allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge& challenge)
+{
+    const String& host = challenge.protectionSpace().host();
+    NSArray *certificates = [NSURLRequest allowsSpecificHTTPSCertificateForHost:host];
+    if (!certificates)
+        return false;
+    
+    bool requireServerCertificates = challenge.protectionSpace().authenticationScheme() == WebCore::ProtectionSpaceAuthenticationScheme::ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
+    RetainPtr<SecPolicyRef> policy = adoptCF(SecPolicyCreateSSL(requireServerCertificates, host.createCFString().get()));
+    
+    SecTrustRef trustRef = nullptr;
+    if (SecTrustCreateWithCertificates((CFArrayRef)certificates, policy.get(), &trustRef) != noErr)
+        return false;
+    RetainPtr<SecTrustRef> trust = adoptCF(trustRef);
+
+    return certificatesMatch(trust.get(), challenge.nsURLAuthenticationChallenge().protectionSpace.serverTrust);
+}
+
 String NetworkDataTask::suggestedFilename()
 {
     return m_task.get().response.suggestedFilename;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to