github.com/yous1230/fabric@v2.0.0-beta.0.20191224111736-74345bee6ac2+incompatible/core/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  	"errors"
    13  	"net"
    14  
    15  	"github.com/hyperledger/fabric/common/flogging"
    16  	"google.golang.org/grpc/credentials"
    17  )
    18  
    19  var (
    20  	ErrClientHandshakeNotImplemented = errors.New("core/comm: client handshakes are not implemented with serverCreds")
    21  	ErrServerHandshakeNotImplemented = errors.New("core/comm: server handshakes are not implemented with clientCreds")
    22  	ErrOverrideHostnameNotSupported  = errors.New("core/comm: OverrideServerName is not supported")
    23  
    24  	// alpnProtoStr are the specified application level protocols for gRPC.
    25  	alpnProtoStr = []string{"h2"}
    26  )
    27  
    28  // NewServerTransportCredentials returns a new initialized
    29  // grpc/credentials.TransportCredentials
    30  func NewServerTransportCredentials(
    31  	serverConfig *tls.Config,
    32  	logger *flogging.FabricLogger) credentials.TransportCredentials {
    33  
    34  	// NOTE: unlike the default grpc/credentials implementation, we do not
    35  	// clone the tls.Config which allows us to update it dynamically
    36  	serverConfig.NextProtos = alpnProtoStr
    37  	// override TLS version and ensure it is 1.2
    38  	serverConfig.MinVersion = tls.VersionTLS12
    39  	serverConfig.MaxVersion = tls.VersionTLS12
    40  	return &serverCreds{
    41  		serverConfig: serverConfig,
    42  		logger:       logger}
    43  }
    44  
    45  // serverCreds is an implementation of grpc/credentials.TransportCredentials.
    46  type serverCreds struct {
    47  	serverConfig *tls.Config
    48  	logger       *flogging.FabricLogger
    49  }
    50  
    51  // ClientHandShake is not implemented for `serverCreds`.
    52  func (sc *serverCreds) ClientHandshake(context.Context,
    53  	string, net.Conn) (net.Conn, credentials.AuthInfo, error) {
    54  	return nil, nil, ErrClientHandshakeNotImplemented
    55  }
    56  
    57  // ServerHandshake does the authentication handshake for servers.
    58  func (sc *serverCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
    59  	conn := tls.Server(rawConn, sc.serverConfig)
    60  	if err := conn.Handshake(); err != nil {
    61  		if sc.logger != nil {
    62  			sc.logger.With("remote address",
    63  				conn.RemoteAddr().String()).Errorf("TLS handshake failed with error %s", err)
    64  		}
    65  		return nil, nil, err
    66  	}
    67  	return conn, credentials.TLSInfo{State: conn.ConnectionState()}, nil
    68  }
    69  
    70  // Info provides the ProtocolInfo of this TransportCredentials.
    71  func (sc *serverCreds) Info() credentials.ProtocolInfo {
    72  	return credentials.ProtocolInfo{
    73  		SecurityProtocol: "tls",
    74  		SecurityVersion:  "1.2",
    75  	}
    76  }
    77  
    78  // Clone makes a copy of this TransportCredentials.
    79  func (sc *serverCreds) Clone() credentials.TransportCredentials {
    80  	creds := NewServerTransportCredentials(sc.serverConfig, sc.logger)
    81  	return creds
    82  }
    83  
    84  // OverrideServerName overrides the server name used to verify the hostname
    85  // on the returned certificates from the server.
    86  func (sc *serverCreds) OverrideServerName(string) error {
    87  	return ErrOverrideHostnameNotSupported
    88  }
    89  
    90  type DynamicClientCredentials struct {
    91  	TLSConfig  *tls.Config
    92  	TLSOptions []TLSOption
    93  }
    94  
    95  func (dtc *DynamicClientCredentials) latestConfig() *tls.Config {
    96  	tlsConfigCopy := dtc.TLSConfig.Clone()
    97  	for _, tlsOption := range dtc.TLSOptions {
    98  		tlsOption(tlsConfigCopy)
    99  	}
   100  	return tlsConfigCopy
   101  }
   102  
   103  func (dtc *DynamicClientCredentials) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
   104  	return credentials.NewTLS(dtc.latestConfig()).ClientHandshake(ctx, authority, rawConn)
   105  }
   106  
   107  func (dtc *DynamicClientCredentials) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
   108  	return nil, nil, ErrServerHandshakeNotImplemented
   109  }
   110  
   111  func (dtc *DynamicClientCredentials) Info() credentials.ProtocolInfo {
   112  	return credentials.NewTLS(dtc.latestConfig()).Info()
   113  }
   114  
   115  func (dtc *DynamicClientCredentials) Clone() credentials.TransportCredentials {
   116  	return credentials.NewTLS(dtc.latestConfig())
   117  }
   118  
   119  func (dtc *DynamicClientCredentials) OverrideServerName(name string) error {
   120  	dtc.TLSConfig.ServerName = name
   121  	return nil
   122  }