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 }