mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-27 07:44:29 +02:00
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@
This commit is contained in:
parent
46ac2ed467
commit
f69b69b862
9
auth.h
9
auth.h
@ -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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
@ -42,6 +42,8 @@
|
|||||||
#include <krb5.h>
|
#include <krb5.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct sshkey;
|
||||||
|
|
||||||
typedef struct Authctxt Authctxt;
|
typedef struct Authctxt Authctxt;
|
||||||
typedef struct Authmethod Authmethod;
|
typedef struct Authmethod Authmethod;
|
||||||
typedef struct KbdintDevice KbdintDevice;
|
typedef struct KbdintDevice KbdintDevice;
|
||||||
@ -75,6 +77,9 @@ struct Authctxt {
|
|||||||
#endif
|
#endif
|
||||||
Buffer *loginmsg;
|
Buffer *loginmsg;
|
||||||
void *methoddata;
|
void *methoddata;
|
||||||
|
|
||||||
|
struct sshkey **prev_userkeys;
|
||||||
|
u_int nprev_userkeys;
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* Every authentication method has to handle authentication requests for
|
* 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 *);
|
int user_key_allowed(struct passwd *, Key *);
|
||||||
void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
|
void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
|
||||||
__attribute__((__format__ (printf, 3, 4)));
|
__attribute__((__format__ (printf, 3, 4)));
|
||||||
|
void auth2_record_userkey(Authctxt *, struct sshkey *);
|
||||||
|
int auth2_userkey_already_used(Authctxt *, struct sshkey *);
|
||||||
|
|
||||||
struct stat;
|
struct stat;
|
||||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
||||||
|
@ -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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -41,6 +41,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
@ -122,6 +123,10 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
"signature scheme");
|
"signature scheme");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (auth2_userkey_already_used(authctxt, key)) {
|
||||||
|
logit("refusing previously-used %s key", key_type(key));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (have_sig) {
|
if (have_sig) {
|
||||||
sig = packet_get_string(&slen);
|
sig = packet_get_string(&slen);
|
||||||
packet_check_eom();
|
packet_check_eom();
|
||||||
@ -159,8 +164,12 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
|
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
|
||||||
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
|
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
|
||||||
buffer_len(&b))) == 1)
|
buffer_len(&b))) == 1) {
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
|
/* Record the successful key to prevent reuse */
|
||||||
|
auth2_record_userkey(authctxt, key);
|
||||||
|
key = NULL; /* Don't free below */
|
||||||
|
}
|
||||||
buffer_free(&b);
|
buffer_free(&b);
|
||||||
free(sig);
|
free(sig);
|
||||||
} else {
|
} else {
|
||||||
@ -682,6 +691,35 @@ user_key_allowed(struct passwd *pw, Key *key)
|
|||||||
return success;
|
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 = {
|
Authmethod method_pubkey = {
|
||||||
"publickey",
|
"publickey",
|
||||||
userauth_pubkey,
|
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 Niels Provos <provos@citi.umich.edu>
|
||||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||||
@ -1170,6 +1170,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case MM_USERKEY:
|
case MM_USERKEY:
|
||||||
allowed = options.pubkey_authentication &&
|
allowed = options.pubkey_authentication &&
|
||||||
|
!auth2_userkey_already_used(authctxt, key) &&
|
||||||
user_key_allowed(authctxt->pw, key);
|
user_key_allowed(authctxt->pw, key);
|
||||||
pubkey_auth_info(authctxt, key, NULL);
|
pubkey_auth_info(authctxt, key, NULL);
|
||||||
auth_method = "publickey";
|
auth_method = "publickey";
|
||||||
@ -1397,7 +1398,12 @@ mm_answer_keyverify(int sock, Buffer *m)
|
|||||||
debug3("%s: key %p signature %s",
|
debug3("%s: key %p signature %s",
|
||||||
__func__, key, (verified == 1) ? "verified" : "unverified");
|
__func__, key, (verified == 1) ? "verified" : "unverified");
|
||||||
|
|
||||||
|
/* 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);
|
key_free(key);
|
||||||
|
|
||||||
free(blob);
|
free(blob);
|
||||||
free(signature);
|
free(signature);
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" 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 $
|
.\" $OpenBSD: sshd_config.5,v 1.185 2014/12/22 07:51:30 djm Exp $
|
||||||
.Dd $Mdocdate: December 21 2014 $
|
.Dd $Mdocdate: December 22 2014 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -210,6 +210,18 @@ would restrict keyboard interactive authentication to the
|
|||||||
.Dq bsdauth
|
.Dq bsdauth
|
||||||
device.
|
device.
|
||||||
.Pp
|
.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
|
This option is only available for SSH protocol 2 and will yield a fatal
|
||||||
error if enabled if protocol 1 is also enabled.
|
error if enabled if protocol 1 is also enabled.
|
||||||
Note that each authentication method listed should also be explicitly enabled
|
Note that each authentication method listed should also be explicitly enabled
|
||||||
|
Loading…
x
Reference in New Issue
Block a user