Commit 5b5d3efc authored by Adam Langley's avatar Adam Langley

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
parent 0fb6f5f2
...@@ -70,11 +70,12 @@ func initSystemRoots() { ...@@ -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 {
defer C.CFRelease(C.CFTypeRef(data)) return
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
roots.AppendCertsFromPEM(buf)
} }
defer C.CFRelease(C.CFTypeRef(data))
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
roots.AppendCertsFromPEM(buf)
systemRoots = roots systemRoots = roots
} }
...@@ -23,9 +23,11 @@ func initSystemRoots() { ...@@ -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.
} }
...@@ -11,5 +11,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate ...@@ -11,5 +11,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
} }
func initSystemRoots() { func initSystemRoots() {
systemRoots = NewCertPool()
} }
...@@ -27,9 +27,11 @@ func initSystemRoots() { ...@@ -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.
} }
...@@ -226,5 +226,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate ...@@ -226,5 +226,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
} }
func initSystemRoots() { func initSystemRoots() {
systemRoots = NewCertPool()
} }
...@@ -82,6 +82,14 @@ func (e UnknownAuthorityError) Error() string { ...@@ -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 ...@@ -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)
......
...@@ -15,19 +15,32 @@ import ( ...@@ -15,19 +15,32 @@ import (
) )
type verifyTest struct { type verifyTest struct {
leaf string leaf string
intermediates []string intermediates []string
roots []string roots []string
currentTime int64 currentTime int64
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) { ...@@ -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) { ...@@ -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)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment