Drop another dependency and get a better read password function
This commit is contained in:
parent
eb4ee13f73
commit
6a79b450f7
1
go.mod
1
go.mod
@ -9,7 +9,6 @@ require (
|
|||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
3
go.sum
3
go.sum
@ -16,10 +16,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"golang.org/x/term"
|
|
||||||
|
|
||||||
"kitty"
|
"kitty"
|
||||||
"kitty/tools/base85"
|
"kitty/tools/base85"
|
||||||
@ -188,10 +187,7 @@ func get_response(rc *utils.RemoteControlCmd, timeout float64) (ans *Response, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer term.RestoreAndClose()
|
||||||
term.Restore()
|
|
||||||
term.Close()
|
|
||||||
}()
|
|
||||||
device = term
|
device = term
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("TODO: Implement socket IO")
|
err = fmt.Errorf("TODO: Implement socket IO")
|
||||||
@ -254,27 +250,33 @@ func get_password(password string, password_file string, password_env string, us
|
|||||||
if ans == "" && password_file != "" {
|
if ans == "" && password_file != "" {
|
||||||
if password_file == "-" {
|
if password_file == "-" {
|
||||||
if tty.IsTerminal(os.Stdin.Fd()) {
|
if tty.IsTerminal(os.Stdin.Fd()) {
|
||||||
q, err := term.ReadPassword(int(os.Stdin.Fd()))
|
var q string
|
||||||
if err != nil {
|
q, err = tty.ReadPassword("Password: ")
|
||||||
|
if err == nil {
|
||||||
ans = string(q)
|
ans = string(q)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
q, err := io.ReadAll(os.Stdin)
|
var q []byte
|
||||||
if err != nil {
|
q, err = io.ReadAll(os.Stdin)
|
||||||
|
if err == nil {
|
||||||
ans = strings.TrimRight(string(q), " \n\t")
|
ans = strings.TrimRight(string(q), " \n\t")
|
||||||
}
|
}
|
||||||
ttyf, err := os.Open("/dev/tty")
|
ttyf, err := os.Open(tty.Ctermid())
|
||||||
if err != nil {
|
if err == nil {
|
||||||
err = unix.Dup2(int(ttyf.Fd()), int(os.Stdin.Fd()))
|
err = unix.Dup2(int(ttyf.Fd()), int(os.Stdin.Fd()))
|
||||||
ttyf.Close()
|
ttyf.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
q, err := os.ReadFile(password_file)
|
var q []byte
|
||||||
if err != nil {
|
q, err = os.ReadFile(password_file)
|
||||||
|
if err == nil {
|
||||||
ans = strings.TrimRight(string(q), " \n\t")
|
ans = strings.TrimRight(string(q), " \n\t")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ans == "" && password_env != "" {
|
if ans == "" && password_env != "" {
|
||||||
ans = os.Getenv(password_env)
|
ans = os.Getenv(password_env)
|
||||||
|
|||||||
113
tools/tty/tty.go
113
tools/tty/tty.go
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@ -90,15 +91,17 @@ var SetNoEcho TermiosOperation = func(t *unix.Termios) {
|
|||||||
t.Lflag &^= unix.ECHO
|
t.Lflag &^= unix.ECHO
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenTerm(name string, operations ...TermiosOperation) (self *Term, err error) {
|
var SetReadPassword TermiosOperation = func(t *unix.Termios) {
|
||||||
fd, err := eintr_retry_intret(func() (int, error) {
|
t.Lflag &^= unix.ECHO
|
||||||
return unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666)
|
t.Lflag |= unix.ISIG
|
||||||
})
|
t.Lflag &^= unix.ICANON
|
||||||
if err != nil {
|
t.Iflag |= unix.ICRNL
|
||||||
return nil, &os.PathError{Op: "open", Path: name, Err: err}
|
t.Cc[unix.VMIN] = 1
|
||||||
|
t.Cc[unix.VTIME] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
self = &Term{name: name, fd: fd}
|
func WrapTerm(fd int, operations ...TermiosOperation) (self *Term, err error) {
|
||||||
|
self = &Term{name: fmt.Sprintf("<fd: %d>", fd), fd: fd}
|
||||||
err = eintr_retry_noret(func() error { return unix.SetNonblock(self.fd, false) })
|
err = eintr_retry_noret(func() error { return unix.SetNonblock(self.fd, false) })
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = self.ApplyOperations(TCSANOW, operations...)
|
err = self.ApplyOperations(TCSANOW, operations...)
|
||||||
@ -110,8 +113,22 @@ func OpenTerm(name string, operations ...TermiosOperation) (self *Term, err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenTerm(name string, operations ...TermiosOperation) (self *Term, err error) {
|
||||||
|
fd, err := eintr_retry_intret(func() (int, error) {
|
||||||
|
return unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, &os.PathError{Op: "open", Path: name, Err: err}
|
||||||
|
}
|
||||||
|
self, err = WrapTerm(fd, operations...)
|
||||||
|
if err != nil {
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func OpenControllingTerm(operations ...TermiosOperation) (self *Term, err error) {
|
func OpenControllingTerm(operations ...TermiosOperation) (self *Term, err error) {
|
||||||
return OpenTerm("/dev/tty", operations...) // go doesnt have a wrapper for ctermid()
|
return OpenTerm(Ctermid(), operations...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Term) Fd() int { return self.fd }
|
func (self *Term) Fd() int { return self.fd }
|
||||||
@ -178,6 +195,11 @@ func (self *Term) Restore() error {
|
|||||||
return self.RestoreWhen(TCSAFLUSH)
|
return self.RestoreWhen(TCSAFLUSH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Term) RestoreAndClose() error {
|
||||||
|
self.Restore()
|
||||||
|
return self.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func clamp(v, lo, hi int64) int64 {
|
func clamp(v, lo, hi int64) int64 {
|
||||||
if v < lo {
|
if v < lo {
|
||||||
return lo
|
return lo
|
||||||
@ -326,3 +348,78 @@ func (self *Term) GetSize() (*unix.Winsize, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Term) read_line(in_password_mode bool) ([]byte, error) {
|
||||||
|
var buf [1]byte
|
||||||
|
var ret []byte
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, err := self.Read(buf[:])
|
||||||
|
if n > 0 {
|
||||||
|
switch buf[0] {
|
||||||
|
case '\b', 0x7f:
|
||||||
|
if len(ret) > 0 {
|
||||||
|
ret = ret[:len(ret)-1]
|
||||||
|
_, err = self.WriteAllWithTimeout([]byte("\x08\x1b[P"), 5*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '\n':
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
// otherwise ignore \n
|
||||||
|
case '\r':
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
// otherwise ignore \r
|
||||||
|
default:
|
||||||
|
ret = append(ret, buf[0])
|
||||||
|
_, err = self.WriteAllWithTimeout([]byte("*"), 5*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF && len(ret) > 0 {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Term) ReadLine() ([]byte, error) {
|
||||||
|
return self.read_line(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Term) ReadPassword() (string, error) {
|
||||||
|
pw, err := self.read_line(false)
|
||||||
|
return string(pw), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// go doesnt have a wrapper for ctermid()
|
||||||
|
func Ctermid() string { return "/dev/tty" }
|
||||||
|
|
||||||
|
func ReadPassword(prompt string) (string, error) {
|
||||||
|
term, err := OpenControllingTerm(SetReadPassword)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer term.RestoreAndClose()
|
||||||
|
if len(prompt) > 0 {
|
||||||
|
_, err = term.WriteAllWithTimeout([]byte(prompt), 5*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pw, err := term.ReadPassword()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return pw, nil
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user