mirror of
https://github.com/fosrl/newt.git
synced 2026-07-24 00:21:27 +02:00
Keep host key in memory
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user