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