diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2017-09-03 23:33:14 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2017-09-03 23:33:14 +0000 |
commit | 87d7dcbb5cbf8214c4117ef9c2f945ac72e5cf99 (patch) | |
tree | 18d14f2b616902cf3d8d486ec42a3ecb74e123ae /usr.bin/ssh | |
parent | 44c7d6b7077e333fc1222c7090566fa825d7b0b8 (diff) |
Expand ssh_config's StrictModes option with two new settings:
StrictModes=accept-new will automatically accept hitherto-unseen keys
but will refuse connections for changed or invalid hostkeys.
StrictModes=off is the same as StrictModes=no
Motivation:
StrictModes=no combines two behaviours for host key processing:
automatically learning new hostkeys and continuing to connect to hosts
with invalid/changed hostkeys. The latter behaviour is quite dangerous
since it removes most of the protections the SSH protocol is supposed to
provide.
Quite a few users want to automatically learn hostkeys however, so
this makes that feature available with less danger.
At some point in the future, StrictModes=no will change to be a synonym
for accept-new, with its current behaviour remaining available via
StrictModes=off.
bz#2400, suggested by Michael Samuel; ok markus
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r-- | usr.bin/ssh/readconf.c | 19 | ||||
-rw-r--r-- | usr.bin/ssh/readconf.h | 7 | ||||
-rw-r--r-- | usr.bin/ssh/ssh_config.5 | 18 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect.c | 30 |
4 files changed, 52 insertions, 22 deletions
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c index b9a7f7c30cb..51bd866638e 100644 --- a/usr.bin/ssh/readconf.c +++ b/usr.bin/ssh/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.277 2017/05/30 18:58:37 bluhm Exp $ */ +/* $OpenBSD: readconf.c,v 1.278 2017/09/03 23:33:13 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -736,6 +736,16 @@ static const struct multistate multistate_yesnoask[] = { { "ask", 2 }, { NULL, -1 } }; +static const struct multistate multistate_strict_hostkey[] = { + { "true", SSH_STRICT_HOSTKEY_YES }, + { "false", SSH_STRICT_HOSTKEY_OFF }, + { "yes", SSH_STRICT_HOSTKEY_YES }, + { "no", SSH_STRICT_HOSTKEY_OFF }, + { "ask", SSH_STRICT_HOSTKEY_ASK }, + { "off", SSH_STRICT_HOSTKEY_OFF }, + { "accept-new", SSH_STRICT_HOSTKEY_NEW }, + { NULL, -1 } +}; static const struct multistate multistate_yesnoaskconfirm[] = { { "true", 1 }, { "false", 0 }, @@ -969,7 +979,7 @@ parse_time: case oStrictHostKeyChecking: intptr = &options->strict_host_key_checking; - multistate_ptr = multistate_yesnoask; + multistate_ptr = multistate_strict_hostkey; goto parse_multistate; case oCompression: @@ -1912,7 +1922,7 @@ fill_default_options(Options * options) if (options->check_host_ip == -1) options->check_host_ip = 1; if (options->strict_host_key_checking == -1) - options->strict_host_key_checking = 2; /* 2 is default */ + options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; if (options->compression == -1) options->compression = 0; if (options->tcp_keep_alive == -1) @@ -2312,9 +2322,10 @@ fmt_intarg(OpCodes code, int val) case oAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case oVerifyHostKeyDNS: - case oStrictHostKeyChecking: case oUpdateHostkeys: return fmt_multistate_int(val, multistate_yesnoask); + case oStrictHostKeyChecking: + return fmt_multistate_int(val, multistate_strict_hostkey); case oControlMaster: return fmt_multistate_int(val, multistate_controlmaster); case oTunnel: diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h index 94dd427f57d..22fe5c1873c 100644 --- a/usr.bin/ssh/readconf.h +++ b/usr.bin/ssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.122 2017/05/30 18:58:37 bluhm Exp $ */ +/* $OpenBSD: readconf.h,v 1.123 2017/09/03 23:33:13 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -190,6 +190,11 @@ typedef struct { #define SSH_UPDATE_HOSTKEYS_YES 1 #define SSH_UPDATE_HOSTKEYS_ASK 2 +#define SSH_STRICT_HOSTKEY_OFF 0 +#define SSH_STRICT_HOSTKEY_NEW 1 +#define SSH_STRICT_HOSTKEY_YES 2 +#define SSH_STRICT_HOSTKEY_ASK 3 + void initialize_options(Options *); void fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); diff --git a/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5 index 15ca0b4f99b..3823da6f34b 100644 --- a/usr.bin/ssh/ssh_config.5 +++ b/usr.bin/ssh/ssh_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: ssh_config.5,v 1.253 2017/07/23 23:37:02 djm Exp $ -.Dd $Mdocdate: July 23 2017 $ +.\" $OpenBSD: ssh_config.5,v 1.254 2017/09/03 23:33:13 djm Exp $ +.Dd $Mdocdate: September 3 2017 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -1459,9 +1459,17 @@ frequently made. This option forces the user to manually add all new hosts. If this flag is set to -.Cm no , -ssh will automatically add new host keys to the -user known hosts files. +.Dq accept-new +then ssh will automatically add new new host keys to the user +known hosts files, but will not permit connections to hosts with +changed host keys. +If this flag is set to +.Dq no +or +.Dq off , +ssh will automatically add new host keys to the user known hosts files, +and allow connections to hosts with changed hostkeys to proceed subject +to some restrictions. If this flag is set to .Cm ask (the default), diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c index 7dad4f418de..a3bcf58ac53 100644 --- a/usr.bin/ssh/sshconnect.c +++ b/usr.bin/ssh/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.284 2017/09/01 05:53:56 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.285 2017/09/03 23:33:13 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -863,7 +863,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, if (readonly || want_cert) goto fail; /* The host is new. */ - if (options.strict_host_key_checking == 1) { + if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_YES) { /* * User has requested strict host key checking. We * will not add the host key automatically. The only @@ -872,7 +873,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, error("No %s host key is known for %.200s and you " "have requested strict checking.", type, host); goto fail; - } else if (options.strict_host_key_checking == 2) { + } else if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_ASK) { char msg1[1024], msg2[1024]; if (show_other_keys(host_hostkeys, host_key)) @@ -916,8 +918,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, hostkey_trusted = 1; /* user explicitly confirmed */ } /* - * If not in strict mode, add the key automatically to the - * local known_hosts file. + * If in "new" or "off" strict mode, add the key automatically + * to the local known_hosts file. */ if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); @@ -959,7 +961,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ - if (options.strict_host_key_checking) { + if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s was revoked and you have " "requested strict checking.", type, host); goto fail; @@ -1012,7 +1015,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ - if (options.strict_host_key_checking) { + if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s has changed and you have " "requested strict checking.", type, host); goto fail; @@ -1099,15 +1103,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, "\nMatching host key in %s:%lu", host_found->file, host_found->line); } - if (options.strict_host_key_checking == 1) { - logit("%s", msg); - error("Exiting, you have requested strict checking."); - goto fail; - } else if (options.strict_host_key_checking == 2) { + if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_ASK) { strlcat(msg, "\nAre you sure you want " "to continue connecting (yes/no)? ", sizeof(msg)); if (!confirm(msg)) goto fail; + } else if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { + logit("%s", msg); + error("Exiting, you have requested strict checking."); + goto fail; } else { logit("%s", msg); } |