diff --git a/nativessh/server.go b/nativessh/server.go index 8cedf94..0e5cbe9 100644 --- a/nativessh/server.go +++ b/nativessh/server.go @@ -4,7 +4,6 @@ import ( "bufio" "crypto/ed25519" "crypto/rand" - "encoding/pem" "fmt" "io" "log" @@ -22,9 +21,6 @@ const ( // DefaultPrincipalsPath is the path to a file listing allowed SSH // certificate principals, one per line. DefaultPrincipalsPath = "/tmp/newt/ssh_principals" - // DefaultHostKeyPath is where the server's Ed25519 host key is persisted. - // A new key is generated and saved here on first run. - DefaultHostKeyPath = "/tmp/newt/ssh_host_key" ) // ServerConfig holds configuration for the native SSH server. @@ -37,11 +33,6 @@ type ServerConfig struct { // PrincipalsPath is the path to a file of allowed principals, one per line. // Defaults to DefaultPrincipalsPath. PrincipalsPath string - // HostKeyPath is where the Ed25519 host private key is stored (PEM). - // Defaults to DefaultHostKeyPath. Generated on first run if absent. - HostKeyPath string - // Shell is the shell executable to spawn. Defaults to /bin/sh. - Shell string } // Server is a simple SSH server that authenticates clients via SSH certificate @@ -64,12 +55,6 @@ func NewServer(cfg ServerConfig) *Server { if cfg.PrincipalsPath == "" { cfg.PrincipalsPath = DefaultPrincipalsPath } - if cfg.HostKeyPath == "" { - cfg.HostKeyPath = DefaultHostKeyPath - } - if cfg.Shell == "" { - cfg.Shell = "/bin/sh" - } return &Server{cfg: cfg} } @@ -85,7 +70,7 @@ func (s *Server) ListenAndServe() error { return fmt.Errorf("load principals from %s: %w", s.cfg.PrincipalsPath, err) } - hostSigner, err := generateOrLoadHostKey(s.cfg.HostKeyPath) + hostSigner, err := generateHostKey() if err != nil { return fmt.Errorf("host key: %w", err) } @@ -152,7 +137,7 @@ func (s *Server) handleSession(ch ssh.Channel, requests <-chan *ssh.Request) { case "pty-req": var err error if sess == nil { - sess, err = NewPTYSession(s.cfg.Shell) + sess, err = NewPTYSession() if err != nil { log.Printf("nativessh: PTY start error: %v", err) if req.WantReply { @@ -230,30 +215,14 @@ func makeCertAuthCallback(caKey ssh.PublicKey, allowedPrincipals map[string]stru } } -// generateOrLoadHostKey loads an Ed25519 host key from path, or generates and -// saves a new one if the file does not exist. -func generateOrLoadHostKey(path string) (ssh.Signer, error) { - data, err := os.ReadFile(path) - if err == nil { - return ssh.ParsePrivateKey(data) - } - if !os.IsNotExist(err) { - return nil, fmt.Errorf("read host key %s: %w", path, err) - } - +// generateHostKey generates a fresh ephemeral Ed25519 host key in memory. +// A new key is created on every server start; nothing is written to disk. +func generateHostKey() (ssh.Signer, error) { _, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, fmt.Errorf("generate host key: %w", err) } - pemBlock, err := ssh.MarshalPrivateKey(priv, "") - if err != nil { - return nil, fmt.Errorf("marshal host key: %w", err) - } - pemData := pem.EncodeToMemory(pemBlock) - if writeErr := os.WriteFile(path, pemData, 0600); writeErr != nil { - log.Printf("nativessh: warning: could not persist host key to %s: %v", path, writeErr) - } - log.Printf("nativessh: generated new Ed25519 host key (saved to %s)", path) + log.Printf("nativessh: generated ephemeral Ed25519 host key") return ssh.NewSignerFromKey(priv) }