upstream: Add a sshd_config PubkeyAuthOptions directive
This directive has a single valid option "no-touch-required" that causes sshd to skip checking whether user presence was tested before a security key signature was made (usually by the user touching the key). ok markus@ OpenBSD-Commit-ID: 46e434a49802d4ed82bc0aa38cb985c198c407de
This commit is contained in:
parent
b7e74ea072
commit
0fddf2967a
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-pubkey.c,v 1.95 2019/11/25 00:51:37 djm Exp $ */
|
/* $OpenBSD: auth2-pubkey.c,v 1.96 2019/11/25 00:52:46 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -68,6 +68,7 @@
|
||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
#include "channels.h" /* XXX for session.h */
|
#include "channels.h" /* XXX for session.h */
|
||||||
#include "session.h" /* XXX for child_set_env(); refactor? */
|
#include "session.h" /* XXX for child_set_env(); refactor? */
|
||||||
|
#include "sk-api.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
@ -96,7 +97,7 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
u_char *pkblob = NULL, *sig = NULL, have_sig;
|
u_char *pkblob = NULL, *sig = NULL, have_sig;
|
||||||
size_t blen, slen;
|
size_t blen, slen;
|
||||||
int r, pktype;
|
int r, pktype;
|
||||||
int authenticated = 0;
|
int req_presence = 0, authenticated = 0;
|
||||||
struct sshauthopt *authopts = NULL;
|
struct sshauthopt *authopts = NULL;
|
||||||
struct sshkey_sig_details *sig_details = NULL;
|
struct sshkey_sig_details *sig_details = NULL;
|
||||||
|
|
||||||
|
@ -217,10 +218,25 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
ssh->compat, &sig_details)) == 0) {
|
ssh->compat, &sig_details)) == 0) {
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
}
|
}
|
||||||
if (sig_details != NULL) {
|
if (authenticated == 1 && sig_details != NULL) {
|
||||||
|
auth2_record_info(authctxt, "signature count = %u",
|
||||||
|
sig_details->sk_counter);
|
||||||
debug("%s: sk_counter = %u, sk_flags = 0x%02x",
|
debug("%s: sk_counter = %u, sk_flags = 0x%02x",
|
||||||
__func__, sig_details->sk_counter,
|
__func__, sig_details->sk_counter,
|
||||||
sig_details->sk_flags);
|
sig_details->sk_flags);
|
||||||
|
req_presence = (options.pubkey_auth_options &
|
||||||
|
PUBKEYAUTH_TOUCH_REQUIRED);
|
||||||
|
if (req_presence && (sig_details->sk_flags &
|
||||||
|
SSH_SK_USER_PRESENCE_REQD) == 0) {
|
||||||
|
error("public key %s signature for %s%s from "
|
||||||
|
"%.128s port %d rejected: user presence "
|
||||||
|
"(key touch) requirement not met ", key_s,
|
||||||
|
authctxt->valid ? "" : "invalid user ",
|
||||||
|
authctxt->user, ssh_remote_ipaddr(ssh),
|
||||||
|
ssh_remote_port(ssh));
|
||||||
|
authenticated = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auth2_record_key(authctxt, authenticated, key);
|
auth2_record_key(authctxt, authenticated, key);
|
||||||
} else {
|
} else {
|
||||||
|
|
63
monitor.c
63
monitor.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: monitor.c,v 1.202 2019/11/25 00:51:37 djm Exp $ */
|
/* $OpenBSD: monitor.c,v 1.203 2019/11/25 00:52:46 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>
|
||||||
|
@ -95,6 +95,7 @@
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
|
#include "sk-api.h"
|
||||||
|
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
static Gssctxt *gsscontext = NULL;
|
static Gssctxt *gsscontext = NULL;
|
||||||
|
@ -542,7 +543,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
|
||||||
|
|
||||||
/* allowed key state */
|
/* allowed key state */
|
||||||
static int
|
static int
|
||||||
monitor_allowed_key(u_char *blob, u_int bloblen)
|
monitor_allowed_key(const u_char *blob, u_int bloblen)
|
||||||
{
|
{
|
||||||
/* make sure key is allowed */
|
/* make sure key is allowed */
|
||||||
if (key_blob == NULL || key_bloblen != bloblen ||
|
if (key_blob == NULL || key_bloblen != bloblen ||
|
||||||
|
@ -1247,7 +1248,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
monitor_valid_userblob(u_char *data, u_int datalen)
|
monitor_valid_userblob(const u_char *data, u_int datalen)
|
||||||
{
|
{
|
||||||
struct sshbuf *b;
|
struct sshbuf *b;
|
||||||
const u_char *p;
|
const u_char *p;
|
||||||
|
@ -1256,10 +1257,8 @@ monitor_valid_userblob(u_char *data, u_int datalen)
|
||||||
u_char type;
|
u_char type;
|
||||||
int r, fail = 0;
|
int r, fail = 0;
|
||||||
|
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_from(data, datalen)) == NULL)
|
||||||
fatal("%s: sshbuf_new", __func__);
|
fatal("%s: sshbuf_from", __func__);
|
||||||
if ((r = sshbuf_put(b, data, datalen)) != 0)
|
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
if (datafellows & SSH_OLD_SESSIONID) {
|
if (datafellows & SSH_OLD_SESSIONID) {
|
||||||
p = sshbuf_ptr(b);
|
p = sshbuf_ptr(b);
|
||||||
|
@ -1314,8 +1313,8 @@ monitor_valid_userblob(u_char *data, u_int datalen)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
|
monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
|
||||||
char *chost)
|
const char *cuser, const char *chost)
|
||||||
{
|
{
|
||||||
struct sshbuf *b;
|
struct sshbuf *b;
|
||||||
const u_char *p;
|
const u_char *p;
|
||||||
|
@ -1324,10 +1323,9 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
|
||||||
int r, fail = 0;
|
int r, fail = 0;
|
||||||
u_char type;
|
u_char type;
|
||||||
|
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_from(data, datalen)) == NULL)
|
||||||
fatal("%s: sshbuf_new", __func__);
|
fatal("%s: sshbuf_new", __func__);
|
||||||
if ((r = sshbuf_put(b, data, datalen)) != 0 ||
|
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
|
||||||
(r = sshbuf_get_string_direct(b, &p, &len)) != 0)
|
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
if ((session_id2 == NULL) ||
|
if ((session_id2 == NULL) ||
|
||||||
|
@ -1387,15 +1385,15 @@ int
|
||||||
mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
|
mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
{
|
{
|
||||||
struct sshkey *key;
|
struct sshkey *key;
|
||||||
u_char *signature, *data, *blob;
|
const u_char *signature, *data, *blob;
|
||||||
char *sigalg;
|
char *sigalg = NULL, *fp = NULL;
|
||||||
size_t signaturelen, datalen, bloblen;
|
size_t signaturelen, datalen, bloblen;
|
||||||
int r, ret, valid_data = 0, encoded_ret;
|
int r, ret, req_presence = 0, valid_data = 0, encoded_ret;
|
||||||
struct sshkey_sig_details *sig_details = NULL;
|
struct sshkey_sig_details *sig_details = NULL;
|
||||||
|
|
||||||
if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
|
if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 ||
|
||||||
(r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
|
(r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 ||
|
||||||
(r = sshbuf_get_string(m, &data, &datalen)) != 0 ||
|
(r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 ||
|
||||||
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
|
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
@ -1430,23 +1428,36 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
if (!valid_data)
|
if (!valid_data)
|
||||||
fatal("%s: bad signature data blob", __func__);
|
fatal("%s: bad signature data blob", __func__);
|
||||||
|
|
||||||
|
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
|
||||||
|
SSH_FP_DEFAULT)) == NULL)
|
||||||
|
fatal("%s: sshkey_fingerprint failed", __func__);
|
||||||
|
|
||||||
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
||||||
sigalg, ssh->compat, &sig_details);
|
sigalg, ssh->compat, &sig_details);
|
||||||
debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key,
|
debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key,
|
||||||
(ret == 0) ? "verified" : "unverified",
|
(ret == 0) ? "verified" : "unverified",
|
||||||
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
|
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
|
||||||
auth2_record_key(authctxt, ret == 0, key);
|
|
||||||
|
|
||||||
free(blob);
|
if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) {
|
||||||
free(signature);
|
req_presence = (options.pubkey_auth_options &
|
||||||
free(data);
|
PUBKEYAUTH_TOUCH_REQUIRED);
|
||||||
free(sigalg);
|
if (req_presence &&
|
||||||
|
(sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) {
|
||||||
|
error("public key %s %s signature for %s%s from %.128s "
|
||||||
|
"port %d rejected: user presence (key touch) "
|
||||||
|
"requirement not met ", sshkey_type(key), fp,
|
||||||
|
authctxt->valid ? "" : "invalid user ",
|
||||||
|
authctxt->user, ssh_remote_ipaddr(ssh),
|
||||||
|
ssh_remote_port(ssh));
|
||||||
|
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auth2_record_key(authctxt, ret == 0, key);
|
||||||
|
|
||||||
if (key_blobtype == MM_USERKEY)
|
if (key_blobtype == MM_USERKEY)
|
||||||
auth_activate_options(ssh, key_opts);
|
auth_activate_options(ssh, key_opts);
|
||||||
monitor_reset_key_state();
|
monitor_reset_key_state();
|
||||||
|
|
||||||
sshkey_free(key);
|
|
||||||
sshbuf_reset(m);
|
sshbuf_reset(m);
|
||||||
|
|
||||||
/* encode ret != 0 as positive integer, since we're sending u32 */
|
/* encode ret != 0 as positive integer, since we're sending u32 */
|
||||||
|
@ -1462,6 +1473,10 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
sshkey_sig_details_free(sig_details);
|
sshkey_sig_details_free(sig_details);
|
||||||
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
|
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
|
||||||
|
|
||||||
|
free(sigalg);
|
||||||
|
free(fp);
|
||||||
|
sshkey_free(key);
|
||||||
|
|
||||||
return ret == 0;
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
servconf.c
33
servconf.c
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
/* $OpenBSD: servconf.c,v 1.353 2019/10/31 21:17:49 djm Exp $ */
|
/* $OpenBSD: servconf.c,v 1.354 2019/11/25 00:52:46 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -118,6 +118,7 @@ initialize_server_options(ServerOptions *options)
|
||||||
options->hostbased_key_types = NULL;
|
options->hostbased_key_types = NULL;
|
||||||
options->hostkeyalgorithms = NULL;
|
options->hostkeyalgorithms = NULL;
|
||||||
options->pubkey_authentication = -1;
|
options->pubkey_authentication = -1;
|
||||||
|
options->pubkey_auth_options = -1;
|
||||||
options->pubkey_key_types = NULL;
|
options->pubkey_key_types = NULL;
|
||||||
options->kerberos_authentication = -1;
|
options->kerberos_authentication = -1;
|
||||||
options->kerberos_or_local_passwd = -1;
|
options->kerberos_or_local_passwd = -1;
|
||||||
|
@ -341,6 +342,8 @@ fill_default_server_options(ServerOptions *options)
|
||||||
options->hostbased_uses_name_from_packet_only = 0;
|
options->hostbased_uses_name_from_packet_only = 0;
|
||||||
if (options->pubkey_authentication == -1)
|
if (options->pubkey_authentication == -1)
|
||||||
options->pubkey_authentication = 1;
|
options->pubkey_authentication = 1;
|
||||||
|
if (options->pubkey_auth_options == -1)
|
||||||
|
options->pubkey_auth_options = 0;
|
||||||
if (options->kerberos_authentication == -1)
|
if (options->kerberos_authentication == -1)
|
||||||
options->kerberos_authentication = 0;
|
options->kerberos_authentication = 0;
|
||||||
if (options->kerberos_or_local_passwd == -1)
|
if (options->kerberos_or_local_passwd == -1)
|
||||||
|
@ -509,7 +512,7 @@ typedef enum {
|
||||||
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
||||||
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||||||
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
||||||
sExposeAuthInfo, sRDomain,
|
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions,
|
||||||
sDeprecated, sIgnore, sUnsupported
|
sDeprecated, sIgnore, sUnsupported
|
||||||
} ServerOpCodes;
|
} ServerOpCodes;
|
||||||
|
|
||||||
|
@ -551,6 +554,7 @@ static struct {
|
||||||
{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
|
{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
|
||||||
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
|
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
|
||||||
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
|
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
|
||||||
|
{ "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
|
||||||
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
|
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
|
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
|
||||||
|
@ -1468,6 +1472,24 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
charptr = &options->pubkey_key_types;
|
charptr = &options->pubkey_key_types;
|
||||||
goto parse_keytypes;
|
goto parse_keytypes;
|
||||||
|
|
||||||
|
case sPubkeyAuthOptions:
|
||||||
|
intptr = &options->pubkey_auth_options;
|
||||||
|
value = 0;
|
||||||
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
|
if (strcasecmp(arg, "none") == 0)
|
||||||
|
continue;
|
||||||
|
if (strcasecmp(arg, "touch-required") == 0)
|
||||||
|
value |= PUBKEYAUTH_TOUCH_REQUIRED;
|
||||||
|
else {
|
||||||
|
fatal("%s line %d: unsupported "
|
||||||
|
"PubkeyAuthOptions option %s",
|
||||||
|
filename, linenum, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*activep && *intptr == -1)
|
||||||
|
*intptr = value;
|
||||||
|
break;
|
||||||
|
|
||||||
case sKerberosAuthentication:
|
case sKerberosAuthentication:
|
||||||
intptr = &options->kerberos_authentication;
|
intptr = &options->kerberos_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
@ -2290,6 +2312,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
||||||
M_CP_INTOPT(password_authentication);
|
M_CP_INTOPT(password_authentication);
|
||||||
M_CP_INTOPT(gss_authentication);
|
M_CP_INTOPT(gss_authentication);
|
||||||
M_CP_INTOPT(pubkey_authentication);
|
M_CP_INTOPT(pubkey_authentication);
|
||||||
|
M_CP_INTOPT(pubkey_auth_options);
|
||||||
M_CP_INTOPT(kerberos_authentication);
|
M_CP_INTOPT(kerberos_authentication);
|
||||||
M_CP_INTOPT(hostbased_authentication);
|
M_CP_INTOPT(hostbased_authentication);
|
||||||
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
|
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
|
||||||
|
@ -2711,4 +2734,10 @@ dump_config(ServerOptions *o)
|
||||||
o->permit_user_env_whitelist);
|
o->permit_user_env_whitelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("pubkeyauthoptions");
|
||||||
|
if (o->pubkey_auth_options == 0)
|
||||||
|
printf(" none");
|
||||||
|
if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
|
||||||
|
printf(" touch-required");
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: servconf.h,v 1.140 2019/04/18 18:56:16 dtucker Exp $ */
|
/* $OpenBSD: servconf.h,v 1.141 2019/11/25 00:52:46 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -42,6 +42,9 @@
|
||||||
/* Magic name for internal sftp-server */
|
/* Magic name for internal sftp-server */
|
||||||
#define INTERNAL_SFTP_NAME "internal-sftp"
|
#define INTERNAL_SFTP_NAME "internal-sftp"
|
||||||
|
|
||||||
|
/* PubkeyAuthOptions flags */
|
||||||
|
#define PUBKEYAUTH_TOUCH_REQUIRED 1
|
||||||
|
|
||||||
struct ssh;
|
struct ssh;
|
||||||
struct fwd_perm_list;
|
struct fwd_perm_list;
|
||||||
|
|
||||||
|
@ -114,6 +117,7 @@ typedef struct {
|
||||||
char *ca_sign_algorithms; /* Allowed CA signature algorithms */
|
char *ca_sign_algorithms; /* Allowed CA signature algorithms */
|
||||||
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
|
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
|
||||||
char *pubkey_key_types; /* Key types allowed for public key */
|
char *pubkey_key_types; /* Key types allowed for public key */
|
||||||
|
int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */
|
||||||
int kerberos_authentication; /* If true, permit Kerberos
|
int kerberos_authentication; /* If true, permit Kerberos
|
||||||
* authentication. */
|
* authentication. */
|
||||||
int kerberos_or_local_passwd; /* If true, permit kerberos
|
int kerberos_or_local_passwd; /* If true, permit kerberos
|
||||||
|
|
|
@ -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.292 2019/11/18 04:55:02 djm Exp $
|
.\" $OpenBSD: sshd_config.5,v 1.293 2019/11/25 00:52:46 djm Exp $
|
||||||
.Dd $Mdocdate: November 18 2019 $
|
.Dd $Mdocdate: November 25 2019 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1444,6 +1444,29 @@ ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
|
||||||
.Pp
|
.Pp
|
||||||
The list of available key types may also be obtained using
|
The list of available key types may also be obtained using
|
||||||
.Qq ssh -Q key .
|
.Qq ssh -Q key .
|
||||||
|
.It Cm PubkeyAuthOptions
|
||||||
|
Sets one or more public key authentication options.
|
||||||
|
Two option keywords are currently supported:
|
||||||
|
.Cm none (the default; indicating no additional options are enabled)
|
||||||
|
and
|
||||||
|
.Cm touch-required .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Cm touch-required
|
||||||
|
option causes public key authentication using a security key algorithm
|
||||||
|
(i.e.
|
||||||
|
.Cm ecdsa-sk
|
||||||
|
or
|
||||||
|
.Cm ed25519-sk )
|
||||||
|
to always require the signature to attest that a physically present user
|
||||||
|
explicitly confirmed the authentication (usually by touching the security key).
|
||||||
|
By default,
|
||||||
|
.Xr sshd 8
|
||||||
|
requires key touch unless overridden with an authorized_keys option.
|
||||||
|
The
|
||||||
|
.Cm touch-required
|
||||||
|
flag disables this override.
|
||||||
|
This option has no effect for other, non-security key public key types.
|
||||||
.It Cm PubkeyAuthentication
|
.It Cm PubkeyAuthentication
|
||||||
Specifies whether public key authentication is allowed.
|
Specifies whether public key authentication is allowed.
|
||||||
The default is
|
The default is
|
||||||
|
|
Loading…
Reference in New Issue