diff --git a/cmd/verify.go b/cmd/verify.go index 0570367..7fa94ae 100644 --- a/cmd/verify.go +++ b/cmd/verify.go @@ -2,13 +2,11 @@ package cmd import ( "fmt" - "syscall" "github.com/passbolt/go-passbolt-cli/util" "github.com/passbolt/go-passbolt/api" "github.com/spf13/cobra" "github.com/spf13/viper" - "golang.org/x/term" ) // verifyCMD represents the verify command @@ -35,12 +33,12 @@ var verifyCMD = &cobra.Command{ userPassword := viper.GetString("userPassword") if userPassword == "" { fmt.Print("Enter Password:") - bytepw, err := term.ReadPassword(int(syscall.Stdin)) + pw, err := util.ReadPassword() if err != nil { fmt.Println() return fmt.Errorf("Reading Password: %w", err) } - userPassword = string(bytepw) + userPassword = pw fmt.Println() } diff --git a/keepass/export.go b/keepass/export.go index c4b62d0..a4c34fb 100644 --- a/keepass/export.go +++ b/keepass/export.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "os" - "syscall" "github.com/passbolt/go-passbolt-cli/util" "github.com/passbolt/go-passbolt/api" @@ -13,7 +12,6 @@ import ( "github.com/spf13/cobra" "github.com/tobischo/gokeepasslib/v3" w "github.com/tobischo/gokeepasslib/v3/wrappers" - "golang.org/x/term" ) // KeepassExportCmd Exports a Passbolt Keepass @@ -56,12 +54,12 @@ func KeepassExport(cmd *cobra.Command, args []string) error { if keepassPassword == "" { fmt.Print("Enter Keepass Password:") - bytepw, err := term.ReadPassword(int(syscall.Stdin)) + pw, err := util.ReadPassword() if err != nil { fmt.Println() return fmt.Errorf("Reading Keepass Password: %w", err) } - keepassPassword = string(bytepw) + keepassPassword = pw fmt.Println() } diff --git a/util/client.go b/util/client.go index 1ba4946..f8abb09 100644 --- a/util/client.go +++ b/util/client.go @@ -1,11 +1,14 @@ package util import ( + "bufio" "context" "encoding/json" "errors" "fmt" "net/http" + "os" + "strings" "syscall" "github.com/passbolt/go-passbolt/api" @@ -14,6 +17,31 @@ import ( "golang.org/x/term" ) +// ReadPassword reads a Password interactively or via Pipe +func ReadPassword() (string, error) { + var fd int + var pass []byte + if term.IsTerminal(syscall.Stdin) { + fmt.Print("Enter Password:") + + fd = syscall.Stdin + inputPass, err := term.ReadPassword(fd) + if err != nil { + return "", err + } + pass = inputPass + } else { + reader := bufio.NewReader(os.Stdin) + s, err := reader.ReadString('\n') + if err != nil { + return "", err + } + pass = []byte(s) + } + + return strings.Replace(string(pass), "\n", "", 1), nil +} + // GetClient gets a Logged in Passbolt Client func GetClient(ctx context.Context) (*api.Client, error) { serverAddress := viper.GetString("serverAddress") @@ -28,13 +56,13 @@ func GetClient(ctx context.Context) (*api.Client, error) { userPassword := viper.GetString("userPassword") if userPassword == "" { - fmt.Print("Enter Password:") - bytepw, err := term.ReadPassword(int(syscall.Stdin)) + cliPassword, err := ReadPassword() if err != nil { fmt.Println() return nil, fmt.Errorf("Reading Password: %w", err) } - userPassword = string(bytepw) + + userPassword = cliPassword fmt.Println() } @@ -69,12 +97,11 @@ func GetClient(ctx context.Context) (*api.Client, error) { for i := 0; i < 3; i++ { var code string fmt.Print("Enter TOTP:") - bytepw, err := term.ReadPassword(int(syscall.Stdin)) + code, err := ReadPassword() if err != nil { fmt.Printf("\n") return http.Cookie{}, fmt.Errorf("Reading TOTP: %w", err) } - code = string(bytepw) fmt.Printf("\n") req := api.MFAChallangeResponse{ TOTP: code,