# HG changeset patch # User Matt Johnston # Date 1143361599 0 # Node ID 474c1a700b673bbee4e1fc7af520afd948d467cd # Parent 6e5f8ce73bf2efe3f0226858f5222e816b8e676b add inetd server mode diff -r 6e5f8ce73bf2 -r 474c1a700b67 options.h --- a/options.h Sat Mar 25 18:35:35 2006 +0000 +++ b/options.h Sun Mar 26 08:26:39 2006 +0000 @@ -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 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "0.48" +#define DROPBEAR_VERSION "0.48axis" #endif #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION diff -r 6e5f8ce73bf2 -r 474c1a700b67 runopts.h --- a/runopts.h Sat Mar 25 18:35:35 2006 +0000 +++ b/runopts.h Sun Mar 26 08:26:39 2006 +0000 @@ -84,6 +84,10 @@ sign_key *hostkey; buffer * banner; +#ifdef INETD_SERVER_MODE + char * inetd_dropbear_path; +#endif + } svr_runopts; extern svr_runopts svr_opts; diff -r 6e5f8ce73bf2 -r 474c1a700b67 svr-auth.c --- a/svr-auth.c Sat Mar 25 18:35:35 2006 +0000 +++ b/svr-auth.c Sun Mar 26 08:26:39 2006 +0000 @@ -212,16 +212,20 @@ 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); diff -r 6e5f8ce73bf2 -r 474c1a700b67 svr-main.c --- a/svr-main.c Sat Mar 25 18:35:35 2006 +0000 +++ b/svr-main.c Sun Mar 26 08:26:39 2006 +0000 @@ -40,8 +40,16 @@ #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 @@ /* 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 @@ /* 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,6 +338,153 @@ } #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)) { @@ -383,7 +545,7 @@ * otherwise we might end up blatting error messages to the socket */ loadhostkeys(); - seedrandom(); + seedrandom(); } /* Set up listening sockets for all the requested ports */ diff -r 6e5f8ce73bf2 -r 474c1a700b67 svr-runopts.c --- a/svr-runopts.c Sat Mar 25 18:35:35 2006 +0000 +++ b/svr-runopts.c Sun Mar 26 08:26:39 2006 +0000 @@ -75,6 +75,9 @@ #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 @@ #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 @@ 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;