diff options
Diffstat (limited to 'ssh2userauth-server.c')
-rw-r--r-- | ssh2userauth-server.c | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/ssh2userauth-server.c b/ssh2userauth-server.c deleted file mode 100644 index cacddee6..00000000 --- a/ssh2userauth-server.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Packet protocol layer for the server side of the SSH-2 userauth - * protocol (RFC 4252). - */ - -#include <assert.h> - -#include "putty.h" -#include "ssh.h" -#include "sshbpp.h" -#include "sshppl.h" -#include "sshcr.h" -#include "sshserver.h" - -#ifndef NO_GSSAPI -#include "sshgssc.h" -#include "sshgss.h" -#endif - -struct ssh2_userauth_server_state { - int crState; - - PacketProtocolLayer *transport_layer, *successor_layer; - ptrlen session_id; - - AuthPolicy *authpolicy; - const SshServerConfig *ssc; - - ptrlen username, service, method; - unsigned methods, this_method; - bool partial_success; - - AuthKbdInt *aki; - - PacketProtocolLayer ppl; -}; - -static void ssh2_userauth_server_free(PacketProtocolLayer *); -static void ssh2_userauth_server_process_queue(PacketProtocolLayer *); - -static const PacketProtocolLayerVtable ssh2_userauth_server_vtable = { - .free = ssh2_userauth_server_free, - .process_queue = ssh2_userauth_server_process_queue, - .queued_data_size = ssh_ppl_default_queued_data_size, - .name = "ssh-userauth", - /* other methods are NULL */ -}; - -static void free_auth_kbdint(AuthKbdInt *aki) -{ - int i; - - if (!aki) - return; - - sfree(aki->title); - sfree(aki->instruction); - for (i = 0; i < aki->nprompts; i++) - sfree(aki->prompts[i].prompt); - sfree(aki->prompts); - sfree(aki); -} - -PacketProtocolLayer *ssh2_userauth_server_new( - PacketProtocolLayer *successor_layer, AuthPolicy *authpolicy, - const SshServerConfig *ssc) -{ - struct ssh2_userauth_server_state *s = - snew(struct ssh2_userauth_server_state); - memset(s, 0, sizeof(*s)); - s->ppl.vt = &ssh2_userauth_server_vtable; - - s->successor_layer = successor_layer; - s->authpolicy = authpolicy; - s->ssc = ssc; - - return &s->ppl; -} - -void ssh2_userauth_server_set_transport_layer(PacketProtocolLayer *userauth, - PacketProtocolLayer *transport) -{ - struct ssh2_userauth_server_state *s = - container_of(userauth, struct ssh2_userauth_server_state, ppl); - s->transport_layer = transport; -} - -static void ssh2_userauth_server_free(PacketProtocolLayer *ppl) -{ - struct ssh2_userauth_server_state *s = - container_of(ppl, struct ssh2_userauth_server_state, ppl); - - if (s->successor_layer) - ssh_ppl_free(s->successor_layer); - - free_auth_kbdint(s->aki); - - sfree(s); -} - -static PktIn *ssh2_userauth_server_pop(struct ssh2_userauth_server_state *s) -{ - return pq_pop(s->ppl.in_pq); -} - -static void ssh2_userauth_server_add_session_id( - struct ssh2_userauth_server_state *s, strbuf *sigdata) -{ - if (s->ppl.remote_bugs & BUG_SSH2_PK_SESSIONID) { - put_datapl(sigdata, s->session_id); - } else { - put_stringpl(sigdata, s->session_id); - } -} - -static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) -{ - struct ssh2_userauth_server_state *s = - container_of(ppl, struct ssh2_userauth_server_state, ppl); - PktIn *pktin; - PktOut *pktout; - - crBegin(s->crState); - - s->session_id = ssh2_transport_get_session_id(s->transport_layer); - - if (s->ssc->banner.ptr) { - pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_BANNER); - put_stringpl(pktout, s->ssc->banner); - put_stringz(pktout, ""); /* language tag */ - pq_push(s->ppl.out_pq, pktout); - } - - while (1) { - crMaybeWaitUntilV((pktin = ssh2_userauth_server_pop(s)) != NULL); - if (pktin->type != SSH2_MSG_USERAUTH_REQUEST) { - ssh_proto_error(s->ppl.ssh, "Received unexpected packet when " - "expecting USERAUTH_REQUEST, type %d (%s)", - pktin->type, - ssh2_pkt_type(s->ppl.bpp->pls->kctx, - s->ppl.bpp->pls->actx, pktin->type)); - return; - } - - s->username = get_string(pktin); - s->service = get_string(pktin); - s->method = get_string(pktin); - - if (!ptrlen_eq_string(s->service, s->successor_layer->vt->name)) { - /* - * Unconditionally reject authentication for any service - * other than the one we're going to hand over to. - */ - pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_FAILURE); - put_stringz(pktout, ""); - put_bool(pktout, false); - pq_push(s->ppl.out_pq, pktout); - continue; - } - - s->methods = auth_methods(s->authpolicy); - s->partial_success = false; - - if (ptrlen_eq_string(s->method, "none")) { - s->this_method = AUTHMETHOD_NONE; - if (!(s->methods & s->this_method)) - goto failure; - - if (!auth_none(s->authpolicy, s->username)) - goto failure; - } else if (ptrlen_eq_string(s->method, "password")) { - bool changing; - ptrlen password, new_password, *new_password_ptr; - - s->this_method = AUTHMETHOD_PASSWORD; - if (!(s->methods & s->this_method)) - goto failure; - - changing = get_bool(pktin); - password = get_string(pktin); - - if (changing) { - new_password = get_string(pktin); - new_password_ptr = &new_password; - } else { - new_password_ptr = NULL; - } - - int result = auth_password(s->authpolicy, s->username, - password, new_password_ptr); - if (result == 2) { - pktout = ssh_bpp_new_pktout( - s->ppl.bpp, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ); - put_stringz(pktout, "Please change your password"); - put_stringz(pktout, ""); /* language tag */ - pq_push(s->ppl.out_pq, pktout); - continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */ - } else if (result != 1) { - goto failure; - } - } else if (ptrlen_eq_string(s->method, "publickey")) { - bool has_signature, success, send_pk_ok, key_really_ok; - ptrlen algorithm, blob, signature; - const ssh_keyalg *keyalg; - ssh_key *key; - strbuf *sigdata; - - s->this_method = AUTHMETHOD_PUBLICKEY; - if (!(s->methods & s->this_method)) - goto failure; - - has_signature = get_bool(pktin); - algorithm = get_string(pktin); - blob = get_string(pktin); - - key_really_ok = auth_publickey(s->authpolicy, s->username, blob); - send_pk_ok = key_really_ok || - s->ssc->stunt_pretend_to_accept_any_pubkey; - - if (!has_signature) { - if (!send_pk_ok) - goto failure; - - pktout = ssh_bpp_new_pktout( - s->ppl.bpp, SSH2_MSG_USERAUTH_PK_OK); - put_stringpl(pktout, algorithm); - put_stringpl(pktout, blob); - pq_push(s->ppl.out_pq, pktout); - continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */ - } - - if (!key_really_ok) - goto failure; - - keyalg = find_pubkey_alg_len(algorithm); - if (!keyalg) - goto failure; - key = ssh_key_new_pub(keyalg, blob); - if (!key) - goto failure; - - sigdata = strbuf_new(); - ssh2_userauth_server_add_session_id(s, sigdata); - put_byte(sigdata, SSH2_MSG_USERAUTH_REQUEST); - put_stringpl(sigdata, s->username); - put_stringpl(sigdata, s->service); - put_stringpl(sigdata, s->method); - put_bool(sigdata, has_signature); - put_stringpl(sigdata, algorithm); - put_stringpl(sigdata, blob); - - signature = get_string(pktin); - success = ssh_key_verify(key, signature, - ptrlen_from_strbuf(sigdata)); - ssh_key_free(key); - strbuf_free(sigdata); - - if (!success) - goto failure; - } else if (ptrlen_eq_string(s->method, "keyboard-interactive")) { - int i, ok; - unsigned n; - - s->this_method = AUTHMETHOD_KBDINT; - if (!(s->methods & s->this_method)) - goto failure; - - do { - s->aki = auth_kbdint_prompts(s->authpolicy, s->username); - if (!s->aki) - goto failure; - - pktout = ssh_bpp_new_pktout( - s->ppl.bpp, SSH2_MSG_USERAUTH_INFO_REQUEST); - put_stringz(pktout, s->aki->title); - put_stringz(pktout, s->aki->instruction); - put_stringz(pktout, ""); /* language tag */ - put_uint32(pktout, s->aki->nprompts); - for (i = 0; i < s->aki->nprompts; i++) { - put_stringz(pktout, s->aki->prompts[i].prompt); - put_bool(pktout, s->aki->prompts[i].echo); - } - pq_push(s->ppl.out_pq, pktout); - - crMaybeWaitUntilV( - (pktin = ssh2_userauth_server_pop(s)) != NULL); - if (pktin->type != SSH2_MSG_USERAUTH_INFO_RESPONSE) { - ssh_proto_error( - s->ppl.ssh, "Received unexpected packet when " - "expecting USERAUTH_INFO_RESPONSE, type %d (%s)", - pktin->type, - ssh2_pkt_type(s->ppl.bpp->pls->kctx, - s->ppl.bpp->pls->actx, pktin->type)); - return; - } - - n = get_uint32(pktin); - if (n != s->aki->nprompts) { - ssh_proto_error( - s->ppl.ssh, "Received %u keyboard-interactive " - "responses after sending %u prompts", - n, s->aki->nprompts); - return; - } - - { - ptrlen *responses = snewn(s->aki->nprompts, ptrlen); - for (i = 0; i < s->aki->nprompts; i++) - responses[i] = get_string(pktin); - ok = auth_kbdint_responses(s->authpolicy, responses); - sfree(responses); - } - - free_auth_kbdint(s->aki); - s->aki = NULL; - } while (ok == 0); - - if (ok <= 0) - goto failure; - } else { - goto failure; - } - - /* - * If we get here, we've successfully completed this - * authentication step. - */ - if (auth_successful(s->authpolicy, s->username, s->this_method)) { - /* - * ... and it was the last one, so we're completely done. - */ - pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_SUCCESS); - pq_push(s->ppl.out_pq, pktout); - break; - } else { - /* - * ... but another is required, so fall through to - * generation of USERAUTH_FAILURE, having first refreshed - * the bit mask of available methods. - */ - s->methods = auth_methods(s->authpolicy); - } - s->partial_success = true; - - failure: - pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_FAILURE); - { - strbuf *list = strbuf_new(); - if (s->methods & AUTHMETHOD_NONE) - add_to_commasep(list, "none"); - if (s->methods & AUTHMETHOD_PASSWORD) - add_to_commasep(list, "password"); - if (s->methods & AUTHMETHOD_PUBLICKEY) - add_to_commasep(list, "publickey"); - if (s->methods & AUTHMETHOD_KBDINT) - add_to_commasep(list, "keyboard-interactive"); - put_stringsb(pktout, list); - } - put_bool(pktout, s->partial_success); - pq_push(s->ppl.out_pq, pktout); - } - - /* - * Finally, hand over to our successor layer, and return - * immediately without reaching the crFinishV: ssh_ppl_replace - * will have freed us, so crFinishV's zeroing-out of crState would - * be a use-after-free bug. - */ - { - PacketProtocolLayer *successor = s->successor_layer; - s->successor_layer = NULL; /* avoid freeing it ourself */ - ssh_ppl_replace(&s->ppl, successor); - return; /* we've just freed s, so avoid even touching s->crState */ - } - - crFinishV; -} |