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: Certificate.Verify on darwin no longer returns UnknownAuthorityError when the system verifier is used #53401

Closed
dnephin opened this issue Jun 15, 2022 · 3 comments

Comments

@dnephin
Copy link
Contributor

dnephin commented Jun 15, 2022

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

1.18.2

I'm pretty sure this is a regression from https://go-review.googlesource.com/c/go/+/353132 (#46287).

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

The bug reproduces on darwin/arm64 (and I suspect darwin/amd64 as well). I tested that the bug does not exist on linux/amd64.

What did you do?

Below is a minimal reproduction.

package main

import (
	"crypto/x509"
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"
)

func main() {
	handler := func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(200)
	}
	srv := httptest.NewTLSServer(http.HandlerFunc(handler))
	defer srv.Close()

	req, _ := http.NewRequest("GET", srv.URL, nil)
	c := http.Client{Timeout: time.Second}
	_, err := c.Do(req)

	fmt.Println(err)
	var uaErr x509.UnknownAuthorityError
	ok := errors.As(err, &uaErr)
	fmt.Println("should be true", ok)
}

The problem can be seen in libraries as well. For example this commit hashicorp/go-retryablehttp@bff1f16 is someone trying to work around the problem in hashicorp/go-retryablehttp.

What did you expect to see?

I expected the underlying error (url.Error.Err) to be x509.UnknownAuthorityError on all platforms regardless of what value I used for tls.Config.RootCAs.

In most cases:

  • on linux/amd64 with all versions of Go
  • on darwin with Go <= 1.17.x
  • when using non-system roots (i.e. any non-default value for tls.Config.RootCAs)

the errors.As(err, &uaErr) line correctly returns true, and the caller is able to inspect the certificate.

I did not test on windows, but from a quick read of root_windows.go it seems there is some effort made to create an UnknownAuthorityError in a number of cases, so it is likely that it works correctly on windows as well.

What did you see instead?

On darwin with Go 1.18.x , errors.As(err, &uaErr) returns false. The error is something like this:

url.Error{Op: "GET", Err: fmt.Errorf("x509: “ServerName” certificate is not trusted")}

url.Error.Err has a type of errors.errorString instead of x509.UnknownAuthorityError.

TestPlatformVerifier in crypto/x509/root_darwin_test.go is the only place I can find this error message, so I guess it must come from Certificate.systemVerify in root_darwin.go.

@dnephin
Copy link
Contributor Author

dnephin commented Jun 15, 2022

The workaround I found was to first attempt the request with the system roots, then repeat the request with the client changed to:

pool := x509.NewCertPool()
httpClient = http.Client{
	Transport: &http.Transport{
		TLSClientConfig: &tls.Config{RootCAs: pool},
	},
}

When using a different value for RootCAs I get the expected x509.UnknownAuthorityError.

@seankhliao
Copy link
Member

Duplicate of #52010

@seankhliao seankhliao marked this as a duplicate of #52010 Jun 15, 2022
@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Jun 15, 2022
@dnephin
Copy link
Contributor Author

dnephin commented Jun 15, 2022

Thanks! I was not able to find that issue from github search

@golang golang locked and limited conversation to collaborators Jun 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants