Package: monkeysphere
Version: 0.35-2
Severity: normal

monkeysphere-authentication reads ~/.ssh/* not as that user but as root.

That commonly works because root ignores filesystem ACLs, but fails e.g.
when $HOME is served with NFS exported with default root_squash option.

To work properly in environments where ACLs apply also to root,
monkeysphere needs to switch user before reading ~/.ssh/*, as that dir
is private by default.

Dkg wondered on irc if not OpenSSH "cheated" as well, to only switch
user after authentication.  But running OpenSSH with DEBUG enabled
reveals that each client connection - before authentication completes -
cuase a log entry like this:

Feb  7 20:15:39 xayide sshd[32641]: debug1: temporarily_use_uid: 1000/1000 
(e=0/0)


Attached are proposed patches to fix this issue.

  * Perhaps better to switch user only once per account, running all
    checks as one single shell script?

  * Perhaps better to exec checkperms as account user?
    Currently works only with MONKEYSPHERE_STRICT_MODES=false which is
    arguably more risky than executing the relatively large checkperms
    perl script.


 - Jonas
--- a/common
+++ b/common
@@ -118,6 +118,60 @@
     esac
 }
 
+# check if private file exists and has a size greater than zero
+su_user_test_nonempty() {
+    # Simple filesystems let superuser bypass ACLs, but others like nfs
+    # and afs respects privacy and need to switch user to gain access to
+    # e.g. ssh config files which are private by default.
+
+    user="$1"
+    shift
+
+    case $(id -un) in
+	# if same user, check directly
+	"$user")
+	    test -s "$1"
+	    ;;
+
+         # if root, su check as user
+	'root')
+	    su "$user" -c "test -s '$1'"
+	    ;;
+
+	# otherwise, fail
+	*)
+	    log error "cannot check file as different non-privileged user."
+	    ;;
+    esac
+}
+
+# read private file
+su_user_cat() {
+    # Simple filesystems let superuser bypass ACLs, but others like nfs
+    # and afs respects privacy and need to switch user to gain access to
+    # e.g. ssh config files which are private by default.
+
+    user="$1"
+    shift
+
+    case $(id -un) in
+	# if same user, cat directly
+	"$user")
+	    cat -- "$1"
+	    ;;
+
+         # if root, su cat as user
+	'root')
+	    su "$user" -c "cat -- '$1'"
+	    ;;
+
+	# otherwise, fail
+	*)
+	    log error "cannot read file as different non-privileged user."
+	    ;;
+    esac
+}
+
 # cut out all comments(#) and blank lines from standard input
 meat() {
     grep -v -e "^[[:space:]]*#" -e '^$' "$1"
--- a/ma/update_users
+++ b/ma/update_users
@@ -95,12 +95,12 @@
     rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
     if [ "$rawAuthorizedKeys" != 'none' ] ; then
 	log debug "checking for raw authorized_keys..."
-	if [ -s "$rawAuthorizedKeys" ] ; then
+	if su_user_test_nonempty "$uname" "$rawAuthorizedKeys" ] ; then
 	    # check permissions on the authorized_keys file path
 	    if check_key_file_permissions "$uname" "$rawAuthorizedKeys" ; then
 		log verbose "adding raw authorized_keys..."
 
-		cat "$rawAuthorizedKeys" >> "$tmpAuthorizedKeys"
+		su_user_cat "$uname" "$rawAuthorizedKeys" >> "$tmpAuthorizedKeys"
 
 	    else
 		log debug "not adding raw authorized_keys."

Reply via email to