refuse to accept previously-used keys.
This allows AuthenticationMethods=publickey,publickey to require
that users authenticate using two _different_ pubkeys.
ok markus@
-/* $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.
#include <krb5.h>
#endif
+struct sshkey;
+
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
char *krb5_ticket_file;
#endif
void *methoddata;
+
+ struct sshkey **prev_userkeys;
+ u_int nprev_userkeys;
};
/*
* Every authentication method has to handle authentication requests for
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,
-/* $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.
*
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <limits.h>
#include "xmalloc.h"
#include "ssh.h"
"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();
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 {
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,
-/* $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>
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";
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);
.\" (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
.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