Skip to content

Instantly share code, notes, and snippets.

@badcock4412
Last active April 2, 2020 17:10
Show Gist options
  • Save badcock4412/452bee5ce0ba96377463b0ce28fda25b to your computer and use it in GitHub Desktop.
Save badcock4412/452bee5ce0ba96377463b0ce28fda25b to your computer and use it in GitHub Desktop.
How to capture username and password from a terminal session in golang (cross-platform)
// adapted from the "best" solution supplied by StackExchange user gihanchanuka:
// https://stackoverflow.com/questions/2137357/getpasswd-functionality-in-go
//
// Tested in Windows Powershell and Windows cmd
package main
import (
"bufio"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
func credentials() (string, string) {
// Initialize the input reader for username
reader := bufio.NewReader(os.Stdin)
// Get the username
fmt.Print("Enter Username: ")
username, _ := reader.ReadString('\n')
// Get the terminal descriptor
termFd := int(syscall.Stdin)
// Get the terminal state
termState, err := terminal.GetState(termFd)
if err != nil {
log.Fatal("error gettting terminal state: %v", err)
}
// Restore the terminal state iff the process terminates
// during password capture
cancelC := make(chan bool)
signalC := make(chan os.Signal)
signal.Notify(signalC, os.Interrupt, os.Kill)
go func() {
select {
case <-cancelC:
signal.Stop(signalC)
fmt.Println("")
case <-signalC:
terminal.Restore(termFd, termState)
os.Exit(2)
}
}()
// Clear the signal capture after function naturaly ends
defer func() {
cancelC <- true
}()
// Capture password
fmt.Print("Enter Password: ")
bytePassword, err := terminal.ReadPassword(termFd)
if err != nil {
log.Fatal("error reading password")
}
password := string(bytePassword)
return strings.TrimSpace(username), strings.TrimSpace(password)
}
func main() {
username, password := credentials()
fmt.Println("username: " + username + ", password: " + password)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment