Skip to content

Commit

Permalink
yubikey-agent: drop transaction on SIGHUP
Browse files Browse the repository at this point in the history
When running yubikey-agent has an exclusive lock on the YubiKey which
applies to both PIV and PGP applets (presumably because they are
mediated by the same daemon) but not FIDO2. This is necessary in order
to keep the PIN cached, see go-piv/piv-go#47.

Handle SIGHUP by releasing that lock. Never was a signal name more apt.

This allows using "killall -HUP yubikey-agent" in a script or alias to
release the applet when needed.

$ ssh -T [email protected]
$ killall -HUP yubikey-agent; pass filippo.io
$ killall gpg-agent # couldn't find a command to make it drop its tx

yubikey-agent will seamlessly make a new transaction and ask for a PIN
the next time a signing operation is requested.
  • Loading branch information
FiloSottile committed Apr 26, 2020
1 parent ed4b7bc commit 0096c09
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import (
"log"
"net"
"os"
"os/signal"
"path/filepath"
"sync"
"syscall"
"time"

"github.com/go-piv/piv-go/piv"
Expand All @@ -36,6 +39,14 @@ func main() {

a := &Agent{}

c := make(chan os.Signal)
signal.Notify(c, syscall.SIGHUP)
go func() {
for range c {
a.Close()
}
}()

os.Remove(*socketPath)
l, err := net.Listen("unix", *socketPath)
if err != nil {
Expand All @@ -61,6 +72,7 @@ func main() {
}

type Agent struct {
mu sync.Mutex
yk *piv.YubiKey
serial uint32
}
Expand Down Expand Up @@ -114,6 +126,18 @@ func (a *Agent) connectToYK() (*piv.YubiKey, error) {
return yk, nil
}

func (a *Agent) Close() error {
a.mu.Lock()
defer a.mu.Unlock()
if a.yk != nil {
log.Println("Received SIGHUP, dropping YubiKey transaction...")
err := a.yk.Close()
a.yk = nil
return err
}
return nil
}

func (a *Agent) getPIN() (string, error) {
p, err := pinentry.New()
if err != nil {
Expand All @@ -128,9 +152,12 @@ func (a *Agent) getPIN() (string, error) {
}

func (a *Agent) List() ([]*agent.Key, error) {
a.mu.Lock()
defer a.mu.Unlock()
if err := a.ensureYK(); err != nil {
return nil, fmt.Errorf("could not reach YubiKey: %w", err)
}

pk, err := getPublicKey(a.yk, piv.SlotAuthentication)
if err != nil {
return nil, err
Expand Down Expand Up @@ -159,9 +186,16 @@ func getPublicKey(yk *piv.YubiKey, slot piv.Slot) (ssh.PublicKey, error) {
}

func (a *Agent) Signers() ([]ssh.Signer, error) {
a.mu.Lock()
defer a.mu.Unlock()
if err := a.ensureYK(); err != nil {
return nil, fmt.Errorf("could not reach YubiKey: %w", err)
}

return a.signers()
}

func (a *Agent) signers() ([]ssh.Signer, error) {
pk, err := getPublicKey(a.yk, piv.SlotAuthentication)
if err != nil {
return nil, err
Expand All @@ -186,7 +220,13 @@ func (a *Agent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
}

func (a *Agent) SignWithFlags(key ssh.PublicKey, data []byte, flags agent.SignatureFlags) (*ssh.Signature, error) {
signers, err := a.Signers()
a.mu.Lock()
defer a.mu.Unlock()
if err := a.ensureYK(); err != nil {
return nil, fmt.Errorf("could not reach YubiKey: %w", err)
}

signers, err := a.signers()
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 0096c09

Please sign in to comment.