React to X509Chain changes in macOS 10.13.4 (dotnet/corefx#28673)
authorJeremy Barton <jbarton@microsoft.com>
Sat, 31 Mar 2018 03:22:55 +0000 (20:22 -0700)
committerDan Moseley <danmose@microsoft.com>
Sat, 31 Mar 2018 03:22:55 +0000 (20:22 -0700)
10.13.4 changed some of the detail codes for building the X509ChainStatusFlag values.

"ValidLeaf" (etc) => "TemporalValidity"
"WeakLeaf" (etc) => "WeakKeySize"
new "MissingIntermediate" when the chain didn't complete instead of "AnchorTrusted" lower down.

Commit migrated from https://github.com/dotnet/corefx/commit/e49a617ba2a98a54b10c8a520b17cb05e9618b30

src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509chain.cpp
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs

index 6db3d53..4bed8b8 100644 (file)
@@ -154,7 +154,8 @@ static void MergeStatusCodes(CFTypeRef key, CFTypeRef value, void* context)
     CFStringRef keyString = reinterpret_cast<CFStringRef>(key);
 
     if (CFEqual(keyString, CFSTR("NotValidBefore")) || CFEqual(keyString, CFSTR("ValidLeaf")) ||
-        CFEqual(keyString, CFSTR("ValidIntermediates")) || CFEqual(keyString, CFSTR("ValidRoot")))
+        CFEqual(keyString, CFSTR("ValidIntermediates")) || CFEqual(keyString, CFSTR("ValidRoot")) ||
+        CFEqual(keyString, CFSTR("TemporalValidity")))
         *pStatus |= PAL_X509ChainNotTimeValid;
     else if (CFEqual(keyString, CFSTR("Revocation")))
         *pStatus |= PAL_X509ChainRevoked;
@@ -168,8 +169,10 @@ static void MergeStatusCodes(CFTypeRef key, CFTypeRef value, void* context)
         *pStatus |= PAL_X509ChainExplicitDistrust;
     else if (CFEqual(keyString, CFSTR("RevocationResponseRequired")))
         *pStatus |= PAL_X509ChainRevocationStatusUnknown;
+    else if (CFEqual(keyString, CFSTR("MissingIntermediate")))
+        *pStatus |= PAL_X509ChainPartialChain;
     else if (CFEqual(keyString, CFSTR("WeakLeaf")) || CFEqual(keyString, CFSTR("WeakIntermediates")) ||
-             CFEqual(keyString, CFSTR("WeakRoot")))
+             CFEqual(keyString, CFSTR("WeakRoot")) || CFEqual(keyString, CFSTR("WeakKeySize")))
     {
         // Because we won't report this out of a chain built by .NET on Windows,
         // don't report it here.
index 95492b5..7d34e05 100644 (file)
@@ -642,7 +642,12 @@ namespace System.Security.Cryptography.X509Certificates.Tests
             }
             else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
             {
-                expectedFlags = X509ChainStatusFlags.UntrustedRoot;
+                // For OSX alone expectedFlags here means OR instead of AND.
+                // Because the error code changed in 10.13.4 from UntrustedRoot to PartialChain
+                // and we handle that later in this test.
+                expectedFlags =
+                    X509ChainStatusFlags.UntrustedRoot |
+                    X509ChainStatusFlags.PartialChain;
             }
             else
             {
@@ -670,6 +675,18 @@ namespace System.Security.Cryptography.X509Certificates.Tests
                         X509ChainStatusFlags.NoError,
                         (a, b) => a | b);
 
+                if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+                {
+                    // If we're on 10.13.3 or older we get UntrustedRoot.
+                    // If we're on 10.13.4 or newer we get PartialChain.
+                    //
+                    // So make the expectedValue be whichever of those two is set.
+                    expectedFlags = (expectedFlags & allFlags);
+                    // One of them has to be set.
+                    Assert.NotEqual(X509ChainStatusFlags.NoError, expectedFlags);
+                    // Continue executing now to ensure that no other unexpected flags were set.
+                }
+
                 Assert.Equal(expectedFlags, allFlags);
             }
         }