summaryrefslogtreecommitdiff
path: root/src/share/m/subkey_to_ssh_agent
blob: 79291b11d58f55a4e8745493e2f5d04c30f6007b (plain)
  1. # -*-shell-script-*-
  2. # This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
  3. # Monkeysphere subkey-to-ssh-agent subcommand
  4. #
  5. # The monkeysphere scripts are written by:
  6. # Jameson Rollins <jrollins@finestructure.net>
  7. # Jamie McClelland <jm@mayfirst.org>
  8. # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
  9. #
  10. # They are Copyright 2008-2009, and are all released under the GPL,
  11. # version 3 or later.
  12. # try to add all authentication subkeys to the agent
  13. # FIXME: what if you only want to add one authentication subkey to the
  14. # agent?
  15. subkey_to_ssh_agent() {
  16. local sshaddresponse=0
  17. local secretkeys
  18. local authsubkeys
  19. local workingdir
  20. local keysuccess=0
  21. local subkey
  22. local publine
  23. local kname
  24. # if there's no agent running, don't bother:
  25. if [ -z "$SSH_AUTH_SOCK" ] || ! type ssh-add >/dev/null ; then
  26. failure "No ssh-agent available."
  27. fi
  28. # and if it looks like it's running, but we can't actually talk to
  29. # it, bail out:
  30. ssh-add -l >/dev/null || sshaddresponse="$?"
  31. if [ "$sshaddresponse" = "2" ]; then
  32. failure "Could not connect to ssh-agent"
  33. fi
  34. # if the MONKEYSPHERE_SUBKEYS_FOR_AGENT variable is set, use the
  35. # keys specified there
  36. if [ "$MONKEYSPHERE_SUBKEYS_FOR_AGENT" ] ; then
  37. authsubkeys="$MONKEYSPHERE_SUBKEYS_FOR_AGENT"
  38. # otherwise find all authentication-capable subkeys and use those
  39. else
  40. # get list of secret keys
  41. # (to work around bug https://bugs.g10code.com/gnupg/issue945):
  42. secretkeys=$(gpg_user --list-secret-keys --with-colons \
  43. --fingerprint | \
  44. grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
  45. if [ -z "$secretkeys" ]; then
  46. failure "You have no secret keys in your keyring!
  47. You might want to run 'gpg --gen-key'."
  48. fi
  49. authsubkeys=$(gpg_user --list-secret-keys --with-colons \
  50. --fingerprint --fingerprint $secretkeys | \
  51. cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \
  52. grep '^fpr::' | cut -f3 -d: | sort -u)
  53. if [ -z "$authsubkeys" ]; then
  54. failure "no authentication-capable subkeys available.
  55. You might want to run 'monkeysphere gen-subkey'."
  56. fi
  57. fi
  58. workingdir=$(msmktempdir)
  59. trap "rm -rf $workingdir" EXIT
  60. umask 077
  61. mkfifo "$workingdir/passphrase"
  62. # FIXME: we're currently allowing any other options to get passed
  63. # through to ssh-add. should we limit it to known ones? For
  64. # example: -d or -c and/or -t <lifetime>
  65. for subkey in $authsubkeys; do
  66. # test that the subkey has proper capability
  67. capability=$(gpg_user --list-secret-keys --with-colons \
  68. --fingerprint --fingerprint "0x${subkey}!" \
  69. | egrep -B 1 "^fpr:::::::::${subkey}:$" | grep "^ssb:" | cut -d: -f12)
  70. if ! check_capability "$capability" 'a' ; then
  71. log error "Did not find authentication-capable subkey with key ID '$subkey'."
  72. continue
  73. fi
  74. # choose a label by which this key will be known in the agent:
  75. # we are labelling the key by User ID instead of by
  76. # fingerprint, but filtering out all / characters to make sure
  77. # the filename is legit.
  78. # FIXME: this assumes that the first listed uid is the primary
  79. # UID. does gpg guarantee that? is there some better way to
  80. # get this info?
  81. primaryuid=$(gpg_user --with-colons --list-key "0x${subkey}!" | grep '^uid:' | head -n1 | cut -f10 -d: | tr -d /)
  82. #kname="[monkeysphere] $primaryuid"
  83. kname="$primaryuid"
  84. if [ "$1" = '-d' ]; then
  85. # we're removing the subkey:
  86. gpg_user --export --no-armor "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
  87. (cd "$workingdir" && ssh-add -d "$kname") || keysuccess="$?"
  88. else
  89. # we're adding the subkey:
  90. mkfifo "$workingdir/$kname"
  91. gpg_user --passphrase-fd 3 3<"$workingdir/passphrase" \
  92. --export-options export-reset-subkey-passwd,export-minimal,no-export-attributes \
  93. --export-secret-subkeys --no-armor "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname" &
  94. (cd "$workingdir" && DISPLAY=nosuchdisplay SSH_ASKPASS=/bin/false ssh-add "$@" "$kname" </dev/null )&
  95. passphrase_prompt "Enter passphrase for key $kname: " "$workingdir/passphrase"
  96. wait %2 || keysuccess="$?"
  97. fi
  98. rm -f "$workingdir/$kname"
  99. done
  100. trap - EXIT
  101. rm -rf "$workingdir"
  102. # FIXME: sort out the return values: we're just returning the
  103. # failure code of the last authentication subkey which fails.
  104. # what if more than one authentication subkey fails?
  105. return "$keysuccess"
  106. }