upstream: PubkeyAuthentication=yes|no|unbound|host-bound

Allow control over which pubkey methods are used. Added out of
concern that some hardware devices may have difficulty signing
the longer pubkey authentication challenges. This provides a
way for them to disable the extension. It's also handy for
testing.

feedback / ok markus@

OpenBSD-Commit-ID: ee52580db95c355cf6d563ba89974c210e603b1a
This commit is contained in:
djm@openbsd.org 2021-12-19 22:14:47 +00:00 committed by Damien Miller
parent 34b1e9cc76
commit c385abf765
3 changed files with 29 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.363 2021/09/16 05:36:03 djm Exp $ */
/* $OpenBSD: readconf.c,v 1.364 2021/12/19 22:14:47 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -890,6 +890,15 @@ static const struct multistate multistate_canonicalizehostname[] = {
{ "always", SSH_CANONICALISE_ALWAYS },
{ NULL, -1 }
};
static const struct multistate multistate_pubkey_auth[] = {
{ "true", SSH_PUBKEY_AUTH_ALL },
{ "false", SSH_PUBKEY_AUTH_NO },
{ "yes", SSH_PUBKEY_AUTH_ALL },
{ "no", SSH_PUBKEY_AUTH_NO },
{ "unbound", SSH_PUBKEY_AUTH_UNBOUND },
{ "host-bound", SSH_PUBKEY_AUTH_HBOUND },
{ NULL, -1 }
};
static const struct multistate multistate_compression[] = {
#ifdef WITH_ZLIB
{ "yes", COMP_ZLIB },
@ -1102,8 +1111,9 @@ parse_time:
goto parse_string;
case oPubkeyAuthentication:
multistate_ptr = multistate_pubkey_auth;
intptr = &options->pubkey_authentication;
goto parse_flag;
goto parse_multistate;
case oHostbasedAuthentication:
intptr = &options->hostbased_authentication;
@ -2487,7 +2497,7 @@ fill_default_options(Options * options)
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_deleg_creds == -1)
@ -3137,6 +3147,8 @@ fmt_intarg(OpCodes code, int val)
return fmt_multistate_int(val, multistate_canonicalizehostname);
case oAddKeysToAgent:
return fmt_multistate_int(val, multistate_yesnoaskconfirm);
case oPubkeyAuthentication:
return fmt_multistate_int(val, multistate_pubkey_auth);
case oFingerprintHash:
return ssh_digest_alg_name(val);
default:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.145 2021/09/15 06:56:01 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.146 2021/12/19 22:14:47 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -179,6 +179,11 @@ typedef struct {
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
#define SSH_PUBKEY_AUTH_NO 0x00
#define SSH_PUBKEY_AUTH_UNBOUND 0x01
#define SSH_PUBKEY_AUTH_HBOUND 0x02
#define SSH_PUBKEY_AUTH_ALL 0x03
#define SSH_CANONICALISE_NO 0
#define SSH_CANONICALISE_YES 1
#define SSH_CANONICALISE_ALWAYS 2

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.353 2021/12/19 22:12:54 djm Exp $ */
/* $OpenBSD: sshconnect2.c,v 1.354 2021/12/19 22:14:47 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -1345,16 +1345,20 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
int r, fallback_sigtype, sent = 0;
char *alg = NULL, *fp = NULL;
const char *loc = "", *method = "publickey";
int hostbound = 0;
/* prefer host-bound pubkey signatures if supported by server */
if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0)
if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0 &&
(options.pubkey_authentication & SSH_PUBKEY_AUTH_HBOUND) != 0) {
hostbound = 1;
method = "publickey-hostbound-v00@openssh.com";
}
if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
return 0;
debug3_f("%s %s", sshkey_type(id->key), fp);
debug3_f("using %s with %s %s", method, sshkey_type(id->key), fp);
/*
* If the key is an certificate, try to find a matching private key
@ -1440,7 +1444,7 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
(r = sshkey_puts(id->key, b)) != 0) {
fatal_fr(r, "assemble signed data");
}
if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0) {
if (hostbound) {
if (ssh->kex->initial_hostkey == NULL) {
fatal_f("internal error: initial hostkey "
"not recorded");