Skip to content

Commit

Permalink
chore: add skip client san verification.
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Weindel <[email protected]>
Co-authored-by: Jingyi Hu <[email protected]>
Co-authored-by: Liming Liu <[email protected]>
  • Loading branch information
3 people committed Oct 3, 2019
1 parent bdd97d5 commit 9d4a134
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
2 changes: 2 additions & 0 deletions etcdmain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ func newConfig() *config {

fs.Var(flags.NewStringsValueV2(""), "cipher-suites", "Comma-separated list of supported TLS cipher suites between client/server and peers (empty will be auto-populated by Go).")

fs.BoolVar(&cfg.PeerTLSInfo.SkipClientSANVerify, "experimental-peer-skip-client-san-verification", false, "Skip verification of SAN field in client certificate for peer connections.")

// logging
fs.BoolVar(&cfg.Debug, "debug", false, "Enable debug-level logging for etcd.")
fs.StringVar(&cfg.LogPkgLevels, "log-package-levels", "", "Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG').")
Expand Down
7 changes: 6 additions & 1 deletion pkg/transport/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ func wrapTLS(addr, scheme string, tlsinfo *TLSInfo, l net.Listener) (net.Listene
if scheme != "https" && scheme != "unixs" {
return l, nil
}
return newTLSListener(l, tlsinfo)
if tlsinfo != nil && tlsinfo.SkipClientSANVerify {
return NewTLSListener(l, tlsinfo)
}
return newTLSListener(l, tlsinfo, checkSAN)
}

type TLSInfo struct {
Expand All @@ -62,6 +65,8 @@ type TLSInfo struct {
TrustedCAFile string
ClientCertAuth bool

SkipClientSANVerify bool

// ServerName ensures the cert matches the given host in case of discovery / virtual hosting
ServerName string

Expand Down
36 changes: 25 additions & 11 deletions pkg/transport/listener_tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,18 @@ type tlsListener struct {
donec chan struct{}
err error
handshakeFailure func(*tls.Conn, error)
check tlsCheckFunc
}

func newTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
type tlsCheckFunc func(context.Context, *tls.Conn) error

// NewTLSListener handshakes TLS connections and performs optional CRL checking.
func NewTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
check := func(context.Context, *tls.Conn) error { return nil }
return newTLSListener(l, tlsinfo, check)
}

func newTLSListener(l net.Listener, tlsinfo *TLSInfo, check tlsCheckFunc) (net.Listener, error) {
if tlsinfo == nil || tlsinfo.Empty() {
l.Close()
return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", l.Addr().String())
Expand All @@ -53,6 +62,7 @@ func newTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
connc: make(chan net.Conn),
donec: make(chan struct{}),
handshakeFailure: hf,
check: check,
}
go tlsl.acceptLoop()
return tlsl, nil
Expand Down Expand Up @@ -116,14 +126,9 @@ func (l *tlsListener) acceptLoop() {
return
}

st := tlsConn.ConnectionState()
if len(st.PeerCertificates) > 0 {
cert := st.PeerCertificates[0]
addr := tlsConn.RemoteAddr().String()
if cerr := checkCert(ctx, cert, addr); cerr != nil {
l.handshakeFailure(tlsConn, cerr)
return
}
if err := l.check(ctx, tlsConn); err != nil {
l.handshakeFailure(tlsConn, err)
return
}
select {
case l.connc <- tlsConn:
Expand All @@ -134,11 +139,20 @@ func (l *tlsListener) acceptLoop() {
}
}

func checkCert(ctx context.Context, cert *x509.Certificate, remoteAddr string) error {
h, _, herr := net.SplitHostPort(remoteAddr)
func checkSAN(ctx context.Context, tlsConn *tls.Conn) error {
st := tlsConn.ConnectionState()
if certs := st.PeerCertificates; len(certs) > 0 {
addr := tlsConn.RemoteAddr().String()
return checkCertSAN(ctx, certs[0], addr)
}
return nil
}

func checkCertSAN(ctx context.Context, cert *x509.Certificate, remoteAddr string) error {
if len(cert.IPAddresses) == 0 && len(cert.DNSNames) == 0 {
return nil
}
h, _, herr := net.SplitHostPort(remoteAddr)
if herr != nil {
return herr
}
Expand Down

0 comments on commit 9d4a134

Please sign in to comment.