From bfe10376f391ae7bd132679d7471f63672fec86d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 14 Nov 2019 09:34:47 +0100 Subject: [PATCH 1/5] lnd: prepare TLS code for extraction --- lnd.go | 96 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 31 deletions(-) diff --git a/lnd.go b/lnd.go index f1eb59024..2d9264aa3 100644 --- a/lnd.go +++ b/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 } From b18698c32190996e688c7373b08d52f5449543d7 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 13 Nov 2019 13:59:13 +0100 Subject: [PATCH 2/5] cert: copy common TLS code from lnd to cert package --- cert/selfsigned.go | 171 +++++++++++++++++++++++++++++++++++++++++++++ cert/tls.go | 60 ++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 cert/selfsigned.go create mode 100644 cert/tls.go diff --git a/cert/selfsigned.go b/cert/selfsigned.go new file mode 100644 index 000000000..7e3dbf63f --- /dev/null +++ b/cert/selfsigned.go @@ -0,0 +1,171 @@ +package cert + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "io/ioutil" + "math/big" + "net" + "os" + "time" +) + +const ( + // 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 ( + // End of ASN.1 time. + endOfTime = time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) + + // Max serial number. + serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128) +) + +// 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 +// desired hostnames for the service. For production/public use, consider a +// real PKI. +// +// This function is adapted from https://github.com/btcsuite/btcd and +// https://github.com/btcsuite/btcutil +func genCertPair(org, certFile, keyFile string, tlsExtraIPs, + tlsExtraDomains []string, certValidity time.Duration) error { + + now := time.Now() + validUntil := now.Add(certValidity) + + // Check that the certificate validity isn't past the ASN.1 end of time. + if validUntil.After(endOfTime) { + validUntil = endOfTime + } + + // Generate a serial number that's below the serialNumberLimit. + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return fmt.Errorf("failed to generate serial number: %s", err) + } + + // Collect the host's IP addresses, including loopback, in a slice. + ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")} + + // addIP appends an IP address only if it isn't already in the slice. + addIP := func(ipAddr net.IP) { + for _, ip := range ipAddresses { + if ip.Equal(ipAddr) { + return + } + } + ipAddresses = append(ipAddresses, ipAddr) + } + + // Add all the interface IPs that aren't already in the slice. + addrs, err := net.InterfaceAddrs() + if err != nil { + return err + } + for _, a := range addrs { + ipAddr, _, err := net.ParseCIDR(a.String()) + if err == nil { + addIP(ipAddr) + } + } + + // Add extra IPs to the slice. + for _, ip := range tlsExtraIPs { + ipAddr := net.ParseIP(ip) + if ipAddr != nil { + addIP(ipAddr) + } + } + + // Collect the host's names into a slice. + host, err := os.Hostname() + if err != nil { + // 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" + } + + dnsNames := []string{host} + if host != "localhost" { + dnsNames = append(dnsNames, "localhost") + } + dnsNames = append(dnsNames, tlsExtraDomains...) + + // Also add fake hostnames for unix sockets, otherwise hostname + // verification will fail in the client. + dnsNames = append(dnsNames, "unix", "unixpacket") + + // Generate a private key for the certificate. + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return err + } + + // Construct the certificate template. + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{org}, + CommonName: host, + }, + NotBefore: now.Add(-time.Hour * 24), + NotAfter: validUntil, + + KeyUsage: x509.KeyUsageKeyEncipherment | + x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + IsCA: true, // so can sign self. + BasicConstraintsValid: true, + + DNSNames: dnsNames, + IPAddresses: ipAddresses, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, + &template, &priv.PublicKey, priv) + if err != nil { + return fmt.Errorf("failed to create certificate: %v", err) + } + + certBuf := &bytes.Buffer{} + err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", + Bytes: derBytes}) + if err != nil { + return fmt.Errorf("failed to encode certificate: %v", err) + } + + keybytes, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return fmt.Errorf("unable to encode privkey: %v", err) + } + keyBuf := &bytes.Buffer{} + err = pem.Encode(keyBuf, &pem.Block{Type: "EC PRIVATE KEY", + Bytes: keybytes}) + if err != nil { + return fmt.Errorf("failed to encode private key: %v", err) + } + + // Write cert and key files. + if err = ioutil.WriteFile(certFile, certBuf.Bytes(), 0644); err != nil { + return err + } + if err = ioutil.WriteFile(keyFile, keyBuf.Bytes(), 0600); err != nil { + os.Remove(certFile) + return err + } + + return nil +} diff --git a/cert/tls.go b/cert/tls.go new file mode 100644 index 000000000..49da5f46a --- /dev/null +++ b/cert/tls.go @@ -0,0 +1,60 @@ +package cert + +import ( + "crypto/tls" + "crypto/x509" +) + +var ( + /* + * 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 + * - Are available in the Go 1.7.6 standard library (more are + * available in 1.8.3 and will be added after lnd no longer + * supports 1.7, including suites that support CBC mode) + **/ + tlsCipherSuites = []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + } +) + +// 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, + } +} From dbbb169e0668ea4c259e6d65133ab6e32df16f44 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 13 Nov 2019 14:03:10 +0100 Subject: [PATCH 3/5] lnd: use TLS code from cert package --- cert/selfsigned.go | 8 +- cert/tls.go | 8 +- lnd.go | 229 ++------------------------------------------- 3 files changed, 17 insertions(+), 228 deletions(-) diff --git a/cert/selfsigned.go b/cert/selfsigned.go index 7e3dbf63f..e8bd57101 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -17,10 +17,10 @@ import ( ) const ( - // defaultAutogenCertValidity is the default validity of a self-signed + // DefaultAutogenValidity 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 + DefaultAutogenValidity = 14 * 30 * 24 * time.Hour ) var ( @@ -31,7 +31,7 @@ var ( serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128) ) -// genCertPair generates a key/cert pair to the paths provided. The +// 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 // desired hostnames for the service. For production/public use, consider a @@ -39,7 +39,7 @@ var ( // // This function is adapted from https://github.com/btcsuite/btcd and // https://github.com/btcsuite/btcutil -func genCertPair(org, certFile, keyFile string, tlsExtraIPs, +func GenCertPair(org, certFile, keyFile string, tlsExtraIPs, tlsExtraDomains []string, certValidity time.Duration) error { now := time.Now() diff --git a/cert/tls.go b/cert/tls.go index 49da5f46a..a8783158e 100644 --- a/cert/tls.go +++ b/cert/tls.go @@ -24,10 +24,10 @@ var ( } ) -// loadCert loads a certificate and its corresponding private key from the PEM +// 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, +func LoadCert(certPath, keyPath string) (tls.Certificate, *x509.Certificate, error) { // The certData returned here is just a wrapper around the PEM blocks @@ -49,9 +49,9 @@ func loadCert(certPath, keyPath string) (tls.Certificate, *x509.Certificate, return certData, x509Cert, nil } -// tLSConfFromCert returns the default TLS configuration used for a server, +// TLSConfFromCert returns the default TLS configuration used for a server, // using the given certificate as identity. -func tlsConfFromCert(certData tls.Certificate) *tls.Config { +func TLSConfFromCert(certData tls.Certificate) *tls.Config { return &tls.Config{ Certificates: []tls.Certificate{certData}, CipherSuites: tlsCipherSuites, diff --git a/lnd.go b/lnd.go index 2d9264aa3..06379c1d1 100644 --- a/lnd.go +++ b/lnd.go @@ -5,18 +5,10 @@ package lnd import ( - "bytes" "context" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" "crypto/tls" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" "fmt" "io/ioutil" - "math/big" "net" "net/http" "os" @@ -42,6 +34,7 @@ import ( "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/build" + "github.com/lightningnetwork/lnd/cert" "github.com/lightningnetwork/lnd/chanacceptor" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" @@ -56,13 +49,6 @@ import ( "github.com/lightningnetwork/lnd/watchtower/wtdb" ) -const ( - // 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 ( cfg *config registeredChains = newChainRegistry() @@ -71,29 +57,6 @@ var ( // network. This path will hold the files related to each different // network. networkDir string - - // End of ASN.1 time. - endOfTime = time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) - - // Max serial number. - serialNumberLimit = new(big.Int).Lsh(big.NewInt(1), 128) - - /* - * 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 - * - Are available in the Go 1.7.6 standard library (more are - * available in 1.8.3 and will be added after lnd no longer - * supports 1.7, including suites that support CBC mode) - **/ - tlsCipherSuites = []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - } ) // ListenerCfg is a wrapper around custom listeners that can be passed to lnd @@ -667,10 +630,10 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs, // Ensure we create TLS key and certificate if they don't exist. if !fileExists(tlsCertPath) && !fileExists(tlsKeyPath) { rpcsLog.Infof("Generating TLS certificates...") - err := genCertPair( + err := cert.GenCertPair( "lnd autogenerated cert", tlsCertPath, tlsKeyPath, tlsExtraIPs, tlsExtraDomains, - defaultAutogenCertValidity, + cert.DefaultAutogenValidity, ) if err != nil { return nil, nil, "", err @@ -678,7 +641,7 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs, rpcsLog.Infof("Done generating TLS certificates") } - certData, parsedCert, err := loadCert(tlsCertPath, tlsKeyPath) + certData, parsedCert, err := cert.LoadCert(tlsCertPath, tlsKeyPath) if err != nil { return nil, nil, "", err } @@ -698,19 +661,19 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs, return nil, nil, "", err } - rpcsLog.Infof("Generating TLS certificates...") - err = genCertPair( + rpcsLog.Infof("Renewing TLS certificates...") + err = cert.GenCertPair( "lnd autogenerated cert", tlsCertPath, tlsKeyPath, tlsExtraIPs, tlsExtraDomains, - defaultAutogenCertValidity, + cert.DefaultAutogenValidity, ) if err != nil { return nil, nil, "", err } - rpcsLog.Infof("Done generating TLS certificates") + rpcsLog.Infof("Done renewing TLS certificates") } - tlsCfg := tlsConfFromCert(certData) + tlsCfg := cert.TLSConfFromCert(certData) restCreds, err := credentials.NewClientTLSFromFile(tlsCertPath, "") if err != nil { return nil, nil, "", err @@ -743,180 +706,6 @@ 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 -// desired hostnames for the service. For production/public use, consider a -// real PKI. -// -// This function is adapted from https://github.com/btcsuite/btcd and -// https://github.com/btcsuite/btcutil -func genCertPair(org, certFile, keyFile string, tlsExtraIPs, - tlsExtraDomains []string, certValidity time.Duration) error { - - now := time.Now() - validUntil := now.Add(certValidity) - - // Check that the certificate validity isn't past the ASN.1 end of time. - if validUntil.After(endOfTime) { - validUntil = endOfTime - } - - // Generate a serial number that's below the serialNumberLimit. - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - return fmt.Errorf("failed to generate serial number: %s", err) - } - - // Collect the host's IP addresses, including loopback, in a slice. - ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")} - - // addIP appends an IP address only if it isn't already in the slice. - addIP := func(ipAddr net.IP) { - for _, ip := range ipAddresses { - if ip.Equal(ipAddr) { - return - } - } - ipAddresses = append(ipAddresses, ipAddr) - } - - // Add all the interface IPs that aren't already in the slice. - addrs, err := net.InterfaceAddrs() - if err != nil { - return err - } - for _, a := range addrs { - ipAddr, _, err := net.ParseCIDR(a.String()) - if err == nil { - addIP(ipAddr) - } - } - - // Add extra IPs to the slice. - for _, ip := range tlsExtraIPs { - ipAddr := net.ParseIP(ip) - if ipAddr != nil { - addIP(ipAddr) - } - } - - // Collect the host's names into a slice. - host, err := os.Hostname() - if err != nil { - // 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" - } - - dnsNames := []string{host} - if host != "localhost" { - dnsNames = append(dnsNames, "localhost") - } - dnsNames = append(dnsNames, tlsExtraDomains...) - - // Also add fake hostnames for unix sockets, otherwise hostname - // verification will fail in the client. - dnsNames = append(dnsNames, "unix", "unixpacket") - - // Generate a private key for the certificate. - priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return err - } - - // Construct the certificate template. - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{org}, - CommonName: host, - }, - NotBefore: now.Add(-time.Hour * 24), - NotAfter: validUntil, - - KeyUsage: x509.KeyUsageKeyEncipherment | - x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - IsCA: true, // so can sign self. - BasicConstraintsValid: true, - - DNSNames: dnsNames, - IPAddresses: ipAddresses, - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, - &template, &priv.PublicKey, priv) - if err != nil { - return fmt.Errorf("failed to create certificate: %v", err) - } - - certBuf := &bytes.Buffer{} - err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", - Bytes: derBytes}) - if err != nil { - return fmt.Errorf("failed to encode certificate: %v", err) - } - - keybytes, err := x509.MarshalECPrivateKey(priv) - if err != nil { - return fmt.Errorf("unable to encode privkey: %v", err) - } - keyBuf := &bytes.Buffer{} - err = pem.Encode(keyBuf, &pem.Block{Type: "EC PRIVATE KEY", - Bytes: keybytes}) - if err != nil { - return fmt.Errorf("failed to encode private key: %v", err) - } - - // Write cert and key files. - if err = ioutil.WriteFile(certFile, certBuf.Bytes(), 0644); err != nil { - return err - } - if err = ioutil.WriteFile(keyFile, keyBuf.Bytes(), 0600); err != nil { - os.Remove(certFile) - return err - } - - return nil -} - // genMacaroons generates three macaroon files; one admin-level, one for // invoice access and one read-only. These can also be used to generate more // granular macaroons. From b145378a4d315a39dc4e5929ea501d3713c46d69 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 13 Nov 2019 09:25:43 +0100 Subject: [PATCH 4/5] cert: create independent go modules --- cert/go.mod | 3 +++ go.mod | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 cert/go.mod diff --git a/cert/go.mod b/cert/go.mod new file mode 100644 index 000000000..29aa7fe7c --- /dev/null +++ b/cert/go.mod @@ -0,0 +1,3 @@ +module github.com/lightningnetwork/lnd/cert + +go 1.13 diff --git a/go.mod b/go.mod index 1014fef38..19dd914bf 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec github.com/lightninglabs/neutrino v0.10.1-0.20191111074637-d9b036bf675c github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a + github.com/lightningnetwork/lnd/cert v0.0.0-00010101000000-000000000000 github.com/lightningnetwork/lnd/queue v1.0.1 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 @@ -58,6 +59,8 @@ replace github.com/lightningnetwork/lnd/ticker => ./ticker replace github.com/lightningnetwork/lnd/queue => ./queue +replace github.com/lightningnetwork/lnd/cert => ./cert + replace git.schwanenlied.me/yawning/bsaes.git => github.com/Yawning/bsaes v0.0.0-20180720073208-c0276d75487e go 1.12 From 6a807b2d4c342a3053cc0d00e6ee9c3ff9489e6b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 18 Nov 2019 09:51:30 +0100 Subject: [PATCH 5/5] mod: use tagged version of cert package --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 19dd914bf..8b5dcb79d 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec github.com/lightninglabs/neutrino v0.10.1-0.20191111074637-d9b036bf675c github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a - github.com/lightningnetwork/lnd/cert v0.0.0-00010101000000-000000000000 + github.com/lightningnetwork/lnd/cert v1.0.0 github.com/lightningnetwork/lnd/queue v1.0.1 github.com/lightningnetwork/lnd/ticker v1.0.0 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796