summaryrefslogtreecommitdiff
path: root/src/monkeysphere-host
blob: 4aab995950e89ed1323275431594023810503da8 (plain)
  1. #!/usr/bin/env bash
  2. # monkeysphere-host: Monkeysphere host admin tool
  3. #
  4. # The monkeysphere scripts are written by:
  5. # Jameson Rollins <jrollins@finestructure.net>
  6. # Jamie McClelland <jm@mayfirst.org>
  7. # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
  8. # Micah Anderson <micah@riseup.net>
  9. #
  10. # They are Copyright 2008-2009, and are all released under the GPL,
  11. # version 3 or later.
  12. ########################################################################
  13. set -e
  14. # set the pipefail option so pipelines fail on first command failure
  15. set -o pipefail
  16. PGRM=$(basename $0)
  17. SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"}
  18. export SYSSHAREDIR
  19. . "${SYSSHAREDIR}/common" || exit 1
  20. SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
  21. export SYSDATADIR
  22. # sharedir for host functions
  23. MHSHAREDIR="${SYSSHAREDIR}/mh"
  24. # datadir for host functions
  25. MHDATADIR="${SYSDATADIR}/host"
  26. # host pub key files
  27. HOST_KEY_PUB="${SYSDATADIR}/ssh_host_rsa_key.pub"
  28. HOST_KEY_PUB_GPG="${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
  29. # UTC date in ISO 8601 format if needed
  30. DATE=$(date -u '+%FT%T')
  31. # unset some environment variables that could screw things up
  32. unset GREP_OPTIONS
  33. # default return code
  34. RETURN=0
  35. ########################################################################
  36. # FUNCTIONS
  37. ########################################################################
  38. usage() {
  39. cat <<EOF >&2
  40. usage: $PGRM <subcommand> [options] [args]
  41. Monkeysphere host admin tool.
  42. subcommands:
  43. show-key (s) output all host key information
  44. set-expire (e) EXPIRE set host key expiration
  45. add-hostname (n+) NAME[:PORT] add hostname user ID to host key
  46. revoke-hostname (n-) NAME[:PORT] revoke hostname user ID
  47. add-revoker (o) FINGERPRINT add a revoker to the host key
  48. revoke-key (r) revoke host key
  49. publish-key (p) publish host key to keyserver
  50. expert <expert-subcommand> run expert command
  51. expert help expert command help
  52. version (v) show version number
  53. help (h,?) this help
  54. EOF
  55. }
  56. # function to interact with the gpg keyring
  57. gpg_host() {
  58. GNUPGHOME="$GNUPGHOME_HOST" gpg "$@"
  59. }
  60. # command to list the info about the host key, in colon format
  61. gpg_host_list() {
  62. gpg_host --list-keys --with-colons --fixed-list-mode \
  63. --with-fingerprint --with-fingerprint \
  64. "0x${HOST_FINGERPRINT}!"
  65. }
  66. # command for edit key scripts, takes scripts on stdin
  67. gpg_host_edit() {
  68. gpg_host --quiet --command-fd 0 --edit-key \
  69. "0x${HOST_FINGERPRINT}!" "$@"
  70. }
  71. # export the host key to stdout
  72. gpg_host_export() {
  73. gpg_host --export --armor --export-options export-minimal \
  74. "0x${HOST_FINGERPRINT}!"
  75. }
  76. # export the host secret key to the monkeysphere ssh sec key file
  77. # NOTE: assumes that the primary key is the proper key to use
  78. create_ssh_sec_file() {
  79. log debug "creating ssh secret key file..."
  80. (umask 077 && \
  81. gpg_host --export-secret-key "$HOST_FINGERPRINT" | \
  82. openpgp2ssh "$HOST_FINGERPRINT" > "${MHDATADIR}/ssh_host_rsa_key")
  83. log info "SSH host secret key file: ${MHDATADIR}/ssh_host_rsa_key"
  84. }
  85. # export the host public key to the monkeysphere ssh pub key file
  86. create_ssh_pub_file() {
  87. log debug "creating ssh public key file..."
  88. ssh-keygen -y -f "${MHDATADIR}/ssh_host_rsa_key" > "$HOST_KEY_PUB"
  89. log info "SSH host public key file: $HOST_KEY_PUB"
  90. }
  91. # export the host public key to the monkeysphere gpg pub key file
  92. create_gpg_pub_file() {
  93. log debug "creating openpgp public key file..."
  94. gpg_host_export > "$HOST_KEY_PUB_GPG"
  95. log info "GPG host public key file: $HOST_KEY_PUB_GPG"
  96. }
  97. # load the host fingerprint into the fingerprint variable, using the
  98. # export gpg pub key file
  99. load_fingerprint() {
  100. if [ -f "$HOST_KEY_PUB_GPG" ] ; then
  101. HOST_FINGERPRINT=$( \
  102. (FUBAR=$(mktemp -d) && export GNUPGHOME="$FUBAR" \
  103. && gpg --quiet --import \
  104. && gpg --quiet --list-keys --with-colons --with-fingerprint \
  105. && rm -rf "$FUBAR") <"$HOST_KEY_PUB_GPG" \
  106. | grep '^fpr:' | cut -d: -f10 )
  107. else
  108. HOST_FINGERPRINT=
  109. fi
  110. }
  111. # load the host fingerprint into the fingerprint variable, using the
  112. # gpg host secret key
  113. load_fingerprint_secret() {
  114. HOST_FINGERPRINT=$( \
  115. gpg_host --quiet --list-secret-key \
  116. --with-colons --with-fingerprint \
  117. | grep '^fpr:' | cut -d: -f10 )
  118. }
  119. # output host key ssh fingerprint
  120. load_ssh_fingerprint() {
  121. [ -f "$HOST_KEY_PUB" ] || return 0
  122. HOST_FINGERPRINT_SSH=$(ssh-keygen -l -f "$HOST_KEY_PUB" \
  123. | awk '{ print $1, $2, $4 }')
  124. }
  125. # fail if host key present
  126. check_host_key() {
  127. [ -z "$HOST_FINGERPRINT" ] \
  128. || failure "An OpenPGP host key already exists."
  129. }
  130. # fail if host key not present
  131. check_host_no_key() {
  132. [ "$HOST_FINGERPRINT" ] \
  133. || failure "You don't appear to have a Monkeysphere host key on this server. Please run 'monkeysphere-host expert import-key' first."
  134. }
  135. # output the index of a user ID on the host key
  136. # return 1 if user ID not found
  137. find_host_userid() {
  138. local userID="$1"
  139. local tmpuidMatch
  140. local line
  141. # match to only ultimately trusted user IDs
  142. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  143. # find the index of the requsted user ID
  144. # NOTE: this is based on circumstantial evidence that the order of
  145. # this output is the appropriate index
  146. line=$(gpg_host_list | egrep '^(uid|uat):' | cut -f2,10 -d: | \
  147. grep -n -x -F "$tmpuidMatch" 2>/dev/null)
  148. if [ "$line" ] ; then
  149. echo ${line%%:*}
  150. return 0
  151. else
  152. return 1
  153. fi
  154. }
  155. # show info about the host key
  156. show_key() {
  157. gpg_host --fingerprint --list-key --list-options show-unusable-uids \
  158. "0x${HOST_FINGERPRINT}!" 2>/dev/null
  159. # FIXME: make sure expiration date is shown
  160. echo "OpenPGP fingerprint: $HOST_FINGERPRINT"
  161. load_ssh_fingerprint
  162. if [ "$HOST_FINGERPRINT_SSH" ] ; then
  163. echo "ssh fingerprint: $HOST_FINGERPRINT_SSH"
  164. else
  165. log error "SSH host key not found."
  166. fi
  167. # FIXME: other relevant key parameters?
  168. }
  169. ########################################################################
  170. # MAIN
  171. ########################################################################
  172. # unset variables that should be defined only in config file
  173. unset KEYSERVER
  174. unset MONKEYSPHERE_USER
  175. # load configuration file
  176. [ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] && . "$MONKEYSPHERE_HOST_CONFIG"
  177. # set empty config variable with ones from the environment, or with
  178. # defaults
  179. LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
  180. KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
  181. AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
  182. RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
  183. MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
  184. # other variables
  185. CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
  186. GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"}
  187. # export variables needed in su invocation
  188. export DATE
  189. export MODE
  190. export LOG_LEVEL
  191. export MONKEYSPHERE_USER
  192. export KEYSERVER
  193. export GNUPGHOME_HOST
  194. export GNUPGHOME
  195. export HOST_FINGERPRINT=
  196. export HOST_FINGERPRINT_SSH=
  197. # get subcommand
  198. COMMAND="$1"
  199. [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
  200. shift
  201. case $COMMAND in
  202. 'show-key'|'show'|'s')
  203. load_fingerprint
  204. check_host_no_key
  205. show_key
  206. ;;
  207. 'set-expire'|'extend-key'|'e')
  208. load_fingerprint
  209. check_host_no_key
  210. source "${MHSHAREDIR}/set_expire"
  211. set_expire "$@"
  212. ;;
  213. 'add-hostname'|'add-name'|'n+')
  214. load_fingerprint
  215. check_host_no_key
  216. source "${MHSHAREDIR}/add_hostname"
  217. add_hostname "$@"
  218. ;;
  219. 'revoke-hostname'|'revoke-name'|'n-')
  220. load_fingerprint
  221. check_host_no_key
  222. source "${MHSHAREDIR}/revoke_hostname"
  223. revoke_hostname "$@"
  224. ;;
  225. 'add-revoker'|'o')
  226. load_fingerprint
  227. check_host_no_key
  228. source "${MHSHAREDIR}/add_revoker"
  229. add_revoker "$@"
  230. ;;
  231. 'revoke-key'|'r')
  232. load_fingerprint
  233. check_host_no_key
  234. source "${MHSHAREDIR}/revoke_key"
  235. revoke_key "$@"
  236. ;;
  237. 'publish-key'|'publish'|'p')
  238. load_fingerprint
  239. check_host_no_key
  240. source "${MHSHAREDIR}/publish_key"
  241. publish_key
  242. ;;
  243. 'expert')
  244. SUBCOMMAND="$1"
  245. shift
  246. case "$SUBCOMMAND" in
  247. 'help'|'h'|'?')
  248. cat <<EOF
  249. usage: $PGRM expert <subcommand> [options] [args]
  250. expert subcommands:
  251. import-key (i) [NAME[:PORT]] import existing ssh key to gpg
  252. gen-key (g) [NAME[:PORT]] generate gpg key for the host
  253. --length (-l) BITS key length in bits (2048)
  254. diagnostics (d) monkeysphere host status
  255. EOF
  256. ;;
  257. 'import-key'|'i')
  258. load_fingerprint
  259. check_host_key
  260. source "${MHSHAREDIR}/import_key"
  261. import_key "$@"
  262. ;;
  263. 'gen-key'|'g')
  264. load_fingerprint
  265. check_host_key
  266. source "${MHSHAREDIR}/gen_key"
  267. gen_key "$@"
  268. ;;
  269. 'diagnostics'|'d')
  270. source "${MHSHAREDIR}/diagnostics"
  271. diagnostics
  272. ;;
  273. *)
  274. failure "Unknown expert subcommand: '$COMMAND'
  275. Type '$PGRM help' for usage."
  276. ;;
  277. esac
  278. ;;
  279. 'version'|'v')
  280. echo "$VERSION"
  281. ;;
  282. '--help'|'help'|'-h'|'h'|'?')
  283. usage
  284. ;;
  285. *)
  286. failure "Unknown command: '$COMMAND'
  287. Type '$PGRM help' for usage."
  288. ;;
  289. esac
  290. exit "$RETURN"