re-work monkeysphere-host diagnostics with an eye toward multiple host keys
[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-2010, and are all released under the GPL,
12 # version 3 or later.
13
14 # check on the status and validity of the host's public certificates (and keys?)
15
16 # global vars for communicating between functions:
17
18 MHD_CURDATE=$(date +%s)
19 # warn when anything is 2 months away from expiration
20 MHD_WARNWINDOW='2 months'
21 MHD_WARNDATE=$(advance_date $MHD_WARNWINDOW +%s)
22 MHD_PROBLEMSFOUND=0
23
24
25 diagnose_key() {
26     local fpr="$1"
27     local certinfo
28     local create
29     local expire
30     local uid
31     local keysfound
32     local uiderrs
33     local errcount
34
35     printf "Checking OpenPGP Certificate for key 0x%s\n" "$fpr"
36
37     certinfo=$(get_cert_info "0x$fpr" <"$HOST_KEY_FILE")
38     keysfound=$(grep -c ^pub: <<<"$certinfo")
39
40     if [ "$keysfound" -lt 1 ] ; then
41         printf "! Could not find key with fingerprint 0x%s\n" "$fpr"
42         # FIXME: recommend a way to resolve this!
43         MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+1))
44     fi
45
46     create=$(echo "$certinfo" | grep ^pub: | cut -f6 -d:)
47     expire=$(echo "$certinfo" | grep ^pub: | cut -f7 -d:)
48     # check for key expiration:
49     if [ "$expire" ]; then
50         if (( "$expire"  < "$MHD_CURDATE" )); then
51             printf "! Host key 0x%s is expired.\n" "$fpr"
52             printf " - Recommendation: extend lifetime of key with 'monkeysphere-host set-expire 0x%s'\n" "$fpr"
53             MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+1))
54         elif (( "$expire" < "$MHD_WARNDATE" )); then
55             printf "! Host key 0x%s expires in less than %s: %s\n" "$fpr" "$MHD_WARNWINDOW" $(advance_date $(( $expire - $MHD_CURDATE )) seconds +%F)
56             printf " - Recommendation: extend lifetime of key with 'monkeysphere-host set-expire %s'\n" "$fpr"
57             MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+1))
58         fi
59     fi
60
61     # and weirdnesses:
62     if [ "$create" ] && (( "$create" > "$MHD_CURDATE" )); then
63         printf "! Host key 0x%s was created in the future(?!): %s. Is your clock correct?\n" "$fpr" $(date -d "1970-01-01 + $create seconds" +%F)
64         printf " - Recommendation: Check your clock (is it really %s?); use NTP?\n" $(date +%F_%T)
65         MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+1))
66     fi
67     
68     # check for UserID expiration:
69     uiderrs=$(printf '%s\n' "$certinfo" | grep ^uid: | cut -d: -f6,7,10 | \
70         while IFS=: read -r create expire uid ; do
71             uid=$(gpg_unescape <<<"$uid")
72             
73             check_service_name "$uid"
74             if [ "$create" ] && (( "$create" > "$MHD_CURDATE" )); then
75                 printf "! The latest self-sig on User ID '%s' was created in the future(?!): %s.\n - Is your clock correct?\n" "$uid" $(date -d "1970-01-01 + $create seconds" +%F)
76                 printf " - Recommendation: Check your clock (is it really %s ?); use NTP?\n" $(date +%F_%T)
77             fi
78             if [ "$expire" ] ; then
79                 if (( "$expire" < "$MHD_CURDATE" )); then
80                     printf "! User ID '%s' is expired.\n" "$uid"
81                 # FIXME: recommend a way to resolve this
82                 elif (( "$expire" < "$MHD_WARNDATE" )); then
83                     printf "! User ID '%s' expires in less than %s: %s\n"  "%s" "$MHD_WARNWINDOW" $(advance_date $(( $expire - $MHD_CURDATE )) seconds +%F)
84                 # FIXME: recommend a way to resolve this
85                 fi
86             fi
87         done)
88     errcount=$(grep -c '^!' <<<"$uiderrs") || \
89         MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+ $errcount ))
90     printf '%s\n' "$uiderrs"
91
92
93             
94 # FIXME: verify that the host key is properly published to the
95 #   keyservers (do this with the non-privileged user)
96
97 # FIXME: check that there are valid, non-expired certifying signatures
98 #   attached to the host key after fetching from the public keyserver
99 #   (do this with the non-privileged user as well)
100
101 # FIXME: propose adding a revoker to the host key if none exist (do we
102 #   have a way to do that after key generation?)
103
104 # FIXME: test (with ssh-keyscan?) that any running ssh daemon is
105 # actually offering the monkeysphere host key, if such a key is
106 # loaded.
107
108 # FIXME: scan /proc/net/tcp and /proc/net/tcp6 to see what
109 #   known-crypto ports (ssh, https, imaps?, ldaps?, etc) are in use
110 #   locally.  Propose bringing them into the monkeysphere.
111
112 # FIXME: ensure that the key is of a reasonable size
113
114 # FIXME: ensure that the cert has the right key usage flags
115
116 # FIXME: ensure that the key doesn't match any known blacklist
117 }
118
119 diagnostics() {
120
121 MHD_PROBLEMSFOUND=0
122
123
124 if ! [ -d "$SYSDATADIR" ] ; then
125     echo "! no $SYSDATADIR directory found.  Please create it."
126     exit
127 fi
128
129 if ! [ -f "$HOST_KEY_FILE" ] ; then
130     echo "No host OpenPGP certificates file found!"
131     echo " - Recommendation: run 'monkeysphere-host import-key' with a service key"
132     exit
133 fi
134
135 if ! id monkeysphere >/dev/null ; then
136     echo "! No monkeysphere user found!  Please create a monkeysphere system user with bash as its shell."
137     MHD_PROBLEMSFOUND=$(($MHD_PROBLEMSFOUND+1))
138 fi
139
140 echo "Checking host OpenPGP certificates..."
141 multi_key diagnose_key
142
143 # FIXME: look at the ownership/privileges of the various keyrings,
144 #    directories housing them, etc (what should those values be?  can
145 #    we make them as minimal as possible?)
146
147 # report on any cruft from old monkeysphere version
148 report_cruft
149
150 if [ "$MHD_PROBLEMSFOUND" -gt 0 ]; then
151     echo "When the above $MHD_PROBLEMSFOUND issue"$(if [ "$MHD_PROBLEMSFOUND" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
152     echo "  monkeysphere-host diagnostics"
153 else
154     echo "Everything seems to be in order!"
155 fi
156
157 }