1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
package policy
import (
"encoding/json"
"fmt"
"strings"
"time"
"rgdd.se/silentct/pkg/crtutil"
)
// Wildcards implement the monitor.Matcher interface for a list of wildcards.
//
// Warning: parsing of SANs in certificates is hard. This matcher depends on
// the parsing defined in github.com/google/certificate-transparency-go/x509.
type Wildcards []Wildcard
func (w *Wildcards) Match(leafData, extraData []byte) (bool, error) {
crt, err := crtutil.CertificateFromLogEntry(leafData, extraData)
if err != nil {
return false, err
}
return w.match(crt.DNSNames, crt.NotAfter), nil
}
func (w *Wildcards) match(sans []string, notAfter time.Time) bool {
for _, wildcard := range *w {
if wildcard.Match(sans, notAfter) {
return true
}
}
return false
}
// Wildcard matches any string that ends with `Wildcard`, unless:
//
// 1. `Excludes[i] + "." + Wildcard` is a longer suffix match, or
// 2. the certificate expired before the BootstrapAt timestamp.
type Wildcard struct {
BootstrapAt time.Time `json:"bootstrap_at"`
Wildcard string `json:"suffix"`
Excludes []string `json:"excludes,omitempty"`
}
func (w *Wildcard) UnmarshalJSON(data []byte) error {
type internal Wildcard
if err := json.Unmarshal(data, (*internal)(w)); err != nil {
return err
}
return w.Validate()
}
func (w *Wildcard) Validate() error {
if w.BootstrapAt.IsZero() {
return fmt.Errorf("bootstrap_at is required")
}
if len(w.Wildcard) == 0 {
return fmt.Errorf("suffix is required")
}
return nil
}
func (w *Wildcard) Match(sans []string, expiresAt time.Time) bool {
for _, san := range sans {
if san == w.Wildcard {
return w.BootstrapAt.Before(expiresAt)
}
if strings.HasSuffix(san, "."+w.Wildcard) && !w.exclude(san) {
return w.BootstrapAt.Before(expiresAt)
}
}
return false
}
func (w *Wildcard) exclude(san string) bool {
for _, exclude := range w.Excludes {
suffix := exclude + "." + w.Wildcard
if strings.HasSuffix(san, suffix) {
return true
}
}
return false
}
|