define variable for public key files (HOST_KEY_PUB, HOST_KEY_PUB_GPG).
[monkeysphere.git] / src / monkeysphere-host
1 #!/usr/bin/env bash
2
3 # monkeysphere-host: Monkeysphere host admin tool
4 #
5 # The monkeysphere scripts are written by:
6 # Jameson Rollins <jrollins@finestructure.net>
7 # Jamie McClelland <jm@mayfirst.org>
8 # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
9 # Micah Anderson <micah@riseup.net>
10 #
11 # They are Copyright 2008-2009, and are all released under the GPL,
12 # version 3 or later.
13
14 ########################################################################
15 set -e
16
17 # set the pipefail option so pipelines fail on first command failure
18 set -o pipefail
19
20 PGRM=$(basename $0)
21
22 SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"}
23 export SYSSHAREDIR
24 . "${SYSSHAREDIR}/common" || exit 1
25
26 SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
27 export SYSDATADIR
28
29 # sharedir for host functions
30 MHSHAREDIR="${SYSSHAREDIR}/mh"
31
32 # datadir for host functions
33 MHDATADIR="${SYSDATADIR}/host"
34
35 # UTC date in ISO 8601 format if needed
36 DATE=$(date -u '+%FT%T')
37
38 # unset some environment variables that could screw things up
39 unset GREP_OPTIONS
40
41 # default return code
42 RETURN=0
43
44 ########################################################################
45 # FUNCTIONS
46 ########################################################################
47
48 usage() {
49     cat <<EOF >&2
50 usage: $PGRM <subcommand> [options] [args]
51 Monkeysphere host admin tool.
52
53 subcommands:
54  show-key (s)                        output all host key information
55  set-expire (e) EXPIRE               set host key expiration
56  add-hostname (n+) NAME[:PORT]       add hostname user ID to host key
57  revoke-hostname (n-) NAME[:PORT]    revoke hostname user ID
58  add-revoker (o) FINGERPRINT         add a revoker to the host key
59  revoke-key (r)                      revoke host key
60  publish-key (p)                     publish host key to keyserver
61
62  expert <expert-subcommand>          run expert command
63  expert help                         expert command help
64
65  version (v)                         show version number
66  help (h,?)                          this help
67
68 EOF
69 }
70
71 # function to run command as monkeysphere user
72 su_monkeysphere_user() {
73     # if the current user is the monkeysphere user, then just eval
74     # command
75     if [ $(id -un) = "$MONKEYSPHERE_USER" ] ; then
76         eval "$@"
77
78     # otherwise su command as monkeysphere user
79     else
80         su "$MONKEYSPHERE_USER" -c "$@"
81     fi
82 }
83
84 # function to interact with the gpg keyring
85 gpg_host() {
86     GNUPGHOME="$GNUPGHOME_HOST" gpg "$@"
87 }
88
89 # command to list the info about the host key, in colon format
90 gpg_host_list() {
91     gpg_host --list-keys --with-colons --fixed-list-mode \
92         --with-fingerprint --with-fingerprint \
93         "0x${HOST_FINGERPRINT}!"
94
95 }
96
97 # command for edit key scripts, takes scripts on stdin
98 gpg_host_edit() {
99     gpg_host --quiet --command-fd 0 --edit-key \
100         "0x${HOST_FINGERPRINT}!" "$@"
101 }
102
103 # export the host key to stdout
104 gpg_host_export() {
105     gpg_host --export --armor --export-options export-minimal \
106         "0x${HOST_FINGERPRINT}!"
107 }
108
109 # export the host key to the monkeysphere host file key
110 gpg_host_export_to_ssh_file() {
111     log debug "exporting openpgp public key..."
112
113     gpg_host_export > "$HOST_KEY_PUB_GPG"
114     log info "SSH host public key in OpenPGP form: $HOST_KEY_PUB_GPG"
115 }
116
117 # output just key fingerprint
118 fingerprint_host_key() {
119     gpg_host --list-secret-keys --fingerprint \
120         --with-colons --fixed-list-mode 2> /dev/null | \
121         grep '^fpr:' | head -1 | cut -d: -f10 2>/dev/null
122 }
123
124 # output the index of a user ID on the host key
125 # return 1 if user ID not found
126 find_host_userid() {
127     local userID="$1"
128     local tmpuidMatch
129     local line
130
131     # match to only ultimately trusted user IDs
132     tmpuidMatch="u:$(echo $userID | gpg_escape)"
133
134     # find the index of the requsted user ID
135     # NOTE: this is based on circumstantial evidence that the order of
136     # this output is the appropriate index
137     line=$(gpg_host_list | egrep '^(uid|uat):' | cut -f2,10 -d: | \
138         grep -n -x -F "$tmpuidMatch" 2>/dev/null)
139
140     if [ "$line" ] ; then
141         echo ${line%%:*}
142         return 0
143     else
144         return 1
145     fi
146 }
147
148 # function to check for host secret key
149 check_host_fail() {
150     [ "$HOST_FINGERPRINT" ] || \
151         failure "You don't appear to have a Monkeysphere host key on this server.  Please run 'monkeysphere-host expert import-key' first."
152 }
153
154 # show info about the host key
155 show_key() {
156     local fingerprintSSH
157
158     # FIXME: should not have to be priviledged user to see this info.
159     # should be taken from publicly accessible key files, instead of
160     # the keyring.
161
162     gpg_host --fingerprint --list-key --list-options show-unusable-uids \
163         "0x${HOST_FINGERPRINT}!" 2>/dev/null
164
165     echo "OpenPGP fingerprint: $HOST_FINGERPRINT"
166
167     if [ -f "$HOST_KEY_PUB" ] ; then
168         fingerprintSSH=$(ssh-keygen -l -f "$HOST_KEY_PUB" | \
169             awk '{ print $1, $2, $4 }')
170
171         echo "ssh fingerprint: $fingerprintSSH"
172     else
173         log error "SSH host key not found."
174     fi
175
176     # FIXME: show expiration date
177     # FIXME: other relevant key parameters?
178 }
179
180 ########################################################################
181 # MAIN
182 ########################################################################
183
184 # unset variables that should be defined only in config file
185 unset KEYSERVER
186 unset MONKEYSPHERE_USER
187
188 # load configuration file
189 [ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] && . "$MONKEYSPHERE_HOST_CONFIG"
190
191 # set empty config variable with ones from the environment, or with
192 # defaults
193 LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
194 KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
195 AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
196 RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
197 MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
198
199 # other variables
200 CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
201 GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"}
202
203 # host key fingerprint
204 HOST_FINGERPRINT=$(fingerprint_host_key)
205
206 # host pub key files
207 HOST_KEY_PUB="${SYSDATADIR}/ssh_host_rsa_key.pub"
208 HOST_KEY_PUB_GPG="${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
209
210 # export variables needed in su invocation
211 export DATE
212 export MODE
213 export LOG_LEVEL
214 export MONKEYSPHERE_USER
215 export KEYSERVER
216 export GNUPGHOME_HOST
217 export GNUPGHOME
218 export HOST_FINGERPRINT
219
220 # get subcommand
221 COMMAND="$1"
222 [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
223 shift
224
225
226 case $COMMAND in
227     'show-key'|'show'|'s')
228         check_host_fail
229         show_key
230         ;;
231
232     'set-expire'|'extend-key'|'e')
233         check_host_fail
234         source "${MHSHAREDIR}/set_expire"
235         set_expire "$@"
236         ;;
237
238     'add-hostname'|'add-name'|'n+')
239         check_host_fail
240         source "${MHSHAREDIR}/add_hostname"
241         add_hostname "$@"
242         ;;
243
244     'revoke-hostname'|'revoke-name'|'n-')
245         check_host_fail
246         source "${MHSHAREDIR}/revoke_hostname"
247         revoke_hostname "$@"
248         ;;
249
250     'add-revoker'|'o')
251         check_host_fail
252         source "${MHSHAREDIR}/add_revoker"
253         add_revoker "$@"
254         ;;
255
256     'revoke-key'|'r')
257         check_host_fail
258         source "${MHSHAREDIR}/revoke_key"
259         revoke_key "$@"
260         ;;
261
262     'publish-key'|'publish'|'p')
263         check_host_fail
264         source "${MHSHAREDIR}/publish_key"
265         publish_key
266         ;;
267
268     'expert')
269         SUBCOMMAND="$1"
270         shift
271         case "$SUBCOMMAND" in
272             'help'|'h'|'?')
273                 cat <<EOF
274 usage: $PGRM expert <subcommand> [options] [args]
275
276 expert subcommands:
277  import-key (i) [NAME[:PORT]]        import existing ssh key to gpg
278  gen-key (g) [NAME[:PORT]]           generate gpg key for the host
279    --length (-l) BITS                  key length in bits (2048)
280  diagnostics (d)                     monkeysphere host status
281
282 EOF
283                 ;;
284
285             'import-key'|'i')
286                 source "${MHSHAREDIR}/import_key"
287                 import_key "$@"
288                 ;;
289
290             'gen-key'|'g')
291                 source "${MHSHAREDIR}/gen_key"
292                 gen_key "$@"
293                 ;;
294
295             'diagnostics'|'d')
296                 source "${MHSHAREDIR}/diagnostics"
297                 diagnostics
298                 ;;
299
300             *)
301                 failure "Unknown expert subcommand: '$COMMAND'
302 Type '$PGRM help' for usage."
303                 ;;
304         esac
305         ;;
306
307     'version'|'v')
308         echo "$VERSION"
309         ;;
310
311     '--help'|'help'|'-h'|'h'|'?')
312         usage
313         ;;
314
315     *)
316         failure "Unknown command: '$COMMAND'
317 Type '$PGRM help' for usage."
318         ;;
319 esac
320
321 exit "$RETURN"