소스 검색

sshd: guard trustedKeys/trustedCAs with a mutex to fix a concurrent map crash on reload (#1787)

Nate Brown 3 달 전
부모
커밋
7bd0bc285a
1개의 변경된 파일과 15개의 추가작업 그리고 0개의 파일을 삭제
  1. 15 0
      sshd/server.go

+ 15 - 0
sshd/server.go

@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"log/slog"
 	"net"
+	"sync"
 
 	"github.com/armon/go-radix"
 	"golang.org/x/crypto/ssh"
@@ -18,6 +19,8 @@ type SSHServer struct {
 
 	certChecker *ssh.CertChecker
 
+	// authLock guards trustedKeys and trustedCAs
+	authLock sync.RWMutex
 	// Map of user -> authorized keys
 	trustedKeys map[string]map[string]bool
 	trustedCAs  []ssh.PublicKey
@@ -45,6 +48,8 @@ func NewSSHServer(ctx context.Context, l *slog.Logger) (*SSHServer, error) {
 
 	cc := ssh.CertChecker{
 		IsUserAuthority: func(auth ssh.PublicKey) bool {
+			s.authLock.RLock()
+			defer s.authLock.RUnlock()
 			for _, ca := range s.trustedCAs {
 				if bytes.Equal(ca.Marshal(), auth.Marshal()) {
 					return true
@@ -57,6 +62,8 @@ func NewSSHServer(ctx context.Context, l *slog.Logger) (*SSHServer, error) {
 			pk := string(pubKey.Marshal())
 			fp := ssh.FingerprintSHA256(pubKey)
 
+			s.authLock.RLock()
+			defer s.authLock.RUnlock()
 			tk, ok := s.trustedKeys[c.User()]
 			if !ok {
 				return nil, fmt.Errorf("unknown user %s", c.User())
@@ -105,11 +112,15 @@ func (s *SSHServer) SetHostKey(hostPrivateKey []byte) error {
 }
 
 func (s *SSHServer) ClearTrustedCAs() {
+	s.authLock.Lock()
 	s.trustedCAs = []ssh.PublicKey{}
+	s.authLock.Unlock()
 }
 
 func (s *SSHServer) ClearAuthorizedKeys() {
+	s.authLock.Lock()
 	s.trustedKeys = make(map[string]map[string]bool)
+	s.authLock.Unlock()
 }
 
 // AddTrustedCA adds a trusted CA for user certificates
@@ -119,7 +130,9 @@ func (s *SSHServer) AddTrustedCA(pubKey string) error {
 		return err
 	}
 
+	s.authLock.Lock()
 	s.trustedCAs = append(s.trustedCAs, pk)
+	s.authLock.Unlock()
 	s.l.Info("Trusted CA key", "sshKey", pubKey)
 	return nil
 }
@@ -131,6 +144,7 @@ func (s *SSHServer) AddAuthorizedKey(user, pubKey string) error {
 		return err
 	}
 
+	s.authLock.Lock()
 	tk, ok := s.trustedKeys[user]
 	if !ok {
 		tk = make(map[string]bool)
@@ -138,6 +152,7 @@ func (s *SSHServer) AddAuthorizedKey(user, pubKey string) error {
 	}
 
 	tk[string(pk.Marshal())] = true
+	s.authLock.Unlock()
 	s.l.Info("Authorized ssh key",
 		"sshKey", pubKey,
 		"sshUser", user,