diff options
| author | Paul Buetow <pbuetow@mimecast.com> | 2022-02-04 21:37:29 +0000 |
|---|---|---|
| committer | Paul Buetow <pbuetow@mimecast.com> | 2022-02-04 21:37:29 +0000 |
| commit | 1db3b5dc1219e34e0e1c612e6646327701c40274 (patch) | |
| tree | cab22128af9e54131facd0062a474459383a1c90 /internal/ssh/server/publickeycallback.go | |
| parent | 6625d019271d3d7931587167845d77834d187d57 (diff) | |
| parent | cc6f19f69d0fb34af96e17147b2030c352d46845 (diff) | |
merge 4.0.0-RC
Diffstat (limited to 'internal/ssh/server/publickeycallback.go')
| -rw-r--r-- | internal/ssh/server/publickeycallback.go | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/internal/ssh/server/publickeycallback.go b/internal/ssh/server/publickeycallback.go index e81f019..f7655b4 100644 --- a/internal/ssh/server/publickeycallback.go +++ b/internal/ssh/server/publickeycallback.go @@ -4,67 +4,94 @@ import ( "fmt" "io/ioutil" "os" - osUser "os/user" + goUser "os/user" "github.com/mimecast/dtail/internal/config" - "github.com/mimecast/dtail/internal/io/logger" + "github.com/mimecast/dtail/internal/io/dlog" user "github.com/mimecast/dtail/internal/user/server" 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, offeredPubKey gossh.PublicKey) (*gossh.Permissions, error) { - user := user.New(c.User(), c.RemoteAddr().String()) - logger.Info(user, "Incoming authorization") +// PublicKeyCallback is for the server to check whether a public SSH key is +// authorized ot not. +func PublicKeyCallback(c gossh.ConnMetadata, + offeredPubKey gossh.PublicKey) (*gossh.Permissions, error) { - cwd, err := os.Getwd() + user, err := user.New(c.User(), c.RemoteAddr().String()) if err != nil { - return nil, fmt.Errorf("Unable to get current working directory|%s|", err.Error()) - } - - if config.ServerRelaxedAuthEnable { - logger.Fatal(user, "Granting permissions via relaxed-auth") - return nil, nil + return nil, err } + dlog.Server.Info(user, "Incoming authorization") - 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" + authorizedKeysFile, err := authorizedKeysFile(user) + if err != nil { + return nil, err } - logger.Info(user, "Reading", authorizedKeysFile) + dlog.Server.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()) + return nil, fmt.Errorf("Unable to read authorized keys file|%s|%s|%s", + authorizedKeysFile, user, err.Error()) } + return verifyAuthorizedKeys(user, authorizedKeysBytes, offeredPubKey) +} + +func verifyAuthorizedKeys(user *user.User, authorizedKeysBytes []byte, + offeredPubKey gossh.PublicKey) (*gossh.Permissions, error) { + authorizedKeysMap := map[string]bool{} for len(authorizedKeysBytes) > 0 { authorizedPubKey, _, _, restBytes, err := gossh.ParseAuthorizedKey(authorizedKeysBytes) if err != nil { - return nil, fmt.Errorf("Unable to parse authorized keys bytes|%s|%s", user, err.Error()) + return nil, fmt.Errorf("unable to parse authorized keys bytes|%s|%s", + user, err.Error()) } authorizedKeysMap[string(authorizedPubKey.Marshal())] = true authorizedKeysBytes = restBytes - - logger.Debug(user, "Authorized public key fingerprint", gossh.FingerprintSHA256(authorizedPubKey)) + dlog.Server.Debug(user, "Authorized public key fingerprint", + gossh.FingerprintSHA256(authorizedPubKey)) } - logger.Debug(user, "Offered public key fingerprint", gossh.FingerprintSHA256(offeredPubKey)) - + dlog.Server.Debug(user, "Offered public key fingerprint", gossh.FingerprintSHA256(offeredPubKey)) if authorizedKeysMap[string(offeredPubKey.Marshal())] { return &gossh.Permissions{ - Extensions: map[string]string{ - "pubkey-fp": gossh.FingerprintSHA256(offeredPubKey), - }, + Extensions: map[string]string{"pubkey-fp": gossh.FingerprintSHA256(offeredPubKey)}, }, nil } - return nil, fmt.Errorf("%s|Public key of user not authorized", user) + return nil, fmt.Errorf("%s|public key of user not authorized", user) +} + +func authorizedKeysFile(user *user.User) (string, error) { + if config.Env("DTAIL_INTEGRATION_TEST_RUN_MODE") { + // In this case, we expect a pub key in the current directory. + return "./id_rsa.pub", nil + } + + cwd, err := os.Getwd() + if err != nil { + return "", err + } + + // Check for cached version in the dserver directory. + authorizedKeysFile := fmt.Sprintf("%s/%s/%s.authorized_keys", cwd, + config.Common.CacheDir, user.Name) + if _, err = os.Stat(authorizedKeysFile); err == nil { + return authorizedKeysFile, nil + } + + // As the last option, check the regular SSH path. + osUser, err := goUser.Lookup(user.Name) + if err != nil { + return "", err + } + authorizedKeysFile = fmt.Sprintf("%s/.ssh/authorized_keys", osUser.HomeDir) + if _, err = os.Stat(authorizedKeysFile); err == nil { + return authorizedKeysFile, nil + } + + return "", fmt.Errorf("unable to find a any authorized keys file") } |
