From 223ea4d1e63cb1f592634539626bd9f2f2aad342 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 26 Apr 2018 19:15:15 +0100 Subject: [PATCH] Make GSS kex and GSS userauth separately configurable. The former has advantages in terms of keeping Kerberos credentials up to date, but it also does something sufficiently weird to the usual SSH host key system that I think it's worth making sure users have a means of turning it off separately from the less intrusive GSS userauth. --- config.c | 9 +++++++++ doc/config.but | 35 +++++++++++++++++++++++------------ putty.h | 3 ++- settings.c | 2 ++ ssh.c | 9 ++++++--- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/config.c b/config.c index 25b6e0ba..c949cf39 100644 --- a/config.c +++ b/config.c @@ -2403,6 +2403,10 @@ void setup_config_box(struct controlbox *b, int midsession, HELPCTX(ssh_kexlist), kexlist_handler, P(NULL)); c->listbox.height = KEX_MAX_CONF; + ctrl_checkbox(s, "Attempt GSSAPI key exchange", + 'k', HELPCTX(ssh_gssapi), + conf_checkbox_handler, + I(CONF_try_gssapi_kex)); s = ctrl_getset(b, "Connection/SSH/Kex", "repeat", "Options controlling key re-exchange"); @@ -2565,6 +2569,11 @@ void setup_config_box(struct controlbox *b, int midsession, conf_checkbox_handler, I(CONF_try_gssapi_auth)); + ctrl_checkbox(s, "Attempt GSSAPI key exchange (SSH-2 only)", + 'k', HELPCTX(ssh_gssapi), + conf_checkbox_handler, + I(CONF_try_gssapi_kex)); + ctrl_checkbox(s, "Allow GSSAPI credential delegation", 'l', HELPCTX(ssh_gssapi_delegation), conf_checkbox_handler, diff --git a/doc/config.but b/doc/config.but index 3107cbb6..1f33f7b0 100644 --- a/doc/config.but +++ b/doc/config.but @@ -2581,6 +2581,13 @@ you to delegate the credentials that are active at the beginning of the session; they can't be refreshed automatically later, in a long-running session. +Another effect of GSSAPI key exchange is that it replaces the usual +SSH mechanism of permanent host keys. So if you use this method, then +you won't be asked any interactive questions about whether to accept +the server's host key. Instead, the Kerberos exchange will verify the +identity of the host you connect to, at the same time as verifying +your identity to it. + \S{config-ssh-kex-rekey} \ii{Repeat key exchange} \cfg{winhelp-topic}{ssh.kex.repeat} @@ -2988,19 +2995,23 @@ GSSAPI authentication is only available in the SSH-2 protocol. PuTTY supports two forms of GSSAPI-based authentication. In one of them, the SSH key exchange happens in the normal way, and GSSAPI is -only involved in authenticating the user. In the other, GSSAPI-based -authentication is combined with the key exchange phase, and the SSH -authentication step has nothing left to do. If you enable GSSAPI -authentication, PuTTY will attempt both of these methods, and use -whichever the server supports. +only involved in authenticating the user. The checkbox labelled +\q{Attempt GSSAPI authentication} controls this form. -The topmost control on the GSSAPI subpanel is the checkbox labelled -\q{Attempt GSSAPI authentication}. If this is disabled, GSSAPI will -not be attempted at all and the rest of this panel is unused. If it -is enabled, GSSAPI authentication will be attempted, and (typically) -if your client machine has valid Kerberos credentials loaded, then -PuTTY should be able to authenticate automatically to servers that -support Kerberos logins. +In the other method, GSSAPI-based authentication is combined with the +SSH key exchange phase. If this succeeds, then the SSH authentication +step has nothing left to do. See \k{config-ssh-gssapi-kex} for more +information about this method. The checkbox labelled \q{Attempt GSSAPI +key exchange} controls this form. + +If one or both of these controls is enabled, then GSSAPI +authentication will be attempted in one form or the other, and +(typically) if your client machine has valid Kerberos credentials +loaded, then PuTTY should be able to authenticate automatically to +servers that support Kerberos logins. + +If both of those checkboxes are disabled, PuTTY will not try any form +of GSSAPI at all, and the rest of this panel will be unused. \S{config-ssh-auth-gssapi-delegation} \q{Allow GSSAPI credential delegation} diff --git a/putty.h b/putty.h index a7cee555..e53adf10 100644 --- a/putty.h +++ b/putty.h @@ -802,7 +802,8 @@ void cleanup_exit(int); X(INT, NONE, ssh_show_banner) /* show USERAUTH_BANNERs (SSH-2 only) */ \ X(INT, NONE, try_tis_auth) \ X(INT, NONE, try_ki_auth) \ - X(INT, NONE, try_gssapi_auth) /* attempt gssapi auth */ \ + X(INT, NONE, try_gssapi_auth) /* attempt gssapi auth via ssh userauth */ \ + X(INT, NONE, try_gssapi_kex) /* attempt gssapi auth via ssh kex */ \ X(INT, NONE, gssapifwd) /* forward tgt via gss */ \ X(INT, NONE, gssapirekey) /* KEXGSS refresh interval (mins) */ \ X(INT, INT, ssh_gsslist) /* preference order for local GSS libs */ \ diff --git a/settings.c b/settings.c index a6b59e28..a1b2a86f 100644 --- a/settings.c +++ b/settings.c @@ -581,6 +581,7 @@ void save_open_settings(void *sesskey, Conf *conf) write_setting_i(sesskey, "AuthTIS", conf_get_int(conf, CONF_try_tis_auth)); write_setting_i(sesskey, "AuthKI", conf_get_int(conf, CONF_try_ki_auth)); write_setting_i(sesskey, "AuthGSSAPI", conf_get_int(conf, CONF_try_gssapi_auth)); + write_setting_i(sesskey, "AuthGSSAPIKEX", conf_get_int(conf, CONF_try_gssapi_kex)); #ifndef NO_GSSAPI wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist); write_setting_filename(sesskey, "GSSCustom", conf_get_filename(conf, CONF_ssh_gss_custom)); @@ -970,6 +971,7 @@ void load_open_settings(void *sesskey, Conf *conf) gppi(sesskey, "AuthTIS", 0, conf, CONF_try_tis_auth); gppi(sesskey, "AuthKI", 1, conf, CONF_try_ki_auth); gppi(sesskey, "AuthGSSAPI", 1, conf, CONF_try_gssapi_auth); + gppi(sesskey, "AuthGSSAPIKEX", 1, conf, CONF_try_gssapi_kex); #ifndef NO_GSSAPI gprefs(sesskey, "GSSLibs", "\0", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist); diff --git a/ssh.c b/ssh.c index 2ba3a17c..f461b5b5 100644 --- a/ssh.c +++ b/ssh.c @@ -6595,7 +6595,7 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen, * where the flag was set on the previous key exchange.) */ s->can_gssapi_keyex = FALSE; - } else { + } else if (conf_get_int(ssh->conf, CONF_try_gssapi_kex)) { /* * We always check if we have GSS creds before we come up with * the kex algorithm list, otherwise future rekeys will fail @@ -6629,6 +6629,8 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen, if (!s->got_session_id && (ssh->gss_status & GSS_CTXT_MAYFAIL) != 0) s->can_gssapi_keyex = 0; s->gss_delegate = conf_get_int(ssh->conf, CONF_gssapifwd); + } else { + s->can_gssapi_keyex = FALSE; } #endif @@ -10429,7 +10431,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen, in_commasep_string("gssapi-with-mic", methods, methlen) && ssh->gsslibs->nlibraries > 0; s->can_gssapi_keyex_auth = - conf_get_int(ssh->conf, CONF_try_gssapi_auth) && + conf_get_int(ssh->conf, CONF_try_gssapi_kex) && in_commasep_string("gssapi-keyex", methods, methlen) && ssh->gsslibs->nlibraries > 0 && ssh->gss_ctx; @@ -11903,7 +11905,8 @@ static void ssh2_gss_update(Ssh ssh) */ if (ssh->gsslibs->nlibraries == 0) return; - if (!conf_get_int(ssh->conf, CONF_try_gssapi_auth)) + if (!conf_get_int(ssh->conf, CONF_try_gssapi_auth) && + !conf_get_int(ssh->conf, CONF_try_gssapi_kex)) return; /* Import server name and cache it */