summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2006-12-06 13:11:41 +0000
committerMatt Johnston <matt@ucc.asn.au>2006-12-06 13:11:41 +0000
commitd5897b9a5d461c91cd525e5b2212125cf53ad268 (patch)
treecec78b43140a2610175f8e918ae22bfff0bbdf1f
parent7b780efb42e3d9b369b4f00421fba1fc21ec2a22 (diff)
parent35bcc463e5ffe2f630c71962ca12d69a84952568 (diff)
merge of '182c2d8dbd5321ef4d1df8758936f4dc7127015f'
and '31dcd7a22983ef19d6c63248e415e71d292dd0ec' --HG-- extra : convert_revision : e84f66826c7ee6ebe99ef92cc0f6c22ecf638d01
-rw-r--r--CHANGES19
-rw-r--r--Makefile.in12
-rw-r--r--auth.h2
-rw-r--r--cli-auth.c4
-rw-r--r--cli-authinteract.c5
-rw-r--r--cli-authpasswd.c7
-rw-r--r--cli-authpubkey.c1
-rw-r--r--cli-kex.c66
-rw-r--r--cli-runopts.c17
-rw-r--r--cli-service.c2
-rw-r--r--cli-session.c25
-rw-r--r--common-channel.c70
-rw-r--r--common-kex.c20
-rw-r--r--common-session.c4
-rw-r--r--configure.in97
-rw-r--r--dbclient.132
-rw-r--r--dbutil.c32
-rw-r--r--debian/changelog34
-rw-r--r--debian/dropbear.README.Debian11
-rw-r--r--debian/implicit10
-rw-r--r--debug.h6
-rw-r--r--dropbear.84
-rw-r--r--dropbearkey.c23
-rw-r--r--dss.c4
-rw-r--r--includes.h7
-rw-r--r--keyimport.c45
-rw-r--r--libtomcrypt/Makefile.in2
-rw-r--r--libtommath/bn_mp_div.c4
-rw-r--r--options.h14
-rw-r--r--rsa.c21
-rw-r--r--runopts.h3
-rw-r--r--svr-chansession.c18
-rw-r--r--svr-kex.c4
-rw-r--r--svr-main.c4
-rw-r--r--svr-runopts.c8
-rw-r--r--svr-tcpfwd.c2
36 files changed, 438 insertions, 201 deletions
diff --git a/CHANGES b/CHANGES
index 5e07ffd..41d25ba 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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 --git a/Makefile.in b/Makefile.in
index fc17c1f..f5b111f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -64,12 +64,12 @@ bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
CC=@CC@
-LD=@LD@
AR=@AR@
RANLIB=@RANLIB@
STRIP=@STRIP@
INSTALL=@INSTALL@
-CFLAGS=-I. -I$(srcdir)/libtomcrypt/src/headers/ @CFLAGS@
+CPPFLAGS=@CPPFLAGS@
+CFLAGS=-I. -I$(srcdir) -I$(srcdir)/libtomcrypt/src/headers/ $(CPPFLAGS) @CFLAGS@
LIBS=$(LTC) $(LTM) @LIBS@
LDFLAGS=@LDFLAGS@
@@ -155,11 +155,11 @@ dropbearconvert: $(dropbearconvertobjs)
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM) \
Makefile
- $(LD) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBS)
+ $(CC) $(LDFLAGS) -o $@$(EXEEXT) $($@objs) $(LIBS)
# scp doesn't use the libs so is special.
scp: $(SCPOBJS) $(HEADERS) Makefile
- $(LD) $(LDFLAGS) -o $@$(EXEEXT) $(SCPOBJS)
+ $(CC) $(LDFLAGS) -o $@$(EXEEXT) $(SCPOBJS)
# multi-binary compilation.
@@ -172,7 +172,7 @@ endif
dropbearmulti: multilink
multibinary: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM) Makefile
- $(LD) $(LDFLAGS) -o dropbearmulti$(EXEEXT) $(MULTIOBJS) $(LIBS)
+ $(CC) $(LDFLAGS) -o dropbearmulti$(EXEEXT) $(MULTIOBJS) $(LIBS)
multilink: multibinary $(addprefix link, $(PROGRAMS))
@@ -186,6 +186,8 @@ $(LTC): options.h
$(LTM): options.h
cd libtommath && $(MAKE)
+.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean
+
ltc-clean:
cd libtomcrypt && $(MAKE) clean
diff --git a/auth.h b/auth.h
index c407ad5..661265a 100644
--- a/auth.h
+++ b/auth.h
@@ -52,7 +52,7 @@ void cli_pubkeyfail();
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 --git a/cli-auth.c b/cli-auth.c
index ba4cf6c..4c17a21 100644
--- a/cli-auth.c
+++ b/cli-auth.c
@@ -281,11 +281,11 @@ void cli_auth_try() {
/* 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 --git a/cli-authinteract.c b/cli-authinteract.c
index 5a169cb..5fe5bf1 100644
--- a/cli-authinteract.c
+++ b/cli-authinteract.c
@@ -99,13 +99,14 @@ void recv_msg_userauth_info_request() {
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 --git a/cli-authpasswd.c b/cli-authpasswd.c
index 5dffac4..2500a25 100644
--- a/cli-authpasswd.c
+++ b/cli-authpasswd.c
@@ -116,16 +116,19 @@ static char *gui_getpass(const char *prompt) {
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 --git a/cli-authpubkey.c b/cli-authpubkey.c
index 9d36bc3..8a8fb42 100644
--- a/cli-authpubkey.c
+++ b/cli-authpubkey.c
@@ -112,6 +112,7 @@ void recv_msg_userauth_pk_ok() {
/* Success */
break;
}
+ buf_free(keybuf);
if (keyitem != NULL) {
TRACE(("matching key"))
diff --git a/cli-kex.c b/cli-kex.c
index 40d4e95..467ae23 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -122,6 +122,7 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
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 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
}
if (response == 'y') {
- m_free(fp);
return;
}
@@ -145,49 +145,59 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
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*/
-
- 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 */
+ if (homedir) {
+
+ len = strlen(homedir);
+ filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/
+
+ 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 --git a/cli-runopts.c b/cli-runopts.c
index 54d4875..7a672da 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -44,12 +44,14 @@ static void addforward(char* str, struct TCPFwdList** fwdlist);
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 <remoteport>\n"
"-l <username>\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 <identityfile> (multiple allowed)\n"
#endif
@@ -88,6 +90,8 @@ void cli_getopts(int argc, char ** argv) {
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 @@ void cli_getopts(int argc, char ** argv) {
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 @@ void cli_getopts(int argc, char ** argv) {
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 --git a/cli-service.c b/cli-service.c
index 87b6ed2..57807be 100644
--- a/cli-service.c
+++ b/cli-service.c
@@ -82,6 +82,4 @@ void recv_msg_service_accept() {
}
dropbear_exit("unrecognised service accept");
- /* m_free(servicename); not reached */
-
}
diff --git a/cli-session.c b/cli-session.c
index 35510fa..be36bec 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -212,19 +212,38 @@ static void cli_sessionloop() {
*/
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 --git a/common-channel.c b/common-channel.c
index 0be354d..11760ec 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -181,6 +181,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
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 @@ void channelio(fd_set *readfds, fd_set *writefds) {
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) {
@@ -241,27 +261,27 @@ static void checkclose(struct Channel *channel) {
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 @@ void setchannelfds(fd_set *readfds, fd_set *writefds) {
}
}
+ 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 --git a/common-kex.c b/common-kex.c
index 5db8e52..af39d1a 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -262,6 +262,7 @@ void gen_new_keys() {
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 @@ void gen_new_keys() {
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 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
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 --git a/common-session.c b/common-session.c
index 4c15391..b8ea6f7 100644
--- a/common-session.c
+++ b/common-session.c
@@ -229,7 +229,7 @@ void session_identification() {
/* 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 @@ void session_identification() {
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 --git a/configure.in b/configure.in
index e860831..798becc 100644
--- a/configure.in
+++ b/configure.in
@@ -19,10 +19,13 @@ fi
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 @@ dnl Can't use login() or logout() with uclibc
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 @@ AC_ARG_ENABLE(zlib,
[
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 @@ AC_ARG_ENABLE(pam,
[
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 @@ AC_ARG_ENABLE(openpty,
[ --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 @@ AC_ARG_ENABLE(syslog,
[
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 @@ AC_ARG_ENABLE(shadow,
[ --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 @@ AC_CHECK_MEMBERS([struct utmp.ut_host, struct utmp.ut_pid, struct utmp.ut_type,
#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 <sys/types.h>
#include <sys/socket.h>
#if HAVE_UTMPX_H
@@ -347,6 +350,11 @@ AC_CHECK_MEMBERS([struct utmpx.ut_host, struct utmpx.ut_syslen, struct utmpx.ut_
#endif
])
+AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family],,,[
+#include <sys/types.h>
+#include <sys/socket.h>
+])
+
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(wtmpx,
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 -z "$no_ptmx_check" ; then
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,14 +612,57 @@ if test -z "$no_ptc_check" ; then
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
AC_EXEEXT
+
+# XXX there must be a nicer way to do this
+AS_MKDIR_P(libtomcrypt/src/ciphers/aes)
+AS_MKDIR_P(libtomcrypt/src/ciphers/safer)
+AS_MKDIR_P(libtomcrypt/src/ciphers/twofish)
+AS_MKDIR_P(libtomcrypt/src/encauth/ccm)
+AS_MKDIR_P(libtomcrypt/src/encauth/eax)
+AS_MKDIR_P(libtomcrypt/src/encauth/gcm)
+AS_MKDIR_P(libtomcrypt/src/encauth/ocb)
+AS_MKDIR_P(libtomcrypt/src/hashes)
+AS_MKDIR_P(libtomcrypt/src/hashes/chc)
+AS_MKDIR_P(libtomcrypt/src/hashes/helper)
+AS_MKDIR_P(libtomcrypt/src/hashes/sha2)
+AS_MKDIR_P(libtomcrypt/src/hashes/whirl)
+AS_MKDIR_P(libtomcrypt/src/mac/hmac)
+AS_MKDIR_P(libtomcrypt/src/mac/omac)
+AS_MKDIR_P(libtomcrypt/src/mac/pelican)
+AS_MKDIR_P(libtomcrypt/src/mac/pmac)
+AS_MKDIR_P(libtomcrypt/src/misc/base64)
+AS_MKDIR_P(libtomcrypt/src/misc/crypt)
+AS_MKDIR_P(libtomcrypt/src/misc/mpi)
+AS_MKDIR_P(libtomcrypt/src/misc/pkcs5)
+AS_MKDIR_P(libtomcrypt/src/modes/cbc)
+AS_MKDIR_P(libtomcrypt/src/modes/cfb)
+AS_MKDIR_P(libtomcrypt/src/modes/ctr)
+AS_MKDIR_P(libtomcrypt/src/modes/ecb)
+AS_MKDIR_P(libtomcrypt/src/modes/ofb)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/bit)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/choice)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/ia5)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/integer)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/object_identifier)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/octet)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/printable_string)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/sequence)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/short_integer)
+AS_MKDIR_P(libtomcrypt/src/pk/asn1/der/utctime)
+AS_MKDIR_P(libtomcrypt/src/pk/dh)
+AS_MKDIR_P(libtomcrypt/src/pk/dsa)
+AS_MKDIR_P(libtomcrypt/src/pk/ecc)
+AS_MKDIR_P(libtomcrypt/src/pk/pkcs1)
+AS_MKDIR_P(libtomcrypt/src/pk/rsa)
+AS_MKDIR_P(libtomcrypt/src/prng)
AC_CONFIG_HEADER(config.h)
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 --git a/dbclient.1 b/dbclient.1
index 4d7cc3c..c91c272 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -29,24 +29,23 @@ Read the identity from file
.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 @@ Allocate a pty.
.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 --git a/dbutil.c b/dbutil.c
index 15f51ba..9445f0e 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -400,7 +400,10 @@ unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
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 @@ unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
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 @@ char* getaddrhostname(struct sockaddr_storage * addr) {
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 @@ char* getaddrhostname(struct sockaddr_storage * addr) {
len = sizeof(struct sockaddr_in6);
}
#endif
+#endif
ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
@@ -521,26 +527,36 @@ char * stripcontrol(const char * text) {
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_readfile(buffer* buf, const char* filename) {
- int fd;
+ int fd = -1;
int len;
int maxlen;
+ int ret = DROPBEAR_FAILURE;
fd = open(filename, O_RDONLY);
if (fd < 0) {
- close(fd);
- return DROPBEAR_FAILURE;
+ goto out;
}
do {
maxlen = buf->size - buf->pos;
- len = read(fd, buf_getwriteptr(buf, maxlen),
- maxlen);
+ len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
+ if (len < 0) {
+ if (errno == EINTR || errno == EAGAIN) {
+ continue;
+ }
+ goto out;
+ }
buf_incrwritepos(buf, len);
} while (len < maxlen && len > 0);
- close(fd);
- return DROPBEAR_SUCCESS;
+ ret = DROPBEAR_SUCCESS;
+
+out:
+ if (fd >= 0) {
+ m_close(fd);
+ }
+ return ret;
}
/* get a line from the file into buffer in the style expected for an
diff --git a/debian/changelog b/debian/changelog
index 4bdb895..acebcef 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -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 <matt@ucc.asn.au> Thu, 8 Mar 2006 19:20:21 +0800
+ -- Matt Johnston <matt@ucc.asn.au> Tues, 13 June 2005 19:20:21 +0800
-dropbear (0.47-0.1) unstable; urgency=high
+dropbear (0.48.1-1) unstable; urgency=medium
+
+ * 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)..
+
+ -- Gerrit Pape <pape@smarden.org> Sun, 16 Apr 2006 16:16:40 +0000
+
+dropbear (0.48-1) unstable; urgency=medium
+
+ * New upstream release.
+ * 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 <pape@smarden.org> Fri, 10 Mar 2006 22:00:32 +0000
+
+dropbear (0.47-1) unstable; urgency=high
* New upstream release.
- * SECURITY: Fix incorrect buffer sizing.
+ * SECURITY: Fix incorrect buffer sizing; CVE-2005-4178.
-- Matt Johnston <matt@ucc.asn.au> Thu, 8 Dec 2005 19:20:21 +0800
diff --git a/debian/dropbear.README.Debian b/debian/dropbear.README.Debian
index 8cdac38..7eec3e6 100644
--- a/debian/dropbear.README.Debian
+++ b/debian/dropbear.README.Debian
@@ -39,3 +39,14 @@ by following these steps:
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 --git a/debian/implicit b/debian/implicit
index 57a444a..7a7ee98 100644
--- a/debian/implicit
+++ b/debian/implicit
@@ -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 @@ deb-checkuid:
@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 --git a/debug.h b/debug.h
index 93cb891..0cb4691 100644
--- a/debug.h
+++ b/debug.h
@@ -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 --git a/dropbear.8 b/dropbear.8
index 38cf7e2..fbbb26b 100644
--- a/dropbear.8
+++ b/dropbear.8
@@ -72,6 +72,10 @@ Use this option to run
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 --git a/dropbearkey.c b/dropbearkey.c
index 8ceefdc..2433381 100644
--- a/dropbearkey.c
+++ b/dropbearkey.c
@@ -283,8 +283,10 @@ out:
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 @@ static void printpubkey(sign_key * key, int keytype) {
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 @@ static void printpubkey(sign_key * key, int keytype) {
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 --git a/dss.c b/dss.c
index 9b25dcc..bcfbb61 100644
--- a/dss.c
+++ b/dss.c
@@ -341,7 +341,9 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
/* 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 --git a/includes.h b/includes.h
index da974cc..1fcf634 100644
--- a/includes.h
+++ b/includes.h
@@ -135,13 +135,6 @@ typedef u_int16_t uint16_t;
#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 --git a/keyimport.c b/keyimport.c
index a0474f3..1d3e3f5 100644
--- a/keyimport.c
+++ b/keyimport.c
@@ -361,7 +361,7 @@ struct openssh_key {
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 @@ static struct openssh_key *load_openssh_key(const char *filename)
memset(&ret, 0, sizeof(ret));
m_free(ret);
}
+ if (fp) {
+ fclose(fp);
+ }
if (errmsg) {
fprintf(stderr, "Error: %s\n", errmsg);
}
@@ -926,40 +929,6 @@ static int openssh_write(const char *filename, sign_key *key,
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 @@ static int openssh_write(const char *filename, sign_key *key,
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 --git a/libtomcrypt/Makefile.in b/libtomcrypt/Makefile.in
index e1bee57..f1cfdad 100644
--- a/libtomcrypt/Makefile.in
+++ b/libtomcrypt/Makefile.in
@@ -158,7 +158,7 @@ default:library
#ciphers come in two flavours... enc+dec and enc
src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c
- $(CC) $(CFLAGS) -DENCRYPT_ONLY -c src/ciphers/aes/aes.c -o src/ciphers/aes/aes_enc.o
+ $(CC) $(CFLAGS) -DENCRYPT_ONLY -c $< -o src/ciphers/aes/aes_enc.o
#These are the rules to make certain object files.
src/ciphers/aes/aes.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c
diff --git a/libtommath/bn_mp_div.c b/libtommath/bn_mp_div.c
index 6b2b8f0..6e1e0fb 100644
--- a/libtommath/bn_mp_div.c
+++ b/libtommath/bn_mp_div.c
@@ -269,7 +269,9 @@ int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
}
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 --git a/options.h b/options.h
index 0349fa9..ad82f8b 100644
--- a/options.h
+++ b/options.h
@@ -128,7 +128,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
* 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_PAM_AUTH */
#define ENABLE_SVR_PUBKEY_AUTH
#define ENABLE_CLI_PASSWORD_AUTH
@@ -199,15 +199,17 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
* not using the Dropbear client, you'll need to change it */
#define _PATH_SSH_PROGRAM "/usr/bin/dbclient"
-/* Multi-purpose binary configuration has now moved. Look at the top
- * of the Makefile for instructions, or INSTALL */
+/* Whether to log commands executed by a client. This only logs the
+ * (single) command sent to the server, not what a user did in a
+ * shell/sftp session etc. */
+/* #define LOG_COMMANDS */
/*******************************************************************
* You shouldn't edit below here unless you know you need to.
*******************************************************************/
#ifndef DROPBEAR_VERSION
-#define DROPBEAR_VERSION "0.48"
+#define DROPBEAR_VERSION "0.49"
#endif
#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
@@ -250,6 +252,9 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
#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"
@@ -300,7 +305,6 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
#define MAX_PROPOSED_ALGO 20
/* size/count limits */
-#define MAX_LISTEN_ADDR 10
#define MAX_PACKET_LEN 35000
#define MIN_PACKET_LEN 16
diff --git a/rsa.c b/rsa.c
index 0715ce1..bc665f2 100644
--- a/rsa.c
+++ b/rsa.c
@@ -300,18 +300,29 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data,
/* 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 --git a/runopts.h b/runopts.h
index 5107a9d..c3db42c 100644
--- a/runopts.h
+++ b/runopts.h
@@ -83,6 +83,7 @@ typedef struct svr_runopts {
sign_key *hostkey;
buffer * banner;
+ char * pidfile;
} svr_runopts;
@@ -101,6 +102,8 @@ typedef struct cli_runopts {
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 --git a/svr-chansession.c b/svr-chansession.c
index 90b58f0..19c4f4a 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -67,8 +67,7 @@ static void get_termmodes(struct ChanSess *chansess);
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 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
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) {
@@ -119,7 +120,6 @@ static void sesssigchild_handler(int UNUSED(dummy)) {
/* we use this to determine how pid exited */
exit->exitsignal = -1;
}
- exit = NULL;
}
@@ -410,7 +410,7 @@ static int sessionwinchange(struct ChanSess *chansess) {
pty_change_window_size(chansess->master, termr, termc, termw, termh);
- return DROPBEAR_FAILURE;
+ return DROPBEAR_SUCCESS;
}
static void get_termmodes(struct ChanSess *chansess) {
@@ -588,6 +588,16 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
}
}
+#ifdef LOG_COMMANDS
+ if (chansess->cmd) {
+ dropbear_log(LOG_INFO, "user %s executing '%s'",
+ ses.authstate.printableuser, chansess->cmd);
+ } else {
+ dropbear_log(LOG_INFO, "user %s executing login shell",
+ ses.authstate.printableuser);
+ }
+#endif
+
if (chansess->term == NULL) {
/* no pty */
ret = noptycommand(channel, chansess);
diff --git a/svr-kex.c b/svr-kex.c
index a9954bb..75cb090 100644
--- a/svr-kex.c
+++ b/svr-kex.c
@@ -52,7 +52,9 @@ void recv_msg_kexdh_init() {
}
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 --git a/svr-main.c b/svr-main.c
index e00de6b..a14c6e6 100644
--- a/svr-main.c
+++ b/svr-main.c
@@ -146,7 +146,7 @@ void main_noinetd() {
}
/* 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);
@@ -189,7 +189,7 @@ void main_noinetd() {
val = select(maxsock+1, &fds, NULL, NULL, &seltimeout);
if (exitflag) {
- unlink(DROPBEAR_PIDFILE);
+ unlink(svr_opts.pidfile);
dropbear_exit("Terminated by signal");
}
diff --git a/svr-runopts.c b/svr-runopts.c
index 8d8b8df..784e0ca 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -72,6 +72,8 @@ static void printhelp(const char * progname) {
#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 @@ static void printhelp(const char * progname) {
#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 @@ void svr_getopts(int argc, char ** argv) {
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 @@ void svr_getopts(int argc, char ** argv) {
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 --git a/svr-tcpfwd.c b/svr-tcpfwd.c
index 6391c4c..d4dca6b 100644
--- a/svr-tcpfwd.c
+++ b/svr-tcpfwd.c
@@ -216,7 +216,7 @@ 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->listenaddr);
+ m_free(bindaddr);
m_free(tcpinfo);
}
TRACE(("leave remotetcpreq"))