summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth.h9
-rw-r--r--auth2-pubkey.c42
-rw-r--r--monitor.c10
-rw-r--r--sshd_config.516
4 files changed, 70 insertions, 7 deletions
diff --git a/auth.h b/auth.h
index d081c94a6..c67e4a4d4 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */ 1/* $OpenBSD: auth.h,v 1.79 2014/12/22 07:51:30 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -42,6 +42,8 @@
42#include <krb5.h> 42#include <krb5.h>
43#endif 43#endif
44 44
45struct sshkey;
46
45typedef struct Authctxt Authctxt; 47typedef struct Authctxt Authctxt;
46typedef struct Authmethod Authmethod; 48typedef struct Authmethod Authmethod;
47typedef struct KbdintDevice KbdintDevice; 49typedef struct KbdintDevice KbdintDevice;
@@ -75,6 +77,9 @@ struct Authctxt {
75#endif 77#endif
76 Buffer *loginmsg; 78 Buffer *loginmsg;
77 void *methoddata; 79 void *methoddata;
80
81 struct sshkey **prev_userkeys;
82 u_int nprev_userkeys;
78}; 83};
79/* 84/*
80 * Every authentication method has to handle authentication requests for 85 * Every authentication method has to handle authentication requests for
@@ -123,6 +128,8 @@ int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
123int user_key_allowed(struct passwd *, Key *); 128int user_key_allowed(struct passwd *, Key *);
124void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) 129void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
125 __attribute__((__format__ (printf, 3, 4))); 130 __attribute__((__format__ (printf, 3, 4)));
131void auth2_record_userkey(Authctxt *, struct sshkey *);
132int auth2_userkey_already_used(Authctxt *, struct sshkey *);
126 133
127struct stat; 134struct stat;
128int auth_secure_path(const char *, struct stat *, const char *, uid_t, 135int auth_secure_path(const char *, struct stat *, const char *, uid_t,
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 */
695void
696auth2_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 */
710int
711auth2_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
685Authmethod method_pubkey = { 723Authmethod method_pubkey = {
686 "publickey", 724 "publickey",
687 userauth_pubkey, 725 userauth_pubkey,
diff --git a/monitor.c b/monitor.c
index dbe29f128..b830e0374 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */ 1/* $OpenBSD: monitor.c,v 1.136 2014/12/22 07:51:30 djm Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1170,6 +1170,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
1170 switch (type) { 1170 switch (type) {
1171 case MM_USERKEY: 1171 case MM_USERKEY:
1172 allowed = options.pubkey_authentication && 1172 allowed = options.pubkey_authentication &&
1173 !auth2_userkey_already_used(authctxt, key) &&
1173 user_key_allowed(authctxt->pw, key); 1174 user_key_allowed(authctxt->pw, key);
1174 pubkey_auth_info(authctxt, key, NULL); 1175 pubkey_auth_info(authctxt, key, NULL);
1175 auth_method = "publickey"; 1176 auth_method = "publickey";
@@ -1397,7 +1398,12 @@ mm_answer_keyverify(int sock, Buffer *m)
1397 debug3("%s: key %p signature %s", 1398 debug3("%s: key %p signature %s",
1398 __func__, key, (verified == 1) ? "verified" : "unverified"); 1399 __func__, key, (verified == 1) ? "verified" : "unverified");
1399 1400
1400 key_free(key); 1401 /* If auth was successful then record key to ensure it isn't reused */
1402 if (verified == 1)
1403 auth2_record_userkey(authctxt, key);
1404 else
1405 key_free(key);
1406
1401 free(blob); 1407 free(blob);
1402 free(signature); 1408 free(signature);
1403 free(data); 1409 free(data);
diff --git a/sshd_config.5 b/sshd_config.5
index 938ba2f1a..d2ab28136 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.184 2014/12/21 23:35:14 jmc Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.185 2014/12/22 07:51:30 djm Exp $
37.Dd $Mdocdate: December 21 2014 $ 37.Dd $Mdocdate: December 22 2014 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -210,6 +210,18 @@ would restrict keyboard interactive authentication to the
210.Dq bsdauth 210.Dq bsdauth
211device. 211device.
212.Pp 212.Pp
213If the
214.Dq publickey
215method is listed more than one,
216.Xr sshd 8
217verifies that keys that have been used successfully are not reused for
218subsequent authentications.
219For example, an
220.Cm AuthenticationMethods
221of
222.Dq publickey,publickey
223will require successful authentication using two different public keys.
224.Pp
213This option is only available for SSH protocol 2 and will yield a fatal 225This option is only available for SSH protocol 2 and will yield a fatal
214error if enabled if protocol 1 is also enabled. 226error if enabled if protocol 1 is also enabled.
215Note that each authentication method listed should also be explicitly enabled 227Note that each authentication method listed should also be explicitly enabled