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
|
package transport
import (
"crypto/tls"
"net"
"time"
"github.com/cloudflare/cfssl/log"
)
// A Listener is a TCP network listener for TLS-secured connections.
type Listener struct {
*Transport
net.Listener
}
// Listen sets up a new server. If an error is returned, it means
// the server isn't ready to begin listening.
func Listen(address string, tr *Transport) (*Listener, error) {
var err error
l := &Listener{Transport: tr}
config, err := tr.getConfig()
if err != nil {
return nil, err
}
l.Listener, err = tls.Listen("tcp", address, config)
return l, err
}
func (tr *Transport) getConfig() (*tls.Config, error) {
if tr.ClientTrustStore != nil {
log.Info("using client auth")
return tr.TLSClientAuthServerConfig()
}
log.Info("not using client auth")
return tr.TLSServerConfig()
}
// PollInterval is how often to check whether a new certificate has
// been found.
var PollInterval = 30 * time.Second
func pollWait(target time.Time) {
for {
<-time.After(PollInterval)
if time.Now().After(target) {
break
}
}
}
// AutoUpdate will automatically update the listener. If a non-nil
// certUpdates chan is provided, it will receive timestamps for
// reissued certificates. If errChan is non-nil, any errors that occur
// in the updater will be passed along.
func (l *Listener) AutoUpdate(certUpdates chan<- time.Time, errChan chan<- error) {
defer func() {
if r := recover(); r != nil {
log.Criticalf("AutoUpdate panicked: %v", r)
}
}()
for {
// Wait until it's time to update the certificate.
target := time.Now().Add(l.Lifespan())
if PollInterval == 0 {
<-time.After(l.Lifespan())
} else {
pollWait(target)
}
// Keep trying to update the certificate until it's
// ready.
for {
log.Debug("refreshing certificate")
err := l.RefreshKeys()
if err == nil {
break
}
delay := l.Transport.Backoff.Duration()
log.Debugf("failed to update certificate, will try again in %s", delay)
if errChan != nil {
errChan <- err
}
<-time.After(delay)
}
if certUpdates != nil {
certUpdates <- time.Now()
}
config, err := l.getConfig()
if err != nil {
log.Debugf("immediately after getting a new certificate, the Transport is reporting errors: %v", err)
if errChan != nil {
errChan <- err
}
}
address := l.Listener.Addr().String()
lnet := l.Listener.Addr().Network()
l.Listener, err = tls.Listen(lnet, address, config)
if err != nil {
log.Debugf("immediately after getting a new certificate, the Transport is reporting errors: %v", err)
if errChan != nil {
errChan <- err
}
}
log.Debug("listener: auto update of certificate complete")
l.Transport.Backoff.Reset()
}
}
|