diff options
-rw-r--r-- | channel.h | 18 | ||||
-rw-r--r-- | cli-chansession.c | 12 | ||||
-rw-r--r-- | cli-main.c | 3 | ||||
-rw-r--r-- | cli-tcpfwd.c | 4 | ||||
-rw-r--r-- | common-channel.c | 17 | ||||
-rw-r--r-- | common-session.c | 48 | ||||
-rw-r--r-- | dbutil.h | 6 | ||||
-rw-r--r-- | session.h | 6 | ||||
-rw-r--r-- | svr-chansession.c | 7 | ||||
-rw-r--r-- | svr-tcpfwd.c | 6 | ||||
-rw-r--r-- | svr-x11fwd.c | 7 | ||||
-rw-r--r-- | tcp-accept.c | 8 | ||||
-rw-r--r-- | tcpfwd.h | 3 |
13 files changed, 120 insertions, 25 deletions
@@ -29,14 +29,6 @@ #include "buffer.h" #include "circbuffer.h" -/* channel->type values */ -#define CHANNEL_ID_NONE 0 -#define CHANNEL_ID_SESSION 1 -#define CHANNEL_ID_X11 2 -#define CHANNEL_ID_AGENT 3 -#define CHANNEL_ID_TCPDIRECT 4 -#define CHANNEL_ID_TCPFORWARDED 5 - #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH_OPEN_CONNECT_FAILED 2 #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3 @@ -49,6 +41,13 @@ struct ChanType; +enum dropbear_channel_prio { + DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */ + DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */ + DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */ + DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */ +}; + struct Channel { unsigned int index; /* the local channel index */ @@ -87,6 +86,8 @@ struct Channel { void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len); const struct ChanType* type; + + enum dropbear_channel_prio prio; }; struct ChanType { @@ -97,7 +98,6 @@ struct ChanType { int (*check_close)(struct Channel*); void (*reqhandler)(struct Channel*); void (*closehandler)(struct Channel*); - }; void chaninitialise(const struct ChanType *chantypes[]); diff --git a/cli-chansession.c b/cli-chansession.c index fa97a6a..c16443e 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -41,7 +41,7 @@ static void cli_chansessreq(struct Channel *channel); static void send_chansess_pty_req(struct Channel *channel); static void send_chansess_shell_req(struct Channel *channel); static void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len); - +static int cli_init_netcat(struct Channel *channel); static void cli_tty_setup(); @@ -357,6 +357,11 @@ static int cli_init_stdpipe_sess(struct Channel *channel) { return 0; } +static int cli_init_netcat(struct Channel *channel) { + channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; + return cli_init_stdpipe_sess(channel); +} + static int cli_initchansess(struct Channel *channel) { cli_init_stdpipe_sess(channel); @@ -369,8 +374,9 @@ static int cli_initchansess(struct Channel *channel) { if (cli_opts.wantpty) { send_chansess_pty_req(channel); + channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE; } else { - set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK); + channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; } send_chansess_shell_req(channel); @@ -389,7 +395,7 @@ static int cli_initchansess(struct Channel *channel) { static const struct ChanType cli_chan_netcat = { 0, /* sepfds */ "direct-tcpip", - cli_init_stdpipe_sess, /* inithandler */ + cli_init_netcat, /* inithandler */ NULL, NULL, cli_closechansess @@ -75,9 +75,6 @@ int main(int argc, char ** argv) { int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 0, &error); sock_in = sock_out = sock; - if (cli_opts.wantpty) { - set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY); - } } if (sock_in < 0) { diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c index c83c7cb..fa61d13 100644 --- a/cli-tcpfwd.c +++ b/cli-tcpfwd.c @@ -52,7 +52,7 @@ static int cli_localtcp(const char* listenaddr, static const struct ChanType cli_chan_tcplocal = { 1, /* sepfds */ "direct-tcpip", - NULL, + tcp_prio_inithandler, NULL, NULL, NULL @@ -267,6 +267,8 @@ static int newtcpforwarded(struct Channel * channel) { * progress succeeds */ channel->writefd = sock; channel->initconn = 1; + + channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; err = SSH_OPEN_IN_PROGRESS; diff --git a/common-channel.c b/common-channel.c index 61b1120..1003896 100644 --- a/common-channel.c +++ b/common-channel.c @@ -174,6 +174,8 @@ static struct Channel* newchannel(unsigned int remotechan, newchan->recvdonelen = 0; newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN; + newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */ + ses.channels[i] = newchan; ses.chancount++; @@ -595,6 +597,8 @@ static void remove_channel(struct Channel * channel) { m_free(channel); ses.chancount--; + update_channel_prio(); + TRACE(("leave remove_channel")) } @@ -885,6 +889,10 @@ void recv_msg_channel_open() { } } + if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { + channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; + } + chan_initwritebuf(channel); /* success */ @@ -898,6 +906,8 @@ failure: cleanup: m_free(type); + + update_channel_prio(); TRACE(("leave recv_msg_channel_open")) } @@ -1013,7 +1023,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) { * for X11, agent, tcp forwarding, and should be filled with channel-specific * options, with the calling function calling encrypt_packet() after * completion. It is mandatory for the caller to encrypt_packet() if - * DROPBEAR_SUCCESS is returned */ + * a channel is returned. NULL is returned on failure. */ int send_msg_channel_open_init(int fd, const struct ChanType *type) { struct Channel* chan; @@ -1082,6 +1092,10 @@ void recv_msg_channel_open_confirmation() { } } + if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { + channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; + } + update_channel_prio(); TRACE(("leave recv_msg_channel_open_confirmation")) } @@ -1113,4 +1127,3 @@ void send_msg_request_failure() { buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE); encrypt_packet(); } - diff --git a/common-session.c b/common-session.c index a90673f..cebd787 100644 --- a/common-session.c +++ b/common-session.c @@ -59,6 +59,10 @@ void common_session_init(int sock_in, int sock_out) { ses.sock_out = sock_out; ses.maxfd = MAX(sock_in, sock_out); + ses.socket_prio = DROPBEAR_PRIO_DEFAULT; + /* Sets it to lowdelay */ + update_channel_prio(); + now = monotonic_now(); ses.last_packet_time_keepalive_recv = now; ses.last_packet_time_idle = now; @@ -512,3 +516,47 @@ void fill_passwd(const char* username) { } } +/* Called when channels are modified */ +void update_channel_prio() { + enum dropbear_prio new_prio; + int any = 0; + unsigned int i; + + TRACE(("update_channel_prio")) + + new_prio = DROPBEAR_PRIO_BULK; + for (i = 0; i < ses.chansize; i++) { + struct Channel *channel = ses.channels[i]; + if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { + if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { + TRACE(("update_channel_prio: early %d", channel->index)) + } + continue; + } + any = 1; + if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE) + { + TRACE(("update_channel_prio: lowdelay %d", channel->index)) + new_prio = DROPBEAR_PRIO_LOWDELAY; + break; + } else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE + && new_prio == DROPBEAR_PRIO_BULK) + { + TRACE(("update_channel_prio: unknowable %d", channel->index)) + new_prio = DROPBEAR_PRIO_DEFAULT; + } + } + + if (any == 0) { + /* lowdelay during setup */ + TRACE(("update_channel_prio: not any")) + new_prio = DROPBEAR_PRIO_LOWDELAY; + } + + if (new_prio != ses.socket_prio) { + TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio)) + set_sock_priority(ses.sock_out, new_prio); + ses.socket_prio = new_prio; + } +} + @@ -62,9 +62,9 @@ extern int debug_trace; #endif enum dropbear_prio { - DROPBEAR_PRIO_DEFAULT, - DROPBEAR_PRIO_LOWDELAY, - DROPBEAR_PRIO_BULK, + DROPBEAR_PRIO_DEFAULT = 'dffd', + DROPBEAR_PRIO_LOWDELAY = 'lddl', + DROPBEAR_PRIO_BULK = 'bllb', }; char * stripcontrol(const char * text); @@ -48,6 +48,8 @@ void session_cleanup(); void send_session_identification(); void send_msg_ignore(); +void update_channel_prio(); + const char* get_user_shell(); void fill_passwd(const char* username); @@ -186,7 +188,9 @@ struct sshsession { unsigned int chancount; /* the number of Channel*s in use */ const struct ChanType **chantypes; /* The valid channel types */ - + /* TCP priority level for the main "port 22" tcp socket */ + enum dropbear_prio socket_prio; + /* TCP forwarding - where manage listeners */ struct Listener ** listeners; unsigned int listensize; diff --git a/svr-chansession.c b/svr-chansession.c index 63e56a8..4b45294 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -253,6 +253,8 @@ static int newchansess(struct Channel *channel) { chansess->agentdir = NULL; #endif + channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE; + return 0; } @@ -668,8 +670,11 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, if (chansess->term == NULL) { /* no pty */ - set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK); ret = noptycommand(channel, chansess); + if (ret == DROPBEAR_SUCCESS) { + channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; + update_channel_prio(); + } } else { /* want pty */ ret = ptycommand(channel, chansess); diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c index 7033a65..e5f219e 100644 --- a/svr-tcpfwd.c +++ b/svr-tcpfwd.c @@ -53,7 +53,7 @@ static int newtcpdirect(struct Channel * channel); static const struct ChanType svr_chan_tcpremote = { 1, /* sepfds */ "forwarded-tcpip", - NULL, + tcp_prio_inithandler, NULL, NULL, NULL @@ -240,6 +240,8 @@ static int newtcpdirect(struct Channel * channel) { int len; int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; + TRACE(("newtcpdirect channel %d", channel->index)) + if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) { TRACE(("leave newtcpdirect: local tcp forwarding disabled")) goto out; @@ -281,6 +283,8 @@ static int newtcpdirect(struct Channel * channel) { * progress succeeds */ channel->writefd = sock; channel->initconn = 1; + + channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; err = SSH_OPEN_IN_PROGRESS; diff --git a/svr-x11fwd.c b/svr-x11fwd.c index f6368d7..ceca26a 100644 --- a/svr-x11fwd.c +++ b/svr-x11fwd.c @@ -182,10 +182,15 @@ void x11cleanup(struct ChanSess *chansess) { } } +static int x11_inithandler(struct Channel *channel) { + channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE; + return 0; +} + static const struct ChanType chan_x11 = { 0, /* sepfds */ "x11", - NULL, /* inithandler */ + x11_inithandler, /* inithandler */ NULL, /* checkclose */ NULL, /* reqhandler */ NULL /* closehandler */ diff --git a/tcp-accept.c b/tcp-accept.c index bb7c5e3..35be32d 100644 --- a/tcp-accept.c +++ b/tcp-accept.c @@ -30,6 +30,7 @@ #include "buffer.h" #include "packet.h" #include "listener.h" +#include "listener.h" #include "runopts.h" #ifdef DROPBEAR_TCP_ACCEPT @@ -44,6 +45,13 @@ static void cleanup_tcp(struct Listener *listener) { m_free(tcpinfo); } +int tcp_prio_inithandler(struct Channel* channel) +{ + TRACE(("tcp_prio_inithandler channel %d", channel->index)) + channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; + return 0; +} + static void tcp_acceptor(struct Listener *listener, int sock) { int fd; @@ -70,5 +70,8 @@ void cli_recv_msg_request_failure(); /* Common */ int listen_tcpfwd(struct TCPListener* tcpinfo); +int tcp_prio_inithandler(struct Channel* chan); + +#define CHANNEL_ID_TCPFORWARDED 'tcpf' #endif |