Improve serialization logic
https://bugs.webkit.org/show_bug.cgi?id=203039
<rdar://problem/55631691>

Reviewed by Alex Christensen.

Check that the SecItemRequestData only contains relevant types for
CFNetwork uses.

* Platform/spi/Cocoa/SecItemSPI.h: Added.
* Shared/mac/SecItemRequestData.cpp:
(WebKit::arrayContainsInvalidType): Added.
(WebKit::dictionaryContainsInvalidType): Added.
(WebKit::validTypeIDs): Added.
(WebKit::isValidType): Added.
(WebKit::SecItemRequestData::decode): Check types during decode.
* Shared/mac/SecItemRequestData.h:
* WebKit.xcodeproj/project.pbxproj:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251358 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 011e1cb..ec0e175 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,24 @@
+2019-10-20  Brent Fulgham  <bfulgham@apple.com>
+
+        Improve serialization logic
+        https://bugs.webkit.org/show_bug.cgi?id=203039
+        <rdar://problem/55631691>
+
+        Reviewed by Alex Christensen.
+
+        Check that the SecItemRequestData only contains relevant types for
+        CFNetwork uses. 
+
+        * Platform/spi/Cocoa/SecItemSPI.h: Added.
+        * Shared/mac/SecItemRequestData.cpp:
+        (WebKit::arrayContainsInvalidType): Added.
+        (WebKit::dictionaryContainsInvalidType): Added.
+        (WebKit::validTypeIDs): Added.
+        (WebKit::isValidType): Added.
+        (WebKit::SecItemRequestData::decode): Check types during decode.
+        * Shared/mac/SecItemRequestData.h:
+        * WebKit.xcodeproj/project.pbxproj:
+
 2019-10-19  Adrian Perez de Castro  <aperez@igalia.com>
 
         [GTK][WPE] Fix non-unified builds after r250857
diff --git a/Source/WebKit/Platform/spi/Cocoa/SecItemSPI.h b/Source/WebKit/Platform/spi/Cocoa/SecItemSPI.h
new file mode 100644
index 0000000..091c14d
--- /dev/null
+++ b/Source/WebKit/Platform/spi/Cocoa/SecItemSPI.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <Security/SecAccessControl.h>
+#include <Security/SecBase.h>
+#include <Security/SecCertificate.h>
+#include <Security/SecIdentity.h>
+#include <Security/SecPolicy.h>
+#include <Security/SecTrust.h>
+
+#if PLATFORM(MAC)
+#include <Security/SecACL.h>
+#include <Security/SecAccess.h>
+#include <Security/SecTrustedApplication.h>
+#endif
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#include <Security/SecCode.h>
+#include <Security/SecRequirement.h>
+#include <Security/SecStaticCode.h>
+
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CF_ASSUME_NONNULL_BEGIN
+
+CFTypeID SecCodeGetTypeID();
+CFTypeID SecRequirementGetTypeID();
+CFTypeID SecStaticCodeGetTypeID();
+
+CF_ASSUME_NONNULL_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // USE(APPLE_INTERNAL_SDK)
diff --git a/Source/WebKit/Shared/mac/SecItemRequestData.cpp b/Source/WebKit/Shared/mac/SecItemRequestData.cpp
index fd1fd66..f1e9fa9 100644
--- a/Source/WebKit/Shared/mac/SecItemRequestData.cpp
+++ b/Source/WebKit/Shared/mac/SecItemRequestData.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,8 @@
 
 #include "ArgumentCoders.h"
 #include "ArgumentCodersCF.h"
+#include "SecItemSPI.h"
+#include <CoreFoundation/CoreFoundation.h>
 
 namespace WebKit {
 
@@ -62,6 +64,86 @@
         IPC::encode(encoder, m_attributesToMatch.get());
 }
 
+static bool isValidType(CFTypeRef);
+
+static bool arrayContainsInvalidType(CFArrayRef array)
+{
+    CFIndex entryCount = CFArrayGetCount(array);
+
+    for (CFIndex entry = 0; entry < entryCount; ++entry) {
+        CFTypeRef value = reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(array, entry));
+        if (!isValidType(value))
+            return true;
+    }
+
+    return false;
+}
+
+static bool dictionaryContainsInvalidType(CFDictionaryRef dict)
+{
+    CFIndex entryCount = CFDictionaryGetCount(dict);
+
+    Vector<const void*> keys(entryCount);
+    Vector<const void*> values(entryCount);
+    CFDictionaryGetKeysAndValues(dict, keys.data(), values.data());
+
+    for (CFIndex entry = 0; entry < entryCount; ++entry) {
+        CFTypeRef key = reinterpret_cast<CFTypeRef>(keys[entry]);
+        if (!isValidType(key))
+            return true;
+
+        CFTypeRef value = reinterpret_cast<CFTypeRef>(values[entry]);
+        if (!isValidType(value))
+            return true;
+    }
+
+    return false;
+}
+
+#if PLATFORM(MAC)
+typedef std::array<CFTypeID, 16> ValidTypes;
+#else
+typedef std::array<CFTypeID, 13> ValidTypes;
+#endif
+
+static const ValidTypes& validTypeIDs()
+{
+    static ValidTypes types = {{
+        CFBooleanGetTypeID(), CFDataGetTypeID(), CFStringGetTypeID(), CFNullGetTypeID(), CFNumberGetTypeID(),
+        SecAccessControlGetTypeID(), SecCertificateGetTypeID(), SecCodeGetTypeID(), SecIdentityGetTypeID(),
+        SecPolicyGetTypeID(), SecRequirementGetTypeID(), SecStaticCodeGetTypeID(), SecTrustGetTypeID()
+#if PLATFORM(MAC)
+        , SecACLGetTypeID(), SecAccessGetTypeID(), SecTrustedApplicationGetTypeID()
+#endif
+    }};
+
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        std::sort(types.begin(), types.end());
+    });
+
+    return types;
+}
+
+static bool isValidType(CFTypeRef type)
+{
+    auto typeID = CFGetTypeID(type);
+    if (typeID == CFDictionaryGetTypeID())
+        return !dictionaryContainsInvalidType(reinterpret_cast<CFDictionaryRef>(type));
+
+    if (typeID == CFArrayGetTypeID())
+        return !arrayContainsInvalidType(reinterpret_cast<CFArrayRef>(type));
+
+    const auto& validTypes = validTypeIDs();
+    
+    bool validType = std::binary_search(validTypes.begin(), validTypes.end(), typeID);
+    if (!validType) {
+        String typeName { adoptCF(CFCopyTypeIDDescription(typeID)).get() };
+        WTFLogAlways("SecItemRequestData::decode: Attempted to serialized invalid type %s", typeName.utf8().data());
+    }
+    return validType;
+}
+
 bool SecItemRequestData::decode(IPC::Decoder& decoder, SecItemRequestData& secItemRequestData)
 {
     if (!decoder.decodeEnum(secItemRequestData.m_type))
@@ -71,16 +153,26 @@
     if (!decoder.decode(expectQuery))
         return false;
 
-    if (expectQuery && !IPC::decode(decoder, secItemRequestData.m_queryDictionary))
-        return false;
+    if (expectQuery) {
+        if (!IPC::decode(decoder, secItemRequestData.m_queryDictionary))
+            return false;
+
+        if (dictionaryContainsInvalidType(secItemRequestData.m_queryDictionary.get()))
+            return false;
+    }
     
     bool expectAttributes;
     if (!decoder.decode(expectAttributes))
         return false;
     
-    if (expectAttributes && !IPC::decode(decoder, secItemRequestData.m_attributesToMatch))
-        return false;
-    
+    if (expectAttributes) {
+        if (!IPC::decode(decoder, secItemRequestData.m_attributesToMatch))
+            return false;
+
+        if (dictionaryContainsInvalidType(secItemRequestData.m_attributesToMatch.get()))
+            return false;
+    }
+
     return true;
 }
 
diff --git a/Source/WebKit/Shared/mac/SecItemRequestData.h b/Source/WebKit/Shared/mac/SecItemRequestData.h
index 465a821..0887c644 100644
--- a/Source/WebKit/Shared/mac/SecItemRequestData.h
+++ b/Source/WebKit/Shared/mac/SecItemRequestData.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,8 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SecItemRequestData_h
-#define SecItemRequestData_h
+#pragma once
 
 #include <wtf/RetainPtr.h>
 
@@ -64,5 +63,3 @@
 };
     
 } // namespace WebKit
-
-#endif // SecItemRequestData_h
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index 140179e..cc2e10d 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -1178,6 +1178,7 @@
 		7A8A9D581EF119B0009801AE /* APIInjectedBundleClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A8A9D571EF119AA009801AE /* APIInjectedBundleClient.h */; };
 		7A8A9D5A1EF13029009801AE /* APIInjectedBundleBundleClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A8A9D591EF13020009801AE /* APIInjectedBundleBundleClient.h */; };
 		7A8A9D5C1EF14598009801AE /* APIInjectedBundlePageResourceLoadClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A8A9D5B1EF1458E009801AE /* APIInjectedBundlePageResourceLoadClient.h */; };
+		7AA746D523593D8100095050 /* SecItemSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AA746D42359308400095050 /* SecItemSPI.h */; };
 		7AB6EA451EEAAE3800037B2B /* APIIconDatabaseClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AB6EA441EEAAE2300037B2B /* APIIconDatabaseClient.h */; };
 		7AB6EA471EEAB6B800037B2B /* APIGeolocationProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AB6EA461EEAB6B000037B2B /* APIGeolocationProvider.h */; };
 		7AF236211E79A40800438A05 /* WebErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AF2361F1E79A3D800438A05 /* WebErrors.h */; };
@@ -3767,6 +3768,7 @@
 		7A8A9D571EF119AA009801AE /* APIInjectedBundleClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIInjectedBundleClient.h; sourceTree = "<group>"; };
 		7A8A9D591EF13020009801AE /* APIInjectedBundleBundleClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIInjectedBundleBundleClient.h; sourceTree = "<group>"; };
 		7A8A9D5B1EF1458E009801AE /* APIInjectedBundlePageResourceLoadClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIInjectedBundlePageResourceLoadClient.h; sourceTree = "<group>"; };
+		7AA746D42359308400095050 /* SecItemSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemSPI.h; sourceTree = "<group>"; };
 		7AB4EA3F22777C460085BBAA /* SandboxExtensionCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SandboxExtensionCocoa.mm; sourceTree = "<group>"; };
 		7AB4EA4122777FC70085BBAA /* SandboxInitialiationParametersCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SandboxInitialiationParametersCocoa.mm; sourceTree = "<group>"; };
 		7AB4EA42227780DD0085BBAA /* SandboxUtilities.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SandboxUtilities.mm; sourceTree = "<group>"; };
@@ -6269,8 +6271,9 @@
 				2DAADA8E2298C21000E36B0C /* DeviceManagementSPI.h */,
 				57B826402304EB3E00B72EB0 /* NearFieldSPI.h */,
 				3754D5441B3A29FD003A4C7F /* NSInvocationSPI.h */,
-				37B47E2C1D64DB76005F4EFF /* objcSPI.h */,
 				0E97D74C200E8FF300BF6643 /* SafeBrowsingSPI.h */,
+				7AA746D42359308400095050 /* SecItemSPI.h */,
+				37B47E2C1D64DB76005F4EFF /* objcSPI.h */,
 			);
 			path = Cocoa;
 			sourceTree = "<group>";
@@ -9406,6 +9409,7 @@
 				1AFDE6621954E9B100C48FFA /* APISessionState.h in Headers */,
 				1A4D664818A2D91A00D82E21 /* APIUIClient.h in Headers */,
 				BCDB86C11200FB97007254BE /* APIURL.h in Headers */,
+				7AA746D523593D8100095050 /* SecItemSPI.h in Headers */,
 				BCE2315D122C30CA00D5C35A /* APIURLRequest.h in Headers */,
 				BC90A1D2122DD55E00CC8C50 /* APIURLResponse.h in Headers */,
 				F6113E25126CE1820057D0A7 /* APIUserContentURLPattern.h in Headers */,