# HG changeset patch # User Matt Johnston # Date 1154958083 0 # Node ID 01e4180895ba1330057d3fb688d8d5303c9b4350 # Parent bf29e6659fb9994eed08801b96f825efe5179e17# Parent dba106bf6b347abe3689f62fcf6208c877de4429 merge of '9a4e042fd565f46141e81e0c1ab90260303348fe' and 'bea3887a5875cf3ab8a1331e15e698b37b61fe37' diff -r dba106bf6b34 -r 01e4180895ba CHANGES --- a/CHANGES Mon Aug 07 13:41:16 2006 +0000 +++ b/CHANGES Mon Aug 07 13:41:23 2006 +0000 @@ -1,3 +1,22 @@ +0.49 - Tues 13 June 2003 + +- Return immediately for "sleep 10 & echo foo", rather than waiting + for the sleep to return (pointed out by Rob Landley) + +- Added -P pidfile argument to the server (from Swen Schillig) + +- Compile fixes, make sure that all variable definitions are at the start + of a scope. + +- Use $HOME in preference to that from /etc/passwd, so that it + dbclient can still work on systems with a broken setup. + +- Add -N dbclient option for "no command" + +- Add -f dbclient option for "background after auth" + +- Try to finally fix ss_family compilation problems + 0.48.1 - Sat 11 March 2006 - Compile fix for scp diff -r dba106bf6b34 -r 01e4180895ba Makefile.in --- a/Makefile.in Mon Aug 07 13:41:16 2006 +0000 +++ b/Makefile.in Mon Aug 07 13:41:23 2006 +0000 @@ -69,7 +69,8 @@ RANLIB=@RANLIB@ STRIP=@STRIP@ INSTALL=@INSTALL@ -CFLAGS=-I. -I$(srcdir)/libtomcrypt/src/headers/ @CFLAGS@ +CPPFLAGS=@CPPFLAGS@ +CFLAGS=-I. -I$(srcdir)/libtomcrypt/src/headers/ $(CPPFLAGS) @CFLAGS@ LIBS=$(LTC) $(LTM) @LIBS@ LDFLAGS=@LDFLAGS@ diff -r dba106bf6b34 -r 01e4180895ba auth.h --- a/auth.h Mon Aug 07 13:41:16 2006 +0000 +++ b/auth.h Mon Aug 07 13:41:23 2006 +0000 @@ -52,7 +52,7 @@ void cli_auth_password(); int cli_auth_pubkey(); void cli_auth_interactive(); -char* getpass_or_cancel(); +char* getpass_or_cancel(char* prompt); #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */ diff -r dba106bf6b34 -r 01e4180895ba cli-auth.c --- a/cli-auth.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-auth.c Mon Aug 07 13:41:23 2006 +0000 @@ -236,8 +236,8 @@ void cli_auth_try() { + int finished = 0; TRACE(("enter cli_auth_try")) - int finished = 0; CHECKCLEARTOWRITE(); @@ -281,11 +281,11 @@ /* A helper for getpass() that exits if the user cancels. The returned * password is statically allocated by getpass() */ -char* getpass_or_cancel() +char* getpass_or_cancel(char* prompt) { char* password = NULL; - password = getpass("Password: "); + password = getpass(prompt); /* 0x03 is a ctrl-c character in the buffer. */ if (password == NULL || strchr(password, '\3') != NULL) { diff -r dba106bf6b34 -r 01e4180895ba cli-authinteract.c --- a/cli-authinteract.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-authinteract.c Mon Aug 07 13:41:23 2006 +0000 @@ -99,13 +99,14 @@ if (strlen(name) > 0) { cleantext(name); fprintf(stderr, "%s", name); - m_free(name); } + m_free(name); + if (strlen(instruction) > 0) { cleantext(instruction); fprintf(stderr, "%s", instruction); - m_free(instruction); } + m_free(instruction); for (i = 0; i < num_prompts; i++) { unsigned int response_len = 0; diff -r dba106bf6b34 -r 01e4180895ba cli-authpasswd.c --- a/cli-authpasswd.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-authpasswd.c Mon Aug 07 13:41:23 2006 +0000 @@ -116,16 +116,19 @@ void cli_auth_password() { char* password = NULL; + char prompt[80]; TRACE(("enter cli_auth_password")) CHECKCLEARTOWRITE(); + snprintf(prompt, sizeof(prompt), "%s@%s's password: ", + cli_opts.username, cli_opts.remotehost); #ifdef ENABLE_CLI_ASKPASS_HELPER if (want_askpass()) - password = gui_getpass("Password: "); + password = gui_getpass(prompt); else #endif - password = getpass_or_cancel("Password: "); + password = getpass_or_cancel(prompt); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); diff -r dba106bf6b34 -r 01e4180895ba cli-authpubkey.c --- a/cli-authpubkey.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-authpubkey.c Mon Aug 07 13:41:23 2006 +0000 @@ -112,6 +112,7 @@ /* Success */ break; } + buf_free(keybuf); if (keyitem != NULL) { TRACE(("matching key")) diff -r dba106bf6b34 -r 01e4180895ba cli-chansession.c --- a/cli-chansession.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-chansession.c Mon Aug 07 13:41:23 2006 +0000 @@ -162,8 +162,6 @@ static void put_termcodes() { - TRACE(("enter put_termcodes")) - struct termios tio; unsigned int sshcode; const struct TermCode *termcode; @@ -172,6 +170,8 @@ unsigned int bufpos1, bufpos2; + TRACE(("enter put_termcodes")) + if (tcgetattr(STDIN_FILENO, &tio) == -1) { dropbear_log(LOG_WARNING, "Failed reading termmodes"); buf_putint(ses.writepayload, 1); /* Just the terminator */ diff -r dba106bf6b34 -r 01e4180895ba cli-kex.c --- a/cli-kex.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-kex.c Mon Aug 07 13:41:23 2006 +0000 @@ -122,6 +122,7 @@ fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n", cli_opts.remotehost, fp); + m_free(fp); tty = fopen(_PATH_TTY, "r"); if (tty) { @@ -132,7 +133,6 @@ } if (response == 'y') { - m_free(fp); return; } @@ -145,49 +145,59 @@ FILE *hostsfile = NULL; int readonly = 0; struct passwd *pw = NULL; + char * homedir = NULL; unsigned int hostlen, algolen; unsigned long len; const char *algoname = NULL; buffer * line = NULL; int ret; - pw = getpwuid(getuid()); + homedir = getenv("HOME"); - if (pw == NULL) { - dropbear_exit("Failed to get homedir"); + if (!homedir) { + pw = getpwuid(getuid()); + if (pw) { + homedir = pw->pw_dir; + } + pw = NULL; } - len = strlen(pw->pw_dir); - filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/ + if (homedir) { + + len = strlen(homedir); + filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/ - snprintf(filename, len+18, "%s/.ssh", pw->pw_dir); - /* Check that ~/.ssh exists - easiest way is just to mkdir */ - if (mkdir(filename, S_IRWXU) != 0) { - if (errno != EEXIST) { - dropbear_log(LOG_INFO, "Warning: failed creating ~/.ssh: %s", - strerror(errno)); - TRACE(("mkdir didn't work: %s", strerror(errno))) - ask_to_confirm(keyblob, keybloblen); - goto out; /* only get here on success */ + snprintf(filename, len+18, "%s/.ssh", homedir); + /* Check that ~/.ssh exists - easiest way is just to mkdir */ + if (mkdir(filename, S_IRWXU) != 0) { + if (errno != EEXIST) { + dropbear_log(LOG_INFO, "Warning: failed creating %s/.ssh: %s", + homedir, strerror(errno)); + TRACE(("mkdir didn't work: %s", strerror(errno))) + ask_to_confirm(keyblob, keybloblen); + goto out; /* only get here on success */ + } } - } - snprintf(filename, len+18, "%s/.ssh/known_hosts", pw->pw_dir); - hostsfile = fopen(filename, "a+"); - - if (hostsfile != NULL) { - fseek(hostsfile, 0, SEEK_SET); - } else { - /* We mightn't have been able to open it if it was read-only */ - if (errno == EACCES || errno == EROFS) { - TRACE(("trying readonly: %s", strerror(errno))) - readonly = 1; - hostsfile = fopen(filename, "r"); + snprintf(filename, len+18, "%s/.ssh/known_hosts", homedir); + hostsfile = fopen(filename, "a+"); + + if (hostsfile != NULL) { + fseek(hostsfile, 0, SEEK_SET); + } else { + /* We mightn't have been able to open it if it was read-only */ + if (errno == EACCES || errno == EROFS) { + TRACE(("trying readonly: %s", strerror(errno))) + readonly = 1; + hostsfile = fopen(filename, "r"); + } } } if (hostsfile == NULL) { TRACE(("hostsfile didn't open: %s", strerror(errno))) + dropbear_log(LOG_WARNING, "Failed to open %s/.ssh/known_hosts", + homedir); ask_to_confirm(keyblob, keybloblen); goto out; /* We only get here on success */ } diff -r dba106bf6b34 -r 01e4180895ba cli-runopts.c --- a/cli-runopts.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-runopts.c Mon Aug 07 13:41:23 2006 +0000 @@ -44,12 +44,14 @@ static void printhelp() { fprintf(stderr, "Dropbear client v%s\n" - "Usage: %s [options] [user@]host\n" + "Usage: %s [options] [user@]host [command]\n" "Options are:\n" "-p \n" "-l \n" "-t Allocate a pty\n" "-T Don't allocate a pty\n" + "-N Don't run a remote command\n" + "-f Run in background after auth\n" #ifdef ENABLE_CLI_PUBKEY_AUTH "-i (multiple allowed)\n" #endif @@ -88,6 +90,8 @@ cli_opts.remoteport = NULL; cli_opts.username = NULL; cli_opts.cmd = NULL; + cli_opts.no_cmd = 0; + cli_opts.backgrounded = 0; cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */ #ifdef ENABLE_CLI_PUBKEY_AUTH cli_opts.privkeys = NULL; @@ -163,6 +167,12 @@ case 'T': /* don't want a pty */ cli_opts.wantpty = 0; break; + case 'N': + cli_opts.no_cmd = 1; + break; + case 'f': + cli_opts.backgrounded = 1; + break; #ifdef ENABLE_CLI_LOCALTCPFWD case 'L': nextislocal = 1; @@ -269,6 +279,11 @@ cli_opts.wantpty = 0; } } + + if (cli_opts.backgrounded && cli_opts.cmd == NULL + && cli_opts.no_cmd == 0) { + dropbear_exit("command required for -f"); + } } #ifdef ENABLE_CLI_PUBKEY_AUTH diff -r dba106bf6b34 -r 01e4180895ba cli-service.c --- a/cli-service.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-service.c Mon Aug 07 13:41:23 2006 +0000 @@ -82,6 +82,4 @@ } dropbear_exit("unrecognised service accept"); - /* m_free(servicename); not reached */ - } diff -r dba106bf6b34 -r 01e4180895ba cli-session.c --- a/cli-session.c Mon Aug 07 13:41:16 2006 +0000 +++ b/cli-session.c Mon Aug 07 13:41:23 2006 +0000 @@ -212,19 +212,38 @@ */ case USERAUTH_SUCCESS_RCVD: + + if (cli_opts.backgrounded) { + int devnull; + // keeping stdin open steals input from the terminal and + // is confusing, though stdout/stderr could be useful. + devnull = open(_PATH_DEVNULL, O_RDONLY); + if (devnull < 0) { + dropbear_exit("opening /dev/null: %d %s", + errno, strerror(errno)); + } + dup2(devnull, STDIN_FILENO); + if (daemon(0, 1) < 0) { + dropbear_exit("Backgrounding failed: %d %s", + errno, strerror(errno)); + } + } + #ifdef ENABLE_CLI_LOCALTCPFWD setup_localtcp(); #endif #ifdef ENABLE_CLI_REMOTETCPFWD setup_remotetcp(); #endif - cli_send_chansess_request(); - TRACE(("leave cli_sessionloop: cli_send_chansess_request")) + if (!cli_opts.no_cmd) { + cli_send_chansess_request(); + } + TRACE(("leave cli_sessionloop: running")) cli_ses.state = SESSION_RUNNING; return; case SESSION_RUNNING: - if (ses.chancount < 1) { + if (ses.chancount < 1 && !cli_opts.no_cmd) { cli_finished(); } diff -r dba106bf6b34 -r 01e4180895ba common-channel.c --- a/common-channel.c Mon Aug 07 13:41:16 2006 +0000 +++ b/common-channel.c Mon Aug 07 13:41:23 2006 +0000 @@ -181,6 +181,7 @@ struct Channel *channel; unsigned int i; + int ret; /* iterate through all the possible channels */ for (i = 0; i < ses.chansize; i++) { @@ -202,6 +203,25 @@ send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); } + /* if we can read from the writefd, it might be closed, so we try to + * see if it has errors */ + if (IS_DROPBEAR_SERVER && channel->writefd >= 0 + && channel->writefd != channel->readfd + && FD_ISSET(channel->writefd, readfds)) { + if (channel->initconn) { + /* Handling for "in progress" connection - this is needed + * to avoid spinning 100% CPU when we connect to a server + * which doesn't send anything (tcpfwding) */ + checkinitdone(channel); + continue; /* Important not to use the channel after + checkinitdone(), as it may be NULL */ + } + ret = write(channel->writefd, NULL, 0); /* Fake write */ + if (ret < 0 && errno != EINTR && errno != EAGAIN) { + closewritefd(channel); + } + } + /* write to program/pipe stdin */ if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) { if (channel->initconn) { @@ -236,32 +256,32 @@ TRACE(("checkclose: writefd %d, readfd %d, errfd %d, sentclosed %d, recvclosed %d", channel->writefd, channel->readfd, channel->errfd, channel->sentclosed, channel->recvclosed)) - TRACE(("writebuf %d extrabuf %s extrabuf %d", + TRACE(("writebuf size %d extrabuf ptr 0x%x extrabuf size %d", cbuf_getused(channel->writebuf), channel->writebuf, channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) - if (!channel->sentclosed) { - - /* check for exited - currently only used for server sessions, - * if the shell has exited etc */ - if (channel->type->checkclose) { - if (channel->type->checkclose(channel)) { - closewritefd(channel); - } + /* server chansession channels are special, since readfd mightn't + * close in the case of "sleep 4 & echo blah" until the sleep is up */ + if (channel->type->checkclose) { + if (channel->type->checkclose(channel)) { + closewritefd(channel); + closereadfd(channel, channel->readfd); + closereadfd(channel, channel->errfd); } + } - if (!channel->senteof - && channel->readfd == FD_CLOSED - && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { - send_msg_channel_eof(channel); - } + if (!channel->senteof + && channel->readfd == FD_CLOSED + && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { + send_msg_channel_eof(channel); + } - if (channel->writefd == FD_CLOSED - && channel->readfd == FD_CLOSED - && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { - send_msg_channel_close(channel); - } + if (!channel->sentclosed + && channel->writefd == FD_CLOSED + && channel->readfd == FD_CLOSED + && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { + send_msg_channel_close(channel); } /* When either party wishes to terminate the channel, it sends @@ -426,10 +446,22 @@ } } + TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d", + channel->writefd, channel->readfd, + channel->errfd, + cbuf_getused(channel->writebuf) )) + + /* For checking FD status (ie closure etc) - we don't actually + * read data from writefd. We don't want to do this for the client, + * since redirection to /dev/null will make it spin in the select */ + if (IS_DROPBEAR_SERVER && channel->writefd >= 0 + && channel->writefd != channel->readfd) { + FD_SET(channel->writefd, readfds); + } + /* Stuff from the wire */ if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 ) || channel->initconn) { - FD_SET(channel->writefd, writefds); } diff -r dba106bf6b34 -r 01e4180895ba common-kex.c --- a/common-kex.c Mon Aug 07 13:41:16 2006 +0000 +++ b/common-kex.c Mon Aug 07 13:41:23 2006 +0000 @@ -262,6 +262,7 @@ hash_state hs; unsigned int C2S_keysize, S2C_keysize; char mactransletter, macrecvletter; /* Client or server specific */ + int recv_cipher = 0, trans_cipher = 0; TRACE(("enter gen_new_keys")) /* the dh_K and hash are the start of all hashes, we make use of that */ @@ -298,17 +299,20 @@ hashkeys(C2S_key, C2S_keysize, &hs, 'C'); hashkeys(S2C_key, S2C_keysize, &hs, 'D'); - if (cbc_start( - find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name), - recv_IV, recv_key, + recv_cipher = find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name); + if (recv_cipher < 0) + dropbear_exit("crypto error"); + + if (cbc_start(recv_cipher, recv_IV, recv_key, ses.newkeys->recv_algo_crypt->keysize, 0, &ses.newkeys->recv_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); } - - if (cbc_start( - find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name), - trans_IV, trans_key, + trans_cipher = find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name); + if (trans_cipher < 0) + dropbear_exit("crypto error"); + + if (cbc_start(trans_cipher, trans_IV, trans_key, ses.newkeys->trans_algo_crypt->keysize, 0, &ses.newkeys->trans_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); @@ -517,7 +521,7 @@ hash_state hs; /* read the prime and generator*/ - mp_init(&dh_p); + m_mp_init(&dh_p); bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN); /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */ diff -r dba106bf6b34 -r 01e4180895ba common-session.c --- a/common-session.c Mon Aug 07 13:41:16 2006 +0000 +++ b/common-session.c Mon Aug 07 13:41:23 2006 +0000 @@ -229,7 +229,7 @@ /* write our version string, this blocks */ if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { - dropbear_exit("Error writing ident string"); + ses.remoteclosed(); } /* If they send more than 50 lines, something is wrong */ @@ -250,7 +250,7 @@ if (!done) { TRACE(("err: %s for '%s'\n", strerror(errno), linebuf)) - dropbear_exit("Failed to get remote version"); + ses.remoteclosed(); } else { /* linebuf is already null terminated */ ses.remoteident = m_malloc(len); diff -r dba106bf6b34 -r 01e4180895ba configure.in --- a/configure.in Mon Aug 07 13:41:16 2006 +0000 +++ b/configure.in Mon Aug 07 13:41:23 2006 +0000 @@ -19,10 +19,13 @@ AC_SUBST(LD) if test -z "$OLDCFLAGS" && test "$GCC" = "yes"; then - AC_MSG_RESULT(No \$CFLAGS set... using "-Os -W -Wall" for GCC) + AC_MSG_NOTICE(No \$CFLAGS set... using "-Os -W -Wall" for GCC) CFLAGS="-Os -W -Wall" fi +# large file support is useful for scp +AC_SYS_LARGEFILE + # Host specific options # this isn't a definitive list of hosts, they are just added as required AC_CANONICAL_HOST @@ -75,7 +78,7 @@ AC_CHECK_DECL(__UCLIBC__, [ no_loginfunc_check=1 - AC_MSG_RESULT(Using uClibc - login() and logout() probably don't work, so we won't use them.) + AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.]) ],,,) # Checks for libraries. @@ -104,16 +107,16 @@ [ if test "x$enableval" = "xno"; then AC_DEFINE(DISABLE_ZLIB,, Use zlib) - AC_MSG_RESULT(Disabling zlib) + AC_MSG_NOTICE(Disabling zlib) else AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***])) - AC_MSG_RESULT(Enabling zlib) + AC_MSG_NOTICE(Enabling zlib) fi ], [ # if not disabled, check for zlib AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***])) - AC_MSG_RESULT(Enabling zlib) + AC_MSG_NOTICE(Enabling zlib) ] ) @@ -141,16 +144,16 @@ [ if test "x$enableval" = "xyes"; then AC_CHECK_LIB(pam, pam_authenticate, , AC_MSG_ERROR([*** PAM missing - install first or check config.log ***])) - AC_MSG_RESULT(Enabling PAM) + AC_MSG_NOTICE(Enabling PAM) else AC_DEFINE(DISABLE_PAM,, Use PAM) - AC_MSG_RESULT(Disabling PAM) + AC_MSG_NOTICE(Disabling PAM) fi ], [ # disable it by default AC_DEFINE(DISABLE_PAM,, Use PAM) - AC_MSG_RESULT(Disabling PAM) + AC_MSG_NOTICE(Disabling PAM) ] ) @@ -158,14 +161,14 @@ [ --disable-openpty Don't use openpty, use alternative method], [ if test "x$enableval" = "xno"; then - AC_MSG_RESULT(Not using openpty) + AC_MSG_NOTICE(Not using openpty) else - AC_MSG_RESULT(Using openpty if available) + AC_MSG_NOTICE(Using openpty if available) AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)]) fi ], [ - AC_MSG_RESULT(Using openpty if available) + AC_MSG_NOTICE(Using openpty if available) AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY)]) ] ) @@ -176,13 +179,13 @@ [ if test "x$enableval" = "xno"; then AC_DEFINE(DISABLE_SYSLOG,, Using syslog) - AC_MSG_RESULT(Disabling syslog) + AC_MSG_NOTICE(Disabling syslog) else - AC_MSG_RESULT(Enabling syslog) + AC_MSG_NOTICE(Enabling syslog) fi ], [ - AC_MSG_RESULT(Enabling syslog) + AC_MSG_NOTICE(Enabling syslog) ] ) @@ -190,15 +193,15 @@ [ --disable-shadow Don't use shadow passwords (if available)], [ if test "x$enableval" = "xno"; then - AC_MSG_RESULT(Not using shadow passwords) + AC_MSG_NOTICE(Not using shadow passwords) else AC_CHECK_HEADERS([shadow.h]) - AC_MSG_RESULT(Using shadow passwords if available) + AC_MSG_NOTICE(Using shadow passwords if available) fi ], [ AC_CHECK_HEADERS([shadow.h]) - AC_MSG_RESULT(Using shadow passwords if available) + AC_MSG_NOTICE(Using shadow passwords if available) ] ) @@ -339,7 +342,7 @@ #endif ]) -AC_CHECK_MEMBERS([struct utmpx.ut_host, struct utmpx.ut_syslen, struct utmpx.ut_type, struct utmpx.ut_id, struct utmpx.ut_addr, struct utmpx.ut_addr_v6, struct utmpx.ut_time, struct utmpx.ut_tv, struct sockaddr_storage.ss_family, struct sockadd_storage.__family],,,[ +AC_CHECK_MEMBERS([struct utmpx.ut_host, struct utmpx.ut_syslen, struct utmpx.ut_type, struct utmpx.ut_id, struct utmpx.ut_addr, struct utmpx.ut_addr_v6, struct utmpx.ut_time, struct utmpx.ut_tv],,,[ #include #include #if HAVE_UTMPX_H @@ -347,6 +350,11 @@ #endif ]) +AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family],,,[ +#include +#include +]) + AC_CHECK_FUNCS(endutent getutent getutid getutline pututline setutent) AC_CHECK_FUNCS(utmpname) AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) @@ -379,7 +387,7 @@ AC_ARG_ENABLE(loginfunc, [ --disable-loginfunc Disable use of login() etc. [no]], [ no_loginfunc_check=1 - AC_MSG_RESULT(Not using login() etc) ] + AC_MSG_NOTICE(Not using login() etc) ] ) AC_ARG_ENABLE(pututline, [ --disable-pututline Disable use of pututline() etc. ([uw]tmp) [no]], @@ -596,7 +604,7 @@ if test x"$cross_compiling" = x"no" ; then AC_CHECK_FILE("/dev/ptmx", AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx)) else - AC_MSG_RESULT(Not checking for /dev/ptmx, we're cross-compiling) + AC_MSG_NOTICE(Not checking for /dev/ptmx, we're cross-compiling) fi fi @@ -604,7 +612,7 @@ if test x"$cross_compiling" = x"no" ; then AC_CHECK_FILE("/dev/ptc", AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts)) else - AC_MSG_RESULT(Not checking for /dev/ptc & /dev/pts\, we're cross-compiling) + AC_MSG_NOTICE(Not checking for /dev/ptc & /dev/pts\, we're cross-compiling) fi fi @@ -613,5 +621,5 @@ AC_OUTPUT(Makefile) AC_OUTPUT(libtomcrypt/Makefile) AC_OUTPUT(libtommath/Makefile) -AC_MSG_RESULT() -AC_MSG_RESULT(Now edit options.h to choose features.) +AC_MSG_NOTICE() +AC_MSG_NOTICE(Now edit options.h to choose features.) diff -r dba106bf6b34 -r 01e4180895ba dbclient.1 --- a/dbclient.1 Mon Aug 07 13:41:16 2006 +0000 +++ b/dbclient.1 Mon Aug 07 13:41:23 2006 +0000 @@ -29,24 +29,23 @@ .I idfile (multiple allowed). .TP -.B \-L \fIlocalport\fR:\fIremotehost\fR:\fIremoteport\fR +.B \-L \fIlistenport\fR:\fIhost\fR:\fIport\fR Local port forwarding. Forward the port -.I localport -on the local host to port -.I remoteport -on the remote host -.IR remotehost . +.I listenport +on the local host through the SSH connection to port +.I port +on the host +.IR host . .TP -.B \-R \fIlocalport\fR:\fIremotehost\fR:\fIremoteport\fR +.B \-R \fIlistenport\fR:\fIhost\fR:\fIport\fR Remote port forwarding. Forward the port -.I remoteport -on the remote host -.I remotehost -to port -.I localport -on the local host. +.I listenport +on the remote host through the SSH connection to port +.I port +on the host +.IR host . .TP .B \-l \fIuser Username. @@ -60,6 +59,13 @@ .B \-T Don't allocate a pty. .TP +.B \-N +Don't request a remote shell or run any commands. Any command arguments are ignored. +.TP +.B \-f +Fork into the background after authentication. A command argument (or -N) is required. +This is useful when using password authentication. +.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 diff -r dba106bf6b34 -r 01e4180895ba dbutil.c --- a/dbutil.c Mon Aug 07 13:41:16 2006 +0000 +++ b/dbutil.c Mon Aug 07 13:41:23 2006 +0000 @@ -400,7 +400,10 @@ len = sizeof(struct sockaddr_storage); /* Some platforms such as Solaris 8 require that len is the length - * of the specific structure. */ + * of the specific structure. Some older linux systems (glibc 2.1.3 + * such as debian potato) have sockaddr_storage.__ss_family instead + * but we'll ignore them */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY if (addr->ss_family == AF_INET) { len = sizeof(struct sockaddr_in); } @@ -409,6 +412,7 @@ len = sizeof(struct sockaddr_in6); } #endif +#endif ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST); @@ -448,6 +452,7 @@ len = sizeof(struct sockaddr_storage); /* Some platforms such as Solaris 8 require that len is the length * of the specific structure. */ +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY if (addr->ss_family == AF_INET) { len = sizeof(struct sockaddr_in); } @@ -456,6 +461,7 @@ len = sizeof(struct sockaddr_in6); } #endif +#endif ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), diff -r dba106bf6b34 -r 01e4180895ba debian/changelog --- a/debian/changelog Mon Aug 07 13:41:16 2006 +0000 +++ b/debian/changelog Mon Aug 07 13:41:23 2006 +0000 @@ -1,14 +1,38 @@ -dropbear (0.48-0.1) unstable; urgency=high +dropbear (0.49-0.1) unstable; urgency=low * New upstream release. - * SECURITY: Improve handling of denial of service attempts from a single IP. + + -- Matt Johnston Tues, 13 June 2005 19:20:21 +0800 + +dropbear (0.48.1-1) unstable; urgency=medium - -- Matt Johnston Thu, 8 Mar 2006 19:20:21 +0800 + * new upstream point release. + * Compile fix for scp + * debian/diff/dbclient.1.diff: new: document -R option to dbclient + accurately (thx Markus Schaber; closes: #351882). + * debian/dropbear.README.Debian: document a workaround for systems with + possibly blocking /dev/random device (closes: #355414).. -dropbear (0.47-0.1) unstable; urgency=high + -- Gerrit Pape Sun, 16 Apr 2006 16:16:40 +0000 + +dropbear (0.48-1) unstable; urgency=medium * New upstream release. - * SECURITY: Fix incorrect buffer sizing. + * SECURITY: Improve handling of denial of service attempts from a single + IP. + + * debian/implicit: update to revision 1.11. + * new upstream release updates to scp from OpenSSH 4.3p2 - fixes a + security issue where use of system() could cause users to execute + arbitrary code through malformed filenames; CVE-2006-0225 (see also + #349645); the scp binary is not provided by this package though. + + -- Gerrit Pape Fri, 10 Mar 2006 22:00:32 +0000 + +dropbear (0.47-1) unstable; urgency=high + + * New upstream release. + * SECURITY: Fix incorrect buffer sizing; CVE-2005-4178. -- Matt Johnston Thu, 8 Dec 2005 19:20:21 +0800 diff -r dba106bf6b34 -r 01e4180895ba debian/dropbear.README.Debian --- a/debian/dropbear.README.Debian Mon Aug 07 13:41:16 2006 +0000 +++ b/debian/dropbear.README.Debian Mon Aug 07 13:41:23 2006 +0000 @@ -39,3 +39,14 @@ See the Dropbear homepage for more information: http://matt.ucc.asn.au/dropbear/dropbear.html + +Entropy from /dev/random +------------------------ + +The dropbear binary package is configured at compile time to read +entropy from /dev/random. If /dev/random on a system blocks when +reading data from it, client logins may be delayed until the client +times out. The dropbear server writes a notice to the logs when it +sees /dev/random blocking. A workaround for such systems is to +re-compile the package with DROPBEAR_RANDOM_DEV set to /dev/urandom +in options.h. diff -r dba106bf6b34 -r 01e4180895ba debian/implicit --- a/debian/implicit Mon Aug 07 13:41:16 2006 +0000 +++ b/debian/implicit Mon Aug 07 13:41:23 2006 +0000 @@ -1,4 +1,4 @@ -# $Id: implicit,v 1.10 2004/07/03 15:20:00 pape Exp $ +# $Id: implicit,v 1.11 2005/11/29 21:57:55 pape Exp $ .PHONY: deb-checkdir deb-checkuid @@ -38,6 +38,14 @@ @gzip -9 debian/$*/usr/share/doc/$*/changelog* %.deb-docs-docs: @for i in `cat debian/$*.docs 2>/dev/null || :`; do \ + if test -d $$i; then \ + sh -cx "install -d -m0755 debian/$*/usr/share/doc/$*/$${i##*/}" && \ + for j in $$i/*; do \ + sh -cx "install -m0644 $$j \ + debian/$*/usr/share/doc/$*/$${i##*/}/" || exit 1; \ + done || exit 1; \ + continue; \ + fi; \ sh -cx "install -m0644 $$i debian/$*/usr/share/doc/$*/" || exit 1; \ done @test ! -r debian/$*.README.Debian || \ diff -r dba106bf6b34 -r 01e4180895ba debug.h --- a/debug.h Mon Aug 07 13:41:16 2006 +0000 +++ b/debug.h Mon Aug 07 13:41:23 2006 +0000 @@ -44,8 +44,10 @@ /* All functions writing to the cleartext payload buffer call * CHECKCLEARTOWRITE() before writing. This is only really useful if you're * attempting to track down a problem */ -#define CHECKCLEARTOWRITE() assert(ses.writepayload->len == 0 && \ - ses.writepayload->pos == 0) +/*#define CHECKCLEARTOWRITE() assert(ses.writepayload->len == 0 && \ + ses.writepayload->pos == 0)*/ + +#define CHECKCLEARTOWRITE() /* Define this, compile with -pg and set GMON_OUT_PREFIX=gmon to get gmon * output when Dropbear forks. This will allow it gprof to be used. diff -r dba106bf6b34 -r 01e4180895ba dropbear.8 --- a/dropbear.8 Mon Aug 07 13:41:16 2006 +0000 +++ b/dropbear.8 Mon Aug 07 13:41:23 2006 +0000 @@ -72,6 +72,10 @@ under TCP/IP servers like inetd, tcpsvd, or tcpserver. In program mode the \-F option is implied, and \-p options are ignored. .TP +.B \-P \fIpidfile +Specify a pidfile to create when running as a daemon. If not specified, the +default is /var/run/dropbear.pid +.TP .B \-a Allow remote hosts to connect to forwarded ports. .SH AUTHOR diff -r dba106bf6b34 -r 01e4180895ba dropbearkey.c --- a/dropbearkey.c Mon Aug 07 13:41:16 2006 +0000 +++ b/dropbearkey.c Mon Aug 07 13:41:23 2006 +0000 @@ -283,8 +283,10 @@ buf_burn(buf); buf_free(buf); buf = NULL; - sign_key_free(key); - key = NULL; + if (key) { + sign_key_free(key); + key = NULL; + } exit(err); } @@ -297,6 +299,9 @@ const char * typestring = NULL; char *fp = NULL; int len; + struct passwd * pw = NULL; + char * username = NULL; + char hostname[100]; buf = buf_new(MAX_PUBKEY_SIZE); buf_put_pub_key(buf, key, keytype); @@ -315,8 +320,18 @@ fp = sign_key_fingerprint(buf_getptr(buf, len), len); - printf("Public key portion is:\n%s %s\nFingerprint: %s\n", - typestring, base64key, fp); + /* a user@host comment is informative */ + username = ""; + pw = getpwuid(getuid()); + if (pw) { + username = pw->pw_name; + } + + gethostname(hostname, sizeof(hostname)); + hostname[sizeof(hostname)-1] = '\0'; + + printf("Public key portion is:\n%s %s %s@%s\nFingerprint: %s\n", + typestring, base64key, username, hostname, fp); m_free(fp); buf_free(buf); diff -r dba106bf6b34 -r 01e4180895ba dss.c --- a/dss.c Mon Aug 07 13:41:16 2006 +0000 +++ b/dss.c Mon Aug 07 13:41:23 2006 +0000 @@ -338,7 +338,9 @@ /* generate k */ m_mp_init(&dss_protok); bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE); - mp_mod(&dss_protok, key->q, &dss_k); + if (mp_mod(&dss_protok, key->q, &dss_k) != MP_OKAY) { + dropbear_exit("dss error"); + } mp_clear(&dss_protok); m_burn(proto_k, SHA512_HASH_SIZE); #else /* DSS_PROTOK not defined*/ diff -r dba106bf6b34 -r 01e4180895ba includes.h --- a/includes.h Mon Aug 07 13:41:16 2006 +0000 +++ b/includes.h Mon Aug 07 13:41:23 2006 +0000 @@ -135,13 +135,6 @@ #define LOG_AUTHPRIV LOG_AUTH #endif -/* glibc 2.1.3 systems have sockaddr_storage.__ss_family rather than - * sockaddr_storage.ss_family */ -#if !defined(HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) \ - && defined(HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY) -#define ss_family __ss_family -#endif - /* so we can avoid warnings about unused params (ie in signal handlers etc) */ #ifdef UNUSED #elif defined(__GNUC__) diff -r dba106bf6b34 -r 01e4180895ba keyimport.c --- a/keyimport.c Mon Aug 07 13:41:16 2006 +0000 +++ b/keyimport.c Mon Aug 07 13:41:23 2006 +0000 @@ -361,7 +361,7 @@ static struct openssh_key *load_openssh_key(const char *filename) { struct openssh_key *ret; - FILE *fp; + FILE *fp = NULL; char buffer[256]; char *errmsg = NULL, *p = NULL; int headers_done; @@ -482,6 +482,9 @@ memset(&ret, 0, sizeof(ret)); m_free(ret); } + if (fp) { + fclose(fp); + } if (errmsg) { fprintf(stderr, "Error: %s\n", errmsg); } @@ -926,40 +929,6 @@ if (passphrase) { fprintf(stderr, "Encrypted keys aren't supported currently\n"); goto error; -#if 0 - /* - * Invent an iv. Then derive encryption key from passphrase - * and iv/salt: - * - * - let block A equal MD5(passphrase || iv) - * - let block B equal MD5(A || passphrase || iv) - * - block C would be MD5(B || passphrase || iv) and so on - * - encryption key is the first N bytes of A || B - */ - struct MD5Context md5c; - unsigned char keybuf[32]; - - for (i = 0; i < 8; i++) iv[i] = random_byte(); - - MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); - MD5Update(&md5c, iv, 8); - MD5Final(keybuf, &md5c); - - MD5Init(&md5c); - MD5Update(&md5c, keybuf, 16); - MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase)); - MD5Update(&md5c, iv, 8); - MD5Final(keybuf+16, &md5c); - - /* - * Now encrypt the key blob. - */ - des3_encrypt_pubkey_ossh(keybuf, iv, outblob, outlen); - - memset(&md5c, 0, sizeof(md5c)); - memset(keybuf, 0, sizeof(keybuf)); -#endif } /* @@ -976,12 +945,6 @@ goto error; } fputs(header, fp); - if (passphrase) { - fprintf(fp, "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,"); - for (i = 0; i < 8; i++) - fprintf(fp, "%02X", iv[i]); - fprintf(fp, "\n\n"); - } base64_encode_fp(fp, outblob, outlen, 64); fputs(footer, fp); fclose(fp); diff -r dba106bf6b34 -r 01e4180895ba libtommath/bn_mp_div.c --- a/libtommath/bn_mp_div.c Mon Aug 07 13:41:16 2006 +0000 +++ b/libtommath/bn_mp_div.c Mon Aug 07 13:41:23 2006 +0000 @@ -269,7 +269,9 @@ } if (d != NULL) { - mp_div_2d (&x, norm, &x, NULL); + if ((res = mp_div_2d (&x, norm, &x, NULL)) != MP_OKAY) { + goto LBL_Y; + } mp_exch (&x, d); } diff -r dba106bf6b34 -r 01e4180895ba options.h --- a/options.h Mon Aug 07 13:41:16 2006 +0000 +++ b/options.h Mon Aug 07 13:41:23 2006 +0000 @@ -127,8 +127,8 @@ * but there's an interface via a PAM module - don't bother using it otherwise. * You can't enable both PASSWORD and PAM. */ -#define ENABLE_SVR_PASSWORD_AUTH -/* #define ENABLE_SVR_PAM_AUTH */ /* requires ./configure --enable-pam */ +/*#define ENABLE_SVR_PASSWORD_AUTH*/ +#define ENABLE_SVR_PAM_AUTH #define ENABLE_SVR_PUBKEY_AUTH #define ENABLE_CLI_PASSWORD_AUTH @@ -209,7 +209,7 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "0.48" +#define DROPBEAR_VERSION "0.49" #endif #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION @@ -252,6 +252,9 @@ #define DROPBEAR_MAX_PORTS 10 /* max number of ports which can be specified, ipv4 and ipv6 don't count twice */ +/* Each port might have at least a v4 and a v6 address */ +#define MAX_LISTEN_ADDR (DROPBEAR_MAX_PORTS*3) + #define _PATH_TTY "/dev/tty" #define _PATH_CP "/bin/cp" @@ -302,7 +305,6 @@ #define MAX_PROPOSED_ALGO 20 /* size/count limits */ -#define MAX_LISTEN_ADDR 10 #define MAX_PACKET_LEN 35000 #define MIN_PACKET_LEN 16 diff -r dba106bf6b34 -r 01e4180895ba random.c --- a/random.c Mon Aug 07 13:41:16 2006 +0000 +++ b/random.c Mon Aug 07 13:41:23 2006 +0000 @@ -31,7 +31,8 @@ /* this is used to generate unique output from the same hashpool */ static uint32_t counter = 0; -#define MAX_COUNTER 1<<31 /* the max value for the counter, so it won't loop */ +/* the max value for the counter, so it won't integer overflow */ +#define MAX_COUNTER 1<<30 static unsigned char hashpool[SHA1_HASH_SIZE]; @@ -133,7 +134,7 @@ hash_state hs; /* initialise so that things won't warn about - * hashing an undefined buffer */ + * hashing an undefined buffer */ if (!donerandinit) { m_burn(hashpool, sizeof(hashpool)); } @@ -156,18 +157,17 @@ * the random pools for fork()ed processes. */ void reseedrandom() { - pid_t pid; - struct timeval tv; + pid_t pid; + hash_state hs; + struct timeval tv; if (!donerandinit) { dropbear_exit("seedrandom not done"); } - pid = getpid(); - gettimeofday(&tv, NULL); + pid = getpid(); + gettimeofday(&tv, NULL); - hash_state hs; - unsigned char hash[SHA1_HASH_SIZE]; sha1_init(&hs); sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); sha1_process(&hs, (void*)&pid, sizeof(pid)); diff -r dba106bf6b34 -r 01e4180895ba rsa.c --- a/rsa.c Mon Aug 07 13:41:16 2006 +0000 +++ b/rsa.c Mon Aug 07 13:41:23 2006 +0000 @@ -285,18 +285,29 @@ /* rsa_tmp1 is em */ /* em' = em * r^e mod n */ - mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s); /* rsa_s used as a temp var*/ - mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3); - mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2); + /* rsa_s used as a temp var*/ + if (mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s) != MP_OKAY) { + dropbear_exit("rsa error"); + } + if (mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3) != MP_OKAY) { + dropbear_exit("rsa error"); + } + if (mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2) != MP_OKAY) { + dropbear_exit("rsa error"); + } /* rsa_tmp2 is em' */ /* s' = (em')^d mod n */ - mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1); + if (mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1) != MP_OKAY) { + dropbear_exit("rsa error"); + } /* rsa_tmp1 is s' */ /* rsa_tmp3 is r^(-1) mod n */ /* s = (s')r^(-1) mod n */ - mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s); + if (mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s) != MP_OKAY) { + dropbear_exit("rsa error"); + } #else diff -r dba106bf6b34 -r 01e4180895ba runopts.h --- a/runopts.h Mon Aug 07 13:41:16 2006 +0000 +++ b/runopts.h Mon Aug 07 13:41:23 2006 +0000 @@ -83,6 +83,7 @@ sign_key *hostkey; buffer * banner; + char * pidfile; } svr_runopts; @@ -101,6 +102,8 @@ char *cmd; int wantpty; + int no_cmd; + int backgrounded; #ifdef ENABLE_CLI_PUBKEY_AUTH struct SignKeyList *privkeys; /* Keys to use for public-key auth */ #endif diff -r dba106bf6b34 -r 01e4180895ba svr-auth.c --- a/svr-auth.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-auth.c Mon Aug 07 13:41:23 2006 +0000 @@ -315,14 +315,15 @@ buf_setpos(typebuf, 0); buf_putstring(ses.writepayload, buf_getptr(typebuf, typebuf->len), typebuf->len); + + TRACE(("auth fail: methods %d, '%s'", ses.authstate.authtypes, + buf_getptr(typebuf, typebuf->len))); + buf_free(typebuf); buf_putbyte(ses.writepayload, partial ? 1 : 0); encrypt_packet(); - TRACE(("auth fail: methods %d, '%s'", ses.authstate.authtypes, - buf_getptr(typebuf, typebuf->len))); - if (incrfail) { usleep(300000); /* XXX improve this */ ses.authstate.failcount++; diff -r dba106bf6b34 -r 01e4180895ba svr-chansession.c --- a/svr-chansession.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-chansession.c Mon Aug 07 13:41:23 2006 +0000 @@ -67,8 +67,7 @@ extern char** environ; static int sesscheckclose(struct Channel *channel) { - struct ChanSess *chansess = (struct ChanSess*)channel->typedata; - return chansess->exit.exitpid >= 0; + return channel->writefd == -1; } /* Handler for childs exiting, store the state for return to the client */ @@ -89,6 +88,8 @@ TRACE(("enter sigchld handler")) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + + exit = NULL; /* find the corresponding chansess */ for (i = 0; i < svr_ses.childpidsize; i++) { if (svr_ses.childpids[i].pid == pid) { @@ -100,7 +101,7 @@ /* If the pid wasn't matched, then we might have hit the race mentioned * above. So we just store the info for the parent to deal with */ - if (i == svr_ses.childpidsize) { + if (!exit) { exit = &svr_ses.lastexit; } @@ -119,7 +120,6 @@ /* we use this to determine how pid exited */ exit->exitsignal = -1; } - exit = NULL; } @@ -410,7 +410,7 @@ pty_change_window_size(chansess->master, termr, termc, termw, termh); - return DROPBEAR_FAILURE; + return DROPBEAR_SUCCESS; } static void get_termmodes(struct ChanSess *chansess) { diff -r dba106bf6b34 -r 01e4180895ba svr-kex.c --- a/svr-kex.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-kex.c Mon Aug 07 13:41:23 2006 +0000 @@ -52,7 +52,9 @@ } m_mp_init(&dh_e); - buf_getmpint(ses.payload, &dh_e); + if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { + dropbear_exit("Failed to get kex value"); + } send_msg_kexdh_reply(&dh_e); diff -r dba106bf6b34 -r 01e4180895ba svr-main.c --- a/svr-main.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-main.c Mon Aug 07 13:41:23 2006 +0000 @@ -28,6 +28,7 @@ #include "buffer.h" #include "signkey.h" #include "runopts.h" +#include "random.h" static size_t listensockets(int *sock, size_t sockcount, int *maxfd); static void sigchld_handler(int dummy); @@ -145,7 +146,7 @@ } /* create a PID file so that we can be killed easily */ - pidfile = fopen(DROPBEAR_PIDFILE, "w"); + pidfile = fopen(svr_opts.pidfile, "w"); if (pidfile) { fprintf(pidfile, "%d\n", getpid()); fclose(pidfile); @@ -188,7 +189,7 @@ val = select(maxsock+1, &fds, NULL, NULL, &seltimeout); if (exitflag) { - unlink(DROPBEAR_PIDFILE); + unlink(svr_opts.pidfile); dropbear_exit("Terminated by signal"); } diff -r dba106bf6b34 -r 01e4180895ba svr-runopts.c --- a/svr-runopts.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-runopts.c Mon Aug 07 13:41:23 2006 +0000 @@ -72,6 +72,8 @@ #endif "-p port Listen on specified tcp port, up to %d can be specified\n" " (default %s if none specified)\n" + "-P PidFile Create pid file PidFile\n" + " (default %s)\n" #ifdef INETD_MODE "-i Start for inetd\n" #endif @@ -85,7 +87,7 @@ #ifdef DROPBEAR_RSA RSA_PRIV_FILENAME, #endif - DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT); + DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE); } void svr_getopts(int argc, char ** argv) { @@ -105,6 +107,7 @@ svr_opts.inetdmode = 0; svr_opts.portcount = 0; svr_opts.hostkey = NULL; + svr_opts.pidfile = DROPBEAR_PIDFILE; #ifdef ENABLE_SVR_LOCALTCPFWD svr_opts.nolocaltcp = 0; #endif @@ -185,6 +188,9 @@ svr_opts.portcount++; } break; + case 'P': + next = &svr_opts.pidfile; + break; #ifdef DO_MOTD /* motd is displayed by default, -m turns it off */ case 'm': diff -r dba106bf6b34 -r 01e4180895ba svr-tcpfwd.c --- a/svr-tcpfwd.c Mon Aug 07 13:41:16 2006 +0000 +++ b/svr-tcpfwd.c Mon Aug 07 13:41:23 2006 +0000 @@ -216,7 +216,7 @@ 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->listenaddr); + m_free(bindaddr); m_free(tcpinfo); } TRACE(("leave remotetcpreq")) diff -r dba106bf6b34 -r 01e4180895ba tcp-accept.c --- a/tcp-accept.c Mon Aug 07 13:41:16 2006 +0000 +++ b/tcp-accept.c Mon Aug 07 13:41:23 2006 +0000 @@ -131,7 +131,6 @@ tcp_acceptor, cleanup_tcp); if (listener == NULL) { - m_free(tcpinfo); TRACE(("leave listen_tcpfwd: listener failed")) return DROPBEAR_FAILURE; }