github.com/true-sqn/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  }