summaryrefslogtreecommitdiff
path: root/src/monkeysphere-host
blob: 9eed3acb61382f6177e0afae7e496f0e71ebb7eb (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@fifthhorseman.net>
  6. # Jamie McClelland <jm@mayfirst.org>
  7. # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
  8. #
  9. # They are Copyright 2008, and are all released under the GPL, version 3
  10. # or later.
  11. ########################################################################
  12. PGRM=$(basename $0)
  13. SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"}
  14. export SYSSHAREDIR
  15. . "${SYSSHAREDIR}/common" || exit 1
  16. SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere/host"}
  17. export SYSDATADIR
  18. # monkeysphere temp directory, in sysdatadir to enable atomic moves of
  19. # authorized_keys files
  20. MSTMPDIR="${SYSDATADIR}/tmp"
  21. export MSTMPDIR
  22. # UTC date in ISO 8601 format if needed
  23. DATE=$(date -u '+%FT%T')
  24. # unset some environment variables that could screw things up
  25. unset GREP_OPTIONS
  26. # default return code
  27. RETURN=0
  28. ########################################################################
  29. # FUNCTIONS
  30. ########################################################################
  31. usage() {
  32. cat <<EOF >&2
  33. usage: $PGRM <subcommand> [options] [args]
  34. Monkeysphere host admin tool.
  35. subcommands:
  36. show-key (s) output all host key information
  37. extend-key (e) EXPIRE extend host key expiration
  38. add-hostname (n+) NAME[:PORT] add hostname user ID to host key
  39. revoke-hostname (n-) NAME[:PORT] revoke hostname user ID
  40. add-revoker (o) FINGERPRINT add a revoker to the host key
  41. revoke-key (r) revoke host key
  42. publish-key (p) publish server host key to keyserver
  43. expert
  44. import-key (i) import existing ssh key to gpg
  45. --hostname (-h) NAME[:PORT] hostname for key user ID
  46. --keyfile (-f) FILE key file to import
  47. --expire (-e) EXPIRE date to expire
  48. gen-key (g) generate gpg key for the host
  49. --hostname (-h) NAME[:PORT] hostname for key user ID
  50. --length (-l) BITS key length in bits (2048)
  51. --expire (-e) EXPIRE date to expire
  52. --revoker (-r) FINGERPRINT add a revoker
  53. diagnostics (d) monkeysphere host status
  54. version (v) show version number
  55. help (h,?) this help
  56. EOF
  57. }
  58. # function to run command as monkeysphere user
  59. su_monkeysphere_user() {
  60. # if the current user is the monkeysphere user, then just eval
  61. # command
  62. if [ $(id -un) = "$MONKEYSPHERE_USER" ] ; then
  63. eval "$@"
  64. # otherwise su command as monkeysphere user
  65. else
  66. su "$MONKEYSPHERE_USER" -c "$@"
  67. fi
  68. }
  69. # function to interact with the host gnupg keyring
  70. gpg_host() {
  71. local returnCode
  72. GNUPGHOME="$GNUPGHOME_HOST"
  73. export GNUPGHOME
  74. # NOTE: we supress this warning because we need the monkeysphere
  75. # user to be able to read the host pubring. we realize this might
  76. # be problematic, but it's the simplest solution, without too much
  77. # loss of security.
  78. gpg --no-permission-warning "$@"
  79. returnCode="$?"
  80. # always reset the permissions on the host pubring so that the
  81. # monkeysphere user can read the trust signatures
  82. chgrp "$MONKEYSPHERE_USER" "${GNUPGHOME_HOST}/pubring.gpg"
  83. chmod g+r "${GNUPGHOME_HOST}/pubring.gpg"
  84. return "$returnCode"
  85. }
  86. # check if user is root
  87. is_root() {
  88. [ $(id -u 2>/dev/null) = '0' ]
  89. }
  90. # check that user is root, for functions that require root access
  91. check_user() {
  92. is_root || failure "You must be root to run this command."
  93. }
  94. # output just key fingerprint
  95. fingerprint_server_key() {
  96. # set the pipefail option so functions fails if can't read sec key
  97. set -o pipefail
  98. gpg_host --list-secret-keys --fingerprint \
  99. --with-colons --fixed-list-mode 2> /dev/null | \
  100. grep '^fpr:' | head -1 | cut -d: -f10 2>/dev/null
  101. }
  102. # function to check for host secret key
  103. check_host_keyring() {
  104. fingerprint_server_key >/dev/null \
  105. || failure "You don't appear to have a Monkeysphere host key on this server. Please run 'monkeysphere-server gen-key' first."
  106. }
  107. # output key information
  108. show_server_key() {
  109. local fingerprintPGP
  110. local fingerprintSSH
  111. local ret=0
  112. # FIXME: you shouldn't have to be root to see the host key fingerprint
  113. if is_root ; then
  114. check_host_keyring
  115. fingerprintPGP=$(fingerprint_server_key)
  116. gpg_authentication "--fingerprint --list-key --list-options show-unusable-uids $fingerprintPGP" 2>/dev/null
  117. echo "OpenPGP fingerprint: $fingerprintPGP"
  118. else
  119. log info "You must be root to see host OpenPGP fingerprint."
  120. ret='1'
  121. fi
  122. if [ -f "${SYSDATADIR}/ssh_host_rsa_key.pub" ] ; then
  123. fingerprintSSH=$(ssh-keygen -l -f "${SYSDATADIR}/ssh_host_rsa_key.pub" | \
  124. awk '{ print $1, $2, $4 }')
  125. echo "ssh fingerprint: $fingerprintSSH"
  126. else
  127. log info "SSH host key not found."
  128. ret='1'
  129. fi
  130. return $ret
  131. }
  132. # import an existing ssh key to a gpg key
  133. import_key() {
  134. local hostName=$(hostname -f)
  135. local keyFile="/etc/ssh/ssh_host_rsa_key"
  136. local keyExpire
  137. local userID
  138. # check for presense of secret key
  139. # FIXME: is this the proper test to be doing here?
  140. fingerprint_server_key >/dev/null \
  141. && failure "An OpenPGP host key already exists."
  142. # get options
  143. while true ; do
  144. case "$1" in
  145. -h|--hostname)
  146. hostName="$2"
  147. shift 2
  148. ;;
  149. -f|--keyfile)
  150. keyFile="$2"
  151. shift 2
  152. ;;
  153. -e|--expire)
  154. keyExpire="$2"
  155. shift 2
  156. ;;
  157. *)
  158. if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
  159. failure "Unknown option '$1'.
  160. Type '$PGRM help' for usage."
  161. fi
  162. break
  163. ;;
  164. esac
  165. done
  166. if [ ! -f "$keyFile" ] ; then
  167. failure "SSH secret key file '$keyFile' not found."
  168. fi
  169. userID="ssh://${hostName}"
  170. # prompt about key expiration if not specified
  171. keyExpire=$(get_gpg_expiration "$keyExpire")
  172. echo "The following key parameters will be used for the host private key:"
  173. echo "Import: $keyFile"
  174. echo "Name-Real: $userID"
  175. echo "Expire-Date: $keyExpire"
  176. read -p "Import key? (Y/n) " OK; OK=${OK:=Y}
  177. if [ ${OK/y/Y} != 'Y' ] ; then
  178. failure "aborting."
  179. fi
  180. log verbose "importing ssh key..."
  181. # translate ssh key to a private key
  182. (umask 077 && \
  183. pem2openpgp "$userID" "$keyExpire" < "$sshKey" | gpg_host --import)
  184. # find the key fingerprint of the newly converted key
  185. fingerprint=$(fingerprint_server_key)
  186. # export host ownertrust to authentication keyring
  187. log verbose "setting ultimate owner trust for host key..."
  188. echo "${fingerprint}:6:" | gpg_host "--import-ownertrust"
  189. echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
  190. # export public key to file
  191. gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
  192. log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
  193. # show info about new key
  194. show_server_key
  195. }
  196. # generate server gpg key
  197. gen_key() {
  198. local keyType="RSA"
  199. local keyLength="2048"
  200. local keyUsage="auth"
  201. local keyExpire
  202. local revoker
  203. local hostName=$(hostname -f)
  204. local userID
  205. local keyParameters
  206. local fingerprint
  207. # check for presense of secret key
  208. # FIXME: is this the proper test to be doing here?
  209. fingerprint_server_key >/dev/null \
  210. && failure "An OpenPGP host key already exists."
  211. # get options
  212. while true ; do
  213. case "$1" in
  214. -h|--hostname)
  215. hostName="$2"
  216. shift 2
  217. ;;
  218. -l|--length)
  219. keyLength="$2"
  220. shift 2
  221. ;;
  222. -e|--expire)
  223. keyExpire="$2"
  224. shift 2
  225. ;;
  226. -r|--revoker)
  227. revoker="$2"
  228. shift 2
  229. ;;
  230. *)
  231. if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
  232. failure "Unknown option '$1'.
  233. Type '$PGRM help' for usage."
  234. fi
  235. break
  236. ;;
  237. esac
  238. done
  239. userID="ssh://${hostName}"
  240. # prompt about key expiration if not specified
  241. keyExpire=$(get_gpg_expiration "$keyExpire")
  242. # set key parameters
  243. keyParameters=\
  244. "Key-Type: $keyType
  245. Key-Length: $keyLength
  246. Key-Usage: $keyUsage
  247. Name-Real: $userID
  248. Expire-Date: $keyExpire"
  249. # add the revoker field if specified
  250. # FIXME: the "1:" below assumes that $REVOKER's key is an RSA key.
  251. # FIXME: key is marked "sensitive"? is this appropriate?
  252. if [ "$revoker" ] ; then
  253. keyParameters=\
  254. "${keyParameters}
  255. Revoker: 1:${revoker} sensitive"
  256. fi
  257. echo "The following key parameters will be used for the host private key:"
  258. echo "$keyParameters"
  259. read -p "Generate key? (Y/n) " OK; OK=${OK:=Y}
  260. if [ ${OK/y/Y} != 'Y' ] ; then
  261. failure "aborting."
  262. fi
  263. # add commit command
  264. # must include blank line!
  265. keyParameters=\
  266. "${keyParameters}
  267. %commit
  268. %echo done"
  269. log verbose "generating host key..."
  270. echo "$keyParameters" | gpg_host --batch --gen-key
  271. # find the key fingerprint of the newly generated key
  272. fingerprint=$(fingerprint_server_key)
  273. # export host ownertrust to authentication keyring
  274. log verbose "setting ultimate owner trust for host key..."
  275. echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
  276. # translate the private key to ssh format, and export to a file
  277. # for sshs usage.
  278. # NOTE: assumes that the primary key is the proper key to use
  279. (umask 077 && \
  280. gpg_host --export-secret-key "$fingerprint" | \
  281. openpgp2ssh "$fingerprint" > "${SYSDATADIR}/ssh_host_rsa_key")
  282. log info "SSH host private key output to file: ${SYSDATADIR}/ssh_host_rsa_key"
  283. ssh-keygen -y -f "${SYSDATADIR}/ssh_host_rsa_key" > "${SYSDATADIR}/ssh_host_rsa_key.pub"
  284. log info "SSH host public key output to file: ${SYSDATADIR}/ssh_host_rsa_key.pub"
  285. gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
  286. log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
  287. # show info about new key
  288. show_server_key
  289. }
  290. # extend the lifetime of a host key:
  291. extend_key() {
  292. local fpr=$(fingerprint_server_key)
  293. local extendTo="$1"
  294. # get the new expiration date
  295. extendTo=$(get_gpg_expiration "$extendTo")
  296. gpg_host --quiet --command-fd 0 --edit-key "$fpr" <<EOF
  297. expire
  298. $extendTo
  299. save
  300. EOF
  301. echo
  302. echo "NOTE: Host key expiration date adjusted, but not yet published."
  303. echo "Run '$PGRM publish-key' to publish the new expiration date."
  304. }
  305. # add hostname user ID to server key
  306. add_hostname() {
  307. local userID
  308. local fingerprint
  309. local tmpuidMatch
  310. local line
  311. local adduidCommand
  312. if [ -z "$1" ] ; then
  313. failure "You must specify a hostname to add."
  314. fi
  315. userID="ssh://${1}"
  316. fingerprint=$(fingerprint_server_key)
  317. # match to only ultimately trusted user IDs
  318. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  319. # find the index of the requsted user ID
  320. # NOTE: this is based on circumstantial evidence that the order of
  321. # this output is the appropriate index
  322. if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
  323. | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
  324. failure "Host userID '$userID' already exists."
  325. fi
  326. echo "The following user ID will be added to the host key:"
  327. echo " $userID"
  328. read -p "Are you sure you would like to add this user ID? (y/N) " OK; OK=${OK:=N}
  329. if [ ${OK/y/Y} != 'Y' ] ; then
  330. failure "User ID not added."
  331. fi
  332. # edit-key script command to add user ID
  333. adduidCommand=$(cat <<EOF
  334. adduid
  335. $userID
  336. save
  337. EOF
  338. )
  339. # execute edit-key script
  340. if echo "$adduidCommand" | \
  341. gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
  342. # update the trustdb for the authentication keyring
  343. gpg_authentication "--check-trustdb"
  344. show_server_key
  345. echo
  346. echo "NOTE: User ID added to key, but key not published."
  347. echo "Run '$PGRM publish-key' to publish the new user ID."
  348. else
  349. failure "Problem adding user ID."
  350. fi
  351. }
  352. # revoke hostname user ID to server key
  353. revoke_hostname() {
  354. local userID
  355. local fingerprint
  356. local tmpuidMatch
  357. local line
  358. local uidIndex
  359. local message
  360. local revuidCommand
  361. if [ -z "$1" ] ; then
  362. failure "You must specify a hostname to revoke."
  363. fi
  364. echo "WARNING: There is a known bug in this function."
  365. echo "This function has been known to occasionally revoke the wrong user ID."
  366. echo "Please see the following bug report for more information:"
  367. echo "http://web.monkeysphere.info/bugs/revoke-hostname-revoking-wrong-userid/"
  368. read -p "Are you sure you would like to proceed? (y/N) " OK; OK=${OK:=N}
  369. if [ ${OK/y/Y} != 'Y' ] ; then
  370. failure "aborting."
  371. fi
  372. userID="ssh://${1}"
  373. fingerprint=$(fingerprint_server_key)
  374. # match to only ultimately trusted user IDs
  375. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  376. # find the index of the requsted user ID
  377. # NOTE: this is based on circumstantial evidence that the order of
  378. # this output is the appropriate index
  379. if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
  380. | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
  381. uidIndex=${line%%:*}
  382. else
  383. failure "No non-revoked user ID '$userID' is found."
  384. fi
  385. echo "The following host key user ID will be revoked:"
  386. echo " $userID"
  387. read -p "Are you sure you would like to revoke this user ID? (y/N) " OK; OK=${OK:=N}
  388. if [ ${OK/y/Y} != 'Y' ] ; then
  389. failure "User ID not revoked."
  390. fi
  391. message="Hostname removed by monkeysphere-server $DATE"
  392. # edit-key script command to revoke user ID
  393. revuidCommand=$(cat <<EOF
  394. $uidIndex
  395. revuid
  396. y
  397. 4
  398. $message
  399. y
  400. save
  401. EOF
  402. )
  403. # execute edit-key script
  404. if echo "$revuidCommand" | \
  405. gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
  406. # update the trustdb for the authentication keyring
  407. gpg_authentication "--check-trustdb"
  408. show_server_key
  409. echo
  410. echo "NOTE: User ID revoked, but revocation not published."
  411. echo "Run '$PGRM publish-key' to publish the revocation."
  412. else
  413. failure "Problem revoking user ID."
  414. fi
  415. }
  416. # add a revoker to the host key
  417. add_revoker() {
  418. # FIXME: implement!
  419. failure "not implemented yet!"
  420. }
  421. # revoke the host key
  422. revoke_key() {
  423. # FIXME: implement!
  424. failure "not implemented yet!"
  425. }
  426. # publish server key to keyserver
  427. publish_server_key() {
  428. read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
  429. if [ ${OK/y/Y} != 'Y' ] ; then
  430. failure "key not published."
  431. fi
  432. # find the key fingerprint
  433. fingerprint=$(fingerprint_server_key)
  434. # publish host key
  435. gpg_authentication "--keyserver $KEYSERVER --send-keys '0x${fingerprint}!'"
  436. }
  437. diagnostics() {
  438. # * check on the status and validity of the key and public certificates
  439. local seckey
  440. local keysfound
  441. local curdate
  442. local warnwindow
  443. local warndate
  444. local create
  445. local expire
  446. local uid
  447. local fingerprint
  448. local badhostkeys
  449. local sshd_config
  450. local problemsfound=0
  451. # FIXME: what's the correct, cross-platform answer?
  452. sshd_config=/etc/ssh/sshd_config
  453. seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
  454. keysfound=$(echo "$seckey" | grep -c ^sec:)
  455. curdate=$(date +%s)
  456. # warn when anything is 2 months away from expiration
  457. warnwindow='2 months'
  458. warndate=$(advance_date $warnwindow +%s)
  459. if ! id monkeysphere >/dev/null ; then
  460. echo "! No monkeysphere user found! Please create a monkeysphere system user with bash as its shell."
  461. problemsfound=$(($problemsfound+1))
  462. fi
  463. if ! [ -d "$SYSDATADIR" ] ; then
  464. echo "! no $SYSDATADIR directory found. Please create it."
  465. problemsfound=$(($problemsfound+1))
  466. fi
  467. echo "Checking host GPG key..."
  468. if (( "$keysfound" < 1 )); then
  469. echo "! No host key found."
  470. echo " - Recommendation: run 'monkeysphere-server gen-key'"
  471. problemsfound=$(($problemsfound+1))
  472. elif (( "$keysfound" > 1 )); then
  473. echo "! More than one host key found?"
  474. # FIXME: recommend a way to resolve this
  475. problemsfound=$(($problemsfound+1))
  476. else
  477. create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
  478. expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
  479. fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
  480. # check for key expiration:
  481. if [ "$expire" ]; then
  482. if (( "$expire" < "$curdate" )); then
  483. echo "! Host key is expired."
  484. echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
  485. problemsfound=$(($problemsfound+1))
  486. elif (( "$expire" < "$warndate" )); then
  487. echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
  488. echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
  489. problemsfound=$(($problemsfound+1))
  490. fi
  491. fi
  492. # and weirdnesses:
  493. if [ "$create" ] && (( "$create" > "$curdate" )); then
  494. echo "! Host key was created in the future(?!). Is your clock correct?"
  495. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  496. problemsfound=$(($problemsfound+1))
  497. fi
  498. # check for UserID expiration:
  499. echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
  500. while IFS=: read create expire uid ; do
  501. # FIXME: should we be doing any checking on the form
  502. # of the User ID? Should we be unmangling it somehow?
  503. if [ "$create" ] && (( "$create" > "$curdate" )); then
  504. echo "! User ID '$uid' was created in the future(?!). Is your clock correct?"
  505. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  506. problemsfound=$(($problemsfound+1))
  507. fi
  508. if [ "$expire" ] ; then
  509. if (( "$expire" < "$curdate" )); then
  510. echo "! User ID '$uid' is expired."
  511. # FIXME: recommend a way to resolve this
  512. problemsfound=$(($problemsfound+1))
  513. elif (( "$expire" < "$warndate" )); then
  514. echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
  515. # FIXME: recommend a way to resolve this
  516. problemsfound=$(($problemsfound+1))
  517. fi
  518. fi
  519. done
  520. # FIXME: verify that the host key is properly published to the
  521. # keyservers (do this with the non-privileged user)
  522. # FIXME: check that there are valid, non-expired certifying signatures
  523. # attached to the host key after fetching from the public keyserver
  524. # (do this with the non-privileged user as well)
  525. # FIXME: propose adding a revoker to the host key if none exist (do we
  526. # have a way to do that after key generation?)
  527. # Ensure that the ssh_host_rsa_key file is present and non-empty:
  528. echo
  529. echo "Checking host SSH key..."
  530. if [ ! -s "${SYSDATADIR}/ssh_host_rsa_key" ] ; then
  531. echo "! The host key as prepared for SSH (${SYSDATADIR}/ssh_host_rsa_key) is missing or empty."
  532. problemsfound=$(($problemsfound+1))
  533. else
  534. if [ $(ls -l "${SYSDATADIR}/ssh_host_rsa_key" | cut -f1 -d\ ) != '-rw-------' ] ; then
  535. echo "! Permissions seem wrong for ${SYSDATADIR}/ssh_host_rsa_key -- should be 0600."
  536. problemsfound=$(($problemsfound+1))
  537. fi
  538. # propose changes needed for sshd_config (if any)
  539. if ! grep -q "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$" "$sshd_config"; then
  540. echo "! $sshd_config does not point to the monkeysphere host key (${SYSDATADIR}/ssh_host_rsa_key)."
  541. echo " - Recommendation: add a line to $sshd_config: 'HostKey ${SYSDATADIR}/ssh_host_rsa_key'"
  542. problemsfound=$(($problemsfound+1))
  543. fi
  544. if badhostkeys=$(grep -i '^HostKey' "$sshd_config" | grep -v "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$") ; then
  545. echo "! $sshd_config refers to some non-monkeysphere host keys:"
  546. echo "$badhostkeys"
  547. echo " - Recommendation: remove the above HostKey lines from $sshd_config"
  548. problemsfound=$(($problemsfound+1))
  549. fi
  550. # FIXME: test (with ssh-keyscan?) that the running ssh
  551. # daemon is actually offering the monkeysphere host key.
  552. fi
  553. fi
  554. # FIXME: look at the ownership/privileges of the various keyrings,
  555. # directories housing them, etc (what should those values be? can
  556. # we make them as minimal as possible?)
  557. # FIXME: look to see that the ownertrust rules are set properly on the
  558. # authentication keyring
  559. # FIXME: make sure that at least one identity certifier exists
  560. # FIXME: look at the timestamps on the monkeysphere-generated
  561. # authorized_keys files -- warn if they seem out-of-date.
  562. # FIXME: check for a cronjob that updates monkeysphere-generated
  563. # authorized_keys?
  564. echo
  565. echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
  566. # Ensure that User ID authentication is enabled:
  567. if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
  568. echo "! $sshd_config does not point to monkeysphere authorized keys."
  569. echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
  570. problemsfound=$(($problemsfound+1))
  571. fi
  572. if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
  573. echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
  574. echo "$badauthorizedkeys"
  575. echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
  576. problemsfound=$(($problemsfound+1))
  577. fi
  578. if [ "$problemsfound" -gt 0 ]; then
  579. echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
  580. echo " monkeysphere-server diagnostics"
  581. else
  582. echo "Everything seems to be in order!"
  583. fi
  584. }
  585. ########################################################################
  586. # MAIN
  587. ########################################################################
  588. # unset variables that should be defined only in config file
  589. unset KEYSERVER
  590. unset AUTHORIZED_USER_IDS
  591. unset RAW_AUTHORIZED_KEYS
  592. unset MONKEYSPHERE_USER
  593. # load configuration file
  594. [ -e ${MONKEYSPHERE_SERVER_CONFIG:="${SYSCONFIGDIR}/monkeysphere-server.conf"} ] && . "$MONKEYSPHERE_SERVER_CONFIG"
  595. # set empty config variable with ones from the environment, or with
  596. # defaults
  597. LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
  598. KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
  599. AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
  600. RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
  601. MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
  602. # other variables
  603. CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
  604. REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"}
  605. GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${SYSDATADIR}/gnupg-host"}
  606. GNUPGHOME_AUTHENTICATION=${MONKEYSPHERE_GNUPGHOME_AUTHENTICATION:="${SYSDATADIR}/gnupg-authentication"}
  607. # export variables needed in su invocation
  608. export DATE
  609. export MODE
  610. export MONKEYSPHERE_USER
  611. export LOG_LEVEL
  612. export KEYSERVER
  613. export CHECK_KEYSERVER
  614. export REQUIRED_USER_KEY_CAPABILITY
  615. export GNUPGHOME_HOST
  616. export GNUPGHOME_AUTHENTICATION
  617. export GNUPGHOME
  618. # get subcommand
  619. COMMAND="$1"
  620. [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
  621. shift
  622. case $COMMAND in
  623. 'show-key'|'show'|'s')
  624. show_server_key
  625. ;;
  626. 'extend-key'|'e')
  627. check_user
  628. check_host_keyring
  629. extend_key "$@"
  630. ;;
  631. 'add-hostname'|'add-name'|'n+')
  632. check_user
  633. check_host_keyring
  634. add_hostname "$@"
  635. ;;
  636. 'revoke-hostname'|'revoke-name'|'n-')
  637. check_user
  638. check_host_keyring
  639. revoke_hostname "$@"
  640. ;;
  641. 'add-revoker'|'o')
  642. check_user
  643. check_host_keyring
  644. add_revoker "$@"
  645. ;;
  646. 'revoke-key'|'r')
  647. check_user
  648. check_host_keyring
  649. revoke_key "$@"
  650. ;;
  651. 'publish-key'|'publish'|'p')
  652. check_user
  653. check_host_keyring
  654. publish_server_key
  655. ;;
  656. 'expert'|'e')
  657. check_user
  658. SUBCOMMAND="$1"
  659. shift
  660. case "$SUBCOMMAND" in
  661. 'import-key'|'i')
  662. import_key "$@"
  663. ;;
  664. 'gen-key'|'g')
  665. gen_key "$@"
  666. ;;
  667. 'diagnostics'|'d')
  668. diagnostics
  669. ;;
  670. *)
  671. failure "Unknown expert subcommand: '$COMMAND'
  672. Type '$PGRM help' for usage."
  673. ;;
  674. esac
  675. ;;
  676. 'version'|'v')
  677. echo "$VERSION"
  678. ;;
  679. '--help'|'help'|'-h'|'h'|'?')
  680. usage
  681. ;;
  682. *)
  683. failure "Unknown command: '$COMMAND'
  684. Type '$PGRM help' for usage."
  685. ;;
  686. esac
  687. exit "$RETURN"