merge of 4cbdd6e0a0d8c061075b9ed7609a06c4547f67d3

and 5d396842815593611f0d61762440145d1fc74d5a

--HG--
extra : convert_revision : 4c883eb469d2d251ee8abddbc11ae4005db6da17
This commit is contained in:
Matt Johnston 2006-03-08 12:53:09 +00:00
commit e4697de175
15 changed files with 118 additions and 26 deletions

1
auth.h
View File

@ -52,6 +52,7 @@ void cli_pubkeyfail();
void cli_auth_password(); void cli_auth_password();
int cli_auth_pubkey(); int cli_auth_pubkey();
void cli_auth_interactive(); void cli_auth_interactive();
char* getpass_or_cancel();
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */ #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */

View File

@ -278,3 +278,18 @@ void cli_auth_try() {
TRACE(("leave 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;
}

View File

@ -115,7 +115,7 @@ void recv_msg_userauth_info_request() {
echo = buf_getbool(ses.payload); echo = buf_getbool(ses.payload);
if (!echo) { if (!echo) {
unsigned char* p = getpass(prompt); unsigned char* p = getpass_or_cancel(prompt);
response = m_strdup(p); response = m_strdup(p);
m_burn(p, strlen(p)); m_burn(p, strlen(p));
} else { } else {

View File

@ -125,10 +125,7 @@ void cli_auth_password() {
password = gui_getpass("Password: "); password = gui_getpass("Password: ");
else else
#endif #endif
password = getpass("Password: "); password = getpass_or_cancel("Password: ");
if (password == NULL)
return 0;
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);

View File

@ -76,12 +76,14 @@ static const struct ChanType *cli_chantypes[] = {
void cli_session(int sock, char* remotehost) { void cli_session(int sock, char* remotehost) {
seedrandom();
crypto_init(); crypto_init();
common_session_init(sock, remotehost); common_session_init(sock, remotehost);
chaninitialise(cli_chantypes); chaninitialise(cli_chantypes);
/* Set up cli_ses vars */ /* Set up cli_ses vars */
cli_session_init(); cli_session_init();
@ -91,12 +93,8 @@ void cli_session(int sock, char* remotehost) {
/* Exchange identification */ /* Exchange identification */
session_identification(); session_identification();
seedrandom();
send_msg_kexinit(); send_msg_kexinit();
/* XXX here we do stuff differently */
session_loop(cli_sessionloop); session_loop(cli_sessionloop);
/* Not reached */ /* Not reached */

View File

@ -376,7 +376,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
cbuf_incrread(cbuf, len); cbuf_incrread(cbuf, len);
channel->recvdonelen += 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 */ /* Check if we're closing up */
closewritefd(channel); closewritefd(channel);
TRACE(("leave writechannel: recveof set")) TRACE(("leave writechannel: recveof set"))

View File

@ -232,10 +232,8 @@ void session_identification() {
dropbear_exit("Error writing ident string"); dropbear_exit("Error writing ident string");
} }
/* We allow up to 9 lines before the actual version string, to /* If they send more than 50 lines, something is wrong */
* account for wrappers/cruft etc. According to the spec only the client for (i = 0; i < 50; i++) {
* needs to handle this, but no harm in letting the server handle it too */
for (i = 0; i < 10; i++) {
len = ident_readln(ses.sock, linebuf, sizeof(linebuf)); len = ident_readln(ses.sock, linebuf, sizeof(linebuf));
if (len < 0 && errno != EINTR) { if (len < 0 && errno != EINTR) {
@ -259,6 +257,12 @@ void session_identification() {
memcpy(ses.remoteident, linebuf, len); 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)) TRACE(("remoteident: %s", ses.remoteident))
} }

View File

@ -30,8 +30,8 @@
static int donerandinit = 0; static int donerandinit = 0;
/* this is used to generate unique output from the same hashpool */ /* this is used to generate unique output from the same hashpool */
static unsigned int counter = 0; static uint32_t counter = 0;
#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */ #define MAX_COUNTER 1<<31 /* the max value for the counter, so it won't loop */
static unsigned char hashpool[SHA1_HASH_SIZE]; static unsigned char hashpool[SHA1_HASH_SIZE];
@ -132,7 +132,8 @@ void seedrandom() {
hash_state hs; 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) { if (!donerandinit) {
m_burn(hashpool, sizeof(hashpool)); m_burn(hashpool, sizeof(hashpool));
} }
@ -150,6 +151,30 @@ void seedrandom() {
donerandinit = 1; 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 */ /* return len bytes of pseudo-random data */
void genrandom(unsigned char* buf, unsigned int len) { void genrandom(unsigned char* buf, unsigned int len) {

View File

@ -28,6 +28,7 @@
struct mp_int; struct mp_int;
void seedrandom(); void seedrandom();
void reseedrandom();
void genrandom(unsigned char* buf, int len); void genrandom(unsigned char* buf, int len);
void addrandom(unsigned char* buf, int len); void addrandom(unsigned char* buf, int len);
void gen_random_mpint(mp_int *max, mp_int *rand); void gen_random_mpint(mp_int *max, mp_int *rand);

32
scp.c
View File

@ -166,8 +166,22 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
close(reserved[0]); close(reserved[0]);
close(reserved[1]); 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. */ /* Fork a child to execute the command on the remote host using ssh. */
#ifdef __uClinux__
do_cmd_pid = vfork();
#else
do_cmd_pid = fork(); do_cmd_pid = fork();
#endif /* __uClinux__ */
if (do_cmd_pid == 0) { if (do_cmd_pid == 0) {
/* Child. */ /* Child. */
close(pin[1]); close(pin[1]);
@ -177,6 +191,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
close(pin[0]); close(pin[0]);
close(pout[1]); close(pout[1]);
#ifndef __uClinux__
args.list[0] = ssh_program; args.list[0] = ssh_program;
if (remuser != NULL) { if (remuser != NULL) {
addargs(&args, "-l"); addargs(&args, "-l");
@ -184,6 +199,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
} }
addargs(&args, "%s", host); addargs(&args, "%s", host);
addargs(&args, "%s", cmd); addargs(&args, "%s", cmd);
#endif
execvp(ssh_program, args.list); execvp(ssh_program, args.list);
perror(ssh_program); perror(ssh_program);
@ -192,6 +208,22 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno)); fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno));
exit(1); 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. */ /* Parent. Close the other side, and return the local side. */
close(pin[0]); close(pin[0]);
*fdout = pin[1]; *fdout = pin[1];

View File

@ -623,7 +623,12 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
if (pipe(errfds) != 0) if (pipe(errfds) != 0)
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
#ifdef __uClinux__
pid = vfork();
#else
pid = fork(); pid = fork();
#endif
if (pid < 0) if (pid < 0)
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
@ -714,7 +719,11 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
} }
#ifdef __uClinux__
pid = vfork();
#else
pid = fork(); pid = fork();
#endif
if (pid < 0) if (pid < 0)
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
@ -828,12 +837,16 @@ static void execchild(struct ChanSess *chansess) {
char * baseshell = NULL; char * baseshell = NULL;
unsigned int i; 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 */ /* wipe the hostkey */
sign_key_free(svr_opts.hostkey); sign_key_free(svr_opts.hostkey);
svr_opts.hostkey = NULL; svr_opts.hostkey = NULL;
/* overwrite the prng state */ /* overwrite the prng state */
seedrandom(); reseedrandom();
#endif
/* close file descriptors except stdin/stdout/stderr /* close file descriptors except stdin/stdout/stderr
* Need to be sure FDs are closed here to avoid reading files as root */ * Need to be sure FDs are closed here to avoid reading files as root */

View File

@ -83,7 +83,7 @@ static void main_inetd() {
int remoteaddrlen; int remoteaddrlen;
char * addrstring = NULL; char * addrstring = NULL;
/* Set up handlers, syslog */ /* Set up handlers, syslog, seed random */
commonsetup(); commonsetup();
remoteaddrlen = sizeof(remoteaddr); remoteaddrlen = sizeof(remoteaddr);
@ -359,6 +359,8 @@ static void commonsetup() {
/* Now we can setup the hostkeys - needs to be after logging is on, /* Now we can setup the hostkeys - needs to be after logging is on,
* otherwise we might end up blatting error messages to the socket */ * otherwise we might end up blatting error messages to the socket */
loadhostkeys(); loadhostkeys();
seedrandom();
} }
/* Set up listening sockets for all the requested ports */ /* Set up listening sockets for all the requested ports */

View File

@ -105,8 +105,12 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.inetdmode = 0; svr_opts.inetdmode = 0;
svr_opts.portcount = 0; svr_opts.portcount = 0;
svr_opts.hostkey = NULL; svr_opts.hostkey = NULL;
#ifdef ENABLE_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0; svr_opts.nolocaltcp = 0;
#endif
#ifdef ENABLE_SVR_REMOTETCPFWD
svr_opts.noremotetcp = 0; svr_opts.noremotetcp = 0;
#endif
/* not yet /* not yet
opts.ipv4 = 1; opts.ipv4 = 1;
opts.ipv6 = 1; opts.ipv6 = 1;
@ -154,12 +158,12 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.usingsyslog = 0; svr_opts.usingsyslog = 0;
break; break;
#endif #endif
#ifndef DISABLE_LOCALTCPFWD #ifdef ENABLE_SVR_LOCALTCPFWD
case 'j': case 'j':
svr_opts.nolocaltcp = 1; svr_opts.nolocaltcp = 1;
break; break;
#endif #endif
#ifndef DISABLE_REMOTETCPFWD #ifdef ENABLE_SVR_REMOTETCPFWD
case 'k': case 'k':
svr_opts.noremotetcp = 1; svr_opts.noremotetcp = 1;
break; break;

View File

@ -79,6 +79,8 @@ void svr_session(int sock, int childpipe,
struct timeval timeout; struct timeval timeout;
reseedrandom();
crypto_init(); crypto_init();
common_session_init(sock, remotehost); common_session_init(sock, remotehost);
@ -110,8 +112,6 @@ void svr_session(int sock, int childpipe,
/* exchange identification, version etc */ /* exchange identification, version etc */
session_identification(); session_identification();
seedrandom();
/* start off with key exchange */ /* start off with key exchange */
send_msg_kexinit(); send_msg_kexinit();

View File

@ -80,7 +80,7 @@ void recv_msg_global_request_remotetcp() {
reqname = buf_getstring(ses.payload, &namelen); reqname = buf_getstring(ses.payload, &namelen);
wantreply = buf_getbool(ses.payload); wantreply = buf_getbool(ses.payload);
if (namelen > MAXNAMLEN) { if (namelen > MAX_NAME_LEN) {
TRACE(("name len is wrong: %d", namelen)) TRACE(("name len is wrong: %d", namelen))
goto out; goto out;
} }