summaryrefslogtreecommitdiff
path: root/src/monkeysphere-host
blob: f79c2bb064714f7c40b1cf65230b2f866af7675c (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. # FIXME: this seems much less than ideal, with all this temp keyring
  100. # stuff. is there a way we can do this without having to create temp
  101. # files?
  102. load_fingerprint() {
  103. if [ -f "$HOST_KEY_PUB_GPG" ] ; then
  104. HOST_FINGERPRINT=$( \
  105. (FUBAR=$(mktemp -d) && export GNUPGHOME="$FUBAR" \
  106. && gpg --quiet --import \
  107. && gpg --quiet --list-keys --with-colons --with-fingerprint \
  108. && rm -rf "$FUBAR") <"$HOST_KEY_PUB_GPG" \
  109. | grep '^fpr:' | cut -d: -f10 )
  110. else
  111. HOST_FINGERPRINT=
  112. fi
  113. }
  114. # load the host fingerprint into the fingerprint variable, using the
  115. # gpg host secret key
  116. load_fingerprint_secret() {
  117. HOST_FINGERPRINT=$( \
  118. gpg_host --quiet --list-secret-key \
  119. --with-colons --with-fingerprint \
  120. | grep '^fpr:' | cut -d: -f10 )
  121. }
  122. # output host key ssh fingerprint
  123. load_ssh_fingerprint() {
  124. [ -f "$HOST_KEY_PUB" ] || return 0
  125. HOST_FINGERPRINT_SSH=$(ssh-keygen -l -f "$HOST_KEY_PUB" \
  126. | awk '{ print $1, $2, $4 }')
  127. }
  128. # fail if host key present
  129. check_host_key() {
  130. [ -z "$HOST_FINGERPRINT" ] \
  131. || failure "An OpenPGP host key already exists."
  132. }
  133. # fail if host key not present
  134. check_host_no_key() {
  135. [ "$HOST_FINGERPRINT" ] \
  136. || failure "You don't appear to have a Monkeysphere host key on this server. Please run 'monkeysphere-host expert import-key' first."
  137. }
  138. # output the index of a user ID on the host key
  139. # return 1 if user ID not found
  140. find_host_userid() {
  141. local userID="$1"
  142. local tmpuidMatch
  143. local line
  144. # match to only ultimately trusted user IDs
  145. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  146. # find the index of the requsted user ID
  147. # NOTE: this is based on circumstantial evidence that the order of
  148. # this output is the appropriate index
  149. line=$(gpg_host_list | egrep '^(uid|uat):' | cut -f2,10 -d: | \
  150. grep -n -x -F "$tmpuidMatch" 2>/dev/null)
  151. if [ "$line" ] ; then
  152. echo ${line%%:*}
  153. return 0
  154. else
  155. return 1
  156. fi
  157. }
  158. # show info about the host key
  159. show_key() {
  160. gpg_host --fingerprint --list-key --list-options show-unusable-uids \
  161. "0x${HOST_FINGERPRINT}!" 2>/dev/null
  162. # FIXME: make sure expiration date is shown
  163. echo "OpenPGP fingerprint: $HOST_FINGERPRINT"
  164. load_ssh_fingerprint
  165. if [ "$HOST_FINGERPRINT_SSH" ] ; then
  166. echo "ssh fingerprint: $HOST_FINGERPRINT_SSH"
  167. else
  168. log error "SSH host key not found."
  169. fi
  170. # FIXME: other relevant key parameters?
  171. }
  172. ########################################################################
  173. # MAIN
  174. ########################################################################
  175. # unset variables that should be defined only in config file
  176. unset KEYSERVER
  177. unset MONKEYSPHERE_USER
  178. # load configuration file
  179. [ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] && . "$MONKEYSPHERE_HOST_CONFIG"
  180. # set empty config variable with ones from the environment, or with
  181. # defaults
  182. LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
  183. KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
  184. AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
  185. RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
  186. MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
  187. # other variables
  188. CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
  189. GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"}
  190. # export variables needed in su invocation
  191. export DATE
  192. export MODE
  193. export LOG_LEVEL
  194. export MONKEYSPHERE_USER
  195. export KEYSERVER
  196. export GNUPGHOME_HOST
  197. export GNUPGHOME
  198. export HOST_FINGERPRINT=
  199. export HOST_FINGERPRINT_SSH=
  200. # get subcommand
  201. COMMAND="$1"
  202. [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
  203. shift
  204. case $COMMAND in
  205. 'show-key'|'show'|'s')
  206. load_fingerprint
  207. check_host_no_key
  208. show_key
  209. ;;
  210. 'set-expire'|'extend-key'|'e')
  211. load_fingerprint
  212. check_host_no_key
  213. source "${MHSHAREDIR}/set_expire"
  214. set_expire "$@"
  215. ;;
  216. 'add-hostname'|'add-name'|'n+')
  217. load_fingerprint
  218. check_host_no_key
  219. source "${MHSHAREDIR}/add_hostname"
  220. add_hostname "$@"
  221. ;;
  222. 'revoke-hostname'|'revoke-name'|'n-')
  223. load_fingerprint
  224. check_host_no_key
  225. source "${MHSHAREDIR}/revoke_hostname"
  226. revoke_hostname "$@"
  227. ;;
  228. 'add-revoker'|'o')
  229. load_fingerprint
  230. check_host_no_key
  231. source "${MHSHAREDIR}/add_revoker"
  232. add_revoker "$@"
  233. ;;
  234. 'revoke-key'|'r')
  235. load_fingerprint
  236. check_host_no_key
  237. source "${MHSHAREDIR}/revoke_key"
  238. revoke_key "$@"
  239. ;;
  240. 'publish-key'|'publish'|'p')
  241. load_fingerprint
  242. check_host_no_key
  243. source "${MHSHAREDIR}/publish_key"
  244. publish_key
  245. ;;
  246. 'expert')
  247. SUBCOMMAND="$1"
  248. shift
  249. case "$SUBCOMMAND" in
  250. 'help'|'h'|'?')
  251. cat <<EOF
  252. usage: $PGRM expert <subcommand> [options] [args]
  253. expert subcommands:
  254. import-key (i) [NAME[:PORT]] import existing ssh key to gpg
  255. gen-key (g) [NAME[:PORT]] generate gpg key for the host
  256. --length (-l) BITS key length in bits (2048)
  257. diagnostics (d) monkeysphere host status
  258. EOF
  259. ;;
  260. 'import-key'|'i')
  261. load_fingerprint
  262. check_host_key
  263. source "${MHSHAREDIR}/import_key"
  264. import_key "$@"
  265. ;;
  266. 'gen-key'|'g')
  267. load_fingerprint
  268. check_host_key
  269. source "${MHSHAREDIR}/gen_key"
  270. gen_key "$@"
  271. ;;
  272. 'diagnostics'|'d')
  273. source "${MHSHAREDIR}/diagnostics"
  274. diagnostics
  275. ;;
  276. *)
  277. failure "Unknown expert subcommand: '$COMMAND'
  278. Type '$PGRM help' for usage."
  279. ;;
  280. esac
  281. ;;
  282. 'version'|'v')
  283. echo "$VERSION"
  284. ;;
  285. '--help'|'help'|'-h'|'h'|'?')
  286. usage
  287. ;;
  288. *)
  289. failure "Unknown command: '$COMMAND'
  290. Type '$PGRM help' for usage."
  291. ;;
  292. esac
  293. exit "$RETURN"