New client/server components:
[monkeysphere.git] / src / monkeysphere-server
1 #!/bin/sh
2
3 ########################################################################
4 PGRM=$(basename $0)
5
6 SHAREDIR=${SHAREDIR:-"/usr/share/monkeysphere"}
7 export SHAREDIR
8 . "${SHAREDIR}/common"
9
10 # date in UTF format if needed
11 DATE=$(date -u '+%FT%T')
12
13 # unset some environment variables that could screw things up
14 GREP_OPTIONS=
15
16 ########################################################################
17 # FUNCTIONS
18 ########################################################################
19
20 usage() {
21 cat <<EOF
22 usage: $PGRM <subcommand> [args]
23 Monkeysphere server admin tool.
24
25 subcommands:
26   update-users (s) [USER]...                update authorized_keys file
27   gen-key (g)                               generate gpg key for the host
28   publish-key (p)                           publish host gpg to keyserver
29   trust-key (t) KEYID [KEYID]...            mark keyid as trusted
30   update-user-userid (u) USER UID [UID]...  add/update userid for user
31   help (h,?)                                this help
32
33 EOF
34 }
35
36 # generate server gpg key
37 gen_key() {
38     KEY_TYPE=${KEY_TYPE:-RSA}
39     KEY_LENGTH=${KEY_LENGTH:-2048}
40     KEY_USAGE=${KEY_USAGE:-encrypt,auth}
41     SERVICE=${SERVICE:-ssh}
42     HOSTNAME_FQDN=${HOSTNAME_FQDN:-$(hostname -f)}
43
44     USERID=${USERID:-"$SERVICE"://"$HOSTNAME_FQDN"}
45
46     echo "key parameters:"
47     cat <<EOF
48 Key-Type: $KEY_TYPE
49 Key-Length: $KEY_LENGTH
50 Key-Usage: $KEY_USAGE
51 Name-Real: $USERID
52 EOF
53
54     read -p "generate key? [Y|n]: " OK; OK=${OK:=Y}
55     if [ ${OK/y/Y} != 'Y' ] ; then
56         failure "aborting."
57     fi
58
59     if gpg --list-key ="$USERID" > /dev/null 2>&1 ; then
60         failure "key for '$USERID' already exists"
61     fi
62
63     echo "generating server key..."
64     gpg --batch --gen-key <<EOF
65 Key-Type: $KEY_TYPE
66 Key-Length: $KEY_LENGTH
67 Key-Usage: $KEY_USAGE
68 Name-Real: $USERID
69 %commit
70 EOF
71 }
72
73 # publish server key to keyserver
74 publish_key() {
75     read -p "publish key to $KEYSERVER? [Y|n]: " OK; OK=${OK:=Y}
76     if [ ${OK/y/Y} != 'Y' ] ; then
77         failure "aborting."
78     fi
79
80     keyID=$(gpg --list-key --with-colons ="$USERID" 2> /dev/null | grep '^pub:' | cut -d: -f5)
81
82     # dummy command so as not to publish fakes keys during testing
83     # eventually:
84     #gpg --send-keys --keyserver "$KEYSERVER" "$keyID"
85     echo "gpg --send-keys --keyserver $KEYSERVER $keyID"
86 }
87
88 # trust key
89 trust_key() {
90     for keyID ; do
91         # get the key from the key server
92         gpg --keyserver "$KEYSERVER" --recv-key "$keyID" || failure "could not retrieve key '$keyID'"
93
94         # edit the key to change trust
95         # FIXME: need to figure out how to automate this,
96         # in a batch mode or something.
97         gpg --edit-key "$keyID"
98     done
99 }
100
101 ########################################################################
102 # MAIN
103 ########################################################################
104
105 COMMAND="$1"
106 [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
107 shift
108
109 # set ms home directory
110 MS_HOME=${MS_HOME:-"$ETC"}
111
112 # load configuration file
113 MS_CONF=${MS_CONF:-"$MS_HOME"/monkeysphere-server.conf}
114 [ -e "$MS_CONF" ] && . "$MS_CONF"
115
116 # set empty config variable with defaults
117 GNUPGHOME=${GNUPGHOME:-"$MS_HOME"/gnupg}
118 KEYSERVER=${KEYSERVER:-subkeys.pgp.net}
119 REQUIRED_KEY_CAPABILITY=${REQUIRED_KEY_CAPABILITY:-"e a"}
120 USER_CONTROLLED_AUTHORIZED_KEYS=${USER_CONTROLLED_AUTHORIZED_KEYS:-%h/.ssh/authorized_keys}
121 STAGING_AREA=${STAGING_AREA:-"$LIB"/stage}
122
123 export GNUPGHOME
124
125 # make sure gpg home exists with proper permissions
126 mkdir -p -m 0700 "$GNUPGHOME"
127
128 case $COMMAND in
129     'update-users'|'s')
130         if [ "$1" ] ; then
131             unames="$@"
132         else
133             unames=$(ls -1 "$MS_HOME"/authorized_user_ids)
134         fi
135
136         for uname in $unames ; do
137             MODE="authorized_keys"
138             authorizedUserIDs="$MS_HOME"/authorized_user_ids/"$uname"
139             cacheDir="$STAGING_AREA"/"$uname"/user_keys
140             msAuthorizedKeys="$STAGING_AREA"/"$uname"/authorized_keys
141
142             # make sure authorized_user_ids file exists
143             if [ ! -s "$authorizedUserIDs" ] ; then
144                 log "authorized_user_ids file for '$uname' is empty or does not exist."
145                 continue
146             fi
147
148             log "processing authorized_keys for user '$uname'..."
149
150             process_authorized_ids "$authorizedUserIDs" "$cacheDir"
151
152             # write output key file
153             log "writing monkeysphere authorized_keys file... "
154             touch "$msAuthorizedKeys"
155             if [ "$(ls "$cacheDir")" ] ; then
156                 log -n "adding gpg keys... "
157                 cat "$cacheDir"/* > "$msAuthorizedKeys"
158                 echo "done."
159             else
160                 log "no gpg keys to add."
161             fi
162             if [ "$USER_CONTROLLED_AUTHORIZED_KEYS" ] ; then
163                 userHome=$(getent passwd "$uname" | cut -d: -f6)
164                 userAuthorizedKeys=${USER_CONTROLLED_AUTHORIZED_KEYS/\%h/"$userHome"}
165                 if [ -s "$userAuthorizedKeys" ] ; then
166                     log -n "adding user authorized_keys file... "
167                     cat "$userAuthorizedKeys" >> "$msAuthorizedKeys"
168                     echo "done."
169                 fi
170             fi
171             log "monkeysphere authorized_keys file generated:"
172             log "$msAuthorizedKeys"
173         done
174         ;;
175
176     'gen-key'|'g')
177         gen_key
178         ;;
179
180     'publish-key'|'p')
181         publish_key
182         ;;
183
184     'trust-key'|'t')
185         if [ -z "$1" ] ; then
186             failure "you must specify at least one key to trust."
187         fi
188         trust_key "$@"
189         ;;
190
191     'update-user-userid'|'u')
192         uname="$1"
193         shift
194         if [ -z "$uname" ] ; then
195             failure "you must specify user."
196         fi
197         if [ -z "$1" ] ; then
198             failure "you must specify at least one userid."
199         fi
200         for userID ; do
201             AUTHORIZED_USER_IDS="$MS_HOME"/authorized_user_ids/"$uname"
202             if ! grep -q "^${userID}\$" "$AUTHORIZED_USER_IDS" ; then
203                 log "userid '$userID' not in authorized_user_ids file."
204                 continue
205             fi
206             log "processing user id: '$userID'"
207             process_user_id "$userID" "$userKeysCacheDir" > /dev/null
208         done
209         ;;
210
211     'help'|'h'|'?')
212         usage
213         ;;
214
215     *)
216         failure "Unknown command: '$COMMAND'
217 Type 'cereal-admin help' for usage."
218         ;;
219 esac