more work on hostname add/revoke
[monkeysphere.git] / src / monkeysphere-server
1 #!/bin/bash
2
3 # monkeysphere-server: MonkeySphere server admin tool
4 #
5 # The monkeysphere scripts are written by:
6 # Jameson Rollins <jrollins@fifthhorseman.net>
7 #
8 # They are Copyright 2008, and are all released under the GPL, version 3
9 # or later.
10
11 ########################################################################
12 PGRM=$(basename $0)
13
14 SHARE=${MONKEYSPHERE_SHARE:="/usr/share/monkeysphere"}
15 export SHARE
16 . "${SHARE}/common" || exit 1
17
18 VARLIB="/var/lib/monkeysphere"
19 export VARLIB
20
21 # date in UTF format if needed
22 DATE=$(date -u '+%FT%T')
23
24 # unset some environment variables that could screw things up
25 unset GREP_OPTIONS
26
27 # default return code
28 RETURN=0
29
30 ########################################################################
31 # FUNCTIONS
32 ########################################################################
33
34 usage() {
35     cat <<EOF
36 usage: $PGRM <subcommand> [options] [args]
37 MonkeySphere server admin tool.
38
39 subcommands:
40  update-users (u) [USER]...          update user authorized_keys files
41
42  gen-key (g) [NAME[:PORT]]           generate gpg key for the server
43    -l|--length BITS                    key length in bits (2048)
44    -e|--expire EXPIRE                  date to expire
45    -r|--revoker FINGERPRINT            add a revoker
46  add-hostname (n+) NAME[:PORT]       add hostname user ID to server key
47  revoke-hostname (n-) NAME[:PORT]    revoke hostname user ID
48  show-key (s)                        output all server host key information
49  fingerprint (f)                     output just the key fingerprint
50  publish-key (p)                     publish server host key to keyserver
51  diagnostics (d)                     report on server monkeysphere status
52
53  add-id-certifier (c+) KEYID         import and tsign a certification key
54    -n|--domain DOMAIN                  limit ID certifications to DOMAIN
55    -t|--trust TRUST                    trust level of certifier (full)
56    -d|--depth DEPTH                    trust depth for certifier (1)
57  remove-id-certifier (c-) KEYID      remove a certification key
58  list-id-certifiers (c)              list certification keys
59
60  gpg-authentication-cmd CMD          gnupg-authentication command
61
62  -h|--help|help (h,?)                this help
63 EOF
64 }
65
66 su_monkeysphere_user() {
67     su --preserve-environment "$MONKEYSPHERE_USER" -- -c "$@"
68 }
69
70 # function to interact with the host gnupg keyring
71 gpg_host() {
72     local returnCode
73
74     GNUPGHOME="$GNUPGHOME_HOST"
75     export GNUPGHOME
76
77     # NOTE: we supress this warning because we need the monkeysphere
78     # user to be able to read the host pubring.  we realize this might
79     # be problematic, but it's the simplest solution, without too much
80     # loss of security.
81     gpg --no-permission-warning "$@"
82     returnCode="$?"
83
84     # always reset the permissions on the host pubring so that the
85     # monkeysphere user can read the trust signatures
86     chgrp "$MONKEYSPHERE_USER" "${GNUPGHOME_HOST}/pubring.gpg"
87     chmod g+r "${GNUPGHOME_HOST}/pubring.gpg"
88     
89     return "$returnCode"
90 }
91
92 # function to interact with the authentication gnupg keyring
93 # FIXME: this function requires basically accepts only a single
94 # argument because of problems with quote expansion.  this needs to be
95 # fixed/improved.
96 gpg_authentication() {
97     GNUPGHOME="$GNUPGHOME_AUTHENTICATION"
98     export GNUPGHOME
99
100     su_monkeysphere_user "gpg $@"
101 }
102
103 # output just key fingerprint
104 fingerprint_server_key() {
105     gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode | \
106         grep '^fpr:' | head -1 | cut -d: -f10
107 }
108
109 # output key information
110 show_server_key() {
111     local fingerprint
112     fingerprint=$(fingerprint_server_key)
113     gpg_host --fingerprint --list-secret-key "$fingerprint"
114 }
115
116 # update authorized_keys for users
117 update_users() {
118     if [ "$1" ] ; then
119         # get users from command line
120         unames="$@"
121     else
122         # or just look at all users if none specified
123         unames=$(getent passwd | cut -d: -f1)
124     fi
125
126     # set mode
127     MODE="authorized_keys"
128
129     # set gnupg home
130     GNUPGHOME="$GNUPGHOME_AUTHENTICATION"
131
132     # check to see if the gpg trust database has been initialized
133     if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
134         failure "GNUPG trust database uninitialized.  Please see MONKEYSPHERE-SERVER(8)."
135     fi
136
137     # make sure the authorized_keys directory exists
138     mkdir -p "${VARLIB}/authorized_keys"
139
140     # loop over users
141     for uname in $unames ; do
142         # check all specified users exist
143         if ! getent passwd "$uname" >/dev/null ; then
144             log "----- unknown user '$uname' -----"
145             continue
146         fi
147
148         # set authorized_user_ids and raw authorized_keys variables,
149         # translating ssh-style path variables
150         authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
151         rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
152
153         # if neither is found, skip user
154         if [ ! -s "$authorizedUserIDs" ] ; then
155             if [ "$rawAuthorizedKeys" = '-' -o ! -s "$rawAuthorizedKeys" ] ; then
156                 continue
157             fi
158         fi
159
160         log "----- user: $uname -----"
161
162         # exit if the authorized_user_ids file is empty
163         if ! check_key_file_permissions "$uname" "$AUTHORIZED_USER_IDS" ; then
164             log "Improper permissions on authorized_user_ids file path."
165             continue
166         fi
167
168         # check permissions on the authorized_keys file path
169         if ! check_key_file_permissions "$uname" "$RAW_AUTHORIZED_KEYS" ; then
170             log "Improper permissions on authorized_keys file path path."
171             continue
172         fi
173
174         # make temporary directory
175         TMPDIR=$(mktemp -d)
176
177         # trap to delete temporary directory on exit
178         trap "rm -rf $TMPDIR" EXIT
179
180         # create temporary authorized_user_ids file
181         TMP_AUTHORIZED_USER_IDS="${TMPDIR}/authorized_user_ids"
182         touch "$TMP_AUTHORIZED_USER_IDS"
183
184         # create temporary authorized_keys file
185         AUTHORIZED_KEYS="${TMPDIR}/authorized_keys"
186         touch "$AUTHORIZED_KEYS"
187
188         # set restrictive permissions on the temporary files
189         # FIXME: is there a better way to do this?
190         chmod 0700 "$TMPDIR"
191         chmod 0600 "$AUTHORIZED_KEYS"
192         chmod 0600 "$TMP_AUTHORIZED_USER_IDS"
193         chown -R "$MONKEYSPHERE_USER" "$TMPDIR"
194
195         # if the authorized_user_ids file exists...
196         if [ -s "$authorizedUserIDs" ] ; then
197             # copy user authorized_user_ids file to temporary
198             # location
199             cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
200
201             # export needed variables
202             export AUTHORIZED_KEYS
203             export TMP_AUTHORIZED_USER_IDS
204
205             # process authorized_user_ids file, as monkeysphere
206             # user
207             su_monkeysphere_user \
208                 ". ${SHARE}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
209             RETURN="$?"
210         fi
211
212         # add user-controlled authorized_keys file path if specified
213         if [ "$rawAuthorizedKeys" != '-' -a -s "$rawAuthorizedKeys" ] ; then
214             log -n "adding raw authorized_keys file... "
215             cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
216             loge "done."
217         fi
218
219         # openssh appears to check the contents of the
220         # authorized_keys file as the user in question, so the
221         # file must be readable by that user at least.
222         # FIXME: is there a better way to do this?
223         chown root "$AUTHORIZED_KEYS"
224         chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
225         chmod g+r "$AUTHORIZED_KEYS"
226
227         # move the resulting authorized_keys file into place
228         mv -f "$AUTHORIZED_KEYS" "${VARLIB}/authorized_keys/${uname}"
229
230         # destroy temporary directory
231         rm -rf "$TMPDIR"
232     done
233 }
234
235 # generate server gpg key
236 gen_key() {
237     local keyType
238     local keyLength
239     local keyUsage
240     local keyExpire
241     local revoker
242     local hostName
243     local userID
244     local keyParameters
245     local fingerprint
246
247     # set default key parameter values
248     keyType="RSA"
249     keyLength="2048"
250     keyUsage="auth"
251     keyExpire=
252     revoker=
253
254     # get options
255     TEMP=$(getopt -o e:l:r -l expire:,length:,revoker: -n "$PGRM" -- "$@")
256
257     if [ $? != 0 ] ; then
258         exit 1
259     fi
260
261     # Note the quotes around `$TEMP': they are essential!
262     eval set -- "$TEMP"
263
264     while true ; do
265         case "$1" in
266             -l|--length)
267                 keyLength="$2"
268                 shift 2
269                 ;;
270             -e|--expire)
271                 keyExpire="$2"
272                 shift 2
273                 ;;
274             -r|--revoker)
275                 revoker="$2"
276                 shift 2
277                 ;;
278             --)
279                 shift
280                 ;;
281             *)
282                 break
283                 ;;
284         esac
285     done
286
287     hostName=${1:-$(hostname --fqdn)}
288     userID="ssh://${hostName}"
289
290     # check for presense of key with user ID
291     if gpg_host --list-key ="$userID" > /dev/null 2>&1 ; then
292         failure "Key for '$userID' already exists"
293     fi
294
295     # prompt about key expiration if not specified
296     if [ -z "$keyExpire" ] ; then
297         cat <<EOF
298 Please specify how long the key should be valid.
299          0 = key does not expire
300       <n>  = key expires in n days
301       <n>w = key expires in n weeks
302       <n>m = key expires in n months
303       <n>y = key expires in n years
304 EOF
305         while [ -z "$keyExpire" ] ; do
306             read -p "Key is valid for? (0) " keyExpire
307             if ! test_gpg_expire ${keyExpire:=0} ; then
308                 echo "invalid value"
309                 unset keyExpire
310             fi
311         done
312     elif ! test_gpg_expire "$keyExpire" ; then
313         failure "invalid key expiration value '$keyExpire'."
314     fi
315
316     # set key parameters
317     keyParameters=$(cat <<EOF
318 Key-Type: $keyType
319 Key-Length: $keyLength
320 Key-Usage: $keyUsage
321 Name-Real: $userID
322 Expire-Date: $keyExpire
323 EOF
324 )
325
326     # add the revoker field if specified
327     # FIXME: the "1:" below assumes that $REVOKER's key is an RSA key.
328     # FIXME: key is marked "sensitive"?  is this appropriate?
329     if [ "$revoker" ] ; then
330         keyParameters="${keyParameters}"$(cat <<EOF
331 Revoker: 1:$revoker sensitive
332 EOF
333 )
334     fi
335
336     echo "The following key parameters will be used for the host private key:"
337     echo "$keyParameters"
338
339     read -p "Generate key? (Y/n) " OK; OK=${OK:=Y}
340     if [ ${OK/y/Y} != 'Y' ] ; then
341         failure "aborting."
342     fi
343
344     # add commit command
345     keyParameters="${keyParameters}"$(cat <<EOF
346
347 %commit
348 %echo done
349 EOF
350 )
351
352     log "generating server key..."
353     echo "$keyParameters" | gpg_host --batch --gen-key
354
355     # output the server fingerprint
356     fingerprint_server_key "=${userID}"
357
358     # find the key fingerprint of the newly generated key
359     fingerprint=$(fingerprint_server_key)
360
361     # export host ownertrust to authentication keyring
362     log "setting ultimate owner trust for server key..."
363     echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
364
365     # translate the private key to ssh format, and export to a file
366     # for sshs usage.
367     # NOTE: assumes that the primary key is the proper key to use
368     (umask 077 && \
369         gpg_host --export-secret-key "$fingerprint" | \
370         openpgp2ssh "$fingerprint" > "${VARLIB}/ssh_host_rsa_key")
371     log "Private SSH host key output to file: ${VARLIB}/ssh_host_rsa_key"
372 }
373
374 # add hostname user ID to server key
375 add_hostname() {
376     local userID
377     local fingerprint
378     local adduidCommand
379
380     if [ -z "$1" ] ; then
381         failure "You must specify a hostname to add."
382     fi
383
384     userID="ssh://${1}"
385
386     if [ "$(gpg_host --list-key "=${userID}" 2> /dev/null)" ] ; then
387         failure "Host userID '$userID' already exists."
388     fi
389
390     echo "The following user ID will be added to the host key:"
391     echo "  '$userID'"
392     read -p "Are you sure you would like to add this user ID? (y/N) " OK; OK=${OK:=N}
393     if [ ${OK/y/Y} != 'Y' ] ; then
394         failure "user ID not added."
395     fi
396
397     fingerprint=$(fingerprint_server_key)
398
399     # edit-key script command to add user ID
400     adduidCommand=$(cat <<EOF
401 adduid
402 $userID
403
404
405 save
406 EOF
407         )
408
409     # execute edit-key script
410     echo "$adduidCommand" | gpg_host --quiet --command-fd 0 --edit-key "$fingerprint"
411
412     # update trust db
413     gpg_host --check-trustdb
414
415     show_server_key
416
417     # publish the key
418     publish_server_key
419 }
420
421 # revoke hostname user ID to server key
422 revoke_hostname() {
423     local userID
424     local uidIndex
425
426     if [ -z "$1" ] ; then
427         failure "You must specify a hostname to revoke."
428     fi
429
430     userID="ssh://${1}"
431
432     fingerprint=$(fingerprint_server_key)
433
434     # find the index of the requsted user ID
435     # NOTE: this is based on circumstantial evidence that the order of
436     # this output is the appropriate index
437     uidIndex=$(gpg_host --with-colons --fixed-list-mode --list-key "$fingerprint" 2> /dev/null | \
438         egrep "^(uid|uat):" | cut -d: -f10 | gpg_unescape | cat -n | \
439         grep "$userID" | awk '{ print $1 }')
440
441     if [ -z "$uidIndex" ] ; then
442         failure "User ID '$userID' not found in host key."
443     fi
444
445     echo "The following user ID will be revoked from the host key:"
446     echo "  '$userID'"
447     read -p "Are you sure you would like to revoke this user ID? (y/N) " OK; OK=${OK:=N}
448     if [ ${OK/y/Y} != 'Y' ] ; then
449         failure "user ID not revoked."
450     fi
451
452     # edit-key script command to revoke user ID
453     revuidCommand=$(cat <<EOF
454 $uidIndex
455 revuid
456 y
457 4
458
459 y
460 save
461 EOF
462         )       
463
464     # execute edit-key script
465     echo "$revuidCommand" | gpg_host --quiet --command-fd 0 --edit-key "$fingerprint"
466
467     # update trust db
468     gpg_host --check-trustdb
469
470     show_server_key
471
472     # publish the key
473     publish_server_key
474 }
475
476 # publish server key to keyserver
477 publish_server_key() {
478     read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
479     if [ ${OK/y/Y} != 'Y' ] ; then
480         failure "key not published."
481     fi
482
483     # find the key fingerprint
484     fingerprint=$(fingerprint_server_key)
485
486     # publish host key
487     gpg_authentication "--keyserver $KEYSERVER --send-keys $fingerprint"
488 }
489
490 diagnostics() {
491 #  * check on the status and validity of the key and public certificates
492     local seckey
493     local keysfound
494     local curdate
495     local warnwindow
496     local warndate
497     local create
498     local expire
499     local uid
500     local fingerprint
501     local badhostkeys
502
503     seckey=$(fingerprint_server_key)
504     keysfound=$(echo "$seckey" | grep -c ^sec:)
505     curdate=$(date +%s)
506     # warn when anything is 2 months away from expiration
507     warnwindow='2 months'
508     warndate=$(date +%s -d "$warnwindow")
509
510     echo "Checking host GPG key..."
511     if (( "$keysfound" < 1 )); then
512         echo "! No host key found."
513         echo " - Recommendation: run 'monkeysphere-server gen-key'"
514     elif (( "$keysfound" > 1 )); then
515         echo "! More than one host key found?"
516         # FIXME: recommend a way to resolve this
517     else
518         create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
519         expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
520         fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
521         # check for key expiration:
522         if [ "$expire" ]; then
523             if (( "$expire"  < "$curdate" )); then
524                 echo "! Host key is expired."
525                 # FIXME: recommend a way to resolve this other than re-keying?
526             elif (( "$expire" < "$warndate" )); then
527                 echo "! Host key expires in less than $warnwindow:" $(date -d "$(( $expire - $curdate )) seconds" +%F)
528                 # FIXME: recommend a way to resolve this?
529             fi
530         fi
531
532         # and weirdnesses:
533         if [ "$create" ] && (( "$create" > "$curdate" )); then
534             echo "! Host key was created in the future(?!). Is your clock correct?"
535             echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
536         fi
537
538         # check for UserID expiration:
539         echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
540         while IFS=: read create expire uid ; do
541             # FIXME: should we be doing any checking on the form
542             # of the User ID?  Should we be unmangling it somehow?
543
544             if [ "$create" ] && (( "$create" > "$curdate" )); then
545                 echo "! User ID '$uid' was created in the future(?!).  Is your clock correct?"
546                 echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
547             fi
548             if [ "$expire" ] ; then
549                 if (( "$expire" < "$curdate" )); then
550                     echo "! User ID '$uid' is expired."
551                         # FIXME: recommend a way to resolve this
552                 elif (( "$expire" < "$warndate" )); then
553                     echo "! User ID '$uid' expires in less than $warnwindow:" $(date -d "$(( $expire - $curdate )) seconds" +%F)                
554                     # FIXME: recommend a way to resolve this
555                 fi
556             fi
557         done
558             
559 # FIXME: verify that the host key is properly published to the
560 #   keyservers (do this with the non-privileged user)
561
562 # FIXME: check that there are valid, non-expired certifying signatures
563 #   attached to the host key after fetching from the public keyserver
564 #   (do this with the non-privileged user as well)
565
566 # FIXME: propose adding a revoker to the host key if none exist (do we
567 #   have a way to do that after key generation?)
568
569         # Ensure that the ssh_host_rsa_key file is present and non-empty:
570         echo "Checking host SSH key..."
571         if [ ! -s "${VARLIB}/ssh_host_rsa_key" ] ; then
572             echo "! The host key as prepared for SSH (${VARLIB}/ssh_host_rsa_key) is missing or empty."
573         else
574             if [ $(stat -c '%a' "${VARLIB}/ssh_host_rsa_key") != 600 ] ; then
575                 echo "! Permissions seem wrong for ${VARLIB}/ssh_host_rsa_key -- should be 0600."
576             fi
577
578             # propose changes needed for sshd_config (if any)
579             if ! grep -q "^HostKey[[:space:]]\+${VARLIB}/ssh_host_rsa_key$" /etc/ssh/sshd_config; then
580                 echo "! /etc/ssh/sshd_config does not point to the monkeysphere host key (${VARLIB}/ssh_host_rsa_key)."
581                 echo " - Recommendation: add a line to /etc/ssh/sshd_config: 'HostKey ${VARLIB}/ssh_host_rsa_key'"
582             fi
583             if badhostkeys=$(grep -i '^HostKey' | grep -q -v "^HostKey[[:space:]]\+${VARLIB}/ssh_host_rsa_key$") ; then
584                 echo "! /etc/sshd_config refers to some non-monkeysphere host keys:"
585                 echo "$badhostkeys"
586                 echo " - Recommendation: remove the above HostKey lines from /etc/ssh/sshd_config"
587             fi
588         fi
589     fi
590
591 # FIXME: look at the ownership/privileges of the various keyrings,
592 #    directories housing them, etc (what should those values be?  can
593 #    we make them as minimal as possible?)
594
595 # FIXME: look to see that the ownertrust rules are set properly on the
596 #    authentication keyring
597
598 # FIXME:  make sure that at least one identity certifier exists
599
600     echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
601     # Ensure that User ID authentication is enabled:
602     if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${VARLIB}/authorized_keys/%u$" /etc/ssh/sshd_config; then
603         echo "! /etc/ssh/sshd_config does not point to monkeysphere authorized keys."
604         echo " - Recommendation: add a line to /etc/ssh/sshd_config: 'AuthorizedKeysFile ${VARLIB}/authorized_keys/%u'"
605     fi
606     if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' | grep -q -v "^AuthorizedKeysFile[[:space:]]\+${VARLIB}/authorized_keys/%u$") ; then
607         echo "! /etc/sshd_config refers to non-monkeysphere authorized_keys files:"
608         echo "$badauthorizedkeys"
609         echo " - Recommendation: remove the above AuthorizedKeysFile lines from /etc/ssh/sshd_config"
610     fi
611 }
612
613 # retrieve key from web of trust, import it into the host keyring, and
614 # ltsign the key in the host keyring so that it may certify other keys
615 add_certifier() {
616     local domain
617     local trust
618     local depth
619     local keyID
620     local fingerprint
621     local ltsignCommand
622     local trustval
623
624     # set default values for trust depth and domain
625     domain=
626     trust=full
627     depth=1
628
629     # get options
630     TEMP=$(getopt -o n:t:d: -l domain:,trust:,depth: -n "$PGRM" -- "$@")
631
632     if [ $? != 0 ] ; then
633         exit 1
634     fi
635
636     # Note the quotes around `$TEMP': they are essential!
637     eval set -- "$TEMP"
638
639     while true ; do
640         case "$1" in
641             -n|--domain)
642                 domain="$2"
643                 shift 2
644                 ;;
645             -t|--trust)
646                 trust="$2"
647                 shift 2
648                 ;;
649             -d|--depth)
650                 depth="$2"
651                 shift 2
652                 ;;
653             --)
654                 shift
655                 ;;
656             *)
657                 break
658                 ;;
659         esac
660     done
661
662     keyID="$1"
663     if [ -z "$keyID" ] ; then
664         failure "You must specify the key ID of a key to add."
665     fi
666     export keyID
667
668     # get the key from the key server
669     gpg_authentication "--keyserver $KEYSERVER --recv-key '$keyID'"
670
671     # get the full fingerprint of a key ID
672     fingerprint=$(gpg_authentication "--list-key --with-colons --with-fingerprint $keyID" | \
673         grep '^fpr:' | grep "$keyID" | cut -d: -f10)
674
675     echo "key found:"
676     gpg_authentication "--fingerprint $fingerprint"
677
678     echo "Are you sure you want to add this key as a certifier of"
679     read -p "users on this system? (y/N) " OK; OK=${OK:-N}
680     if [ "${OK/y/Y}" != 'Y' ] ; then
681         failure "aborting."
682     fi
683
684     # export the key to the host keyring
685     gpg_authentication "--export $keyID" | gpg_host --import
686
687     if [ "$trust" == marginal ]; then
688         trustval=1
689     elif [ "$trust" == full ]; then
690         trustval=2
691     else
692         failure "trust value requested ('$trust') was unclear (only 'marginal' or 'full' are supported)"
693     fi
694
695     # ltsign command
696     # NOTE: *all* user IDs will be ltsigned
697     ltsignCommand=$(cat <<EOF
698 ltsign
699 y
700 $trustval
701 $depth
702 $domain
703 y
704 save
705 EOF
706         )
707
708     # ltsign the key
709     echo "$ltsignCommand" | gpg_host --quiet --command-fd 0 --edit-key "$fingerprint"
710
711     # update the trustdb for the authentication keyring
712     gpg_authentication "--check-trustdb"
713 }
714
715 # delete a certifiers key from the host keyring
716 remove_certifier() {
717     local keyID
718     local fingerprint
719
720     keyID="$1"
721     if [ -z "$keyID" ] ; then
722         failure "You must specify the key ID of a key to remove."
723     fi
724
725     # delete the requested key (with prompting)
726     gpg_host --delete-key "$keyID"
727
728     # update the trustdb for the authentication keyring
729     gpg_authentication "--check-trustdb"
730 }
731
732 # list the host certifiers
733 list_certifiers() {
734     gpg_host --list-keys
735 }
736
737 # issue command to gpg-authentication keyring
738 gpg_authentication_cmd() {
739     gpg_authentication "$@"
740 }
741
742 ########################################################################
743 # MAIN
744 ########################################################################
745
746 # unset variables that should be defined only in config file
747 unset KEYSERVER
748 unset AUTHORIZED_USER_IDS
749 unset RAW_AUTHORIZED_KEYS
750 unset MONKEYSPHERE_USER
751
752 # load configuration file
753 [ -e ${MONKEYSPHERE_SERVER_CONFIG:="${ETC}/monkeysphere-server.conf"} ] && . "$MONKEYSPHERE_SERVER_CONFIG"
754
755 # set empty config variable with ones from the environment, or with
756 # defaults
757 KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="subkeys.pgp.net"}}
758 AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.config/monkeysphere/authorized_user_ids"}}
759 RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
760 MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
761
762 # other variables
763 CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
764 REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"}
765 GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${VARLIB}/gnupg-host"}
766 GNUPGHOME_AUTHENTICATION=${MONKEYSPHERE_GNUPGHOME_AUTHENTICATION:="${VARLIB}/gnupg-authentication"}
767
768 # export variables needed in su invocation
769 export DATE
770 export MODE
771 export MONKEYSPHERE_USER
772 export KEYSERVER
773 export CHECK_KEYSERVER
774 export REQUIRED_USER_KEY_CAPABILITY
775 export GNUPGHOME_HOST
776 export GNUPGHOME_AUTHENTICATION
777 export GNUPGHOME
778
779 # get subcommand
780 COMMAND="$1"
781 [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
782 shift
783
784 case $COMMAND in
785     'update-users'|'update-user'|'u')
786         update_users "$@"
787         ;;
788
789     'gen-key'|'g')
790         gen_key "$@"
791         ;;
792
793     'add-hostname'|'add-name'|'n+')
794         add_hostname "$@"
795         ;;
796
797     'revoke-hostname'|'revoke-name'|'n-')
798         revoke_hostname "$@"
799         ;;
800
801     'show-key'|'show'|'s')
802         show_server_key
803         ;;
804
805     'show-fingerprint'|'fingerprint'|'f')
806         fingerprint_server_key
807         ;;
808
809     'publish-key'|'publish'|'p')
810         publish_server_key
811         ;;
812
813     'diagnostics'|'d')
814         diagnostics
815         ;;
816
817     'add-identity-certifier'|'add-id-certifier'|'add-certifier'|'c+')
818         add_certifier "$@"
819         ;;
820
821     'remove-identity-certifier'|'remove-id-certifier'|'remove-certifier'|'c-')
822         remove_certifier "$@"
823         ;;
824
825     'list-identity-certifiers'|'list-id-certifiers'|'list-certifiers'|'list-certifier'|'c')
826         list_certifiers "$@"
827         ;;
828
829     'gpg-authentication-cmd')
830         gpg_authentication_cmd "$@"
831         ;;
832
833     '--help'|'help'|'-h'|'h'|'?')
834         usage
835         ;;
836
837     *)
838         failure "Unknown command: '$COMMAND'
839 Type '$PGRM help' for usage."
840         ;;
841 esac
842
843 exit "$RETURN"