From b9e9373b042704e8a7ce0b3215f335a637dfb2cb Mon Sep 17 00:00:00 2001 From: Greg Date: Fri, 6 Sep 2019 13:36:06 -0400 Subject: [PATCH] Fix animation code. Retry GPG agent password prompt and clear cache if the passphrase does not work. --- README.md | 2 +- cmd/passgo-gui/main.go | 56 ++++++++++++++++++++++++++++++------------ main.go | 24 ++++++++++++------ 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 595ba7a..b85d244 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ err := passgo.GetStore(&store) if err != nil { ... } passlist := store.List() for _,x := range passlist { - if x.Pathname = "myPass" { + if x.Pathname == "myPass" { p, err := store.Decrypt(x.Pathname) if err == nil { passgo.Clip(p) // put on the clipboard diff --git a/cmd/passgo-gui/main.go b/cmd/passgo-gui/main.go index e8f2b5d..7797d8c 100644 --- a/cmd/passgo-gui/main.go +++ b/cmd/passgo-gui/main.go @@ -25,6 +25,7 @@ import ( type conf struct { StoreDir string + ClearDelay int } func main() { @@ -50,6 +51,9 @@ func main() { if err != nil { log(Fatal, err) } + if Config.ClearDelay == 0 { + Config.ClearDelay = 45 + } if fd != nil { // we still have an empty conf file open: Config.StoreDir = store.Dir @@ -156,13 +160,8 @@ func eventLoop() { titleflex := &layout.Flex{Axis: layout.Horizontal} flex := &layout.Flex{Axis: layout.Vertical} - passInput := &text.Editor{Face: face, SingleLine: true} - passInput.SetText("passphrase") - passSubmit := &Button{Face: face, Label: "submit", Color: black} lst := &layout.List{Axis: layout.Vertical} passBtns := make([]*Button, 0) - _ = passInput - _ = passSubmit pathnames := make([]string, 0) copied := &Overlay{Face: face, Text: "copied to clipboard", Color: black, @@ -226,7 +225,7 @@ func eventLoop() { } promptLabel := &text.Label{Face: face, Text: "passphrase"} - promptEd := &text.Editor{Face: face, SingleLine: true} + promptEd := &text.Editor{Face: face, SingleLine: true, Submit: true} okBtn := &Button{ Face: face, Label: "ok", @@ -238,11 +237,13 @@ func eventLoop() { anim := &time.Ticker{} animating := false animOn := func() { + log(Info,"animOn()") anim = time.NewTicker(time.Second / 120) animating = true w.Invalidate() } animOff := func() { + log(Info,"animOff()") anim.Stop() animating = false } @@ -286,13 +287,13 @@ func eventLoop() { passgo.Clip(p) overlayStart = time.Now() overlay = copied + overlay.Color = black + overlay.Background = darkgray animOn() go func() { - time.Sleep(time.Second * 45) + time.Sleep(time.Second * time.Duration(Config.ClearDelay)) + log(Info, "clearing clipboard") passgo.Clip("") - overlay = cleared - overlayStart = time.Now() - animOn() }() } else { log(Info, "Can't decrypt ", name) @@ -311,10 +312,19 @@ func eventLoop() { } flex.Layout(c1, c2) x := time.Since(overlayStart).Seconds() - start, end := 1.5, 1.75 + fade1a, fade1b := 1.5, 1.75 + start2 := float64(Config.ClearDelay) + fade2a, end := start2 + 1.5, start2 + 1.75 switch { - case x > start && x < end: - fade := (end - x) / (end - start) + case x > fade1a && x < fade1b || + x > fade2a && x < end: + var fade float64 + switch { + case x < fade1b: + fade = (fade1b - x) / (fade1b - fade1a) + case x > fade2a: + fade = (end - x) / (end - fade2a) + } overlay.Color.R = uint8(float64(black.R) * fade) overlay.Color.G = uint8(float64(black.G) * fade) overlay.Color.B = uint8(float64(black.B) * fade) @@ -324,13 +334,19 @@ func eventLoop() { overlay.Background.B = uint8(float64(darkgray.B) * fade) overlay.Background.A = uint8(float64(darkgray.A) * fade) fallthrough - case x <= start: + case x <= fade1b || + x > start2 && x < end: + if x > start2 && overlay == copied { + overlay = cleared + overlay.Color = black + overlay.Background = darkgray + } cs = margincs al := layout.Align{Alignment: layout.SE} cs = al.Begin(ops, cs) cs.Width.Min = cs.Width.Max dims = al.End(overlay.Layout(c, ops, cs)) - case animating: + case animating && x > end: animOff() } } @@ -373,6 +389,14 @@ func eventLoop() { } promptPage = func() { + submit := false + for e, ok := promptEd.Next(c, q); ok; e, ok = promptEd.Next(c, q) { + switch e.(type) { + case text.SubmitEvent: + log(Info, "Submit") + submit = true + } + } cs = flex.Rigid() c2 := flex.End(promptLabel.Layout(ops, cs)) cs = flex.Rigid() @@ -389,7 +413,7 @@ func eventLoop() { dims = btnflx.Layout(bc1, bc2) c4 := flex.End(al.End(dims)) flex.Layout(c1, c2, c3, c4) - if okBtn.Clicked() { + if submit || okBtn.Clicked() { log(Info, "Ok") go func() { // do not block UI thread passch <-[]byte(promptEd.Text()) diff --git a/main.go b/main.go index 9a618e2..e19d440 100644 --- a/main.go +++ b/main.go @@ -126,13 +126,16 @@ func AskPass(prompts ...func() []byte) openpgp.PromptFunction { dec := func(p *packet.PrivateKey) error { for i := 0; i < 3; i++ { if err := p.Decrypt(passphrase); err == nil { + passphrase = nil return err } passphrase = prompt() if passphrase == nil { + passphrase = nil return fmt.Errorf("Passphrase entry aborted") } } + passphrase = nil return fmt.Errorf("Passphrase entry failed") } @@ -170,15 +173,20 @@ func GPGPrompt(keys []openpgp.Key, symmetric bool) ([]byte, error) { for _, key := range keys { cacheId := strings.ToUpper(hex.EncodeToString(key.PublicKey.Fingerprint[:])) request := gpgagent.PassphraseRequest{CacheKey: cacheId} - passphrase, err := conn.GetPassphrase(&request) - if err != nil { - return nil, err + for i := 0; i < 3; i++ { + var passphrase string + passphrase, err = conn.GetPassphrase(&request) + if err != nil { + continue + } + err = key.PrivateKey.Decrypt([]byte(passphrase)) + if err != nil { + conn.RemoveFromCache(cacheId) + continue + } + return []byte(passphrase), nil } - err = key.PrivateKey.Decrypt([]byte(passphrase)) - if err != nil { - return nil, err - } - return []byte(passphrase), nil + return nil, err } return nil, fmt.Errorf("Unable to find key") }