GNOME Keyring Daemon Breaks My GPG Encrypted Backups
Background
Somewhere along the way my backups stopped working when I upgraded to Ubuntu 13.04. I don’t understand what exactly changed as the backup script is the same and I’m pretty sure I was using gnome-keyring-daemon as my gpg-agent.
I use obnam from remote back-ups and it works great. Every night it copies the delta from the last back-up to Dreamhost Personal Backup and encrypts my data on the fly. In the event my apartment burns down I’ll have my most important data. The rest of my data is backed-up using rsync to another local harddrive which is considerably cheaper and significantly faster.
Troubleshooting
My cron scripts started complaining, so I began my investigation with a simple obnam command. This command is supposed to list all my backups on the remote server after it decrypts the remote metadata locally. However it failed after I took a while guess that an empty or unset $DISPLAY
environmental variable would trip it up:
$ DISPLAY="" obnam generations
Host key fingerprint is 0e:c2:f6:f4:d9:86:9d:4b:c4:3d:77:e7:a4:bb:59:14
+--[ RSA 2048]----+
| |
| |
| E |
| . . . .|
| + o S o o . =|
| . + + * . o *.|
| . = * . o|
| o . + |
| . +. |
+-----------------+
ERROR: gpg: problem with the agent - disabling agent use
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: decryption failed: secret key not available
Next step was to try gpg standalone in a terminal with DISPLAY set and then unset.
$ echo "test" | gpg -ase --batch --default-key 0x4437655D -r 0x4437655D | gpg
You need a passphrase to unlock the secret key for
user: "Obnam <[email protected]>"
2048-bit RSA key, ID 6DEBA469, created 2012-07-08 (main key ID 4437655D)
gpg: encrypted with 2048-bit RSA key, ID 6DEBA469, created 2012-07-08
"Obnam <[email protected]>"
test
gpg: Signature made Tue 07 May 2013 12:20:01 AM PDT using RSA key ID 4437655D
gpg: Good signature from "Obnam <[email protected]>"
$ echo "test" | DISPLAY="" gpg -ase --batch --default-key 0x4437655D -r 0x4437655D | gpg
gpg: problem with the agent - disabling agent use
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: no default secret key: bad passphrase
gpg: [stdin]: sign+encrypt failed: bad passphrase
gpg: processing message failed: eof
Okay, so it’s not an obnam invocation problem or something from cron other then DISPLAY seems to break everything. Lets see what strace tells us:
$ echo "test" | DISPLAY="" strace -vo strace.log gpg -ase --batch --default-key 0x4437655D -r 0x4437655D
gpg: problem with the agent - disabling agent use
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: Invalid passphrase; please try again ...
gpg: can't query passphrase in batch mode
gpg: no default secret key: bad passphrase
gpg: [stdin]: sign+encrypt failed: bad passphrase
And the strace output is in strace.log:
...
socket(PF_FILE, SOCK_STREAM, 0) = 7
connect(7, {sa_family=AF_FILE, path="/run/user/nitro/keyring-FUvSXm/gpg"}, 36) = 0
read(7, "OK your orders please\n", 1002) = 22
| 00000 4f 4b 20 79 6f 75 72 20 6f 72 64 65 72 73 20 70 OK your orders p |
| 00010 6c 65 61 73 65 0a lease. |
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff53fd8900) = -1 ENOTTY (Inappropriate ioctl for device)
write(7, "OPTION ttyname=/dev/tty", 23) = 23
| 00000 4f 50 54 49 4f 4e 20 74 74 79 6e 61 6d 65 3d 2f OPTION t tyname=/ |
| 00010 64 65 76 2f 74 74 79 dev/tty |
write(7, "\n", 1) = 1
| 00000 0a . |
read(7, "OK \n", 1002) = 4
| 00000 4f 4b 20 0a OK . |
write(7, "OPTION ttytype=screen-256color", 30) = 30
| 00000 4f 50 54 49 4f 4e 20 74 74 79 74 79 70 65 3d 73 OPTION t tytype=s |
| 00010 63 72 65 65 6e 2d 32 35 36 63 6f 6c 6f 72 creen-25 6color |
write(7, "\n", 1) = 1
| 00000 0a . |
read(7, "OK \n", 1002) = 4
| 00000 4f 4b 20 0a OK . |
write(7, "OPTION lc-ctype=en_US.UTF-8", 27) = 27
| 00000 4f 50 54 49 4f 4e 20 6c 63 2d 63 74 79 70 65 3d OPTION l c-ctype= |
| 00010 65 6e 5f 55 53 2e 55 54 46 2d 38 en_US.UT F-8 |
write(7, "\n", 1) = 1
| 00000 0a . |
read(7, "OK \n", 1002) = 4
| 00000 4f 4b 20 0a OK . |
write(7, "OPTION lc-messages=en_US.UTF-8", 30) = 30
| 00000 4f 50 54 49 4f 4e 20 6c 63 2d 6d 65 73 73 61 67 OPTION l c-messag |
| 00010 65 73 3d 65 6e 5f 55 53 2e 55 54 46 2d 38 es=en_US .UTF-8 |
write(7, "\n", 1) = 1
| 00000 0a . |
read(7, "OK \n", 1002) = 4
| 00000 4f 4b 20 0a OK . |
...
write(7, "GET_PASSPHRASE 0C7DFA3DEF7B1A269"..., 202) = 202
| 00000 47 45 54 5f 50 41 53 53 50 48 52 41 53 45 20 30 GET_PASS PHRASE 0 |
| 00010 43 37 44 46 41 33 44 45 46 37 42 31 41 32 36 39 C7DFA3DE F7B1A269 |
| 00020 34 45 41 38 39 34 31 30 46 38 34 45 31 30 41 34 4EA89410 F84E10A4 |
| 00030 34 33 37 36 35 35 44 20 58 20 58 20 59 6f 75 2b 437655D X X You+ |
| 00040 6e 65 65 64 2b 61 2b 70 61 73 73 70 68 72 61 73 need+a+p assphras |
| 00050 65 2b 74 6f 2b 75 6e 6c 6f 63 6b 2b 74 68 65 2b e+to+unl ock+the+ |
| 00060 73 65 63 72 65 74 2b 6b 65 79 2b 66 6f 72 2b 75 secret+k ey+for+u |
| 00070 73 65 72 3a 25 30 41 22 4f 62 6e 61 6d 2b 3c 6b ser:%0A" Obnam+<k |
| 00080 79 6c 65 40 6b 79 6c 65 6d 61 6e 6e 61 2e 63 6f yle@kyle manna.co |
| 00090 6d 3e 22 25 30 41 32 30 34 38 2d 62 69 74 2b 52 m>"%0A20 48-bit+R |
| 000a0 53 41 2b 6b 65 79 2c 2b 49 44 2b 34 34 33 37 36 SA+key,+ ID+44376 |
| 000b0 35 35 44 2c 2b 63 72 65 61 74 65 64 2b 32 30 31 55D,+cre ated+201 |
| 000c0 32 2d 30 37 2d 30 38 25 30 41 2-07-08% 0A |
write(7, "\n", 1) = 1
| 00000 0a . |
read(7, "ERR 113 Server Resource Problem\n", 1002) = 32
| 00000 45 52 52 20 31 31 33 20 53 65 72 76 65 72 20 52 ERR 113 Server R |
| 00010 65 73 6f 75 72 63 65 20 50 72 6f 62 6c 65 6d 0a esource Problem. |
write(2, "gpg: ", 5) = 5
write(2, "problem with the agent - disabli"..., 45) = 45
write(7, "BYE", 3) = 3
| 00000 42 59 45 BYE |
write(7, "\n", 1) = 1
| 00000 0a . |
close(7) = 0
...
Note the “ERR 113 Server Resource Problem.” response from the gpg-agent. That seems odd doesn’t it?
Next lets compare a working strace (with DISPLAY set) and one without, diff and we see the following:
socket(PF_FILE, SOCK_STREAM, 0) = 7
connect(7, {sa_family=AF_FILE, path="/run/user/nitro/keyring-FUvSXm/gpg"}, 36) = 0
read(7, "OK your orders please\n", 1002) = 22
| 00000 4f 4b 20 79 6f 75 72 20 6f 72 64 65 72 73 20 70 OK your orders p |
| 00010 6c 65 61 73 65 0a lease. |
-ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffb7a69230) = -1 ENOTTY (Inappropriate ioctl for device)
+write(7, "OPTION display=:0.0", 19) = 19
+ | 00000 4f 50 54 49 4f 4e 20 64 69 73 70 6c 61 79 3d 3a OPTION d isplay=: |
+ | 00010 30 2e 30 0.0 |
+write(7, "\n", 1) = 1
+ | 00000 0a . |
+read(7, "OK \n", 1002) = 4
+ | 00000 4f 4b 20 0a OK . |
+ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff847e57e0) = -1 ENOTTY (Inappropriate ioctl for device)
write(7, "OPTION ttyname=/dev/tty", 23) = 23
| 00000 4f 50 54 49 4f 4e 20 74 74 79 6e 61 6d 65 3d 2f OPTION t tyname=/ |
| 00010 64 65 76 2f 74 74 79 dev/tty |
Clearly the working one passes a “OPTION display=:0.0” to the server. Why should the server care what the display is if the key is already unlocked and doesn’t need to pop-up a passphrase entry dialog?
Since I’m running Ubuntu 13.04 and that uses gnupg v3.6.3, lets look at the source code. In gkd-gpg-agent-ops.c we can see why it doesn’t work. We need to set $DISPLAY
correctly in-order for call->terminal_ok
to be set. Otherwise, if call->terminal_ok
isn’t set, it breaks like I’ve observed.
Solutions
This leaves me with a few options:
- Forge
export DISPLAY=:0.0
in my cron script to dodge this pointless “security” check - Patch the code so it isn’t silly
- Use gnupg-agent which doesn’t behave silly like this
In the interest of simplicity, I picked 1 and added one line to my backup script. And life goes on.
Part of me still wonders why this broke when I upgrade to Ubuntu 13.04, this should have affected earlier versions of Ubuntu looking at the change log for gkd-gpg-agent-ops.c.
Comments