diff --git a/README.md b/README.md index e5bfff1..2fbf011 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ The interface is inspired by [`htop`](https://en.wikipedia.org/wiki/Htop) and sh currency convert menu +## Demo + +```bash +ssh cointop.sh +``` + In action screencast diff --git a/pkg/ssh/server.go b/pkg/ssh/server.go index daa415c..de35230 100644 --- a/pkg/ssh/server.go +++ b/pkg/ssh/server.go @@ -4,6 +4,7 @@ package ssh import ( "context" + "crypto/sha256" "errors" "fmt" "io" @@ -20,10 +21,10 @@ import ( gossh "golang.org/x/crypto/ssh" ) -// DefaultHostKeyFile ... +// DefaultHostKeyFile is default SSH key path var DefaultHostKeyFile = "~/.ssh/id_rsa" -// Config ... +// Config is config struct type Config struct { Port uint Address string @@ -32,7 +33,7 @@ type Config struct { HostKeyFile string } -// Server ... +// Server is server struct type Server struct { port uint address string @@ -42,7 +43,7 @@ type Server struct { hostKeyFile string } -// NewServer ... +// NewServer returns a new server instance func NewServer(config *Config) *Server { hostKeyFile := DefaultHostKeyFile if config.HostKeyFile != "" { @@ -60,7 +61,7 @@ func NewServer(config *Config) *Server { } } -// ListenAndServe ... +// ListenAndServe starts the server func (s *Server) ListenAndServe() error { s.sshServer = &ssh.Server{ Addr: fmt.Sprintf("%s:%v", s.address, s.port), @@ -74,13 +75,32 @@ func (s *Server) ListenAndServe() error { return } - tempDir, err := createTempDir() - if err != nil { - fmt.Println(err) - return + configDir := "" + pubKey := sshSession.PublicKey() + if pubKey != nil { + pubBytes := pubKey.Marshal() + if len(pubBytes) > 0 { + hash := sha256.Sum256(pubBytes) + configDir = fmt.Sprintf("/tmp/cointop_config/%x", hash) + err := os.MkdirAll(configDir, 0700) + if err != nil { + fmt.Println(err) + return + } + } } - configPath := fmt.Sprintf("%s/config", tempDir) + if configDir == "" { + tempDir, err := createTempDir() + if err != nil { + fmt.Println(err) + return + } + configDir = tempDir + defer os.RemoveAll(configDir) + } + + configPath := fmt.Sprintf("%s/config", configDir) colorsDir := pathutil.NormalizePath("~/.config/cointop/colors") cmdCtx, cancelCmd := context.WithCancel(sshSession.Context()) @@ -90,7 +110,7 @@ func (s *Server) ListenAndServe() error { "--reset", "--silent", "--cache-dir", - tempDir, + configDir, "--config", configPath, "--colors-dir", @@ -128,10 +148,8 @@ func (s *Server) ListenAndServe() error { io.Copy(sshSession, f) f.Close() cmd.Wait() - os.Remove(configPath) }, PtyCallback: func(ctx ssh.Context, pty ssh.Pty) bool { - // TODO: check public key hash return true }, PublicKeyHandler: func(ctx ssh.Context, key ssh.PublicKey) bool { @@ -157,19 +175,18 @@ func (s *Server) ListenAndServe() error { return s.sshServer.ListenAndServe() } -// Shutdown ... +// Shutdown shuts down the server func (s *Server) Shutdown() { s.sshServer.Close() } -// setWinsize ... +// setWinsize sets the PTY window size func setWinsize(f *os.File, w, h int) { syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) } -// createTempDir ... -// TODO: load saved configuration based on ssh public key hash +// createTempDir creates a temporary directory func createTempDir() (string, error) { return ioutil.TempDir("", "") }