upstream commit
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 Upstream-ID: 0f55502bf75fc93a74fb9853264a8276b9680b64
This commit is contained in:
parent
ff3c423840
commit
22376d27a3
19
readconf.c
19
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -751,6 +751,16 @@ static const struct multistate multistate_yesnoask[] = {
|
||||||
{ "ask", 2 },
|
{ "ask", 2 },
|
||||||
{ NULL, -1 }
|
{ 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[] = {
|
static const struct multistate multistate_yesnoaskconfirm[] = {
|
||||||
{ "true", 1 },
|
{ "true", 1 },
|
||||||
{ "false", 0 },
|
{ "false", 0 },
|
||||||
|
@ -984,7 +994,7 @@ parse_time:
|
||||||
|
|
||||||
case oStrictHostKeyChecking:
|
case oStrictHostKeyChecking:
|
||||||
intptr = &options->strict_host_key_checking;
|
intptr = &options->strict_host_key_checking;
|
||||||
multistate_ptr = multistate_yesnoask;
|
multistate_ptr = multistate_strict_hostkey;
|
||||||
goto parse_multistate;
|
goto parse_multistate;
|
||||||
|
|
||||||
case oCompression:
|
case oCompression:
|
||||||
|
@ -1927,7 +1937,7 @@ fill_default_options(Options * options)
|
||||||
if (options->check_host_ip == -1)
|
if (options->check_host_ip == -1)
|
||||||
options->check_host_ip = 1;
|
options->check_host_ip = 1;
|
||||||
if (options->strict_host_key_checking == -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)
|
if (options->compression == -1)
|
||||||
options->compression = 0;
|
options->compression = 0;
|
||||||
if (options->tcp_keep_alive == -1)
|
if (options->tcp_keep_alive == -1)
|
||||||
|
@ -2329,9 +2339,10 @@ fmt_intarg(OpCodes code, int val)
|
||||||
case oAddressFamily:
|
case oAddressFamily:
|
||||||
return fmt_multistate_int(val, multistate_addressfamily);
|
return fmt_multistate_int(val, multistate_addressfamily);
|
||||||
case oVerifyHostKeyDNS:
|
case oVerifyHostKeyDNS:
|
||||||
case oStrictHostKeyChecking:
|
|
||||||
case oUpdateHostkeys:
|
case oUpdateHostkeys:
|
||||||
return fmt_multistate_int(val, multistate_yesnoask);
|
return fmt_multistate_int(val, multistate_yesnoask);
|
||||||
|
case oStrictHostKeyChecking:
|
||||||
|
return fmt_multistate_int(val, multistate_strict_hostkey);
|
||||||
case oControlMaster:
|
case oControlMaster:
|
||||||
return fmt_multistate_int(val, multistate_controlmaster);
|
return fmt_multistate_int(val, multistate_controlmaster);
|
||||||
case oTunnel:
|
case oTunnel:
|
||||||
|
|
|
@ -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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -190,6 +190,11 @@ typedef struct {
|
||||||
#define SSH_UPDATE_HOSTKEYS_YES 1
|
#define SSH_UPDATE_HOSTKEYS_YES 1
|
||||||
#define SSH_UPDATE_HOSTKEYS_ASK 2
|
#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 initialize_options(Options *);
|
||||||
void fill_default_options(Options *);
|
void fill_default_options(Options *);
|
||||||
void fill_default_options_for_canonicalization(Options *);
|
void fill_default_options_for_canonicalization(Options *);
|
||||||
|
|
18
ssh_config.5
18
ssh_config.5
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" 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 $
|
.\" $OpenBSD: ssh_config.5,v 1.254 2017/09/03 23:33:13 djm Exp $
|
||||||
.Dd $Mdocdate: July 23 2017 $
|
.Dd $Mdocdate: September 3 2017 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1459,9 +1459,17 @@ frequently made.
|
||||||
This option forces the user to manually
|
This option forces the user to manually
|
||||||
add all new hosts.
|
add all new hosts.
|
||||||
If this flag is set to
|
If this flag is set to
|
||||||
.Cm no ,
|
.Dq accept-new
|
||||||
ssh will automatically add new host keys to the
|
then ssh will automatically add new new host keys to the user
|
||||||
user known hosts files.
|
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
|
If this flag is set to
|
||||||
.Cm ask
|
.Cm ask
|
||||||
(the default),
|
(the default),
|
||||||
|
|
30
sshconnect.c
30
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -891,7 +891,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
if (readonly || want_cert)
|
if (readonly || want_cert)
|
||||||
goto fail;
|
goto fail;
|
||||||
/* The host is new. */
|
/* 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
|
* User has requested strict host key checking. We
|
||||||
* will not add the host key automatically. The only
|
* will not add the host key automatically. The only
|
||||||
|
@ -900,7 +901,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
error("No %s host key is known for %.200s and you "
|
error("No %s host key is known for %.200s and you "
|
||||||
"have requested strict checking.", type, host);
|
"have requested strict checking.", type, host);
|
||||||
goto fail;
|
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];
|
char msg1[1024], msg2[1024];
|
||||||
|
|
||||||
if (show_other_keys(host_hostkeys, host_key))
|
if (show_other_keys(host_hostkeys, host_key))
|
||||||
|
@ -944,8 +946,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
hostkey_trusted = 1; /* user explicitly confirmed */
|
hostkey_trusted = 1; /* user explicitly confirmed */
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If not in strict mode, add the key automatically to the
|
* If in "new" or "off" strict mode, add the key automatically
|
||||||
* local known_hosts file.
|
* to the local known_hosts file.
|
||||||
*/
|
*/
|
||||||
if (options.check_host_ip && ip_status == HOST_NEW) {
|
if (options.check_host_ip && ip_status == HOST_NEW) {
|
||||||
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
|
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
|
||||||
|
@ -987,7 +989,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
* If strict host key checking is in use, the user will have
|
* If strict host key checking is in use, the user will have
|
||||||
* to edit the key manually and we can only abort.
|
* 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 "
|
error("%s host key for %.200s was revoked and you have "
|
||||||
"requested strict checking.", type, host);
|
"requested strict checking.", type, host);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1040,7 +1043,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
* If strict host key checking is in use, the user will have
|
* If strict host key checking is in use, the user will have
|
||||||
* to edit the key manually and we can only abort.
|
* 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 "
|
error("%s host key for %.200s has changed and you have "
|
||||||
"requested strict checking.", type, host);
|
"requested strict checking.", type, host);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1127,15 +1131,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
|
||||||
"\nMatching host key in %s:%lu",
|
"\nMatching host key in %s:%lu",
|
||||||
host_found->file, host_found->line);
|
host_found->file, host_found->line);
|
||||||
}
|
}
|
||||||
if (options.strict_host_key_checking == 1) {
|
if (options.strict_host_key_checking ==
|
||||||
logit("%s", msg);
|
SSH_STRICT_HOSTKEY_ASK) {
|
||||||
error("Exiting, you have requested strict checking.");
|
|
||||||
goto fail;
|
|
||||||
} else if (options.strict_host_key_checking == 2) {
|
|
||||||
strlcat(msg, "\nAre you sure you want "
|
strlcat(msg, "\nAre you sure you want "
|
||||||
"to continue connecting (yes/no)? ", sizeof(msg));
|
"to continue connecting (yes/no)? ", sizeof(msg));
|
||||||
if (!confirm(msg))
|
if (!confirm(msg))
|
||||||
goto fail;
|
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 {
|
} else {
|
||||||
logit("%s", msg);
|
logit("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue