gopasspw / gopass

The slightly more awesome standard unix password manager for teams
https://www.gopass.pw/
MIT License
5.94k stars 496 forks source link

Pinentry error `ERR 83918950 Inappropriate ioctl for device` #1879

Open kfken opened 3 years ago

kfken commented 3 years ago

Summary

When setting up a new age backend on Kali Linux 2021.1 with gopass init --crypto age I get:

Error: Failed to initialize store: failed to read user input: pinentry Error: unexpected response: ERR 83918950 Inappropriate ioctl for device <Pinentry>

Steps To Reproduce

gopass init --crypto age Follow setup prompts Enter password for your new keypair: Retype password for your new keypair: ⏳ This can take a long time. If you get impatient see https://github.com/gopasspw/gopass/b lob/master/docs/entropy.md Continue? [Y/n/q]: 🔑 Please enter your passphrase to unlock the age keyring 2021/03/25 11:24:59 failed to create new private key: failed to create new private key: pin entry Error: unexpected response: ERR 83918950 Inappropriate ioctl for device <Pinentry>

Expected behavior

Accepts PIN and creates new gopass store

Environment

Additional context

From the debug log:

2021/03/25 11:25:32.636902 age/keyring.go:43    age.(*Age).genKey       No native age key found. Generating ... 
2021/03/25 11:25:32.637016 age/keyring.go:85    age.(*Age).loadKeyring  no password callback found, redirecting to askPass                                            
2021/03/25 11:25:32.637069 age/keyring.go:94    age.(*Age).loadKeyring  can't decrypt keyring at /root/.config/gopass/age-keyring.age: open /root/.config/gopass/age-keyring.age: no such file or directory                                                                      
2021/03/25 11:25:32.637107 age/keyring.go:66    age.(*Age).generateIdentity     failed to load existing keyring from /root/.config/gopass/age-keyring.age: open /root/.config/gopass/age-keyring.age: no such file or directory                                                  
2021/03/25 11:25:32.637143 age/keyring.go:70    age.(*Age).generateIdentity     no existing keyring, creating new one                                                                 
2021/03/25 11:25:32.637212 age/keyring.go:118   age.(*Age).saveKeyring  no password callback found, redirecting to askPass                                                            
2021/03/25 11:25:32.637303 age/askpass.go:63    age.(*askPass).Passphrase       Value for /root/.config/gopass/age-keyring.age not found in cache                                     
2021/03/25 11:25:32.637400 gpgconf/gpgconf.go:20        gpgconf.Path    /usr/bin/gpgconf [gpgconf]                                                                                    
2021/03/25 11:25:32.680771 pinentry/pinentry.go:130     pinentry.(*Client).GetPin       message: "S ERROR curses.isatty 83918950 "                                                    
2021/03/25 11:25:32.681314 action/errors.go:59  action.ExitError        failed to read user input: pinentry Error: unexpected response: ERR 83918950 Inappropriate ioctl for device <Pinentry> - stacktrace: %!v(MISSING)  

Using ncurses pinentry, however thought this shouldn't matter since the fallback GetPin() would takeover if there was an error.

update-alternatives --config pinentry
There are 2 choices for the alternative pinentry (providing /usr/bin/pinentry).

Selection    Path                      Priority   Status
  0            /usr/bin/pinentry-gnome3   90        auto mode
* 1            /usr/bin/pinentry-curses   50        manual mode
  2            /usr/bin/pinentry-gnome3   90        manual mode
dominikschulz commented 3 years ago

This is the same (useless) error I've been seeing on MacOS with a recent pinentry-curses.

dominikschulz commented 3 years ago

@kfken Could you please provide the output of gpgconf? Unfortunately we don't seem to log that in the debug log.

dominikschulz commented 3 years ago

Also: did you set export GPG_TTY=$(tty)?

dominikschulz commented 3 years ago

FYI: the cli fallback will only be used if pinentry fails to initialize (usually due to the binary not being available). But this error happens when calling the GetPin method.

dominikschulz commented 3 years ago

Btw. I can reproduce the error when manually changing my pinentry (with update-alternatives --config pinentry) to pinentry-curses. With pinentry-gnome3 it all works.

Using the gpg backend with pinentry-curses works. With pinentry-gnome3 both gpg and age work for me.

kfken commented 3 years ago

Using the gpg backend with pinentry-curses works. With pinentry-gnome3 both gpg and age work for me.

Same here. I didn't want to use gnome for other reasons, so I had set curses. After removing the pinentry symlink, the fallback to GetPin() worked and I was able to create the store successfully.

I did have export GPG_TTY=$(tty) and pinentry:Passphrase Entry:/usr/bin/pinentry in gpgconf.

For the time being, that workaround is good for me, although would be nice to not have to rely on gnome for age backend.

Thanks again (and awesome work on this project)!

dominikschulz commented 3 years ago

Thanks!

I'd really like to figure out if this is a gopass / pinentry client issue or another strange gpg issue, but for the time being I'm out of ideas.

Let's keep this open in case anyone else encounters the same issue or has some idea what's going on.

tomeon commented 3 years ago

Ran into a similar-seeming issue:

The problem is that pinentry tries to treat something that's not a TTY as a TTY:

# strace -f yubikey-agent with pinentry-tty
<mountains of output ...>
[pid 10429] ioctl(0, TCGETS <unfinished ...>       
[pid 10259] futex(0x7810d8, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>                            
[pid 10429] <... ioctl resumed>, 0x7ffea979f870) = -1 ENOTTY (Inappropriate ioctl for device)
<more output ...>
# strace -f yubikey-agent, with pinentry-curses
<mountains of output ...>
[pid 12914] ioctl(0, TCGETS, 0x7ffecb3e04c0) = -1 ENOTTY (Inappropriate ioctl for device)    
[pid 12914] write(4, "S ERROR curses.isatty 83918950 ", 31) = 31
<more output ...>

Note that the bad ioctls pertain to fd 0 / stdin, and that both pinentry-tty and pinentry-curses assume that they should use stdin as the TTY to interact with if the --ttyname command-line option is absent and the client didn't provide OPTION ttyname=/path/to/tty. Presumably, the not-a-TTY stream in question is the pipe that gopass sets up as pinentry's stdin.

Note also that I (unsurprisingly) don't hit an ioctl issue when using pinentry-gtk2, pinentry-qt, and other graphical pinentry implementations.

huhndev commented 3 years ago

Summary

I can reproduce the error already at the first prompt for a password.

Steps To Reproduce

$ gopass init --crypto age
[...]
No existing age identities found. Do you want to generate a new one? [Y/n/q]: y
Please enter your passphrase to unlock the age keyring

Error: Failed to initialize store: failed to read user input: pinentry (/usr/local/bin/pinentry) error: unexpected response: ERR 83918950 Inappropiate ioctl for device <Pinentry>

Environment

OS: OpenBSD 7.0 -current gopass Version: gopass 1.12.7 go1.17 openbsd amd64 Installation method: Installed from ports

Mrfiregem commented 3 years ago

I get the same error on Arch Linux:

$ gopass init --crypto age
🍭 Initializing a new password store ...
🔑 Searching for usable private Keys ...
⚠ Hint: Use 'gopass init <subkey> to use subkeys!'
🔑 No existing age identities found. Do you want to generate a new one? [Y/n/q]: 
🔑 Please enter your passphrase to unlock the age keyring

Error: Failed to initialize store: failed to read user input: pinentry (/usr/bin/pinentry) error: unexpected response: ERR 83918950 Inappropriate ioctl for device <Pinentry>
$ paru -Q pinentry gopass
pinentry 1.1.1-1
gopass 1.12.8-1

Also, how should one specify an existing age key?

dominikschulz commented 3 years ago

Specifying an existing age key isn't support yet (I think). But I think this is something the age backend should eventually support. I'd be happy to accept a PR for that.

dominikschulz commented 2 years ago

FTR: Keybase seems to have a similar issue, open since 2016 😢

AnomalRoil commented 2 years ago

And they also have another issue where the solution seems to really "just" be to have export GPG_TTY=$(tty)

huhndev commented 2 years ago
$ cat .kshrc                                                                                                                                                                                                             
[...]
export GPG_TTY=$(tty)
[..]
$ env                 
[...]
GPG_TTY=/dev/ttyp2
[...]
$ gopass init --crypto age
🍭 Initializing a new password store ...
🔑 Searching for usable private Keys ...
⚠ Hint: Use 'gopass init <subkey> to use subkeys!'
🔑 No existing age identities found. Do you want to generate a new one? [Y/n/q]: Y

Error: Failed to initialize store: failed to read user input: pinentry (/usr/local/bin/pinentry) error: unexpected response: ERR 83918950 Inappropriate ioctl for device <Pinentry>

Environment

OS: OpenBSD 7.0 -current gopass version: gopass 1.13.0 go1.17.5 openbsd amd64 pinentry version: pinentry-1.1.1 Installation method: Installed from OpenBSD ports

SirMishaa commented 2 years ago

I got the same issue, i'm on a clean install on WSL and the GUI to ask the passphrase is only show when I use pinentry-qt

$GPG_TTY is exported.

❯ echo $GPG_TTY
/dev/pts/4
andy-shev commented 1 year ago

After updating export GPG_TTY=$(tty) one must tell GPG agent about it with gpg-connect-agent updatestartuptty /bye. So, pinentry will pop up on this tty.

r3mi commented 10 months ago

Same issue on a fresh install of Ubuntu 22.04.3 LTS. installed gopass through apt-get from https://packages.gopass.pw/repos/gopass source. Using only age crypto backend. export GPG_TTY=$(tty) solved the issue. Not sure why though, I am not using the gpg backend.