github.com/lzy4123/fabric@v2.1.1+incompatible/internal/pkg/comm/creds.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package comm 8 9 import ( 10 "context" 11 "crypto/tls" 12 "crypto/x509" 13 "errors" 14 "net" 15 "sync" 16 17 "github.com/hyperledger/fabric/common/flogging" 18 "google.golang.org/grpc/credentials" 19 ) 20 21 var ( 22 ErrClientHandshakeNotImplemented = errors.New("core/comm: client handshakes are not implemented with serverCreds") 23 ErrServerHandshakeNotImplemented = errors.New("core/comm: server handshakes are not implemented with clientCreds") 24 ErrOverrideHostnameNotSupported = errors.New("core/comm: OverrideServerName is not supported") 25 26 // alpnProtoStr are the specified application level protocols for gRPC. 27 alpnProtoStr = []string{"h2"} 28 ) 29 30 // NewServerTransportCredentials returns a new initialized 31 // grpc/credentials.TransportCredentials 32 func NewServerTransportCredentials( 33 serverConfig *TLSConfig, 34 logger *flogging.FabricLogger) credentials.TransportCredentials { 35 // NOTE: unlike the default grpc/credentials implementation, we do not 36 // clone the tls.Config which allows us to update it dynamically 37 serverConfig.config.NextProtos = alpnProtoStr 38 // override TLS version and ensure it is 1.2 39 serverConfig.config.MinVersion = tls.VersionTLS12 40 serverConfig.config.MaxVersion = tls.VersionTLS12 41 return &serverCreds{ 42 serverConfig: serverConfig, 43 logger: logger} 44 } 45 46 // serverCreds is an implementation of grpc/credentials.TransportCredentials. 47 type serverCreds struct { 48 serverConfig *TLSConfig 49 logger *flogging.FabricLogger 50 } 51 52 type TLSConfig struct { 53 config *tls.Config 54 lock sync.RWMutex 55 } 56 57 func NewTLSConfig(config *tls.Config) *TLSConfig { 58 return &TLSConfig{ 59 config: config, 60 } 61 } 62 63 func (t *TLSConfig) Config() tls.Config { 64 t.lock.RLock() 65 defer t.lock.RUnlock() 66 67 if t.config != nil { 68 return *t.config.Clone() 69 } 70 71 return tls.Config{} 72 } 73 74 func (t *TLSConfig) AddClientRootCA(cert *x509.Certificate) { 75 t.lock.Lock() 76 defer t.lock.Unlock() 77 78 t.config.ClientCAs.AddCert(cert) 79 } 80 81 func (t *TLSConfig) SetClientCAs(certPool *x509.CertPool) { 82 t.lock.Lock() 83 defer t.lock.Unlock() 84 85 t.config.ClientCAs = certPool 86 } 87 88 // ClientHandShake is not implemented for `serverCreds`. 89 func (sc *serverCreds) ClientHandshake(context.Context, 90 string, net.Conn) (net.Conn, credentials.AuthInfo, error) { 91 return nil, nil, ErrClientHandshakeNotImplemented 92 } 93 94 // ServerHandshake does the authentication handshake for servers. 95 func (sc *serverCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 96 serverConfig := sc.serverConfig.Config() 97 98 conn := tls.Server(rawConn, &serverConfig) 99 if err := conn.Handshake(); err != nil { 100 if sc.logger != nil { 101 sc.logger.With("remote address", 102 conn.RemoteAddr().String()).Errorf("TLS handshake failed with error %s", err) 103 } 104 return nil, nil, err 105 } 106 return conn, credentials.TLSInfo{State: conn.ConnectionState()}, nil 107 } 108 109 // Info provides the ProtocolInfo of this TransportCredentials. 110 func (sc *serverCreds) Info() credentials.ProtocolInfo { 111 return credentials.ProtocolInfo{ 112 SecurityProtocol: "tls", 113 SecurityVersion: "1.2", 114 } 115 } 116 117 // Clone makes a copy of this TransportCredentials. 118 func (sc *serverCreds) Clone() credentials.TransportCredentials { 119 config := sc.serverConfig.Config() 120 serverConfig := NewTLSConfig(&config) 121 return NewServerTransportCredentials(serverConfig, sc.logger) 122 } 123 124 // OverrideServerName overrides the server name used to verify the hostname 125 // on the returned certificates from the server. 126 func (sc *serverCreds) OverrideServerName(string) error { 127 return ErrOverrideHostnameNotSupported 128 } 129 130 type DynamicClientCredentials struct { 131 TLSConfig *tls.Config 132 TLSOptions []TLSOption 133 } 134 135 func (dtc *DynamicClientCredentials) latestConfig() *tls.Config { 136 tlsConfigCopy := dtc.TLSConfig.Clone() 137 for _, tlsOption := range dtc.TLSOptions { 138 tlsOption(tlsConfigCopy) 139 } 140 return tlsConfigCopy 141 } 142 143 func (dtc *DynamicClientCredentials) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 144 return credentials.NewTLS(dtc.latestConfig()).ClientHandshake(ctx, authority, rawConn) 145 } 146 147 func (dtc *DynamicClientCredentials) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 148 return nil, nil, ErrServerHandshakeNotImplemented 149 } 150 151 func (dtc *DynamicClientCredentials) Info() credentials.ProtocolInfo { 152 return credentials.NewTLS(dtc.latestConfig()).Info() 153 } 154 155 func (dtc *DynamicClientCredentials) Clone() credentials.TransportCredentials { 156 return credentials.NewTLS(dtc.latestConfig()) 157 } 158 159 func (dtc *DynamicClientCredentials) OverrideServerName(name string) error { 160 dtc.TLSConfig.ServerName = name 161 return nil 162 }