-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows Certificate Store Issue #46370
Comments
There got to be a reason why second certificate is deemed to be bad by boringssl/openssl. It is surprising you got two |
I hand crafted a certificate bundle with that cert and all certs in the chain. I used it with the
When I navigate to the URL in the browser, all certificates in the chain are valid.
The certificates are in the local machine store. The certs listed in the output are intermediate. The root certs for them are stored in root and are trusted and valid.
I thought it was odd as well. |
Have you been able to confirm that any(or all) of these certificates that you bundled are present in your Windows localmachine/currentuser certificate store(via certmgr.msc)?
This is actually working as intended as per https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html the callback is called for every certificate in the chain that failed openssl builtin verification.
I am not familiar with this process. |
So if the first certificate printed(which seems to be an intermediate certificate in the chain) has expired/is invalid, then whole certificate won't be trusted neither. |
I have verified that all certificates are in the local machine store.
The proxy servers in my environment do not always use the certificates of the host site for secure communication with the workstations. For example, if I navigate to microsoft.com, the browser shows that the certs I am using are the ones from microsoft.com. When I navigate to pub.dev, the browser shows that the certs are from the internal CA. All of the certificates are valid and present in the local machine cert store.
When I open the URL in the browser, an intermediate certificate with the same name is in the chain but it is valid. Several intermediate certificates with the same name are in the store and all but one of them are expired. I exported the valid ones in the chain to create the bundle I was testing with. |
I have finally been able to come back to this issue. I downloaded the most recent DEV build (2.15.0-42.0) and this issue is still present. I decided it was time to reduce the issue down to its core. I left the wonky proxy configuration out of the equation and focused specifically on the certificate store. I created a small .NET app that exported all certificates out of the local machine stores. The file produced by this code worked with the class Program
{
static void Main(string[] args)
{
// The locations here are CurrentUser and LocalMachine
IEnumerable<StoreLocation> locations = (StoreLocation[])Enum.GetValues(typeof(StoreLocation));
// The AddressBook, Disallowed, and TrustedPeople stores were explicily omitted.
IEnumerable<StoreName> names = new StoreName[] { StoreName.AuthRoot, StoreName.CertificateAuthority, StoreName.My, StoreName.Root, StoreName.TrustedPublisher };
List<X509Store> stores = new List<X509Store>();
System.Console.WriteLine("Getting certificate stores.");
foreach (StoreLocation location in locations)
{
foreach (StoreName name in names)
{
stores.Add(new X509Store(name, location));
}
}
IEnumerable<X509Certificate2> storeCerts = null;
System.Console.WriteLine("Writing certificates to valid_certs.pem");
using (StreamWriter writer = new StreamWriter("valid_certs.pem"))
{
foreach (X509Store store in stores)
{
storeCerts = Program.GetCertificates(store);
foreach (X509Certificate2 cert in storeCerts)
{
writer.WriteLine("-----BEGIN CERTIFICATE-----");
writer.WriteLine(Convert.ToBase64String(cert.RawData, Base64FormattingOptions.InsertLineBreaks));
writer.WriteLine("-----END CERTIFICATE-----");
writer.WriteLine(String.Empty);
writer.Flush();
}
if (store.IsOpen)
{
store.Close();
}
store.Dispose();
}
}
System.Console.WriteLine("Done");
}
private static IEnumerable<X509Certificate2> GetCertificates(X509Store store)
{
IEnumerable<X509Certificate2> certs = new List<X509Certificate2>();
store.Open(OpenFlags.ReadOnly);
if (store.Certificates.Count > 0)
{
certs = store.Certificates.Cast<X509Certificate2>().Where(c => c.NotAfter > DateTime.Now);
}
store.Close();
return certs;
}
} I then changed the private static IEnumerable<X509Certificate2> GetCertificates(X509Store store)
{
IEnumerable<X509Certificate2> certs = new List<X509Certificate2>();
store.Open(OpenFlags.ReadOnly);
if (store.Certificates.Count > 0)
{
// The call to Where was removed. This ensures all certificates are returned.
certs = store.Certificates.Cast<X509Certificate2>();
}
store.Close();
return certs;
} The two files were also tested with It looks like the certificate lookup is stopping on the first one found and ignoring all others. |
Okay, thank you @JSanford42 . Will you be able to give a try to dart sdk with a proposed fix https://dart-review.googlesource.com/c/sdk/+/211160 I can build for you? I don't have a clear plan on how to test this yet in ci setting. |
@aam I will gladly test the change. I usually download the SDK as a zip so I can switch between builds for testing. |
Okay @JSanford42 thanks, can you ping me your email to [email protected] so I share manually-built dart sdk google drive link with you? |
@aam I received the link, downloaded the build, and tested it. I did not enounter any of the certificate issues. The bad certificate callback was not executed in the code from the original post. I also tested the build with I look foward to seeing this fix in a future |
…not_after properties, only add valid ones. boringssl seems to be confused when expired certificates are present in trusted root, only picks up the first matching one which could be expired and ignores still-valid-ones. TEST=secure_socket_utils_test Fixes #46370 Change-Id: I5bbc0a1a3331ce4dcda46eee41b02b5b6e835b2a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211160 Reviewed-by: Siva Annamalai <[email protected]> Commit-Queue: Alexander Aprelev <[email protected]>
Windows Dart 2.14.0-93-dev and later.
The majority of this issue was discussed in the
pub
repo at dart-lang/pub#2990 and it appears to be an issue withdart
.A recent change to the runtime made all certificate stores on Windows accessible to
dart
. I am in an environment with an internal CA that issues certificates to the proxy servers. When the root certificates for a site are not known to the proxy, it uses the internal certificates for the communication between the workstation and the proxy. The internal certificates are regularly pushed to the workstations to prevent invalid certificate errors.The issue is that the expired certificates remain in the store and
dart
is attempting to use them. The runtime appears to be using the first certificate it encounters. If it is invalid for any reason, it throws an exception and moves on. This happens even when it does find a valid certificate.Running this code produces this result. (I had to mask some of the names with XXX due to policy.)
The first certificate displayed is expired but the second one is not. I have tried this URL in the browser and the valid certificate here is the one being used.
This issue can be replicated using the
--root-certs-file
option fordart
. I used a hand crafted certificate bundle that removed all expired certificates and this code worked. I tried using it withpub
and was getting local issuer certificate errors because I did not have the time to hand craft a certificate bundle that included 100+ items from my environment.The text was updated successfully, but these errors were encountered: