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