12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- package gopass
- import (
- "errors"
- "fmt"
- "io"
- "os"
- )
- var defaultGetCh = func() (byte, error) {
- buf := make([]byte, 1)
- if n, err := os.Stdin.Read(buf); n == 0 || err != nil {
- if err != nil {
- return 0, err
- }
- return 0, io.EOF
- }
- return buf[0], nil
- }
- var (
- maxLength = 512
- ErrInterrupted = errors.New("interrupted")
- ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
- // Provide variable so that tests can provide a mock implementation.
- getch = defaultGetCh
- )
- // getPasswd returns the input read from terminal.
- // If masked is true, typing will be matched by asterisks on the screen.
- // Otherwise, typing will echo nothing.
- func getPasswd(masked bool) ([]byte, error) {
- var err error
- var pass, bs, mask []byte
- if masked {
- bs = []byte("\b \b")
- mask = []byte("*")
- }
- if isTerminal(os.Stdin.Fd()) {
- if oldState, err := makeRaw(os.Stdin.Fd()); err != nil {
- return pass, err
- } else {
- defer restore(os.Stdin.Fd(), oldState)
- }
- }
- // Track total bytes read, not just bytes in the password. This ensures any
- // errors that might flood the console with nil or -1 bytes infinitely are
- // capped.
- var counter int
- for counter = 0; counter <= maxLength; counter++ {
- if v, e := getch(); e != nil {
- err = e
- break
- } else if v == 127 || v == 8 {
- if l := len(pass); l > 0 {
- pass = pass[:l-1]
- fmt.Print(string(bs))
- }
- } else if v == 13 || v == 10 {
- break
- } else if v == 3 {
- err = ErrInterrupted
- break
- } else if v != 0 {
- pass = append(pass, v)
- fmt.Print(string(mask))
- }
- }
- if counter > maxLength {
- err = ErrMaxLengthExceeded
- }
- fmt.Println()
- return pass, err
- }
- // GetPasswd returns the password read from the terminal without echoing input.
- // The returned byte array does not include end-of-line characters.
- func GetPasswd() ([]byte, error) {
- return getPasswd(false)
- }
- // GetPasswdMasked returns the password read from the terminal, echoing asterisks.
- // The returned byte array does not include end-of-line characters.
- func GetPasswdMasked() ([]byte, error) {
- return getPasswd(true)
- }
|