From: Jameson Graef Rollins Date: Mon, 23 Jun 2008 23:33:54 +0000 (-0400) Subject: Merge commit 'dkg/master' X-Git-Tag: monkeysphere_0.3-1~3^2~2 X-Git-Url: https://codewiz.org/gitweb?p=monkeysphere.git;a=commitdiff_plain;h=91bf57bac7bed32937c13595044158007e7b5812;hp=70cf71b1d716e2ec16fae03cd89da3f088f5f4c4 Merge commit 'dkg/master' --- diff --git a/debian/changelog b/debian/changelog index 41af80c..d3d7d9b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ -monkeysphere (0.2-1) UNRELEASED; urgency=low +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 +14,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 Sun, 22 Jun 2008 11:42:42 -0400 + -- Daniel Kahn Gillmor 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..85b2d3f 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: extra Maintainer: Daniel Kahn Gillmor Uploaders: Jameson Rollins -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 diff --git a/doc/TODO b/doc/TODO index 4f32bb0..e1e90f0 100644 --- a/doc/TODO +++ b/doc/TODO @@ -114,7 +114,7 @@ File bug against seahorse about how, when creating new primary keys, 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. @@ -122,3 +122,14 @@ Check permissions of authorized_user_ids file to be writable only by user and root (same as authorized_keys) Improve function that sets owner trust for keys in server keychain. + +Test and document what happens when any filesystem that the + monkeysphere-server relies on and modifies (/tmp, /etc, and /var?) + fills up. + +Consider moving monkeysphere-managed files (gpg homedirs? temporary + files?) into /var. + +Optimize keyserver access, particularly on monkeysphere-server + update-users -- is there a way to query the keyserver all in a + chunk? diff --git a/etc/monkeysphere-server.conf b/etc/monkeysphere-server.conf index 847e879..85b37c1 100644 --- a/etc/monkeysphere-server.conf +++ b/etc/monkeysphere-server.conf @@ -3,6 +3,9 @@ # This is an sh-style shell configuration file. Variable names should # be separated from their assignements by a single '=' and no spaces. +#FIXME: shouldn't this be in /var by default? These are not text +#files, and they should generally not be managed directly by the +#admin: # GPG home directory for server #GNUPGHOME=/etc/monkeysphere/gnupg @@ -24,8 +27,17 @@ # in /etc/monkeysphere/authorized_user_ids/%u #AUTHORIZED_USER_IDS="%h/.config/monkeysphere/authorized_user_ids" +#FIXME: why is the following variable named USER_CONTROLLED_...? +#shouldn't this be something like MONKEYSPHERE_RAW_AUTHORIZED_KEYS +#instead? For example, what about a server where the administrator +#has locked down the authorized_keys file from user control, but still +#wants to combine raw authorized_keys for some users with the +#monkeysphere? + # 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 "-" +# 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? #USER_CONTROLLED_AUTHORIZED_KEYS="%h/.ssh/authorized_keys" diff --git a/etc/monkeysphere.conf b/etc/monkeysphere.conf index f2ba4a7..cce9366 100644 --- a/etc/monkeysphere.conf +++ b/etc/monkeysphere.conf @@ -9,6 +9,8 @@ # GPG keyserver to search for keys #KEYSERVER=subkeys.pgp.net +# FIXME: consider removing REQUIRED_*_KEY_CAPABILITY entirely from +# this example config, given our discussion # Required key capabilities # Must be quoted, lowercase, space-seperated list of the following: # e = encrypt @@ -25,9 +27,12 @@ # Should be "true" or "false" #HASH_KNOWN_HOSTS=true -# ssh authorized_keys file +# ssh authorized_keys file (FIXME: why is this relevant in this file?) #AUTHORIZED_KEYS=~/.ssh/known_hosts -# This overrides other environment variables -# NOTE: there is leakage -#CHECK_KEYRING=true +# check keyservers at every ssh connection: +# This overrides other environment variables (FIXME: what does this mean???) +# 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 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..f808eff 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 diff --git a/src/common b/src/common index 1908022..5bb0b79 100644 --- a/src/common +++ b/src/common @@ -109,7 +109,7 @@ translate_ssh_variables() { echo "$path" } -### CONVERTION UTILITIES +### CONVERSION UTILITIES # output the ssh key for a given key ID gpg2ssh() { @@ -263,7 +263,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" 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-server b/src/monkeysphere-server index f68f391..e099a74 100755 --- a/src/monkeysphere-server +++ b/src/monkeysphere-server @@ -21,6 +21,9 @@ DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up GREP_OPTIONS= +# assuming other problems don't crop up, we'll return 0 as success +ERR=0 + ######################################################################## # FUNCTIONS ######################################################################## @@ -31,7 +34,7 @@ usage: $PGRM [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 @@ -168,7 +171,7 @@ mkdir -p -m 0700 "$GNUPGHOME" 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="$@" @@ -193,6 +196,9 @@ case $COMMAND in # skip user if authorized_user_ids file does not exist if [ ! -f "$authorizedUserIDs" ] ; then + #FIXME: what about a user with no authorized_user_ids + # file, but with an authorized_keys file when + # USER_CONTROLLED_AUTHORIZED_KEYS is set? continue fi @@ -204,6 +210,10 @@ case $COMMAND in # skip if the user's authorized_user_ids file is empty if [ ! -s "$authorizedUserIDs" ] ; then log "authorized_user_ids file '$authorizedUserIDs' is empty." + #FIXME: what about a user with an empty + # authorized_user_ids file, but with an + # authorized_keys file when + # USER_CONTROLLED_AUTHORIZED_KEYS is set? continue fi @@ -221,6 +231,13 @@ case $COMMAND in 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? + chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS" + chmod g+r "$AUTHORIZED_KEYS" + # move the temp authorized_keys file into place mv -f "$AUTHORIZED_KEYS" "${CACHE}/authorized_keys/${uname}"