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