From d1b1bf6cbdf5582d837aaf33ee2679d657a35be8 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 9 Jan 2025 05:37:08 -0800 Subject: [PATCH] add crash protection for GetAllCertificates --- certs/certs_test.go | 17 +++++++++++++++++ certs/manager.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/certs/certs_test.go b/certs/certs_test.go index b6bf4f4..3e03da4 100644 --- a/certs/certs_test.go +++ b/certs/certs_test.go @@ -67,6 +67,23 @@ func TestNewManager(t *testing.T) { if err == nil { t.Fatal("Expected to fail but got success") } + + allCerts := c.GetAllCertificates() + var found bool + for _, cert := range allCerts { + if cert.Issuer.String() != "CN=minio.io,OU=Engineering,O=Minio,L=Redwood City,ST=CA,C=US" { + t.Error("Unexpected cert issuer found") + } + found = true + } + if !found { + t.Error("atleast one public cert is expected") + } + + var nilMgr *certs.Manager + if len(nilMgr.GetAllCertificates()) != 0 { + t.Error("no public cert is expected") + } } func TestValidPairAfterWrite(t *testing.T) { diff --git a/certs/manager.go b/certs/manager.go index b4be333..bef7b7d 100644 --- a/certs/manager.go +++ b/certs/manager.go @@ -96,6 +96,10 @@ func NewManager(ctx context.Context, certFile, keyFile string, loadX509KeyPair L // UpdateReloadDuration set custom symlink reload duration func (m *Manager) UpdateReloadDuration(t time.Duration) { + if m == nil { + return + } + m.lock.Lock() m.duration = t m.lock.Unlock() @@ -107,6 +111,10 @@ func (m *Manager) UpdateReloadDuration(t time.Duration) { // If there is already a certificate with the same base name it will be // replaced by the newly added one. func (m *Manager) AddCertificate(certFile, keyFile string) (err error) { + if m == nil { + return nil + } + certFile, err = filepath.Abs(certFile) if err != nil { return err @@ -194,6 +202,10 @@ func (m *Manager) reloader() <-chan struct{} { // ReloadOnSignal specifies one or more signals that will trigger certificates reloading. // If called multiple times with the same signal certificates func (m *Manager) ReloadOnSignal(sig ...os.Signal) { + if m == nil { + return + } + if len(sig) == 0 { return } @@ -214,6 +226,10 @@ func (m *Manager) ReloadOnSignal(sig ...os.Signal) { // ReloadCerts will forcefully reload all certs. func (m *Manager) ReloadCerts() { + if m == nil { + return + } + m.lock.RLock() defer m.lock.RUnlock() for _, ch := range m.reloadCerts { @@ -228,6 +244,10 @@ func (m *Manager) ReloadCerts() { // watchSymlinks starts an endless loop reloading the // certFile and keyFile periodically. func (m *Manager) watchSymlinks(watch pair, reload <-chan struct{}) { + if m == nil { + return + } + t := time.NewTimer(m.duration) defer t.Stop() @@ -263,6 +283,10 @@ func (m *Manager) watchSymlinks(watch pair, reload <-chan struct{}) { // Once an event occurs it reloads the private key and certificate that // has changed, if any. func (m *Manager) watchFileEvents(watch pair, events chan notify.EventInfo, reload <-chan struct{}) { + if m == nil { + return + } + for { select { case <-m.done: @@ -301,6 +325,10 @@ func (m *Manager) watchFileEvents(watch pair, events chan notify.EventInfo, relo // found GetCertificate returns the certificate loaded from the // Public file. func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + if m == nil { + return nil, errors.New("certs: no server certificate is supported by peer") + } + m.lock.RLock() defer m.lock.RUnlock() @@ -368,6 +396,10 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, // found GetClientCertificate returns the certificate loaded from the // Public file. func (m *Manager) GetClientCertificate(reqInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) { + if m == nil { + return nil, errors.New("certs: no client certificate is supported by peer") + } + m.lock.RLock() defer m.lock.RUnlock() @@ -406,6 +438,10 @@ func isSymlink(file string) (bool, error) { // GetAllCertificates returns all the certificates loaded func (m *Manager) GetAllCertificates() []*x509.Certificate { + if m == nil { + return nil + } + m.lock.RLock() defer m.lock.RUnlock()