Mercurial > dropbear
diff common-session.c @ 1069:2fa71c3b2827 pam
merge pam branch up to date
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 16 Mar 2015 21:34:05 +0800 |
parents | 9a6395ddb1b6 4c733310c21d |
children | 16379795f80b |
line wrap: on
line diff
--- a/common-session.c Fri Jan 23 22:32:49 2015 +0800 +++ b/common-session.c Mon Mar 16 21:34:05 2015 +0800 @@ -34,6 +34,7 @@ #include "kex.h" #include "channel.h" #include "runopts.h" +#include "netio.h" static void checktimeouts(); static long select_timeout(); @@ -53,6 +54,10 @@ void common_session_init(int sock_in, int sock_out) { time_t now; +#ifdef DEBUG_TRACE + debug_start_net(); +#endif + TRACE(("enter session_init")) ses.sock_in = sock_in; @@ -150,8 +155,10 @@ FD_ZERO(&readfd); dropbear_assert(ses.payload == NULL); - /* during initial setup we flush out the KEXINIT packet before - * attempting to read the remote version string, which might block */ + /* We delay reading from the input socket during initial setup until + after we have written out our initial KEXINIT packet (empty writequeue). + This means our initial packet can be in-flight while we're doing a blocking + read for the remote ident */ if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { FD_SET(ses.sock_in, &readfd); } @@ -166,6 +173,9 @@ /* set up for channels which can be read/written */ setchannelfds(&readfd, &writefd); + /* Pending connections to test */ + set_connect_fds(&writefd); + val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); if (exitflag) { @@ -213,11 +223,13 @@ process_packet(); } } - + /* if required, flush out any queued reply packets that were being held up during a KEX */ maybe_flush_reply_queue(); + handle_connect_fds(&writefd); + /* process pipes etc for the channels, ses.dataallowed == 0 * during rekeying ) */ channelio(&readfd, &writefd); @@ -239,6 +251,15 @@ ses.exit_recursion = 0; } +static void cleanup_buf(buffer **buf) { + if (!*buf) { + return; + } + buf_burn(*buf); + buf_free(*buf); + *buf = NULL; +} + /* clean up a session on exit */ void session_cleanup() { @@ -250,24 +271,47 @@ return; } + /* Beware of changing order of functions here. */ + + /* Must be before extra_session_cleanup() */ + chancleanup(); + if (ses.extra_session_cleanup) { ses.extra_session_cleanup(); } - chancleanup(); - - /* Cleaning up keys must happen after other cleanup - functions which might queue packets */ - if (ses.session_id) { - buf_burn(ses.session_id); - buf_free(ses.session_id); - ses.session_id = NULL; + /* After these are freed most functions will exit */ +#ifdef DROPBEAR_CLEANUP + /* listeners call cleanup functions, this should occur before + other session state is freed. */ + remove_all_listeners(); + + remove_connect_pending(); + + while (!isempty(&ses.writequeue)) { + buf_free(dequeue(&ses.writequeue)); } - if (ses.hash) { - buf_burn(ses.hash); - buf_free(ses.hash); - ses.hash = NULL; + + m_free(ses.remoteident); + m_free(ses.authstate.pw_dir); + m_free(ses.authstate.pw_name); + m_free(ses.authstate.pw_shell); + m_free(ses.authstate.pw_passwd); + m_free(ses.authstate.username); +#endif + + cleanup_buf(&ses.session_id); + cleanup_buf(&ses.hash); + cleanup_buf(&ses.payload); + cleanup_buf(&ses.readbuf); + cleanup_buf(&ses.writepayload); + cleanup_buf(&ses.kexhashbuf); + cleanup_buf(&ses.transkexinit); + if (ses.dh_K) { + mp_clear(ses.dh_K); } + m_free(ses.dh_K); + m_burn(ses.keys, sizeof(struct key_context)); m_free(ses.keys); @@ -398,15 +442,15 @@ } void ignore_recv_response() { - // Do nothing + /* Do nothing */ TRACE(("Ignored msg_request_response")) } static void send_msg_keepalive() { + time_t old_time_idle = ses.last_packet_time_idle; + struct Channel *chan = get_any_ready_channel(); + CHECKCLEARTOWRITE(); - time_t old_time_idle = ses.last_packet_time_idle; - - struct Channel *chan = get_any_ready_channel(); if (chan) { /* Channel requests are preferable, more implementations @@ -546,6 +590,11 @@ TRACE(("update_channel_prio")) + if (ses.sock_out < 0) { + TRACE(("leave update_channel_prio: no socket")) + return; + } + new_prio = DROPBEAR_PRIO_BULK; for (i = 0; i < ses.chansize; i++) { struct Channel *channel = ses.channels[i]; @@ -576,7 +625,7 @@ } if (new_prio != ses.socket_prio) { - TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio)) + TRACE(("Dropbear priority transitioning %d -> %d", ses.socket_prio, new_prio)) set_sock_priority(ses.sock_out, new_prio); ses.socket_prio = new_prio; }