Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pinentry Serve returned error: EOF #28

Open
stffndtz opened this issue Jun 6, 2022 · 14 comments
Open

Pinentry Serve returned error: EOF #28

stffndtz opened this issue Jun 6, 2022 · 14 comments
Labels
bug Something isn't working

Comments

@stffndtz
Copy link

stffndtz commented Jun 6, 2022

Describe the bug

When running echo "GETPIN" | pinentry-touchid I get the following response

OK Hi from pinentry-touchid!
OK
2022/06/06 10:54:16 Pinentry Serve returned error: EOF

pinentry-mac runs as expected - I have tried to unsinstall & re-install pinentry-mac & pinentry-touchid with no sucess at this point. I have also been looking for similar issues but haven't found a solution as of yet.

System information

macOS

  • Architecture: Intel
  • Version: 12.3.1

GPG

  • Output of gpg --version
gpg (GnuPG) 2.3.6
libgcrypt 1.10.1
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /Users/<USER>/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
AEAD: EAX, OCB
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2 
  • Installed via Homebrew?

Yes.

Configuration

  • Please attach the output of the command gpgconf.
gpg:OpenPGP:/usr/local/Cellar/gnupg/2.3.6/bin/gpg
gpgsm:S/MIME:/usr/local/Cellar/gnupg/2.3.6/bin/gpgsm
keyboxd:Public Keys:/usr/local/Cellar/gnupg/2.3.6/libexec/keyboxd
gpg-agent:Private Keys:/usr/local/Cellar/gnupg/2.3.6/bin/gpg-agent
scdaemon:Smartcards:/usr/local/Cellar/gnupg/2.3.6/libexec/scdaemon
dirmngr:Network:/usr/local/Cellar/gnupg/2.3.6/bin/dirmngr
pinentry:Passphrase Entry:/usr/local/opt/pinentry/bin/pinentry
  • gpg-agent.conf
cat /Users/<USERNAME>/.gnupg/gpg-agent.conf
debug-level basic
log-file /Users/<USERNAME>.gnupg/gpg-agent.log
pinentry-program /usr/local/opt/pinentry-touchid/bin/pinentry-touchid

Logs

gpg-agent:

2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK Pleased to meet you, process 36805
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- RESET
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- OPTION ttyname=/dev/ttys004
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- OPTION ttytype=xterm-256color
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- OPTION lc-ctype=UTF-8
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- reloadagent
2022-06-06 10:53:55 gpg-agent[36329] SIGHUP received - re-reading configuration and flushing cache
2022-06-06 10:53:55 gpg-agent[36329] reading options from '/Users/<USERNAME>/.gnupg/gpg-agent.conf'
2022-06-06 10:53:55 gpg-agent[36329] enabled debug flags: ipc
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 -> OK
2022-06-06 10:53:55 gpg-agent[36329] DBG: chan_8 <- [eof]

pinentry-touchid:

2022/06/06 10:49:49 main.go:105: Ready!
2022/06/06 10:49:49 main.go:211: Confirm was called!
2022/06/06 10:49:50 main.go:105: Ready!
2022/06/06 10:49:50 main.go:211: Confirm was called!
2022/06/06 10:50:15 main.go:105: Ready!
2022/06/06 10:51:10 main.go:105: Ready!
2022/06/06 10:51:45 main.go:105: Ready!
2022/06/06 10:54:16 main.go:105: Ready!
2022/06/06 10:57:46 main.go:105: Ready!
2022/06/06 10:57:59 main.go:105: Ready!
@stffndtz stffndtz added the bug Something isn't working label Jun 6, 2022
@jorgelbg
Copy link
Owner

jorgelbg commented Aug 5, 2022

@stffndtz can you give it a try to the latest release (v0.0.3) and check if it fixes the issue?

@stffndtz
Copy link
Author

stffndtz commented Aug 5, 2022

@jorgelbg It seems I am still getting the same error after the update:

echo "GETPIN" | pinentry-touchid
OK Hi from pinentry-touchid!
D hello
OK
Pinentry Serve returned error: EOF

Post update (via brew) I ran

/usr/local/opt/pinentry-touchid/bin/pinentry-touchid -fix && gpg-connect-agent reloadagent /bye

Let me know if I can help!

@Myridium
Copy link

Myridium commented Aug 7, 2022

I have the same issue. I can use pinentry-touchid for gpg-agent, but I cannot use it generally for other programs.

$ echo GETPIN | pinentry-touchid
OK Hi from pinentry-touchid!
D abc
OK
Pinentry Serve returned error: EOF

@Myridium
Copy link

Myridium commented Aug 7, 2022

Could this be the culprit?

pinentry-touchid/main.go

Lines 428 to 431 in 0235243

if err := pinentry.Serve(callbacks, "Hi from pinentry-mac!"); err != nil {
fmt.Fprintf(os.Stderr, "Pinentry Serve returned error: %v\n", err)
os.Exit(-1)
}

Note the response from pinentry-mac is not Hi from pinentry-mac!. In fact it is Pleased to meet you. Viz.

$ echo GETPIN | pinentry-mac
OK Pleased to meet you
D abc
OK

So maybe line 428 should be changed to:

if err := pinentry.Serve(callbacks, "Pleased to meet you"); err != nil { 

I am just guessing.

@jorgelbg
Copy link
Owner

jorgelbg commented Aug 7, 2022

Just to be clear, if you are only checking directly with:

$ echo GETPIN | pinentry-touchid

This is rightfully showing the pinentry-mac GUI. This happens because you haven't followed the full assuan protocol to talk to pinentry. Yes, GETPIN is a valid assuan command that pinentry-touchid understands but since no information about your GPG key has been provided, it assumes that there is no item in the keychain and asks you to provide one (as a fallback mechanism).

You need to set pinentry-touchid as your pinentry-program in ~/.gnupg/gpg-agent.conf by adding the following line:

pinentry-program /usr/local/bin/pinentry-touchid

and also reload your gpg-agent:

$ gpg-connect-agent reloadagent /bye

For checking that it is working you can use:

$ echo 1234 | gpg -as -

You can also interact directly via stdin with pinentry-touchid, but you need to do the full dance of providing the potions that the gpg-agent usually sends to any pinentry program.

@Myridium
Copy link

Myridium commented Aug 7, 2022

Just to be clear, if you are only checking directly with:

$ echo GETPIN | pinentry-touchid

This is rightfully showing the pinentry-mac GUI. This happens because you haven't followed the full assuan protocol to talk to pinentry. Yes, GETPIN is a valid assuan command that pinentry-touchid understands but since no information about your GPG key has been provided, it assumes that there is no item in the keychain and asks you to provide one (as a fallback mechanism).

You need to set pinentry-touchid as your pinentry-program in ~/.gnupg/gpg-agent.conf by adding the following line:

pinentry-program /usr/local/bin/pinentry-touchid

and also reload your gpg-agent:

$ gpg-connect-agent reloadagent /bye

For checking that it is working you can use:

$ echo 1234 | gpg -as -

You can also interact directly via stdin with pinentry-touchid, but you need to do the full dance of providing the potions that the gpg-agent usually sends to any pinentry program.

This comment doesn't appear to have any relation to this bug report.

@jorgelbg
Copy link
Owner

jorgelbg commented Aug 8, 2022

What I meant is that just sending GETPIN to pinentry-touchid is not enough and it does not considered a valid assuan session, the gpg-agent (and I would expect the same from the program that is trying to use it) should do the valid session.

In this case EOF is just a report of an early disconnection. That being said it is true that pinentry-mac does not consider this early termination as an unexpected error. I've adjusted the behaviour of the the error check in 82cc231 and also set the default prompt in case none is passed, which provides a more similar experience to what pinentry-mac does. Can you give it a try?

@Myridium
Copy link

Myridium commented Aug 8, 2022

What I meant is that just sending GETPIN to pinentry-touchid is not enough and it does not considered a valid assuan session, the gpg-agent (and I would expect the same from the program that is trying to use it) should do the valid session.

In this case EOF is just a report of an early disconnection. That being said it is true that pinentry-mac does not consider this early termination as an unexpected error. I've adjusted the behaviour of the the error check in 82cc231 and also set the default prompt in case none is passed, which provides a more similar experience to what pinentry-mac does. Can you give it a try?

Thanks, I'll give it a try soon.

To clarify, the problem (for me at least) is that echo GETPIN | pinentry-touchid is a perfectly valid way to use a pinentry program, however it returns an error in this case even though a PIN can be fetched from the user. So, the program succeeds in collecting a PIN, but it prints an error message and, more importantly, returns a non-zero exit code.

In my case, I am attempting to use software called passage which in return uses software called rage which calls pinentry to ask for a PIN. I symlinked pinentry to pinentry-touchid because I want to use it for everything. It fails however. I assume what is happening is that pinentry-touchid falls back to pinentry-mac but doesn't return the exit code from the latter. And it also prints that error.

@Myridium
Copy link

Myridium commented Aug 8, 2022

I don't know anything about Assuan commands, but the way that rage uses pinentry triggers this error, so I assume that something about pinentry-touchid is not conforming to spec here. I'll try the fix soon.

@Myridium
Copy link

Myridium commented Aug 9, 2022

Sorry, I don't use go and don't know how to compile this project, so I can't try your fix.
If you add a Makefile for dummies, I can make.

@jorgelbg
Copy link
Owner

I've added a step to the CI that should build & upload the binaries. You could grab the built binaries from the summary page of the workflow. For instance for the latest commit: https://github.com/jorgelbg/pinentry-touchid/actions/runs/2831484675 (at the bottom).

@jorgelbg
Copy link
Owner

I had a chance to take a look under the hood at what rage sends to the pinentry program and I think that pinentry-touchid will keep falling back always to pinentry-mac.

When used with PGP the gpg-agent sends some identifying metadata about the key that is requesting the passphrase. This metadata is used by pinentry-touchid to tag the passphrase when it is stored in the keychain, since it is possible for a user to have multiple keys. Since this metadata it is not provided at all by rage pinentry-touchid cannot identify (nor currently store) an item in the keychain and falls back to pinentry-mac for the user to provide a password.

One way to go is to use a default label/name for tagging the keychain item. The downside of this is that you wouldn't be able to have more than 1 keys stored in the keychain (for rage) because there wouldn't be any way of distinguishing them apart.

Anyhow, this is my interpretation of what I've seen on the interaction between rage and whatever pinentry program is configured.

@Myridium
Copy link

Excellent, thanks for that clear explanation. I had wondered how pinentry-touchid knows which secret is being requested. That explains it.

The gpg-agent must pass an identifier string to the Assuan GETPIN instruction, or use a different instruction. Is it possible for pinentry-touchid to support caching of secrets with arbitrary identifiers/tags? Could you give an example of a shell command which does this, like echo GETPIN MY_ID | pinentry-touchid?

This would not help with rage specifically, but it would allow other programs to easily use pinentry-touchid. This may pose an additional security risk, if programs supplied predictable (guessable) identifiers. This could be somewhat reduced by having the pinentry-touchid program display clearly which program is requesting which secret (process name, tag/identifier requested).

@jorgelbg
Copy link
Owner

The majority of the information is passed via the SETDESC command. The pinentry program is expected to extract the metadata from the description. For instance:

pinentry-touchid/main.go

Lines 52 to 53 in 1170eb6

emailRegex = regexp.MustCompile(`\"(?P<name>.*<(?P<email>.*)>)\"`)
keyIDRegex = regexp.MustCompile(`ID (?P<keyId>.*),`) // keyID should be of exactly 8 or 16 characters

If the description contains any of the info that matches those regexes (plus the key ID) it will be used to label the keychain item.

If rage passes down some sort of key id or anything else that could be used to label and retrieve the password, pinentry-touchid should work similarly to how it works with the gpg-agent. This could be also shared via the description that rage sets when calling the pinentry program.

This would not help with rage specifically, but it would allow other programs to easily use pinentry-touchid. This may pose an additional security risk, if programs supplied predictable (guessable) identifiers. This could be somewhat reduced by having the pinentry-touchid program display clearly which program is requesting which secret (process name, tag/identifier requested).

The info passed down to pinentry-touchid is essentially provided with the intention of helping the user identify which passphrase is needed (or to automatically fetch it from the keychain) so it shouldn't be insecure by default. In the gpg-agent case, the private key is never shared. In any case, is responsibility of the caller that sends the commands to pinentry.

Having said that, I'm not familiar enough with age/rage to say which info could potentially be shared with pinentry-touchid 😅.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants