Open SeanBurford opened 4 years ago
@SeanBurford it helps if you bracket code examples with ``` lines
example
cc @alexbrainman @mattn @zx2c4 @gopherbot add OS-Windows
x509.SystemCertPool()
on Windows is not provided from standard library any more. The reason is that Windows doesn't ship with all of its root certificates installed. Instead, it downloads them on-demand.
@SeanBurford Are you saying that when the process is running as S-1-5-18, HCCE_CURRENT_USER
results in Go using a totally empty certificate store?
@zx2c4, no, I'm saying that the intermediates that we need to build the chain to a certificate are installed in the Local Machine System CA store. When running as S-1-5-18 a search of the Current User CA store doesn't find them so the chain(s) cannot be built.
So should we be passing HCCE_LOCAL_MACHINE all the time, or will that result in other complications when running as non-S-1-5-18?
I have a similar issue. Connecting to TLS with LetsEncrypt certificate I'd like to verify that root ca is either LetsEncrypt (I'd expect that to come from the system cert pool) or my own root ca certificate (I don't claim cryptographic correctness).
On windows this will error when retrieving the system cert pool:
certPool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}
if !certPool.AppendCertsFromPEM(caPEM()) {
return nil, fmt.Errorf("failed to add CA certificate")
}
// create the credentials and return it
config := &tls.Config{
RootCAs: certPool,
}
In the absence of SystemCertPool
, what is the right way to check the root CA (on Windows)?
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?Windows.
What did you do?
Attempted to build a set of certificate chains for a certificate:
What did you expect to see?
Complete chains when running as a user or as the system user.
What did you see instead?
systemVerify() in crypto.x509.root_windows.go always passes HCCE_CURRENT_USER as the hChainEngine argument to syscall.CertGetCertificateChain() (syscall.Handle(0) in the first argument). This means that chain lookups as the system user will fail for us, because the required certificates are stored in HCCE_LOCAL_MACHINE (syscall.Handle(1)).
It's possible to pass an additional store as argument 4 to the syscall. This argument is currently storeCtx.Store, which is nil but it might be possible for createStoreContext to populate it with a HCERTSTORE pointing to HCCE_LOCAL_MACHINE.
Alternately, the store preference could be specified in VerifyOptions.