diff --git a/src/cli/init.go b/src/cli/init.go index c3a2b42..d727378 100644 --- a/src/cli/init.go +++ b/src/cli/init.go @@ -32,7 +32,7 @@ func TempInitCli() { configSSH := inputBinary("Configure SSH settings (for synchronization)?") if configSSH { // necessary SSH info - fmt.Print(AnsiBold+"Note:"+backend.AnsiReset, "Only key-based authentication is supported (keys may optionally be passphrase-protected).\nThe remote server must already be in your ~/.ssh/known_hosts file.\n\n") + fmt.Println(AnsiBold + "\nNote:" + backend.AnsiReset + " Only key-based authentication is supported (keys may optionally be passphrase-protected).\nThe remote server must already be in your ~/.ssh/known_hosts file.") sshUser := input("Remote SSH username:") sshIP := input("Remote SSH IP address:") sshPort := input("Remote SSH port:") @@ -40,7 +40,7 @@ func TempInitCli() { sshKeyProtected := inputBinary("Is the identity file password-protected?") // write config file - backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshIdentity": sshKey, "sshIDProtected": strconv.FormatBool(sshKeyProtected)}) + backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected)}) // generate device ID sync.DeviceIDGen() diff --git a/src/cli/utilitiesMisc.go b/src/cli/utilitiesMisc.go index 8c68c88..2ebad10 100644 --- a/src/cli/utilitiesMisc.go +++ b/src/cli/utilitiesMisc.go @@ -25,8 +25,8 @@ func input(prompt string) string { return strings.TrimRight(userInput, "\n\r ") // remove trailing newlines, carriage returns, and spaces } -// InputHidden prompts the user for input and returns the input as a string, hiding the input from the terminal -func InputHidden(prompt string) string { +// inputHidden prompts the user for input and returns the input as a string, hiding the input from the terminal +func inputHidden(prompt string) string { fmt.Print("\n" + prompt + " ") byteInput, _ := terminal.ReadPassword(int(os.Stdin.Fd())) password := string(byteInput) diff --git a/src/sync/client.go b/src/sync/client.go index 7e09f02..b074db0 100644 --- a/src/sync/client.go +++ b/src/sync/client.go @@ -3,7 +3,6 @@ package sync import ( "fmt" "github.com/rwinkhart/MUTN/src/backend" - "github.com/rwinkhart/MUTN/src/cli" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/knownhosts" "os" @@ -19,7 +18,7 @@ const ( ) // GetSSHOutput runs a command over SSH and returns the output -// only supports key-based authentication (passphrase-protected keys are supported in a CLI environment) TODO create a more generic interface for passphrase input +// only supports key-based authentication (passphrases are supported for CLI-based implementations) func GetSSHOutput(cmd string, manualSync bool) string { // get SSH config info, exit if not configured (displaying an error if the sync job was called manually) var sshUserConfig []string @@ -57,7 +56,7 @@ func GetSSHOutput(cmd string, manualSync bool) string { if keyFileProtected != "true" { parsedKey, err = ssh.ParsePrivateKey(key) } else { - parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, []byte(cli.InputHidden("Enter passphrase for \""+keyFile+"\":"))) // TODO test passphrase-protected keys + parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, inputKeyFilePassphrase()) // TODO test passphrase-protected keys } if err != nil { fmt.Println(backend.AnsiError+"Sync failed - Unable to parse private key:", keyFile+backend.AnsiReset) @@ -113,7 +112,7 @@ func GetSSHOutput(cmd string, manualSync bool) string { func getRemoteDataFromClient(manualSync bool) (map[string]int64, []string, []string) { // get remote output over SSH clientDeviceID, _ := os.ReadDir(backend.ConfigDir + backend.PathSeparator + "devices") - output := GetSSHOutput("libmuttonserver fetch "+clientDeviceID[0].Name(), manualSync) + output := GetSSHOutput("libmuttonserver fetch "+clientDeviceID[0].Name(), manualSync) // TODO fix potential index error if clientDeviceID was not configured // split output into slice based on occurrences of "\x1d" outputSlice := strings.Split(output, "\x1d") diff --git a/src/sync/input.go b/src/sync/input.go new file mode 100644 index 0000000..d848d3a --- /dev/null +++ b/src/sync/input.go @@ -0,0 +1,16 @@ +package sync + +import ( + "fmt" + "golang.org/x/crypto/ssh/terminal" + "os" +) + +// inputKeyFilePassphrase prompts the user for a passphrase for an SSH key file +// TODO support non-CLI implementations +func inputKeyFilePassphrase() []byte { + fmt.Print("\nEnter passphrase for your SSH keyfile: ") + passphrase, _ := terminal.ReadPassword(int(os.Stdin.Fd())) + fmt.Println() + return passphrase +}