Read SSL_CERT_FILE contents before SSL_CERT_DIR contents
authorJeremy Barton <jbarton@microsoft.com>
Thu, 13 Sep 2018 20:30:34 +0000 (13:30 -0700)
committerGitHub <noreply@github.com>
Thu, 13 Sep 2018 20:30:34 +0000 (13:30 -0700)
The OpenSSL commandline utility (openssl verify) uses the "single file" lookup
before the directory contents lookup in both OpenSSL 1.0.2 and 1.1.0.  Normally,
this doesn't matter, as the contents between the two are normally not in conflict.

The certificates on SLES 15 and Fedora 28, however, seem to use the plain X509
data ("BEGIN CERTIFICATE") as the "by file" multi-PEM, and newly use
trust-specified certificates ("BEGIN TRUSTED CERTIFICATE") contents in the
directory lookup.

When a certificate gets loaded with explicit trust settings, any trust not
explicitly permitted is implicitly denied.  Our X509Chain class uses the default
trust for the trust decision (X509_TRUST_DEFAULT), which means it does a
check for the "any extended key usage" trust.  That purpose is not present
in the certificates we're seeing now, meaning we get
X509_V_ERR_CERT_REJECTED as the response from the chain, but the CLI
tool gets a successful response.

By changing the order to be "file first" we match the behavior of the CLI tool.

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

src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/StorePal.cs

index 5c3cc54..e23af68 100644 (file)
@@ -244,7 +244,7 @@ namespace Internal.Cryptography.Pal
 
             if (rootStoreFile != null && rootStoreFile.Exists)
             {
-                trustedCertFiles = Append(trustedCertFiles, rootStoreFile);
+                trustedCertFiles = Prepend(trustedCertFiles, rootStoreFile);
             }
 
             HashSet<X509Certificate2> uniqueRootCerts = new HashSet<X509Certificate2>();
@@ -301,12 +301,14 @@ namespace Internal.Cryptography.Pal
             Volatile.Write(ref s_machineRootStore, rootStorePal);
         }
 
-        private static IEnumerable<T> Append<T>(IEnumerable<T> current, T addition)
+        private static IEnumerable<T> Prepend<T>(IEnumerable<T> current, T addition)
         {
+            yield return addition;
+
             foreach (T element in current)
+            {
                 yield return element;
-
-            yield return addition;
+            }
         }
     }
 }