From: Jameson Graef Rollins <jrollins@phys.columbia.edu>
Date: Fri, 20 Jun 2008 04:44:36 +0000 (-0400)
Subject: add file locking to known_hosts and authorized_keys
X-Git-Tag: monkeysphere_0.2-1~18^2
X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=736054b1c1d8e3433d709ea8bbeb1b8ac7257927;p=monkeysphere.git

add file locking to known_hosts and authorized_keys
---

diff --git a/debian/changelog b/debian/changelog
index bd12e1a..2133d2d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,8 +10,9 @@ monkeysphere (0.2-1) UNRELEASED; urgency=low
   * Remove {update,remove}-userids functions, since we decided they
     weren't useful enough to be worth maintaining.
   * Better handling of unknown users in server update-users
+  * Add file locking when modifying known_hosts or authorized_keys
 
- -- Jameson Graef Rollins <jrollins@phys.columbia.edu>  Thu, 19 Jun 2008 18:08:57 -0400
+ -- Jameson Graef Rollins <jrollins@phys.columbia.edu>  Fri, 20 Jun 2008 00:43:44 -0400
 
 monkeysphere (0.1-1) experimental; urgency=low
 
diff --git a/src/common b/src/common
index e98f1bc..7df6908 100644
--- a/src/common
+++ b/src/common
@@ -376,62 +376,79 @@ process_user_id() {
     done
 }
 
-# process a host in known_host file
-process_host_known_hosts() {
+# process hosts in the known_host file
+process_hosts_known_hosts() {
     local host
     local userID
     local ok
     local keyid
     local tmpfile
 
-    host="$1"
-    userID="ssh://${host}"
-
-    log "processing host: $host"
-
-    process_user_id "ssh://${host}" | \
-    while read -r ok keyid ; do
-	sshKey=$(gpg2ssh "$keyid")
-	# remove the old host key line
-	remove_line "$KNOWN_HOSTS" "$sshKey"
-	# if key OK, add new host line
-	if [ "$ok" -eq '0' ] ; then
-	    # hash if specified
-	    if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then
-		# FIXME: this is really hackish cause ssh-keygen won't
-		# hash from stdin to stdout
-		tmpfile=$(mktemp)
-		ssh2known_hosts "$host" "$sshKey" > "$tmpfile"
-		ssh-keygen -H -f "$tmpfile" 2> /dev/null
-		cat "$tmpfile" >> "$KNOWN_HOSTS"
-		rm -f "$tmpfile" "${tmpfile}.old"
-	    else
-		ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS"
+    # create a lockfile on known_hosts
+    lockfile-create "$KNOWN_HOSTS"
+
+    for host ; do
+	log "processing host: $host"
+
+	userID="ssh://${host}"
+
+	process_user_id "ssh://${host}" | \
+	while read -r ok keyid ; do
+	    sshKey=$(gpg2ssh "$keyid")
+	    # remove the old host key line
+	    remove_line "$KNOWN_HOSTS" "$sshKey"
+	    # if key OK, add new host line
+	    if [ "$ok" -eq '0' ] ; then
+		# hash if specified
+		if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then
+		    # FIXME: this is really hackish cause ssh-keygen won't
+		    # hash from stdin to stdout
+		    tmpfile=$(mktemp)
+		    ssh2known_hosts "$host" "$sshKey" > "$tmpfile"
+		    ssh-keygen -H -f "$tmpfile" 2> /dev/null
+		    cat "$tmpfile" >> "$KNOWN_HOSTS"
+		    rm -f "$tmpfile" "${tmpfile}.old"
+		else
+		    ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS"
+		fi
 	    fi
-	fi
+	done
+	# touch the lockfile, for good measure.
+	lockfile-touch --oneshot "$KNOWN_HOSTS"
     done
+
+    # remove the lockfile
+    lockfile-remove "$KNOWN_HOSTS"
 }
 
-# process a uid in an authorized_keys file
-process_uid_authorized_keys() {
+# process uids for the authorized_keys file
+process_uids_authorized_keys() {
     local userID
     local ok
     local keyid
 
-    userID="$1"
+    # create a lockfile on authorized_keys
+    lockfile-create "$AUTHORIZED_KEYS"
 
-    log "processing user ID: $userID"
+    for userID ; do
+	log "processing user ID: $userID"
 
-    process_user_id "$userID" | \
-    while read -r ok keyid ; do
-	sshKey=$(gpg2ssh "$keyid")
-	# remove the old host key line
-	remove_line "$AUTHORIZED_KEYS" "$sshKey"
-	# if key OK, add new host line
-	if [ "$ok" -eq '0' ] ; then
-	    ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS"
-	fi
+	process_user_id "$userID" | \
+	while read -r ok keyid ; do
+	    sshKey=$(gpg2ssh "$keyid")
+	    # remove the old host key line
+	    remove_line "$AUTHORIZED_KEYS" "$sshKey"
+	    # if key OK, add new host line
+	    if [ "$ok" -eq '0' ] ; then
+		ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS"
+	    fi
+	done
+	# touch the lockfile, for good measure.
+	lockfile-touch --oneshot "$AUTHORIZED_KEYS"
     done
+
+    # remove the lockfile
+    lockfile-remove "$AUTHORIZED_KEYS"
 }
 
 # process known_hosts file
@@ -446,10 +463,7 @@ process_known_hosts() {
     cat "$KNOWN_HOSTS" | meat | \
 	cut -d ' ' -f 1 | grep -v '^|.*$' | \
     while IFS=, read -r -a hosts ; do
-	# and process each host
-	for host in ${hosts[*]} ; do
-	    process_host_known_hosts "$host"
-	done
+	process_hosts_known_hosts ${hosts[@]}
     done
 }
 
@@ -461,7 +475,7 @@ process_authorized_user_ids() {
 
     cat "$authorizedUserIDs" | meat | \
     while read -r userid ; do
-	process_uid_authorized_keys "$userid"
+	process_uids_authorized_keys "$userid"
     done
 }
 
diff --git a/src/monkeysphere b/src/monkeysphere
index a433701..58f0fdc 100755
--- a/src/monkeysphere
+++ b/src/monkeysphere
@@ -140,12 +140,9 @@ case $COMMAND in
         # if hosts are specified on the command line, process just
         # those hosts
 	if [ "$1" ] ; then
-            for host ; do
-		process_host_known_hosts "$host"
-	    done
-	    log "known_hosts file updated."
+	    process_hosts_known_hosts "$@"
 
-        # otherwise, if no hosts are specified, process every user
+        # otherwise, if no hosts are specified, process every host
         # in the user's known_hosts file
 	else
 	    if [ ! -s "$KNOWN_HOSTS" ] ; then
@@ -153,8 +150,9 @@ case $COMMAND in
 	    fi
 	    log "processing known_hosts file..."
 	    process_known_hosts
-	    log "known_hosts file updated."
 	fi
+
+	log "known_hosts file updated."
 	;;
 
     'update-authorized_keys'|'update-authorized-keys'|'a')