ssh2userauth.c (putty-0.75) | : | ssh2userauth.c (putty-0.76) | ||
---|---|---|---|---|
skipping to change at line 31 | skipping to change at line 31 | |||
typedef struct agent_key { | typedef struct agent_key { | |||
strbuf *blob, *comment; | strbuf *blob, *comment; | |||
ptrlen algorithm; | ptrlen algorithm; | |||
} agent_key; | } agent_key; | |||
struct ssh2_userauth_state { | struct ssh2_userauth_state { | |||
int crState; | int crState; | |||
PacketProtocolLayer *transport_layer, *successor_layer; | PacketProtocolLayer *transport_layer, *successor_layer; | |||
Filename *keyfile; | Filename *keyfile; | |||
bool show_banner, tryagent, change_username; | bool show_banner, tryagent, notrivialauth, change_username; | |||
char *hostname, *fullhostname; | char *hostname, *fullhostname; | |||
char *default_username; | char *default_username; | |||
bool try_ki_auth, try_gssapi_auth, try_gssapi_kex_auth, gssapi_fwd; | bool try_ki_auth, try_gssapi_auth, try_gssapi_kex_auth, gssapi_fwd; | |||
ptrlen session_id; | ptrlen session_id; | |||
enum { | enum { | |||
AUTH_TYPE_NONE, | AUTH_TYPE_NONE, | |||
AUTH_TYPE_PUBLICKEY, | AUTH_TYPE_PUBLICKEY, | |||
AUTH_TYPE_PUBLICKEY_OFFER_LOUD, | AUTH_TYPE_PUBLICKEY_OFFER_LOUD, | |||
AUTH_TYPE_PUBLICKEY_OFFER_QUIET, | AUTH_TYPE_PUBLICKEY_OFFER_QUIET, | |||
skipping to change at line 85 | skipping to change at line 85 | |||
ptrlen agent_response; | ptrlen agent_response; | |||
BinarySource asrc[1]; /* for reading SSH agent response */ | BinarySource asrc[1]; /* for reading SSH agent response */ | |||
size_t agent_keys_len; | size_t agent_keys_len; | |||
agent_key *agent_keys; | agent_key *agent_keys; | |||
size_t agent_key_index, agent_key_limit; | size_t agent_key_index, agent_key_limit; | |||
ptrlen agent_keyalg; | ptrlen agent_keyalg; | |||
unsigned signflags; | unsigned signflags; | |||
int len; | int len; | |||
PktOut *pktout; | PktOut *pktout; | |||
bool want_user_input; | bool want_user_input; | |||
bool is_trivial_auth; | ||||
agent_pending_query *auth_agent_query; | agent_pending_query *auth_agent_query; | |||
bufchain banner; | bufchain banner; | |||
bufchain_sink banner_bs; | bufchain_sink banner_bs; | |||
StripCtrlChars *banner_scc; | StripCtrlChars *banner_scc; | |||
bool banner_scc_initialised; | bool banner_scc_initialised; | |||
StripCtrlChars *ki_scc; | StripCtrlChars *ki_scc; | |||
bool ki_scc_initialised; | bool ki_scc_initialised; | |||
bool ki_printed_header; | bool ki_printed_header; | |||
skipping to change at line 137 | skipping to change at line 138 | |||
.want_user_input = ssh2_userauth_want_user_input, | .want_user_input = ssh2_userauth_want_user_input, | |||
.got_user_input = ssh2_userauth_got_user_input, | .got_user_input = ssh2_userauth_got_user_input, | |||
.reconfigure = ssh2_userauth_reconfigure, | .reconfigure = ssh2_userauth_reconfigure, | |||
.queued_data_size = ssh_ppl_default_queued_data_size, | .queued_data_size = ssh_ppl_default_queued_data_size, | |||
.name = "ssh-userauth", | .name = "ssh-userauth", | |||
}; | }; | |||
PacketProtocolLayer *ssh2_userauth_new( | PacketProtocolLayer *ssh2_userauth_new( | |||
PacketProtocolLayer *successor_layer, | PacketProtocolLayer *successor_layer, | |||
const char *hostname, const char *fullhostname, | const char *hostname, const char *fullhostname, | |||
Filename *keyfile, bool show_banner, bool tryagent, | Filename *keyfile, bool show_banner, bool tryagent, bool notrivialauth, | |||
const char *default_username, bool change_username, | const char *default_username, bool change_username, | |||
bool try_ki_auth, bool try_gssapi_auth, bool try_gssapi_kex_auth, | bool try_ki_auth, bool try_gssapi_auth, bool try_gssapi_kex_auth, | |||
bool gssapi_fwd, struct ssh_connection_shared_gss_state *shgss) | bool gssapi_fwd, struct ssh_connection_shared_gss_state *shgss) | |||
{ | { | |||
struct ssh2_userauth_state *s = snew(struct ssh2_userauth_state); | struct ssh2_userauth_state *s = snew(struct ssh2_userauth_state); | |||
memset(s, 0, sizeof(*s)); | memset(s, 0, sizeof(*s)); | |||
s->ppl.vt = &ssh2_userauth_vtable; | s->ppl.vt = &ssh2_userauth_vtable; | |||
s->successor_layer = successor_layer; | s->successor_layer = successor_layer; | |||
s->hostname = dupstr(hostname); | s->hostname = dupstr(hostname); | |||
s->fullhostname = dupstr(fullhostname); | s->fullhostname = dupstr(fullhostname); | |||
s->keyfile = filename_copy(keyfile); | s->keyfile = filename_copy(keyfile); | |||
s->show_banner = show_banner; | s->show_banner = show_banner; | |||
s->tryagent = tryagent; | s->tryagent = tryagent; | |||
s->notrivialauth = notrivialauth; | ||||
s->default_username = dupstr(default_username); | s->default_username = dupstr(default_username); | |||
s->change_username = change_username; | s->change_username = change_username; | |||
s->try_ki_auth = try_ki_auth; | s->try_ki_auth = try_ki_auth; | |||
s->try_gssapi_auth = try_gssapi_auth; | s->try_gssapi_auth = try_gssapi_auth; | |||
s->try_gssapi_kex_auth = try_gssapi_kex_auth; | s->try_gssapi_kex_auth = try_gssapi_kex_auth; | |||
s->gssapi_fwd = gssapi_fwd; | s->gssapi_fwd = gssapi_fwd; | |||
s->shgss = shgss; | s->shgss = shgss; | |||
s->last_methods_string = strbuf_new(); | s->last_methods_string = strbuf_new(); | |||
s->is_trivial_auth = true; | ||||
bufchain_init(&s->banner); | bufchain_init(&s->banner); | |||
bufchain_sink_init(&s->banner_bs, &s->banner); | bufchain_sink_init(&s->banner_bs, &s->banner); | |||
return &s->ppl; | return &s->ppl; | |||
} | } | |||
void ssh2_userauth_set_transport_layer(PacketProtocolLayer *userauth, | void ssh2_userauth_set_transport_layer(PacketProtocolLayer *userauth, | |||
PacketProtocolLayer *transport) | PacketProtocolLayer *transport) | |||
{ | { | |||
struct ssh2_userauth_state *s = | struct ssh2_userauth_state *s = | |||
skipping to change at line 821 | skipping to change at line 824 | |||
if (get_byte(src) == SSH2_AGENT_SIGN_RESPONSE && | if (get_byte(src) == SSH2_AGENT_SIGN_RESPONSE && | |||
(sigblob = get_string(src), !get_err(src))) { | (sigblob = get_string(src), !get_err(src))) { | |||
ppl_logevent("Sending Pageant's response"); | ppl_logevent("Sending Pageant's response"); | |||
ssh2_userauth_add_sigblob( | ssh2_userauth_add_sigblob( | |||
s, s->pktout, | s, s->pktout, | |||
ptrlen_from_strbuf( | ptrlen_from_strbuf( | |||
s->agent_keys[s->agent_key_index].blob), | s->agent_keys[s->agent_key_index].blob), | |||
sigblob); | sigblob); | |||
pq_push(s->ppl.out_pq, s->pktout); | pq_push(s->ppl.out_pq, s->pktout); | |||
s->type = AUTH_TYPE_PUBLICKEY; | s->type = AUTH_TYPE_PUBLICKEY; | |||
s->is_trivial_auth = false; | ||||
} else { | } else { | |||
ppl_logevent("Pageant refused signing request"); | ppl_logevent("Pageant refused signing request"); | |||
ppl_printf("Pageant failed to " | ppl_printf("Pageant failed to " | |||
"provide a signature\r\n"); | "provide a signature\r\n"); | |||
s->suppress_wait_for_response_packet = true; | s->suppress_wait_for_response_packet = true; | |||
ssh_free_pktout(s->pktout); | ssh_free_pktout(s->pktout); | |||
} | } | |||
} else { | } else { | |||
ppl_logevent("Pageant failed to respond to " | ppl_logevent("Pageant failed to respond to " | |||
"signing request"); | "signing request"); | |||
skipping to change at line 1041 | skipping to change at line 1045 | |||
ptrlen_from_strbuf(sigblob)); | ptrlen_from_strbuf(sigblob)); | |||
strbuf_free(pkblob); | strbuf_free(pkblob); | |||
strbuf_free(sigblob); | strbuf_free(sigblob); | |||
pq_push(s->ppl.out_pq, s->pktout); | pq_push(s->ppl.out_pq, s->pktout); | |||
ppl_logevent("Sent public key signature"); | ppl_logevent("Sent public key signature"); | |||
s->type = AUTH_TYPE_PUBLICKEY; | s->type = AUTH_TYPE_PUBLICKEY; | |||
ssh_key_free(key->key); | ssh_key_free(key->key); | |||
sfree(key->comment); | sfree(key->comment); | |||
sfree(key); | sfree(key); | |||
s->is_trivial_auth = false; | ||||
} | } | |||
#ifndef NO_GSSAPI | #ifndef NO_GSSAPI | |||
} else if (s->can_gssapi && !s->tried_gssapi) { | } else if (s->can_gssapi && !s->tried_gssapi) { | |||
/* gssapi-with-mic authentication */ | /* gssapi-with-mic authentication */ | |||
ptrlen data; | ptrlen data; | |||
s->type = AUTH_TYPE_GSSAPI; | s->type = AUTH_TYPE_GSSAPI; | |||
skipping to change at line 1172 | skipping to change at line 1177 | |||
pq_push_front(s->ppl.in_pq, pktin); | pq_push_front(s->ppl.in_pq, pktin); | |||
break; | break; | |||
} | } | |||
ppl_logevent("GSSAPI authentication initialised"); | ppl_logevent("GSSAPI authentication initialised"); | |||
/* | /* | |||
* Client and server now exchange tokens until GSSAPI | * Client and server now exchange tokens until GSSAPI | |||
* no longer says CONTINUE_NEEDED | * no longer says CONTINUE_NEEDED | |||
*/ | */ | |||
if (s->gss_sndtok.length != 0) { | if (s->gss_sndtok.length != 0) { | |||
s->is_trivial_auth = false; | ||||
s->pktout = | s->pktout = | |||
ssh_bpp_new_pktout( | ssh_bpp_new_pktout( | |||
s->ppl.bpp, SSH2_MSG_USERAUTH_GSSAPI_TOKEN); | s->ppl.bpp, SSH2_MSG_USERAUTH_GSSAPI_TOKEN); | |||
put_string(s->pktout, | put_string(s->pktout, | |||
s->gss_sndtok.value, s->gss_sndtok.length); | s->gss_sndtok.value, s->gss_sndtok.length); | |||
pq_push(s->ppl.out_pq, s->pktout); | pq_push(s->ppl.out_pq, s->pktout); | |||
s->shgss->lib->free_tok(s->shgss->lib, &s->gss_sndtok); | s->shgss->lib->free_tok(s->shgss->lib, &s->gss_sndtok); | |||
} | } | |||
if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) { | if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) { | |||
skipping to change at line 1291 | skipping to change at line 1297 | |||
s->kbd_inter_refused = true; /* don't try it again */ | s->kbd_inter_refused = true; /* don't try it again */ | |||
continue; | continue; | |||
} | } | |||
s->ki_printed_header = false; | s->ki_printed_header = false; | |||
/* | /* | |||
* Loop while the server continues to send INFO_REQUESTs. | * Loop while the server continues to send INFO_REQUESTs. | |||
*/ | */ | |||
while (pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) { | while (pktin->type == SSH2_MSG_USERAUTH_INFO_REQUEST) { | |||
ptrlen name, inst; | ptrlen name, inst; | |||
strbuf *sb; | strbuf *sb; | |||
/* | /* | |||
* We've got a fresh USERAUTH_INFO_REQUEST. | * We've got a fresh USERAUTH_INFO_REQUEST. | |||
* Get the preamble and start building a prompt. | * Get the preamble and start building a prompt. | |||
*/ | */ | |||
name = get_string(pktin); | name = get_string(pktin); | |||
inst = get_string(pktin); | inst = get_string(pktin); | |||
get_string(pktin); /* skip language tag */ | get_string(pktin); /* skip language tag */ | |||
s->cur_prompt = new_prompts(); | s->cur_prompt = new_prompts(); | |||
s->cur_prompt->to_server = true; | s->cur_prompt->to_server = true; | |||
s->cur_prompt->from_server = true; | s->cur_prompt->from_server = true; | |||
/* | /* | |||
* Get any prompt(s) from the packet. | * Get any prompt(s) from the packet. | |||
*/ | */ | |||
s->num_prompts = get_uint32(pktin); | s->num_prompts = get_uint32(pktin); | |||
for (uint32_t i = 0; i < s->num_prompts; i++) { | for (uint32_t i = 0; i < s->num_prompts; i++) { | |||
s->is_trivial_auth = false; | ||||
ptrlen prompt = get_string(pktin); | ptrlen prompt = get_string(pktin); | |||
bool echo = get_bool(pktin); | bool echo = get_bool(pktin); | |||
if (get_err(pktin)) { | if (get_err(pktin)) { | |||
ssh_proto_error( | ssh_proto_error( | |||
s->ppl.ssh, "Server sent truncated " | s->ppl.ssh, "Server sent truncated " | |||
"SSH_MSG_USERAUTH_INFO_REQUEST packet"); | "SSH_MSG_USERAUTH_INFO_REQUEST packet"); | |||
return; | return; | |||
} | } | |||
skipping to change at line 1475 | skipping to change at line 1481 | |||
ssh2_userauth_antispoof_msg( | ssh2_userauth_antispoof_msg( | |||
s, "End of keyboard-interactive prompts from server"); | s, "End of keyboard-interactive prompts from server"); | |||
} | } | |||
/* | /* | |||
* We should have SUCCESS or FAILURE now. | * We should have SUCCESS or FAILURE now. | |||
*/ | */ | |||
pq_push_front(s->ppl.in_pq, pktin); | pq_push_front(s->ppl.in_pq, pktin); | |||
} else if (s->can_passwd) { | } else if (s->can_passwd) { | |||
s->is_trivial_auth = false; | ||||
/* | /* | |||
* Plain old password authentication. | * Plain old password authentication. | |||
*/ | */ | |||
bool changereq_first_time; /* not live over crReturn */ | bool changereq_first_time; /* not live over crReturn */ | |||
s->ppl.bpp->pls->actx = SSH2_PKTCTX_PASSWORD; | s->ppl.bpp->pls->actx = SSH2_PKTCTX_PASSWORD; | |||
s->cur_prompt = new_prompts(); | s->cur_prompt = new_prompts(); | |||
s->cur_prompt->to_server = true; | s->cur_prompt->to_server = true; | |||
s->cur_prompt->from_server = false; | s->cur_prompt->from_server = false; | |||
skipping to change at line 1734 | skipping to change at line 1740 | |||
"available (server sent: %s)", | "available (server sent: %s)", | |||
s->last_methods_string->s); | s->last_methods_string->s); | |||
return; | return; | |||
} | } | |||
} | } | |||
try_new_username:; | try_new_username:; | |||
} | } | |||
userauth_success: | userauth_success: | |||
if (s->notrivialauth && s->is_trivial_auth) { | ||||
ssh_proto_error(s->ppl.ssh, "Authentication was trivial! " | ||||
"Abandoning session as specified in configuration."); | ||||
return; | ||||
} | ||||
/* | /* | |||
* We've just received USERAUTH_SUCCESS, and we haven't sent | * We've just received USERAUTH_SUCCESS, and we haven't sent | |||
* any packets since. Signal the transport layer to consider | * any packets since. Signal the transport layer to consider | |||
* doing an immediate rekey, if it has any reason to want to. | * doing an immediate rekey, if it has any reason to want to. | |||
*/ | */ | |||
ssh2_transport_notify_auth_done(s->transport_layer); | ssh2_transport_notify_auth_done(s->transport_layer); | |||
/* | /* | |||
* Finally, hand over to our successor layer, and return | * Finally, hand over to our successor layer, and return | |||
* immediately without reaching the crFinishV: ssh_ppl_replace | * immediately without reaching the crFinishV: ssh_ppl_replace | |||
End of changes. 12 change blocks. | ||||
4 lines changed or deleted | 16 lines changed or added |