mirror of
https://github.com/golang/go.git
synced 2025-05-17 21:34:36 +00:00
Fixes #38710 Change-Id: I9b210e95fd997ff53ec704c5f61110045aaa94bb Reviewed-on: https://go-review.googlesource.com/c/go/+/239559 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
180 lines
4.3 KiB
Go
180 lines
4.3 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ignore
|
|
|
|
// Generates root_darwin_ios.go.
|
|
//
|
|
// As of iOS 13, there is no API for querying the system trusted X.509 root
|
|
// certificates.
|
|
//
|
|
// Apple publishes the trusted root certificates for iOS and macOS on
|
|
// opensource.apple.com so we embed them into the x509 package.
|
|
//
|
|
// Note that this ignores distrusted and revoked certificates.
|
|
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/sha256"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"flag"
|
|
"fmt"
|
|
"go/format"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"path"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
var output = flag.String("output", "root_darwin_ios.go", "file name to write")
|
|
var version = flag.String("version", "", "security_certificates version")
|
|
flag.Parse()
|
|
if *version == "" {
|
|
log.Fatal("Select the latest security_certificates version from " +
|
|
"https://opensource.apple.com/source/security_certificates/")
|
|
}
|
|
|
|
url := "https://opensource.apple.com/tarballs/security_certificates/security_certificates-%s.tar.gz"
|
|
hc := &http.Client{Timeout: 1 * time.Minute}
|
|
resp, err := hc.Get(fmt.Sprintf(url, *version))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
log.Fatalf("HTTP status not OK: %s", resp.Status)
|
|
}
|
|
|
|
zr, err := gzip.NewReader(resp.Body)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer zr.Close()
|
|
|
|
var certs []*x509.Certificate
|
|
pool := x509.NewCertPool()
|
|
|
|
tr := tar.NewReader(zr)
|
|
for {
|
|
hdr, err := tr.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
rootsDirectory := fmt.Sprintf("security_certificates-%s/certificates/roots/", *version)
|
|
if dir, file := path.Split(hdr.Name); hdr.Typeflag != tar.TypeReg ||
|
|
dir != rootsDirectory || strings.HasPrefix(file, ".") {
|
|
continue
|
|
}
|
|
|
|
der, err := ioutil.ReadAll(tr)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
c, err := x509.ParseCertificate(der)
|
|
if err != nil {
|
|
log.Printf("Failed to parse certificate %q: %v", hdr.Name, err)
|
|
continue
|
|
}
|
|
|
|
certs = append(certs, c)
|
|
pool.AddCert(c)
|
|
}
|
|
|
|
// Quick smoke test to check the pool is well formed, and that we didn't end
|
|
// up trusting roots in the removed folder.
|
|
for _, c := range certs {
|
|
if c.Subject.CommonName == "Symantec Class 2 Public Primary Certification Authority - G4" {
|
|
log.Fatal("The pool includes a removed root!")
|
|
}
|
|
}
|
|
conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{
|
|
RootCAs: pool,
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
conn.Close()
|
|
|
|
certName := func(c *x509.Certificate) string {
|
|
if c.Subject.CommonName != "" {
|
|
return c.Subject.CommonName
|
|
}
|
|
if len(c.Subject.OrganizationalUnit) > 0 {
|
|
return c.Subject.OrganizationalUnit[0]
|
|
}
|
|
return c.Subject.Organization[0]
|
|
}
|
|
sort.Slice(certs, func(i, j int) bool {
|
|
if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) {
|
|
return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j]))
|
|
}
|
|
return certs[i].NotBefore.Before(certs[j].NotBefore)
|
|
})
|
|
|
|
out := new(bytes.Buffer)
|
|
fmt.Fprintf(out, header, *version)
|
|
fmt.Fprintf(out, "const systemRootsPEM = `\n")
|
|
|
|
for _, c := range certs {
|
|
fmt.Fprintf(out, "# %q\n", certName(c))
|
|
h := sha256.Sum256(c.Raw)
|
|
fmt.Fprintf(out, "# % X\n", h[:len(h)/2])
|
|
fmt.Fprintf(out, "# % X\n", h[len(h)/2:])
|
|
b := &pem.Block{
|
|
Type: "CERTIFICATE",
|
|
Bytes: c.Raw,
|
|
}
|
|
if err := pem.Encode(out, b); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
fmt.Fprintf(out, "`")
|
|
|
|
source, err := format.Source(out.Bytes())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
const header = `// Code generated by root_darwin_ios_gen.go -version %s; DO NOT EDIT.
|
|
// Update the version in root.go and regenerate with "go generate".
|
|
|
|
// +build darwin,arm64 darwin,amd64,ios
|
|
// +build !x509omitbundledroots
|
|
|
|
package x509
|
|
|
|
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// loadSystemRootsWithCgo is not available on iOS.
|
|
var loadSystemRootsWithCgo func() (*CertPool, error)
|
|
|
|
func loadSystemRoots() (*CertPool, error) {
|
|
p := NewCertPool()
|
|
p.AppendCertsFromPEM([]byte(systemRootsPEM))
|
|
return p, nil
|
|
}
|
|
`
|