summaryrefslogtreecommitdiff
path: root/src/subcommands/mh/diagnostics
blob: 5b04b14d2d7f63de216b73a04316243b89fa0c7e (plain)
  1. #!/usr/bin/env bash
  2. # Monkeysphere host diagnostics subcommand
  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. # check on the status and validity of the key and public certificates
  12. diagnostics() {
  13. local seckey
  14. local keysfound
  15. local curdate
  16. local warnwindow
  17. local warndate
  18. local create
  19. local expire
  20. local uid
  21. local fingerprint
  22. local badhostkeys
  23. local sshd_config
  24. local problemsfound=0
  25. # FIXME: what's the correct, cross-platform answer?
  26. sshd_config=/etc/ssh/sshd_config
  27. seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
  28. keysfound=$(echo "$seckey" | grep -c ^sec:)
  29. curdate=$(date +%s)
  30. # warn when anything is 2 months away from expiration
  31. warnwindow='2 months'
  32. warndate=$(advance_date $warnwindow +%s)
  33. if ! id monkeysphere >/dev/null ; then
  34. echo "! No monkeysphere user found! Please create a monkeysphere system user with bash as its shell."
  35. problemsfound=$(($problemsfound+1))
  36. fi
  37. if ! [ -d "$SYSDATADIR" ] ; then
  38. echo "! no $SYSDATADIR directory found. Please create it."
  39. problemsfound=$(($problemsfound+1))
  40. fi
  41. echo "Checking host GPG key..."
  42. if (( "$keysfound" < 1 )); then
  43. echo "! No host key found."
  44. echo " - Recommendation: run 'monkeysphere-server gen-key'"
  45. problemsfound=$(($problemsfound+1))
  46. elif (( "$keysfound" > 1 )); then
  47. echo "! More than one host key found?"
  48. # FIXME: recommend a way to resolve this
  49. problemsfound=$(($problemsfound+1))
  50. else
  51. create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
  52. expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
  53. fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
  54. # check for key expiration:
  55. if [ "$expire" ]; then
  56. if (( "$expire" < "$curdate" )); then
  57. echo "! Host key is expired."
  58. echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
  59. problemsfound=$(($problemsfound+1))
  60. elif (( "$expire" < "$warndate" )); then
  61. echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
  62. echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
  63. problemsfound=$(($problemsfound+1))
  64. fi
  65. fi
  66. # and weirdnesses:
  67. if [ "$create" ] && (( "$create" > "$curdate" )); then
  68. echo "! Host key was created in the future(?!). Is your clock correct?"
  69. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  70. problemsfound=$(($problemsfound+1))
  71. fi
  72. # check for UserID expiration:
  73. echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
  74. while IFS=: read create expire uid ; do
  75. # FIXME: should we be doing any checking on the form
  76. # of the User ID? Should we be unmangling it somehow?
  77. if [ "$create" ] && (( "$create" > "$curdate" )); then
  78. echo "! User ID '$uid' was created in the future(?!). Is your clock correct?"
  79. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  80. problemsfound=$(($problemsfound+1))
  81. fi
  82. if [ "$expire" ] ; then
  83. if (( "$expire" < "$curdate" )); then
  84. echo "! User ID '$uid' is expired."
  85. # FIXME: recommend a way to resolve this
  86. problemsfound=$(($problemsfound+1))
  87. elif (( "$expire" < "$warndate" )); then
  88. echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
  89. # FIXME: recommend a way to resolve this
  90. problemsfound=$(($problemsfound+1))
  91. fi
  92. fi
  93. done
  94. # FIXME: verify that the host key is properly published to the
  95. # keyservers (do this with the non-privileged user)
  96. # FIXME: check that there are valid, non-expired certifying signatures
  97. # attached to the host key after fetching from the public keyserver
  98. # (do this with the non-privileged user as well)
  99. # FIXME: propose adding a revoker to the host key if none exist (do we
  100. # have a way to do that after key generation?)
  101. # Ensure that the ssh_host_rsa_key file is present and non-empty:
  102. echo
  103. echo "Checking host SSH key..."
  104. if [ ! -s "${SYSDATADIR}/ssh_host_rsa_key" ] ; then
  105. echo "! The host key as prepared for SSH (${SYSDATADIR}/ssh_host_rsa_key) is missing or empty."
  106. problemsfound=$(($problemsfound+1))
  107. else
  108. if [ $(ls -l "${SYSDATADIR}/ssh_host_rsa_key" | cut -f1 -d\ ) != '-rw-------' ] ; then
  109. echo "! Permissions seem wrong for ${SYSDATADIR}/ssh_host_rsa_key -- should be 0600."
  110. problemsfound=$(($problemsfound+1))
  111. fi
  112. # propose changes needed for sshd_config (if any)
  113. if ! grep -q "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$" "$sshd_config"; then
  114. echo "! $sshd_config does not point to the monkeysphere host key (${SYSDATADIR}/ssh_host_rsa_key)."
  115. echo " - Recommendation: add a line to $sshd_config: 'HostKey ${SYSDATADIR}/ssh_host_rsa_key'"
  116. problemsfound=$(($problemsfound+1))
  117. fi
  118. if badhostkeys=$(grep -i '^HostKey' "$sshd_config" | grep -v "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$") ; then
  119. echo "! $sshd_config refers to some non-monkeysphere host keys:"
  120. echo "$badhostkeys"
  121. echo " - Recommendation: remove the above HostKey lines from $sshd_config"
  122. problemsfound=$(($problemsfound+1))
  123. fi
  124. # FIXME: test (with ssh-keyscan?) that the running ssh
  125. # daemon is actually offering the monkeysphere host key.
  126. fi
  127. fi
  128. # FIXME: look at the ownership/privileges of the various keyrings,
  129. # directories housing them, etc (what should those values be? can
  130. # we make them as minimal as possible?)
  131. # FIXME: look to see that the ownertrust rules are set properly on the
  132. # authentication keyring
  133. # FIXME: make sure that at least one identity certifier exists
  134. # FIXME: look at the timestamps on the monkeysphere-generated
  135. # authorized_keys files -- warn if they seem out-of-date.
  136. # FIXME: check for a cronjob that updates monkeysphere-generated
  137. # authorized_keys?
  138. echo
  139. echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
  140. # Ensure that User ID authentication is enabled:
  141. if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
  142. echo "! $sshd_config does not point to monkeysphere authorized keys."
  143. echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
  144. problemsfound=$(($problemsfound+1))
  145. fi
  146. if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
  147. echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
  148. echo "$badauthorizedkeys"
  149. echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
  150. problemsfound=$(($problemsfound+1))
  151. fi
  152. if [ "$problemsfound" -gt 0 ]; then
  153. echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
  154. echo " monkeysphere-server diagnostics"
  155. else
  156. echo "Everything seems to be in order!"
  157. fi
  158. }