summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Goins <mjgoins@openflows.com>2008-06-25 01:59:19 -0400
committerMatt Goins <mjgoins@openflows.com>2008-06-25 01:59:19 -0400
commit43097e923b8051ecd0912e367c1cd78149a97dbe (patch)
treee0553c718ea443a9f7f08a50c6ef1f7c9a9d953a
parentc1a5568ee2f6c46501df057a71f23681ea0194ec (diff)
parente0b50e3859931c7fe2a58bb08af440a4f2455174 (diff)
Merge branch 'master' of http://lair.fifthhorseman.net/~dkg/git/monkeysphere
-rw-r--r--debian/changelog30
-rw-r--r--debian/control4
-rw-r--r--debian/dirs4
-rw-r--r--debian/monkeysphere.dirs4
-rw-r--r--doc/TODO31
-rw-r--r--doc/george/changelog9
-rw-r--r--etc/monkeysphere-server.conf19
-rw-r--r--etc/monkeysphere.conf23
-rw-r--r--man/man1/openpgp2ssh.118
-rw-r--r--man/man8/monkeysphere-server.825
-rw-r--r--src/common228
-rw-r--r--src/keytrans/gnutls-helpers.c26
-rw-r--r--src/keytrans/gnutls-helpers.h13
-rw-r--r--src/keytrans/openpgp2ssh.c134
-rwxr-xr-xsrc/monkeysphere22
-rwxr-xr-xsrc/monkeysphere-server109
-rwxr-xr-xsrc/monkeysphere-ssh-proxycommand13
17 files changed, 471 insertions, 241 deletions
diff --git a/debian/changelog b/debian/changelog
index 41af80c..82f274a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,7 +1,31 @@
-monkeysphere (0.2-1) UNRELEASED; urgency=low
+monkeysphere (0.4-1) UNRELEASED; urgency=low
+
+ [Daniel Kahn Gillmor]
+ * New version (switch UNRELEASED to experimental when ready)
+
+ -- Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net> Tue, 24 Jun 2008 01:25:45 -0400
+
+monkeysphere (0.3-1) experimental; urgency=low
+
+ [ Daniel Kahn Gillmor ]
+ * new version.
+
+ [ Jameson Graef Rollins ]
+ * Move files in /var/cache/monkeysphere and GNUPGHOME for server to
+ the more appropriate /var/lib/monkeysphere.
+
+ -- Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net> Tue, 24 Jun 2008 00:55:29 -0400
+
+monkeysphere (0.2-2) experimental; urgency=low
+
+ * added lockfile-progs dependency
+
+ -- Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net> Mon, 23 Jun 2008 19:34:05 -0400
+
+monkeysphere (0.2-1) experimental; urgency=low
[ Daniel Kahn Gillmor ]
- * NOT YET RELEASED (switch to "experimental" when ready to release)
+ * openpgp2ssh now supports specifying keys by full fingerprint.
[ Jameson Graef Rollins ]
* Add AUTHORIZED_USER_IDS config variable for server, which defaults to
@@ -14,7 +38,7 @@ monkeysphere (0.2-1) UNRELEASED; urgency=low
* Better failure/prompting for gen-subkey
* Add ability to set any owner trust level for keys in server keychain.
- -- Jameson Graef Rollins <jrollins@phys.columbia.edu> Sun, 22 Jun 2008 11:42:42 -0400
+ -- Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net> Mon, 23 Jun 2008 17:03:19 -0400
monkeysphere (0.1-1) experimental; urgency=low
diff --git a/debian/control b/debian/control
index d4d25c6..4f0e5f5 100644
--- a/debian/control
+++ b/debian/control
@@ -3,14 +3,14 @@ Section: net
Priority: extra
Maintainer: Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>
Uploaders: Jameson Rollins <jrollins@fifthhorseman.net>
-Build-Depends: debhelper (>= 7.0), libgnutls-dev (>= 2.3.14)
+Build-Depends: debhelper (>= 7.0), libgnutls-dev (>= 2.4.0)
Standards-Version: 3.8.0.1
Homepage: http://cmrg.fifthhorseman.net/wiki/OpenPGPandSSH
Dm-Upload-Allowed: yes
Package: monkeysphere
Architecture: any
-Depends: openssh-client, gnupg | gnupg2, coreutils (>= 6), moreutils, ${shlibs:Depends}
+Depends: openssh-client, gnupg | gnupg2, coreutils (>= 6), moreutils, lockfile-progs, ${shlibs:Depends}
Recommends: netcat
Enhances: openssh-client, openssh-server
Description: use the OpenPGP web of trust to verify ssh connections
diff --git a/debian/dirs b/debian/dirs
index b458649..43b742a 100644
--- a/debian/dirs
+++ b/debian/dirs
@@ -1,5 +1,5 @@
-var/cache/monkeysphere
-var/cache/monkeysphere/authorized_keys
+var/lib/monkeysphere
+var/lib/monkeysphere/authorized_keys
usr/bin
usr/sbin
usr/share
diff --git a/debian/monkeysphere.dirs b/debian/monkeysphere.dirs
index 6e90899..b0b2d9c 100644
--- a/debian/monkeysphere.dirs
+++ b/debian/monkeysphere.dirs
@@ -1,4 +1,4 @@
usr/share/monkeysphere
-var/cache/monkeysphere
-var/cache/monkeysphere/authorized_keys
+var/lib/monkeysphere
+var/lib/monkeysphere/authorized_keys
etc/monkeysphere
diff --git a/doc/TODO b/doc/TODO
index 4f32bb0..e50da4d 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -5,9 +5,6 @@ Detail advantages of monkeysphere: detail the race conditions in ssh,
and how the monkeysphere can help you reduce these threat vectors:
threat model reduction diagrams.
-Determine how openssh handles multiple processes writing to
- known_hosts/authorized_keys files (lockfile, atomic appends?)
-
Handle unverified monkeysphere hosts in such a way that they're not
always removed from known_hosts file. Ask user to lsign the host
key?
@@ -30,22 +27,10 @@ Ensure that authorized_user_ids are under as tight control as ssh
expects from authorized_keys: we don't want monkeysphere to be a
weak link in the filesystem.
-What happens when a user account has no corresponding
- /etc/monkeysphere/authorized_user_ids/$USER file? What gets placed
- in /var/cache/monkeysphere/authorized_keys/$USER? It looks
- currently untouched, which could mean bad things for such a user.
- - if authorized_user_ids is empty, then the user's authorized_keys
- file will be also, unless the user-controlled authorized_keys file
- is added. I believe this is expected, correct behavior.
-
Consider the default permissions for
- /var/cache/monkeysphere/authorized_keys/* (and indeed the whole
+ /var/lib/monkeysphere/authorized_keys/* (and indeed the whole
directory path leading up to that)
-As an administrator, how do i reverse the effect of a
- "monkeysphere-server trust-keys" that i later decide i should not
- have run?
-
Make sure alternate ports are handled for known_hosts.
Script to import private key into ssh agent.
@@ -105,20 +90,20 @@ When using ssh-proxycommand, if only host keys found are expired or
Update monkeysphere-ssh-proxycommand man page with new keyserver
checking policy info.
-Update monkeysphere-ssh-proxycommand man page with info about
- no-connect option.
-
File bug against seahorse about how, when creating new primary keys,
it presents option for "RSA (sign only)" but then creates an "esca"
key.
File bug against enigmail about lack of ability to create subkeys.
-Priviledge separation: monkeysphere user to handle authn keyring and
+Privilege separation: monkeysphere user to handle authn keyring and
generate authorized_keys file (which would be moved into place by
root). Host keyring would be owned by root.
-Check permissions of authorized_user_ids file to be writable only by
- user and root (same as authorized_keys)
+Test and document what happens when any filesystem that the
+ monkeysphere-server relies on and modifies (/tmp, /etc, and /var?)
+ fills up.
-Improve function that sets owner trust for keys in server keychain.
+Optimize keyserver access, particularly on monkeysphere-server
+ update-users -- is there a way to query the keyserver all in a
+ chunk?
diff --git a/doc/george/changelog b/doc/george/changelog
index aefbf7f..e49a053 100644
--- a/doc/george/changelog
+++ b/doc/george/changelog
@@ -6,7 +6,14 @@
* Please add new entries in reverse chronological order whenever you make *
* changes to this system *
******************************************************************************
-
+2008-06-23 - dkg
+ * added monkeysphere apt repository to /etc/apt/sources.list
+ * added dkg's key to apt's list of trusted keys.
+ * ran aptitude dist-upgrade
+ * upgraded to monkeysphere 0.2-1
+ * moved authorized_user_ids files into users' home directories.
+ * installed lockfile-progs
+
2008-06-22 - dkg
* installed screen (mjgoins and i were collaborating)
diff --git a/etc/monkeysphere-server.conf b/etc/monkeysphere-server.conf
index 847e879..defb0f7 100644
--- a/etc/monkeysphere-server.conf
+++ b/etc/monkeysphere-server.conf
@@ -3,20 +3,9 @@
# This is an sh-style shell configuration file. Variable names should
# be separated from their assignements by a single '=' and no spaces.
-# GPG home directory for server
-#GNUPGHOME=/etc/monkeysphere/gnupg
-
# GPG keyserver to search for keys
#KEYSERVER=subkeys.pgp.net
-# Required user key capabilities
-# Must be quoted, lowercase, space-seperated list of the following:
-# e = encrypt
-# s = sign
-# c = certify
-# a = authentication
-#REQUIRED_USER_KEY_CAPABILITY="a"
-
# Path to authorized_user_ids file to process to create
# authorized_keys file. '%h' will be replaced by the home directory
# of the user, and %u will be replaced by the username of the user.
@@ -26,6 +15,8 @@
# Whether to add user controlled authorized_keys file to
# monkeysphere-generated authorized_keys file. Should be path to file
-# where '%h' will be replaced by the home directory of the user.
-# To not add any user-controlled file, put "-"
-#USER_CONTROLLED_AUTHORIZED_KEYS="%h/.ssh/authorized_keys"
+# where '%h' will be replaced by the home directory of the user or
+# '%u' by the username. To not add any user-controlled file, put "-"
+# FIXME: this usage of "-" contravenes the normal convention where "-"
+# means standard in/out. Why not use "none" or "" instead?
+#RAW_AUTHORIZED_KEYS="%h/.ssh/authorized_keys"
diff --git a/etc/monkeysphere.conf b/etc/monkeysphere.conf
index f2ba4a7..aa3a664 100644
--- a/etc/monkeysphere.conf
+++ b/etc/monkeysphere.conf
@@ -9,14 +9,13 @@
# GPG keyserver to search for keys
#KEYSERVER=subkeys.pgp.net
-# Required key capabilities
-# Must be quoted, lowercase, space-seperated list of the following:
-# e = encrypt
-# s = sign
-# c = certify
-# a = authentication
-#REQUIRED_HOST_KEY_CAPABILITY="a"
-#REQUIRED_USER_KEY_CAPABILITY="a"
+# Set whether or not to check keyservers at every monkeysphere
+# interaction, including all ssh connections if you use the
+# monkeysphere-ssh-proxycommand.
+# NOTE: setting CHECK_KEYSERVER to true will leak information about
+# the timing and frequency of your ssh connections to the maintainer
+# of the keyserver.
+#CHECK_KEYSERVER=true
# ssh known_hosts file
#KNOWN_HOSTS=~/.ssh/known_hosts
@@ -25,9 +24,5 @@
# Should be "true" or "false"
#HASH_KNOWN_HOSTS=true
-# ssh authorized_keys file
-#AUTHORIZED_KEYS=~/.ssh/known_hosts
-
-# This overrides other environment variables
-# NOTE: there is leakage
-#CHECK_KEYRING=true
+# ssh authorized_keys file (FIXME: why is this relevant in this file?)
+#AUTHORIZED_KEYS=~/.ssh/authorized_keys
diff --git a/man/man1/openpgp2ssh.1 b/man/man1/openpgp2ssh.1
index bea1da5..6141ec5 100644
--- a/man/man1/openpgp2ssh.1
+++ b/man/man1/openpgp2ssh.1
@@ -19,11 +19,14 @@ SSH-style key on standard output.
.Pp
If the data on standard input contains no subkeys, you can invoke
.Nm
-without arguments. If the data on standard input contains
-multiple keys (e.g. a primary key and associated subkeys), you must
-specify a specific OpenPGP keyid (e.g. CCD2ED94D21739E9) or
-fingerprint as the first argument to indicate which key to export.
-The keyid must be exactly 16 hex characters.
+without arguments. If the data on standard input contains multiple
+keys (e.g. a primary key and associated subkeys), you must specify a
+specific OpenPGP key identifier as the first argument to indicate
+which key to export. The key ID is normally the 40 hex digit OpenPGP
+fingerprint of the key or subkey desired, but
+.Nm
+will accept as few as the last 8 digits of the fingerprint as a key
+ID.
.Pp
If the input contains an OpenPGP RSA or DSA public key, it will be
converted to the OpenSSH-style single-line keystring, prefixed with
@@ -78,8 +81,9 @@ Secret key output is currently not passphrase-protected.
.Nm
currently cannot handle passphrase-protected secret keys on input.
.Pp
-It would be nice to be able to use keyids shorter or longer than 16
-hex characters.
+Key identifiers consisting of an odd number of hex digits are not
+accepted. Users who use a key ID with a standard length of 8, 16, or
+40 hex digits should not be affected by this.
.Pp
.Nm
only acts on keys associated with the first primary key
diff --git a/man/man8/monkeysphere-server.8 b/man/man8/monkeysphere-server.8
index e821e63..9bb7b2d 100644
--- a/man/man8/monkeysphere-server.8
+++ b/man/man8/monkeysphere-server.8
@@ -28,8 +28,8 @@ file are processed, and the user's authorized_keys file in
/var/cache/monkeysphere/authorized_keys/USER. See `man monkeysphere'
for more info. If the USER_CONTROLLED_AUTHORIZED_KEYS variable is
set, then a user-controlled authorized_keys file (usually
-~USER/.ssh/authorized_keys) is added to the authorized_keys file. `k'
-may be used in place of `update-known_hosts'.
+~USER/.ssh/authorized_keys) is added to the authorized_keys file. `u'
+may be used in place of `update-users.
.TP
.B gen-key
Generate a gpg key for the host. `g' may be used in place of
@@ -63,12 +63,12 @@ that is done, publish the key to a keyserver with "publish-key"
subcommand. Finally, you need to modify the sshd_config to tell sshd
where the new server host key:
-HostKey /etc/monkeysphere/ssh_host_rsa_key
+HostKey /var/lib/monkeysphere/ssh_host_rsa_key
If the server will also handle user authentication through
monkeysphere-generated authorized_keys files, set the following:
-AuthorizedKeysFile /var/cache/monkeysphere/authorized_keys/%u
+AuthorizedKeysFile /var/lib/monkeysphere/authorized_keys/%u
Once those changes are made, restart the ssh server.
@@ -81,17 +81,18 @@ System monkeysphere-server config file.
/etc/monkeysphere/monkeysphere.conf
System-wide monkeysphere config file.
.TP
-/etc/monkeysphere/gnupg
-Monkeysphere GNUPG home directory.
+/var/lib/monkeysphere/authorized_keys/USER
+Monkeysphere-generated user authorized_keys files.
.TP
-/etc/monkeysphere/ssh_host_rsa_key
-Copy of the host's private key in ssh format, suitable for use by sshd.
+/var/lib/monkeysphere/ssh_host_rsa_key
+Copy of the host's private key in ssh format, suitable for use by
+sshd.
.TP
-/etc/monkeysphere/authorized_user_ids/USER
-Server maintained authorized_user_ids files for users.
+/var/lib/monkeysphere/gnupg-host
+Monkeysphere host GNUPG home directory.
.TP
-/var/cache/monkeysphere/authorized_keys/USER
-User authorized_keys file.
+/var/lib/monkeysphere/gnupg-authentication
+Monkeysphere authentication GNUPG home directory.
.SH AUTHOR
diff --git a/src/common b/src/common
index 4021263..ead3736 100644
--- a/src/common
+++ b/src/common
@@ -16,10 +16,6 @@
# managed directories
ETC="/etc/monkeysphere"
export ETC
-CACHE="/var/cache/monkeysphere"
-export CACHE
-ERR=0
-export ERR
########################################################################
### UTILITY FUNCTIONS
@@ -111,15 +107,13 @@ translate_ssh_variables() {
echo "$path"
}
-### CONVERTION UTILITIES
+### CONVERSION UTILITIES
# output the ssh key for a given key ID
gpg2ssh() {
local keyID
- #keyID="$1" #TMP
- # only use last 16 characters until openpgp2ssh can take all 40 #TMP
- keyID=$(echo "$1" | cut -c 25-) #TMP
+ keyID="$1"
gpg --export "$keyID" | openpgp2ssh "$keyID" 2> /dev/null
}
@@ -265,7 +259,7 @@ process_user_id() {
fi
requiredPubCapability=$(echo "$requiredCapability" | tr "[:lower:]" "[:upper:]")
- # if CHECK_KEYSERVER variable set, check the keyserver
+ # if CHECK_KEYSERVER variable set to true, check the keyserver
# for the user ID
if [ "$CHECK_KEYSERVER" = "true" ] ; then
gpg_fetch_userid "$userID"
@@ -344,9 +338,9 @@ process_user_id() {
# 0 = ok, 1 = bad
if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
log " * acceptable key found."
- echo 0 "$fingerprint"
+ echo "0:${fingerprint}"
else
- echo 1 "$fingerprint"
+ echo "1:${fingerprint}"
fi
;;
'sub') # sub keys
@@ -379,116 +373,199 @@ process_user_id() {
# 0 = ok, 1 = bad
if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
log " * acceptable key found."
- echo 0 "$fingerprint"
+ echo "0:${fingerprint}"
else
- echo 1 "$fingerprint"
+ echo "1:${fingerprint}"
fi
;;
esac
done
}
-# process hosts in the known_host file
-process_hosts_known_hosts() {
+# process a single host in the known_host file
+process_host_known_hosts() {
local host
local userID
local ok
local keyid
local tmpfile
+ local returnCode
+
+ # default return code is 1, which assumes no key was found
+ returnCode=1
+
+ host="$1"
+
+ log "processing host: $host"
+
+ userID="ssh://${host}"
+
+ for line in $(process_user_id "ssh://${host}") ; do
+ ok=$(echo "$line" | cut -d: -f1)
+ keyid=$(echo "$line" | cut -d: -f2)
+
+ 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
+ # set return code to be 0, since a key was found
+ returnCode=0
+ fi
+ return "$returnCode"
+ done
+
+ return "$returnCode"
+}
+
+# update the known_hosts file for a set of hosts listed on command
+# line
+update_known_hosts() {
+ local host
+ local returnCode
+
+ # default return code is 0, which assumes a key was found for
+ # every host. code will be set to 1 if a key is not found for at
+ # least one host
+ returnCode=0
+
+ # set the trap to remove any lockfiles on exit
+ trap "lockfile-remove $KNOWN_HOSTS" EXIT
# 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
- done
+ # process the host, change return code if host key not found
+ process_host_known_hosts "$host" || returnCode=1
+
# touch the lockfile, for good measure.
lockfile-touch --oneshot "$KNOWN_HOSTS"
done
# remove the lockfile
lockfile-remove "$KNOWN_HOSTS"
+
+ return "$returnCode"
+}
+
+# process known_hosts file, going through line-by-line, extract each
+# host, and process with the host processing function
+process_known_hosts() {
+ local returnCode
+
+ # default return code is 0, which assumes a key was found for
+ # every host. code will be set to 1 if a key is not found for at
+ # least one host
+ returnCode=0
+
+ # take all the hosts from the known_hosts file (first field), grep
+ # out all the hashed hosts (lines starting with '|')...
+ for line in $(cat "$KNOWN_HOSTS" | meat | cut -d ' ' -f 1 | grep -v '^|.*$') ; do
+ # break up hosts into separate words
+ update_known_hosts $(echo "$line" | tr , ' ') || returnCode=1
+ done
+
+ return "$returnCode"
}
# process uids for the authorized_keys file
-process_uids_authorized_keys() {
+process_uid_authorized_keys() {
local userID
local ok
local keyid
+ local returnCode
+
+ # default return code is 1, which assumes no key was found
+ returnCode=1
+
+ userID="$1"
+
+ log "processing user ID: $userID"
+
+ for line in $(process_user_id "$userID") ; do
+ ok=$(echo "$line" | cut -d: -f1)
+ keyid=$(echo "$line" | cut -d: -f2)
+
+ 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"
+
+ # set return code to be 0, since a key was found
+ returnCode=0
+ fi
+ done
+
+ return "$returnCode"
+}
+
+# update the authorized_keys files from a list of user IDs on command
+# line
+update_authorized_keys() {
+ local userID
+ local returnCode
+
+ # default return code is 0, which assumes a key was found for
+ # every user ID. code will be set to 1 if a key is not found for
+ # at least one user ID
+ returnCode=0
+
+ # set the trap to remove any lockfiles on exit
+ trap "lockfile-remove $AUTHORIZED_KEYS" EXIT
# create a lockfile on authorized_keys
lockfile-create "$AUTHORIZED_KEYS"
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
- done
+ # process the user ID, change return code if key not found for
+ # user ID
+ process_uid_authorized_keys "$userID" || returnCode=1
+
# touch the lockfile, for good measure.
lockfile-touch --oneshot "$AUTHORIZED_KEYS"
done
# remove the lockfile
lockfile-remove "$AUTHORIZED_KEYS"
-}
-# process known_hosts file
-# go through line-by-line, extract each host, and process with the
-# host processing function
-process_known_hosts() {
- local hosts
- local host
-
- # take all the hosts from the known_hosts file (first field),
- # grep out all the hashed hosts (lines starting with '|')...
- cat "$KNOWN_HOSTS" | meat | \
- cut -d ' ' -f 1 | grep -v '^|.*$' | \
- while IFS=, read -r -a hosts ; do
- process_hosts_known_hosts ${hosts[@]}
- done
+ return "$returnCode"
}
# process an authorized_user_ids file for authorized_keys
process_authorized_user_ids() {
local userid
+ local returnCode
+
+ # default return code is 0, and is set to 1 if a key for a user ID
+ # is not found
+ returnCode=0
authorizedUserIDs="$1"
- cat "$authorizedUserIDs" | meat | \
- while read -r userid ; do
- process_uids_authorized_keys "$userid"
+ # set the IFS to be newline for parsing the authorized_user_ids
+ # file. can't find it in BASH(1) (found it on the net), but it
+ # works.
+ IFS=$'\n'
+ for userid in $(cat "$authorizedUserIDs" | meat) ; do
+ update_authorized_keys "$userid" || returnCode=1
done
+
+ return "$returnCode"
}
# EXPERIMENTAL (unused) process userids found in authorized_keys file
@@ -498,6 +575,11 @@ process_authorized_user_ids() {
process_authorized_keys() {
local authorizedKeys
local userID
+ local returnCode
+
+ # default return code is 0, and is set to 1 if a key for a user
+ # is not found
+ returnCode=0
authorizedKeys="$1"
@@ -522,8 +604,10 @@ process_authorized_keys() {
# process the userid
log "processing userid: '$userID'"
- process_user_id "$userID" > /dev/null
+ process_user_id "$userID" > /dev/null || returnCode=1
done
+
+ return "$returnCode"
}
##################################################
diff --git a/src/keytrans/gnutls-helpers.c b/src/keytrans/gnutls-helpers.c
index 5b4c46a..7c4348d 100644
--- a/src/keytrans/gnutls-helpers.c
+++ b/src/keytrans/gnutls-helpers.c
@@ -44,11 +44,11 @@ void init_keyid(gnutls_openpgp_keyid_t keyid) {
void make_keyid_printable(printable_keyid out, gnutls_openpgp_keyid_t keyid)
{
assert(sizeof(out) >= 2*sizeof(keyid));
- hex_print_data((char*)out, (const char*)keyid, sizeof(keyid));
+ hex_print_data((char*)out, (const unsigned char*)keyid, sizeof(keyid));
}
/* you must have twice as many bytes in the out buffer as in the in buffer */
-void hex_print_data(char* out, const char* in, size_t incount)
+void hex_print_data(char* out, const unsigned char* in, size_t incount)
{
static const char hex[16] = "0123456789ABCDEF";
unsigned int inix = 0, outix = 0;
@@ -73,7 +73,6 @@ unsigned char hex2bin(unsigned char x) {
void collapse_printable_keyid(gnutls_openpgp_keyid_t out, printable_keyid in) {
unsigned int pkix = 0, outkix = 0;
-
while (pkix < sizeof(printable_keyid)) {
unsigned hi = hex2bin(in[pkix]);
unsigned lo = hex2bin(in[pkix + 1]);
@@ -92,6 +91,27 @@ void collapse_printable_keyid(gnutls_openpgp_keyid_t out, printable_keyid in) {
}
}
+unsigned int hexstring2bin(unsigned char* out, const char* in) {
+ unsigned int pkix = 0, outkix = 0;
+ int hi = 0; /* which nybble is it? */
+
+ while (in[pkix]) {
+ unsigned char z = hex2bin(in[pkix]);
+ if (z != 0xff) {
+ if (!hi) {
+ if (out) out[outkix] = (z << 4);
+ hi = 1;
+ } else {
+ if (out) out[outkix] |= z;
+ hi = 0;
+ outkix++;
+ }
+ pkix++;
+ }
+ }
+ return outkix*8 + (hi ? 4 : 0);
+}
+
int convert_string_to_keyid(gnutls_openpgp_keyid_t out, const char* str) {
printable_keyid p;
int ret;
diff --git a/src/keytrans/gnutls-helpers.h b/src/keytrans/gnutls-helpers.h
index f196456..bf54af0 100644
--- a/src/keytrans/gnutls-helpers.h
+++ b/src/keytrans/gnutls-helpers.h
@@ -49,7 +49,18 @@ int convert_string_to_keyid(gnutls_openpgp_keyid_t out, const char* str);
int convert_string_to_printable_keyid(printable_keyid out, const char* str);
/* you must have twice as many bytes in the out buffer as in the in buffer */
-void hex_print_data(char* out, const char* in, size_t incount);
+void hex_print_data(char* out, const unsigned char* in, size_t incount);
+
+/* expects a null-terminated string as in, containing an even number
+ of hexadecimal characters.
+
+ returns length in *bits* of raw data as output.
+
+ the out buffer must be at least half as long as in to hold the
+ output. if out is NULL, no output will be generated, but the
+ length will still be returned.
+*/
+unsigned int hexstring2bin(unsigned char* out, const char* in);
/* functions to get data into datum objects: */
diff --git a/src/keytrans/openpgp2ssh.c b/src/keytrans/openpgp2ssh.c
index 92bdc19..5cc6cfa 100644
--- a/src/keytrans/openpgp2ssh.c
+++ b/src/keytrans/openpgp2ssh.c
@@ -35,15 +35,16 @@
/* FIXME: keyid should be const as well */
-int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_openpgp_privkey_t* pgp_privkey, gnutls_openpgp_keyid_t* keyid) {
+int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_openpgp_privkey_t* pgp_privkey, const unsigned char* keyfpr, unsigned int fprlen) {
gnutls_datum_t m, e, d, p, q, u, g, y, x;
gnutls_pk_algorithm_t pgp_algo;
unsigned int pgp_bits;
int ret;
- gnutls_openpgp_keyid_t curkeyid;
int subkeyidx;
int subkeycount;
int found = 0;
+ unsigned char fingerprint[20];
+ size_t fingerprint_length = sizeof(fingerprint);
init_datum(&m);
init_datum(&e);
@@ -61,20 +62,27 @@ int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_open
return 1;
}
- if ((keyid == NULL) &&
+ if ((keyfpr == NULL) &&
(subkeycount > 0)) {
- err(0,"No keyid passed in, but there were %d keys to choose from\n", subkeycount + 1);
+ err(0,"No key identifier passed in, but there were %d keys to choose from\n", subkeycount + 1);
return 1;
}
- if (keyid != NULL) {
- ret = gnutls_openpgp_privkey_get_key_id(*pgp_privkey, curkeyid);
+ if (keyfpr != NULL) {
+ ret = gnutls_openpgp_privkey_get_fingerprint(*pgp_privkey, fingerprint, &fingerprint_length);
if (ret) {
- err(0,"Could not get keyid (error: %d)\n", ret);
+ err(0,"Could not get fingerprint (error: %d)\n", ret);
return 1;
}
+ if (fprlen > fingerprint_length) {
+ err(0, "Requested key identifier is longer than computed fingerprint\n");
+ return 1;
+ }
+ if (fingerprint_length > fprlen) {
+ err(0, "Only comparing last %d bits of key fingerprint\n", fprlen*8);
+ }
}
- if ((keyid == NULL) || (memcmp(*keyid, curkeyid, sizeof(gnutls_openpgp_keyid_t)) == 0)) {
+ if ((keyfpr == NULL) || (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0)) {
/* we want to export the primary key: */
err(0,"exporting primary key\n");
@@ -106,12 +114,19 @@ int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_open
} else {
/* lets trawl through the subkeys until we find the one we want: */
for (subkeyidx = 0; (subkeyidx < subkeycount) && !found; subkeyidx++) {
- ret = gnutls_openpgp_privkey_get_subkey_id(*pgp_privkey, subkeyidx, curkeyid);
+ ret = gnutls_openpgp_privkey_get_subkey_fingerprint(*pgp_privkey, subkeyidx, fingerprint, &fingerprint_length);
if (ret) {
- err(0,"Could not get keyid of subkey with index %d (error: %d)\n", subkeyidx, ret);
+ err(0,"Could not get fingerprint of subkey with index %d (error: %d)\n", subkeyidx, ret);
return 1;
}
- if (memcmp(*keyid, curkeyid, sizeof(gnutls_openpgp_keyid_t)) == 0) {
+ if (fprlen > fingerprint_length) {
+ err(0, "Requested key identifier is longer than computed fingerprint\n");
+ return 1;
+ }
+ if (fingerprint_length > fprlen) {
+ err(1, "Only comparing last %d bits of key fingerprint\n", fprlen*8);
+ }
+ if (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0) {
err(0,"exporting subkey index %d\n", subkeyidx);
/* FIXME: this is almost identical to the block above for the
@@ -172,8 +187,7 @@ int convert_private_pgp_to_x509(gnutls_x509_privkey_t* output, const gnutls_open
}
/* FIXME: keyid should be const also */
-int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, gnutls_openpgp_keyid_t* keyid) {
- gnutls_openpgp_keyid_t curkeyid;
+int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, const unsigned char* keyfpr, size_t fprlen) {
int ret;
int subkeyidx;
int subkeycount;
@@ -188,6 +202,9 @@ int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, gnutls_ope
algorithm name: */
char output_data[20];
+ unsigned char fingerprint[20];
+ size_t fingerprint_length = sizeof(fingerprint);
+
/* variables for the output conversion: */
int pipestatus;
int pipefd, child_pid;
@@ -208,20 +225,27 @@ int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, gnutls_ope
return 1;
}
- if ((keyid == NULL) &&
+ if ((keyfpr == NULL) &&
(subkeycount > 0)) {
- err(0,"No keyid passed in, but there were %d keys to choose from\n", subkeycount + 1);
+ err(0,"No key identifier passed in, but there were %d keys to choose from\n", subkeycount + 1);
return 1;
}
- if (keyid != NULL) {
- ret = gnutls_openpgp_crt_get_key_id(*pgp_crt, curkeyid);
+ if (keyfpr != NULL) {
+ ret = gnutls_openpgp_crt_get_fingerprint(*pgp_crt, fingerprint, &fingerprint_length);
if (ret) {
- err(0,"Could not get keyid (error: %d)\n", ret);
+ err(0,"Could not get key fingerprint (error: %d)\n", ret);
return 1;
}
+ if (fprlen > fingerprint_length) {
+ err(0, "Requested key identifier is longer than computed fingerprint\n");
+ return 1;
+ }
+ if (fingerprint_length > fprlen) {
+ err(0, "Only comparing last %d bits of key fingerprint\n", fprlen*8);
+ }
}
- if ((keyid == NULL) || (memcmp(*keyid, curkeyid, sizeof(gnutls_openpgp_keyid_t)) == 0)) {
+ if ((keyfpr == NULL) || (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0)) {
/* we want to export the primary key: */
err(0,"exporting primary key\n");
@@ -252,12 +276,19 @@ int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, gnutls_ope
} else {
/* lets trawl through the subkeys until we find the one we want: */
for (subkeyidx = 0; (subkeyidx < subkeycount) && !found; subkeyidx++) {
- ret = gnutls_openpgp_crt_get_subkey_id(*pgp_crt, subkeyidx, curkeyid);
+ ret = gnutls_openpgp_crt_get_subkey_fingerprint(*pgp_crt, subkeyidx, fingerprint, &fingerprint_length);
if (ret) {
- err(0,"Could not get keyid of subkey with index %d (error: %d)\n", subkeyidx, ret);
+ err(0,"Could not get fingerprint of subkey with index %d (error: %d)\n", subkeyidx, ret);
return 1;
}
- if (memcmp(*keyid, curkeyid, sizeof(gnutls_openpgp_keyid_t)) == 0) {
+ if (fprlen > fingerprint_length) {
+ err(0, "Requested key identifier is longer than computed fingerprint\n");
+ return 1;
+ }
+ if (fingerprint_length > fprlen) {
+ err(1, "Only comparing last %d bits of key fingerprint\n", fprlen*8);
+ }
+ if (memcmp(fingerprint + (fingerprint_length - fprlen), keyfpr, fprlen) == 0) {
err(0,"exporting subkey index %d\n", subkeyidx);
/* FIXME: this is almost identical to the block above for the
@@ -351,7 +382,7 @@ int emit_public_openssh_from_pgp(const gnutls_openpgp_crt_t* pgp_crt, gnutls_ope
int main(int argc, char* argv[]) {
gnutls_datum_t data;
- int ret;
+ int ret = 0;
gnutls_x509_privkey_t x509_privkey;
gnutls_openpgp_privkey_t pgp_privkey;
gnutls_openpgp_crt_t pgp_crt;
@@ -359,18 +390,54 @@ int main(int argc, char* argv[]) {
char output_data[10240];
size_t ods = sizeof(output_data);
- gnutls_openpgp_keyid_t keyid;
- gnutls_openpgp_keyid_t* use_keyid;
+ unsigned char * fingerprint = NULL;
+ size_t fpr_size;
+ char * prettyfpr = NULL;
init_gnutls();
- /* figure out what keyid we should be looking for: */
- use_keyid = NULL;
+ /* figure out what key we should be looking for: */
if (argv[1] != NULL) {
- ret = convert_string_to_keyid(keyid, argv[1]);
- if (ret != 0)
- return ret;
- use_keyid = &keyid;
+ if (strlen(argv[1]) > 81) {
+ /* safety check to avoid some sort of wacky overflow situation:
+ there's no reason that the key id should be longer than twice
+ a sane fingerprint (one byte between chars, and then another
+ two at the beginning and end) */
+ err(0, "Key identifier is way too long. Please use at most 40 hex digits.\n");
+ return 1;
+ }
+
+ fpr_size = hexstring2bin(NULL, argv[1]);
+ if (fpr_size > 40*4) {
+ err(0, "Key identifier is longer than 40 hex digits\n");
+ return 1;
+ }
+ /* since fpr_size is initially in bits: */
+ if (fpr_size % 8 != 0) {
+ err(0, "Please provide an even number of hex digits for the key identifier\n");
+ return 1;
+ }
+ fpr_size /= 8;
+
+ fingerprint = malloc(sizeof(unsigned char) * fpr_size);
+ bzero(fingerprint, sizeof(unsigned char) * fpr_size);
+ hexstring2bin(fingerprint, argv[1]);
+
+ prettyfpr = malloc(sizeof(unsigned char)*fpr_size*2 + 1);
+ if (prettyfpr != NULL) {
+ hex_print_data(prettyfpr, fingerprint, fpr_size);
+ prettyfpr[sizeof(unsigned char)*fpr_size*2] = '\0';
+ err(1, "searching for key with fingerprint '%s'\n", prettyfpr);
+ free(prettyfpr);
+ }
+
+ if (fpr_size < 4) {
+ err(0, "You MUST provide at least 8 hex digits in any key identifier\n");
+ return 1;
+ }
+ if (fpr_size < 8)
+ err(0, "You should provide at least 16 hex digits in any key identifier (proceeding with %d digits anyway)\n", fpr_size*2);
+
}
@@ -397,7 +464,7 @@ int main(int argc, char* argv[]) {
return 1;
}
- ret = convert_private_pgp_to_x509(&x509_privkey, &pgp_privkey, use_keyid);
+ ret = convert_private_pgp_to_x509(&x509_privkey, &pgp_privkey, fingerprint, fpr_size);
gnutls_openpgp_privkey_deinit(pgp_privkey);
if (ret)
@@ -423,7 +490,7 @@ int main(int argc, char* argv[]) {
/* we're dealing with a public key */
err(0,"Translating public key\n");
- ret = emit_public_openssh_from_pgp(&pgp_crt, use_keyid);
+ ret = emit_public_openssh_from_pgp(&pgp_crt, fingerprint, fpr_size);
} else {
/* we have no idea what kind of key this is at all anyway! */
@@ -433,5 +500,6 @@ int main(int argc, char* argv[]) {
}
gnutls_global_deinit();
+ free(fingerprint);
return 0;
}
diff --git a/src/monkeysphere b/src/monkeysphere
index 9b315e2..d8d4667 100755
--- a/src/monkeysphere
+++ b/src/monkeysphere
@@ -24,6 +24,9 @@ DATE=$(date -u '+%FT%T')
# unset some environment variables that could screw things up
GREP_OPTIONS=
+# default return code
+ERR=0
+
########################################################################
# FUNCTIONS
########################################################################
@@ -125,15 +128,17 @@ MS_CONF=${MS_CONF:-"${MS_HOME}/monkeysphere.conf"}
[ -e "$MS_CONF" ] && . "$MS_CONF"
# set empty config variable with defaults
-AUTHORIZED_USER_IDS=${AUTHORIZED_USER_IDS:-"${MS_HOME}/authorized_user_ids"}
GNUPGHOME=${GNUPGHOME:-"${HOME}/.gnupg"}
KEYSERVER=${KEYSERVER:-"subkeys.pgp.net"}
CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
-REQUIRED_HOST_KEY_CAPABILITY=${REQUIRED_HOST_KEY_CAPABILITY:-"a"}
-REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
KNOWN_HOSTS=${KNOWN_HOSTS:-"${HOME}/.ssh/known_hosts"}
-AUTHORIZED_KEYS=${AUTHORIZED_KEYS:-"${HOME}/.ssh/authorized_keys"}
HASH_KNOWN_HOSTS=${HASH_KNOWN_HOSTS:-"true"}
+AUTHORIZED_KEYS=${AUTHORIZED_KEYS:-"${HOME}/.ssh/authorized_keys"}
+
+# other variables
+AUTHORIZED_USER_IDS=${AUTHORIZED_USER_IDS:-"${MS_HOME}/authorized_user_ids"}
+REQUIRED_HOST_KEY_CAPABILITY=${REQUIRED_HOST_KEY_CAPABILITY:-"a"}
+REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
export GNUPGHOME
@@ -143,7 +148,6 @@ mkdir -p -m 0700 "$GNUPGHOME"
# make sure the user monkeysphere home directory exists
mkdir -p -m 0700 "$MS_HOME"
touch "$AUTHORIZED_USER_IDS"
-touch "$AUTHORIZED_KEYS"
case $COMMAND in
'update-known_hosts'|'update-known-hosts'|'k')
@@ -156,7 +160,7 @@ case $COMMAND in
# if hosts are specified on the command line, process just
# those hosts
if [ "$1" ] ; then
- process_hosts_known_hosts "$@"
+ update_known_hosts "$@" || ERR=1
# otherwise, if no hosts are specified, process every host
# in the user's known_hosts file
@@ -165,7 +169,7 @@ case $COMMAND in
failure "known_hosts file '$KNOWN_HOSTS' is empty."
fi
log "processing known_hosts file..."
- process_known_hosts
+ process_known_hosts || ERR=1
fi
log "known_hosts file updated."
@@ -181,7 +185,7 @@ case $COMMAND in
# process authorized_user_ids file
log "processing authorized_user_ids file..."
- process_authorized_user_ids "$AUTHORIZED_USER_IDS"
+ process_authorized_user_ids "$AUTHORIZED_USER_IDS" || ERR=1
log "authorized_keys file updated."
;;
@@ -202,3 +206,5 @@ case $COMMAND in
Type '$PGRM help' for usage."
;;
esac
+
+exit "$ERR"
diff --git a/src/monkeysphere-server b/src/monkeysphere-server
index f68f391..ac7c1cb 100755
--- a/src/monkeysphere-server
+++ b/src/monkeysphere-server
@@ -11,9 +11,12 @@
########################################################################
PGRM=$(basename $0)
-SHAREDIR=${SHAREDIR:-"/usr/share/monkeysphere"}
-export SHAREDIR
-. "${SHAREDIR}/common"
+SHARE=${SHARE:-"/usr/share/monkeysphere"}
+export SHARE
+. "${SHARE}/common"
+
+VARLIB="/var/lib/monkeysphere"
+export VARLIB
# date in UTF format if needed
DATE=$(date -u '+%FT%T')
@@ -21,6 +24,9 @@ DATE=$(date -u '+%FT%T')
# unset some environment variables that could screw things up
GREP_OPTIONS=
+# default return code
+ERR=0
+
########################################################################
# FUNCTIONS
########################################################################
@@ -31,7 +37,7 @@ usage: $PGRM <subcommand> [args]
MonkeySphere server admin tool.
subcommands:
- update-users (s) [USER]... update users authorized_keys files
+ update-users (u) [USER]... update users authorized_keys files
gen-key (g) [HOSTNAME] generate gpg key for the server
show-fingerprint (f) show server's host key fingerprint
publish-key (p) publish server's host key to keyserver
@@ -46,8 +52,9 @@ gen_key() {
local hostName
hostName=${1:-$(hostname --fqdn)}
- service=${SERVICE:-"ssh"}
- userID="${service}://${hostName}"
+
+ SERVICE=${SERVICE:-"ssh"}
+ userID="${SERVICE}://${hostName}"
if gpg --list-key ="$userID" > /dev/null 2>&1 ; then
failure "Key for '$userID' already exists"
@@ -118,8 +125,8 @@ EOF
# write the key to the file
# NOTE: assumes that the primary key is the proper key to use
- (umask 077 && gpgsecret2ssh "$keyID" > "${MS_HOME}/ssh_host_rsa_key")
- log "Private SSH host key output to file: ${MS_HOME}/ssh_host_rsa_key"
+ (umask 077 && gpgsecret2ssh "$keyID" > "${VARLIB}/ssh_host_rsa_key")
+ log "Private SSH host key output to file: ${VARLIB}/ssh_host_rsa_key"
}
# gpg output key fingerprint
@@ -151,24 +158,26 @@ MS_CONF=${MS_CONF:-"$MS_HOME"/monkeysphere-server.conf}
[ -e "$MS_CONF" ] && . "$MS_CONF"
# set empty config variable with defaults
-GNUPGHOME=${GNUPGHOME:-"${MS_HOME}/gnupg"}
+MONKEYSPHERE_USER=${MONKEYSPHERE_USER:-"monkeysphere"}
KEYSERVER=${KEYSERVER:-"subkeys.pgp.net"}
CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
-REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
AUTHORIZED_USER_IDS=${AUTHORIZED_USER_IDS:-"%h/.config/monkeysphere/authorized_user_ids"}
-USER_CONTROLLED_AUTHORIZED_KEYS=${USER_CONTROLLED_AUTHORIZED_KEYS:-"%h/.ssh/authorized_keys"}
+RAW_AUTHORIZED_KEYS=${RAW_AUTHORIZED_KEYS:-"%h/.ssh/authorized_keys"}
-export GNUPGHOME
+# other variables
+REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
+GNUPGHOME_HOST=${GNUPGHOME_HOST:-"${VARLIB}/gnupg-host"}
+GNUPGHOME_AUTHENTICATION=${GNUPGHOME_AUTHENTICATION:-"${VARLIB}/gnupg-authentication"}
-# make sure the monkeysphere home directory exists
-mkdir -p "${MS_HOME}/authorized_user_ids"
-# make sure gpg home exists with proper permissions
+# set default GNUPGHOME, and make sure the directory exists. this is
+# true for all functions expect user authentication
+# (ie. update-users).
+GNUPGHOME="$GNUPGHOME_HOST"
+export GNUPGHOME
mkdir -p -m 0700 "$GNUPGHOME"
-# make sure the authorized_keys directory exists
-mkdir -p "${CACHE}/authorized_keys"
case $COMMAND in
- 'update-users'|'update-user'|'s')
+ 'update-users'|'update-user'|'u')
if [ "$1" ] ; then
# get users from command line
unames="$@"
@@ -177,22 +186,32 @@ case $COMMAND in
unames=$(getent passwd | cut -d: -f1)
fi
+ # set mode
+ MODE="authorized_keys"
+
+ # make sure the authorized_keys directory exists
+ mkdir -p "${VARLIB}/authorized_keys"
+
+ # set GNUPGHOME, and make sure the directory exists
+ GNUPGHOME="$GNUPGHOME_AUTHENTICATION"
+ export GNUPGHOME
+ mkdir -p -m 0700 "$GNUPGHOME"
+
# loop over users
for uname in $unames ; do
- MODE="authorized_keys"
-
# check all specified users exist
if ! getent passwd "$uname" >/dev/null ; then
error "----- unknown user '$uname' -----"
continue
fi
- # set authorized_user_ids variable,
- # translate ssh-style path variables
+ # 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")
- # skip user if authorized_user_ids file does not exist
- if [ ! -f "$authorizedUserIDs" ] ; then
+ # if neither is found, skip user
+ if [ ! -s "$authorizedUserIDs" -a ! -s "$rawAuthorizedKeys" ] ; then
continue
fi
@@ -201,30 +220,42 @@ case $COMMAND in
# temporary authorized_keys file
AUTHORIZED_KEYS=$(mktemp)
- # skip if the user's authorized_user_ids file is empty
- if [ ! -s "$authorizedUserIDs" ] ; then
- log "authorized_user_ids file '$authorizedUserIDs' is empty."
- continue
- fi
+ # trap to delete file on exit
+ trap "rm -f $AUTHORIZE_KEYS" EXIT
# process authorized_user_ids file
- log "processing authorized_user_ids file..."
- process_authorized_user_ids "$authorizedUserIDs"
+ if [ -s "$authorizedUserIDs" ] ; then
+ log "processing authorized_user_ids file..."
+ process_authorized_user_ids "$authorizedUserIDs"
+ fi
# add user-controlled authorized_keys file path if specified
- if [ "$USER_CONTROLLED_AUTHORIZED_KEYS" != '-' ] ; then
- userAuthorizedKeys=$(translate_ssh_variables "$uname" "$USER_CONTROLLED_AUTHORIZED_KEYS")
- if [ -f "$userAuthorizedKeys" ] ; then
- log -n "adding user's authorized_keys file... "
- cat "$userAuthorizedKeys" >> "$AUTHORIZED_KEYS"
+ if [ "$RAW_AUTHORIZED_KEYS" != '-' ] ; then
+ if [ -s "$rawAuthorizedKeys" ] ; then
+ log -n "adding raw authorized_keys file... "
+ cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
loge "done."
fi
fi
- # move the temp authorized_keys file into place
- mv -f "$AUTHORIZED_KEYS" "${CACHE}/authorized_keys/${uname}"
+ # if the resulting authorized_keys file is not empty, move
+ # the temp 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.
+ # FIXME: is there a better way to do this?
+ chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
+ chmod g+r "$AUTHORIZED_KEYS"
+
+ mv -f "$AUTHORIZED_KEYS" "${VARLIB}/authorized_keys/${uname}"
- log "authorized_keys file updated."
+ log "authorized_keys file updated."
+
+ # else destroy it
+ else
+ rm -f "$AUTHORIZED_KEYS"
+ fi
done
;;
diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand
index f4d4b0d..6dcb723 100755
--- a/src/monkeysphere-ssh-proxycommand
+++ b/src/monkeysphere-ssh-proxycommand
@@ -31,6 +31,8 @@ fi
HOST="$1"
PORT="$2"
+MS_HOME=${MS_HOME:-"${HOME}/.config/monkeysphere"}
+
if [ -z "$HOST" ] ; then
log "host must be specified."
usage
@@ -58,11 +60,12 @@ else
# FIXME: this only works for default known_hosts location
hostKey=$(ssh-keygen -F "$HOST")
if [ "$hostKey" ] ; then
- # if the check keyserver variable is NOT set to true...
- if [ "$CHECK_KEYSERVER" != 'true' ] ; then
- # schedule a keyserver check for host at a later time
- echo "monkeysphere update-known_hosts $HOST" | at noon
- fi
+ # do not check the keyserver
+ # FIXME: more nuanced checking should be done here to properly
+ # take into consideration hosts that join monkeysphere by
+ # converting an existing and known ssh key
+ CHECK_KEYSERVER="false"
+
# if the host key is not found in the known_hosts file...
else
# check the keyserver