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 */