summaryrefslogtreecommitdiffhomepage
path: root/common-session.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2013-05-21 12:09:35 +0800
committerMatt Johnston <matt@ucc.asn.au>2013-05-21 12:09:35 +0800
commit04518e9e801ee57bd6d4caab470da8dc0ec98fd7 (patch)
tree5e46adedc7cd70e6f7b0547a200544cbcf80b96b /common-session.c
parent41f531ceafc86507c82847f44f9c9e126d798c48 (diff)
parenta57947c513a53e77de0b2eaa67ca6404f444a29f (diff)
merge in HEAD
--HG-- branch : ecc
Diffstat (limited to 'common-session.c')
-rw-r--r--common-session.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/common-session.c b/common-session.c
index ef8e6fa..470d1f6 100644
--- a/common-session.c
+++ b/common-session.c
@@ -33,12 +33,12 @@
#include "random.h"
#include "kex.h"
#include "channel.h"
-#include "atomicio.h"
#include "runopts.h"
static void checktimeouts();
static long select_timeout();
static int ident_readln(int fd, char* buf, int count);
+static void read_session_identification();
struct sshsession ses; /* GLOBAL */
@@ -49,8 +49,6 @@ int sessinitdone = 0; /* GLOBAL */
/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
int exitflag = 0; /* GLOBAL */
-
-
/* called only at the start of a session, set up initial state */
void common_session_init(int sock_in, int sock_out) {
@@ -84,7 +82,7 @@ void common_session_init(int sock_in, int sock_out) {
initqueue(&ses.writequeue);
- ses.requirenext = SSH_MSG_KEXINIT;
+ ses.requirenext[0] = SSH_MSG_KEXINIT;
ses.dataallowed = 1; /* we can send data until we actually
send the SSH_MSG_KEXINIT */
ses.ignorenext = 0;
@@ -141,7 +139,10 @@ void session_loop(void(*loophandler)()) {
FD_ZERO(&writefd);
FD_ZERO(&readfd);
dropbear_assert(ses.payload == NULL);
- if (ses.sock_in != -1) {
+
+ /* during initial setup we flush out the KEXINIT packet before
+ * attempting to read the remote version string, which might block */
+ if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) {
FD_SET(ses.sock_in, &readfd);
}
if (ses.sock_out != -1 && !isempty(&ses.writequeue)) {
@@ -195,7 +196,12 @@ void session_loop(void(*loophandler)()) {
if (ses.sock_in != -1) {
if (FD_ISSET(ses.sock_in, &readfd)) {
- read_packet();
+ if (!ses.remoteident) {
+ /* blocking read of the version string */
+ read_session_identification();
+ } else {
+ read_packet();
+ }
}
/* Process the decrypted packet. After this, the read buffer
@@ -225,7 +231,7 @@ void session_loop(void(*loophandler)()) {
}
/* clean up a session on exit */
-void common_session_cleanup() {
+void session_cleanup() {
TRACE(("enter session_cleanup"))
@@ -234,6 +240,10 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup: !sessinitdone"))
return;
}
+
+ if (ses.extra_session_cleanup) {
+ ses.extra_session_cleanup();
+ }
if (ses.session_id) {
buf_burn(ses.session_id);
@@ -253,21 +263,20 @@ void common_session_cleanup() {
TRACE(("leave session_cleanup"))
}
+void send_session_identification() {
+ buffer *writebuf = buf_new(strlen(LOCAL_IDENT "\r\n") + 1);
+ buf_putbytes(writebuf, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n"));
+ buf_putbyte(writebuf, 0x0); // packet type
+ buf_setpos(writebuf, 0);
+ enqueue(&ses.writequeue, writebuf);
+}
-void session_identification() {
-
+static void read_session_identification() {
/* max length of 255 chars */
char linebuf[256];
int len = 0;
char done = 0;
int i;
-
- /* write our version string, this blocks */
- if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n",
- strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
- ses.remoteclosed();
- }
-
/* If they send more than 50 lines, something is wrong */
for (i = 0; i < 50; i++) {
len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf));