diff options
author | djm@openbsd.org <djm@openbsd.org> | 2014-12-22 07:51:30 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-12-22 19:06:52 +1100 |
commit | f69b69b8625be447b8826b21d87713874dac25a6 (patch) | |
tree | ad29e7621445860c76e02f7f2384b0198bfc27e5 | |
parent | 46ac2ed4677968224c4ca825bc98fc68dae183f0 (diff) |
upstream commit
remember which public keys have been used for
authentication and refuse to accept previously-used keys.
This allows AuthenticationMethods=publickey,publickey to require
that users authenticate using two _different_ pubkeys.
ok markus@
-rw-r--r-- | auth.h | 9 | ||||
-rw-r--r-- | auth2-pubkey.c | 42 | ||||
-rw-r--r-- | monitor.c | 10 | ||||
-rw-r--r-- | sshd_config.5 | 16 |
4 files changed, 70 insertions, 7 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.79 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -42,6 +42,8 @@ #include <krb5.h> #endif +struct sshkey; + typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; typedef struct KbdintDevice KbdintDevice; @@ -75,6 +77,9 @@ struct Authctxt { #endif Buffer *loginmsg; void *methoddata; + + struct sshkey **prev_userkeys; + u_int nprev_userkeys; }; /* * Every authentication method has to handle authentication requests for @@ -123,6 +128,8 @@ int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); int user_key_allowed(struct passwd *, Key *); void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) __attribute__((__format__ (printf, 3, 4))); +void auth2_record_userkey(Authctxt *, struct sshkey *); +int auth2_userkey_already_used(Authctxt *, struct sshkey *); struct stat; int auth_secure_path(const char *, struct stat *, const char *, uid_t, diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 04b70e36..2b048622 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.44 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -41,6 +41,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <limits.h> #include "xmalloc.h" #include "ssh.h" @@ -122,6 +123,10 @@ userauth_pubkey(Authctxt *authctxt) "signature scheme"); goto done; } + if (auth2_userkey_already_used(authctxt, key)) { + logit("refusing previously-used %s key", key_type(key)); + goto done; + } if (have_sig) { sig = packet_get_string(&slen); packet_check_eom(); @@ -159,8 +164,12 @@ userauth_pubkey(Authctxt *authctxt) authenticated = 0; if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + buffer_len(&b))) == 1) { authenticated = 1; + /* Record the successful key to prevent reuse */ + auth2_record_userkey(authctxt, key); + key = NULL; /* Don't free below */ + } buffer_free(&b); free(sig); } else { @@ -682,6 +691,35 @@ user_key_allowed(struct passwd *pw, Key *key) return success; } +/* Records a public key in the list of previously-successful keys */ +void +auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) +{ + struct sshkey **tmp; + + if (authctxt->nprev_userkeys >= INT_MAX || + (tmp = reallocarray(authctxt->prev_userkeys, + authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) + fatal("%s: reallocarray failed", __func__); + authctxt->prev_userkeys = tmp; + authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; + authctxt->nprev_userkeys++; +} + +/* Checks whether a key has already been used successfully for authentication */ +int +auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) +{ + u_int i; + + for (i = 0; i < authctxt->nprev_userkeys; i++) { + if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { + return 1; + } + } + return 0; +} + Authmethod method_pubkey = { "publickey", userauth_pubkey, @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: monitor.c,v 1.136 2014/12/22 07:51:30 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -1170,6 +1170,7 @@ mm_answer_keyallowed(int sock, Buffer *m) switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && + !auth2_userkey_already_used(authctxt, key) && user_key_allowed(authctxt->pw, key); pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; @@ -1397,7 +1398,12 @@ mm_answer_keyverify(int sock, Buffer *m) debug3("%s: key %p signature %s", __func__, key, (verified == 1) ? "verified" : "unverified"); - key_free(key); + /* If auth was successful then record key to ensure it isn't reused */ + if (verified == 1) + auth2_record_userkey(authctxt, key); + else + key_free(key); + free(blob); free(signature); free(data); diff --git a/sshd_config.5 b/sshd_config.5 index 938ba2f1..d2ab2813 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.184 2014/12/21 23:35:14 jmc Exp $ -.Dd $Mdocdate: December 21 2014 $ +.\" $OpenBSD: sshd_config.5,v 1.185 2014/12/22 07:51:30 djm Exp $ +.Dd $Mdocdate: December 22 2014 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -210,6 +210,18 @@ would restrict keyboard interactive authentication to the .Dq bsdauth device. .Pp +If the +.Dq publickey +method is listed more than one, +.Xr sshd 8 +verifies that keys that have been used successfully are not reused for +subsequent authentications. +For example, an +.Cm AuthenticationMethods +of +.Dq publickey,publickey +will require successful authentication using two different public keys. +.Pp This option is only available for SSH protocol 2 and will yield a fatal error if enabled if protocol 1 is also enabled. Note that each authentication method listed should also be explicitly enabled |