summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth-options.c20
-rw-r--r--auth-options.h4
-rw-r--r--auth.c9
-rw-r--r--auth2-pubkey.c18
-rw-r--r--monitor.c17
-rw-r--r--servconf.c6
-rw-r--r--servconf.h5
-rw-r--r--sshd.811
-rw-r--r--sshd_config.523
9 files changed, 88 insertions, 25 deletions
diff --git a/auth-options.c b/auth-options.c
index 696ba6ac..98afdf5f 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.92 2020/03/06 18:15:38 markus Exp $ */
+/* $OpenBSD: auth-options.c,v 1.93 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
@@ -119,7 +119,10 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
}
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
- if (strcmp(name, "force-command") == 0) {
+ if (strcmp(name, "verify-required") == 0) {
+ opts->require_verify = 1;
+ found = 1;
+ } else if (strcmp(name, "force-command") == 0) {
if ((r = sshbuf_get_cstring(data, &command,
NULL)) != 0) {
error("Unable to parse \"%s\" "
@@ -134,8 +137,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
}
opts->force_command = command;
found = 1;
- }
- if (strcmp(name, "source-address") == 0) {
+ } else if (strcmp(name, "source-address") == 0) {
if ((r = sshbuf_get_cstring(data, &allowed,
NULL)) != 0) {
error("Unable to parse \"%s\" "
@@ -351,6 +353,8 @@ sshauthopt_parse(const char *opts, const char **errstrp)
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("verify-required", 1, &opts)) != -1) {
+ ret->require_verify = r == 1;
} 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) {
@@ -572,6 +576,7 @@ sshauthopt_merge(const struct sshauthopt *primary,
}
#define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1)
+#define OPTFLAG_OR(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);
@@ -579,6 +584,8 @@ sshauthopt_merge(const struct sshauthopt *primary,
OPTFLAG_AND(permit_pty_flag);
OPTFLAG_AND(permit_user_rc);
OPTFLAG_AND(no_require_user_presence);
+ /* Restrictive flags are logical-OR (i.e. must be set in either) */
+ OPTFLAG_OR(require_verify);
#undef OPTFLAG_AND
/* Earliest expiry time should win */
@@ -649,6 +656,7 @@ sshauthopt_copy(const struct sshauthopt *orig)
OPTSCALAR(force_tun_device);
OPTSCALAR(valid_before);
OPTSCALAR(no_require_user_presence);
+ OPTSCALAR(require_verify);
#undef OPTSCALAR
#define OPTSTRING(x) \
do { \
@@ -781,7 +789,8 @@ 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_u8(m, opts->no_require_user_presence)) != 0)
+ (r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0 ||
+ (r = sshbuf_put_u8(m, opts->require_verify)) != 0)
return r;
/* Simple integer options */
@@ -844,6 +853,7 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
OPT_FLAG(restricted);
OPT_FLAG(cert_authority);
OPT_FLAG(no_require_user_presence);
+ OPT_FLAG(require_verify);
#undef OPT_FLAG
/* Simple integer options */
diff --git a/auth-options.h b/auth-options.h
index d96ffede..118a3208 100644
--- a/auth-options.h
+++ b/auth-options.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.h,v 1.29 2019/11/25 00:54:23 djm Exp $ */
+/* $OpenBSD: auth-options.h,v 1.30 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
@@ -71,6 +71,8 @@ struct sshauthopt {
/* Key requires user presence asserted */
int no_require_user_presence;
+ /* Key requires user verification (e.g. PIN) */
+ int require_verify;
};
struct sshauthopt *sshauthopt_new(void);
diff --git a/auth.c b/auth.c
index 086b8ebb..9a5498b6 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.146 2020/01/31 22:42:45 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.147 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -1006,21 +1006,22 @@ 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%s",
+ snprintf(msg, sizeof(msg), "key options:%s%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" : "",
opts->valid_before == 0 ? "" : "expires",
+ opts->no_require_user_presence ? " no-touch-required" : "",
do_permitopen ? " permitopen" : "",
do_permitlisten ? " permitlisten" : "",
opts->permit_port_forwarding_flag ? " port-forwarding" : "",
opts->cert_principals == NULL ? "" : " principals",
opts->permit_pty_flag ? " pty" : "",
+ opts->require_verify ? " uv" : "",
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->no_require_user_presence ? " no-touch-required" : "");
+ opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");
debug("%s: %s", loc, msg);
if (do_remote)
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 815ea0f2..c3ecd9af 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.99 2020/02/06 22:30:54 naddy Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.100 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -97,7 +97,7 @@ userauth_pubkey(struct ssh *ssh)
u_char *pkblob = NULL, *sig = NULL, have_sig;
size_t blen, slen;
int r, pktype;
- int req_presence = 0, authenticated = 0;
+ int req_presence = 0, req_verify = 0, authenticated = 0;
struct sshauthopt *authopts = NULL;
struct sshkey_sig_details *sig_details = NULL;
@@ -239,6 +239,20 @@ userauth_pubkey(struct ssh *ssh)
authenticated = 0;
goto done;
}
+ req_verify = (options.pubkey_auth_options &
+ PUBKEYAUTH_VERIFY_REQUIRED) ||
+ authopts->require_verify;
+ if (req_verify && (sig_details->sk_flags &
+ SSH_SK_USER_VERIFICATION_REQD) == 0) {
+ error("public key %s signature for %s%s from "
+ "%.128s port %d rejected: user "
+ "verification 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);
} else {
diff --git a/monitor.c b/monitor.c
index 7c3e6aaf..4cf79dfc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.213 2020/08/27 01:06:18 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.214 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1387,7 +1387,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
const u_char *signature, *data, *blob;
char *sigalg = NULL, *fp = NULL;
size_t signaturelen, datalen, bloblen;
- int r, ret, req_presence = 0, valid_data = 0, encoded_ret;
+ int r, ret, req_presence = 0, req_verify = 0, valid_data = 0;
+ int encoded_ret;
struct sshkey_sig_details *sig_details = NULL;
if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 ||
@@ -1452,6 +1453,18 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
ssh_remote_port(ssh));
ret = SSH_ERR_SIGNATURE_INVALID;
}
+ req_verify = (options.pubkey_auth_options &
+ PUBKEYAUTH_VERIFY_REQUIRED) || key_opts->require_verify;
+ if (req_verify &&
+ (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) {
+ error("public key %s %s signature for %s%s from %.128s "
+ "port %d rejected: user verification 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);
diff --git a/servconf.c b/servconf.c
index 67581ccf..1bc7ee31 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: servconf.c,v 1.367 2020/07/05 23:59:45 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.368 2020/08/27 01:07:09 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -1527,6 +1527,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
continue;
if (strcasecmp(arg, "touch-required") == 0)
value |= PUBKEYAUTH_TOUCH_REQUIRED;
+ else if (strcasecmp(arg, "verify-required") == 0)
+ value |= PUBKEYAUTH_VERIFY_REQUIRED;
else {
fatal("%s line %d: unsupported "
"PubkeyAuthOptions option %s",
@@ -2937,5 +2939,7 @@ dump_config(ServerOptions *o)
printf(" none");
if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
printf(" touch-required");
+ if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
+ printf(" verify-required");
printf("\n");
}
diff --git a/servconf.h b/servconf.h
index 8422f3f5..1df8f3db 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.145 2020/07/05 23:59:45 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.146 2020/08/27 01:07:10 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -50,7 +50,8 @@
#define INTERNAL_SFTP_NAME "internal-sftp"
/* PubkeyAuthOptions flags */
-#define PUBKEYAUTH_TOUCH_REQUIRED 1
+#define PUBKEYAUTH_TOUCH_REQUIRED (1)
+#define PUBKEYAUTH_VERIFY_REQUIRED (1<<1)
struct ssh;
struct fwd_perm_list;
diff --git a/sshd.8 b/sshd.8
index c5f8987d..b2fad56d 100644
--- a/sshd.8
+++ b/sshd.8
@@ -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.312 2020/01/25 06:03:10 djm Exp $
-.Dd $Mdocdate: January 25 2020 $
+.\" $OpenBSD: sshd.8,v 1.313 2020/08/27 01:07:10 djm Exp $
+.Dd $Mdocdate: August 27 2020 $
.Dt SSHD 8
.Os
.Sh NAME
@@ -631,6 +631,13 @@ This option only makes sense for the FIDO authenticator algorithms
.Cm ecdsa-sk
and
.Cm ed25519-sk .
+.It Cm verify-required
+Require that signatures made using this key attest that they verified
+the user, e.g. via a PIN.
+This option only makes sense for the FIDO authenticator 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
diff --git a/sshd_config.5 b/sshd_config.5
index 17d8c130..a1898baa 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -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_config.5,v 1.312 2020/05/29 05:37:03 djm Exp $
-.Dd $Mdocdate: May 29 2020 $
+.\" $OpenBSD: sshd_config.5,v 1.313 2020/08/27 01:07:10 djm Exp $
+.Dd $Mdocdate: August 27 2020 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -1476,11 +1476,12 @@ The list of available key types may also be obtained using
.Qq ssh -Q PubkeyAcceptedKeyTypes .
.It Cm PubkeyAuthOptions
Sets one or more public key authentication options.
-Two option keywords are currently supported:
+The supported keywords are:
.Cm none
-(the default; indicating no additional options are enabled)
+(the default; indicating no additional options are enabled),
+.Cm touch-required
and
-.Cm touch-required .
+.Cm verify-required .
.Pp
The
.Cm touch-required
@@ -1497,7 +1498,17 @@ requires user presence unless overridden with an authorized_keys option.
The
.Cm touch-required
flag disables this override.
-This option has no effect for other, non-authenticator public key types.
+.Pp
+The
+.Cm verify-required
+option requires a FIDO key signature attest that verified the user, e.g.
+via a PIN.
+.Pp
+Neither the
+.Cm touch-required
+or
+.Cm verify-required
+options have any effect for other, non-FIDO public key types.
.It Cm PubkeyAuthentication
Specifies whether public key authentication is allowed.
The default is