summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2005-12-04 16:13:11 +0000
committerMatt Johnston <matt@ucc.asn.au>2005-12-04 16:13:11 +0000
commita673d609639b180eee3a4ba49d7f07d0239ea666 (patch)
treecc1c3b4f3d9d52b79861942a360bca266e98bdcb
parent736f370dce614b717193f45d084e9e009de723ce (diff)
* add -g (dbclient) and -a (dropbear) options for allowing non-local
hosts to connect to forwarded ports. Rearranged various some of the tcp listening code. * changed to /* */ style brackets in svr-authpam.c --HG-- extra : convert_revision : c1e04e648867db464fe9818c4910e4320cd50c32
-rw-r--r--cli-runopts.c9
-rw-r--r--cli-tcpfwd.c17
-rw-r--r--dbclient.15
-rw-r--r--dbutil.c17
-rw-r--r--dropbear.83
-rw-r--r--runopts.h14
-rw-r--r--svr-authpam.c20
-rw-r--r--svr-main.c2
-rw-r--r--svr-runopts.c21
-rw-r--r--svr-tcpfwd.c24
-rw-r--r--tcp-accept.c24
-rw-r--r--tcpfwd.h11
12 files changed, 111 insertions, 56 deletions
diff --git a/cli-runopts.c b/cli-runopts.c
index 285c51d..54d4875 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -47,6 +47,7 @@ static void printhelp() {
"Usage: %s [options] [user@]host\n"
"Options are:\n"
"-p <remoteport>\n"
+ "-l <username>\n"
"-t Allocate a pty\n"
"-T Don't allocate a pty\n"
#ifdef ENABLE_CLI_PUBKEY_AUTH
@@ -54,11 +55,11 @@ static void printhelp() {
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
"-L <listenport:remotehost:remoteport> Local port forwarding\n"
+ "-g Allow remote hosts to connect to forwarded ports\n"
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
"-R <listenport:remotehost:remoteport> Remote port forwarding\n"
#endif
- "-l <username>\n"
#ifdef DEBUG_TRACE
"-v verbose\n"
#endif
@@ -93,12 +94,11 @@ void cli_getopts(int argc, char ** argv) {
#endif
#ifdef ENABLE_CLI_LOCALTCPFWD
cli_opts.localfwds = NULL;
+ opts.listen_fwd_all = 0;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
cli_opts.remotefwds = NULL;
#endif
- opts.nolocaltcp = 0;
- opts.noremotetcp = 0;
/* not yet
opts.ipv4 = 1;
opts.ipv6 = 1;
@@ -167,6 +167,9 @@ void cli_getopts(int argc, char ** argv) {
case 'L':
nextislocal = 1;
break;
+ case 'g':
+ opts.listen_fwd_all = 1;
+ break;
#endif
#ifdef ENABLE_CLI_REMOTETCPFWD
case 'R':
diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c
index 6832cbf..d8f1da6 100644
--- a/cli-tcpfwd.c
+++ b/cli-tcpfwd.c
@@ -95,9 +95,17 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
remoteport));
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
+
tcpinfo->sendaddr = m_strdup(remoteaddr);
tcpinfo->sendport = remoteport;
+
+ if (opts.listen_fwd_all) {
+ tcpinfo->listenaddr = m_strdup("");
+ } else {
+ tcpinfo->listenaddr = m_strdup("localhost");
+ }
tcpinfo->listenport = listenport;
+
tcpinfo->chantype = &cli_chan_tcplocal;
ret = listen_tcpfwd(tcpinfo);
@@ -113,13 +121,20 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
#ifdef ENABLE_CLI_REMOTETCPFWD
static void send_msg_global_request_remotetcp(int port) {
+ char* listenspec = NULL;
TRACE(("enter send_msg_global_request_remotetcp"))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
buf_putstring(ses.writepayload, "tcpip-forward", 13);
buf_putbyte(ses.writepayload, 0);
- buf_putstring(ses.writepayload, "0.0.0.0", 7); /* TODO: IPv6? */
+ if (opts.listen_fwd_all) {
+ listenspec = "";
+ } else {
+ listenspec = "localhost";
+ }
+ /* TODO: IPv6? */;
+ buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
buf_putint(ses.writepayload, port);
encrypt_packet();
diff --git a/dbclient.1 b/dbclient.1
index fc6f0d0..4d7cc3c 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -59,6 +59,11 @@ Allocate a pty.
.TP
.B \-T
Don't allocate a pty.
+.TP
+.B \-g
+Allow non-local hosts to connect to forwarded ports. Applies to -L and -R
+forwarded ports, though remote connections to -R forwarded ports may be limited
+by the ssh server.
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
diff --git a/dbutil.c b/dbutil.c
index 3067d5f..696bac3 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -177,8 +177,9 @@ static void set_sock_priority(int sock) {
}
-/* Listen on address:port. Unless address is NULL, in which case listen on
- * everything. If called with address == "", we'll listen on localhost/loopback.
+/* Listen on address:port.
+ * Special cases are address of "" listening on everything,
+ * and address of NULL listening on localhost only.
* Returns the number of sockets bound on success, or -1 on failure. On
* failure, if errstring wasn't NULL, it'll be a newly malloced error
* string.*/
@@ -198,11 +199,17 @@ int dropbear_listen(const char* address, const char* port,
hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
hints.ai_socktype = SOCK_STREAM;
- if (address && address[0] == '\0') {
+ // for calling getaddrinfo:
+ // address == NULL and !AI_PASSIVE: local loopback
+ // address == NULL and AI_PASSIVE: all interfaces
+ // address != NULL: whatever the address says
+ if (!address) {
TRACE(("dropbear_listen: local loopback"))
- address = NULL;
} else {
- TRACE(("dropbear_listen: not local loopback"))
+ if (address[0] == '\0') {
+ TRACE(("dropbear_listen: all interfaces"))
+ address = NULL;
+ }
hints.ai_flags = AI_PASSIVE;
}
err = getaddrinfo(address, port, &hints, &res0);
diff --git a/dropbear.8 b/dropbear.8
index 1cf5c11..38cf7e2 100644
--- a/dropbear.8
+++ b/dropbear.8
@@ -71,6 +71,9 @@ Use this option to run
.B dropbear
under TCP/IP servers like inetd, tcpsvd, or tcpserver.
In program mode the \-F option is implied, and \-p options are ignored.
+.TP
+.B \-a
+Allow remote hosts to connect to forwarded ports.
.SH AUTHOR
Matt Johnston (matt@ucc.asn.au).
.br
diff --git a/runopts.h b/runopts.h
index 3d589e7..5107a9d 100644
--- a/runopts.h
+++ b/runopts.h
@@ -33,8 +33,9 @@
typedef struct runopts {
- int nolocaltcp;
- int noremotetcp;
+#if defined(ENABLE_SVR_REMOTETCPFWD) || defined(ENABLE_CLI_LOCALTCPFWD)
+ int listen_fwd_all;
+#endif
} runopts;
@@ -73,6 +74,13 @@ typedef struct svr_runopts {
int noauthpass;
int norootpass;
+#ifdef ENABLE_SVR_REMOTETCPFWD
+ int noremotetcp;
+#endif
+#ifdef ENABLE_SVR_LOCALTCPFWD
+ int nolocaltcp;
+#endif
+
sign_key *hostkey;
buffer * banner;
@@ -83,7 +91,6 @@ extern svr_runopts svr_opts;
void svr_getopts(int argc, char ** argv);
void loadhostkeys();
-/* Uncompleted XXX matt */
typedef struct cli_runopts {
char *progname;
@@ -103,7 +110,6 @@ typedef struct cli_runopts {
#ifdef ENABLE_CLI_LOCALTCPFWD
struct TCPFwdList * localfwds;
#endif
- /* XXX TODO */
} cli_runopts;
diff --git a/svr-authpam.c b/svr-authpam.c
index 985646a..4e257ae 100644
--- a/svr-authpam.c
+++ b/svr-authpam.c
@@ -59,7 +59,7 @@ pamConvFunc(int num_msg,
const char* message = (*msg)->msg;
- // make a copy we can strip
+ /* make a copy we can strip */
char * compare_message = m_strdup(message);
TRACE(("enter pamConvFunc"))
@@ -80,14 +80,14 @@ pamConvFunc(int num_msg,
}
- // Make the string lowercase.
+ /* Make the string lowercase. */
msg_len = strlen(compare_message);
for (i = 0; i < msg_len; i++) {
compare_message[i] = tolower(compare_message[i]);
}
- // If the string ends with ": ", remove the space.
- // ie "login: " vs "login:"
+ /* If the string ends with ": ", remove the space.
+ ie "login: " vs "login:" */
if (msg_len > 2
&& compare_message[msg_len-2] == ':'
&& compare_message[msg_len-1] == ' ') {
@@ -99,9 +99,9 @@ pamConvFunc(int num_msg,
case PAM_PROMPT_ECHO_OFF:
if (!(strcmp(compare_message, "password:") == 0)) {
- // We don't recognise the prompt as asking for a password,
- // so can't handle it. Add more above as required for
- // different pam modules/implementations
+ /* We don't recognise the prompt as asking for a password,
+ so can't handle it. Add more above as required for
+ different pam modules/implementations */
dropbear_log(LOG_NOTICE, "PAM unknown prompt %s (no echo)",
compare_message);
rc = PAM_CONV_ERR;
@@ -125,9 +125,9 @@ pamConvFunc(int num_msg,
if (!((strcmp(compare_message, "login:" ) == 0)
|| (strcmp(compare_message, "please enter username:") == 0))) {
- // We don't recognise the prompt as asking for a username,
- // so can't handle it. Add more above as required for
- // different pam modules/implementations
+ /* We don't recognise the prompt as asking for a username,
+ so can't handle it. Add more above as required for
+ different pam modules/implementations */
dropbear_log(LOG_NOTICE, "PAM unknown prompt %s (with echo)",
compare_message);
rc = PAM_CONV_ERR;
diff --git a/svr-main.c b/svr-main.c
index 46f6078..4641e24 100644
--- a/svr-main.c
+++ b/svr-main.c
@@ -375,7 +375,7 @@ static int listensockets(int *sock, int sockcount, int *maxfd) {
TRACE(("listening on '%s'", svr_opts.ports[i]))
- nsock = dropbear_listen(NULL, svr_opts.ports[i], &sock[sockpos],
+ nsock = dropbear_listen("", svr_opts.ports[i], &sock[sockpos],
sockcount - sockpos,
&errstring, maxfd);
diff --git a/svr-runopts.c b/svr-runopts.c
index 375797b..6c42fb4 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -63,13 +63,14 @@ static void printhelp(const char * progname) {
"-s Disable password logins\n"
"-g Disable password logins for root\n"
#endif
-#ifndef DISABLE_LOCALTCPFWD
+#ifdef ENABLE_SVR_LOCALTCPFWD
"-j Disable local port forwarding\n"
#endif
-#ifndef DISABLE_REMOTETCPFWD
+#ifdef ENABLE_SVR_REMOTETCPFWD
"-k Disable remote port forwarding\n"
+ "-a Allow connections to forwarded ports from any host\n"
#endif
- "-p port Listen on specified tcp port, up to %d can be specified\n"
+ "-p port Listen on specified tcp port, up to %d can be specified\n"
" (default %s if none specified)\n"
#ifdef INETD_MODE
"-i Start for inetd\n"
@@ -104,8 +105,8 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.inetdmode = 0;
svr_opts.portcount = 0;
svr_opts.hostkey = NULL;
- opts.nolocaltcp = 0;
- opts.noremotetcp = 0;
+ svr_opts.nolocaltcp = 0;
+ svr_opts.noremotetcp = 0;
/* not yet
opts.ipv4 = 1;
opts.ipv6 = 1;
@@ -116,6 +117,9 @@ void svr_getopts(int argc, char ** argv) {
#ifndef DISABLE_SYSLOG
svr_opts.usingsyslog = 1;
#endif
+#ifdef ENABLE_SVR_REMOTETCPFWD
+ opts.listen_fwd_all = 0;
+#endif
for (i = 1; i < (unsigned int)argc; i++) {
if (next) {
@@ -152,12 +156,15 @@ void svr_getopts(int argc, char ** argv) {
#endif
#ifndef DISABLE_LOCALTCPFWD
case 'j':
- opts.nolocaltcp = 1;
+ svr_opts.nolocaltcp = 1;
break;
#endif
#ifndef DISABLE_REMOTETCPFWD
case 'k':
- opts.noremotetcp = 1;
+ svr_opts.noremotetcp = 1;
+ break;
+ case 'a':
+ opts.listen_fwd_all = 1;
break;
#endif
#ifdef INETD_MODE
diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c
index ecfaf2b..6e70d67 100644
--- a/svr-tcpfwd.c
+++ b/svr-tcpfwd.c
@@ -72,7 +72,7 @@ void recv_msg_global_request_remotetcp() {
TRACE(("enter recv_msg_global_request_remotetcp"))
- if (opts.noremotetcp) {
+ if (svr_opts.noremotetcp) {
TRACE(("leave recv_msg_global_request_remotetcp: remote tcp forwarding disabled"))
goto out;
}
@@ -129,9 +129,9 @@ static int matchtcp(void* typedata1, void* typedata2) {
const struct TCPListener *info1 = (struct TCPListener*)typedata1;
const struct TCPListener *info2 = (struct TCPListener*)typedata2;
- return (info1->sendport == info2->sendport)
+ return (info1->listenport == info2->listenport)
&& (info1->chantype == info2->chantype)
- && (strcmp(info1->sendaddr, info2->sendaddr) == 0);
+ && (strcmp(info1->listenaddr, info2->listenaddr) == 0);
}
static int svr_cancelremotetcp() {
@@ -153,8 +153,10 @@ static int svr_cancelremotetcp() {
port = buf_getint(ses.payload);
- tcpinfo.sendaddr = bindaddr;
- tcpinfo.sendport = port;
+ tcpinfo.sendaddr = NULL;
+ tcpinfo.sendport = 0;
+ tcpinfo.listenaddr = bindaddr;
+ tcpinfo.listenport = port;
listener = get_listener(CHANNEL_ID_TCPFORWARDED, &tcpinfo, matchtcp);
if (listener) {
remove_listener( listener );
@@ -177,7 +179,6 @@ static int svr_remotetcpreq() {
TRACE(("enter remotetcpreq"))
- /* NOTE: at this stage, we ignore bindaddr. see below and listen_tcpfwd */
bindaddr = buf_getstring(ses.payload, &addrlen);
if (addrlen > MAX_IP_LEN) {
TRACE(("addr len too long: %d", addrlen))
@@ -202,20 +203,19 @@ static int svr_remotetcpreq() {
}
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
- tcpinfo->sendaddr = bindaddr;
- tcpinfo->sendport = port;
+ tcpinfo->sendaddr = NULL;
+ tcpinfo->sendport = 0;
+ tcpinfo->listenaddr = bindaddr;
tcpinfo->listenport = port;
tcpinfo->chantype = &svr_chan_tcpremote;
- /* Note: bindaddr is actually ignored by listen_tcpfwd, since
- * we only want to bind to localhost */
ret = listen_tcpfwd(tcpinfo);
out:
if (ret == DROPBEAR_FAILURE) {
/* we only free it if a listener wasn't created, since the listener
* has to remember it if it's to be cancelled */
- m_free(tcpinfo->sendaddr);
+ m_free(tcpinfo->listenaddr);
m_free(tcpinfo);
}
TRACE(("leave remotetcpreq"))
@@ -235,7 +235,7 @@ static int newtcpdirect(struct Channel * channel) {
int len;
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
- if (opts.nolocaltcp) {
+ if (svr_opts.nolocaltcp) {
TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
goto out;
}
diff --git a/tcp-accept.c b/tcp-accept.c
index e75224e..ac33566 100644
--- a/tcp-accept.c
+++ b/tcp-accept.c
@@ -39,6 +39,7 @@ static void cleanup_tcp(struct Listener *listener) {
struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata);
m_free(tcpinfo->sendaddr);
+ m_free(tcpinfo->listenaddr);
m_free(tcpinfo);
}
@@ -65,10 +66,14 @@ static void tcp_acceptor(struct Listener *listener, int sock) {
if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) {
- buf_putstring(ses.writepayload, tcpinfo->sendaddr,
- strlen(tcpinfo->sendaddr));
- buf_putint(ses.writepayload, tcpinfo->sendport);
+ // address that was connected
+ buf_putstring(ses.writepayload, tcpinfo->listenaddr,
+ strlen(tcpinfo->listenaddr));
+ // port that was connected
+ buf_putint(ses.writepayload, tcpinfo->listenport);
+ // originator ip
buf_putstring(ses.writepayload, ipstring, strlen(ipstring));
+ // originator port
buf_putint(ses.writepayload, atol(portstring));
encrypt_packet();
@@ -86,16 +91,21 @@ int listen_tcpfwd(struct TCPListener* tcpinfo) {
struct Listener *listener = NULL;
int nsocks;
char* errstring = NULL;
+ // listen_spec = NULL indicates localhost
+ const char* listen_spec = NULL;
TRACE(("enter listen_tcpfwd"))
/* first we try to bind, so don't need to do so much cleanup on failure */
snprintf(portstring, sizeof(portstring), "%d", tcpinfo->listenport);
- /* XXX Note: we're just listening on localhost, no matter what they tell
- * us. If someone wants to make it listen otherways, then change
- * the "" argument. but that requires UI changes too */
- nsocks = dropbear_listen("", portstring, socks,
+ /* a listenaddr of "" will indicate all interfaces */
+ 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);
if (nsocks < 0) {
dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring);
diff --git a/tcpfwd.h b/tcpfwd.h
index 504a8d3..e980ee2 100644
--- a/tcpfwd.h
+++ b/tcpfwd.h
@@ -28,16 +28,15 @@
struct TCPListener {
- /* sendaddr/sendport are what we send in the channel init request. For a
- * forwarded-tcpip request, it's the addr/port we were binding to.
- * For a direct-tcpip request, it's the addr/port we want the other
+ /* For a direct-tcpip request, it's the addr/port we want the other
* end to connect to */
-
unsigned char *sendaddr;
unsigned int sendport;
- /* This is for direct-tcpip (ie the client listening), and specifies the
- * port to listen on. Is unspecified for the server */
+ /* This is the address/port that we listen on. The address has special
+ * meanings as per the rfc, "" for all interfaces, "localhost" for
+ * localhost, or a normal interface name. */
+ unsigned char *listenaddr;
unsigned int listenport;
const struct ChanType *chantype;