add a gpg_user function in monkeysphere to add some gpg quieting
[monkeysphere.git] / src / share / m / subkey_to_ssh_agent
1 # -*-shell-script-*-
2 # This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
3
4 # Monkeysphere subkey-to-ssh-agent subcommand
5 #
6 # The monkeysphere scripts are written by:
7 # Jameson Rollins <jrollins@finestructure.net>
8 # Jamie McClelland <jm@mayfirst.org>
9 # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
10 #
11 # They are Copyright 2008-2009, and are all released under the GPL,
12 # version 3 or later.
13
14 # try to add all authentication subkeys to the agent
15
16 subkey_to_ssh_agent() {
17     local sshaddresponse
18     local secretkeys
19     local authsubkeys
20     local workingdir
21     local keysuccess
22     local subkey
23     local publine
24     local kname
25
26     if ! test_gnu_dummy_s2k_extension ; then
27         failure "Your version of GnuTLS does not seem capable of using with gpg's exported subkeys.
28 You may want to consider patching or upgrading to GnuTLS 2.6 or later.
29
30 For more details, see:
31  http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html"
32     fi
33
34     # if there's no agent running, don't bother:
35     if [ -z "$SSH_AUTH_SOCK" ] || ! which ssh-add >/dev/null ; then
36         failure "No ssh-agent available."
37     fi
38
39     # and if it looks like it's running, but we can't actually talk to
40     # it, bail out:
41     ssh-add -l >/dev/null
42     sshaddresponse="$?"
43     if [ "$sshaddresponse" = "2" ]; then
44         failure "Could not connect to ssh-agent"
45     fi
46     
47     # get list of secret keys (to work around bug
48     # https://bugs.g10code.com/gnupg/issue945):
49     secretkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
50         --fingerprint | \
51         grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
52
53     if [ -z "$secretkeys" ]; then
54         failure "You have no secret keys in your keyring!
55 You might want to run 'gpg --gen-key'."
56     fi
57     
58     authsubkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
59         --fingerprint --fingerprint $secretkeys | \
60         cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \
61         grep '^fpr::' | cut -f3 -d: | sort -u)
62
63     if [ -z "$authsubkeys" ]; then
64         failure "no authentication-capable subkeys available.
65 You might want to 'monkeysphere gen-subkey'"
66     fi
67
68     workingdir=$(msmktempdir)
69     trap "rm -rf $workingdir" EXIT
70     umask 077
71     mkfifo "$workingdir/passphrase"
72     keysuccess=1
73
74     # FIXME: we're currently allowing any other options to get passed
75     # through to ssh-add.  should we limit it to known ones?  For
76     # example: -d or -c and/or -t <lifetime> 
77
78     for subkey in $authsubkeys; do 
79         # choose a label by which this key will be known in the agent:
80         # we are labelling the key by User ID instead of by
81         # fingerprint, but filtering out all / characters to make sure
82         # the filename is legit.
83
84         primaryuid=$(gpg_user --with-colons --list-key "0x${subkey}!" | grep '^pub:' | cut -f10 -d: | tr -d /)
85
86         #kname="[monkeysphere] $primaryuid"
87         kname="$primaryuid"
88
89         if [ "$1" = '-d' ]; then
90             # we're removing the subkey:
91             gpg_user --export "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
92             (cd "$workingdir" && ssh-add -d "$kname")
93         else
94             # we're adding the subkey:
95             mkfifo "$workingdir/$kname"
96             gpg_user --passphrase-fd 3 3<"$workingdir/passphrase" \
97                 --export-options export-reset-subkey-passwd,export-minimal,no-export-attributes \
98                 --export-secret-subkeys "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname" &
99             (cd "$workingdir" && DISPLAY=nosuchdisplay SSH_ASKPASS=/bin/false ssh-add "$@" "$kname" </dev/null )&
100
101             passphrase_prompt "Enter passphrase for key $kname: " "$workingdir/passphrase"
102             wait %2
103         fi
104         keysuccess="$?"
105
106         rm -f "$workingdir/$kname"
107     done
108
109     trap - EXIT
110     rm -rf "$workingdir"
111
112     # FIXME: sort out the return values: we're just returning the
113     # success or failure of the final authentication subkey in this
114     # case.  What if earlier ones failed?
115     exit "$keysuccess"
116 }