summaryrefslogtreecommitdiff
path: root/src/monkeysphere-server
blob: db2f428e5a9377caa2628ee7966ec2bb03b8a7ab (plain)
  1. #!/bin/bash
  2. # monkeysphere-server: MonkeySphere server admin tool
  3. #
  4. # The monkeysphere scripts are written by:
  5. # Jameson Rollins <jrollins@fifthhorseman.net>
  6. #
  7. # They are Copyright 2008, and are all released under the GPL, version 3
  8. # or later.
  9. ########################################################################
  10. PGRM=$(basename $0)
  11. SHAREDIR=${SHAREDIR:-"/usr/share/monkeysphere"}
  12. export SHAREDIR
  13. . "${SHAREDIR}/common"
  14. # date in UTF format if needed
  15. DATE=$(date -u '+%FT%T')
  16. # unset some environment variables that could screw things up
  17. GREP_OPTIONS=
  18. # default return code
  19. ERR=0
  20. ########################################################################
  21. # FUNCTIONS
  22. ########################################################################
  23. usage() {
  24. cat <<EOF
  25. usage: $PGRM <subcommand> [args]
  26. MonkeySphere server admin tool.
  27. subcommands:
  28. update-users (u) [USER]... update users authorized_keys files
  29. gen-key (g) [HOSTNAME] generate gpg key for the server
  30. show-fingerprint (f) show server's host key fingerprint
  31. publish-key (p) publish server's host key to keyserver
  32. trust-key (t) KEYID [LEVEL] set owner trust for keyid
  33. help (h,?) this help
  34. EOF
  35. }
  36. # generate server gpg key
  37. gen_key() {
  38. local hostName
  39. hostName=${1:-$(hostname --fqdn)}
  40. service=${SERVICE:-"ssh"}
  41. userID="${service}://${hostName}"
  42. if gpg --list-key ="$userID" > /dev/null 2>&1 ; then
  43. failure "Key for '$userID' already exists"
  44. fi
  45. # set key defaults
  46. KEY_TYPE=${KEY_TYPE:-"RSA"}
  47. KEY_LENGTH=${KEY_LENGTH:-"2048"}
  48. KEY_USAGE=${KEY_USAGE:-"auth"}
  49. KEY_EXPIRE=${KEY_EXPIRE:-"0"}
  50. cat <<EOF
  51. Please specify how long the key should be valid.
  52. 0 = key does not expire
  53. <n> = key expires in n days
  54. <n>w = key expires in n weeks
  55. <n>m = key expires in n months
  56. <n>y = key expires in n years
  57. EOF
  58. read -p "Key is valid for? ($KEY_EXPIRE) " KEY_EXPIRE; KEY_EXPIRE=${KEY_EXPIRE:-"0"}
  59. # set key parameters
  60. keyParameters=$(cat <<EOF
  61. Key-Type: $KEY_TYPE
  62. Key-Length: $KEY_LENGTH
  63. Key-Usage: $KEY_USAGE
  64. Name-Real: $userID
  65. Expire-Date: $KEY_EXPIRE
  66. EOF
  67. )
  68. # add the revoker field if requested
  69. # FIXME: the "1:" below assumes that $REVOKER's key is an RSA key. why?
  70. # FIXME: why is this marked "sensitive"? how will this signature ever
  71. # be transmitted to the expected revoker?
  72. if [ "$REVOKER" ] ; then
  73. keyParameters="${keyParameters}"$(cat <<EOF
  74. Revoker: 1:$REVOKER sensitive
  75. EOF
  76. )
  77. fi
  78. echo "The following key parameters will be used:"
  79. echo "$keyParameters"
  80. read -p "Generate key? [Y|n]: " OK; OK=${OK:=Y}
  81. if [ ${OK/y/Y} != 'Y' ] ; then
  82. failure "aborting."
  83. fi
  84. # add commit command
  85. keyParameters="${keyParameters}"$(cat <<EOF
  86. %commit
  87. %echo done
  88. EOF
  89. )
  90. log "generating server key... "
  91. echo "$keyParameters" | gpg --batch --gen-key
  92. # output the server fingerprint
  93. fingerprint_server_key "=${userID}"
  94. # find the key fingerprint of the server primary key
  95. keyID=$(gpg --list-key --with-colons --with-fingerprint "=${userID}" | \
  96. grep '^fpr:' | head -1 | cut -d: -f10)
  97. # write the key to the file
  98. # NOTE: assumes that the primary key is the proper key to use
  99. (umask 077 && gpgsecret2ssh "$keyID" > "${MS_HOME}/ssh_host_rsa_key")
  100. log "Private SSH host key output to file: ${MS_HOME}/ssh_host_rsa_key"
  101. }
  102. # gpg output key fingerprint
  103. fingerprint_server_key() {
  104. local ID
  105. if [ -z "$1" ] ; then
  106. ID="$1"
  107. else
  108. ID="=ssh://$(hostname --fqdn)"
  109. fi
  110. gpg --fingerprint --list-secret-keys "$ID"
  111. }
  112. ########################################################################
  113. # MAIN
  114. ########################################################################
  115. COMMAND="$1"
  116. [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
  117. shift
  118. # set ms home directory
  119. MS_HOME=${MS_HOME:-"$ETC"}
  120. # load configuration file
  121. MS_CONF=${MS_CONF:-"$MS_HOME"/monkeysphere-server.conf}
  122. [ -e "$MS_CONF" ] && . "$MS_CONF"
  123. # set empty config variable with defaults
  124. GNUPGHOME=${GNUPGHOME:-"${MS_HOME}/gnupg"}
  125. KEYSERVER=${KEYSERVER:-"subkeys.pgp.net"}
  126. CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
  127. REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
  128. AUTHORIZED_USER_IDS=${AUTHORIZED_USER_IDS:-"%h/.config/monkeysphere/authorized_user_ids"}
  129. USER_CONTROLLED_AUTHORIZED_KEYS=${USER_CONTROLLED_AUTHORIZED_KEYS:-"%h/.ssh/authorized_keys"}
  130. export GNUPGHOME
  131. # make sure the monkeysphere home directory exists
  132. mkdir -p "${MS_HOME}/authorized_user_ids"
  133. # make sure gpg home exists with proper permissions
  134. mkdir -p -m 0700 "$GNUPGHOME"
  135. # make sure the authorized_keys directory exists
  136. mkdir -p "${CACHE}/authorized_keys"
  137. case $COMMAND in
  138. 'update-users'|'update-user'|'u')
  139. if [ "$1" ] ; then
  140. # get users from command line
  141. unames="$@"
  142. else
  143. # or just look at all users if none specified
  144. unames=$(getent passwd | cut -d: -f1)
  145. fi
  146. # loop over users
  147. for uname in $unames ; do
  148. MODE="authorized_keys"
  149. # check all specified users exist
  150. if ! getent passwd "$uname" >/dev/null ; then
  151. error "----- unknown user '$uname' -----"
  152. continue
  153. fi
  154. log "----- user: $uname -----"
  155. # set authorized_user_ids variable, translating ssh-style
  156. # path variables
  157. authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
  158. # temporary authorized_keys file
  159. AUTHORIZED_KEYS=$(mktemp)
  160. # process authorized_user_ids file
  161. if [ -s "$authorizedUserIDs" ] ; then
  162. log "processing authorized_user_ids file..."
  163. process_authorized_user_ids "$authorizedUserIDs"
  164. fi
  165. # add user-controlled authorized_keys file path if specified
  166. if [ "$USER_CONTROLLED_AUTHORIZED_KEYS" != '-' ] ; then
  167. userAuthorizedKeys=$(translate_ssh_variables "$uname" "$USER_CONTROLLED_AUTHORIZED_KEYS")
  168. if [ -s "$userAuthorizedKeys" ] ; then
  169. log -n "adding user's authorized_keys file... "
  170. cat "$userAuthorizedKeys" >> "$AUTHORIZED_KEYS"
  171. loge "done."
  172. fi
  173. fi
  174. # if the resulting authorized_keys file is not empty
  175. if [ -s "$AUTHORIZED_KEYS" ] ; then
  176. # openssh appears to check the contents of the
  177. # authorized_keys file as the user in question, so the
  178. # file must be readable by that user at least.
  179. # FIXME: is there a better way to do this?
  180. chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
  181. chmod g+r "$AUTHORIZED_KEYS"
  182. # move the temp authorized_keys file into place
  183. mv -f "$AUTHORIZED_KEYS" "${CACHE}/authorized_keys/${uname}"
  184. log "authorized_keys file updated."
  185. # else destroy it
  186. else
  187. rm -f "$AUTHORIZED_KEYS"
  188. fi
  189. done
  190. ;;
  191. 'gen-key'|'g')
  192. gen_key "$1"
  193. ;;
  194. 'show-fingerprint'|'f')
  195. fingerprint_server_key "$@"
  196. ;;
  197. 'publish-key'|'p')
  198. publish_server_key
  199. ;;
  200. 'trust-key'|'trust-key'|'t')
  201. trust_key "$@"
  202. ;;
  203. 'help'|'h'|'?')
  204. usage
  205. ;;
  206. *)
  207. failure "Unknown command: '$COMMAND'
  208. Type '$PGRM help' for usage."
  209. ;;
  210. esac
  211. exit "$ERR"