lnd: prepare TLS code for extraction

This commit is contained in:
Oliver Gugger 2019-11-14 09:34:47 +01:00
parent e8b306b0ff
commit bfe10376f3
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

96
lnd.go

@ -57,8 +57,10 @@ import (
)
const (
// Make certificate valid for 14 months.
autogenCertValidity = 14 /*months*/ * 30 /*days*/ * 24 * time.Hour
// defaultAutogenCertValidity is the default validity of a self-signed
// certificate. The value corresponds to 14 months
// (14 months * 30 days * 24 hours).
defaultAutogenCertValidity = 14 * 30 * 24 * time.Hour
)
var (
@ -77,7 +79,8 @@ var (
serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128)
/*
* These cipher suites fit the following criteria:
* tlsCipherSuites is the list of cipher suites we accept for TLS
* connections. These cipher suites fit the following criteria:
* - Don't use outdated algorithms like SHA-1 and 3DES
* - Don't use ECB mode or other insecure symmetric methods
* - Included in the TLS v1.2 suite
@ -661,28 +664,28 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
tlsExtraDomains []string, rpcListeners []net.Addr) (*tls.Config,
*credentials.TransportCredentials, string, error) {
// Ensure we create TLS key and certificate if they don't exist
// Ensure we create TLS key and certificate if they don't exist.
if !fileExists(tlsCertPath) && !fileExists(tlsKeyPath) {
rpcsLog.Infof("Generating TLS certificates...")
err := genCertPair(
tlsCertPath, tlsKeyPath, tlsExtraIPs, tlsExtraDomains,
"lnd autogenerated cert", tlsCertPath, tlsKeyPath,
tlsExtraIPs, tlsExtraDomains,
defaultAutogenCertValidity,
)
if err != nil {
return nil, nil, "", err
}
rpcsLog.Infof("Done generating TLS certificates")
}
certData, err := tls.LoadX509KeyPair(tlsCertPath, tlsKeyPath)
certData, parsedCert, err := loadCert(tlsCertPath, tlsKeyPath)
if err != nil {
return nil, nil, "", err
}
cert, err := x509.ParseCertificate(certData.Certificate[0])
if err != nil {
return nil, nil, "", err
}
// If the certificate expired, delete it and the TLS key and generate a new pair
if time.Now().After(cert.NotAfter) {
// If the certificate expired, delete it and the TLS key and generate a
// new pair.
if time.Now().After(parsedCert.NotAfter) {
ltndLog.Info("TLS certificate is expired, generating a new one")
err := os.Remove(tlsCertPath)
@ -695,21 +698,19 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
return nil, nil, "", err
}
rpcsLog.Infof("Generating TLS certificates...")
err = genCertPair(
tlsCertPath, tlsKeyPath, tlsExtraIPs, tlsExtraDomains,
"lnd autogenerated cert", tlsCertPath, tlsKeyPath,
tlsExtraIPs, tlsExtraDomains,
defaultAutogenCertValidity,
)
if err != nil {
return nil, nil, "", err
}
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{certData},
CipherSuites: tlsCipherSuites,
MinVersion: tls.VersionTLS12,
rpcsLog.Infof("Done generating TLS certificates")
}
tlsCfg := tlsConfFromCert(certData)
restCreds, err := credentials.NewClientTLSFromFile(tlsCertPath, "")
if err != nil {
return nil, nil, "", err
@ -742,6 +743,41 @@ func fileExists(name string) bool {
return true
}
// loadCert loads a certificate and its corresponding private key from the PEM
// files indicated and returns the certificate in the two formats it is most
// commonly used.
func loadCert(certPath, keyPath string) (tls.Certificate, *x509.Certificate,
error) {
// The certData returned here is just a wrapper around the PEM blocks
// loaded from the file. The PEM is not yet fully parsed but a basic
// check is performed that the certificate and private key actually
// belong together.
certData, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return tls.Certificate{}, nil, err
}
// Now parse the the PEM block of the certificate into its x509 data
// structure so it can be examined in more detail.
x509Cert, err := x509.ParseCertificate(certData.Certificate[0])
if err != nil {
return tls.Certificate{}, nil, err
}
return certData, x509Cert, nil
}
// tLSConfFromCert returns the default TLS configuration used for a server,
// using the given certificate as identity.
func tlsConfFromCert(certData tls.Certificate) *tls.Config {
return &tls.Config{
Certificates: []tls.Certificate{certData},
CipherSuites: tlsCipherSuites,
MinVersion: tls.VersionTLS12,
}
}
// genCertPair generates a key/cert pair to the paths provided. The
// auto-generated certificates should *not* be used in production for public
// access as they're self-signed and don't necessarily contain all of the
@ -750,14 +786,11 @@ func fileExists(name string) bool {
//
// This function is adapted from https://github.com/btcsuite/btcd and
// https://github.com/btcsuite/btcutil
func genCertPair(certFile, keyFile string, tlsExtraIPs,
tlsExtraDomains []string) error {
func genCertPair(org, certFile, keyFile string, tlsExtraIPs,
tlsExtraDomains []string, certValidity time.Duration) error {
rpcsLog.Infof("Generating TLS certificates...")
org := "lnd autogenerated cert"
now := time.Now()
validUntil := now.Add(autogenCertValidity)
validUntil := now.Add(certValidity)
// Check that the certificate validity isn't past the ASN.1 end of time.
if validUntil.After(endOfTime) {
@ -776,7 +809,7 @@ func genCertPair(certFile, keyFile string, tlsExtraIPs,
// addIP appends an IP address only if it isn't already in the slice.
addIP := func(ipAddr net.IP) {
for _, ip := range ipAddresses {
if bytes.Equal(ip, ipAddr) {
if ip.Equal(ipAddr) {
return
}
}
@ -806,8 +839,10 @@ func genCertPair(certFile, keyFile string, tlsExtraIPs,
// Collect the host's names into a slice.
host, err := os.Hostname()
if err != nil {
rpcsLog.Errorf("Failed getting hostname, falling back to "+
"localhost: %v", err)
// Nothing much we can do here, other than falling back to
// localhost as fallback. A hostname can still be provided with
// the tlsExtraDomain parameter if the problem persists on a
// system.
host = "localhost"
}
@ -879,7 +914,6 @@ func genCertPair(certFile, keyFile string, tlsExtraIPs,
return err
}
rpcsLog.Infof("Done generating TLS certificates")
return nil
}