1package tlsutil
2
3import (
4	"crypto/tls"
5	"crypto/x509"
6	"fmt"
7	"io/ioutil"
8	"net"
9	"os"
10	"path/filepath"
11	"sort"
12	"strings"
13	"sync"
14	"time"
15
16	"github.com/hashicorp/go-hclog"
17
18	"github.com/hashicorp/consul/logging"
19)
20
21// ALPNWrapper is a function that is used to wrap a non-TLS connection and
22// returns an appropriate TLS connection or error. This taks a datacenter and
23// node name as argument to configure the desired SNI value and the desired
24// next proto for configuring ALPN.
25type ALPNWrapper func(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error)
26
27// DCWrapper is a function that is used to wrap a non-TLS connection
28// and returns an appropriate TLS connection or error. This takes
29// a datacenter as an argument.
30type DCWrapper func(dc string, conn net.Conn) (net.Conn, error)
31
32// Wrapper is a variant of DCWrapper, where the DC is provided as
33// a constant value. This is usually done by currying DCWrapper.
34type Wrapper func(conn net.Conn) (net.Conn, error)
35
36// TLSLookup maps the tls_min_version configuration to the internal value
37var TLSLookup = map[string]uint16{
38	"":      tls.VersionTLS10, // default in golang
39	"tls10": tls.VersionTLS10,
40	"tls11": tls.VersionTLS11,
41	"tls12": tls.VersionTLS12,
42	"tls13": tls.VersionTLS13,
43}
44
45// TLSVersions has all the keys from the map above.
46var TLSVersions = strings.Join(tlsVersions(), ", ")
47
48// Config used to create tls.Config
49type Config struct {
50	// VerifyIncoming is used to verify the authenticity of incoming
51	// connections.  This means that TCP requests are forbidden, only
52	// allowing for TLS. TLS connections must match a provided certificate
53	// authority. This can be used to force client auth.
54	VerifyIncoming bool
55
56	// VerifyIncomingRPC is used to verify the authenticity of incoming RPC
57	// connections.  This means that TCP requests are forbidden, only
58	// allowing for TLS. TLS connections must match a provided certificate
59	// authority. This can be used to force client auth.
60	VerifyIncomingRPC bool
61
62	// VerifyIncomingHTTPS is used to verify the authenticity of incoming
63	// HTTPS connections.  This means that TCP requests are forbidden, only
64	// allowing for TLS. TLS connections must match a provided certificate
65	// authority. This can be used to force client auth.
66	VerifyIncomingHTTPS bool
67
68	// VerifyOutgoing is used to verify the authenticity of outgoing
69	// connections.  This means that TLS requests are used, and TCP
70	// requests are not made. TLS connections must match a provided
71	// certificate authority. This is used to verify authenticity of server
72	// nodes.
73	VerifyOutgoing bool
74
75	// VerifyServerHostname is used to enable hostname verification of
76	// servers. This ensures that the certificate presented is valid for
77	// server.<datacenter>.<domain>.  This prevents a compromised client
78	// from being restarted as a server, and then intercepting request
79	// traffic as well as being added as a raft peer. This should be
80	// enabled by default with VerifyOutgoing, but for legacy reasons we
81	// cannot break existing clients.
82	VerifyServerHostname bool
83
84	// CAFile is a path to a certificate authority file. This is used with
85	// VerifyIncoming or VerifyOutgoing to verify the TLS connection.
86	CAFile string
87
88	// CAPath is a path to a directory containing certificate authority
89	// files. This is used with VerifyIncoming or VerifyOutgoing to verify
90	// the TLS connection.
91	CAPath string
92
93	// CertFile is used to provide a TLS certificate that is used for
94	// serving TLS connections.  Must be provided to serve TLS connections.
95	CertFile string
96
97	// KeyFile is used to provide a TLS key that is used for serving TLS
98	// connections.  Must be provided to serve TLS connections.
99	KeyFile string
100
101	// Node name is the name we use to advertise. Defaults to hostname.
102	NodeName string
103
104	// ServerName is used with the TLS certificate to ensure the name we
105	// provide matches the certificate
106	ServerName string
107
108	// Domain is the Consul TLD being used. Defaults to "consul."
109	Domain string
110
111	// TLSMinVersion is the minimum accepted TLS version that can be used.
112	TLSMinVersion string
113
114	// CipherSuites is the list of TLS cipher suites to use.
115	CipherSuites []uint16
116
117	// PreferServerCipherSuites specifies whether to prefer the server's
118	// ciphersuite over the client ciphersuites.
119	PreferServerCipherSuites bool
120
121	// EnableAgentTLSForChecks is used to apply the agent's TLS settings in
122	// order to configure the HTTP client used for health checks. Enabling
123	// this allows HTTP checks to present a client certificate and verify
124	// the server using the same TLS configuration as the agent (CA, cert,
125	// and key).
126	EnableAgentTLSForChecks bool
127
128	// AutoTLS opts the agent into provisioning agent
129	// TLS certificates.
130	AutoTLS bool
131}
132
133func tlsVersions() []string {
134	versions := []string{}
135	for v := range TLSLookup {
136		if v != "" {
137			versions = append(versions, v)
138		}
139	}
140	sort.Strings(versions)
141	return versions
142}
143
144// KeyPair is used to open and parse a certificate and key file
145func (c *Config) KeyPair() (*tls.Certificate, error) {
146	return loadKeyPair(c.CertFile, c.KeyFile)
147}
148
149// SpecificDC is used to invoke a static datacenter
150// and turns a DCWrapper into a Wrapper type.
151func SpecificDC(dc string, tlsWrap DCWrapper) Wrapper {
152	if tlsWrap == nil {
153		return nil
154	}
155	return func(conn net.Conn) (net.Conn, error) {
156		return tlsWrap(dc, conn)
157	}
158}
159
160type autoTLS struct {
161	extraCAPems          []string
162	connectCAPems        []string
163	cert                 *tls.Certificate
164	verifyServerHostname bool
165}
166
167// manual stores the TLS CA and cert received from Configurator.Update which
168// generally comes from the agent configuration.
169type manual struct {
170	caPems []string
171	cert   *tls.Certificate
172	// caPool containing only the caPems. This CertPool should be used instead of
173	// the Configurator.caPool when only the Agent TLS CA is allowed.
174	caPool *x509.CertPool
175}
176
177// Configurator holds a Config and is responsible for generating all the
178// *tls.Config necessary for Consul. Except the one in the api package.
179type Configurator struct {
180	sync.RWMutex
181	base                 *Config
182	autoTLS              *autoTLS
183	manual               *manual
184	peerDatacenterUseTLS map[string]bool
185
186	caPool  *x509.CertPool
187	logger  hclog.Logger
188	version int
189}
190
191// NewConfigurator creates a new Configurator and sets the provided
192// configuration.
193func NewConfigurator(config Config, logger hclog.Logger) (*Configurator, error) {
194	if logger == nil {
195		logger = hclog.New(&hclog.LoggerOptions{
196			Level: hclog.Debug,
197		})
198	}
199
200	c := &Configurator{
201		logger:               logger.Named(logging.TLSUtil),
202		manual:               &manual{},
203		autoTLS:              &autoTLS{},
204		peerDatacenterUseTLS: map[string]bool{},
205	}
206	err := c.Update(config)
207	if err != nil {
208		return nil, err
209	}
210	return c, nil
211}
212
213// ManualCAPems returns the currently loaded CAs in PEM format.
214func (c *Configurator) ManualCAPems() []string {
215	c.RLock()
216	defer c.RUnlock()
217	return c.manual.caPems
218}
219
220// Update updates the internal configuration which is used to generate
221// *tls.Config.
222// This function acquires a write lock because it writes the new config.
223func (c *Configurator) Update(config Config) error {
224	c.Lock()
225	// order of defers matters because log acquires a RLock()
226	defer c.log("Update")
227	defer c.Unlock()
228
229	cert, err := loadKeyPair(config.CertFile, config.KeyFile)
230	if err != nil {
231		return err
232	}
233	pems, err := LoadCAs(config.CAFile, config.CAPath)
234	if err != nil {
235		return err
236	}
237	caPool, err := newX509CertPool(pems, c.autoTLS.extraCAPems, c.autoTLS.connectCAPems)
238	if err != nil {
239		return err
240	}
241	if err = c.check(config, caPool, cert); err != nil {
242		return err
243	}
244	manualCAPool, err := newX509CertPool(pems)
245	if err != nil {
246		return err
247	}
248
249	c.base = &config
250	c.manual.cert = cert
251	c.manual.caPool = manualCAPool
252	c.manual.caPems = pems
253	c.caPool = caPool
254	c.version++
255	return nil
256}
257
258// UpdateAutoTLSCA updates the autoEncrypt.caPems. This is supposed to be called
259// from the server in order to be able to accept TLS connections with TLS
260// certificates.
261// Or it is being called on the client side when CA changes are detected.
262func (c *Configurator) UpdateAutoTLSCA(connectCAPems []string) error {
263	c.Lock()
264	// order of defers matters because log acquires a RLock()
265	defer c.log("UpdateAutoEncryptCA")
266	defer c.Unlock()
267
268	pool, err := newX509CertPool(c.manual.caPems, c.autoTLS.extraCAPems, connectCAPems)
269	if err != nil {
270		c.RUnlock()
271		return err
272	}
273	if err = c.check(*c.base, pool, c.manual.cert); err != nil {
274		c.RUnlock()
275		return err
276	}
277	c.autoTLS.connectCAPems = connectCAPems
278	c.caPool = pool
279	c.version++
280	return nil
281}
282
283// UpdateAutoTLSCert
284func (c *Configurator) UpdateAutoTLSCert(pub, priv string) error {
285	// order of defers matters because log acquires a RLock()
286	defer c.log("UpdateAutoEncryptCert")
287	cert, err := tls.X509KeyPair([]byte(pub), []byte(priv))
288	if err != nil {
289		return fmt.Errorf("Failed to load cert/key pair: %v", err)
290	}
291
292	c.Lock()
293	defer c.Unlock()
294
295	c.autoTLS.cert = &cert
296	c.version++
297	return nil
298}
299
300// UpdateAutoTLS sets everything under autoEncrypt. This is being called on the
301// client when it received its cert from AutoEncrypt/AutoConfig endpoints.
302func (c *Configurator) UpdateAutoTLS(manualCAPems, connectCAPems []string, pub, priv string, verifyServerHostname bool) error {
303	// order of defers matters because log acquires a RLock()
304	defer c.log("UpdateAutoEncrypt")
305	cert, err := tls.X509KeyPair([]byte(pub), []byte(priv))
306	if err != nil {
307		return fmt.Errorf("Failed to load cert/key pair: %v", err)
308	}
309
310	c.Lock()
311	defer c.Unlock()
312
313	pool, err := newX509CertPool(c.manual.caPems, manualCAPems, connectCAPems)
314	if err != nil {
315		return err
316	}
317	c.autoTLS.extraCAPems = manualCAPems
318	c.autoTLS.connectCAPems = connectCAPems
319	c.autoTLS.cert = &cert
320	c.caPool = pool
321	c.autoTLS.verifyServerHostname = verifyServerHostname
322	c.version++
323	return nil
324}
325
326func (c *Configurator) UpdateAreaPeerDatacenterUseTLS(peerDatacenter string, useTLS bool) {
327	c.Lock()
328	defer c.Unlock()
329	c.version++
330	c.peerDatacenterUseTLS[peerDatacenter] = useTLS
331}
332
333func (c *Configurator) getAreaForPeerDatacenterUseTLS(peerDatacenter string) bool {
334	c.RLock()
335	defer c.RUnlock()
336	if v, ok := c.peerDatacenterUseTLS[peerDatacenter]; ok {
337		return v
338	}
339	return true
340}
341
342func (c *Configurator) Base() Config {
343	c.RLock()
344	defer c.RUnlock()
345	return *c.base
346}
347
348// newX509CertPool loads all the groups of PEM encoded certificates into a
349// single x509.CertPool.
350//
351// The groups argument is a varargs of slices so that callers do not need to
352// append slices together. In some cases append can modify the backing array
353// of the first slice passed to append, which will often result in hard to
354// find bugs. By accepting a varargs of slices we remove the need for the
355// caller to append the groups, which should prevent any such bugs.
356func newX509CertPool(groups ...[]string) (*x509.CertPool, error) {
357	pool := x509.NewCertPool()
358	for _, group := range groups {
359		for _, pem := range group {
360			if !pool.AppendCertsFromPEM([]byte(pem)) {
361				return nil, fmt.Errorf("failed to parse PEM %s", pem)
362			}
363		}
364	}
365	if len(pool.Subjects()) == 0 {
366		return nil, nil
367	}
368	return pool, nil
369}
370
371func (c *Configurator) check(config Config, pool *x509.CertPool, cert *tls.Certificate) error {
372	// Check if a minimum TLS version was set
373	if config.TLSMinVersion != "" {
374		if _, ok := TLSLookup[config.TLSMinVersion]; !ok {
375			return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", config.TLSMinVersion, TLSVersions)
376		}
377	}
378
379	// Ensure we have a CA if VerifyOutgoing is set
380	if config.VerifyOutgoing && pool == nil {
381		return fmt.Errorf("VerifyOutgoing set, and no CA certificate provided!")
382	}
383
384	// Ensure we have a CA and cert if VerifyIncoming is set
385	if config.anyVerifyIncoming() {
386		if pool == nil {
387			// both auto-config and auto-encrypt require verifying the connection from the client to the server for secure
388			// operation. In order to be able to verify the servers certificate we must have some CA certs already provided.
389			// Therefore, even though both of those features can push down extra CA certificates which could be used to
390			// verify incoming connections, we still must consider it an error if none are provided in the initial configuration
391			// as those features cannot be successfully enabled without providing CA certificates to use those features.
392			return fmt.Errorf("VerifyIncoming set but no CA certificates were provided")
393		}
394
395		// We will use the auto_encrypt/auto_config cert for TLS in the incoming APIs when available. Therefore the check
396		// here will ensure that either we enabled one of those two features or a certificate and key were provided manually
397		if cert == nil && !config.AutoTLS {
398			return fmt.Errorf("VerifyIncoming requires either a Cert and Key pair in the configuration file, or auto_encrypt/auto_config be enabled")
399		}
400	}
401	return nil
402}
403
404func (c Config) anyVerifyIncoming() bool {
405	return c.baseVerifyIncoming() || c.VerifyIncomingRPC || c.VerifyIncomingHTTPS
406}
407
408func (c Config) verifyIncomingRPC() bool {
409	return c.baseVerifyIncoming() || c.VerifyIncomingRPC
410}
411
412func (c Config) verifyIncomingHTTPS() bool {
413	return c.baseVerifyIncoming() || c.VerifyIncomingHTTPS
414}
415
416func (c *Config) baseVerifyIncoming() bool {
417	return c.VerifyIncoming
418}
419
420func loadKeyPair(certFile, keyFile string) (*tls.Certificate, error) {
421	if certFile == "" || keyFile == "" {
422		return nil, nil
423	}
424	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
425	if err != nil {
426		return nil, fmt.Errorf("Failed to load cert/key pair: %v", err)
427	}
428	return &cert, nil
429}
430
431func LoadCAs(caFile, caPath string) ([]string, error) {
432	if caFile == "" && caPath == "" {
433		return nil, nil
434	}
435
436	pems := []string{}
437
438	readFn := func(path string) error {
439		pem, err := ioutil.ReadFile(path)
440		if err != nil {
441			return fmt.Errorf("Error loading from %s: %s", path, err)
442		}
443		pems = append(pems, string(pem))
444		return nil
445	}
446
447	walkFn := func(path string, info os.FileInfo, err error) error {
448		if err != nil {
449			return err
450		}
451
452		if !info.IsDir() {
453			if err := readFn(path); err != nil {
454				return err
455			}
456		}
457		return nil
458	}
459
460	if caFile != "" {
461		err := readFn(caFile)
462		if err != nil {
463			return pems, err
464		}
465	} else if caPath != "" {
466		err := filepath.Walk(caPath, walkFn)
467		if err != nil {
468			return pems, err
469		}
470		if len(pems) == 0 {
471			return pems, fmt.Errorf("Error loading from CAPath: no CAs found")
472		}
473	}
474	return pems, nil
475}
476
477// commonTLSConfig generates a *tls.Config from the base configuration the
478// Configurator has. It accepts an additional flag in case a config is needed
479// for incoming TLS connections.
480// This function acquires a read lock because it reads from the config.
481func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
482	// this needs to be outside of RLock because it acquires an RLock itself
483	verifyServerHostname := c.VerifyServerHostname()
484
485	c.RLock()
486	defer c.RUnlock()
487	tlsConfig := &tls.Config{
488		InsecureSkipVerify: !verifyServerHostname,
489	}
490
491	// Set the cipher suites
492	if len(c.base.CipherSuites) != 0 {
493		tlsConfig.CipherSuites = c.base.CipherSuites
494	}
495
496	tlsConfig.PreferServerCipherSuites = c.base.PreferServerCipherSuites
497
498	// GetCertificate is used when acting as a server and responding to
499	// client requests. Default to the manually configured cert, but allow
500	// autoEncrypt cert too so that a client can encrypt incoming
501	// connections without having a manual cert configured.
502	tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
503		return c.Cert(), nil
504	}
505
506	// GetClientCertificate is used when acting as a client and responding
507	// to a server requesting a certificate. Return the autoEncrypt certificate
508	// if possible, otherwise default to the manually provisioned one.
509	tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
510		cert := c.autoTLS.cert
511		if cert == nil {
512			cert = c.manual.cert
513		}
514
515		if cert == nil {
516			// the return value MUST not be nil but an empty certificate will be
517			// treated the same as having no client certificate
518			cert = &tls.Certificate{}
519		}
520
521		return cert, nil
522	}
523
524	tlsConfig.ClientCAs = c.caPool
525	tlsConfig.RootCAs = c.caPool
526
527	// This is possible because TLSLookup also contains "" with golang's
528	// default (tls10). And because the initial check makes sure the
529	// version correctly matches.
530	tlsConfig.MinVersion = TLSLookup[c.base.TLSMinVersion]
531
532	// Set ClientAuth if necessary
533	if verifyIncoming {
534		tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
535	}
536
537	return tlsConfig
538}
539
540// This function acquires a read lock because it reads from the config.
541func (c *Configurator) Cert() *tls.Certificate {
542	c.RLock()
543	defer c.RUnlock()
544	cert := c.manual.cert
545	if cert == nil {
546		cert = c.autoTLS.cert
547	}
548	return cert
549}
550
551// This function acquires a read lock because it reads from the config.
552func (c *Configurator) VerifyIncomingRPC() bool {
553	c.RLock()
554	defer c.RUnlock()
555	return c.base.verifyIncomingRPC()
556}
557
558// This function acquires a read lock because it reads from the config.
559func (c *Configurator) outgoingRPCTLSDisabled() bool {
560	c.RLock()
561	defer c.RUnlock()
562
563	// if AutoEncrypt enabled, always use TLS
564	if c.base.AutoTLS {
565		return false
566	}
567
568	// if CAs are provided or VerifyOutgoing is set, use TLS
569	if c.base.VerifyOutgoing {
570		return false
571	}
572
573	return true
574}
575
576func (c *Configurator) MutualTLSCapable() bool {
577	return c.mutualTLSCapable()
578}
579
580// This function acquires a read lock because it reads from the config.
581func (c *Configurator) mutualTLSCapable() bool {
582	c.RLock()
583	defer c.RUnlock()
584	return c.caPool != nil && (c.autoTLS.cert != nil || c.manual.cert != nil)
585}
586
587// This function acquires a read lock because it reads from the config.
588func (c *Configurator) verifyOutgoing() bool {
589	c.RLock()
590	defer c.RUnlock()
591
592	// If AutoEncryptTLS is enabled and there is a CA, then verify
593	// outgoing.
594	if c.base.AutoTLS && c.caPool != nil {
595		return true
596	}
597
598	return c.base.VerifyOutgoing
599}
600
601func (c *Configurator) ServerSNI(dc, nodeName string) string {
602	// Strip the trailing '.' from the domain if any
603	domain := strings.TrimSuffix(c.domain(), ".")
604
605	if nodeName == "" || nodeName == "*" {
606		return "server." + dc + "." + domain
607	}
608
609	return nodeName + ".server." + dc + "." + domain
610}
611
612// This function acquires a read lock because it reads from the config.
613func (c *Configurator) domain() string {
614	c.RLock()
615	defer c.RUnlock()
616	return c.base.Domain
617}
618
619// This function acquires a read lock because it reads from the config.
620func (c *Configurator) verifyIncomingRPC() bool {
621	c.RLock()
622	defer c.RUnlock()
623	return c.base.verifyIncomingRPC()
624}
625
626// This function acquires a read lock because it reads from the config.
627func (c *Configurator) verifyIncomingHTTPS() bool {
628	c.RLock()
629	defer c.RUnlock()
630	return c.base.verifyIncomingHTTPS()
631}
632
633// This function acquires a read lock because it reads from the config.
634func (c *Configurator) enableAgentTLSForChecks() bool {
635	c.RLock()
636	defer c.RUnlock()
637	return c.base.EnableAgentTLSForChecks
638}
639
640// This function acquires a read lock because it reads from the config.
641func (c *Configurator) serverNameOrNodeName() string {
642	c.RLock()
643	defer c.RUnlock()
644	if c.base.ServerName != "" {
645		return c.base.ServerName
646	}
647	return c.base.NodeName
648}
649
650// This function acquires a read lock because it reads from the config.
651func (c *Configurator) VerifyServerHostname() bool {
652	c.RLock()
653	defer c.RUnlock()
654	return c.base.VerifyServerHostname || c.autoTLS.verifyServerHostname
655}
656
657// IncomingGRPCConfig generates a *tls.Config for incoming GRPC connections.
658func (c *Configurator) IncomingGRPCConfig() *tls.Config {
659	c.log("IncomingGRPCConfig")
660
661	// false has the effect that this config doesn't require a client cert
662	// verification. This is because there is no verify_incoming_grpc
663	// configuration option. And using verify_incoming would be backwards
664	// incompatible, because even if it was set before, it didn't have an
665	// effect on the grpc server.
666	config := c.commonTLSConfig(false)
667	config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
668		return c.IncomingGRPCConfig(), nil
669	}
670	return config
671}
672
673// IncomingRPCConfig generates a *tls.Config for incoming RPC connections.
674func (c *Configurator) IncomingRPCConfig() *tls.Config {
675	c.log("IncomingRPCConfig")
676	config := c.commonTLSConfig(c.verifyIncomingRPC())
677	config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
678		return c.IncomingRPCConfig(), nil
679	}
680	return config
681}
682
683// IncomingALPNRPCConfig generates a *tls.Config for incoming RPC connections
684// directly using TLS with ALPN instead of the older byte-prefixed protocol.
685func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config {
686	c.log("IncomingALPNRPCConfig")
687	// Since the ALPN-RPC variation is indirectly exposed to the internet via
688	// mesh gateways we force mTLS and full server name verification.
689	config := c.commonTLSConfig(true)
690	config.InsecureSkipVerify = false
691
692	config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
693		return c.IncomingALPNRPCConfig(alpnProtos), nil
694	}
695	config.NextProtos = alpnProtos
696	return config
697}
698
699// IncomingInsecureRPCConfig means that it doesn't verify incoming even thought
700// it might have been configured. This is only supposed to be used by the
701// servers for the insecure RPC server. At the time of writing only the
702// AutoEncrypt.Sign call is supported on that server. And it might be the only
703// usecase ever.
704func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config {
705	c.log("IncomingInsecureRPCConfig")
706	config := c.commonTLSConfig(false)
707	config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
708		return c.IncomingInsecureRPCConfig(), nil
709	}
710	return config
711}
712
713// IncomingHTTPSConfig generates a *tls.Config for incoming HTTPS connections.
714func (c *Configurator) IncomingHTTPSConfig() *tls.Config {
715	c.log("IncomingHTTPSConfig")
716	config := c.commonTLSConfig(c.verifyIncomingHTTPS())
717	config.NextProtos = []string{"h2", "http/1.1"}
718	config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
719		return c.IncomingHTTPSConfig(), nil
720	}
721	return config
722}
723
724// OutgoingTLSConfigForCheck generates a *tls.Config for outgoing TLS connections
725// for checks. This function is separated because there is an extra flag to
726// consider for checks. EnableAgentTLSForChecks and InsecureSkipVerify has to
727// be checked for checks.
728func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName string) *tls.Config {
729	c.log("OutgoingTLSConfigForCheck")
730
731	if !c.enableAgentTLSForChecks() {
732		return &tls.Config{
733			InsecureSkipVerify: skipVerify,
734			ServerName:         serverName,
735		}
736	}
737
738	if serverName == "" {
739		serverName = c.serverNameOrNodeName()
740	}
741	config := c.commonTLSConfig(false)
742	config.InsecureSkipVerify = skipVerify
743	config.ServerName = serverName
744
745	return config
746}
747
748// OutgoingRPCConfig generates a *tls.Config for outgoing RPC connections. If
749// there is a CA or VerifyOutgoing is set, a *tls.Config will be provided,
750// otherwise we assume that no TLS should be used.
751func (c *Configurator) OutgoingRPCConfig() *tls.Config {
752	c.log("OutgoingRPCConfig")
753	if c.outgoingRPCTLSDisabled() {
754		return nil
755	}
756	return c.commonTLSConfig(false)
757}
758
759// OutgoingALPNRPCConfig generates a *tls.Config for outgoing RPC connections
760// directly using TLS with ALPN instead of the older byte-prefixed protocol.
761// If there is a CA or VerifyOutgoing is set, a *tls.Config will be provided,
762// otherwise we assume that no TLS should be used which completely disables the
763// ALPN variation.
764func (c *Configurator) OutgoingALPNRPCConfig() *tls.Config {
765	c.log("OutgoingALPNRPCConfig")
766	if !c.mutualTLSCapable() {
767		return nil // ultimately this will hard-fail as TLS is required
768	}
769
770	// Since the ALPN-RPC variation is indirectly exposed to the internet via
771	// mesh gateways we force mTLS and full server name verification.
772	config := c.commonTLSConfig(true)
773	config.InsecureSkipVerify = false
774	return config
775}
776
777// OutgoingRPCWrapper wraps the result of OutgoingRPCConfig in a DCWrapper. It
778// decides if verify server hostname should be used.
779func (c *Configurator) OutgoingRPCWrapper() DCWrapper {
780	c.log("OutgoingRPCWrapper")
781
782	// Generate the wrapper based on dc
783	return func(dc string, conn net.Conn) (net.Conn, error) {
784		if c.UseTLS(dc) {
785			return c.wrapTLSClient(dc, conn)
786		}
787		return conn, nil
788	}
789}
790
791func (c *Configurator) UseTLS(dc string) bool {
792	return !c.outgoingRPCTLSDisabled() && c.getAreaForPeerDatacenterUseTLS(dc)
793}
794
795// OutgoingALPNRPCWrapper wraps the result of OutgoingALPNRPCConfig in an
796// ALPNWrapper. It configures all of the negotiation plumbing.
797func (c *Configurator) OutgoingALPNRPCWrapper() ALPNWrapper {
798	c.log("OutgoingALPNRPCWrapper")
799	if !c.mutualTLSCapable() {
800		return nil
801	}
802
803	return func(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) {
804		return c.wrapALPNTLSClient(dc, nodeName, alpnProto, conn)
805	}
806}
807
808// AutoEncryptCertNotAfter returns NotAfter from the auto_encrypt cert. In case
809// there is no cert, it will return a time in the past.
810func (c *Configurator) AutoEncryptCertNotAfter() time.Time {
811	c.RLock()
812	defer c.RUnlock()
813	tlsCert := c.autoTLS.cert
814	if tlsCert == nil || tlsCert.Certificate == nil {
815		return time.Now().AddDate(0, 0, -1)
816	}
817	cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
818	if err != nil {
819		return time.Now().AddDate(0, 0, -1)
820	}
821	return cert.NotAfter
822}
823
824// AutoEncryptCertExpired returns if the auto_encrypt cert is expired.
825func (c *Configurator) AutoEncryptCertExpired() bool {
826	return c.AutoEncryptCertNotAfter().Before(time.Now())
827}
828
829// This function acquires a read lock because it reads from the config.
830func (c *Configurator) log(name string) {
831	if c.logger != nil {
832		c.RLock()
833		defer c.RUnlock()
834		c.logger.Trace(name, "version", c.version)
835	}
836}
837
838// Wrap a net.Conn into a client tls connection, performing any
839// additional verification as needed.
840//
841// As of go 1.3, crypto/tls only supports either doing no certificate
842// verification, or doing full verification including of the peer's
843// DNS name. For consul, we want to validate that the certificate is
844// signed by a known CA, but because consul doesn't use DNS names for
845// node names, we don't verify the certificate DNS names. Since go 1.3
846// no longer supports this mode of operation, we have to do it
847// manually.
848func (c *Configurator) wrapTLSClient(dc string, conn net.Conn) (net.Conn, error) {
849	config := c.OutgoingRPCConfig()
850	verifyServerHostname := c.VerifyServerHostname()
851	verifyOutgoing := c.verifyOutgoing()
852	domain := c.domain()
853
854	if verifyServerHostname {
855		// Strip the trailing '.' from the domain if any
856		domain = strings.TrimSuffix(domain, ".")
857		config.ServerName = "server." + dc + "." + domain
858	}
859	tlsConn := tls.Client(conn, config)
860
861	// If crypto/tls is doing verification, there's no need to do
862	// our own.
863	if !config.InsecureSkipVerify {
864		return tlsConn, nil
865	}
866
867	// If verification is not turned on, don't do it.
868	if !verifyOutgoing {
869		return tlsConn, nil
870	}
871
872	err := tlsConn.Handshake()
873	if err != nil {
874		tlsConn.Close()
875		return nil, err
876	}
877
878	// The following is lightly-modified from the doFullHandshake
879	// method in crypto/tls's handshake_client.go.
880	opts := x509.VerifyOptions{
881		Roots:         config.RootCAs,
882		CurrentTime:   time.Now(),
883		DNSName:       "",
884		Intermediates: x509.NewCertPool(),
885	}
886
887	certs := tlsConn.ConnectionState().PeerCertificates
888	for i, cert := range certs {
889		if i == 0 {
890			continue
891		}
892		opts.Intermediates.AddCert(cert)
893	}
894
895	_, err = certs[0].Verify(opts)
896	if err != nil {
897		tlsConn.Close()
898		return nil, err
899	}
900
901	return tlsConn, err
902}
903
904// Wrap a net.Conn into a client tls connection suitable for secure ALPN-RPC,
905// performing any additional verification as needed.
906func (c *Configurator) wrapALPNTLSClient(dc, nodeName, alpnProto string, conn net.Conn) (net.Conn, error) {
907	if dc == "" {
908		return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target datacenter")
909	} else if nodeName == "" {
910		return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target node")
911	} else if alpnProto == "" {
912		return nil, fmt.Errorf("cannot dial using ALPN-RPC without a target alpn protocol")
913	}
914
915	config := c.OutgoingALPNRPCConfig()
916	if config == nil {
917		return nil, fmt.Errorf("cannot dial via a mesh gateway when outgoing TLS is disabled")
918	}
919
920	// Since the ALPN-RPC variation is indirectly exposed to the internet via
921	// mesh gateways we force mTLS and full hostname validation (forcing
922	// verify_server_hostname and verify_outgoing to be effectively true).
923
924	config.ServerName = c.ServerSNI(dc, nodeName)
925	config.NextProtos = []string{alpnProto}
926
927	tlsConn := tls.Client(conn, config)
928
929	// NOTE: For this handshake to succeed the server must have key material
930	// for either "<nodename>.server.<datacenter>.<domain>" or
931	// "*.server.<datacenter>.<domain>" in addition to the
932	// "server.<datacenter>.<domain>" required for standard TLS'd RPC.
933	if err := tlsConn.Handshake(); err != nil {
934		tlsConn.Close()
935		return nil, err
936	}
937
938	return tlsConn, nil
939}
940
941// AuthorizeServerConn is used to validate that the connection is being established
942// by a Consul server in the same datacenter.
943//
944// The identity of the connection is checked by verifying that the certificate
945// presented is signed by the Agent TLS CA, and has a DNSName that matches the
946// local ServerSNI name.
947//
948// Note this check is only performed if VerifyServerHostname is enabled, otherwise
949// it does no authorization.
950func (c *Configurator) AuthorizeServerConn(dc string, conn *tls.Conn) error {
951	if !c.VerifyServerHostname() {
952		return nil
953	}
954
955	c.RLock()
956	caPool := c.manual.caPool
957	c.RUnlock()
958
959	expected := c.ServerSNI(dc, "")
960	for _, chain := range conn.ConnectionState().VerifiedChains {
961		if len(chain) == 0 {
962			continue
963		}
964		clientCert := chain[0]
965		_, err := clientCert.Verify(x509.VerifyOptions{
966			DNSName:   expected,
967			Roots:     caPool,
968			KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
969		})
970		if err == nil {
971			return nil
972		}
973		c.logger.Debug("AuthorizeServerConn failed certificate validation", "error", err)
974	}
975	return fmt.Errorf("a TLS certificate with a CommonName of %v is required for this operation", expected)
976}
977
978// ParseCiphers parse ciphersuites from the comma-separated string into
979// recognized slice
980func ParseCiphers(cipherStr string) ([]uint16, error) {
981	suites := []uint16{}
982
983	cipherStr = strings.TrimSpace(cipherStr)
984	if cipherStr == "" {
985		return []uint16{}, nil
986	}
987	ciphers := strings.Split(cipherStr, ",")
988
989	// Note: this needs to be kept up to date with the cipherMap in CipherString
990	cipherMap := map[string]uint16{
991		"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":    tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
992		"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
993		"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
994		"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":    tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
995		"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
996		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":      tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
997		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256":   tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
998		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":   tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
999		"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":      tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
1000		"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":   tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
1001	}
1002	for _, cipher := range ciphers {
1003		if v, ok := cipherMap[cipher]; ok {
1004			suites = append(suites, v)
1005		} else {
1006			return suites, fmt.Errorf("unsupported cipher %q", cipher)
1007		}
1008	}
1009
1010	return suites, nil
1011}
1012
1013// CipherString performs the inverse operation of ParseCiphers
1014func CipherString(ciphers []uint16) (string, error) {
1015	// Note: this needs to be kept up to date with the cipherMap in ParseCiphers
1016	cipherMap := map[uint16]string{
1017		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
1018		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
1019		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
1020		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
1021		tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
1022		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
1023		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
1024		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:   "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
1025		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:      "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
1026		tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:   "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
1027	}
1028
1029	cipherStrings := make([]string, len(ciphers))
1030	for i, cipher := range ciphers {
1031		if v, ok := cipherMap[cipher]; ok {
1032			cipherStrings[i] = v
1033		} else {
1034			return "", fmt.Errorf("unsupported cipher %d", cipher)
1035		}
1036	}
1037
1038	return strings.Join(cipherStrings, ","), nil
1039}
1040