diff options
-rw-r--r-- | auth-options.c | 20 | ||||
-rw-r--r-- | auth-options.h | 4 | ||||
-rw-r--r-- | auth.c | 9 | ||||
-rw-r--r-- | auth2-pubkey.c | 18 | ||||
-rw-r--r-- | monitor.c | 17 | ||||
-rw-r--r-- | servconf.c | 6 | ||||
-rw-r--r-- | servconf.h | 5 | ||||
-rw-r--r-- | sshd.8 | 11 | ||||
-rw-r--r-- | sshd_config.5 | 23 |
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); @@ -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 { @@ -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); @@ -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"); } @@ -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; @@ -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 |