change from using a filename that is a just a space to an actual temporary file
[monkeysphere.git] / src / monkeysphere-server
index 0c562799a3355a09207c7023e0d1044a7eea5451..5edaa4f2c9448dfabd74c535b536381641fea176 100755 (executable)
@@ -20,6 +20,11 @@ export SYSSHAREDIR
 SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
 export SYSDATADIR
 
+# monkeysphere temp directory, in sysdatadir to enable atomic moves of
+# authorized_keys files
+MSTMPDIR="${SYSDATADIR}/tmp"
+export MSTMPDIR
+
 # UTC date in ISO 8601 format if needed
 DATE=$(date -u '+%FT%T')
 
@@ -129,10 +134,10 @@ show_server_key() {
 
     # dumping to a file named ' ' so that the ssh-keygen output
     # doesn't claim any potentially bogus hostname(s):
-    tmpkey=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
-    gpg_authentication "--export $fingerprint" | openpgp2ssh "$fingerprint" 2>/dev/null > "$tmpkey"
+    tmpkey=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
+    gpg_authentication "--export $fingerprint" | openpgp2ssh "$fingerprint" 2>/dev/null > "$tmpkey"
     echo -n "ssh fingerprint: "
-    (cd "$tmpkey" && ssh-keygen -l -f ' ' | awk '{ print $2 }')
+    ssh-keygen -l -f $tmpkey | awk '{ print $1, $2, $4 }'
     rm -rf "$tmpkey"
     echo -n "OpenPGP fingerprint: "
     echo "$fingerprint"
@@ -148,6 +153,8 @@ update_users() {
        unames=$(getent passwd | cut -d: -f1)
     fi
 
+    RETCODE=0
+
     # set mode
     MODE="authorized_keys"
 
@@ -165,39 +172,15 @@ update_users() {
     # loop over users
     for uname in $unames ; do
        # check all specified users exist
-       if ! getent passwd "$uname" >/dev/null ; then
+       if ! id "$uname" >/dev/null ; then
            log error "----- unknown user '$uname' -----"
            continue
        fi
 
-       # set authorized_user_ids and raw authorized_keys variables,
-       # translating ssh-style path variables
-       authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
-       rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
-
-       # if neither is found, skip user
-       if [ ! -s "$authorizedUserIDs" ] ; then
-           if [ "$rawAuthorizedKeys" = '-' -o ! -s "$rawAuthorizedKeys" ] ; then
-               continue
-           fi
-       fi
-
        log verbose "----- user: $uname -----"
 
-        # exit if the authorized_user_ids file is empty
-       if ! check_key_file_permissions "$uname" "$AUTHORIZED_USER_IDS" ; then
-           log error "Improper permissions on path '$AUTHORIZED_USER_IDS'."
-           continue
-       fi
-
-       # check permissions on the authorized_keys file path
-       if ! check_key_file_permissions "$uname" "$RAW_AUTHORIZED_KEYS" ; then
-           log error "Improper permissions on path '$RAW_AUTHORIZED_KEYS'."
-           continue
-       fi
-
         # make temporary directory
-        TMPLOC=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+        TMPLOC=$(mktemp -d ${MSTMPDIR}/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
 
        # trap to delete temporary directory on exit
        trap "rm -rf $TMPLOC" EXIT
@@ -217,39 +200,81 @@ update_users() {
         chmod 0600 "$TMP_AUTHORIZED_USER_IDS"
         chown -R "$MONKEYSPHERE_USER" "$TMPLOC"
 
-       # if the authorized_user_ids file exists...
+       # process authorized_user_ids file
+       log debug "checking for authorized_user_ids..."
+       # translating ssh-style path variables
+       authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
        if [ -s "$authorizedUserIDs" ] ; then
-            # copy user authorized_user_ids file to temporary
-            # location
-           cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
-
-           # export needed variables
-           export AUTHORIZED_KEYS
-           export TMP_AUTHORIZED_USER_IDS
-
-           # process authorized_user_ids file, as monkeysphere
-           # user
-           su_monkeysphere_user \
-               ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
-           RETURN="$?"
+           # check permissions on the authorized_user_ids file path
+           if check_key_file_permissions "$uname" "$authorizedUserIDs" ; then
+                # copy user authorized_user_ids file to temporary
+                # location
+               cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
+
+               # export needed variables
+               export AUTHORIZED_KEYS
+               export TMP_AUTHORIZED_USER_IDS
+
+               # process authorized_user_ids file, as monkeysphere
+               # user
+               su_monkeysphere_user \
+                   ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
+               RETURN="$?"
+           else
+               log debug "not processing authorized_user_ids."
+           fi
+       else
+           log debug "empty or absent authorized_user_ids file."
        fi
 
-       # add user-controlled authorized_keys file path if specified
-       if [ "$rawAuthorizedKeys" != '-' -a -s "$rawAuthorizedKeys" ] ; then
-           log verbose "adding raw authorized_keys file... "
-           cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
+       # add user-controlled authorized_keys file if specified
+       # translate ssh-style path variables
+       rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
+       if [ "$rawAuthorizedKeys" != 'none' ] ; then
+           log debug "checking for raw authorized_keys..."
+           if [ -s "$rawAuthorizedKeys" ] ; then
+               # check permissions on the authorized_keys file path
+               if check_key_file_permissions "$uname" "$rawAuthorizedKeys" ; then
+                   log verbose "adding raw authorized_keys file... "
+                   cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
+               else
+                   log debug "not adding raw authorized_keys file."            
+               fi
+           else
+               log debug "empty or absent authorized_keys file."
+           fi
        fi
 
-       # openssh appears to check the contents of the
-        # authorized_keys file as the user in question, so the
-        # file must be readable by that user at least.
-       # FIXME: is there a better way to do this?
-       chown root "$AUTHORIZED_KEYS"
-       chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
-       chmod g+r "$AUTHORIZED_KEYS"
+       # move the new authorized_keys file into place
+       if [ -s "$AUTHORIZED_KEYS" ] ; then
+           # openssh appears to check the contents of the
+           # authorized_keys file as the user in question, so the
+           # file must be readable by that user at least.
+
+           # but in general, we don't want the user tampering with
+           # this file directly, so we'll adopt this approach: Own
+           # the file by the monkeysphere-server invoker (usually
+           # root, but should be the same uid that sshd is launched
+           # as); change the group of the file so that members of the
+           # user's group can read it.
+
+           # FIXME: is there a better way to do this?
+           chown $(whoami) "$AUTHORIZED_KEYS" && \
+               chgrp $(id -g "$uname") "$AUTHORIZED_KEYS" && \
+               chmod g+r "$AUTHORIZED_KEYS" && \
+               mv -f "$AUTHORIZED_KEYS" "${SYSDATADIR}/authorized_keys/${uname}" || \
+               { 
+               log error "Failed to install authorized_keys for '$uname'!"
+               rm -f "${SYSDATADIR}/authorized_keys/${uname}"
+               # indicate that there has been a failure:
+               RETURN=1
+               }
+       else
+           rm -f "${SYSDATADIR}/authorized_keys/${uname}"
+       fi
 
-       # move the resulting authorized_keys file into place
-       mv -f "$AUTHORIZED_KEYS" "${SYSDATADIR}/authorized_keys/${uname}"
+       # unset the trap
+       trap - EXIT
 
        # destroy temporary directory
        rm -rf "$TMPLOC"
@@ -374,7 +399,7 @@ EOF
     (umask 077 && \
        gpg_host --export-secret-key "$fingerprint" | \
        openpgp2ssh "$fingerprint" > "${SYSDATADIR}/ssh_host_rsa_key")
-    log info "Private SSH host key output to file: ${SYSDATADIR}/ssh_host_rsa_key"
+    log info "private SSH host key output to file: ${SYSDATADIR}/ssh_host_rsa_key"
 }
 
 # extend the lifetime of a host key: