all repos — flounder @ dff2f1903d9d0f3b83c67388342900af013cbc5f

A small site builder for the Gemini protocol

Automatically generate ssh host keys
alex wennerberg alex@alexwennerberg.com
Sat, 27 Feb 2021 07:23:55 -0800
commit

dff2f1903d9d0f3b83c67388342900af013cbc5f

parent

deb0c5ae2a24efdbaa79345b0fbddfd3ad74e972

3 files changed, 47 insertions(+), 1 deletions(-)

jump to
M config.goconfig.go

@@ -29,6 +29,7 @@ SMTPServer string

SMTPUsername string SMTPPassword string EnableSFTP bool + HostKeyPath string } func getConfig(filename string) (Config, error) {
M example-config.tomlexample-config.toml

@@ -24,6 +24,7 @@

# Whether to enable user SFTP access # experimental feature, enable at your own risk EnableSFTP=true +HostKeyPath="id_rsa" # will be generated for you. Pub key at x.pub # Templates and static files # Everything in the static subfolder will be served at /
M sftp.gosftp.go

@@ -3,6 +3,10 @@ // A lot of this is copied from SFTPGo, but simplified for our use case.

package main import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" "fmt" "io" "io/ioutil"

@@ -135,7 +139,16 @@ },

} // TODO generate key automatically - privateBytes, err := ioutil.ReadFile("id_rsa") + if _, err := os.Stat(c.HostKeyPath); os.IsNotExist(err) { + // path/to/whatever does not exist + log.Println("Host key not found, generating host key") + err := GenerateRSAKeys() + if err != nil { + log.Fatal(err) + } + } + + privateBytes, err := ioutil.ReadFile(c.HostKeyPath) if err != nil { log.Fatal("Failed to load private key", err) }

@@ -246,6 +259,37 @@ log.Println("sftp server completed with error:", err)

return } } +} + +// GenerateRSAKeys generate rsa private and public keys and write the +// private key to specified file and the public key to the specified +// file adding the .pub suffix +func GenerateRSAKeys() error { + key, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return err + } + + o, err := os.OpenFile(c.HostKeyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return err + } + defer o.Close() + + priv := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(key), + } + + if err := pem.Encode(o, priv); err != nil { + return err + } + + pub, err := ssh.NewPublicKey(&key.PublicKey) + if err != nil { + return err + } + return ioutil.WriteFile(c.HostKeyPath+".pub", ssh.MarshalAuthorizedKey(pub), 0600) } type listerat []os.FileInfo