Dropbear patch to specify the listening address via the "-p" command line switch

Max-Gerd Retzlaff m.retzlaff at gmx.net
Wed Feb 21 01:34:37 WST 2007


Hello,

I've had a look at FreeWRT yesterday and installed it (FreeWRT 1.0,
built via the Web Image Builder). I noticed that Dropbear doesn't
support to have it bound to only particular interfaces. This patch
changes this, whilst being compatible with the existent interface:

Until now "-p" has only taken a port as its argument, to specify
a particular port Dropbear should listen to. With my patch it accepts
an optional listening address in addition to the port: "-p [address:]port".
If the address is not given Dropbear will listen for every address,
as it does without the patch. Now you can also call it this way:
   dropbear -g -p 127.0.0.1:22 -p 192.168.100.100:22 -p 2323
The "-h" help is updated, as well.

(That means for FreeWRT that you can now make Dropbear listen only
 on the LAN ports, the WLAN, and the loopback interfaces, but not
 on the WAN port.)


Luckily, Dropbear is already internally designed to have it listen only
to a particular address or addresses, it is only not plumbed to the
command line option parsing machinery. (That is, dropbear_listen() in
dbutil.c of Dropbear already takes the listening address as its first
argument, it is only always called with "" as the address from
listensockets() in svr-main.c, which means "listening on everything".)

The patch is attached. I have sticked to the existing coding style
(and tab mode). The "-p" option of the server now is processed in a
way as the "-i", "-L", and "-R" options of the client are processed.
The new function addportandaddress() in svr-runopts.c, the function
that does the "-p" option processing itself, is very similar to the
function parsehostname() in cli-runopts.c. No fancy different way
to do the similar task. Of course, I've written the patch to the best
of my knowledge.

The patch is against version 0.48.1 of Dropbear, tested with a
subversion checkout of freewrt_1_0, that has been, well, checked out
only yesterday.  Just put it in freewrt_1_0/package/dropbear/patches/
(probably with a number prepended), and it'll build. (At least it did
for me.) No additional changes, e.g. to configuration files, have been
necessary.

Bye,
Max

PS: Please CC me, as I'm not subscribed to any of the two mailing lists.

-- 
Max-Gerd Retzlaff <m.retzlaff at gmx.net>       http://blog.matroid.org

For your amusement:
I got a postcard from my friend George with a satellite picture of
the entire earth. On the back he wrote: "Wish you were here."
		-- Steven Wright
-------------- next part --------------
diff -Naur dropbear-0.48.1/options.h dropbear-0.48.1-l_empty/options.h
--- dropbear-0.48.1/options.h	2006-03-12 05:52:51.000000000 +0100
+++ dropbear-0.48.1-l_empty/options.h	2007-02-20 06:58:59.000000000 +0100
@@ -14,6 +14,10 @@
 #define DROPBEAR_DEFPORT "22"
 #endif
 
+#ifndef DROPBEAR_DEFADDRESS
+#define DROPBEAR_DEFADDRESS ""
+#endif
+
 /* Default hostkey paths - these can be specified on the command line */
 #ifndef DSS_PRIV_FILENAME
 #define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
diff -Naur dropbear-0.48.1/runopts.h dropbear-0.48.1-l_empty/runopts.h
--- dropbear-0.48.1/runopts.h	2006-03-12 05:52:51.000000000 +0100
+++ dropbear-0.48.1-l_empty/runopts.h	2007-02-20 05:30:11.000000000 +0100
@@ -55,6 +55,7 @@
 	/* ports is an array of the portcount listening ports */
 	char *ports[DROPBEAR_MAX_PORTS];
 	unsigned int portcount;
+	char *addresses[DROPBEAR_MAX_PORTS];
 
 	int inetdmode;
 
diff -Naur dropbear-0.48.1/svr-main.c dropbear-0.48.1-l_empty/svr-main.c
--- dropbear-0.48.1/svr-main.c	2006-03-12 05:52:52.000000000 +0100
+++ dropbear-0.48.1-l_empty/svr-main.c	2007-02-20 15:01:10.000000000 +0100
@@ -397,9 +397,9 @@
 
 	for (i = 0; i < svr_opts.portcount; i++) {
 
-		TRACE(("listening on '%s'", svr_opts.ports[i]))
+		TRACE(("listening on '%s:%s'", svr_opts.addresses[i], svr_opts.ports[i]))
 
-		nsock = dropbear_listen("", svr_opts.ports[i], &sock[sockpos], 
+		nsock = dropbear_listen(svr_opts.addresses[i], svr_opts.ports[i], &sock[sockpos], 
 				sockcount - sockpos,
 				&errstring, maxfd);
 
diff -Naur dropbear-0.48.1/svr-runopts.c dropbear-0.48.1-l_empty/svr-runopts.c
--- dropbear-0.48.1/svr-runopts.c	2006-03-12 05:52:52.000000000 +0100
+++ dropbear-0.48.1-l_empty/svr-runopts.c	2007-02-20 15:16:42.000000000 +0100
@@ -32,6 +32,7 @@
 svr_runopts svr_opts; /* GLOBAL */
 
 static void printhelp(const char * progname);
+static void addportandaddress(char* spec);
 
 static void printhelp(const char * progname) {
 
@@ -70,8 +71,11 @@
 					"-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"
-					"		(default %s if none specified)\n"
+					"-p [address:]port\n"
+					"		Listen on specified tcp port (and optionally address),\n"
+					"		up to %d can be specified\n"
+					"		(default port is %s if none specified)\n"
+					"		(default address is %s address if not specified)\n"
 #ifdef INETD_MODE
 					"-i		Start for inetd\n"
 #endif
@@ -85,13 +89,15 @@
 #ifdef DROPBEAR_RSA
 					RSA_PRIV_FILENAME,
 #endif
-					DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT);
+					DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT,
+					(!strcmp(DROPBEAR_DEFADDRESS,""))?"any":DROPBEAR_DEFADDRESS);
 }
 
 void svr_getopts(int argc, char ** argv) {
 
 	unsigned int i;
 	char ** next = 0;
+	int nextisport = 0;
 
 	/* see printhelp() for options */
 	svr_opts.rsakeyfile = NULL;
@@ -126,6 +132,12 @@
 #endif
 
 	for (i = 1; i < (unsigned int)argc; i++) {
+		if (nextisport) {
+			addportandaddress(argv[i]);
+			nextisport = 0;
+			continue;
+		}
+	  
 		if (next) {
 			*next = argv[i];
 			if (*next == NULL) {
@@ -177,14 +189,8 @@
 					break;
 #endif
 				case 'p':
-					if (svr_opts.portcount < DROPBEAR_MAX_PORTS) {
-						svr_opts.ports[svr_opts.portcount] = NULL;
-						next = &svr_opts.ports[svr_opts.portcount];
-						/* Note: if it doesn't actually get set, we'll
-						 * decrement it after the loop */
-						svr_opts.portcount++;
-					}
-					break;
+				  nextisport = 1;
+				  break;
 #ifdef DO_MOTD
 				/* motd is displayed by default, -m turns it off */
 				case 'm':
@@ -223,6 +229,7 @@
 	/* Set up listening ports */
 	if (svr_opts.portcount == 0) {
 		svr_opts.ports[0] = m_strdup(DROPBEAR_DEFPORT);
+		svr_opts.addresses[0] = m_strdup(DROPBEAR_DEFADDRESS);
 		svr_opts.portcount = 1;
 	} else {
 		/* we may have been given a -p option but no argument to go with
@@ -231,6 +238,13 @@
 			svr_opts.portcount--;
 		}
 	}
+        
+	/*
+	 * printf("ports: %d\n", svr_opts.portcount);
+	 * for (i = 0; i < svr_opts.portcount; i++) {
+	 *  printf("%s %s\n", svr_opts.addresses[i], svr_opts.ports[i]);
+	 * }
+	 */
 
 	if (svr_opts.dsskeyfile == NULL) {
 		svr_opts.dsskeyfile = DSS_PRIV_FILENAME;
@@ -261,6 +275,42 @@
 
 }
 
+static void addportandaddress(char* spec) {
+
+	char *myspec = NULL;
+
+	if (svr_opts.portcount < DROPBEAR_MAX_PORTS) {
+
+		myspec = m_strdup(spec);
+
+		/* search for ':', that separates address and port */
+		svr_opts.ports[svr_opts.portcount] = strchr(myspec, ':');
+
+		if (svr_opts.ports[svr_opts.portcount] == NULL) {
+			/* no ':' -> the whole string specifies just a port */
+			svr_opts.ports[svr_opts.portcount] = myspec;
+		} else {
+			svr_opts.ports[svr_opts.portcount][0] = '\0'; /* Split the address/port */
+			svr_opts.ports[svr_opts.portcount]++;
+			svr_opts.addresses[svr_opts.portcount] = myspec;
+		}
+
+		if (svr_opts.addresses[svr_opts.portcount] == NULL) {
+			/* no address given -> fill in the default address */
+			svr_opts.addresses[svr_opts.portcount] = m_strdup(DROPBEAR_DEFADDRESS);
+		}
+
+		if (svr_opts.ports[svr_opts.portcount][0] == '\0') {
+			/* empty port -> exit */
+			dropbear_exit("Bad port");
+		}
+
+		svr_opts.portcount++;
+		/* Note: if it doesn't actually get set, we'll
+		 * decrement it after the loop in svr_getopts(). */
+	}
+}
+
 static void disablekey(int type, const char* filename) {
 
 	int i;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.ucc.gu.uwa.edu.au/pipermail/dropbear/attachments/20070220/1ca5da7a/attachment.pgp 


More information about the Dropbear mailing list