func (repo CloudControllerBuildpackBitsRepository) downloadBuildpack(url string, cb func(*os.File, error)) { fileutils.TempFile("buildpack-download", func(tempfile *os.File, err error) { if err != nil { cb(nil, err) return } var certPool *x509.CertPool if len(repo.TrustedCerts) > 0 { certPool = x509.NewCertPool() for _, tlsCert := range repo.TrustedCerts { cert, _ := x509.ParseCertificate(tlsCert.Certificate[0]) certPool.AddCert(cert) } } client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: certPool}, Proxy: http.ProxyFromEnvironment, }, } response, err := client.Get(url) if err != nil { cb(nil, err) return } io.Copy(tempfile, response.Body) tempfile.Seek(0, 0) cb(tempfile, nil) }) }
func loadPEMCertificate(certPool *x509.CertPool, pemCerts []byte) (ok bool) { for len(pemCerts) > 0 { var block *pem.Block block, pemCerts = pem.Decode(pemCerts) if block == nil { break } if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { continue } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { continue } // Assumption: CA is self-signed. Not recommended // for production environments. cert.IsCA = true certPool.AddCert(cert) ok = true } return }
func loadStore(roots *x509.CertPool, name string) { store, errno := syscall.CertOpenSystemStore(syscall.InvalidHandle, syscall.StringToUTF16Ptr(name)) if errno != 0 { return } var cert *syscall.CertContext for { cert = syscall.CertEnumCertificatesInStore(store, cert) if cert == nil { break } var asn1Slice []byte hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&asn1Slice)) hdrp.Data = cert.EncodedCert hdrp.Len = int(cert.Length) hdrp.Cap = int(cert.Length) buf := make([]byte, len(asn1Slice)) copy(buf, asn1Slice) if cert, err := x509.ParseCertificate(buf); err == nil { roots.AddCert(cert) } } syscall.CertCloseStore(store, 0) }
func appendCerts(pool *x509.CertPool, certs []*x509.Certificate) *x509.CertPool { if len(certs) == 0 { // important to return unmodified (may be nil) return pool } if pool == nil { pool = x509.NewCertPool() } for _, cert := range certs { pool.AddCert(cert) } return pool }
func (c *CLI) GetTLSConfig(ctx *cli.Context) *tls.Config { var pool *x509.CertPool caCert, err := c.Config.Cluster.GetCertificateAuthority() if err != nil { // warn user } else { if caCert != nil { pool = x509.NewCertPool() pool.AddCert(caCert) } } return &tls.Config{ RootCAs: pool, InsecureSkipVerify: c.Config.Cluster.InsecureSkipVerify, } }
func loadStore(roots *x509.CertPool, name string) { store, err := syscall.CertOpenSystemStore(syscall.InvalidHandle, syscall.StringToUTF16Ptr(name)) if err != nil { return } defer syscall.CertCloseStore(store, 0) var cert *syscall.CertContext for { cert, err = syscall.CertEnumCertificatesInStore(store, cert) if err != nil { return } buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:] // ParseCertificate requires its own copy of certificate data to keep. buf2 := make([]byte, cert.Length) copy(buf2, buf) if c, err := x509.ParseCertificate(buf2); err == nil { roots.AddCert(c) } } }
// processCertDir iterates through the certDir looking for *.pem files. // Each pem file is read in turn and added to the pool. A count of the number // of successful certificates processed is returned. func processCertDir(pool *x509.CertPool) (count int) { fileInfo, err := os.Stat(certDir) if os.IsNotExist(err) { logger.Tracef("cert dir %q does not exist", certDir) return -1 } if err != nil { logger.Infof("unexpected error reading cert dir: %s", err) return -1 } if !fileInfo.IsDir() { logger.Infof("cert dir %q is not a directory", certDir) return -1 } matches, err := filepath.Glob(filepath.Join(certDir, "*.pem")) if err != nil { logger.Infof("globbing files failed: %s", err) return -1 } for _, match := range matches { data, err := ioutil.ReadFile(match) if err != nil { logger.Infof("error reading %q: %v", match, err) continue } certificate, err := cert.ParseCert(string(data)) if err != nil { logger.Infof("error parsing cert %q: %v", match, err) continue } pool.AddCert(certificate) count++ } return count }
func main() { var caFile, intFile string var forceIntermediateBundle, revexp, verbose bool flag.StringVar(&caFile, "ca", "", "CA certificate `bundle`") flag.StringVar(&intFile, "i", "", "intermediate `bundle`") flag.BoolVar(&forceIntermediateBundle, "f", false, "force the use of the intermediate bundle, ignoring any intermediates bundled with certificate") flag.BoolVar(&revexp, "r", false, "print revocation and expiry information") flag.BoolVar(&verbose, "v", false, "verbose") flag.Parse() var roots *x509.CertPool if caFile != "" { var err error if verbose { fmt.Println("[+] loading root certificates from", caFile) } roots, err = helpers.LoadPEMCertPool(caFile) die.If(err) } var ints *x509.CertPool if intFile != "" { var err error if verbose { fmt.Println("[+] loading intermediate certificates from", intFile) } ints, err = helpers.LoadPEMCertPool(caFile) die.If(err) } else { ints = x509.NewCertPool() } if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "Usage: %s [-ca bundle] [-i bundle] cert", lib.ProgName()) } fileData, err := ioutil.ReadFile(flag.Arg(0)) die.If(err) chain, err := helpers.ParseCertificatesPEM(fileData) die.If(err) if verbose { fmt.Printf("[+] %s has %d certificates\n", flag.Arg(0), len(chain)) } cert := chain[0] if len(chain) > 1 { if !forceIntermediateBundle { for _, intermediate := range chain[1:] { if verbose { fmt.Printf("[+] adding intermediate with SKI %x\n", intermediate.SubjectKeyId) } ints.AddCert(intermediate) } } } opts := x509.VerifyOptions{ Intermediates: ints, Roots: roots, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, } _, err = cert.Verify(opts) if err != nil { fmt.Fprintf(os.Stderr, "Verification failed: %v\n", err) os.Exit(1) } if verbose { fmt.Println("OK") } if revexp { printRevocation(cert) } }
func (conf *config) validCert(cert *x509.Certificate, intermediates *x509.CertPool) bool { _, err := cert.Verify(x509.VerifyOptions{Intermediates: intermediates}) if err == nil { return true } if _, ok := err.(x509.UnknownAuthorityError); !ok { // There was an error, but not because the certificate wasn't signed // by a recognized CA. So we go ahead and use the cert and let // the client experience the same error. return true } if conf.ExtraRootCerts != nil { _, err = cert.Verify(x509.VerifyOptions{Roots: conf.ExtraRootCerts, Intermediates: intermediates}) if err == nil { return true } if _, ok := err.(x509.UnknownAuthorityError); !ok { return true } } // Before we give up, we'll try fetching some intermediate certificates. if len(cert.IssuingCertificateURL) == 0 { return false } toFetch := cert.IssuingCertificateURL fetched := make(map[string]bool) for i := 0; i < len(toFetch); i++ { certURL := toFetch[i] if fetched[certURL] { continue } resp, err := http.Get(certURL) if err == nil { defer resp.Body.Close() } if err != nil || resp.StatusCode != 200 { continue } fetchedCert, err := ioutil.ReadAll(resp.Body) if err != nil { continue } // The fetched certificate might be in either DER or PEM format. if bytes.Contains(fetchedCert, []byte("-----BEGIN CERTIFICATE-----")) { // It's PEM. var certDER *pem.Block for { certDER, fetchedCert = pem.Decode(fetchedCert) if certDER == nil { break } if certDER.Type != "CERTIFICATE" { continue } thisCert, err := x509.ParseCertificate(certDER.Bytes) if err != nil { continue } intermediates.AddCert(thisCert) toFetch = append(toFetch, thisCert.IssuingCertificateURL...) } } else { // Hopefully it's DER. thisCert, err := x509.ParseCertificate(fetchedCert) if err != nil { continue } intermediates.AddCert(thisCert) toFetch = append(toFetch, thisCert.IssuingCertificateURL...) } } _, err = cert.Verify(x509.VerifyOptions{Intermediates: intermediates}) if err == nil { return true } if _, ok := err.(x509.UnknownAuthorityError); !ok { // There was an error, but not because the certificate wasn't signed // by a recognized CA. So we go ahead and use the cert and let // the client experience the same error. return true } return false }