Title: [263296] trunk
Revision
263296
Author
jiewen_...@apple.com
Date
2020-06-19 16:40:04 -0700 (Fri, 19 Jun 2020)

Log Message

[WebAuthn] Provide a _WKWebAuthenticationPanelUpdatePINInvalid update to UI clients if the returned PIN from the client is not valid
https://bugs.webkit.org/show_bug.cgi?id=213404
<rdar://problem/64543894>

Reviewed by Brent Fulgham.

Source/WebKit:

Provide a _WKWebAuthenticationPanelUpdatePINInvalid update to UI clients if the returned PIN from the client is not valid such that clients can
reuse the same logic to handle invalid pin from the authenticator. This change makes their life easier.

Covered by API tests.

* UIProcess/API/APIWebAuthenticationPanelClient.h:
(API::WebAuthenticationPanelClient::requestPin const):
* UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
(WebKit::WebAuthenticationPanelClient::requestPin const):
Now, only null strings are intepreted as cancels.

* UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
(WebKit::CtapAuthenticator::continueMakeCredentialAfterResponseReceived):
(WebKit::CtapAuthenticator::continueGetAssertionAfterResponseReceived):
(WebKit::CtapAuthenticator::continueGetPinTokenAfterRequestPin):
(WebKit::CtapAuthenticator::continueRequestAfterGetPinToken):
This patch also removes potential null pointer dereferences.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (263295 => 263296)


--- trunk/Source/WebKit/ChangeLog	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Source/WebKit/ChangeLog	2020-06-19 23:40:04 UTC (rev 263296)
@@ -1,3 +1,29 @@
+2020-06-19  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthn] Provide a _WKWebAuthenticationPanelUpdatePINInvalid update to UI clients if the returned PIN from the client is not valid
+        https://bugs.webkit.org/show_bug.cgi?id=213404
+        <rdar://problem/64543894>
+
+        Reviewed by Brent Fulgham.
+
+        Provide a _WKWebAuthenticationPanelUpdatePINInvalid update to UI clients if the returned PIN from the client is not valid such that clients can
+        reuse the same logic to handle invalid pin from the authenticator. This change makes their life easier.
+
+        Covered by API tests.
+
+        * UIProcess/API/APIWebAuthenticationPanelClient.h:
+        (API::WebAuthenticationPanelClient::requestPin const):
+        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
+        (WebKit::WebAuthenticationPanelClient::requestPin const):
+        Now, only null strings are intepreted as cancels.
+
+        * UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
+        (WebKit::CtapAuthenticator::continueMakeCredentialAfterResponseReceived):
+        (WebKit::CtapAuthenticator::continueGetAssertionAfterResponseReceived):
+        (WebKit::CtapAuthenticator::continueGetPinTokenAfterRequestPin):
+        (WebKit::CtapAuthenticator::continueRequestAfterGetPinToken):
+        This patch also removes potential null pointer dereferences.
+
 2020-06-19  Per Arne Vollan  <pvol...@apple.com>
 
         [macOS] Connections to the preference daemon are established before entering the sandbox

Modified: trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h (263295 => 263296)


--- trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h	2020-06-19 23:40:04 UTC (rev 263296)
@@ -49,7 +49,7 @@
 
     virtual void updatePanel(WebKit::WebAuthenticationStatus) const { }
     virtual void dismissPanel(WebKit::WebAuthenticationResult) const { }
-    virtual void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&& completionHandler) const { completionHandler(emptyString()); }
+    virtual void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&& completionHandler) const { completionHandler(WTF::String()); }
     virtual void selectAssertionResponse(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&&, WebKit::WebAuthenticationSource, CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)>&& completionHandler) const { completionHandler(nullptr); }
     virtual void decidePolicyForLocalAuthenticator(CompletionHandler<void(WebKit::LocalAuthenticatorPolicy)>&& completionHandler) const { completionHandler(WebKit::LocalAuthenticatorPolicy::Disallow); }
 };

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm (263295 => 263296)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm	2020-06-19 23:40:04 UTC (rev 263296)
@@ -118,13 +118,13 @@
 void WebAuthenticationPanelClient::requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&& completionHandler) const
 {
     if (!m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler) {
-        completionHandler(emptyString());
+        completionHandler(String());
         return;
     }
 
     auto delegate = m_delegate.get();
     if (!delegate) {
-        completionHandler(emptyString());
+        completionHandler(String());
         return;
     }
 

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp (263295 => 263296)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp	2020-06-19 23:40:04 UTC (rev 263296)
@@ -115,7 +115,7 @@
         }
 
         if (isPinError(error)) {
-            if (!m_pinAuth.isEmpty()) // Skip the very first command that acts like wink.
+            if (!m_pinAuth.isEmpty() && observer()) // Skip the very first command that acts like wink.
                 observer()->authenticatorStatusUpdated(toStatus(error));
             if (tryRestartPin(error))
                 return;
@@ -154,7 +154,7 @@
             return;
 
         if (isPinError(error)) {
-            if (!m_pinAuth.isEmpty()) // Skip the very first command that acts like wink.
+            if (!m_pinAuth.isEmpty() && observer()) // Skip the very first command that acts like wink.
                 observer()->authenticatorStatusUpdated(toStatus(error));
             if (tryRestartPin(error))
                 return;
@@ -274,9 +274,17 @@
 
 void CtapAuthenticator::continueGetPinTokenAfterRequestPin(const String& pin, const CryptoKeyEC& peerKey)
 {
+    if (pin.isNull()) {
+        receiveRespond(ExceptionData { UnknownError, "Pin is null."_s });
+        return;
+    }
+
     auto pinUtf8 = pin::validateAndConvertToUTF8(pin);
     if (!pinUtf8) {
-        receiveRespond(ExceptionData { UnknownError, makeString("Pin is not valid: ", pin) });
+        // Fake a pin invalid response from the authenticator such that clients could show some error to the user.
+        if (auto* observer = this->observer())
+            observer->authenticatorStatusUpdated(WebAuthenticationStatus::PinInvalid);
+        tryRestartPin(CtapDeviceResponseCode::kCtap2ErrPinInvalid);
         return;
     }
     auto tokenRequest = pin::TokenRequest::tryCreate(*pinUtf8, peerKey);
@@ -301,7 +309,8 @@
         auto error = getResponseCode(data);
 
         if (isPinError(error)) {
-            observer()->authenticatorStatusUpdated(toStatus(error));
+            if (auto* observer = this->observer())
+                observer->authenticatorStatusUpdated(toStatus(error));
             if (tryRestartPin(error))
                 return;
         }

Modified: trunk/Tools/ChangeLog (263295 => 263296)


--- trunk/Tools/ChangeLog	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Tools/ChangeLog	2020-06-19 23:40:04 UTC (rev 263296)
@@ -1,3 +1,16 @@
+2020-06-19  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthn] Provide a _WKWebAuthenticationPanelUpdatePINInvalid update to UI clients if the returned PIN from the client is not valid
+        https://bugs.webkit.org/show_bug.cgi?id=213404
+        <rdar://problem/64543894>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html: Added.
+
 2020-06-19  Jonathan Bedard  <jbed...@apple.com>
 
         Bring up watchOS/tvOS on build.webkit.org

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (263295 => 263296)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-06-19 23:40:04 UTC (rev 263296)
@@ -371,6 +371,7 @@
 		5742178A2400AED8002B303D /* web-authentication-make-credential-la-duplicate-credential.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 574217892400AED0002B303D /* web-authentication-make-credential-la-duplicate-credential.html */; };
 		5742178E2400D2DF002B303D /* web-authentication-make-credential-la.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */; };
 		574F55D2204D47F0002948C6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F55D0204D471C002948C6 /* Security.framework */; };
+		5751B28A249D5BC500664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */; };
 		5758597F23A2527A00C74572 /* CtapPinTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5758597E23A2527A00C74572 /* CtapPinTest.cpp */; };
 		5758598423C3C3A400C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */; };
 		57599E211F07191900A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */; };
@@ -1225,6 +1226,7 @@
 			dstPath = TestWebKitAPI.resources;
 			dstSubfolderSpec = 7;
 			files = (
+				5751B28A249D5BC500664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html in Copy Resources */,
 				55A817FF2181021A0004A39A /* 100x100-red.tga in Copy Resources */,
 				1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
 				55A81800218102210004A39A /* 400x400-green.png in Copy Resources */,
@@ -2054,6 +2056,7 @@
 		574217892400AED0002B303D /* web-authentication-make-credential-la-duplicate-credential.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la-duplicate-credential.html"; sourceTree = "<group>"; };
 		5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la.html"; sourceTree = "<group>"; };
 		574F55D0204D471C002948C6 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+		5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html"; sourceTree = "<group>"; };
 		5758597D23A2527A00C74572 /* CtapPinTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapPinTest.h; sourceTree = "<group>"; };
 		5758597E23A2527A00C74572 /* CtapPinTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapPinTest.cpp; sourceTree = "<group>"; };
 		5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-retries-error.html"; sourceTree = "<group>"; };
@@ -3741,6 +3744,7 @@
 				57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */,
 				578DA44723ECD01300246010 /* web-authentication-make-credential-hid-pin-auth-blocked-error.html */,
 				570D26F323C3CA5500D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html */,
+				5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */,
 				578DA44123ECC76B00246010 /* web-authentication-make-credential-hid-pin-get-pin-token-pin-auth-blocked-error.html */,
 				578DA44523ECCBD000246010 /* web-authentication-make-credential-hid-pin-get-pin-token-pin-auth-invalid-error-retry.html */,
 				570D26F923C3F24500D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-pin-blocked-error.html */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm (263295 => 263296)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2020-06-19 23:37:55 UTC (rev 263295)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2020-06-19 23:40:04 UTC (rev 263296)
@@ -937,7 +937,7 @@
 
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
-    [webView waitForMessage:@"Pin is not valid: "];
+    [webView waitForMessage:@"Pin is null."];
 }
 
 TEST(WebAuthenticationPanel, PinRequestPinErrorNullDelegate)
@@ -954,13 +954,13 @@
     [webView setUIDelegate:delegate.get()];
 
     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
-    [webView waitForMessage:@"Pin is not valid: "];
+    [webView waitForMessage:@"Pin is null."];
 }
 
 TEST(WebAuthenticationPanel, PinRequestPinError)
 {
     reset();
-    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
 
     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
@@ -971,7 +971,9 @@
 
     webAuthenticationPanelPin = "123";
     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
-    [webView waitForMessage:@"Pin is not valid: 123"];
+    Util::run(&webAuthenticationPanelUpdatePINInvalid);
+    webAuthenticationPanelPin = "1234";
+    [webView waitForMessage:@"Succeeded!"];
 }
 
 TEST(WebAuthenticationPanel, PinGetPinTokenPinBlockedError)

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html (0 => 263296)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html	2020-06-19 23:40:04 UTC (rev 263296)
@@ -0,0 +1,56 @@
+<input type="text" id="input">
+<script>
+    const testCtapPinInvalidErrorBase64 = "MQ==";
+    const testPinGetRetriesResponseBase64 = "AKEDCA==";
+    const testPinGetKeyAgreementResponseBase64 = "AKEBpQECAzgYIAEhWCDodiWJbuTkbcAydm6Ah5YvNt+d/otWfzdjAVsZkKYOFCJYICfeYS1mQYvaGVBYHrxcjB2tcQyxTCL4yXBF9GEvsgyR";
+    const testPinGetPinTokenResponseBase64 = "AKECUBOk7rcOyRrqAB6TFvYeQfc=";
+    const testCreationMessageBase64 =
+        "AKMBZnBhY2tlZAJYxEbMf7lnnVWy25CS4cjZ5eHQK3WA8LSBLHcJYuHkj1rYQQAA" +
+        "AE74oBHzjApNFYAGFxEfntx9AEAoCK3O6P5OyXN6V/f+9nAga0NA2Cgp4V3mgSJ5" +
+        "jOHLMDrmxp/S0rbD+aihru1C0aAN3BkiM6GNy5nSlDVqOgTgpQECAyYgASFYIEFb" +
+        "he3RkNud6sgyraBGjlh1pzTlCZehQlL/b18HZ6WGIlggJgfUd/en9p5AIqMQbUni" +
+        "nEeXdFLkvW0/zV5BpEjjNxADo2NhbGcmY3NpZ1hHMEUCIQDKg+ZBmEBtf0lWq4Re" +
+        "dH4/i/LOYqOR4uR2NAj2zQmw9QIgbTXb4hvFbj4T27bv/rGrc+y+0puoYOBkBk9P" +
+        "mCewWlNjeDVjgVkCwjCCAr4wggGmoAMCAQICBHSG/cIwDQYJKoZIhvcNAQELBQAw" +
+        "LjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEw" +
+        "IBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMG8xCzAJBgNVBAYTAlNF" +
+        "MRIwEAYDVQQKDAlZdWJpY28gQUIxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0" +
+        "ZXN0YXRpb24xKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NTUwMDM4" +
+        "NDIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASVXfOt9yR9MXXv/ZzE8xpOh466" +
+        "4YEJVmFQ+ziLLl9lJ79XQJqlgaUNCsUvGERcChNUihNTyKTlmnBOUjvATevto2ww" +
+        "ajAiBgkrBgEEAYLECgIEFTEuMy42LjEuNC4xLjQxNDgyLjEuMTATBgsrBgEEAYLl" +
+        "HAIBAQQEAwIFIDAhBgsrBgEEAYLlHAEBBAQSBBD4oBHzjApNFYAGFxEfntx9MAwG" +
+        "A1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBADFcSIDmmlJ+OGaJvWn9Cqhv" +
+        "SeueToVFQVVvqtALOgCKHdwB+Wx29mg2GpHiMsgQp5xjB0ybbnpG6x212FxESJ+G" +
+        "inZD0ipchi7APwPlhIvjgH16zVX44a4e4hOsc6tLIOP71SaMsHuHgCcdH0vg5d2s" +
+        "c006WJe9TXO6fzV+ogjJnYpNKQLmCXoAXE3JBNwKGBIOCvfQDPyWmiiG5bGxYfPt" +
+        "y8Z3pnjX+1MDnM2hhr40ulMxlSNDnX/ZSnDyMGIbk8TOQmjTF02UO8auP8k3wt5D" +
+        "1rROIRU9+FCSX5WQYi68RuDrGMZB8P5+byoJqbKQdxn2LmE1oZAyohPAmLcoPO4=";
+    if (window.internals) {
+        internals.setMockWebAuthenticationConfiguration({ hid: { supportClientPin: true, payloadBase64: [testCtapPinInvalidErrorBase64, testPinGetRetriesResponseBase64, testPinGetKeyAgreementResponseBase64, testPinGetRetriesResponseBase64, testPinGetKeyAgreementResponseBase64, testPinGetPinTokenResponseBase64, testCreationMessageBase64] } });
+        internals.withUserGesture(() => { input.focus(); });
+    }
+
+    const options = {
+        publicKey: {
+            rp: {
+                name: "localhost",
+            },
+            user: {
+                name: "John Appleseed",
+                id: new Uint8Array(16),
+                displayName: "Appleseed",
+            },
+            challenge: new Uint8Array(16),
+            pubKeyCredParams: [{ type: "public-key", alg: -7 }]
+        }
+    };
+
+    navigator.credentials.create(options).then(credential => {
+        // console.log("Succeeded!");
+        window.webkit.messageHandlers.testHandler.postMessage("Succeeded!");
+    }, error => {
+        // console.log(error.message);
+        window.webkit.messageHandlers.testHandler.postMessage(error.message);
+    });
+</script>
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to