Skip to content
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

crypto/x509: select a certificate store for systemVerify on Windows #34977

Open
SeanBurford opened this issue Oct 18, 2019 · 6 comments
Open
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Milestone

Comments

@SeanBurford
Copy link

SeanBurford commented Oct 18, 2019

What version of Go are you using (go version)?

$ go version
go version go1.13 linux/amd64

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:

var cert *x509.Certificate
...
intermediates := x509.NewCertPool()
intermediates.AddCert(intermediate)
vo := x509.VerifyOptions{
    Roots:         nil, // Use system roots
    Intermediates: intermediates,
}
chains, err := cert.Verify(vo)

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.

@networkimprov
Copy link

@SeanBurford it helps if you bracket code examples with ``` lines

example

cc @alexbrainman @mattn @zx2c4
@gopherbot add OS-Windows

@mattn
Copy link
Member

mattn commented Oct 18, 2019

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.

See #18609

@zx2c4
Copy link
Contributor

zx2c4 commented Oct 18, 2019

@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?

@dmitshur dmitshur changed the title Select a certificate store for systemVerify on Windows crypto/x509: select a certificate store for systemVerify on Windows Oct 21, 2019
@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 21, 2019
@SeanBurford
Copy link
Author

@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.

@zx2c4
Copy link
Contributor

zx2c4 commented Oct 22, 2019

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?

@andig
Copy link
Contributor

andig commented Mar 19, 2022

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)?

@seankhliao seankhliao added this to the Unplanned milestone Aug 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

8 participants