1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package x509util
16
17 import (
18 "encoding/pem"
19 "fmt"
20 "io"
21 "net/http"
22 "net/url"
23 "os"
24 "strings"
25
26 "github.com/google/certificate-transparency-go/x509"
27 )
28
29
30
31 func ReadPossiblePEMFile(filename, blockname string) ([][]byte, error) {
32 data, err := os.ReadFile(filename)
33 if err != nil {
34 return nil, fmt.Errorf("%s: failed to read data: %v", filename, err)
35 }
36 return dePEM(data, blockname), nil
37 }
38
39
40
41
42 func ReadPossiblePEMURL(target, blockname string) ([][]byte, error) {
43 if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") {
44
45 return ReadPossiblePEMFile(target, blockname)
46 }
47
48 rsp, err := http.Get(target)
49 if err != nil {
50 return nil, fmt.Errorf("failed to http.Get(%q): %v", target, err)
51 }
52 data, err := io.ReadAll(rsp.Body)
53 if err != nil {
54 return nil, fmt.Errorf("failed to io.ReadAll(%q): %v", target, err)
55 }
56 return dePEM(data, blockname), nil
57 }
58
59 func dePEM(data []byte, blockname string) [][]byte {
60 var results [][]byte
61 if strings.Contains(string(data), "BEGIN "+blockname) {
62 rest := data
63 for {
64 var block *pem.Block
65 block, rest = pem.Decode(rest)
66 if block == nil {
67 break
68 }
69 if block.Type == blockname {
70 results = append(results, block.Bytes)
71 }
72 }
73 } else {
74 results = append(results, data)
75 }
76 return results
77 }
78
79
80
81 func ReadFileOrURL(target string, client *http.Client) ([]byte, error) {
82 u, err := url.Parse(target)
83 if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
84 return os.ReadFile(target)
85 }
86
87 rsp, err := client.Get(u.String())
88 if err != nil {
89 return nil, fmt.Errorf("failed to http.Get(%q): %v", target, err)
90 }
91 return io.ReadAll(rsp.Body)
92 }
93
94
95
96
97 func GetIssuer(cert *x509.Certificate, client *http.Client) (*x509.Certificate, error) {
98 if len(cert.IssuingCertificateURL) == 0 {
99 return nil, nil
100 }
101 issuerURL := cert.IssuingCertificateURL[0]
102 rsp, err := client.Get(issuerURL)
103 if err != nil || rsp.StatusCode != http.StatusOK {
104 return nil, fmt.Errorf("failed to get issuer from %q: %v", issuerURL, err)
105 }
106 defer rsp.Body.Close()
107 body, err := io.ReadAll(rsp.Body)
108 if err != nil {
109 return nil, fmt.Errorf("failed to read issuer from %q: %v", issuerURL, err)
110 }
111 issuers, err := x509.ParseCertificates(body)
112 if err != nil {
113 return nil, fmt.Errorf("failed to parse issuer cert: %v", err)
114 }
115 return issuers[0], nil
116 }
117
View as plain text