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