diff options
author | Matt Johnston <matt@ucc.asn.au> | 2005-12-04 16:13:11 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2005-12-04 16:13:11 +0000 |
commit | a673d609639b180eee3a4ba49d7f07d0239ea666 (patch) | |
tree | cc1c3b4f3d9d52b79861942a360bca266e98bdcb | |
parent | 736f370dce614b717193f45d084e9e009de723ce (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.c | 9 | ||||
-rw-r--r-- | cli-tcpfwd.c | 17 | ||||
-rw-r--r-- | dbclient.1 | 5 | ||||
-rw-r--r-- | dbutil.c | 17 | ||||
-rw-r--r-- | dropbear.8 | 3 | ||||
-rw-r--r-- | runopts.h | 14 | ||||
-rw-r--r-- | svr-authpam.c | 20 | ||||
-rw-r--r-- | svr-main.c | 2 | ||||
-rw-r--r-- | svr-runopts.c | 21 | ||||
-rw-r--r-- | svr-tcpfwd.c | 24 | ||||
-rw-r--r-- | tcp-accept.c | 24 | ||||
-rw-r--r-- | tcpfwd.h | 11 |
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(); @@ -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 @@ -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); @@ -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 @@ -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; @@ -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); @@ -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; |