]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/x509: implement SystemCertPool on Windows
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Fri, 7 Oct 2016 08:10:53 +0000 (17:10 +0900)
committerBrad Fitzpatrick <bradfitz@golang.org>
Mon, 17 Oct 2016 08:29:16 +0000 (08:29 +0000)
Fixes #16736

Change-Id: I335d201e3f6738d838de3881087cb640fc7670e8
Reviewed-on: https://go-review.googlesource.com/30578
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/crypto/x509/cert_pool.go
src/crypto/x509/root_windows.go
src/crypto/x509/x509_test.go

index 7650494824e66a66da4f093bfbab7dbba975b7f3..8508cbacd773f2d072a6ba10f3a45595776af10d 100644 (file)
@@ -7,8 +7,6 @@ package x509
 import (
        "bytes"
        "encoding/pem"
-       "errors"
-       "runtime"
 )
 
 // CertPool is a set of certificates.
@@ -31,9 +29,6 @@ func NewCertPool() *CertPool {
 // 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()
 }
 
index 392c869012d8fc2f5d4b6ef730b49043b828984d..ca2fba5cb421fe7b7925358fa50d15061da99cc5 100644 (file)
@@ -225,4 +225,37 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
        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
+}
index ae77331a41a7a4e60943c2aad2031cd2e3573e77..354545ccbcbe70974a1a8c8d1ad586e600aef6df 100644 (file)
@@ -1457,3 +1457,10 @@ func TestMultipleRDN(t *testing.T) {
                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)
+       }
+}