From 6fc2dfe5a9a750262005382d2f2d047f1956b199 Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 25 Nov 2024 11:02:47 -0500 Subject: [PATCH] do not panic when loading a V2 CA certificate, but don't try to use it either --- cert/ca.go | 6 ++++++ cert/cert.go | 4 ++++ cert/cert_test.go | 12 ++++++++++++ cert/errors.go | 13 +++++++------ pki.go | 2 ++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cert/ca.go b/cert/ca.go index 0ffbd8792..331bd65df 100644 --- a/cert/ca.go +++ b/cert/ca.go @@ -30,11 +30,15 @@ func NewCAPoolFromBytes(caPEMs []byte) (*NebulaCAPool, error) { pool := NewCAPool() var err error var expired bool + var caTooNew bool for { caPEMs, err = pool.AddCACertificate(caPEMs) if errors.Is(err, ErrExpired) { expired = true err = nil + } else if errors.Is(err, ErrInvalidPEMCertificateUnsupported) { + caTooNew = true + err = nil } if err != nil { return nil, err @@ -46,6 +50,8 @@ func NewCAPoolFromBytes(caPEMs []byte) (*NebulaCAPool, error) { if expired { return pool, ErrExpired + } else if caTooNew { + return pool, ErrInvalidPEMCertificateUnsupported } return pool, nil diff --git a/cert/cert.go b/cert/cert.go index a0164f7bc..8d90ffe60 100644 --- a/cert/cert.go +++ b/cert/cert.go @@ -28,6 +28,7 @@ const publicKeyLen = 32 const ( CertBanner = "NEBULA CERTIFICATE" + CertificateV2Banner = "NEBULA CERTIFICATE V2" X25519PrivateKeyBanner = "NEBULA X25519 PRIVATE KEY" X25519PublicKeyBanner = "NEBULA X25519 PUBLIC KEY" EncryptedEd25519PrivateKeyBanner = "NEBULA ED25519 ENCRYPTED PRIVATE KEY" @@ -163,6 +164,9 @@ func UnmarshalNebulaCertificateFromPEM(b []byte) (*NebulaCertificate, []byte, er if p == nil { return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block") } + if p.Type == CertificateV2Banner { + return nil, r, ErrInvalidPEMCertificateUnsupported + } if p.Type != CertBanner { return nil, r, fmt.Errorf("bytes did not contain a proper nebula certificate banner") } diff --git a/cert/cert_test.go b/cert/cert_test.go index 30e99eca1..b316e7447 100644 --- a/cert/cert_test.go +++ b/cert/cert_test.go @@ -572,6 +572,13 @@ CmYKEG5lYnVsYSBQMjU2IHRlc3Qo4s+7mgYw4tXrsAc6QQRkaW2jFmllYvN4+/k2 76gvQAGgBgESRzBFAiEAib0/te6eMiZOKD8gdDeloMTS0wGuX2t0C7TFdUhAQzgC IBNWYMep3ysx9zCgknfG5dKtwGTaqF++BWKDYdyl34KX -----END NEBULA CERTIFICATE----- +` + + v2 := ` +# valid PEM with the V2 header +-----BEGIN NEBULA CERTIFICATE V2----- +CmYKEG5lYnVsYSBQMjU2IHRlc3Qo4s+7mgYw4tXrsAc6QQRkaW2jFmllYvN4+/k2 +-----END NEBULA CERTIFICATE V2----- ` rootCA := NebulaCertificate{ @@ -619,6 +626,11 @@ IBNWYMep3ysx9zCgknfG5dKtwGTaqF++BWKDYdyl34KX assert.Nil(t, err) assert.Equal(t, ppppp.CAs[string("a7938893ec8c4ef769b06d7f425e5e46f7a7f5ffa49c3bcf4a86b608caba9159")].Details.Name, rootCAP256.Details.Name) assert.Equal(t, len(ppppp.CAs), 1) + + pppppp, err := NewCAPoolFromBytes(append([]byte(p256), []byte(v2)...)) + assert.Equal(t, err, ErrInvalidPEMCertificateUnsupported) + assert.Equal(t, pppppp.CAs[string("a7938893ec8c4ef769b06d7f425e5e46f7a7f5ffa49c3bcf4a86b608caba9159")].Details.Name, rootCAP256.Details.Name) + assert.Equal(t, len(pppppp.CAs), 1) } func appendByteSlices(b ...[]byte) []byte { diff --git a/cert/errors.go b/cert/errors.go index 05b42d10c..df2dd4e59 100644 --- a/cert/errors.go +++ b/cert/errors.go @@ -5,10 +5,11 @@ import ( ) var ( - ErrRootExpired = errors.New("root certificate is expired") - ErrExpired = errors.New("certificate is expired") - ErrNotCA = errors.New("certificate is not a CA") - ErrNotSelfSigned = errors.New("certificate is not self-signed") - ErrBlockListed = errors.New("certificate is in the block list") - ErrSignatureMismatch = errors.New("certificate signature did not match") + ErrRootExpired = errors.New("root certificate is expired") + ErrExpired = errors.New("certificate is expired") + ErrNotCA = errors.New("certificate is not a CA") + ErrNotSelfSigned = errors.New("certificate is not self-signed") + ErrBlockListed = errors.New("certificate is in the block list") + ErrSignatureMismatch = errors.New("certificate signature did not match") + ErrInvalidPEMCertificateUnsupported = errors.New("bytes contain an unsupported certificate format") ) diff --git a/pki.go b/pki.go index ab95a0477..e3fd5e0c2 100644 --- a/pki.go +++ b/pki.go @@ -237,6 +237,8 @@ func loadCAPoolFromConfig(l *logrus.Logger, c *config.C) (*cert.NebulaCAPool, er return nil, errors.New("no valid CA certificates present") } + } else if errors.Is(err, cert.ErrInvalidPEMCertificateUnsupported) { + l.WithError(err).Warn("At least one configured CA is unsupported by this version of nebula. It has been ignored.") } else if err != nil { return nil, fmt.Errorf("error while adding CA certificate to CA trust store: %s", err) }