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{}
}
}
|