diff options
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r-- | auth2-pubkey.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 04b70e362..2b0486222 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-pubkey.c,v 1.43 2014/12/21 22:27:56 djm Exp $ */ | 1 | /* $OpenBSD: auth2-pubkey.c,v 1.44 2014/12/22 07:51:30 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -41,6 +41,7 @@ | |||
41 | #include <string.h> | 41 | #include <string.h> |
42 | #include <time.h> | 42 | #include <time.h> |
43 | #include <unistd.h> | 43 | #include <unistd.h> |
44 | #include <limits.h> | ||
44 | 45 | ||
45 | #include "xmalloc.h" | 46 | #include "xmalloc.h" |
46 | #include "ssh.h" | 47 | #include "ssh.h" |
@@ -122,6 +123,10 @@ userauth_pubkey(Authctxt *authctxt) | |||
122 | "signature scheme"); | 123 | "signature scheme"); |
123 | goto done; | 124 | goto done; |
124 | } | 125 | } |
126 | if (auth2_userkey_already_used(authctxt, key)) { | ||
127 | logit("refusing previously-used %s key", key_type(key)); | ||
128 | goto done; | ||
129 | } | ||
125 | if (have_sig) { | 130 | if (have_sig) { |
126 | sig = packet_get_string(&slen); | 131 | sig = packet_get_string(&slen); |
127 | packet_check_eom(); | 132 | packet_check_eom(); |
@@ -159,8 +164,12 @@ userauth_pubkey(Authctxt *authctxt) | |||
159 | authenticated = 0; | 164 | authenticated = 0; |
160 | if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && | 165 | if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && |
161 | PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), | 166 | PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), |
162 | buffer_len(&b))) == 1) | 167 | buffer_len(&b))) == 1) { |
163 | authenticated = 1; | 168 | authenticated = 1; |
169 | /* Record the successful key to prevent reuse */ | ||
170 | auth2_record_userkey(authctxt, key); | ||
171 | key = NULL; /* Don't free below */ | ||
172 | } | ||
164 | buffer_free(&b); | 173 | buffer_free(&b); |
165 | free(sig); | 174 | free(sig); |
166 | } else { | 175 | } else { |
@@ -682,6 +691,35 @@ user_key_allowed(struct passwd *pw, Key *key) | |||
682 | return success; | 691 | return success; |
683 | } | 692 | } |
684 | 693 | ||
694 | /* Records a public key in the list of previously-successful keys */ | ||
695 | void | ||
696 | auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) | ||
697 | { | ||
698 | struct sshkey **tmp; | ||
699 | |||
700 | if (authctxt->nprev_userkeys >= INT_MAX || | ||
701 | (tmp = reallocarray(authctxt->prev_userkeys, | ||
702 | authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) | ||
703 | fatal("%s: reallocarray failed", __func__); | ||
704 | authctxt->prev_userkeys = tmp; | ||
705 | authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; | ||
706 | authctxt->nprev_userkeys++; | ||
707 | } | ||
708 | |||
709 | /* Checks whether a key has already been used successfully for authentication */ | ||
710 | int | ||
711 | auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) | ||
712 | { | ||
713 | u_int i; | ||
714 | |||
715 | for (i = 0; i < authctxt->nprev_userkeys; i++) { | ||
716 | if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { | ||
717 | return 1; | ||
718 | } | ||
719 | } | ||
720 | return 0; | ||
721 | } | ||
722 | |||
685 | Authmethod method_pubkey = { | 723 | Authmethod method_pubkey = { |
686 | "publickey", | 724 | "publickey", |
687 | userauth_pubkey, | 725 | userauth_pubkey, |