diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | auth-rsa.c | 70 | ||||
-rw-r--r-- | auth.c | 10 | ||||
-rw-r--r-- | auth.h | 4 | ||||
-rw-r--r-- | auth2-pubkey.c | 13 | ||||
-rw-r--r-- | monitor.c | 9 | ||||
-rw-r--r-- | monitor_wrap.c | 9 | ||||
-rw-r--r-- | pathnames.h | 5 | ||||
-rw-r--r-- | servconf.c | 54 | ||||
-rw-r--r-- | servconf.h | 8 | ||||
-rw-r--r-- | sshd.8 | 12 | ||||
-rw-r--r-- | sshd_config | 7 | ||||
-rw-r--r-- | sshd_config.5 | 11 |
13 files changed, 151 insertions, 74 deletions
@@ -1,3 +1,16 @@ +20110529 + - (djm) OpenBSD CVS Sync + - djm@cvs.openbsd.org 2011/05/23 03:30:07 + [auth-rsa.c auth.c auth.h auth2-pubkey.c monitor.c monitor_wrap.c] + [pathnames.h servconf.c servconf.h sshd.8 sshd_config sshd_config.5] + allow AuthorizedKeysFile to specify multiple files, separated by spaces. + Bring back authorized_keys2 as a default search path (to avoid breaking + existing users of this file), but override this in sshd_config so it will + be no longer used on fresh installs. Maybe in 2015 we can remove it + entierly :) + + feedback and ok markus@ dtucker@ + 20110520 - (djm) [session.c] call setexeccon() before executing passwd for pw changes; bz#1891 reported by jchadima AT redhat.com; ok dtucker@ @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.79 2010/12/03 23:55:27 djm Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -160,44 +160,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; @@ -235,7 +218,10 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) } /* 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; @@ -264,11 +250,7 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) break; } - /* Restore the privileged uid. */ - restore_uid(); - /* Close the file. */ - xfree(file); fclose(f); /* return key if allowed */ @@ -276,7 +258,33 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) *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; } /* @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.92 2011/05/11 04:47:06 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.93 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -331,7 +331,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]; @@ -355,12 +355,6 @@ expand_authorized_keys(const char *filename, struct passwd *pw) } char * -authorized_keys_file(struct passwd *pw) -{ - return expand_authorized_keys(options.authorized_keys_file, pw); -} - -char * authorized_principals_file(struct passwd *pw) { if (options.authorized_principals_file == NULL) @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.68 2011/05/11 04:47:06 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -168,7 +168,7 @@ char *get_challenge(Authctxt *); int verify_response(Authctxt *, const char *); void abandon_challenge_response(Authctxt *); -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); diff --git a/auth2-pubkey.c b/auth2-pubkey.c index a97509c2..137887ec 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.28 2011/05/11 04:47:06 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.29 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -436,7 +436,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) int user_key_allowed(struct passwd *pw, Key *key) { - int success; + u_int success, i; char *file; if (auth_key_is_revoked(key)) @@ -448,9 +448,12 @@ user_key_allowed(struct passwd *pw, Key *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; } @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.112 2011/05/20 03:25:45 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.113 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -632,6 +632,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) char *username; struct passwd *pwent; int allowed = 0; + u_int i; debug3("%s", __func__); @@ -676,9 +677,14 @@ mm_answer_pwnamallow(int sock, Buffer *m) if (options.x != NULL) \ buffer_put_cstring(m, options.x); \ } while (0) +#define M_CP_STRARRAYOPT(x, nx) do { \ + for (i = 0; i < options.nx; i++) \ + buffer_put_cstring(m, options.x[i]); \ + } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT +#undef M_CP_STRARRAYOPT debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); @@ -691,7 +697,6 @@ mm_answer_pwnamallow(int sock, Buffer *m) monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); } - #ifdef USE_PAM if (options.use_pam) monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); diff --git a/monitor_wrap.c b/monitor_wrap.c index d3f27402..7a90b3ba 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.71 2011/05/20 03:25:45 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.72 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -211,7 +211,7 @@ mm_getpwnamallow(const char *username) { Buffer m; struct passwd *pw; - u_int len; + u_int len, i; ServerOptions *newopts; debug3("%s entering", __func__); @@ -250,9 +250,14 @@ out: if (newopts->x != NULL) \ newopts->x = buffer_get_string(&m, NULL); \ } while (0) +#define M_CP_STRARRAYOPT(x, nx) do { \ + for (i = 0; i < newopts->nx; i++) \ + newopts->x[i] = buffer_get_string(&m, NULL); \ + } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT +#undef M_CP_STRARRAYOPT copy_set_server_options(&options, newopts, 1); xfree(newopts); diff --git a/pathnames.h b/pathnames.h index 787bdb67..c3d9abff 100644 --- a/pathnames.h +++ b/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.21 2011/05/11 04:47:06 djm Exp $ */ +/* $OpenBSD: pathnames.h,v 1.22 2011/05/23 03:30:07 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -96,6 +96,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 @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.218 2011/05/20 03:25:45 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.219 2011/05/23 03:30:07 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * All rights reserved @@ -126,7 +126,7 @@ initialize_server_options(ServerOptions *options) 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; @@ -263,8 +263,12 @@ fill_default_server_options(ServerOptions *options) 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) @@ -430,6 +434,7 @@ static struct { { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, + { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, @@ -1241,11 +1246,22 @@ process_server_config_line(ServerOptions *options, char *line, * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: - charptr = &options->authorized_keys_file; - goto parse_tilde_filename; + if (*activep && options->num_authkeys_files == 0) { + 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()); + } + } + return 0; + case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; - parse_tilde_filename: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", @@ -1464,6 +1480,12 @@ parse_server_match_config(ServerOptions *options, const char *user, dst->n = src->n; \ } \ } while(0) +#define M_CP_STRARRAYOPT(n, num_n) do {\ + if (src->num_n != 0) { \ + 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. @@ -1508,12 +1530,14 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) */ if (preauth) return; + M_CP_STROPT(adm_forced_command); M_CP_STROPT(chroot_directory); } #undef M_CP_INTOPT #undef M_CP_STROPT +#undef M_CP_STRARRAYOPT void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, @@ -1627,7 +1651,18 @@ dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) u_int i; for (i = 0; i < count; i++) - printf("%s %s\n", lookup_opcode_name(code), vals[i]); + printf("%s %s\n", lookup_opcode_name(code), vals[i]); +} + +static void +dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) +{ + u_int i; + + printf("%s", lookup_opcode_name(code)); + for (i = 0; i < count; i++) + printf(" %s", vals[i]); + printf("\n"); } void @@ -1725,7 +1760,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); @@ -1738,6 +1772,8 @@ dump_config(ServerOptions *o) dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); /* string array arguments */ + dump_cfg_strarray_oneline(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, @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.97 2011/05/20 03:25:45 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.98 2011/05/23 03:30:07 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -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; @@ -171,8 +173,8 @@ typedef struct { M_CP_STROPT(banner); \ 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); \ } while (0) void initialize_server_options(ServerOptions *); @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.260 2010/10/28 18:33:28 jmc Exp $ -.Dd $Mdocdate: October 28 2010 $ +.\" $OpenBSD: sshd.8,v 1.261 2011/05/23 03:30:07 djm Exp $ +.Dd $Mdocdate: May 23 2011 $ .Dt SSHD 8 .Os .Sh NAME @@ -462,10 +462,12 @@ 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 . +if none is specified, the default is both +.Pa ~/.ssh/authorized_keys +and +.Pa ~/.ssh/authorized_keys2 . Each line of the file contains one key (empty lines and lines starting with a .Ql # diff --git a/sshd_config b/sshd_config index 9b0d9fa2..473e8665 100644 --- a/sshd_config +++ b/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.83 2011/05/06 01:03:35 dtucker Exp $ +# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -44,7 +44,10 @@ #RSAAuthentication yes #PubkeyAuthentication yes -#AuthorizedKeysFile .ssh/authorized_keys + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no diff --git a/sshd_config.5 b/sshd_config.5 index c3d6df30..b23e0f78 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.131 2010/12/08 04:02:47 djm Exp $ -.Dd $Mdocdate: December 8 2010 $ +.\" $OpenBSD: sshd_config.5,v 1.132 2011/05/23 03:30:07 djm Exp $ +.Dd $Mdocdate: May 23 2011 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -168,8 +168,11 @@ After expansion, .Cm AuthorizedKeysFile is taken to be an absolute path or one relative to the user's home directory. -The default is -.Dq .ssh/authorized_keys . +The default is both +.Dq .ssh/authorized_keys +and +.Dq .ssh/authorized_keys2 . +Multiple files may be listed separated by whitespace. .It Cm AuthorizedPrincipalsFile Specifies a file that lists principal names that are accepted for certificate authentication. |