From 65887ae1b495c55e5c51371ff9807dbe5cb3fbc4 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sun, 23 Dec 2018 00:21:53 +0900 Subject: [PATCH] pkg, clientv3, etcdmain: let grpcproxy rise an error when its cert has non empty CN Fix https://github.com/etcd-io/etcd/issues/9521 --- etcdmain/grpc_proxy.go | 2 +- pkg/tlsutil/tlsutil.go | 1 + pkg/transport/listener.go | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/etcdmain/grpc_proxy.go b/etcdmain/grpc_proxy.go index 425ba8fc8..581863d99 100644 --- a/etcdmain/grpc_proxy.go +++ b/etcdmain/grpc_proxy.go @@ -307,7 +307,7 @@ func newTLS(ca, cert, key string) *transport.TLSInfo { if ca == "" && cert == "" && key == "" { return nil } - return &transport.TLSInfo{TrustedCAFile: ca, CertFile: cert, KeyFile: key} + return &transport.TLSInfo{TrustedCAFile: ca, CertFile: cert, KeyFile: key, EmptyCN: true} } func mustListenCMux(lg *zap.Logger, tlsinfo *transport.TLSInfo) cmux.CMux { diff --git a/pkg/tlsutil/tlsutil.go b/pkg/tlsutil/tlsutil.go index 79b1f632e..3a5aef089 100644 --- a/pkg/tlsutil/tlsutil.go +++ b/pkg/tlsutil/tlsutil.go @@ -41,6 +41,7 @@ func NewCertPool(CAFiles []string) (*x509.CertPool, error) { if err != nil { return nil, err } + certPool.AddCert(cert) } } diff --git a/pkg/transport/listener.go b/pkg/transport/listener.go index 620b9e790..0c593e8e2 100644 --- a/pkg/transport/listener.go +++ b/pkg/transport/listener.go @@ -91,6 +91,10 @@ type TLSInfo struct { // Logger logs TLS errors. // If nil, all logs are discarded. Logger *zap.Logger + + // EmptyCN indicates that the cert must have empty CN. + // If true, ClientConfig() will return an error for a cert with non empty CN. + EmptyCN bool } func (info TLSInfo) String() string { @@ -378,6 +382,28 @@ func (info TLSInfo) ClientConfig() (*tls.Config, error) { if info.selfCert { cfg.InsecureSkipVerify = true } + + if info.EmptyCN { + hasNonEmptyCN := false + cn := "" + tlsutil.NewCert(info.CertFile, info.KeyFile, func(certPEMBlock []byte, keyPEMBlock []byte) (tls.Certificate, error) { + var block *pem.Block + block, _ = pem.Decode(certPEMBlock) + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return tls.Certificate{}, err + } + if len(cert.Subject.CommonName) != 0 { + hasNonEmptyCN = true + cn = cert.Subject.CommonName + } + return tls.X509KeyPair(certPEMBlock, keyPEMBlock) + }) + if hasNonEmptyCN { + return nil, fmt.Errorf("cert has non empty Common Name (%s)", cn) + } + } + return cfg, nil }