1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

Patch from Alejandro Sedeno, somewhat modified by me, which

reorganises the GSSAPI support so that it handles alternative
implementations of the GSS-API. In particular, this means PuTTY can
now talk to MIT Kerberos for Windows instead of being limited to
SSPI. I don't know for sure whether further tweaking will be needed
(to the UI, most likely, or to automatic selection of credentials),
but testing reports suggest it's now at least worth committing to
trunk to get it more widely tested.

[originally from svn r8952]
This commit is contained in:
Simon Tatham
2010-05-19 18:22:17 +00:00
parent f2b737cdd6
commit 99fffd6ed3
21 changed files with 1148 additions and 303 deletions

76
ssh.c
View File

@ -13,6 +13,7 @@
#include "tree234.h"
#include "ssh.h"
#ifndef NO_GSSAPI
#include "sshgssc.h"
#include "sshgss.h"
#endif
@ -7209,6 +7210,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
int num_env, env_left, env_ok;
struct Packet *pktout;
#ifndef NO_GSSAPI
struct ssh_gss_library *gsslib;
Ssh_gss_ctx gss_ctx;
Ssh_gss_buf gss_buf;
Ssh_gss_buf gss_rcvtok, gss_sndtok;
@ -7584,9 +7586,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
s->can_keyb_inter = ssh->cfg.try_ki_auth &&
in_commasep_string("keyboard-interactive", methods, methlen);
#ifndef NO_GSSAPI
ssh_gss_init();
s->can_gssapi = ssh->cfg.try_gssapi_auth &&
in_commasep_string("gssapi-with-mic", methods, methlen) &&
ssh_gss_init();
in_commasep_string("gssapi-with-mic", methods, methlen) &&
n_ssh_gss_libraries > 0;
#endif
}
@ -7929,6 +7932,35 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
s->gotit = TRUE;
ssh->pkt_actx = SSH2_PKTCTX_GSSAPI;
/*
* Pick the highest GSS library on the preference
* list.
*/
{
int i, j;
s->gsslib = NULL;
for (i = 0; i < ngsslibs; i++) {
int want_id = ssh->cfg.ssh_gsslist[i];
for (j = 0; j < n_ssh_gss_libraries; j++)
if (ssh_gss_libraries[j].id == want_id) {
s->gsslib = &ssh_gss_libraries[j];
goto got_gsslib; /* double break */
}
}
got_gsslib:
/*
* We always expect to have found something in
* the above loop: we only came here if there
* was at least one viable GSS library, and the
* preference list should always mention
* everything and only change the order.
*/
assert(s->gsslib);
}
if (s->gsslib->gsslogmsg)
logevent(s->gsslib->gsslogmsg);
/* Sending USERAUTH_REQUEST with "gssapi-with-mic" method */
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(s->pktout, s->username);
@ -7936,7 +7968,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
ssh2_pkt_addstring(s->pktout, "gssapi-with-mic");
/* add mechanism info */
ssh_gss_indicate_mech(&s->gss_buf);
s->gsslib->indicate_mech(s->gsslib, &s->gss_buf);
/* number of GSSAPI mechanisms */
ssh2_pkt_adduint32(s->pktout,1);
@ -7972,8 +8004,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
}
/* now start running */
s->gss_stat = ssh_gss_import_name(ssh->fullhostname,
&s->gss_srv_name);
s->gss_stat = s->gsslib->import_name(s->gsslib,
ssh->fullhostname,
&s->gss_srv_name);
if (s->gss_stat != SSH_GSS_OK) {
if (s->gss_stat == SSH_GSS_BAD_HOST_NAME)
logevent("GSSAPI import name failed - Bad service name");
@ -7983,11 +8016,11 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
}
/* fetch TGT into GSS engine */
s->gss_stat = ssh_gss_acquire_cred(&s->gss_ctx);
s->gss_stat = s->gsslib->acquire_cred(s->gsslib, &s->gss_ctx);
if (s->gss_stat != SSH_GSS_OK) {
logevent("GSSAPI authentication failed to get credentials");
ssh_gss_release_name(&s->gss_srv_name);
s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
continue;
}
@ -7997,17 +8030,20 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
/* now enter the loop */
do {
s->gss_stat = ssh_gss_init_sec_context(&s->gss_ctx,
s->gss_srv_name,
ssh->cfg.gssapifwd,
&s->gss_rcvtok,
&s->gss_sndtok);
s->gss_stat = s->gsslib->init_sec_context
(s->gsslib,
&s->gss_ctx,
s->gss_srv_name,
ssh->cfg.gssapifwd,
&s->gss_rcvtok,
&s->gss_sndtok);
if (s->gss_stat!=SSH_GSS_S_COMPLETE &&
s->gss_stat!=SSH_GSS_S_CONTINUE_NEEDED) {
logevent("GSSAPI authentication initialisation failed");
if (ssh_gss_display_status(s->gss_ctx,&s->gss_buf) == SSH_GSS_OK) {
if (s->gsslib->display_status(s->gsslib, s->gss_ctx,
&s->gss_buf) == SSH_GSS_OK) {
logevent(s->gss_buf.value);
sfree(s->gss_buf.value);
}
@ -8024,7 +8060,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
ssh_pkt_addstring_start(s->pktout);
ssh_pkt_addstring_data(s->pktout,s->gss_sndtok.value,s->gss_sndtok.length);
ssh2_pkt_send(ssh, s->pktout);
ssh_gss_free_tok(&s->gss_sndtok);
s->gsslib->free_tok(s->gsslib, &s->gss_sndtok);
}
if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) {
@ -8041,8 +8077,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
} while (s-> gss_stat == SSH_GSS_S_CONTINUE_NEEDED);
if (s->gss_stat != SSH_GSS_OK) {
ssh_gss_release_name(&s->gss_srv_name);
ssh_gss_release_cred(&s->gss_ctx);
s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
s->gsslib->release_cred(s->gsslib, &s->gss_ctx);
continue;
}
logevent("GSSAPI authentication loop finished OK");
@ -8061,17 +8097,17 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
s->gss_buf.value = (char *)s->pktout->data + micoffset;
s->gss_buf.length = s->pktout->length - micoffset;
ssh_gss_get_mic(s->gss_ctx, &s->gss_buf, &mic);
s->gsslib->get_mic(s->gsslib, s->gss_ctx, &s->gss_buf, &mic);
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_GSSAPI_MIC);
ssh_pkt_addstring_start(s->pktout);
ssh_pkt_addstring_data(s->pktout, mic.value, mic.length);
ssh2_pkt_send(ssh, s->pktout);
ssh_gss_free_mic(&mic);
s->gsslib->free_mic(s->gsslib, &mic);
s->gotit = FALSE;
ssh_gss_release_name(&s->gss_srv_name);
ssh_gss_release_cred(&s->gss_ctx);
s->gsslib->release_name(s->gsslib, &s->gss_srv_name);
s->gsslib->release_cred(s->gsslib, &s->gss_ctx);
continue;
#endif
} else if (s->can_keyb_inter && !s->kbd_inter_refused) {