crypto/x509: return a better error when we fail to load system roots.

R=golang-dev, krautz, rsc
CC=golang-dev
https://golang.org/cl/7157044
This commit is contained in:
Adam Langley 2013-01-21 11:25:28 -05:00
parent 0fb6f5f21b
commit 5b5d3efcf3
7 changed files with 63 additions and 17 deletions

View file

@ -70,11 +70,12 @@ func initSystemRoots() {
var data C.CFDataRef = nil var data C.CFDataRef = nil
err := C.FetchPEMRoots(&data) err := C.FetchPEMRoots(&data)
if err != -1 { if err == -1 {
return
}
defer C.CFRelease(C.CFTypeRef(data)) defer C.CFRelease(C.CFTypeRef(data))
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
roots.AppendCertsFromPEM(buf) roots.AppendCertsFromPEM(buf)
}
systemRoots = roots systemRoots = roots
} }

View file

@ -23,9 +23,11 @@ func initSystemRoots() {
data, err := ioutil.ReadFile(file) data, err := ioutil.ReadFile(file)
if err == nil { if err == nil {
roots.AppendCertsFromPEM(data) roots.AppendCertsFromPEM(data)
break systemRoots = roots
return
} }
} }
systemRoots = roots // All of the files failed to load. systemRoots will be nil which will
// trigger a specific error at verification time.
} }

View file

@ -11,5 +11,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
} }
func initSystemRoots() { func initSystemRoots() {
systemRoots = NewCertPool()
} }

View file

@ -27,9 +27,11 @@ func initSystemRoots() {
data, err := ioutil.ReadFile(file) data, err := ioutil.ReadFile(file)
if err == nil { if err == nil {
roots.AppendCertsFromPEM(data) roots.AppendCertsFromPEM(data)
break systemRoots = roots
return
} }
} }
systemRoots = roots // All of the files failed to load. systemRoots will be nil which will
// trigger a specific error at verification time.
} }

View file

@ -226,5 +226,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
} }
func initSystemRoots() { func initSystemRoots() {
systemRoots = NewCertPool()
} }

View file

@ -82,6 +82,14 @@ func (e UnknownAuthorityError) Error() string {
return "x509: certificate signed by unknown authority" return "x509: certificate signed by unknown authority"
} }
// SystemRootsError results when we fail to load the system root certificates.
type SystemRootsError struct {
}
func (e SystemRootsError) Error() string {
return "x509: failed to load system roots and no roots provided"
}
// VerifyOptions contains parameters for Certificate.Verify. It's a structure // VerifyOptions contains parameters for Certificate.Verify. It's a structure
// because other PKIX verification APIs have ended up needing many options. // because other PKIX verification APIs have ended up needing many options.
type VerifyOptions struct { type VerifyOptions struct {
@ -170,6 +178,9 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
if opts.Roots == nil { if opts.Roots == nil {
opts.Roots = systemRootsPool() opts.Roots = systemRootsPool()
if opts.Roots == nil {
return nil, SystemRootsError{}
}
} }
err = c.isValid(leafCertificate, nil, &opts) err = c.isValid(leafCertificate, nil, &opts)

View file

@ -22,12 +22,25 @@ type verifyTest struct {
dnsName string dnsName string
systemSkip bool systemSkip bool
keyUsages []ExtKeyUsage keyUsages []ExtKeyUsage
testSystemRootsError bool
errorCallback func(*testing.T, int, error) bool errorCallback func(*testing.T, int, error) bool
expectedChains [][]string expectedChains [][]string
} }
var verifyTests = []verifyTest{ var verifyTests = []verifyTest{
{
leaf: googleLeaf,
intermediates: []string{thawteIntermediate},
currentTime: 1302726541,
dnsName: "www.google.com",
testSystemRootsError: true,
systemSkip: true,
// Without any roots specified we should get a system roots
// error.
errorCallback: expectSystemRootsError,
},
{ {
leaf: googleLeaf, leaf: googleLeaf,
intermediates: []string{thawteIntermediate}, intermediates: []string{thawteIntermediate},
@ -180,6 +193,14 @@ func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
return true return true
} }
func expectSystemRootsError(t *testing.T, i int, err error) bool {
if _, ok := err.(SystemRootsError); !ok {
t.Errorf("#%d: error was not SystemRootsError: %s", i, err)
return false
}
return true
}
func certificateFromPEM(pemBytes string) (*Certificate, error) { func certificateFromPEM(pemBytes string) (*Certificate, error) {
block, _ := pem.Decode([]byte(pemBytes)) block, _ := pem.Decode([]byte(pemBytes))
if block == nil { if block == nil {
@ -226,8 +247,19 @@ func testVerify(t *testing.T, useSystemRoots bool) {
return return
} }
var oldSystemRoots *CertPool
if test.testSystemRootsError {
oldSystemRoots = systemRootsPool()
systemRoots = nil
opts.Roots = nil
}
chains, err := leaf.Verify(opts) chains, err := leaf.Verify(opts)
if test.testSystemRootsError {
systemRoots = oldSystemRoots
}
if test.errorCallback == nil && err != nil { if test.errorCallback == nil && err != nil {
t.Errorf("#%d: unexpected error: %s", i, err) t.Errorf("#%d: unexpected error: %s", i, err)
} }