
djm at mindrot
May 14, 2011, 3:28 PM
Post #22 of 33
(1778 views)
Permalink
|
|
Re: backdoor by authorized_keys2 leftovers
[In reply to]
|
|
On Sat, 14 May 2011, Damien Miller wrote: > On Wed, 11 May 2011, Damien Miller wrote: > > > > I also think that being able to specify multiple authorized_keys files > > > is very useful, so I would prefer to just see this as a documented > > > feature. > > > > Perhaps we should make options.authorized_keys_file an array to let > > people who want to use multiple files do so. > > Here's a lightly-tested patch against -current (OpenBSD version, it > will probably need some editing for portable) doh, wrong diff Index: auth-rsa.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/auth-rsa.c,v retrieving revision 1.79 diff -u -p -r1.79 auth-rsa.c --- auth-rsa.c 3 Dec 2010 23:55:27 -0000 1.79 +++ auth-rsa.c 13 May 2011 12:22:18 -0000 @@ -157,44 +157,27 @@ auth_rsa_challenge_dialog(Key *key) return (success); } -/* - * check if there's user key matching client_n, - * return key if login is allowed, NULL otherwise - */ - -int -auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) +static int +rsa_key_allowed_in_file(struct passwd *pw, char *file, + const BIGNUM *client_n, Key **rkey) { - char line[SSH_MAX_PUBKEY_BYTES], *file; + char line[SSH_MAX_PUBKEY_BYTES]; int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; Key *key; - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - - /* The authorized keys. */ - file = authorized_keys_file(pw); debug("trying public RSA key file %s", file); - f = auth_openkeyfile(file, pw, options.strict_modes); - if (!f) { - xfree(file); - restore_uid(); - return (0); - } - - /* Flag indicating whether the key is allowed. */ - allowed = 0; - - key = key_new(KEY_RSA1); + if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) + return 0; /* * Go though the accepted keys, looking for the current key. If * found, perform a challenge-response dialog to verify that the * user really has the corresponding private key. */ + key = key_new(KEY_RSA1); while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp; char *key_options; @@ -232,7 +215,10 @@ auth_rsa_key_allowed(struct passwd *pw, } /* cp now points to the comment part. */ - /* Check if the we have found the desired key (identified by its modulus). */ + /* + * Check if the we have found the desired key (identified + * by its modulus). + */ if (BN_cmp(key->rsa->n, client_n) != 0) continue; @@ -261,11 +247,7 @@ auth_rsa_key_allowed(struct passwd *pw, break; } - /* Restore the privileged uid. */ - restore_uid(); - /* Close the file. */ - xfree(file); fclose(f); /* return key if allowed */ @@ -273,7 +255,33 @@ auth_rsa_key_allowed(struct passwd *pw, *rkey = key; else key_free(key); - return (allowed); + + return allowed; +} + +/* + * check if there's user key matching client_n, + * return key if login is allowed, NULL otherwise + */ + +int +auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) +{ + char *file; + u_int i, allowed = 0; + + temporarily_use_uid(pw); + + for (i = 0; !allowed && i < options.num_authkeys_files; i++) { + file = expand_authorized_keys( + options.authorized_keys_files[i], pw); + allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey); + xfree(file); + } + + restore_uid(); + + return allowed; } /* Index: auth.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/auth.c,v retrieving revision 1.92 diff -u -p -r1.92 auth.c --- auth.c 11 May 2011 04:47:06 -0000 1.92 +++ auth.c 13 May 2011 12:22:18 -0000 @@ -241,7 +241,7 @@ auth_root_allowed(char *method) * * This returns a buffer allocated by xmalloc. */ -static char * +char * expand_authorized_keys(const char *filename, struct passwd *pw) { char *file, ret[MAXPATHLEN]; @@ -262,12 +262,6 @@ expand_authorized_keys(const char *filen fatal("expand_authorized_keys: path too long"); xfree(file); return (xstrdup(ret)); -} - -char * -authorized_keys_file(struct passwd *pw) -{ - return expand_authorized_keys(options.authorized_keys_file, pw); } char * Index: auth.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/auth.h,v retrieving revision 1.68 diff -u -p -r1.68 auth.h --- auth.h 11 May 2011 04:47:06 -0000 1.68 +++ auth.h 13 May 2011 12:22:18 -0000 @@ -145,7 +145,7 @@ struct passwd * getpwnamallow(const char char *get_challenge(Authctxt *); int verify_response(Authctxt *, const char *); -char *authorized_keys_file(struct passwd *); +char *expand_authorized_keys(const char *, struct passwd *pw); char *authorized_principals_file(struct passwd *); FILE *auth_openkeyfile(const char *, struct passwd *, int); Index: auth2-pubkey.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/auth2-pubkey.c,v retrieving revision 1.28 diff -u -p -r1.28 auth2-pubkey.c --- auth2-pubkey.c 11 May 2011 04:47:06 -0000 1.28 +++ auth2-pubkey.c 13 May 2011 12:22:18 -0000 @@ -435,7 +435,7 @@ user_cert_trusted_ca(struct passwd *pw, int user_key_allowed(struct passwd *pw, Key *key) { - int success; + u_int success, i; char *file; if (auth_key_is_revoked(key)) @@ -447,9 +447,12 @@ user_key_allowed(struct passwd *pw, Key if (success) return success; - file = authorized_keys_file(pw); - success = user_key_allowed2(pw, key, file); - xfree(file); + for (i = 0; !success && i < options.num_authkeys_files; i++) { + file = expand_authorized_keys( + options.authorized_keys_files[i], pw); + success = user_key_allowed2(pw, key, file); + xfree(file); + } return success; } Index: pathnames.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/pathnames.h,v retrieving revision 1.21 diff -u -p -r1.21 pathnames.h --- pathnames.h 11 May 2011 04:47:06 -0000 1.21 +++ pathnames.h 13 May 2011 12:22:18 -0000 @@ -88,6 +88,9 @@ */ #define _PATH_SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys" +/* backward compat for protocol v2 */ +#define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2" + /* * Per-user and system-wide ssh "rc" files. These files are executed with * /bin/sh before starting the shell or command if they exist. They will be Index: servconf.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/servconf.c,v retrieving revision 1.215 diff -u -p -r1.215 servconf.c --- servconf.c 11 May 2011 04:47:06 -0000 1.215 +++ servconf.c 13 May 2011 12:22:19 -0000 @@ -119,7 +119,7 @@ initialize_server_options(ServerOptions options->use_dns = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; - options->authorized_keys_file = NULL; + options->num_authkeys_files = 0; options->num_accept_env = 0; options->permit_tun = -1; options->num_permitted_opens = -1; @@ -249,8 +249,12 @@ fill_default_server_options(ServerOption options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; - if (options->authorized_keys_file == NULL) - options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); + if (options->num_authkeys_files == 0) { + options->authorized_keys_files[options->num_authkeys_files++] = + xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); + options->authorized_keys_files[options->num_authkeys_files++] = + xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); + } if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; if (options->zero_knowledge_password_authentication == -1) @@ -286,7 +290,7 @@ typedef enum { sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, @@ -391,7 +395,6 @@ static struct { { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, - { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL }, { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, @@ -1197,11 +1200,19 @@ process_server_config_line(ServerOptions * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: - charptr = &options->authorized_keys_file; - goto parse_tilde_filename; + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_authkeys_files >= MAX_AUTHKEYS_FILES) + fatal("%s line %d: " + "too many authorized keys files.", + filename, linenum); + options->authorized_keys_files[ + options->num_authkeys_files++] = + tilde_expand_filename(arg, getuid()); + } + break; + case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; - parse_tilde_filename: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", @@ -1420,6 +1431,10 @@ parse_server_match_config(ServerOptions dst->n = src->n; \ } \ } while(0) +#define M_CP_STRARRAYOPT(n, num_n) do {\ + for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ + dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ +} while(0) /* * Copy any supported values that are set. @@ -1462,8 +1477,8 @@ copy_set_server_options(ServerOptions *d M_CP_STROPT(chroot_directory); M_CP_STROPT(trusted_user_ca_keys); M_CP_STROPT(revoked_keys_file); - M_CP_STROPT(authorized_keys_file); M_CP_STROPT(authorized_principals_file); + M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); } #undef M_CP_INTOPT @@ -1674,7 +1689,6 @@ dump_config(ServerOptions *o) dump_cfg_string(sCiphers, o->ciphers); dump_cfg_string(sMacs, o->macs); dump_cfg_string(sBanner, o->banner); - dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); @@ -1687,6 +1701,8 @@ dump_config(ServerOptions *o) dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); /* string array arguments */ + dump_cfg_strarray(sAuthorizedKeysFile, o->num_authkeys_files, + o->authorized_keys_files); dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, o->host_key_files); dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, Index: servconf.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/servconf.h,v retrieving revision 1.96 diff -u -p -r1.96 servconf.h --- servconf.h 11 May 2011 04:47:06 -0000 1.96 +++ servconf.h 13 May 2011 12:22:19 -0000 @@ -27,6 +27,7 @@ #define MAX_HOSTCERTS 256 /* Max # host certificates. */ #define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ #define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */ +#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */ /* permit_root_login */ #define PERMIT_NOT_SET -1 @@ -145,7 +146,8 @@ typedef struct { * disconnect the session */ - char *authorized_keys_file; /* File containing public keys */ + u_int num_authkeys_files; /* Files containing public keys */ + char *authorized_keys_files[MAX_AUTHKEYS_FILES]; char *adm_forced_command; Index: sshd.8 =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd.8,v retrieving revision 1.260 diff -u -p -r1.260 sshd.8 --- sshd.8 28 Oct 2010 18:33:28 -0000 1.260 +++ sshd.8 13 May 2011 12:22:19 -0000 @@ -435,7 +435,7 @@ is run, and if that does not exist either, xauth is used to add the cookie. .Sh AUTHORIZED_KEYS FILE FORMAT .Cm AuthorizedKeysFile -specifies the file containing public keys for +specifies the file or files containing public keys for public key authentication; if none is specified, the default is .Pa ~/.ssh/authorized_keys . Index: sshd_config =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd_config,v retrieving revision 1.83 diff -u -p -r1.83 sshd_config --- sshd_config 6 May 2011 01:03:35 -0000 1.83 +++ sshd_config 13 May 2011 12:22:19 -0000 @@ -42,7 +42,7 @@ #RSAAuthentication yes #PubkeyAuthentication yes -#AuthorizedKeysFile .ssh/authorized_keys +#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no Index: sshd_config.5 =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd_config.5,v retrieving revision 1.131 diff -u -p -r1.131 sshd_config.5 --- sshd_config.5 8 Dec 2010 04:02:47 -0000 1.131 +++ sshd_config.5 13 May 2011 12:22:19 -0000 @@ -170,6 +170,10 @@ is taken to be an absolute path or one r directory. The default is .Dq .ssh/authorized_keys . +Multiple files may be listed, either on a single line separated by +whitespace or on additional +.Cm AuthorizedKeysFile +lines. .It Cm AuthorizedPrincipalsFile Specifies a file that lists principal names that are accepted for certificate authentication. _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev [at] mindrot https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
|