The unified diff between revisions [4cbdd6e0..] and [4c883eb4..] is displayed below. It can also be downloaded as a raw diff.
#
#
# patch "auth.h"
# from [84e61bd4fb2b09bcc8e5bef98e4d5c71fde907a2]
# to [c541f307bc55bce59169119bfaac5608d66c9687]
#
# patch "cli-auth.c"
# from [eb6d2144c4d4b27aaa50b7b1a1f2b879a9c0a06f]
# to [3b308d18cc57b0b95f782bc7e4d8ea118a974343]
#
# patch "cli-authinteract.c"
# from [001567a2e62e0f5f87d73463ab4f6e1f85415f35]
# to [c65d9c192f42ce4654ec4e8d6765b11e4f5ca9a9]
#
# patch "cli-authpasswd.c"
# from [ac2864b6001ecb7272b258aeee75ed1287d745e2]
# to [f90967c3816ba60765b1027a373209206fc73b4f]
#
# patch "cli-session.c"
# from [49416025c7fc3883ad9b8975474ad68307b24717]
# to [74a7cf84c59c70bc92142ba7d75aa49f8be2fa2b]
#
# patch "common-channel.c"
# from [7fbf9449681eb0dc6cb4bc553a0691b8c0838a0e]
# to [73156662683bd6d4401257f7315934f5ac053c89]
#
# patch "common-session.c"
# from [2469aa8351074283ffeaaf89f3c56a87f15cc0ed]
# to [96eecb59aa3e87bb0a2364636f6d7a5035bfb2ff]
#
# patch "random.c"
# from [6b27327c1fd2cc9eca918be77a997c93404ab00d]
# to [a83e157ef0889daf7bb2b91fc8fe98e5d03d7dfe]
#
# patch "random.h"
# from [128a6e472a5e4900a7458ceda877961affa43c24]
# to [3a02d46ff409f774f6cb2b85059084e50a4b7d8f]
#
# patch "scp.c"
# from [4ef18ec9a3c36d87f1f28efc1a0186bdaf7548b3]
# to [589bc8c7aeca0bfc20e5d0ddb3e9c5dc17509ae0]
#
# patch "svr-chansession.c"
# from [ab83b6c177a51cefc83b038932c9fc1e9b296692]
# to [248542573188674e77293507ac3a23b081041f56]
#
# patch "svr-main.c"
# from [5c0e59de51df9c03a47947b7dcd100053623bfd3]
# to [018c4a2cc2dd9cee3cca8b162ec50551fd7a30be]
#
# patch "svr-runopts.c"
# from [f68d09f9fe84a764badcdd18a0f69b14e44cb0e8]
# to [dddf02f4bdfdd604ebf291af5ce48fa0fb8d6924]
#
# patch "svr-session.c"
# from [81c3452c7ce320dcb17826c8acc672e6ebee559d]
# to [b43a0a676506ef61f10c21f4cd6e82c9fd5154a3]
#
# patch "svr-tcpfwd.c"
# from [bfd47e1ced10186c0d9ce06dca0f0d3694e9c3df]
# to [aa3d9bd98b61f4a84f5b28b1debc66a2b398045b]
#
============================================================
--- auth.h 84e61bd4fb2b09bcc8e5bef98e4d5c71fde907a2
+++ auth.h c541f307bc55bce59169119bfaac5608d66c9687
@@ -52,6 +52,7 @@ void cli_auth_interactive();
void cli_auth_password();
int cli_auth_pubkey();
void cli_auth_interactive();
+char* getpass_or_cancel();
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
============================================================
--- cli-auth.c eb6d2144c4d4b27aaa50b7b1a1f2b879a9c0a06f
+++ cli-auth.c 3b308d18cc57b0b95f782bc7e4d8ea118a974343
@@ -278,3 +278,18 @@ void cli_auth_try() {
TRACE(("leave 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* password = NULL;
+
+ password = getpass("Password: ");
+
+ /* 0x03 is a ctrl-c character in the buffer. */
+ if (password == NULL || strchr(password, '\3') != NULL) {
+ dropbear_close("Interrupted.");
+ }
+ return password;
+}
============================================================
--- cli-authinteract.c 001567a2e62e0f5f87d73463ab4f6e1f85415f35
+++ cli-authinteract.c c65d9c192f42ce4654ec4e8d6765b11e4f5ca9a9
@@ -115,7 +115,7 @@ void recv_msg_userauth_info_request() {
echo = buf_getbool(ses.payload);
if (!echo) {
- unsigned char* p = getpass(prompt);
+ unsigned char* p = getpass_or_cancel(prompt);
response = m_strdup(p);
m_burn(p, strlen(p));
} else {
============================================================
--- cli-authpasswd.c ac2864b6001ecb7272b258aeee75ed1287d745e2
+++ cli-authpasswd.c f90967c3816ba60765b1027a373209206fc73b4f
@@ -125,11 +125,8 @@ void cli_auth_password() {
password = gui_getpass("Password: ");
else
#endif
- password = getpass("Password: ");
+ password = getpass_or_cancel("Password: ");
- if (password == NULL)
- return 0;
-
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
============================================================
--- cli-session.c 49416025c7fc3883ad9b8975474ad68307b24717
+++ cli-session.c 74a7cf84c59c70bc92142ba7d75aa49f8be2fa2b
@@ -76,12 +76,14 @@ void cli_session(int sock, char* remoteh
void cli_session(int sock, char* remotehost) {
+ seedrandom();
+
crypto_init();
+
common_session_init(sock, remotehost);
chaninitialise(cli_chantypes);
-
/* Set up cli_ses vars */
cli_session_init();
@@ -91,12 +93,8 @@ void cli_session(int sock, char* remoteh
/* Exchange identification */
session_identification();
- seedrandom();
-
send_msg_kexinit();
- /* XXX here we do stuff differently */
-
session_loop(cli_sessionloop);
/* Not reached */
============================================================
--- common-channel.c 7fbf9449681eb0dc6cb4bc553a0691b8c0838a0e
+++ common-channel.c 73156662683bd6d4401257f7315934f5ac053c89
@@ -376,7 +376,7 @@ static void writechannel(struct Channel*
cbuf_incrread(cbuf, len);
channel->recvdonelen += len;
- if (fd == channel->writefd && len == maxlen && channel->recveof) {
+ if (fd == channel->writefd && cbuf_getused(cbuf) == 0 && channel->recveof) {
/* Check if we're closing up */
closewritefd(channel);
TRACE(("leave writechannel: recveof set"))
============================================================
--- common-session.c 2469aa8351074283ffeaaf89f3c56a87f15cc0ed
+++ common-session.c 96eecb59aa3e87bb0a2364636f6d7a5035bfb2ff
@@ -232,10 +232,8 @@ void session_identification() {
dropbear_exit("Error writing ident string");
}
- /* We allow up to 9 lines before the actual version string, to
- * account for wrappers/cruft etc. According to the spec only the client
- * needs to handle this, but no harm in letting the server handle it too */
- for (i = 0; i < 10; i++) {
+ /* If they send more than 50 lines, something is wrong */
+ for (i = 0; i < 50; i++) {
len = ident_readln(ses.sock, linebuf, sizeof(linebuf));
if (len < 0 && errno != EINTR) {
@@ -259,6 +257,12 @@ void session_identification() {
memcpy(ses.remoteident, linebuf, len);
}
+ /* Shall assume that 2.x will be backwards compatible. */
+ if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
+ && strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
+ dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
+ }
+
TRACE(("remoteident: %s", ses.remoteident))
}
============================================================
--- random.c 6b27327c1fd2cc9eca918be77a997c93404ab00d
+++ random.c a83e157ef0889daf7bb2b91fc8fe98e5d03d7dfe
@@ -30,8 +30,8 @@ static int donerandinit = 0;
static int donerandinit = 0;
/* this is used to generate unique output from the same hashpool */
-static unsigned int counter = 0;
-#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */
+static uint32_t counter = 0;
+#define MAX_COUNTER 1<<31 /* the max value for the counter, so it won't loop */
static unsigned char hashpool[SHA1_HASH_SIZE];
@@ -132,7 +132,8 @@ void seedrandom() {
hash_state hs;
- /* initialise so compilers will be happy about hashing it */
+ /* initialise so that things won't warn about
+ * hashing an undefined buffer */
if (!donerandinit) {
m_burn(hashpool, sizeof(hashpool));
}
@@ -150,6 +151,30 @@ void seedrandom() {
donerandinit = 1;
}
+/* hash the current random pool with some unique identifiers
+ * for this process and point-in-time. this is used to separate
+ * the random pools for fork()ed processes. */
+void reseedrandom() {
+
+ pid_t pid;
+ struct timeval tv;
+
+ if (!donerandinit) {
+ dropbear_exit("seedrandom not done");
+ }
+
+ 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));
+ sha1_process(&hs, (void*)&tv, sizeof(tv));
+ sha1_done(&hs, hashpool);
+}
+
/* return len bytes of pseudo-random data */
void genrandom(unsigned char* buf, unsigned int len) {
============================================================
--- random.h 128a6e472a5e4900a7458ceda877961affa43c24
+++ random.h 3a02d46ff409f774f6cb2b85059084e50a4b7d8f
@@ -28,6 +28,7 @@ void seedrandom();
struct mp_int;
void seedrandom();
+void reseedrandom();
void genrandom(unsigned char* buf, int len);
void addrandom(unsigned char* buf, int len);
void gen_random_mpint(mp_int *max, mp_int *rand);
============================================================
--- scp.c 4ef18ec9a3c36d87f1f28efc1a0186bdaf7548b3
+++ scp.c 589bc8c7aeca0bfc20e5d0ddb3e9c5dc17509ae0
@@ -166,8 +166,22 @@ do_cmd(char *host, char *remuser, char *
close(reserved[0]);
close(reserved[1]);
+ // uClinux needs to build the args here before vforking,
+ // otherwise we do it later on.
+#ifdef __uClinux__
+ args.list[0] = ssh_program;
+ if (remuser != NULL)
+ addargs(&args, "-l%s", remuser);
+ addargs(&args, "%s", host);
+ addargs(&args, "%s", cmd);
+#endif /* __uClinux__ */
+
/* Fork a child to execute the command on the remote host using ssh. */
+#ifdef __uClinux__
+ do_cmd_pid = vfork();
+#else
do_cmd_pid = fork();
+#endif /* __uClinux__ */
if (do_cmd_pid == 0) {
/* Child. */
close(pin[1]);
@@ -177,6 +191,7 @@ do_cmd(char *host, char *remuser, char *
close(pin[0]);
close(pout[1]);
+#ifndef __uClinux__
args.list[0] = ssh_program;
if (remuser != NULL) {
addargs(&args, "-l");
@@ -184,6 +199,7 @@ do_cmd(char *host, char *remuser, char *
}
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
+#endif
execvp(ssh_program, args.list);
perror(ssh_program);
@@ -192,6 +208,22 @@ do_cmd(char *host, char *remuser, char *
fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno));
exit(1);
}
+
+#ifdef __uClinux__
+ /* clean up command */
+ /* pop cmd */
+ free(args->list[--args->num]);
+ args->list[args->num]=NULL;
+ /* pop host */
+ free(args->list[--args->num-1]);
+ args->list[args->num]=NULL;
+ /* pop user */
+ if (remuser != NULL) {
+ free(args->list[--args->num-1]);
+ args->list[args->num]=NULL;
+ }
+#endif /* __uClinux__
+
/* Parent. Close the other side, and return the local side. */
close(pin[0]);
*fdout = pin[1];
============================================================
--- svr-chansession.c ab83b6c177a51cefc83b038932c9fc1e9b296692
+++ svr-chansession.c 248542573188674e77293507ac3a23b081041f56
@@ -623,7 +623,12 @@ static int noptycommand(struct Channel *
if (pipe(errfds) != 0)
return DROPBEAR_FAILURE;
+#ifdef __uClinux__
+ pid = vfork();
+#else
pid = fork();
+#endif
+
if (pid < 0)
return DROPBEAR_FAILURE;
@@ -714,7 +719,11 @@ static int ptycommand(struct Channel *ch
return DROPBEAR_FAILURE;
}
+#ifdef __uClinux__
+ pid = vfork();
+#else
pid = fork();
+#endif
if (pid < 0)
return DROPBEAR_FAILURE;
@@ -828,12 +837,16 @@ static void execchild(struct ChanSess *c
char * baseshell = NULL;
unsigned int i;
+ /* with uClinux we'll have vfork()ed, so don't want to overwrite the
+ * hostkey. can't think of a workaround to clear it */
+#ifndef __uClinux__
/* wipe the hostkey */
sign_key_free(svr_opts.hostkey);
svr_opts.hostkey = NULL;
/* overwrite the prng state */
- seedrandom();
+ reseedrandom();
+#endif
/* close file descriptors except stdin/stdout/stderr
* Need to be sure FDs are closed here to avoid reading files as root */
============================================================
--- svr-main.c 5c0e59de51df9c03a47947b7dcd100053623bfd3
+++ svr-main.c 018c4a2cc2dd9cee3cca8b162ec50551fd7a30be
@@ -83,7 +83,7 @@ static void main_inetd() {
int remoteaddrlen;
char * addrstring = NULL;
- /* Set up handlers, syslog */
+ /* Set up handlers, syslog, seed random */
commonsetup();
remoteaddrlen = sizeof(remoteaddr);
@@ -359,6 +359,8 @@ static void commonsetup() {
/* Now we can setup the hostkeys - needs to be after logging is on,
* otherwise we might end up blatting error messages to the socket */
loadhostkeys();
+
+ seedrandom();
}
/* Set up listening sockets for all the requested ports */
============================================================
--- svr-runopts.c f68d09f9fe84a764badcdd18a0f69b14e44cb0e8
+++ svr-runopts.c dddf02f4bdfdd604ebf291af5ce48fa0fb8d6924
@@ -105,8 +105,12 @@ void svr_getopts(int argc, char ** argv)
svr_opts.inetdmode = 0;
svr_opts.portcount = 0;
svr_opts.hostkey = NULL;
+#ifdef ENABLE_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0;
+#endif
+#ifdef ENABLE_SVR_REMOTETCPFWD
svr_opts.noremotetcp = 0;
+#endif
/* not yet
opts.ipv4 = 1;
opts.ipv6 = 1;
@@ -154,12 +158,12 @@ void svr_getopts(int argc, char ** argv)
svr_opts.usingsyslog = 0;
break;
#endif
-#ifndef DISABLE_LOCALTCPFWD
+#ifdef ENABLE_SVR_LOCALTCPFWD
case 'j':
svr_opts.nolocaltcp = 1;
break;
#endif
-#ifndef DISABLE_REMOTETCPFWD
+#ifdef ENABLE_SVR_REMOTETCPFWD
case 'k':
svr_opts.noremotetcp = 1;
break;
============================================================
--- svr-session.c 81c3452c7ce320dcb17826c8acc672e6ebee559d
+++ svr-session.c b43a0a676506ef61f10c21f4cd6e82c9fd5154a3
@@ -78,7 +78,9 @@ void svr_session(int sock, int childpipe
char* remotehost, char *addrstring) {
struct timeval timeout;
-
+
+ reseedrandom();
+
crypto_init();
common_session_init(sock, remotehost);
@@ -110,8 +112,6 @@ void svr_session(int sock, int childpipe
/* exchange identification, version etc */
session_identification();
- seedrandom();
-
/* start off with key exchange */
send_msg_kexinit();
============================================================
--- svr-tcpfwd.c bfd47e1ced10186c0d9ce06dca0f0d3694e9c3df
+++ svr-tcpfwd.c aa3d9bd98b61f4a84f5b28b1debc66a2b398045b
@@ -80,7 +80,7 @@ void recv_msg_global_request_remotetcp()
reqname = buf_getstring(ses.payload, &namelen);
wantreply = buf_getbool(ses.payload);
- if (namelen > MAXNAMLEN) {
+ if (namelen > MAX_NAME_LEN) {
TRACE(("name len is wrong: %d", namelen))
goto out;
}