Browse Source

pkg, clientv3, etcdmain: let grpcproxy rise an error when its cert has non empty CN

Fix https://github.com/etcd-io/etcd/issues/9521
Hitoshi Mitake 7 years ago
parent
commit
65887ae1b4
3 changed files with 28 additions and 1 deletions
  1. 1 1
      etcdmain/grpc_proxy.go
  2. 1 0
      pkg/tlsutil/tlsutil.go
  3. 26 0
      pkg/transport/listener.go

+ 1 - 1
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 {

+ 1 - 0
pkg/tlsutil/tlsutil.go

@@ -41,6 +41,7 @@ func NewCertPool(CAFiles []string) (*x509.CertPool, error) {
 			if err != nil {
 				return nil, err
 			}
+
 			certPool.AddCert(cert)
 		}
 	}

+ 26 - 0
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
 }