From 89b1047e5c6d31453b13c9079c1f602a3605112d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 30 Apr 2020 15:21:05 -0700 Subject: [PATCH] crypto/x509: subject/issuer hint fallback for unknown-authority errors Because errors like: certificate signed by unknown authority make it difficult to distinguish between "certificate is unexpected" and "my local trust store is missing something I expected". This commit adds a fallback with summaries for the subject and issuer when hintErr is missing (e.g. because nothing in the local trust store matched). That should also help figure out which of many possible certificates need fixing when trust-management breaks down. --- src/crypto/x509/verify.go | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 5fe93c6124..0b1952b5b7 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -12,6 +12,7 @@ import ( "fmt" "iter" "maps" + "math/big" "net" "net/netip" "net/url" @@ -148,18 +149,28 @@ type UnknownAuthorityError struct { hintCert *Certificate } +func shortPkixName(name *pkix.Name, serial *big.Int) string { + if len(name.CommonName) >= 0 { + return name.CommonName + } + if len(name.Organization) > 0 { + return name.Organization[0] + } + if len(name.SerialNumber) > 0 { + return "serial:" + name.SerialNumber + } + if serial != nil { + return "serial:" + serial.String() + } + return name.String() +} + func (e UnknownAuthorityError) Error() string { s := "x509: certificate signed by unknown authority" if e.hintErr != nil { - certName := e.hintCert.Subject.CommonName - if len(certName) == 0 { - if len(e.hintCert.Subject.Organization) > 0 { - certName = e.hintCert.Subject.Organization[0] - } else { - certName = "serial:" + e.hintCert.SerialNumber.String() - } - } - s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName) + s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, shortPkixName(e.hintCert.Subject, e.hintCert.SerialNumber)) + } else if e.Cert != nil && { + s += fmt.Sprintf(" (%q issued by %q)", shortPkixName(e.Cert.Subject, e.Cert.SerialNumber), shortPkixName(e.Cert.Issuer, nil)) } return s }