gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

tls.go (8694B)


      1 /*
      2  *
      3  * Copyright 2014 gRPC authors.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  */
     18 
     19 package credentials
     20 
     21 import (
     22 	"context"
     23 	"crypto/tls"
     24 	"crypto/x509"
     25 	"fmt"
     26 	"net"
     27 	"net/url"
     28 	"os"
     29 
     30 	credinternal "google.golang.org/grpc/internal/credentials"
     31 )
     32 
     33 // TLSInfo contains the auth information for a TLS authenticated connection.
     34 // It implements the AuthInfo interface.
     35 type TLSInfo struct {
     36 	State tls.ConnectionState
     37 	CommonAuthInfo
     38 	// This API is experimental.
     39 	SPIFFEID *url.URL
     40 }
     41 
     42 // AuthType returns the type of TLSInfo as a string.
     43 func (t TLSInfo) AuthType() string {
     44 	return "tls"
     45 }
     46 
     47 // GetSecurityValue returns security info requested by channelz.
     48 func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
     49 	v := &TLSChannelzSecurityValue{
     50 		StandardName: cipherSuiteLookup[t.State.CipherSuite],
     51 	}
     52 	// Currently there's no way to get LocalCertificate info from tls package.
     53 	if len(t.State.PeerCertificates) > 0 {
     54 		v.RemoteCertificate = t.State.PeerCertificates[0].Raw
     55 	}
     56 	return v
     57 }
     58 
     59 // tlsCreds is the credentials required for authenticating a connection using TLS.
     60 type tlsCreds struct {
     61 	// TLS configuration
     62 	config *tls.Config
     63 }
     64 
     65 func (c tlsCreds) Info() ProtocolInfo {
     66 	return ProtocolInfo{
     67 		SecurityProtocol: "tls",
     68 		SecurityVersion:  "1.2",
     69 		ServerName:       c.config.ServerName,
     70 	}
     71 }
     72 
     73 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
     74 	// use local cfg to avoid clobbering ServerName if using multiple endpoints
     75 	cfg := credinternal.CloneTLSConfig(c.config)
     76 	if cfg.ServerName == "" {
     77 		serverName, _, err := net.SplitHostPort(authority)
     78 		if err != nil {
     79 			// If the authority had no host port or if the authority cannot be parsed, use it as-is.
     80 			serverName = authority
     81 		}
     82 		cfg.ServerName = serverName
     83 	}
     84 	conn := tls.Client(rawConn, cfg)
     85 	errChannel := make(chan error, 1)
     86 	go func() {
     87 		errChannel <- conn.Handshake()
     88 		close(errChannel)
     89 	}()
     90 	select {
     91 	case err := <-errChannel:
     92 		if err != nil {
     93 			conn.Close()
     94 			return nil, nil, err
     95 		}
     96 	case <-ctx.Done():
     97 		conn.Close()
     98 		return nil, nil, ctx.Err()
     99 	}
    100 	tlsInfo := TLSInfo{
    101 		State: conn.ConnectionState(),
    102 		CommonAuthInfo: CommonAuthInfo{
    103 			SecurityLevel: PrivacyAndIntegrity,
    104 		},
    105 	}
    106 	id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
    107 	if id != nil {
    108 		tlsInfo.SPIFFEID = id
    109 	}
    110 	return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
    111 }
    112 
    113 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
    114 	conn := tls.Server(rawConn, c.config)
    115 	if err := conn.Handshake(); err != nil {
    116 		conn.Close()
    117 		return nil, nil, err
    118 	}
    119 	tlsInfo := TLSInfo{
    120 		State: conn.ConnectionState(),
    121 		CommonAuthInfo: CommonAuthInfo{
    122 			SecurityLevel: PrivacyAndIntegrity,
    123 		},
    124 	}
    125 	id := credinternal.SPIFFEIDFromState(conn.ConnectionState())
    126 	if id != nil {
    127 		tlsInfo.SPIFFEID = id
    128 	}
    129 	return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil
    130 }
    131 
    132 func (c *tlsCreds) Clone() TransportCredentials {
    133 	return NewTLS(c.config)
    134 }
    135 
    136 func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
    137 	c.config.ServerName = serverNameOverride
    138 	return nil
    139 }
    140 
    141 // NewTLS uses c to construct a TransportCredentials based on TLS.
    142 func NewTLS(c *tls.Config) TransportCredentials {
    143 	tc := &tlsCreds{credinternal.CloneTLSConfig(c)}
    144 	tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos)
    145 	return tc
    146 }
    147 
    148 // NewClientTLSFromCert constructs TLS credentials from the provided root
    149 // certificate authority certificate(s) to validate server connections. If
    150 // certificates to establish the identity of the client need to be included in
    151 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
    152 // tls.Config can be specified.
    153 // serverNameOverride is for testing only. If set to a non empty string,
    154 // it will override the virtual host name of authority (e.g. :authority header
    155 // field) in requests.
    156 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
    157 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
    158 }
    159 
    160 // NewClientTLSFromFile constructs TLS credentials from the provided root
    161 // certificate authority certificate file(s) to validate server connections. If
    162 // certificates to establish the identity of the client need to be included in
    163 // the credentials (eg: for mTLS), use NewTLS instead, where a complete
    164 // tls.Config can be specified.
    165 // serverNameOverride is for testing only. If set to a non empty string,
    166 // it will override the virtual host name of authority (e.g. :authority header
    167 // field) in requests.
    168 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
    169 	b, err := os.ReadFile(certFile)
    170 	if err != nil {
    171 		return nil, err
    172 	}
    173 	cp := x509.NewCertPool()
    174 	if !cp.AppendCertsFromPEM(b) {
    175 		return nil, fmt.Errorf("credentials: failed to append certificates")
    176 	}
    177 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
    178 }
    179 
    180 // NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
    181 func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
    182 	return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
    183 }
    184 
    185 // NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
    186 // file for server.
    187 func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
    188 	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    189 	if err != nil {
    190 		return nil, err
    191 	}
    192 	return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
    193 }
    194 
    195 // TLSChannelzSecurityValue defines the struct that TLS protocol should return
    196 // from GetSecurityValue(), containing security info like cipher and certificate used.
    197 //
    198 // # Experimental
    199 //
    200 // Notice: This type is EXPERIMENTAL and may be changed or removed in a
    201 // later release.
    202 type TLSChannelzSecurityValue struct {
    203 	ChannelzSecurityValue
    204 	StandardName      string
    205 	LocalCertificate  []byte
    206 	RemoteCertificate []byte
    207 }
    208 
    209 var cipherSuiteLookup = map[uint16]string{
    210 	tls.TLS_RSA_WITH_RC4_128_SHA:                "TLS_RSA_WITH_RC4_128_SHA",
    211 	tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA:           "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
    212 	tls.TLS_RSA_WITH_AES_128_CBC_SHA:            "TLS_RSA_WITH_AES_128_CBC_SHA",
    213 	tls.TLS_RSA_WITH_AES_256_CBC_SHA:            "TLS_RSA_WITH_AES_256_CBC_SHA",
    214 	tls.TLS_RSA_WITH_AES_128_GCM_SHA256:         "TLS_RSA_WITH_AES_128_GCM_SHA256",
    215 	tls.TLS_RSA_WITH_AES_256_GCM_SHA384:         "TLS_RSA_WITH_AES_256_GCM_SHA384",
    216 	tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:        "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
    217 	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
    218 	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
    219 	tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA:          "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
    220 	tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:     "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
    221 	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
    222 	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:      "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
    223 	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:   "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    224 	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    225 	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:   "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    226 	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
    227 	tls.TLS_FALLBACK_SCSV:                       "TLS_FALLBACK_SCSV",
    228 	tls.TLS_RSA_WITH_AES_128_CBC_SHA256:         "TLS_RSA_WITH_AES_128_CBC_SHA256",
    229 	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
    230 	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
    231 	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
    232 	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:  "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
    233 	tls.TLS_AES_128_GCM_SHA256:                  "TLS_AES_128_GCM_SHA256",
    234 	tls.TLS_AES_256_GCM_SHA384:                  "TLS_AES_256_GCM_SHA384",
    235 	tls.TLS_CHACHA20_POLY1305_SHA256:            "TLS_CHACHA20_POLY1305_SHA256",
    236 }