summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--chansession.h4
-rw-r--r--cli-auth.c2
-rw-r--r--cli-chansession.c125
-rw-r--r--cli-main.c7
-rw-r--r--cli-runopts.c3
-rw-r--r--cli-session.c29
-rw-r--r--dbutil.c2
-rw-r--r--options.h2
-rw-r--r--runopts.h1
-rw-r--r--session.h1
-rw-r--r--signkey.c1
-rw-r--r--svr-chansession.c196
12 files changed, 255 insertions, 118 deletions
diff --git a/chansession.h b/chansession.h
index 7879791..0930d9d 100644
--- a/chansession.h
+++ b/chansession.h
@@ -39,7 +39,6 @@ struct ChanSess {
int slave;
unsigned char * tty;
unsigned char * term;
- unsigned int termw, termh, termc, termr; /* width, height, col, rows */
/* exit details */
int exited;
@@ -76,6 +75,9 @@ void send_msg_chansess_exitsignal(struct Channel * channel,
struct ChanSess * chansess);
void addnewvar(const char* param, const char* var);
+void cli_send_chansess_request();
+void cli_tty_cleanup();
+
void svr_chansessinitialise();
extern const struct ChanType svrchansess;
diff --git a/cli-auth.c b/cli-auth.c
index 37e7814..e081587 100644
--- a/cli-auth.c
+++ b/cli-auth.c
@@ -7,6 +7,8 @@
#include "packet.h"
#include "runopts.h"
+#undef DROPBEAR_PUBKEY_AUTH
+
void cli_authinitialise() {
memset(&ses.authstate, 0, sizeof(ses.authstate));
diff --git a/cli-chansession.c b/cli-chansession.c
index 852bffa..be6fc14 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -6,6 +6,7 @@
#include "channel.h"
#include "ssh.h"
#include "runopts.h"
+#include "termcodes.h"
static void cli_closechansess(struct Channel *channel);
static int cli_initchansess(struct Channel *channel);
@@ -16,7 +17,7 @@ static void send_chansess_pty_req(struct Channel *channel);
static void send_chansess_shell_req(struct Channel *channel);
static void cli_tty_setup();
-static void cli_tty_cleanup();
+void cli_tty_cleanup();
static const struct ChanType clichansess = {
0, /* sepfds */
@@ -50,7 +51,6 @@ static void start_channel_request(struct Channel *channel,
}
-
/* Taken from OpenSSH's sshtty.c:
* RCSID("OpenBSD: sshtty.c,v 1.5 2003/09/19 17:43:35 markus Exp "); */
static void cli_tty_setup() {
@@ -91,12 +91,13 @@ static void cli_tty_setup() {
TRACE(("leave cli_tty_setup"));
}
-static void cli_tty_cleanup() {
+void cli_tty_cleanup() {
TRACE(("enter cli_tty_cleanup"));
if (cli_ses.tty_raw_mode == 0) {
TRACE(("leave cli_tty_cleanup: not in raw mode"));
+ return;
}
if (tcsetattr(STDIN_FILENO, TCSADRAIN, &cli_ses.saved_tio) == -1) {
@@ -108,30 +109,123 @@ static void cli_tty_cleanup() {
TRACE(("leave cli_tty_cleanup"));
}
+static void put_termcodes() {
+
+ TRACE(("enter put_termcodes"));
+
+ struct termios tio;
+ unsigned int sshcode;
+ const struct TermCode *termcode;
+ unsigned int value;
+ unsigned int mapcode;
+
+ unsigned int bufpos1, bufpos2;
+
+ if (tcgetattr(STDIN_FILENO, &tio) == -1) {
+ dropbear_log(LOG_WARNING, "Failed reading termmodes");
+ buf_putint(ses.writepayload, 1); /* Just the terminator */
+ buf_putbyte(ses.writepayload, 0); /* TTY_OP_END */
+ return;
+ }
+
+ bufpos1 = ses.writepayload->pos;
+ buf_putint(ses.writepayload, 0); /* A placeholder for the final length */
+
+ /* As with Dropbear server, we ignore baud rates for now */
+ for (sshcode = 1; sshcode < MAX_TERMCODE; sshcode++) {
+
+ termcode = &termcodes[sshcode];
+ mapcode = termcode->mapcode;
+
+ switch (termcode->type) {
+
+ case TERMCODE_NONE:
+ continue;
+
+ case TERMCODE_CONTROLCHAR:
+ value = tio.c_cc[mapcode];
+ break;
+
+ case TERMCODE_INPUT:
+ value = tio.c_iflag & mapcode;
+ break;
+
+ case TERMCODE_OUTPUT:
+ value = tio.c_oflag & mapcode;
+ break;
+
+ case TERMCODE_LOCAL:
+ value = tio.c_lflag & mapcode;
+ break;
+
+ case TERMCODE_CONTROL:
+ value = tio.c_cflag & mapcode;
+ break;
+
+ default:
+ continue;
+
+ }
+
+ /* If we reach here, we have something to say */
+ buf_putbyte(ses.writepayload, sshcode);
+ buf_putint(ses.writepayload, value);
+ }
+
+ buf_putbyte(ses.writepayload, 0); /* THE END, aka TTY_OP_END */
+
+ /* Put the string length at the start of the buffer */
+ bufpos2 = ses.writepayload->pos;
+
+ buf_setpos(ses.writepayload, bufpos1); /* Jump back */
+ buf_putint(ses.writepayload, bufpos2 - bufpos1); /* len(termcodes) */
+ buf_setpos(ses.writepayload, bufpos2); /* Back where we were */
+
+ TRACE(("leave put_termcodes"));
+}
+
+static void put_winsize() {
+
+ struct winsize ws;
+
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
+ /* Some sane defaults */
+ ws.ws_row = 25;
+ ws.ws_col = 80;
+ ws.ws_xpixel = 0;
+ ws.ws_ypixel = 0;
+ }
+
+ buf_putint(ses.writepayload, ws.ws_col); /* Cols */
+ buf_putint(ses.writepayload, ws.ws_row); /* Rows */
+ buf_putint(ses.writepayload, ws.ws_xpixel); /* Width */
+ buf_putint(ses.writepayload, ws.ws_ypixel); /* Height */
+
+}
+
static void send_chansess_pty_req(struct Channel *channel) {
- unsigned char* termmodes = "\0";
unsigned char* term = NULL;
- int termc = 80, termr = 25, termw = 0, termh = 0; /* XXX TODO matt */
TRACE(("enter send_chansess_pty_req"));
+
start_channel_request(channel, "pty-req");
+ /* Don't want replies */
+ buf_putbyte(ses.writepayload, 0);
+
+ /* Get the terminal */
term = getenv("TERM");
if (term == NULL) {
- term = "vt100";
+ term = "vt100"; /* Seems a safe default */
}
-
- /* XXX TODO */
- buf_putbyte(ses.writepayload, 0); /* Don't want replies */
buf_putstring(ses.writepayload, term, strlen(term));
- buf_putint(ses.writepayload, termc); /* Cols */
- buf_putint(ses.writepayload, termr); /* Rows */
- buf_putint(ses.writepayload, termw); /* Width */
- buf_putint(ses.writepayload, termh); /* Height */
- buf_putstring(ses.writepayload, termmodes, 1); /* XXX TODO */
- //m_free(termmodes);
+ /* Window size */
+ put_winsize();
+
+ /* Terminal mode encoding */
+ put_termcodes();
encrypt_packet();
TRACE(("leave send_chansess_pty_req"));
@@ -171,7 +265,6 @@ static int cli_initchansess(struct Channel *channel) {
send_chansess_pty_req(channel);
}
- cli_opts.cmd = "df";
send_chansess_shell_req(channel);
if (cli_opts.wantpty) {
diff --git a/cli-main.c b/cli-main.c
index c5d5b3e..106cc64 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -61,9 +61,12 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
cli_opts.remoteport, format);
}
+ /* Do the cleanup first, since then the terminal will be reset */
+ cli_session_cleanup();
+ common_session_cleanup();
+
_dropbear_log(LOG_INFO, fmtbuf, param);
- common_session_cleanup();
exit(exitcode);
}
@@ -73,6 +76,6 @@ static void cli_dropbear_log(int priority, const char* format, va_list param) {
vsnprintf(printbuf, sizeof(printbuf), format, param);
- fprintf(stderr, "Dropbear: %s\n", printbuf);
+ fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
}
diff --git a/cli-runopts.c b/cli-runopts.c
index 137e0da..2811ef3 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -55,11 +55,12 @@ void cli_getopts(int argc, char ** argv) {
char* userhostarg = NULL;
/* see printhelp() for options */
+ cli_opts.progname = argv[0];
cli_opts.remotehost = NULL;
cli_opts.remoteport = NULL;
cli_opts.username = NULL;
cli_opts.cmd = NULL;
- cli_opts.wantpty = 0;
+ cli_opts.wantpty = 1;
opts.nolocaltcp = 0;
opts.noremotetcp = 0;
/* not yet
diff --git a/cli-session.c b/cli-session.c
index 258d5c4..42770f5 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -9,10 +9,13 @@
#include "channel.h"
#include "random.h"
#include "service.h"
+#include "runopts.h"
+#include "chansession.h"
static void cli_remoteclosed();
static void cli_sessionloop();
static void cli_session_init();
+static void cli_finished();
struct clientsession cli_ses; /* GLOBAL */
@@ -163,6 +166,12 @@ static void cli_sessionloop() {
cli_ses.state = SESSION_RUNNING;
return;
+ case SESSION_RUNNING:
+ if (ses.chancount < 1) {
+ cli_finished();
+ }
+ return;
+
/* XXX more here needed */
@@ -174,6 +183,26 @@ static void cli_sessionloop() {
}
+void cli_session_cleanup() {
+
+ if (!sessinitdone) {
+ return;
+ }
+ cli_tty_cleanup();
+
+}
+
+static void cli_finished() {
+
+ cli_session_cleanup();
+ common_session_cleanup();
+ fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
+ cli_opts.remotehost, cli_opts.remoteport);
+ exit(EXIT_SUCCESS);
+}
+
+
+
/* called when the remote side closes the connection */
static void cli_remoteclosed() {
diff --git a/dbutil.c b/dbutil.c
index 1c0648c..a89c3c8 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -103,6 +103,7 @@ void dropbear_log(int priority, const char* format, ...) {
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) {
+#if 0
va_list param;
va_start(param, format);
@@ -110,6 +111,7 @@ void dropbear_trace(const char* format, ...) {
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
+#endif
}
#endif /* DEBUG_TRACE */
diff --git a/options.h b/options.h
index ee0ee60..1ab16c7 100644
--- a/options.h
+++ b/options.h
@@ -111,7 +111,7 @@
/* Authentication types to enable, at least one required.
RFC Draft requires pubkey auth, and recommends password */
#define DROPBEAR_PASSWORD_AUTH
-//#define DROPBEAR_PUBKEY_AUTH
+#define DROPBEAR_PUBKEY_AUTH
/* Random device to use - you must specify _one only_.
* DEV_RANDOM is recommended on hosts with a good /dev/urandom, otherwise use
diff --git a/runopts.h b/runopts.h
index b2fc149..26d15ef 100644
--- a/runopts.h
+++ b/runopts.h
@@ -79,6 +79,7 @@ void svr_getopts(int argc, char ** argv);
/* Uncompleted XXX matt */
typedef struct cli_runopts {
+ char *progname;
char *remotehost;
char *remoteport;
diff --git a/session.h b/session.h
index 1000c5e..1ce944a 100644
--- a/session.h
+++ b/session.h
@@ -55,6 +55,7 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
void cli_session(int sock, char *remotehost);
void cli_dropbear_exit(int exitcode, const char* format, va_list param);
void cli_dropbear_log(int priority, const char* format, va_list param);
+void cli_session_cleanup();
struct key_context {
diff --git a/signkey.c b/signkey.c
index faf3739..2fd301f 100644
--- a/signkey.c
+++ b/signkey.c
@@ -53,7 +53,6 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
unsigned int len;
TRACE(("enter buf_get_pub_key"));
- printhex(buf_getptr(buf, 0x99), 0x99);
ident = buf_getstring(buf, &len);
diff --git a/svr-chansession.c b/svr-chansession.c
index 50e0a5e..9639961 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -56,6 +56,7 @@ static void chansessionrequest(struct Channel *channel);
static void send_exitsignalstatus(struct Channel *channel);
static int sesscheckclose(struct Channel *channel);
+static void get_termmodes(struct ChanSess *chansess);
/* required to clear environment */
@@ -192,10 +193,6 @@ static int newchansess(struct Channel *channel) {
chansess->slave = -1;
chansess->tty = NULL;
chansess->term = NULL;
- chansess->termw = 0;
- chansess->termh = 0;
- chansess->termc = 0;
- chansess->termr = 0;
chansess->exited = 0;
@@ -376,22 +373,111 @@ static int sessionsignal(struct ChanSess *chansess) {
* client. Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int sessionwinchange(struct ChanSess *chansess) {
+ int termc, termr, termw, termh;
+
if (chansess->master < 0) {
/* haven't got a pty yet */
return DROPBEAR_FAILURE;
}
- chansess->termc = buf_getint(ses.payload);
- chansess->termr = buf_getint(ses.payload);
- chansess->termw = buf_getint(ses.payload);
- chansess->termh = buf_getint(ses.payload);
+ termc = buf_getint(ses.payload);
+ termr = buf_getint(ses.payload);
+ termw = buf_getint(ses.payload);
+ termh = buf_getint(ses.payload);
- pty_change_window_size(chansess->master, chansess->termr, chansess->termc,
- chansess->termw, chansess->termh);
+ pty_change_window_size(chansess->master, termr, termc, termw, termh);
return DROPBEAR_FAILURE;
}
+static void get_termmodes(struct ChanSess *chansess) {
+
+ struct termios termio;
+ unsigned char opcode;
+ unsigned int value;
+ const struct TermCode * termcode;
+ unsigned int len;
+
+ TRACE(("enter get_termmodes"));
+
+ /* Term modes */
+ /* We'll ignore errors and continue if we can't set modes.
+ * We're ignoring baud rates since they seem evil */
+ if (tcgetattr(chansess->master, &termio) == -1) {
+ return;
+ }
+
+ len = buf_getint(ses.payload);
+ if (len != ses.payload->len - ses.payload->pos) {
+ dropbear_exit("bad term mode string");
+ }
+
+ if (len == 0) {
+ TRACE(("leave get_termmodes: empty terminal modes string"));
+ }
+
+ while (((opcode = buf_getbyte(ses.payload)) != 0x00) && opcode <= 159) {
+
+ /* must be before checking type, so that value is consumed even if
+ * we don't use it */
+ value = buf_getint(ses.payload);
+
+ /* handle types of code */
+ if (opcode > MAX_TERMCODE) {
+ continue;
+ }
+ termcode = &termcodes[(unsigned int)opcode];
+
+
+ switch (termcode->type) {
+
+ case TERMCODE_NONE:
+ break;
+
+ case TERMCODE_CONTROLCHAR:
+ termio.c_cc[termcode->mapcode] = value;
+ break;
+
+ case TERMCODE_INPUT:
+ if (value) {
+ termio.c_iflag |= termcode->mapcode;
+ } else {
+ termio.c_iflag &= ~(termcode->mapcode);
+ }
+ break;
+
+ case TERMCODE_OUTPUT:
+ if (value) {
+ termio.c_oflag |= termcode->mapcode;
+ } else {
+ termio.c_oflag &= ~(termcode->mapcode);
+ }
+ break;
+
+ case TERMCODE_LOCAL:
+ if (value) {
+ termio.c_lflag |= termcode->mapcode;
+ } else {
+ termio.c_lflag &= ~(termcode->mapcode);
+ }
+ break;
+
+ case TERMCODE_CONTROL:
+ if (value) {
+ termio.c_cflag |= termcode->mapcode;
+ } else {
+ termio.c_cflag &= ~(termcode->mapcode);
+ }
+ break;
+
+ }
+ }
+ if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) {
+ dropbear_log(LOG_INFO, "error setting terminal attributes");
+ }
+ TRACE(("leave get_termmodes"));
+}
+
/* Set up a session pty which will be used to execute the shell or program.
* The pty is allocated now, and kept for when the shell/program executes.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
@@ -399,7 +485,6 @@ static int sessionpty(struct ChanSess * chansess) {
unsigned int termlen;
unsigned char namebuf[65];
- struct termios termio;
TRACE(("enter sessionpty"));
chansess->term = buf_getstring(ses.payload, &termlen);
@@ -408,10 +493,6 @@ static int sessionpty(struct ChanSess * chansess) {
TRACE(("leave sessionpty: term len too long"));
return DROPBEAR_FAILURE;
}
- chansess->termc = buf_getint(ses.payload);
- chansess->termr = buf_getint(ses.payload);
- chansess->termw = buf_getint(ses.payload);
- chansess->termh = buf_getint(ses.payload);
/* allocate the pty */
assert(chansess->master == -1); /* haven't already got one */
@@ -426,89 +507,12 @@ static int sessionpty(struct ChanSess * chansess) {
}
pty_setowner(ses.authstate.pw, chansess->tty);
- pty_change_window_size(chansess->master, chansess->termr, chansess->termc,
- chansess->termw, chansess->termh);
- /* Term modes */
- /* We'll ignore errors and continue if we can't set modes.
- * We're ignoring baud rates since they seem evil */
- if (tcgetattr(chansess->master, &termio) == 0) {
- unsigned char opcode;
- unsigned int value;
- const struct TermCode * termcode;
- unsigned int len;
-
- len = buf_getint(ses.payload);
- if (len != ses.payload->len - ses.payload->pos) {
- dropbear_exit("bad term mode string");
- }
-
- if (len == 0) {
- TRACE(("empty terminal modes string"));
- return DROPBEAR_SUCCESS;
- }
-
- while (((opcode = buf_getbyte(ses.payload)) != 0x00) &&
- opcode <= 159) {
+ /* Set up the rows/col counts */
+ sessionwinchange(chansess);
- /* must be before checking type, so that value is consumed even if
- * we don't use it */
- value = buf_getint(ses.payload);
-
- /* handle types of code */
- if (opcode > MAX_TERMCODE) {
- continue;
- }
- termcode = &termcodes[(unsigned int)opcode];
-
-
- switch (termcode->type) {
-
- case TERMCODE_NONE:
- break;
-
- case TERMCODE_CONTROLCHAR:
- termio.c_cc[termcode->mapcode] = value;
- break;
-
- case TERMCODE_INPUT:
- if (value) {
- termio.c_iflag |= termcode->mapcode;
- } else {
- termio.c_iflag &= ~(termcode->mapcode);
- }
- break;
-
- case TERMCODE_OUTPUT:
- if (value) {
- termio.c_oflag |= termcode->mapcode;
- } else {
- termio.c_oflag &= ~(termcode->mapcode);
- }
- break;
-
- case TERMCODE_LOCAL:
- if (value) {
- termio.c_lflag |= termcode->mapcode;
- } else {
- termio.c_lflag &= ~(termcode->mapcode);
- }
- break;
-
- case TERMCODE_CONTROL:
- if (value) {
- termio.c_cflag |= termcode->mapcode;
- } else {
- termio.c_cflag &= ~(termcode->mapcode);
- }
- break;
-
- }
- }
- if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) {
- dropbear_log(LOG_INFO, "error setting terminal attributes");
- }
- }
+ /* Read the terminal modes */
+ get_termmodes(chansess);
TRACE(("leave sessionpty"));
return DROPBEAR_SUCCESS;