summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-11-25 00:52:46 +0000
committerDamien Miller <djm@mindrot.org>2019-11-25 12:23:40 +1100
commit0fddf2967ac51d518e300408a0d7e6adf4cd2634 (patch)
treed7fe4a4f7cd92c565a765e21b7cb19b9c7544d29
parentb7e74ea072919b31391bc0f5ff653f80b9f5e84f (diff)
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
-rw-r--r--auth2-pubkey.c22
-rw-r--r--monitor.c63
-rw-r--r--servconf.c33
-rw-r--r--servconf.h6
-rw-r--r--sshd_config.527
5 files changed, 119 insertions, 32 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 2b6986709..0ef982a48 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.95 2019/11/25 00:51:37 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.96 2019/11/25 00:52:46 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -68,6 +68,7 @@
68#include "ssherr.h" 68#include "ssherr.h"
69#include "channels.h" /* XXX for session.h */ 69#include "channels.h" /* XXX for session.h */
70#include "session.h" /* XXX for child_set_env(); refactor? */ 70#include "session.h" /* XXX for child_set_env(); refactor? */
71#include "sk-api.h"
71 72
72/* import */ 73/* import */
73extern ServerOptions options; 74extern ServerOptions options;
@@ -96,7 +97,7 @@ userauth_pubkey(struct ssh *ssh)
96 u_char *pkblob = NULL, *sig = NULL, have_sig; 97 u_char *pkblob = NULL, *sig = NULL, have_sig;
97 size_t blen, slen; 98 size_t blen, slen;
98 int r, pktype; 99 int r, pktype;
99 int authenticated = 0; 100 int req_presence = 0, authenticated = 0;
100 struct sshauthopt *authopts = NULL; 101 struct sshauthopt *authopts = NULL;
101 struct sshkey_sig_details *sig_details = NULL; 102 struct sshkey_sig_details *sig_details = NULL;
102 103
@@ -217,10 +218,25 @@ userauth_pubkey(struct ssh *ssh)
217 ssh->compat, &sig_details)) == 0) { 218 ssh->compat, &sig_details)) == 0) {
218 authenticated = 1; 219 authenticated = 1;
219 } 220 }
220 if (sig_details != NULL) { 221 if (authenticated == 1 && sig_details != NULL) {
222 auth2_record_info(authctxt, "signature count = %u",
223 sig_details->sk_counter);
221 debug("%s: sk_counter = %u, sk_flags = 0x%02x", 224 debug("%s: sk_counter = %u, sk_flags = 0x%02x",
222 __func__, sig_details->sk_counter, 225 __func__, sig_details->sk_counter,
223 sig_details->sk_flags); 226 sig_details->sk_flags);
227 req_presence = (options.pubkey_auth_options &
228 PUBKEYAUTH_TOUCH_REQUIRED);
229 if (req_presence && (sig_details->sk_flags &
230 SSH_SK_USER_PRESENCE_REQD) == 0) {
231 error("public key %s signature for %s%s from "
232 "%.128s port %d rejected: user presence "
233 "(key touch) requirement not met ", key_s,
234 authctxt->valid ? "" : "invalid user ",
235 authctxt->user, ssh_remote_ipaddr(ssh),
236 ssh_remote_port(ssh));
237 authenticated = 0;
238 goto done;
239 }
224 } 240 }
225 auth2_record_key(authctxt, authenticated, key); 241 auth2_record_key(authctxt, authenticated, key);
226 } else { 242 } else {
diff --git a/monitor.c b/monitor.c
index 40ff43ee2..9b171c447 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.202 2019/11/25 00:51:37 djm Exp $ */ 1/* $OpenBSD: monitor.c,v 1.203 2019/11/25 00:52:46 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>
@@ -95,6 +95,7 @@
95#include "authfd.h" 95#include "authfd.h"
96#include "match.h" 96#include "match.h"
97#include "ssherr.h" 97#include "ssherr.h"
98#include "sk-api.h"
98 99
99#ifdef GSSAPI 100#ifdef GSSAPI
100static Gssctxt *gsscontext = NULL; 101static Gssctxt *gsscontext = NULL;
@@ -542,7 +543,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
542 543
543/* allowed key state */ 544/* allowed key state */
544static int 545static int
545monitor_allowed_key(u_char *blob, u_int bloblen) 546monitor_allowed_key(const u_char *blob, u_int bloblen)
546{ 547{
547 /* make sure key is allowed */ 548 /* make sure key is allowed */
548 if (key_blob == NULL || key_bloblen != bloblen || 549 if (key_blob == NULL || key_bloblen != bloblen ||
@@ -1247,7 +1248,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
1247} 1248}
1248 1249
1249static int 1250static int
1250monitor_valid_userblob(u_char *data, u_int datalen) 1251monitor_valid_userblob(const u_char *data, u_int datalen)
1251{ 1252{
1252 struct sshbuf *b; 1253 struct sshbuf *b;
1253 const u_char *p; 1254 const u_char *p;
@@ -1256,10 +1257,8 @@ monitor_valid_userblob(u_char *data, u_int datalen)
1256 u_char type; 1257 u_char type;
1257 int r, fail = 0; 1258 int r, fail = 0;
1258 1259
1259 if ((b = sshbuf_new()) == NULL) 1260 if ((b = sshbuf_from(data, datalen)) == NULL)
1260 fatal("%s: sshbuf_new", __func__); 1261 fatal("%s: sshbuf_from", __func__);
1261 if ((r = sshbuf_put(b, data, datalen)) != 0)
1262 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1263 1262
1264 if (datafellows & SSH_OLD_SESSIONID) { 1263 if (datafellows & SSH_OLD_SESSIONID) {
1265 p = sshbuf_ptr(b); 1264 p = sshbuf_ptr(b);
@@ -1314,8 +1313,8 @@ monitor_valid_userblob(u_char *data, u_int datalen)
1314} 1313}
1315 1314
1316static int 1315static int
1317monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 1316monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
1318 char *chost) 1317 const char *cuser, const char *chost)
1319{ 1318{
1320 struct sshbuf *b; 1319 struct sshbuf *b;
1321 const u_char *p; 1320 const u_char *p;
@@ -1324,10 +1323,9 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
1324 int r, fail = 0; 1323 int r, fail = 0;
1325 u_char type; 1324 u_char type;
1326 1325
1327 if ((b = sshbuf_new()) == NULL) 1326 if ((b = sshbuf_from(data, datalen)) == NULL)
1328 fatal("%s: sshbuf_new", __func__); 1327 fatal("%s: sshbuf_new", __func__);
1329 if ((r = sshbuf_put(b, data, datalen)) != 0 || 1328 if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
1330 (r = sshbuf_get_string_direct(b, &p, &len)) != 0)
1331 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1329 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1332 1330
1333 if ((session_id2 == NULL) || 1331 if ((session_id2 == NULL) ||
@@ -1387,15 +1385,15 @@ int
1387mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) 1385mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
1388{ 1386{
1389 struct sshkey *key; 1387 struct sshkey *key;
1390 u_char *signature, *data, *blob; 1388 const u_char *signature, *data, *blob;
1391 char *sigalg; 1389 char *sigalg = NULL, *fp = NULL;
1392 size_t signaturelen, datalen, bloblen; 1390 size_t signaturelen, datalen, bloblen;
1393 int r, ret, valid_data = 0, encoded_ret; 1391 int r, ret, req_presence = 0, valid_data = 0, encoded_ret;
1394 struct sshkey_sig_details *sig_details = NULL; 1392 struct sshkey_sig_details *sig_details = NULL;
1395 1393
1396 if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || 1394 if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 ||
1397 (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || 1395 (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 ||
1398 (r = sshbuf_get_string(m, &data, &datalen)) != 0 || 1396 (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 ||
1399 (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) 1397 (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
1400 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1398 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1401 1399
@@ -1430,23 +1428,36 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
1430 if (!valid_data) 1428 if (!valid_data)
1431 fatal("%s: bad signature data blob", __func__); 1429 fatal("%s: bad signature data blob", __func__);
1432 1430
1431 if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
1432 SSH_FP_DEFAULT)) == NULL)
1433 fatal("%s: sshkey_fingerprint failed", __func__);
1434
1433 ret = sshkey_verify(key, signature, signaturelen, data, datalen, 1435 ret = sshkey_verify(key, signature, signaturelen, data, datalen,
1434 sigalg, ssh->compat, &sig_details); 1436 sigalg, ssh->compat, &sig_details);
1435 debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key, 1437 debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key,
1436 (ret == 0) ? "verified" : "unverified", 1438 (ret == 0) ? "verified" : "unverified",
1437 (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); 1439 (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
1438 auth2_record_key(authctxt, ret == 0, key);
1439 1440
1440 free(blob); 1441 if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) {
1441 free(signature); 1442 req_presence = (options.pubkey_auth_options &
1442 free(data); 1443 PUBKEYAUTH_TOUCH_REQUIRED);
1443 free(sigalg); 1444 if (req_presence &&
1445 (sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) {
1446 error("public key %s %s signature for %s%s from %.128s "
1447 "port %d rejected: user presence (key touch) "
1448 "requirement not met ", sshkey_type(key), fp,
1449 authctxt->valid ? "" : "invalid user ",
1450 authctxt->user, ssh_remote_ipaddr(ssh),
1451 ssh_remote_port(ssh));
1452 ret = SSH_ERR_SIGNATURE_INVALID;
1453 }
1454 }
1455 auth2_record_key(authctxt, ret == 0, key);
1444 1456
1445 if (key_blobtype == MM_USERKEY) 1457 if (key_blobtype == MM_USERKEY)
1446 auth_activate_options(ssh, key_opts); 1458 auth_activate_options(ssh, key_opts);
1447 monitor_reset_key_state(); 1459 monitor_reset_key_state();
1448 1460
1449 sshkey_free(key);
1450 sshbuf_reset(m); 1461 sshbuf_reset(m);
1451 1462
1452 /* encode ret != 0 as positive integer, since we're sending u32 */ 1463 /* 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)
1462 sshkey_sig_details_free(sig_details); 1473 sshkey_sig_details_free(sig_details);
1463 mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); 1474 mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
1464 1475
1476 free(sigalg);
1477 free(fp);
1478 sshkey_free(key);
1479
1465 return ret == 0; 1480 return ret == 0;
1466} 1481}
1467 1482
diff --git a/servconf.c b/servconf.c
index e2f44d38d..1f3beab4a 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.353 2019/10/31 21:17:49 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.354 2019/11/25 00:52:46 djm Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -118,6 +118,7 @@ initialize_server_options(ServerOptions *options)
118 options->hostbased_key_types = NULL; 118 options->hostbased_key_types = NULL;
119 options->hostkeyalgorithms = NULL; 119 options->hostkeyalgorithms = NULL;
120 options->pubkey_authentication = -1; 120 options->pubkey_authentication = -1;
121 options->pubkey_auth_options = -1;
121 options->pubkey_key_types = NULL; 122 options->pubkey_key_types = NULL;
122 options->kerberos_authentication = -1; 123 options->kerberos_authentication = -1;
123 options->kerberos_or_local_passwd = -1; 124 options->kerberos_or_local_passwd = -1;
@@ -341,6 +342,8 @@ fill_default_server_options(ServerOptions *options)
341 options->hostbased_uses_name_from_packet_only = 0; 342 options->hostbased_uses_name_from_packet_only = 0;
342 if (options->pubkey_authentication == -1) 343 if (options->pubkey_authentication == -1)
343 options->pubkey_authentication = 1; 344 options->pubkey_authentication = 1;
345 if (options->pubkey_auth_options == -1)
346 options->pubkey_auth_options = 0;
344 if (options->kerberos_authentication == -1) 347 if (options->kerberos_authentication == -1)
345 options->kerberos_authentication = 0; 348 options->kerberos_authentication = 0;
346 if (options->kerberos_or_local_passwd == -1) 349 if (options->kerberos_or_local_passwd == -1)
@@ -509,7 +512,7 @@ typedef enum {
509 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 512 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
510 sStreamLocalBindMask, sStreamLocalBindUnlink, 513 sStreamLocalBindMask, sStreamLocalBindUnlink,
511 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, 514 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
512 sExposeAuthInfo, sRDomain, 515 sExposeAuthInfo, sRDomain, sPubkeyAuthOptions,
513 sDeprecated, sIgnore, sUnsupported 516 sDeprecated, sIgnore, sUnsupported
514} ServerOpCodes; 517} ServerOpCodes;
515 518
@@ -551,6 +554,7 @@ static struct {
551 { "rsaauthentication", sDeprecated, SSHCFG_ALL }, 554 { "rsaauthentication", sDeprecated, SSHCFG_ALL },
552 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, 555 { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
553 { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, 556 { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
557 { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
554 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ 558 { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
555#ifdef KRB5 559#ifdef KRB5
556 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, 560 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
@@ -1468,6 +1472,24 @@ process_server_config_line(ServerOptions *options, char *line,
1468 charptr = &options->pubkey_key_types; 1472 charptr = &options->pubkey_key_types;
1469 goto parse_keytypes; 1473 goto parse_keytypes;
1470 1474
1475 case sPubkeyAuthOptions:
1476 intptr = &options->pubkey_auth_options;
1477 value = 0;
1478 while ((arg = strdelim(&cp)) && *arg != '\0') {
1479 if (strcasecmp(arg, "none") == 0)
1480 continue;
1481 if (strcasecmp(arg, "touch-required") == 0)
1482 value |= PUBKEYAUTH_TOUCH_REQUIRED;
1483 else {
1484 fatal("%s line %d: unsupported "
1485 "PubkeyAuthOptions option %s",
1486 filename, linenum, arg);
1487 }
1488 }
1489 if (*activep && *intptr == -1)
1490 *intptr = value;
1491 break;
1492
1471 case sKerberosAuthentication: 1493 case sKerberosAuthentication:
1472 intptr = &options->kerberos_authentication; 1494 intptr = &options->kerberos_authentication;
1473 goto parse_flag; 1495 goto parse_flag;
@@ -2290,6 +2312,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2290 M_CP_INTOPT(password_authentication); 2312 M_CP_INTOPT(password_authentication);
2291 M_CP_INTOPT(gss_authentication); 2313 M_CP_INTOPT(gss_authentication);
2292 M_CP_INTOPT(pubkey_authentication); 2314 M_CP_INTOPT(pubkey_authentication);
2315 M_CP_INTOPT(pubkey_auth_options);
2293 M_CP_INTOPT(kerberos_authentication); 2316 M_CP_INTOPT(kerberos_authentication);
2294 M_CP_INTOPT(hostbased_authentication); 2317 M_CP_INTOPT(hostbased_authentication);
2295 M_CP_INTOPT(hostbased_uses_name_from_packet_only); 2318 M_CP_INTOPT(hostbased_uses_name_from_packet_only);
@@ -2711,4 +2734,10 @@ dump_config(ServerOptions *o)
2711 o->permit_user_env_whitelist); 2734 o->permit_user_env_whitelist);
2712 } 2735 }
2713 2736
2737 printf("pubkeyauthoptions");
2738 if (o->pubkey_auth_options == 0)
2739 printf(" none");
2740 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
2741 printf(" touch-required");
2742 printf("\n");
2714} 2743}
diff --git a/servconf.h b/servconf.h
index 5483da051..9f202260a 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.140 2019/04/18 18:56:16 dtucker Exp $ */ 1/* $OpenBSD: servconf.h,v 1.141 2019/11/25 00:52:46 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -42,6 +42,9 @@
42/* Magic name for internal sftp-server */ 42/* Magic name for internal sftp-server */
43#define INTERNAL_SFTP_NAME "internal-sftp" 43#define INTERNAL_SFTP_NAME "internal-sftp"
44 44
45/* PubkeyAuthOptions flags */
46#define PUBKEYAUTH_TOUCH_REQUIRED 1
47
45struct ssh; 48struct ssh;
46struct fwd_perm_list; 49struct fwd_perm_list;
47 50
@@ -114,6 +117,7 @@ typedef struct {
114 char *ca_sign_algorithms; /* Allowed CA signature algorithms */ 117 char *ca_sign_algorithms; /* Allowed CA signature algorithms */
115 int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ 118 int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
116 char *pubkey_key_types; /* Key types allowed for public key */ 119 char *pubkey_key_types; /* Key types allowed for public key */
120 int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */
117 int kerberos_authentication; /* If true, permit Kerberos 121 int kerberos_authentication; /* If true, permit Kerberos
118 * authentication. */ 122 * authentication. */
119 int kerberos_or_local_passwd; /* If true, permit kerberos 123 int kerberos_or_local_passwd; /* If true, permit kerberos
diff --git a/sshd_config.5 b/sshd_config.5
index 5052ca200..60077e394 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.292 2019/11/18 04:55:02 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.293 2019/11/25 00:52:46 djm Exp $
37.Dd $Mdocdate: November 18 2019 $ 37.Dd $Mdocdate: November 25 2019 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -1444,6 +1444,29 @@ ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
1444.Pp 1444.Pp
1445The list of available key types may also be obtained using 1445The list of available key types may also be obtained using
1446.Qq ssh -Q key . 1446.Qq ssh -Q key .
1447.It Cm PubkeyAuthOptions
1448Sets one or more public key authentication options.
1449Two option keywords are currently supported:
1450.Cm none (the default; indicating no additional options are enabled)
1451and
1452.Cm touch-required .
1453.Pp
1454The
1455.Cm touch-required
1456option causes public key authentication using a security key algorithm
1457(i.e.
1458.Cm ecdsa-sk
1459or
1460.Cm ed25519-sk )
1461to always require the signature to attest that a physically present user
1462explicitly confirmed the authentication (usually by touching the security key).
1463By default,
1464.Xr sshd 8
1465requires key touch unless overridden with an authorized_keys option.
1466The
1467.Cm touch-required
1468flag disables this override.
1469This option has no effect for other, non-security key public key types.
1447.It Cm PubkeyAuthentication 1470.It Cm PubkeyAuthentication
1448Specifies whether public key authentication is allowed. 1471Specifies whether public key authentication is allowed.
1449The default is 1472The default is