forked from letsencrypt/challtestsrv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
event.go
133 lines (113 loc) · 3.62 KB
/
event.go
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package challtestsrv
import (
"net"
"strings"
"github.com/miekg/dns"
)
// RequestEventType indicates what type of event occurred.
type RequestEventType int
const (
// HTTP requests
HTTPRequestEventType RequestEventType = iota
// DNS requests
DNSRequestEventType
// TLS-ALPN-01 requests
TLSALPNRequestEventType
)
// A RequestEvent is anything that can identify its RequestEventType and a key
// for storing the request event in the history.
type RequestEvent interface {
Type() RequestEventType
Key() string
}
// HTTPRequestEvent corresponds to an HTTP request received by a httpOneServer.
// It implements the RequestEvent interface.
type HTTPRequestEvent struct {
// The full request URL (path and query arguments)
URL string
// The Host header from the request
Host string
// Whether the request was received over HTTPS or HTTP
HTTPS bool
// The ServerName from the ClientHello. May be empty if there was no SNI or if
// the request was not HTTPS
ServerName string
}
// HTTPRequestEvents always have type HTTPRequestEventType
func (e HTTPRequestEvent) Type() RequestEventType {
return HTTPRequestEventType
}
// HTTPRequestEvents use the HTTP Host as the storage key. Any explicit port
// will be removed.
func (e HTTPRequestEvent) Key() string {
if h, _, err := net.SplitHostPort(e.Host); err == nil {
return h
}
return e.Host
}
// DNSRequestEvent corresponds to a DNS request received by a dnsOneServer. It
// implements the RequestEvent interface.
type DNSRequestEvent struct {
// The DNS question received.
Question dns.Question
}
// DNSRequestEvents always have type DNSRequestEventType
func (e DNSRequestEvent) Type() RequestEventType {
return DNSRequestEventType
}
// DNSRequestEvents use the Question Name as the storage key. Any trailing `.`
// in the question name is removed.
func (e DNSRequestEvent) Key() string {
key := e.Question.Name
if strings.HasSuffix(key, ".") {
key = strings.TrimSuffix(key, ".")
}
return key
}
// TLSALPNRequestEvent corresponds to a TLS request received by
// a tlsALPNOneServer. It implements the RequestEvent interface.
type TLSALPNRequestEvent struct {
// ServerName from the TLS Client Hello.
ServerName string
// SupportedProtos from the TLS Client Hello.
SupportedProtos []string
}
// TLSALPNRequestEvents always have type TLSALPNRequestEventType
func (e TLSALPNRequestEvent) Type() RequestEventType {
return TLSALPNRequestEventType
}
// TLSALPNRequestEvents use the SNI value as the storage key
func (e TLSALPNRequestEvent) Key() string {
return e.ServerName
}
// AddRequestEvent adds a RequestEvent to the server's request history. It is
// appeneded to a list of RequestEvents indexed by the event's Type().
func (s *ChallSrv) AddRequestEvent(event RequestEvent) {
s.challMu.Lock()
defer s.challMu.Unlock()
typ := event.Type()
host := event.Key()
if s.requestHistory[host] == nil {
s.requestHistory[host] = make(map[RequestEventType][]RequestEvent)
}
s.requestHistory[host][typ] = append(s.requestHistory[host][typ], event)
}
// RequestHistory returns the server's request history for the given hostname
// and event type.
func (s *ChallSrv) RequestHistory(hostname string, typ RequestEventType) []RequestEvent {
s.challMu.RLock()
defer s.challMu.RUnlock()
if hostEvents, ok := s.requestHistory[hostname]; ok {
return hostEvents[typ]
}
return []RequestEvent{}
}
// ClearRequestHistory clears the server's request history for the given
// hostname and event type.
func (s *ChallSrv) ClearRequestHistory(hostname string, typ RequestEventType) {
s.challMu.Lock()
defer s.challMu.Unlock()
if hostEvents, ok := s.requestHistory[hostname]; ok {
hostEvents[typ] = []RequestEvent{}
}
}