upstream: add a "no-touch-required" option for authorized_keys and

a similar extension for certificates. This option disables the default
requirement that security key signatures attest that the user touched their
key to authorize them.

feedback deraadt, ok markus

OpenBSD-Commit-ID: f1fb56151ba68d55d554d0f6d3d4dba0cf1a452e
This commit is contained in:
djm@openbsd.org 2019-11-25 00:54:23 +00:00 committed by Damien Miller
parent 0fddf2967a
commit 2e71263b80
8 changed files with 78 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.89 2019/09/13 04:36:43 dtucker Exp $ */
/* $OpenBSD: auth-options.c,v 1.90 2019/11/25 00:54:23 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
@ -96,7 +96,10 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
name, sshbuf_len(data));
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
if (strcmp(name, "permit-X11-forwarding") == 0) {
if (strcmp(name, "no-touch-required") == 0) {
opts->no_require_user_presence = 1;
found = 1;
} else if (strcmp(name, "permit-X11-forwarding") == 0) {
opts->permit_x11_forwarding_flag = 1;
found = 1;
} else if (strcmp(name,
@ -347,6 +350,8 @@ sshauthopt_parse(const char *opts, const char **errstrp)
ret->permit_agent_forwarding_flag = r == 1;
} else if ((r = opt_flag("x11-forwarding", 1, &opts)) != -1) {
ret->permit_x11_forwarding_flag = r == 1;
} else if ((r = opt_flag("touch-required", 1, &opts)) != -1) {
ret->no_require_user_presence = r != 1; /* NB. flip */
} else if ((r = opt_flag("pty", 1, &opts)) != -1) {
ret->permit_pty_flag = r == 1;
} else if ((r = opt_flag("user-rc", 1, &opts)) != -1) {
@ -567,14 +572,15 @@ sshauthopt_merge(const struct sshauthopt *primary,
goto alloc_fail;
}
/* Flags are logical-AND (i.e. must be set in both for permission) */
#define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1)
OPTFLAG(permit_port_forwarding_flag);
OPTFLAG(permit_agent_forwarding_flag);
OPTFLAG(permit_x11_forwarding_flag);
OPTFLAG(permit_pty_flag);
OPTFLAG(permit_user_rc);
#undef OPTFLAG
#define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1)
/* Permissive flags are logical-AND (i.e. must be set in both) */
OPTFLAG_AND(permit_port_forwarding_flag);
OPTFLAG_AND(permit_agent_forwarding_flag);
OPTFLAG_AND(permit_x11_forwarding_flag);
OPTFLAG_AND(permit_pty_flag);
OPTFLAG_AND(permit_user_rc);
OPTFLAG_AND(no_require_user_presence);
#undef OPTFLAG_AND
/* Earliest expiry time should win */
if (primary->valid_before != 0)
@ -643,6 +649,7 @@ sshauthopt_copy(const struct sshauthopt *orig)
OPTSCALAR(cert_authority);
OPTSCALAR(force_tun_device);
OPTSCALAR(valid_before);
OPTSCALAR(no_require_user_presence);
#undef OPTSCALAR
#define OPTSTRING(x) \
do { \
@ -765,7 +772,7 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
{
int r = SSH_ERR_INTERNAL_ERROR;
/* Flag and simple integer options */
/* Flag options */
if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 ||
(r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 ||
(r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 ||
@ -773,7 +780,11 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
(r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 ||
(r = sshbuf_put_u8(m, opts->restricted)) != 0 ||
(r = sshbuf_put_u8(m, opts->cert_authority)) != 0 ||
(r = sshbuf_put_u64(m, opts->valid_before)) != 0)
(r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0)
return r;
/* Simple integer options */
if ((r = sshbuf_put_u64(m, opts->valid_before)) != 0)
return r;
/* tunnel number can be negative to indicate "unset" */
@ -817,6 +828,7 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
if ((opts = calloc(1, sizeof(*opts))) == NULL)
return SSH_ERR_ALLOC_FAIL;
/* Flag options */
#define OPT_FLAG(x) \
do { \
if ((r = sshbuf_get_u8(m, &f)) != 0) \
@ -830,8 +842,10 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
OPT_FLAG(permit_user_rc);
OPT_FLAG(restricted);
OPT_FLAG(cert_authority);
OPT_FLAG(no_require_user_presence);
#undef OPT_FLAG
/* Simple integer options */
if ((r = sshbuf_get_u64(m, &opts->valid_before)) != 0)
goto out;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.h,v 1.28 2019/07/09 04:15:00 djm Exp $ */
/* $OpenBSD: auth-options.h,v 1.29 2019/11/25 00:54:23 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
@ -68,6 +68,9 @@ struct sshauthopt {
*/
char *required_from_host_cert;
char *required_from_host_keys;
/* Key requires user presence asserted */
int no_require_user_presence;
};
struct sshauthopt *sshauthopt_new(void);

7
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.142 2019/10/16 06:05:39 djm Exp $ */
/* $OpenBSD: auth.c,v 1.143 2019/11/25 00:54:23 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -1005,7 +1005,7 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
snprintf(buf, sizeof(buf), "%d", opts->force_tun_device);
/* Try to keep this alphabetically sorted */
snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s",
snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
opts->force_command == NULL ? "" : " command",
do_env ? " environment" : "",
@ -1018,7 +1018,8 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
opts->force_tun_device == -1 ? "" : " tun=",
opts->force_tun_device == -1 ? "" : buf,
opts->permit_user_rc ? " user-rc" : "",
opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");
opts->permit_x11_forwarding_flag ? " x11-forwarding" : "",
opts->no_require_user_presence ? " no-touch-required" : "");
debug("%s: %s", loc, msg);
if (do_remote)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.96 2019/11/25 00:52:46 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.97 2019/11/25 00:54:23 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -225,7 +225,8 @@ userauth_pubkey(struct ssh *ssh)
__func__, sig_details->sk_counter,
sig_details->sk_flags);
req_presence = (options.pubkey_auth_options &
PUBKEYAUTH_TOUCH_REQUIRED);
PUBKEYAUTH_TOUCH_REQUIRED) ||
!authopts->no_require_user_presence;
if (req_presence && (sig_details->sk_flags &
SSH_SK_USER_PRESENCE_REQD) == 0) {
error("public key %s signature for %s%s from "

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.203 2019/11/25 00:52:46 djm Exp $ */
/* $OpenBSD: monitor.c,v 1.204 2019/11/25 00:54:23 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -1440,7 +1440,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) {
req_presence = (options.pubkey_auth_options &
PUBKEYAUTH_TOUCH_REQUIRED);
PUBKEYAUTH_TOUCH_REQUIRED) ||
!key_opts->no_require_user_presence;
if (req_presence &&
(sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) {
error("public key %s %s signature for %s%s from %.128s "

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.176 2019/11/18 23:16:49 naddy Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.177 2019/11/25 00:54:23 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: November 18 2019 $
.Dd $Mdocdate: November 25 2019 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@ -534,6 +534,14 @@ by
.It Ic permit-X11-forwarding
Allows X11 forwarding.
.Pp
.It Ic no-touch-required
Do not require signatures made using this key require demonstration
of user presence (e.g. by having the user touch the key).
This option only makes sense for the Security Key algorithms
.Cm ecdsa-sk
and
.Cm ed25519-sk .
.Pp
.It Ic source-address Ns = Ns Ar address_list
Restrict the source addresses from which the certificate is considered valid.
The

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keygen.c,v 1.370 2019/11/25 00:51:37 djm Exp $ */
/* $OpenBSD: ssh-keygen.c,v 1.371 2019/11/25 00:54:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -120,11 +120,12 @@ static u_int64_t cert_valid_from = 0;
static u_int64_t cert_valid_to = ~0ULL;
/* Certificate options */
#define CERTOPT_X_FWD (1)
#define CERTOPT_AGENT_FWD (1<<1)
#define CERTOPT_PORT_FWD (1<<2)
#define CERTOPT_PTY (1<<3)
#define CERTOPT_USER_RC (1<<4)
#define CERTOPT_X_FWD (1)
#define CERTOPT_AGENT_FWD (1<<1)
#define CERTOPT_PORT_FWD (1<<2)
#define CERTOPT_PTY (1<<3)
#define CERTOPT_USER_RC (1<<4)
#define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5)
#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
static u_int32_t certflags_flags = CERTOPT_DEFAULT;
@ -1665,6 +1666,9 @@ prepare_options_buf(struct sshbuf *c, int which)
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_USER_RC) != 0)
add_flag_option(c, "permit-user-rc");
if ((which & OPTIONS_CRITICAL) != 0 &&
(certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
add_flag_option(c, "no-touch-required");
if ((which & OPTIONS_CRITICAL) != 0 &&
certflags_src_addr != NULL)
add_string_option(c, "source-address", certflags_src_addr);
@ -1967,6 +1971,10 @@ add_cert_option(char *opt)
certflags_flags &= ~CERTOPT_USER_RC;
else if (strcasecmp(opt, "permit-user-rc") == 0)
certflags_flags |= CERTOPT_USER_RC;
else if (strcasecmp(opt, "touch-required") == 0)
certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE;
else if (strcasecmp(opt, "no-touch-required") == 0)
certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE;
else if (strncasecmp(opt, "force-command=", 14) == 0) {
val = opt + 14;
if (*val == '\0')
@ -2020,9 +2028,10 @@ show_options(struct sshbuf *optbuf, int in_critical)
strcmp(name, "permit-agent-forwarding") == 0 ||
strcmp(name, "permit-port-forwarding") == 0 ||
strcmp(name, "permit-pty") == 0 ||
strcmp(name, "permit-user-rc") == 0))
strcmp(name, "permit-user-rc") == 0 ||
strcmp(name, "no-touch-required") == 0)) {
printf("\n");
else if (in_critical &&
} else if (in_critical &&
(strcmp(name, "force-command") == 0 ||
strcmp(name, "source-address") == 0)) {
if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)

13
sshd.8
View File

@ -33,8 +33,8 @@
.\" (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.8,v 1.306 2019/11/18 04:55:02 djm Exp $
.Dd $Mdocdate: November 18 2019 $
.\" $OpenBSD: sshd.8,v 1.307 2019/11/25 00:54:23 djm Exp $
.Dd $Mdocdate: November 25 2019 $
.Dt SSHD 8
.Os
.Sh NAME
@ -627,6 +627,13 @@ option.
Permits tty allocation previously disabled by the
.Cm restrict
option.
.It Cm no-touch-required
Do not require demonstration of user presence
for signatures made using this key.
This option only makes sense for the Security Key algorithms
.Cm ecdsa-sk
and
.Cm ed25519-sk .
.It Cm restrict
Enable all restrictions, i.e. disable port, agent and X11 forwarding,
as well as disabling PTY allocation
@ -670,6 +677,8 @@ restrict,command="uptime" ssh-rsa AAAA1C8...32Tv==
user@example.net
restrict,pty,command="nethack" ssh-rsa AAAA1f8...IrrC5==
user@example.net
no-touch-required sk-ecdsa-sha2-nistp256@openssh.com AAAAInN...Ko==
user@example.net
.Ed
.Sh SSH_KNOWN_HOSTS FILE FORMAT
The