github.com/decred/dcrlnd@v0.7.6/server_test.go (about)

     1  //go:build !rpctest
     2  // +build !rpctest
     3  
     4  package dcrlnd
     5  
     6  import (
     7  	"bytes"
     8  	"crypto/ecdsa"
     9  	"crypto/elliptic"
    10  	"crypto/rand"
    11  	"crypto/tls"
    12  	"crypto/x509"
    13  	"crypto/x509/pkix"
    14  	"encoding/pem"
    15  	"io/ioutil"
    16  	"math/big"
    17  	"net"
    18  	"os"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/decred/dcrlnd/lncfg"
    23  )
    24  
    25  func TestParseHexColor(t *testing.T) {
    26  	var colorTestCases = []struct {
    27  		test  string
    28  		valid bool // If valid format
    29  		R     byte
    30  		G     byte
    31  		B     byte
    32  	}{
    33  		{"#123", false, 0, 0, 0},
    34  		{"#1234567", false, 0, 0, 0},
    35  		{"$123456", false, 0, 0, 0},
    36  		{"#12345+", false, 0, 0, 0},
    37  		{"#fFGG00", false, 0, 0, 0},
    38  		{"", false, 0, 0, 0},
    39  		{"#123456", true, 0x12, 0x34, 0x56},
    40  		{"#C0FfeE", true, 0xc0, 0xff, 0xee},
    41  	}
    42  
    43  	// Perform the table driven tests.
    44  	for _, ct := range colorTestCases {
    45  
    46  		color, err := parseHexColor(ct.test)
    47  		if !ct.valid && err == nil {
    48  			t.Fatalf("Invalid color string: %s, should return "+
    49  				"error, but did not", ct.test)
    50  		}
    51  
    52  		if ct.valid && err != nil {
    53  			t.Fatalf("Color %s valid to parse: %s", ct.test, err)
    54  		}
    55  
    56  		// Ensure that the string to hex decoding is working properly.
    57  		if color.R != ct.R || color.G != ct.G || color.B != ct.B {
    58  			t.Fatalf("Color %s incorrectly parsed as %v", ct.test, color)
    59  		}
    60  	}
    61  }
    62  
    63  // TestTLSAutoRegeneration creates an expired TLS certificate, to test that a
    64  // new TLS certificate pair is regenerated when the old pair expires. This is
    65  // necessary because the pair expires after a little over a year.
    66  func TestTLSAutoRegeneration(t *testing.T) {
    67  	tempDirPath, err := ioutil.TempDir("", ".testLnd")
    68  	if err != nil {
    69  		t.Fatalf("couldn't create temporary cert directory")
    70  	}
    71  	defer os.RemoveAll(tempDirPath)
    72  
    73  	certPath := tempDirPath + "/tls.cert"
    74  	keyPath := tempDirPath + "/tls.key"
    75  
    76  	certDerBytes, keyBytes := genExpiredCertPair(t, tempDirPath)
    77  	expiredCert, err := x509.ParseCertificate(certDerBytes)
    78  	if err != nil {
    79  		t.Fatalf("failed to parse certificate: %v", err)
    80  	}
    81  
    82  	certBuf := bytes.Buffer{}
    83  	err = pem.Encode(
    84  		&certBuf, &pem.Block{
    85  			Type:  "CERTIFICATE",
    86  			Bytes: certDerBytes,
    87  		},
    88  	)
    89  	if err != nil {
    90  		t.Fatalf("failed to encode certificate: %v", err)
    91  	}
    92  
    93  	keyBuf := bytes.Buffer{}
    94  	err = pem.Encode(
    95  		&keyBuf, &pem.Block{
    96  			Type:  "EC PRIVATE KEY",
    97  			Bytes: keyBytes,
    98  		},
    99  	)
   100  	if err != nil {
   101  		t.Fatalf("failed to encode private key: %v", err)
   102  	}
   103  
   104  	// Write cert and key files.
   105  	err = ioutil.WriteFile(tempDirPath+"/tls.cert", certBuf.Bytes(), 0644)
   106  	if err != nil {
   107  		t.Fatalf("failed to write cert file: %v", err)
   108  	}
   109  	err = ioutil.WriteFile(tempDirPath+"/tls.key", keyBuf.Bytes(), 0600)
   110  	if err != nil {
   111  		t.Fatalf("failed to write key file: %v", err)
   112  	}
   113  
   114  	rpcListener := net.IPAddr{IP: net.ParseIP("127.0.0.1"), Zone: ""}
   115  	rpcListeners := make([]net.Addr, 0)
   116  	rpcListeners = append(rpcListeners, &rpcListener)
   117  
   118  	// Now let's run getTLSConfig. If it works properly, it should delete
   119  	// the cert and create a new one.
   120  	cfg := &Config{
   121  		TLSCertPath:     certPath,
   122  		TLSKeyPath:      keyPath,
   123  		TLSCertDuration: 42 * time.Hour,
   124  		RPCListeners:    rpcListeners,
   125  	}
   126  	_, _, _, cleanUp, err := getTLSConfig(cfg)
   127  	if err != nil {
   128  		t.Fatalf("couldn't retrieve TLS config")
   129  	}
   130  	defer cleanUp()
   131  
   132  	// Grab the certificate to test that getTLSConfig did its job correctly
   133  	// and generated a new cert.
   134  	newCertData, err := tls.LoadX509KeyPair(certPath, keyPath)
   135  	if err != nil {
   136  		t.Fatalf("couldn't grab new certificate")
   137  	}
   138  
   139  	newCert, err := x509.ParseCertificate(newCertData.Certificate[0])
   140  	if err != nil {
   141  		t.Fatalf("couldn't parse new certificate")
   142  	}
   143  
   144  	// Check that the expired certificate was successfully deleted and
   145  	// replaced with a new one.
   146  	if !newCert.NotAfter.After(expiredCert.NotAfter) {
   147  		t.Fatalf("New certificate expiration is too old")
   148  	}
   149  }
   150  
   151  // genExpiredCertPair generates an expired key/cert pair to test that expired
   152  // certificates are being regenerated correctly.
   153  func genExpiredCertPair(t *testing.T, certDirPath string) ([]byte, []byte) {
   154  	// Max serial number.
   155  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
   156  
   157  	// Generate a serial number that's below the serialNumberLimit.
   158  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
   159  	if err != nil {
   160  		t.Fatalf("failed to generate serial number: %s", err)
   161  	}
   162  
   163  	host := "lightning"
   164  
   165  	// Create a simple ip address for the fake certificate.
   166  	ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}
   167  
   168  	dnsNames := []string{host, "unix", "unixpacket"}
   169  
   170  	// Construct the certificate template.
   171  	template := x509.Certificate{
   172  		SerialNumber: serialNumber,
   173  		Subject: pkix.Name{
   174  			Organization: []string{"lnd autogenerated cert"},
   175  			CommonName:   host,
   176  		},
   177  		NotBefore: time.Now().Add(-time.Hour * 24),
   178  		NotAfter:  time.Now(),
   179  
   180  		KeyUsage: x509.KeyUsageKeyEncipherment |
   181  			x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   182  		IsCA:                  true, // so can sign self.
   183  		BasicConstraintsValid: true,
   184  
   185  		DNSNames:    dnsNames,
   186  		IPAddresses: ipAddresses,
   187  	}
   188  
   189  	// Generate a private key for the certificate.
   190  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   191  	if err != nil {
   192  		t.Fatalf("failed to generate a private key")
   193  	}
   194  
   195  	certDerBytes, err := x509.CreateCertificate(
   196  		rand.Reader, &template, &template, &priv.PublicKey, priv,
   197  	)
   198  	if err != nil {
   199  		t.Fatalf("failed to create certificate: %v", err)
   200  	}
   201  
   202  	keyBytes, err := x509.MarshalECPrivateKey(priv)
   203  	if err != nil {
   204  		t.Fatalf("unable to encode privkey: %v", err)
   205  	}
   206  
   207  	return certDerBytes, keyBytes
   208  }
   209  
   210  // TestShouldPeerBootstrap tests that we properly skip network bootstrap for
   211  // the developer networks, and also if bootstrapping is explicitly disabled.
   212  func TestShouldPeerBootstrap(t *testing.T) {
   213  	t.Parallel()
   214  
   215  	testCases := []struct {
   216  		cfg            *Config
   217  		shouldBoostrap bool
   218  	}{
   219  		// Simnet active, no bootstrap.
   220  		{
   221  			cfg: &Config{
   222  				Decred: &lncfg.Chain{
   223  					SimNet: true,
   224  				},
   225  			},
   226  		},
   227  
   228  		// Regtest active, no bootstrap.
   229  		{
   230  			cfg: &Config{
   231  				Decred: &lncfg.Chain{
   232  					RegTest: true,
   233  				},
   234  			},
   235  		},
   236  
   237  		// Mainnet active, but boostrap disabled, no boostrap.
   238  		{
   239  			cfg: &Config{
   240  				Decred:         &lncfg.Chain{},
   241  				NoNetBootstrap: true,
   242  			},
   243  		},
   244  
   245  		// Mainnet active, should boostrap.
   246  		{
   247  			cfg: &Config{
   248  				Decred: &lncfg.Chain{},
   249  			},
   250  			shouldBoostrap: true,
   251  		},
   252  
   253  		// Testnet active, should boostrap.
   254  		{
   255  			cfg: &Config{
   256  				Decred: &lncfg.Chain{
   257  					TestNet3: true,
   258  				},
   259  			},
   260  			shouldBoostrap: true,
   261  		},
   262  	}
   263  	for i, testCase := range testCases {
   264  		bootstrapped := shouldPeerBootstrap(testCase.cfg)
   265  		if bootstrapped != testCase.shouldBoostrap {
   266  			t.Fatalf("#%v: expected bootstrap=%v, got bootstrap=%v",
   267  				i, testCase.shouldBoostrap, bootstrapped)
   268  		}
   269  	}
   270  }