connection_manager_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. package nebula
  2. import (
  3. "crypto/ed25519"
  4. "crypto/rand"
  5. "net/netip"
  6. "testing"
  7. "time"
  8. "github.com/slackhq/nebula/cert"
  9. "github.com/slackhq/nebula/config"
  10. "github.com/slackhq/nebula/overlay/overlaytest"
  11. "github.com/slackhq/nebula/test"
  12. "github.com/slackhq/nebula/udp"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. )
  16. func newTestLighthouse() *LightHouse {
  17. lh := &LightHouse{
  18. l: test.NewLogger(),
  19. addrMap: map[netip.Addr]*RemoteList{},
  20. queryChan: make(chan netip.Addr, 10),
  21. }
  22. lighthouses := []netip.Addr{}
  23. staticList := map[netip.Addr]struct{}{}
  24. lh.localAddrsFn = func(*LocalAllowList) []netip.Addr { return nil }
  25. lh.lighthouses.Store(&lighthouses)
  26. lh.staticList.Store(&staticList)
  27. return lh
  28. }
  29. func Test_NewConnectionManagerTest(t *testing.T) {
  30. l := test.NewLogger()
  31. //_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
  32. localrange := netip.MustParsePrefix("10.1.1.1/24")
  33. vpnIp := netip.MustParseAddr("172.1.1.2")
  34. preferredRanges := []netip.Prefix{localrange}
  35. // Very incomplete mock objects
  36. hostMap := newHostMap(l)
  37. hostMap.preferredRanges.Store(&preferredRanges)
  38. cs := &CertState{
  39. initiatingVersion: cert.Version1,
  40. privateKey: []byte{},
  41. v1Cert: &dummyCert{version: cert.Version1},
  42. v1Credential: nil,
  43. }
  44. lh := newTestLighthouse()
  45. ifce := &Interface{
  46. hostMap: hostMap,
  47. inside: &overlaytest.NoopTun{},
  48. outside: &udp.NoopConn{},
  49. firewall: &Firewall{},
  50. lightHouse: lh,
  51. pki: &PKI{},
  52. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  53. l: l,
  54. }
  55. ifce.pki.cs.Store(cs)
  56. // Create manager
  57. conf := config.NewC(test.NewLogger())
  58. punchy := NewPunchyFromConfig(test.NewLogger(), conf, nil)
  59. nc := newConnectionManagerFromConfig(test.NewLogger(), conf, hostMap, punchy)
  60. nc.intf = ifce
  61. p := []byte("")
  62. nb := make([]byte, 12, 12)
  63. out := make([]byte, mtu)
  64. // Add an ip we have established a connection w/ to hostmap
  65. hostinfo := &HostInfo{
  66. vpnAddrs: []netip.Addr{vpnIp},
  67. localIndexId: 1099,
  68. remoteIndexId: 9901,
  69. }
  70. hostinfo.ConnectionState = &ConnectionState{
  71. myCert: &dummyCert{version: cert.Version1},
  72. }
  73. nc.hostMap.unlockedAddHostInfo(hostinfo, ifce)
  74. // We saw traffic out to vpnIp
  75. nc.Out(hostinfo)
  76. nc.In(hostinfo)
  77. assert.False(t, hostinfo.isPendingDeletion())
  78. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  79. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  80. assert.True(t, hostinfo.sentSinceCheck())
  81. assert.True(t, (hostinfo.state.Load()&stateIn != 0))
  82. // Do a traffic check tick, should not be pending deletion but should not have any in/out packets recorded
  83. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  84. assert.False(t, hostinfo.isPendingDeletion())
  85. assert.False(t, hostinfo.sentSinceCheck())
  86. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  87. // Do another traffic check tick, this host should be pending deletion now
  88. nc.Out(hostinfo)
  89. assert.True(t, hostinfo.sentSinceCheck())
  90. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  91. assert.True(t, hostinfo.isPendingDeletion())
  92. assert.False(t, hostinfo.sentSinceCheck())
  93. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  94. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  95. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  96. // Do a final traffic check tick, the host should now be removed
  97. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  98. assert.NotContains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs)
  99. assert.NotContains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  100. }
  101. func Test_NewConnectionManagerTest2(t *testing.T) {
  102. l := test.NewLogger()
  103. //_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
  104. localrange := netip.MustParsePrefix("10.1.1.1/24")
  105. vpnIp := netip.MustParseAddr("172.1.1.2")
  106. preferredRanges := []netip.Prefix{localrange}
  107. // Very incomplete mock objects
  108. hostMap := newHostMap(l)
  109. hostMap.preferredRanges.Store(&preferredRanges)
  110. cs := &CertState{
  111. initiatingVersion: cert.Version1,
  112. privateKey: []byte{},
  113. v1Cert: &dummyCert{version: cert.Version1},
  114. v1Credential: nil,
  115. }
  116. lh := newTestLighthouse()
  117. ifce := &Interface{
  118. hostMap: hostMap,
  119. inside: &overlaytest.NoopTun{},
  120. outside: &udp.NoopConn{},
  121. firewall: &Firewall{},
  122. lightHouse: lh,
  123. pki: &PKI{},
  124. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  125. l: l,
  126. }
  127. ifce.pki.cs.Store(cs)
  128. // Create manager
  129. conf := config.NewC(test.NewLogger())
  130. punchy := NewPunchyFromConfig(test.NewLogger(), conf, nil)
  131. nc := newConnectionManagerFromConfig(test.NewLogger(), conf, hostMap, punchy)
  132. nc.intf = ifce
  133. p := []byte("")
  134. nb := make([]byte, 12, 12)
  135. out := make([]byte, mtu)
  136. // Add an ip we have established a connection w/ to hostmap
  137. hostinfo := &HostInfo{
  138. vpnAddrs: []netip.Addr{vpnIp},
  139. localIndexId: 1099,
  140. remoteIndexId: 9901,
  141. }
  142. hostinfo.ConnectionState = &ConnectionState{
  143. myCert: &dummyCert{version: cert.Version1},
  144. }
  145. nc.hostMap.unlockedAddHostInfo(hostinfo, ifce)
  146. // We saw traffic out to vpnIp
  147. nc.Out(hostinfo)
  148. nc.In(hostinfo)
  149. assert.True(t, (hostinfo.state.Load()&stateIn != 0))
  150. assert.True(t, hostinfo.sentSinceCheck())
  151. assert.False(t, hostinfo.isPendingDeletion())
  152. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  153. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  154. // Do a traffic check tick, should not be pending deletion but should not have any in/out packets recorded
  155. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  156. assert.False(t, hostinfo.isPendingDeletion())
  157. assert.False(t, hostinfo.sentSinceCheck())
  158. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  159. // Do another traffic check tick, this host should be pending deletion now
  160. nc.Out(hostinfo)
  161. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  162. assert.True(t, hostinfo.isPendingDeletion())
  163. assert.False(t, hostinfo.sentSinceCheck())
  164. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  165. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  166. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  167. // We saw traffic, should no longer be pending deletion
  168. nc.In(hostinfo)
  169. nc.doTrafficCheck(hostinfo.localIndexId, p, nb, out, time.Now())
  170. assert.False(t, hostinfo.isPendingDeletion())
  171. assert.False(t, hostinfo.sentSinceCheck())
  172. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  173. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  174. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  175. }
  176. func Test_NewConnectionManager_CounterLimits(t *testing.T) {
  177. l := test.NewLogger()
  178. localrange := netip.MustParsePrefix("10.1.1.1/24")
  179. vpnIp := netip.MustParseAddr("172.1.1.2")
  180. preferredRanges := []netip.Prefix{localrange}
  181. // Very incomplete mock objects
  182. hostMap := newHostMap(l)
  183. hostMap.preferredRanges.Store(&preferredRanges)
  184. cs := &CertState{
  185. initiatingVersion: cert.Version1,
  186. privateKey: []byte{},
  187. v1Cert: &dummyCert{version: cert.Version1},
  188. v1Credential: nil,
  189. }
  190. lh := newTestLighthouse()
  191. ifce := &Interface{
  192. hostMap: hostMap,
  193. inside: &overlaytest.NoopTun{},
  194. outside: &udp.NoopConn{},
  195. firewall: &Firewall{},
  196. lightHouse: lh,
  197. pki: &PKI{},
  198. myVpnAddrs: []netip.Addr{netip.MustParseAddr("172.1.1.1")}, // sorts below vpnIp so shouldSwapPrimary can proceed
  199. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  200. l: l,
  201. }
  202. ifce.pki.cs.Store(cs)
  203. conf := config.NewC(test.NewLogger())
  204. punchy := NewPunchyFromConfig(test.NewLogger(), conf, nil)
  205. nc := newConnectionManagerFromConfig(test.NewLogger(), conf, hostMap, punchy)
  206. nc.intf = ifce
  207. hostinfo := &HostInfo{
  208. vpnAddrs: []netip.Addr{vpnIp},
  209. localIndexId: 1099,
  210. remoteIndexId: 9901,
  211. }
  212. hostinfo.ConnectionState = &ConnectionState{
  213. myCert: &dummyCert{version: cert.Version1},
  214. }
  215. nc.hostMap.unlockedAddHostInfo(hostinfo, ifce)
  216. // Below the rehandshake threshold, no handshake is started
  217. hostinfo.ConnectionState.messageCounter.Store(RehandshakeAfterMessages - 1)
  218. nc.tryRehandshake(hostinfo)
  219. assert.Nil(t, ifce.handshakeManager.QueryVpnAddr(vpnIp))
  220. // A tunnel on its current cert would normally swap to primary
  221. assert.True(t, nc.shouldSwapPrimary(hostinfo))
  222. // At the rehandshake threshold, a new handshake is started
  223. hostinfo.ConnectionState.messageCounter.Store(RehandshakeAfterMessages)
  224. nc.tryRehandshake(hostinfo)
  225. assert.NotNil(t, ifce.handshakeManager.QueryVpnAddr(vpnIp))
  226. // An exhausted tunnel being rolled must never swap back to primary onto its spent key
  227. assert.False(t, nc.shouldSwapPrimary(hostinfo))
  228. // Still below the reject limit, the tunnel stays up
  229. nc.In(hostinfo)
  230. decision, _, _ := nc.makeTrafficDecision(hostinfo.localIndexId, time.Now())
  231. assert.Equal(t, tryRehandshake, decision)
  232. // At the reject limit, the tunnel is deleted locally without a doomed CloseTunnel notify
  233. hostinfo.ConnectionState.messageCounter.Store(RejectAfterMessages)
  234. decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, time.Now())
  235. assert.Equal(t, deleteTunnel, decision)
  236. }
  237. func Test_NewConnectionManager_DisconnectInactive(t *testing.T) {
  238. l := test.NewLogger()
  239. localrange := netip.MustParsePrefix("10.1.1.1/24")
  240. vpnAddrs := []netip.Addr{netip.MustParseAddr("172.1.1.2")}
  241. preferredRanges := []netip.Prefix{localrange}
  242. // Very incomplete mock objects
  243. hostMap := newHostMap(l)
  244. hostMap.preferredRanges.Store(&preferredRanges)
  245. cs := &CertState{
  246. initiatingVersion: cert.Version1,
  247. privateKey: []byte{},
  248. v1Cert: &dummyCert{version: cert.Version1},
  249. v1Credential: nil,
  250. }
  251. lh := newTestLighthouse()
  252. ifce := &Interface{
  253. hostMap: hostMap,
  254. inside: &overlaytest.NoopTun{},
  255. outside: &udp.NoopConn{},
  256. firewall: &Firewall{},
  257. lightHouse: lh,
  258. pki: &PKI{},
  259. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  260. l: l,
  261. }
  262. ifce.pki.cs.Store(cs)
  263. // Create manager
  264. conf := config.NewC(test.NewLogger())
  265. conf.Settings["tunnels"] = map[string]any{
  266. "drop_inactive": true,
  267. }
  268. punchy := NewPunchyFromConfig(test.NewLogger(), conf, nil)
  269. nc := newConnectionManagerFromConfig(test.NewLogger(), conf, hostMap, punchy)
  270. assert.True(t, nc.dropInactive.Load())
  271. nc.intf = ifce
  272. // Add an ip we have established a connection w/ to hostmap
  273. hostinfo := &HostInfo{
  274. vpnAddrs: vpnAddrs,
  275. localIndexId: 1099,
  276. remoteIndexId: 9901,
  277. }
  278. hostinfo.ConnectionState = &ConnectionState{
  279. myCert: &dummyCert{version: cert.Version1},
  280. }
  281. nc.hostMap.unlockedAddHostInfo(hostinfo, ifce)
  282. // Do a traffic check tick, in and out should be cleared but should not be pending deletion
  283. nc.Out(hostinfo)
  284. nc.In(hostinfo)
  285. assert.True(t, hostinfo.sentSinceCheck())
  286. assert.True(t, (hostinfo.state.Load()&stateIn != 0))
  287. now := time.Now()
  288. decision, _, _ := nc.makeTrafficDecision(hostinfo.localIndexId, now)
  289. assert.Equal(t, tryRehandshake, decision)
  290. assert.Equal(t, now, hostinfo.lastUsed)
  291. assert.False(t, hostinfo.isPendingDeletion())
  292. assert.False(t, hostinfo.sentSinceCheck())
  293. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  294. decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Second*5))
  295. assert.Equal(t, doNothing, decision)
  296. assert.Equal(t, now, hostinfo.lastUsed)
  297. assert.False(t, hostinfo.isPendingDeletion())
  298. assert.False(t, hostinfo.sentSinceCheck())
  299. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  300. // Do another traffic check tick, should still not be pending deletion
  301. decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Second*10))
  302. assert.Equal(t, doNothing, decision)
  303. assert.Equal(t, now, hostinfo.lastUsed)
  304. assert.False(t, hostinfo.isPendingDeletion())
  305. assert.False(t, hostinfo.sentSinceCheck())
  306. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  307. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  308. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  309. // Finally advance beyond the inactivity timeout
  310. decision, _, _ = nc.makeTrafficDecision(hostinfo.localIndexId, now.Add(time.Minute*10))
  311. assert.Equal(t, closeTunnel, decision)
  312. assert.Equal(t, now, hostinfo.lastUsed)
  313. assert.False(t, hostinfo.isPendingDeletion())
  314. assert.False(t, hostinfo.sentSinceCheck())
  315. assert.False(t, (hostinfo.state.Load()&stateIn != 0))
  316. assert.Contains(t, nc.hostMap.Indexes, hostinfo.localIndexId)
  317. assert.Contains(t, nc.hostMap.Hosts, hostinfo.vpnAddrs[0])
  318. }
  319. // Check if we can disconnect the peer.
  320. // Validate if the peer's certificate is invalid (expired, etc.)
  321. // Disconnect only if disconnectInvalid: true is set.
  322. func Test_NewConnectionManagerTest_DisconnectInvalid(t *testing.T) {
  323. now := time.Now()
  324. l := test.NewLogger()
  325. vpncidr := netip.MustParsePrefix("172.1.1.1/24")
  326. localrange := netip.MustParsePrefix("10.1.1.1/24")
  327. vpnIp := netip.MustParseAddr("172.1.1.2")
  328. preferredRanges := []netip.Prefix{localrange}
  329. hostMap := newHostMap(l)
  330. hostMap.preferredRanges.Store(&preferredRanges)
  331. // Generate keys for CA and peer's cert.
  332. pubCA, privCA, _ := ed25519.GenerateKey(rand.Reader)
  333. tbs := &cert.TBSCertificate{
  334. Version: 1,
  335. Name: "ca",
  336. IsCA: true,
  337. NotBefore: now,
  338. NotAfter: now.Add(1 * time.Hour),
  339. PublicKey: pubCA,
  340. }
  341. caCert, err := tbs.Sign(nil, cert.Curve_CURVE25519, privCA)
  342. require.NoError(t, err)
  343. ncp := cert.NewCAPool()
  344. require.NoError(t, ncp.AddCA(caCert))
  345. pubCrt, _, _ := ed25519.GenerateKey(rand.Reader)
  346. tbs = &cert.TBSCertificate{
  347. Version: 1,
  348. Name: "host",
  349. Networks: []netip.Prefix{vpncidr},
  350. NotBefore: now,
  351. NotAfter: now.Add(60 * time.Second),
  352. PublicKey: pubCrt,
  353. }
  354. peerCert, err := tbs.Sign(caCert, cert.Curve_CURVE25519, privCA)
  355. require.NoError(t, err)
  356. cachedPeerCert, err := ncp.VerifyCertificate(now.Add(time.Second), peerCert)
  357. cs := &CertState{
  358. privateKey: []byte{},
  359. v1Cert: &dummyCert{},
  360. v1Credential: nil,
  361. }
  362. lh := newTestLighthouse()
  363. ifce := &Interface{
  364. hostMap: hostMap,
  365. inside: &overlaytest.NoopTun{},
  366. outside: &udp.NoopConn{},
  367. firewall: &Firewall{},
  368. lightHouse: lh,
  369. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  370. l: l,
  371. pki: &PKI{},
  372. }
  373. ifce.pki.cs.Store(cs)
  374. ifce.pki.caPool.Store(ncp)
  375. ifce.disconnectInvalid.Store(true)
  376. // Create manager
  377. conf := config.NewC(test.NewLogger())
  378. punchy := NewPunchyFromConfig(test.NewLogger(), conf, nil)
  379. nc := newConnectionManagerFromConfig(test.NewLogger(), conf, hostMap, punchy)
  380. nc.intf = ifce
  381. ifce.connectionManager = nc
  382. hostinfo := &HostInfo{
  383. vpnAddrs: []netip.Addr{vpnIp},
  384. ConnectionState: &ConnectionState{
  385. myCert: &dummyCert{},
  386. peerCert: cachedPeerCert,
  387. },
  388. }
  389. nc.hostMap.unlockedAddHostInfo(hostinfo, ifce)
  390. // Move ahead 45s.
  391. // Check if to disconnect with invalid certificate.
  392. // Should be alive.
  393. nextTick := now.Add(45 * time.Second)
  394. invalid := nc.isInvalidCertificate(nextTick, hostinfo)
  395. assert.False(t, invalid)
  396. // Move ahead 61s.
  397. // Check if to disconnect with invalid certificate.
  398. // Should be disconnected.
  399. nextTick = now.Add(61 * time.Second)
  400. invalid = nc.isInvalidCertificate(nextTick, hostinfo)
  401. assert.True(t, invalid)
  402. }
  403. type dummyCert struct {
  404. version cert.Version
  405. curve cert.Curve
  406. groups []string
  407. isCa bool
  408. issuer string
  409. name string
  410. networks []netip.Prefix
  411. notAfter time.Time
  412. notBefore time.Time
  413. publicKey []byte
  414. signature []byte
  415. unsafeNetworks []netip.Prefix
  416. }
  417. func (d *dummyCert) Version() cert.Version {
  418. return d.version
  419. }
  420. func (d *dummyCert) Curve() cert.Curve {
  421. return d.curve
  422. }
  423. func (d *dummyCert) Groups() []string {
  424. return d.groups
  425. }
  426. func (d *dummyCert) IsCA() bool {
  427. return d.isCa
  428. }
  429. func (d *dummyCert) Issuer() string {
  430. return d.issuer
  431. }
  432. func (d *dummyCert) Name() string {
  433. return d.name
  434. }
  435. func (d *dummyCert) Networks() []netip.Prefix {
  436. return d.networks
  437. }
  438. func (d *dummyCert) NotAfter() time.Time {
  439. return d.notAfter
  440. }
  441. func (d *dummyCert) NotBefore() time.Time {
  442. return d.notBefore
  443. }
  444. func (d *dummyCert) PublicKey() []byte {
  445. return d.publicKey
  446. }
  447. func (d *dummyCert) MarshalPublicKeyPEM() []byte {
  448. return cert.MarshalPublicKeyToPEM(d.curve, d.publicKey)
  449. }
  450. func (d *dummyCert) Signature() []byte {
  451. return d.signature
  452. }
  453. func (d *dummyCert) UnsafeNetworks() []netip.Prefix {
  454. return d.unsafeNetworks
  455. }
  456. func (d *dummyCert) MarshalForHandshakes() ([]byte, error) {
  457. return nil, nil
  458. }
  459. func (d *dummyCert) Sign(curve cert.Curve, key []byte) error {
  460. return nil
  461. }
  462. func (d *dummyCert) CheckSignature(key []byte) bool {
  463. return true
  464. }
  465. func (d *dummyCert) Expired(t time.Time) bool {
  466. return false
  467. }
  468. func (d *dummyCert) CheckRootConstraints(signer cert.Certificate) error {
  469. return nil
  470. }
  471. func (d *dummyCert) VerifyPrivateKey(curve cert.Curve, key []byte) error {
  472. return nil
  473. }
  474. func (d *dummyCert) String() string {
  475. return ""
  476. }
  477. func (d *dummyCert) Marshal() ([]byte, error) {
  478. return nil, nil
  479. }
  480. func (d *dummyCert) MarshalPEM() ([]byte, error) {
  481. return nil, nil
  482. }
  483. func (d *dummyCert) Fingerprint() (string, error) {
  484. return "", nil
  485. }
  486. func (d *dummyCert) MarshalJSON() ([]byte, error) {
  487. return nil, nil
  488. }
  489. func (d *dummyCert) Copy() cert.Certificate {
  490. return d
  491. }