diff options
| author | Paul Bütow <pbuetow@mimecast.com> | 2020-01-09 20:30:15 +0000 |
|---|---|---|
| committer | Paul Bütow <pbuetow@mimecast.com> | 2020-01-09 20:30:15 +0000 |
| commit | 3755a9911ecb05886577095f2b8cc8b9e4066a3a (patch) | |
| tree | 86e24bc466986cb5c9c6d167a918e6064defeafc /ssh/server | |
Release of DTail v1.0.0v1.0.0
Diffstat (limited to 'ssh/server')
| -rw-r--r-- | ssh/server/hostkey.go | 37 | ||||
| -rw-r--r-- | ssh/server/publickeycallback.go | 61 |
2 files changed, 98 insertions, 0 deletions
diff --git a/ssh/server/hostkey.go b/ssh/server/hostkey.go new file mode 100644 index 0000000..ff1eb82 --- /dev/null +++ b/ssh/server/hostkey.go @@ -0,0 +1,37 @@ +package server + +import ( + "dtail/config" + "dtail/logger" + "dtail/ssh" + "io/ioutil" + "os" +) + +// PrivateHostKey retrieves the private server RSA host key. +func PrivateHostKey() []byte { + hostKeyFile := config.Server.HostKeyFile + _, err := os.Stat(hostKeyFile) + + if os.IsNotExist(err) { + logger.Info("Generating private server RSA host key") + privateKey, err := ssh.GeneratePrivateRSAKey(config.Server.HostKeyBits) + + if err != nil { + logger.FatalExit("Failed to generate private server RSA host key", err) + } + + pem := ssh.EncodePrivateKeyToPEM(privateKey) + if err := ioutil.WriteFile(hostKeyFile, pem, 0600); err != nil { + logger.Error("Unable to write private server RSA host key to file", hostKeyFile, err) + } + return pem + } + + logger.Info("Reading private server RSA host key from file", hostKeyFile) + pem, err := ioutil.ReadFile(hostKeyFile) + if err != nil { + logger.FatalExit("Failed to load private server RSA host key", err) + } + return pem +} diff --git a/ssh/server/publickeycallback.go b/ssh/server/publickeycallback.go new file mode 100644 index 0000000..867f639 --- /dev/null +++ b/ssh/server/publickeycallback.go @@ -0,0 +1,61 @@ +package server + +import ( + "dtail/config" + "dtail/logger" + "dtail/server/user" + "fmt" + "io/ioutil" + "os" + osUser "os/user" + + gossh "golang.org/x/crypto/ssh" +) + +// PublicKeyCallback is for the server to check whether a public SSH key is authorized ot not. +func PublicKeyCallback(c gossh.ConnMetadata, pubKey gossh.PublicKey) (*gossh.Permissions, error) { + user := user.New(c.User(), c.RemoteAddr().String()) + logger.Info(user, "Incoming authorization") + + cwd, err := os.Getwd() + if err != nil { + return nil, fmt.Errorf("Unable to get current working directory|%s|", err.Error()) + } + + authorizedKeysFile := fmt.Sprintf("%s/%s/%s.authorized_keys", cwd, config.Common.CacheDir, user.Name) + if _, err := os.Stat(authorizedKeysFile); os.IsNotExist(err) { + user, err := osUser.Lookup(user.Name) + if err != nil { + return nil, fmt.Errorf("Unable to authorize|%s|%s|", user, err.Error()) + } + // Fallback to ~ + authorizedKeysFile = user.HomeDir + "/.ssh/authorized_keys" + } + + logger.Info(user, "Reading", authorizedKeysFile) + authorizedKeysBytes, err := ioutil.ReadFile(authorizedKeysFile) + if err != nil { + return nil, fmt.Errorf("Unable to read authorized keys file|%s|%s|%s", authorizedKeysFile, user, err.Error()) + } + + authorizedKeysMap := map[string]bool{} + for len(authorizedKeysBytes) > 0 { + pubKey, _, _, rest, err := gossh.ParseAuthorizedKey(authorizedKeysBytes) + if err != nil { + return nil, fmt.Errorf("Unable to parse authorized keys bytes|%s|%s", user, err.Error()) + } + authorizedKeysMap[string(pubKey.Marshal())] = true + authorizedKeysBytes = rest + } + + if authorizedKeysMap[string(pubKey.Marshal())] { + logger.Debug("Public key fingerprint", gossh.FingerprintSHA256(pubKey), user) + return &gossh.Permissions{ + Extensions: map[string]string{ + "pubkey-fp": gossh.FingerprintSHA256(pubKey), + }, + }, nil + } + + return nil, fmt.Errorf("Unknown public key|%s", user) +} |
