- Progress for allowing specifying a listenaddr for tcp forwards

--HG--
extra : convert_revision : 48fdaa8706d1acda35e9d564adc9a1fbc96c18c8
This commit is contained in:
Matt Johnston 2010-02-24 16:13:15 +00:00
parent 3dbc707820
commit 85288d7b61
5 changed files with 88 additions and 45 deletions

View File

@ -564,13 +564,15 @@ static void fill_own_user() {
} }
#ifdef ENABLE_CLI_ANYTCPFWD #ifdef ENABLE_CLI_ANYTCPFWD
/* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding /* Turn a "[listenaddr:]listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */ * set, and add it to the forwarding list */
static void addforward(const char* origstr, struct TCPFwdList** fwdlist) { static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
char *part1 = NULL, *part2 = NULL, *part3 = NULL, *part4 = NULL;
char * listenaddr = NULL;
char * listenport = NULL; char * listenport = NULL;
char * connectport = NULL;
char * connectaddr = NULL; char * connectaddr = NULL;
char * connectport = NULL;
struct TCPFwdList* newfwd = NULL; struct TCPFwdList* newfwd = NULL;
char * str = NULL; char * str = NULL;
@ -580,23 +582,41 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
is never free()d. */ is never free()d. */
str = m_strdup(origstr); str = m_strdup(origstr);
listenport = str; part1 = str;
connectaddr = strchr(str, ':'); part2 = strchr(str, ':');
if (connectaddr == NULL) { if (part2 == NULL) {
TRACE(("connectaddr == NULL")) TRACE(("part2 == NULL"))
goto fail; goto fail;
} }
*connectaddr = '\0'; *part2 = '\0';
connectaddr++; part2++;
connectport = strchr(connectaddr, ':'); part3 = strchr(part2, ':');
if (connectport == NULL) { if (part3 == NULL) {
TRACE(("connectport == NULL")) TRACE(("part3 == NULL"))
goto fail; goto fail;
} }
*connectport = '\0'; *part3 = '\0';
connectport++; part3++;
part4 = strchr(part3, ':');
if (part4) {
*part4 = '\0';
part4++;
}
if (part4) {
listenaddr = part1;
listenport = part2;
connectaddr = part3;
connectport = part4;
} else {
listenaddr = NULL;
listenport = part1;
connectaddr = part2;
connectport = part3;
}
newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList)); newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList));
@ -612,6 +632,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
goto fail; goto fail;
} }
newfwd->listenaddr = listenaddr;
newfwd->connectaddr = connectaddr; newfwd->connectaddr = connectaddr;
if (newfwd->listenport > 65535) { if (newfwd->listenport > 65535) {

View File

@ -45,7 +45,9 @@ const struct ChanType cli_chan_tcpremote = {
#endif #endif
#ifdef ENABLE_CLI_LOCALTCPFWD #ifdef ENABLE_CLI_LOCALTCPFWD
static int cli_localtcp(unsigned int listenport, const char* remoteaddr, static int cli_localtcp(const char* listenaddr,
unsigned int listenport,
const char* remoteaddr,
unsigned int remoteport); unsigned int remoteport);
static const struct ChanType cli_chan_tcplocal = { static const struct ChanType cli_chan_tcplocal = {
1, /* sepfds */ 1, /* sepfds */
@ -69,11 +71,14 @@ void setup_localtcp() {
} }
while (cli_opts.localfwds != NULL) { while (cli_opts.localfwds != NULL) {
ret = cli_localtcp(cli_opts.localfwds->listenport, ret = cli_localtcp(
cli_opts.localfwds->listenaddr,
cli_opts.localfwds->listenport,
cli_opts.localfwds->connectaddr, cli_opts.localfwds->connectaddr,
cli_opts.localfwds->connectport); cli_opts.localfwds->connectport);
if (ret == DROPBEAR_FAILURE) { if (ret == DROPBEAR_FAILURE) {
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
cli_opts.localfwds->listenaddr,
cli_opts.localfwds->listenport, cli_opts.localfwds->listenport,
cli_opts.localfwds->connectaddr, cli_opts.localfwds->connectaddr,
cli_opts.localfwds->connectport); cli_opts.localfwds->connectport);
@ -85,7 +90,9 @@ void setup_localtcp() {
} }
static int cli_localtcp(unsigned int listenport, const char* remoteaddr, static int cli_localtcp(const char* listenaddr,
unsigned int listenport,
const char* remoteaddr,
unsigned int remoteport) { unsigned int remoteport) {
struct TCPListener* tcpinfo = NULL; struct TCPListener* tcpinfo = NULL;
@ -99,10 +106,17 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
tcpinfo->sendaddr = m_strdup(remoteaddr); tcpinfo->sendaddr = m_strdup(remoteaddr);
tcpinfo->sendport = remoteport; tcpinfo->sendport = remoteport;
if (opts.listen_fwd_all) { if (listenaddr)
tcpinfo->listenaddr = m_strdup(""); {
} else { tcpinfo->listenaddr = m_strdup(listenaddr);
tcpinfo->listenaddr = m_strdup("localhost"); }
else
{
if (opts.listen_fwd_all) {
tcpinfo->listenaddr = m_strdup("");
} else {
tcpinfo->listenaddr = m_strdup("localhost");
}
} }
tcpinfo->listenport = listenport; tcpinfo->listenport = listenport;
@ -120,7 +134,7 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
#endif /* ENABLE_CLI_LOCALTCPFWD */ #endif /* ENABLE_CLI_LOCALTCPFWD */
#ifdef ENABLE_CLI_REMOTETCPFWD #ifdef ENABLE_CLI_REMOTETCPFWD
static void send_msg_global_request_remotetcp(int port) { static void send_msg_global_request_remotetcp(const char *addr, int port) {
char* listenspec = NULL; char* listenspec = NULL;
TRACE(("enter send_msg_global_request_remotetcp")) TRACE(("enter send_msg_global_request_remotetcp"))
@ -129,13 +143,7 @@ static void send_msg_global_request_remotetcp(int port) {
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
buf_putstring(ses.writepayload, "tcpip-forward", 13); buf_putstring(ses.writepayload, "tcpip-forward", 13);
buf_putbyte(ses.writepayload, 1); /* want_reply */ buf_putbyte(ses.writepayload, 1); /* want_reply */
if (opts.listen_fwd_all) { buf_putstring(ses.writepayload, addr, strlen(addr));
listenspec = "";
} else {
listenspec = "localhost";
}
/* TODO: IPv6? */;
buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
buf_putint(ses.writepayload, port); buf_putint(ses.writepayload, port);
encrypt_packet(); encrypt_packet();
@ -192,7 +200,17 @@ void setup_remotetcp() {
iter = cli_opts.remotefwds; iter = cli_opts.remotefwds;
while (iter != NULL) { while (iter != NULL) {
send_msg_global_request_remotetcp(iter->listenport); if (!iter->listenaddr)
{
// we store the addresses so that we can compare them
// when the server sends them back
if (opts.listen_fwd_all) {
iter->listenaddr = m_strdup("");
} else {
iter->listenaddr = m_strdup("localhost");
}
}
send_msg_global_request_remotetcp(iter->listenaddr, iter->listenport);
iter = iter->next; iter = iter->next;
} }
TRACE(("leave setup_remotetcp")) TRACE(("leave setup_remotetcp"))
@ -200,22 +218,22 @@ void setup_remotetcp() {
static int newtcpforwarded(struct Channel * channel) { static int newtcpforwarded(struct Channel * channel) {
char *origaddr = NULL;
unsigned int origport; unsigned int origport;
struct TCPFwdList * iter = NULL; struct TCPFwdList * iter = NULL;
char portstring[NI_MAXSERV]; char portstring[NI_MAXSERV];
int sock; int sock;
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
/* We don't care what address they connected to */ origaddr = buf_getstring(ses.payload, NULL);
buf_eatstring(ses.payload);
origport = buf_getint(ses.payload); origport = buf_getint(ses.payload);
/* Find which port corresponds */ /* Find which port corresponds */
iter = cli_opts.remotefwds; iter = cli_opts.remotefwds;
while (iter != NULL) { while (iter != NULL) {
if (origport == iter->listenport) { if (origport == iter->listenport
&& (strcmp(origaddr, iter->listenaddr) == 0)) {
break; break;
} }
iter = iter->next; iter = iter->next;
@ -223,8 +241,9 @@ static int newtcpforwarded(struct Channel * channel) {
if (iter == NULL) { if (iter == NULL) {
/* We didn't request forwarding on that port */ /* We didn't request forwarding on that port */
dropbear_log(LOG_INFO, "Server send unrequested port, from port %d", cleantext(origaddr);
origport); dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"",
origaddr, origport);
goto out; goto out;
} }
@ -246,6 +265,7 @@ static int newtcpforwarded(struct Channel * channel) {
err = SSH_OPEN_IN_PROGRESS; err = SSH_OPEN_IN_PROGRESS;
out: out:
m_free(origaddr);
TRACE(("leave newtcpdirect: err %d", err)) TRACE(("leave newtcpdirect: err %d", err))
return err; return err;
} }

View File

@ -206,11 +206,20 @@ static int svr_remotetcpreq() {
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
tcpinfo->sendaddr = NULL; tcpinfo->sendaddr = NULL;
tcpinfo->sendport = 0; tcpinfo->sendport = 0;
tcpinfo->listenaddr = bindaddr;
tcpinfo->listenport = port; tcpinfo->listenport = port;
tcpinfo->chantype = &svr_chan_tcpremote; tcpinfo->chantype = &svr_chan_tcpremote;
tcpinfo->tcp_type = forwarded; tcpinfo->tcp_type = forwarded;
if (!opts.listen_fwd_all
|| (strcmp(tcpinfo->listenaddr, "localhost") == 0) ) {
// NULL means "localhost only"
tcpinfo->listenaddr = NULL;
}
else
{
tcpinfo->listenaddr = bindaddr;
}
ret = listen_tcpfwd(tcpinfo); ret = listen_tcpfwd(tcpinfo);
out: out:

View File

@ -104,21 +104,13 @@ int listen_tcpfwd(struct TCPListener* tcpinfo) {
struct Listener *listener = NULL; struct Listener *listener = NULL;
int nsocks; int nsocks;
char* errstring = NULL; char* errstring = NULL;
/* listen_spec = NULL indicates localhost */
const char* listen_spec = NULL;
TRACE(("enter listen_tcpfwd")) TRACE(("enter listen_tcpfwd"))
/* first we try to bind, so don't need to do so much cleanup on failure */ /* first we try to bind, so don't need to do so much cleanup on failure */
snprintf(portstring, sizeof(portstring), "%d", tcpinfo->listenport); snprintf(portstring, sizeof(portstring), "%d", tcpinfo->listenport);
/* a listenaddr of "" will indicate all interfaces */ nsocks = dropbear_listen(tcpinfo->listenaddr, portstring, socks,
if (opts.listen_fwd_all
&& (strcmp(tcpinfo->listenaddr, "localhost") != 0) ) {
listen_spec = tcpinfo->listenaddr;
}
nsocks = dropbear_listen(listen_spec, portstring, socks,
DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd); DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd);
if (nsocks < 0) { if (nsocks < 0) {
dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring); dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring);

View File

@ -48,6 +48,7 @@ struct TCPFwdList {
const unsigned char* connectaddr; const unsigned char* connectaddr;
unsigned int connectport; unsigned int connectport;
const unsigned char* listenaddr;
unsigned int listenport; unsigned int listenport;
unsigned int have_reply; /* is set to 1 after a reply has been received unsigned int have_reply; /* is set to 1 after a reply has been received
when setting up the forwarding */ when setting up the forwarding */