Gnupg can't import or generate private key as root
Closed, InvalidPublic

Description

gpg: key A4A0D73114FDE6FC/A4A0D73114FDE6FC: error sending to agent: Permission denied
gpg: error building skey array: Permission denied
gpg: error reading 'priv.key': Permission denied
gpg: import from 'priv.key' failed: Permission denied

write(5, "GENKEY", 6) = 6
write(5, "\n", 1) = 1
read(5, "S INQUIRE_MAXLEN 1024\nINQUIRE KE"..., 1002) = 39
write(5, "D (genkey(rsa(nbits 4:2048)))\n", 30) = 30
write(5, "END", 3) = 3
write(5, "\n", 1) = 1
read(5, "INQUIRE PINENTRY_LAUNCHED 16959 "..., 1002) = 65
write(5, "END", 3) = 3
write(5, "\n", 1) = 1
read(5, "ERR 83918849 Permission denied <"..., 1002) = 42

Used shell: zsh 5.7.1
Login: sudo -i

Details

External Link
https://bugs.archlinux.org/task/63711
Version
2.2.17
werner added a subscriber: werner.Sep 29 2019, 7:40 PM

Please provide a full description of what you did. What command line did you use, have you su-ed or logged in regular.? What is the output of "gpgcof --list-dirs" ?

bionade24 updated the task description. (Show Details)Sep 29 2019, 7:52 PM
sysconfdir:/etc/gnupg
bindir:/usr/bin
libexecdir:/usr/lib/gnupg
libdir:/usr/lib/gnupg
datadir:/usr/share/gnupg
localedir:/usr/share/locale
socketdir:/root/.gnupg
dirmngr-socket:/root/.gnupg/S.dirmngr
agent-ssh-socket:/root/.gnupg/S.gpg-agent.ssh
agent-extra-socket:/root/.gnupg/S.gpg-agent.extra
agent-browser-socket:/root/.gnupg/S.gpg-agent.browser
agent-socket:/root/.gnupg/S.gpg-agent
homedir:/root/.gnupg

You should always run gpg with --verbose if you run into an unknown error. It shows more information; in your case info about the requested pinentry. The strace does not show this. You probably have no permission to launch the X version opf the pinentry because the xauth does not work. As a quick test use ssh -X root@localhost instead.

bisson added a subscriber: bisson.Sep 30 2019, 8:49 PM

What is weird is that pinentry supposedly detects the absence of an X session and falls back on curses. For instance, I have:

$ sudo su -l
# env | grep DISPLAY
# /usr/bin/pinentry-gtk-2
OK Pleased to meet you
GETPIN

This successfully runs an ncurses password prompt. However, when I run (in the exact same shell session):

# gpg --gen-key --verbose
gpg (GnuPG) 2.2.17; Copyright (C) 2019 Free Software Foundation, Inc.
[...]
gpg: no running gpg-agent - starting '/usr/bin/gpg-agent'
gpg: waiting for the agent to come up ... (5s)
gpg: connection to agent established
gpg: pinentry launched (124925 gtk2:curses 1.1.0 /dev/pts/6 xterm -)
gpg: agent_genkey failed: Permission denied
Key generation failed: Permission denied

if you run

gpg --debug ipc -K

you should see a line

[...] OPTION ttyname=/dev/pts/N

Check whether you can access that device. It is the device pinentry will use. If that does not get you any further add

log-file /somewhere/agent.log
verbose
debug-pinentry

to ~/.gnupg/gpg-agent.conf and restart gpg-agent. That will put all output from pinentry and the commands send to it into the log file.

Thanks for your help investigating this.

Here's the output of gpg --verbose --debug ipc --gen-key:

gpg: DBG: chan_4 <- OK Pleased to meet you, process 134432
gpg: DBG: connection to agent established
gpg: DBG: chan_4 -> RESET
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION ttyname=/dev/pts/0
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION ttytype=xterm
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION lc-ctype=en_US.UTF-8
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION lc-messages=en_US.UTF-8
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> GETINFO version
gpg: DBG: chan_4 <- D 2.2.17
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION allow-pinentry-notify
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> OPTION agent-awareness=2.1.0
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> RESET
gpg: DBG: chan_4 <- OK
gpg: DBG: chan_4 -> GENKEY
gpg: DBG: chan_4 <- S INQUIRE_MAXLEN 1024
gpg: DBG: chan_4 <- INQUIRE KEYPARAM
gpg: DBG: chan_4 -> D (genkey(rsa(nbits 4:2048)))
gpg: DBG: chan_4 -> END
gpg: DBG: chan_4 <- INQUIRE PINENTRY_LAUNCHED 134434 gtk2:curses 1.1.0 /dev/pts/0 xterm -
gpg: pinentry launched (134434 gtk2:curses 1.1.0 /dev/pts/0 xterm -)
gpg: DBG: chan_4 -> END
gpg: DBG: chan_4 <- ERR 83918849 Permission denied <Pinentry>
gpg: agent_genkey failed: Permission denied
Key generation failed: Permission denied
gpg: secmem usage: 1344/32768 bytes in 2 blocks

Indeed, the permissions on /dev/pts/0 are:

# ls -la /dev/pts/0
crw--w---- 1 bisson tty 136, 0 Sep 30 11:05 /dev/pts/0

while I am running as root. But running /usr/bin/pinentry-gtk-2 directly works as expected. What is different when gpg --gen-key runs pinentry that makes it fail?

werner added a comment.Oct 1 2019, 9:51 AM

Do you have

GPG_TTY=$(tty)
export GPG_TTY

in your shell's profile so that gpg-agent knowns the right tty to use? /dev/pts/0 does not look right.

I did not (neither in my root shell nor in my user shell) but setting and exporting this environment variable does not make any difference: gpg --gen-key still fails as above. (Note that tty indeed returns /dev/pts/0 .)

Also in another terminal?

bisson added a comment.Oct 1 2019, 8:46 PM

My other terminals (xterm) are /dev/pts/1, /dev/pts/2, etc. and I can reproduce the bug in them too.

I can also reproduce the bug in a virtual console: log in as a regular user, run su -l, then gpg --gen-key fails as above; in that case tty returns /dev/tty2 which has the following permissions:

crw------- 1 bisson tty 4, 2 Oct  1 08:41 /dev/tty2

However, in both xterm and virtual consoles, running /usr/bin/pinentry and typing GETPIN successfully displays a curses password prompt.

bisson added a comment.Oct 1 2019, 9:42 PM

I found a way to replicate that error with just pinentry by doing (as root):

# tty
/dev/pts/1
# pinentry
OK Pleased to meet you
OPTION ttyname=/dev/pts/1
OK
GETPIN
S ERROR gtk2.open_tty_for_read 83918849
ERR 83918849 Permission denied <Pinentry>

When I remove OPTION ttyname=... there is no error.

bisson added a comment.Oct 1 2019, 9:54 PM

I believe the issue is as follows. When given the option ttyname=... pinentry will open() the given tty and that fails since it is owned by the regular user and not root; strace reports:

openat(AT_FDCWD, "/dev/pts/1", O_RDONLY) = -1 EACCES (Permission denied)

However, when not given this option, pinentry will simply write() to stdout which causes no permission problem; through sudo and the terminal this goes to /dev/pts/1.

aheinecke closed this task as Invalid.Jun 2 2020, 11:53 AM
aheinecke added a subscriber: aheinecke.

While triaging issues this looks to me more like a support case. And not an issue of the software itself. So I'm closing this issue.

Closing the issue does not prevent you from communicating in this issue, its more for us so that we can better track open issues that require changes to the Software. Additionally I would suggest that such questions are handled on gnupg-users@gnupg.org where other users can additionally offer advice.