diff --git a/ssh1connection-client.c b/ssh1connection-client.c index faa0df28..40107dc3 100644 --- a/ssh1connection-client.c +++ b/ssh1connection-client.c @@ -526,3 +526,8 @@ SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan) { unreachable("Should never be called in the client"); } + +bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s) +{ + return !seat_set_trust_status(s->ppl.seat, false); +} diff --git a/ssh1connection-server.c b/ssh1connection-server.c index 6cef5012..aa44c529 100644 --- a/ssh1connection-server.c +++ b/ssh1connection-server.c @@ -374,3 +374,8 @@ SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan) return &c->sc; } + +bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s) +{ + return false; +} diff --git a/ssh1connection.c b/ssh1connection.c index 8b0c3aa9..d9b98420 100644 --- a/ssh1connection.c +++ b/ssh1connection.c @@ -209,6 +209,9 @@ static void ssh1_connection_free(PacketProtocolLayer *ppl) freetree234(s->rportfwds); portfwdmgr_free(s->portfwdmgr); + if (s->antispoof_prompt) + free_prompts(s->antispoof_prompt); + delete_callbacks_for_context(s); sfree(s); @@ -376,6 +379,42 @@ static void ssh1_connection_process_queue(PacketProtocolLayer *ppl) crBegin(s->crState); + /* + * Signal the seat that authentication is done, so that it can + * deploy spoofing defences. If it doesn't have any, deploy our + * own fallback one. + * + * We do this here rather than at the end of userauth, because we + * might not have gone through userauth at all (if we're a + * connection-sharing downstream). + */ + if (ssh1_connection_need_antispoof_prompt(s)) { + s->antispoof_prompt = new_prompts(); + s->antispoof_prompt->to_server = true; + s->antispoof_prompt->from_server = false; + s->antispoof_prompt->name = dupstr("Authentication successful"); + add_prompt( + s->antispoof_prompt, + dupstr("Access granted. Press Return to begin session. "), false); + s->antispoof_ret = seat_get_userpass_input( + s->ppl.seat, s->antispoof_prompt, NULL); + while (1) { + while (s->antispoof_ret < 0 && + bufchain_size(s->ppl.user_input) > 0) + s->antispoof_ret = seat_get_userpass_input( + s->ppl.seat, s->antispoof_prompt, s->ppl.user_input); + + if (s->antispoof_ret >= 0) + break; + + s->want_user_input = true; + crReturnV; + s->want_user_input = false; + } + free_prompts(s->antispoof_prompt); + s->antispoof_prompt = NULL; + } + portfwdmgr_config(s->portfwdmgr, s->conf); s->portfwdmgr_configured = true; diff --git a/ssh1connection.h b/ssh1connection.h index 0e5a71fd..1ee5465d 100644 --- a/ssh1connection.h +++ b/ssh1connection.h @@ -52,6 +52,9 @@ struct ssh1_connection_state { bool compressing; /* used in server mode only */ bool sent_exit_status; /* also for server mode */ + prompts_t *antispoof_prompt; + int antispoof_ret; + const SshServerConfig *ssc; ConnectionLayer cl; @@ -120,3 +123,5 @@ bool ssh1_handle_direction_specific_packet( struct ssh1_connection_state *s, PktIn *pktin); bool ssh1_check_termination(struct ssh1_connection_state *s); + +bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s);