1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

do_ssh2_authconn: get packets from a PacketQueue.

Just like do_ssh1_login, do_ssh2_authconn is now no longer receiving
its packets via function arguments; instead, it's pulling them off a
dedicated PacketQueue populated by particular dispatch table entries,
with the same reference-counting system to stop them being freed when
the pq_full processing function regains control.

This eliminates further ugly bombout()s from the code while waiting
for authentication responses from the user or the SSH agent.

As I mentioned in the previous commit, I've had to keep
ssh2_authconn_input separate from do_ssh2_authconn, and this time the
reason why is thoroughly annoying: it's because do_ssh2_authconn has
changed its prototype to take the Ssh structure as a void * so that it
can be called from the idempotent callback system, whereas
ssh2_authconn_input has to have the type of ssh->current_user_input_fn
which takes the more sensible pointer type 'Ssh'.
This commit is contained in:
Simon Tatham 2018-05-18 07:22:58 +01:00
parent 364b3a2838
commit e2b7f4f374

76
ssh.c
View File

@ -385,7 +385,7 @@ static int ssh2_pkt_construct(Ssh, struct Packet *);
static void ssh2_pkt_send(Ssh, struct Packet *);
static void ssh2_pkt_send_noqueue(Ssh, struct Packet *);
static void do_ssh1_login(void *vctx);
static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin);
static void do_ssh2_authconn(void *vctx);
static void ssh_channel_init(struct ssh_channel *c);
static struct ssh_channel *ssh_channel_msg(Ssh ssh, struct Packet *pktin);
static void ssh_channel_got_eof(struct ssh_channel *c);
@ -969,6 +969,9 @@ struct ssh_tag {
struct PacketQueue pq_ssh1_login;
struct IdempotentCallback ssh1_login_icb;
struct PacketQueue pq_ssh2_authconn;
struct IdempotentCallback ssh2_authconn_icb;
bufchain user_input;
struct IdempotentCallback user_input_consumer;
@ -3514,7 +3517,7 @@ static void do_ssh_connection_init(Ssh ssh)
/*
* Get authconn (really just conn) under way.
*/
do_ssh2_authconn(ssh, NULL);
do_ssh2_authconn(ssh);
sfree(s->vstring);
@ -3956,7 +3959,7 @@ static void ssh_agent_callback(void *sshv, void *reply, int replylen)
if (ssh->version == 1)
do_ssh1_login(ssh);
else
do_ssh2_authconn(ssh, NULL);
do_ssh2_authconn(ssh);
}
static void ssh_dialog_callback(void *sshv, int ret)
@ -8432,8 +8435,8 @@ static void do_ssh2_transport(Ssh ssh, const void *vin, int inlen,
/*
* Allow authconn to initialise itself.
*/
do_ssh2_authconn(ssh, NULL);
ssh->current_user_input_fn = ssh2_authconn_input;
do_ssh2_authconn(ssh);
}
crReturnV;
}
@ -9985,18 +9988,23 @@ static void ssh2_setup_env(struct ssh_channel *c, struct Packet *pktin,
*/
static void ssh2_msg_authconn(Ssh ssh, struct Packet *pktin)
{
do_ssh2_authconn(ssh, pktin);
pktin->refcount++; /* avoid packet being freed when we return */
pq_push(&ssh->pq_ssh2_authconn, pktin);
queue_idempotent_callback(&ssh->ssh2_authconn_icb);
}
static void ssh2_response_authconn(struct ssh_channel *c, struct Packet *pktin,
void *ctx)
{
if (pktin)
do_ssh2_authconn(c->ssh, pktin);
ssh2_msg_authconn(c->ssh, pktin);
}
static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
static void do_ssh2_authconn(void *vctx)
{
Ssh ssh = (Ssh)vctx;
struct Packet *pktin;
struct do_ssh2_authconn_state {
int crLine;
enum {
@ -10091,7 +10099,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
ssh2_pkt_addstring(s->pktout, "ssh-userauth");
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type == SSH2_MSG_SERVICE_ACCEPT)
s->done_service_req = TRUE;
}
@ -10102,7 +10110,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
s->pktout = ssh2_pkt_init(SSH2_MSG_SERVICE_REQUEST);
ssh2_pkt_addstring(s->pktout, "ssh-connection");
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type == SSH2_MSG_SERVICE_ACCEPT) {
s->we_are_in = TRUE; /* no auth required */
} else {
@ -10197,14 +10205,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh_agent_callback, ssh);
if (ssh->auth_agent_query) {
ssh->agent_response = NULL;
do {
crReturnV;
if (pktin) {
bombout(("Unexpected data from server while"
" waiting for agent response"));
crStopV;
}
} while (!ssh->agent_response);
crWaitUntilV(ssh->agent_response);
r = ssh->agent_response;
s->agent_responselen = ssh->agent_response_len;
}
@ -10399,7 +10400,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
* Wait for the result of the last authentication request.
*/
if (!s->gotit)
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
/*
* Now is a convenient point to spew any banner material
* that we've accumulated. (This should ensure that when
@ -10593,7 +10594,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh2_pkt_send(ssh, s->pktout);
s->type = AUTH_TYPE_PUBLICKEY_OFFER_QUIET;
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
/* Offer of key refused. */
@ -10663,15 +10664,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh_agent_callback, ssh);
if (ssh->auth_agent_query) {
ssh->agent_response = NULL;
do {
crReturnV;
if (pktin) {
bombout(("Unexpected data from server"
" while waiting for agent"
" response"));
crStopV;
}
} while (!ssh->agent_response);
crWaitUntilV(ssh->agent_response);
vret = ssh->agent_response;
s->retlen = ssh->agent_response_len;
}
@ -10737,7 +10730,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh2_pkt_send(ssh, s->pktout);
logevent("Offered public key");
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
/* Key refused. Give up. */
s->gotit = TRUE; /* reconsider message next loop */
@ -10929,7 +10922,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh_pkt_adddata(s->pktout, s->gss_buf.value,
s->gss_buf.length);
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) {
logevent("GSSAPI authentication request refused");
continue;
@ -11021,7 +11014,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
}
if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) {
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_TOKEN) {
logevent("GSSAPI authentication -"
" bad server response");
@ -11073,7 +11066,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
logevent("Attempting keyboard-interactive authentication");
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
/* Server is not willing to do keyboard-interactive
* at all (or, bizarrely but legally, accepts the
@ -11201,7 +11194,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
* Get the next packet in case it's another
* INFO_REQUEST.
*/
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
}
@ -11281,7 +11274,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
* Wait for next packet, in case it's a password change
* request.
*/
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
changereq_first_time = TRUE;
while (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) {
@ -11417,7 +11410,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
* (If it's CHANGEREQ again, it's not happy with the
* new password.)
*/
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
changereq_first_time = FALSE;
}
@ -11525,7 +11518,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh2_pkt_send(ssh, s->pktout);
ssh->ncmode = FALSE;
}
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
bombout(("Server sent strange packet %d in response to main "
@ -11665,7 +11658,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
}
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
crMaybeWaitUntilV((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
@ -11711,7 +11704,7 @@ static void do_ssh2_authconn(Ssh ssh, struct Packet *pktin)
ssh->send_ok = 1;
while (1) {
crReturnV;
if (pktin) {
if ((pktin = pq_pop(&ssh->pq_ssh2_authconn)) != NULL) {
/*
* _All_ the connection-layer packets we expect to
@ -12229,7 +12222,7 @@ static void ssh2_general_packet_processing(Ssh ssh, struct Packet *pktin)
static void ssh2_authconn_input(Ssh ssh)
{
do_ssh2_authconn(ssh, NULL);
do_ssh2_authconn(ssh);
}
static void ssh_cache_conf_values(Ssh ssh)
@ -12316,6 +12309,10 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
ssh->ssh1_login_icb.fn = do_ssh1_login;
ssh->ssh1_login_icb.ctx = ssh;
ssh->ssh1_login_icb.queued = FALSE;
pq_init(&ssh->pq_ssh2_authconn);
ssh->ssh2_authconn_icb.fn = do_ssh2_authconn;
ssh->ssh2_authconn_icb.ctx = ssh;
ssh->ssh2_authconn_icb.queued = FALSE;
bufchain_init(&ssh->user_input);
ssh->user_input_consumer.fn = ssh_process_user_input;
ssh->user_input_consumer.ctx = ssh;
@ -12495,6 +12492,7 @@ static void ssh_free(void *handle)
sfree(ssh->incoming_data_eof_message);
pq_clear(&ssh->pq_full);
pq_clear(&ssh->pq_ssh1_login);
pq_clear(&ssh->pq_ssh2_authconn);
bufchain_clear(&ssh->user_input);
sfree(ssh->v_c);
sfree(ssh->v_s);