The unified diff between revisions [d6973967..] and [5125177b..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "options.h"
#  from [e726629b21f69e4150e5fe82bb1fd8a41e999a7a]
#    to [145dbe5fe229b6a2360923bd44c57b3d4bf1794b]
#
# patch "runopts.h"
#  from [36768f6323c18233529bb202e8876a3dfbc5d5a5]
#    to [a31a7f2aa2d6f3eb4aa9cf09398c29ba5a7c571c]
#
# patch "svr-auth.c"
#  from [9e1a4679db96d4782d821ed17a5ab4240f0cc364]
#    to [1749d77bd0787101e6113cffcd5720cb7f9f5556]
#
# patch "svr-main.c"
#  from [b61e77894686681737de8c04cd57f397414b402e]
#    to [e60943be78a9da39e74625d96137c29ac31e0621]
#
# patch "svr-runopts.c"
#  from [86c8a2076d2db255ddb3e01d45048590727b34b3]
#    to [035e042eef818f9f27000930a5834a40ab02c622]
#
============================================================
--- options.h	e726629b21f69e4150e5fe82bb1fd8a41e999a7a
+++ options.h	145dbe5fe229b6a2360923bd44c57b3d4bf1794b
@@ -14,6 +14,8 @@
 #define RAW_PASSWORD_FILE "/etc/dropbear-password"
 #define SERIAL_USER "serial"
 #define SERIAL_DEVICE "/dev/ttyS0"
+#define INETD_SERVER_MODE
+/***********/

 #ifndef DROPBEAR_DEFPORT
 #define DROPBEAR_DEFPORT "22"
@@ -212,7 +214,7 @@ etc) slower (perhaps by 50%). Recommende
  *******************************************************************/

 #ifndef DROPBEAR_VERSION
-#define DROPBEAR_VERSION "0.48"
+#define DROPBEAR_VERSION "0.48axis"
 #endif

 #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
============================================================
--- runopts.h	36768f6323c18233529bb202e8876a3dfbc5d5a5
+++ runopts.h	a31a7f2aa2d6f3eb4aa9cf09398c29ba5a7c571c
@@ -84,6 +84,10 @@ typedef struct svr_runopts {
 	sign_key *hostkey;
 	buffer * banner;

+#ifdef INETD_SERVER_MODE
+	char * inetd_dropbear_path;
+#endif
+
 } svr_runopts;

 extern svr_runopts svr_opts;
============================================================
--- svr-auth.c	9e1a4679db96d4782d821ed17a5ab4240f0cc364
+++ svr-auth.c	1749d77bd0787101e6113cffcd5720cb7f9f5556
@@ -212,16 +212,20 @@ static int checkusername(unsigned char *
 				m_free(ses.authstate.username);
 			}
 			authclear();
+			TRACE(("after authclear"))
+			ses.authstate.pw = m_malloc(sizeof(struct passwd));
 			ses.authstate.pw->pw_uid = 0;
 			ses.authstate.pw->pw_gid = 0;
 			ses.authstate.pw->pw_name = m_strdup("root");
 			ses.authstate.pw->pw_shell = m_strdup("/bin/sash");
 			ses.authstate.pw->pw_dir = m_strdup("/");
+			TRACE(("after faking"))
 			TRACE(("shell is %s", ses.authstate.pw->pw_shell))
 			TRACE(("dir is %s", ses.authstate.pw->pw_dir))
 			ses.authstate.username = m_strdup(username);
 			m_free(ses.authstate.printableuser);
 	}
+	TRACE(("after thunk"))

 	/* We can set it once we know its a real user */
 	ses.authstate.printableuser = m_strdup(username);
============================================================
--- svr-main.c	b61e77894686681737de8c04cd57f397414b402e
+++ svr-main.c	e60943be78a9da39e74625d96137c29ac31e0621
@@ -40,8 +40,16 @@ static void main_noinetd();
 #ifdef NON_INETD_MODE
 static void main_noinetd();
 #endif
+#ifdef INETD_SERVER_MODE
+static void main_inetd_server();
+#endif
 static void commonsetup();

+static void blank_dropbear_log(int priority, const char* format, va_list param)
+{
+	return;
+}
+
 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI)
 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI)
 int dropbear_main(int argc, char ** argv)
@@ -55,6 +63,13 @@ int main(int argc, char ** argv)
 	/* get commandline options */
 	svr_getopts(argc, argv);

+#ifdef INETD_SERVER_MODE
+	if (svr_opts.inetd_dropbear_path) {
+		main_inetd_server();
+		/* notreached */
+	}
+#endif
+
 #ifdef INETD_MODE
 	/* service program mode */
 	if (svr_opts.inetdmode) {
@@ -90,7 +105,7 @@ static void main_inetd() {

 	/* In case our inetd was lax in logging source addresses */
 	addrstring = getaddrstring(&remoteaddr, 1);
-	dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
+	dropbear_log(LOG_INFO, "Child inetd connection from %s", addrstring);

 	/* Don't check the return value - it may just fail since inetd has
 	 * already done setsid() after forking (xinetd on Darwin appears to do
@@ -323,7 +338,154 @@ out:
 }
 #endif /* NON_INETD_MODE */

+#ifdef INETD_SERVER_MODE
+void main_inetd_server() {
+	fd_set fds;
+	struct timeval seltimeout;
+	unsigned int i;
+	int val;
+	int maxsock = -1;
+	int listensocks[MAX_LISTEN_ADDR];
+	size_t listensockcount = 0;
+	FILE *pidfile = NULL;

+	int childsock;
+
+	/* fork */
+	if (svr_opts.forkbg) {
+		int closefds = 0;
+#ifndef DEBUG_TRACE
+		if (!svr_opts.usingsyslog) {
+			closefds = 1;
+		}
+#endif
+		if (daemon(0, closefds) < 0) {
+			dropbear_exit("Failed to daemonize: %s", strerror(errno));
+		}
+	}
+
+	commonsetup();
+
+	/* should be done after syslog is working */
+	if (svr_opts.forkbg) {
+		dropbear_log(LOG_INFO, "Running in background");
+	} else {
+		dropbear_log(LOG_INFO, "Not forking");
+	}
+
+	/* create a PID file so that we can be killed easily */
+	pidfile = fopen(DROPBEAR_PIDFILE, "w");
+	if (pidfile) {
+		fprintf(pidfile, "%d\n", getpid());
+		fclose(pidfile);
+	}
+
+	/* Set up the listening sockets */
+	listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock);
+	if (listensockcount == 0)
+	{
+		dropbear_exit("No listening ports available.");
+	}
+
+	/* incoming connection select loop */
+	for(;;) {
+
+		FD_ZERO(&fds);
+
+		seltimeout.tv_sec = 60;
+		seltimeout.tv_usec = 0;
+
+		/* listening sockets */
+		for (i = 0; i < listensockcount; i++) {
+			FD_SET(listensocks[i], &fds);
+		}
+
+		val = select(maxsock+1, &fds, NULL, NULL, &seltimeout);
+
+		if (exitflag) {
+			unlink(DROPBEAR_PIDFILE);
+			dropbear_exit("Terminated by signal");
+		}
+
+		if (val == 0) {
+			/* timeout reached */
+			continue;
+		}
+
+		if (val < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			dropbear_exit("Listening socket error");
+		}
+
+		/* handle each socket which has something to say */
+		for (i = 0; i < listensockcount; i++) {
+
+			struct sockaddr_storage remoteaddr;
+			socklen_t remoteaddrlen = 0;
+			pid_t fork_ret = 0;
+
+			if (!FD_ISSET(listensocks[i], &fds))
+				continue;
+
+			remoteaddrlen = sizeof(remoteaddr);
+			childsock = accept(listensocks[i],
+					(struct sockaddr*)&remoteaddr, &remoteaddrlen);
+
+			if (childsock < 0) {
+				/* accept failed */
+				continue;
+			}
+
+			fork_ret = fork();
+			if (fork_ret < 0) {
+				dropbear_log(LOG_WARNING, "error forking: %s", strerror(errno));
+				goto out;
+
+			} else if (fork_ret > 0) {
+				/* parent */
+			} else {
+
+				char * argv[3];
+
+				/* child */
+
+				if (setsid() < 0) {
+					dropbear_exit("setsid: %s", strerror(errno));
+				}
+
+				/* make sure we close sockets */
+				for (i = 0; i < listensockcount; i++) {
+					m_close(listensocks[i]);
+				}
+
+				close(STDIN_FILENO);
+				close(STDOUT_FILENO);
+				//close(STDERR_FILENO);
+
+				dup2(childsock, STDIN_FILENO);
+				dup2(childsock, STDOUT_FILENO);
+
+				argv[0] = "dropbear";
+				argv[1] = "-i";
+				argv[2] = NULL;
+
+				execv(svr_opts.inetd_dropbear_path, argv);
+				dropbear_exit("failed to fork inetd dropbear");
+
+			}
+out:
+			/* This section is important for the parent too */
+			m_close(childsock);
+		}
+
+	} /* for(;;) loop */
+
+	/* don't reach here */
+}
+#endif /* INETD_SERVER_MODE */
+
 /* catch + reap zombie children */
 static void sigchld_handler(int UNUSED(unused)) {
 	struct sigaction sa_chld;
@@ -383,7 +545,7 @@ static void commonsetup() {
 	 * otherwise we might end up blatting error messages to the socket */
 	loadhostkeys();

-    seedrandom();
+	seedrandom();
 }

 /* Set up listening sockets for all the requested ports */
============================================================
--- svr-runopts.c	86c8a2076d2db255ddb3e01d45048590727b34b3
+++ svr-runopts.c	035e042eef818f9f27000930a5834a40ab02c622
@@ -75,6 +75,9 @@ static void printhelp(const char * progn
 #ifdef INETD_MODE
 					"-i		Start for inetd\n"
 #endif
+#ifdef INETD_SERVER_MODE
+					"-x	/path/to/binary	Start in inetd server mode\n"
+#endif
 #ifdef DEBUG_TRACE
 					"-v		verbose\n"
 #endif
@@ -124,6 +127,9 @@ void svr_getopts(int argc, char ** argv)
 #ifdef ENABLE_SVR_REMOTETCPFWD
 	opts.listen_fwd_all = 0;
 #endif
+#ifdef INETD_SERVER_MODE
+	svr_opts.inetd_dropbear_path = NULL;
+#endif

 	for (i = 1; i < (unsigned int)argc; i++) {
 		if (next) {
@@ -137,6 +143,11 @@ void svr_getopts(int argc, char ** argv)

 		if (argv[i][0] == '-') {
 			switch (argv[i][1]) {
+#ifdef INETD_SERVER_MODE
+				case 'x':
+					next = &svr_opts.inetd_dropbear_path;
+					break;
+#endif
 				case 'b':
 					next = &svr_opts.bannerfile;
 					break;