import (
"bytes"
"encoding/pem"
- "errors"
- "runtime"
)
// CertPool is a set of certificates.
// Any mutations to the returned pool are not written to disk and do
// not affect any other pool.
func SystemCertPool() (*CertPool, error) {
- if runtime.GOOS == "windows" {
- return nil, errors.New("crypto/x509: system root pool is not available on Windows")
- }
return loadSystemRoots()
}
return chains, nil
}
-func loadSystemRoots() (*CertPool, error) { return nil, nil }
+func loadSystemRoots() (*CertPool, error) {
+ const CRYPT_E_NOT_FOUND = 0x80092004
+
+ store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
+ if err != nil {
+ return nil, err
+ }
+ defer syscall.CertCloseStore(store, 0)
+
+ roots := NewCertPool()
+ var cert *syscall.CertContext
+ for {
+ cert, err = syscall.CertEnumCertificatesInStore(store, cert)
+ if err != nil {
+ if errno, ok := err.(syscall.Errno); ok {
+ if errno == CRYPT_E_NOT_FOUND {
+ break
+ }
+ }
+ return nil, err
+ }
+ if cert == nil {
+ break
+ }
+ // Copy the buf, since ParseCertificate does not create its own copy.
+ buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
+ buf2 := make([]byte, cert.Length)
+ copy(buf2, buf)
+ if c, err := ParseCertificate(buf2); err == nil {
+ roots.AddCert(c)
+ }
+ }
+ return roots, nil
+}
t.Errorf("got serial number of %q, but want %q", cert.Subject.SerialNumber, want)
}
}
+
+func TestSystemCertPool(t *testing.T) {
+ _, err := SystemCertPool()
+ if err != nil {
+ t.Fatal(err)
+ }
+}