Commit dd09194e authored by Niels Möller's avatar Niels Möller
Browse files

New file

Rev: doc/TODO:1.1
Rev: src/abstract_io.h:1.13
Rev: src/client.c:1.20
Rev: src/client_keyexchange.c:1.11
Rev: src/connection.c:1.12
Rev: src/debug.c:1.12
Rev: src/disconnect.c:1.4
Rev: src/keyexchange.c:1.16
Rev: src/packet_ignore.c:1.4
Rev: src/read_data.c:1.7
Rev: src/read_packet.c:1.19
Rev: src/server.c:1.13
Rev: src/server_keyexchange.c:1.9
parent 8c69e475
Consider return values from handlers. A return value has seveal
components:
x Success/failure indication
x Next action (continue, close immediately, flush buffers then close,
exit...)
x Process return value in case the proper action is to exit.
It should be possible to encode all this information into a simple integer.
...@@ -47,6 +47,29 @@ struct abstract_read ...@@ -47,6 +47,29 @@ struct abstract_read
#define A_READ(f, length, buffer) (f)->read(&(f), (length), (buffer)) #define A_READ(f, length, buffer) (f)->read(&(f), (length), (buffer))
/* Return values for write- and readhandlers.
*
* Several components are OR:ed together */
/* Success/fail indication */
#define LSH_OK 0
#define LSH_FAIL 1
/* Actions */
#define LSH_GOON 0
#define LSH_CLOSE 2
#define LSH_DIE 4
#define LSH_GET_ACTION(x) ((x) & 6)
/* Non-zero if there's any problem */
#define LSH_PROBLEMP(x) (x)
/* Are return codes really needed here? */
#if 0
#define LSH_EXIT(x) ((x) << 3)
#define LSH_GET_EXIT(x) ((x) >> 3)
#endif
/* May store a new handler into *h. */ /* May store a new handler into *h. */
struct read_handler struct read_handler
{ {
...@@ -57,21 +80,9 @@ struct read_handler ...@@ -57,21 +80,9 @@ struct read_handler
#define READ_HANDLER(h, read) ((h)->handler(&(h), (read))) #define READ_HANDLER(h, read) ((h)->handler(&(h), (read)))
/* Return values for write callbacks
*
* FIXME: Perhaps some more values are needed? What if we want to
* close a file, but not until all data has bee flushed? Perhaps it is
* best not to put too much meaning into the return value, and use it
* as a succes/fail indication only. */
/* Everything is ok */
#define WRITE_OK 1
/* Write failed, and the packet could not be processed or delivered.
* Most likely because of a protocol error */
#define WRITE_CLOSED 0
/* May store a new handler into *w. */ /* May store a new handler into *w. FIXME: Is this indirection ever
* used? */
struct abstract_write struct abstract_write
{ {
struct lsh_object header; struct lsh_object header;
...@@ -81,7 +92,7 @@ struct abstract_write ...@@ -81,7 +92,7 @@ struct abstract_write
#define A_WRITE(f, packet) ((f)->write(&(f), (packet))) #define A_WRITE(f, packet) ((f)->write(&(f), (packet)))
/* A processor that passes its result on to another processor */ /* A handler that passes packets on to another processor */
struct abstract_write_pipe struct abstract_write_pipe
{ {
struct abstract_write super; struct abstract_write super;
......
...@@ -80,7 +80,7 @@ static int client_initiate(struct fd_callback **c, ...@@ -80,7 +80,7 @@ static int client_initiate(struct fd_callback **c,
res = A_WRITE(connection->raw, res = A_WRITE(connection->raw,
ssh_format("%lS\r\n", connection->client_version)); ssh_format("%lS\r\n", connection->client_version));
if (res != WRITE_OK) if (LSH_PROBLEMP(res))
return res; return res;
return initiate_keyexchange(connection, CONNECTION_CLIENT, return initiate_keyexchange(connection, CONNECTION_CLIENT,
......
...@@ -63,7 +63,7 @@ static int do_handle_dh_reply(struct packet_handler *c, ...@@ -63,7 +63,7 @@ static int do_handle_dh_reply(struct packet_handler *c,
if (!dh_process_server_msg(&closure->dh, packet)) if (!dh_process_server_msg(&closure->dh, packet))
{ {
disconnect_kex_failed(connection, "Bad dh-reply\r\n"); disconnect_kex_failed(connection, "Bad dh-reply\r\n");
return WRITE_CLOSED; return LSH_FAILURE | LSH_CLOSE;
} }
v = LOOKUP_VERIFIER(closure->verifier, closure->dh.server_key); v = LOOKUP_VERIFIER(closure->verifier, closure->dh.server_key);
...@@ -72,7 +72,7 @@ static int do_handle_dh_reply(struct packet_handler *c, ...@@ -72,7 +72,7 @@ static int do_handle_dh_reply(struct packet_handler *c,
/* FIXME: Use a more appropriate error code? */ /* FIXME: Use a more appropriate error code? */
{ {
disconnect_kex_failed(connection, "Bad server host key\r\n"); disconnect_kex_failed(connection, "Bad server host key\r\n");
return WRITE_CLOSED; return LSH_FAILURE | LSH_CLOSE;
} }
if (!dh_verify_server_msg(&closure->dh, v)) if (!dh_verify_server_msg(&closure->dh, v))
...@@ -83,7 +83,7 @@ static int do_handle_dh_reply(struct packet_handler *c, ...@@ -83,7 +83,7 @@ static int do_handle_dh_reply(struct packet_handler *c,
* handler for recieving the newkeys message. */ * handler for recieving the newkeys message. */
res = A_WRITE(connection->write, ssh_format("%c", SSH_MSG_NEWKEYS)); res = A_WRITE(connection->write, ssh_format("%c", SSH_MSG_NEWKEYS));
if (res != WRITE_OK) if (LSH_PROBLEMP(res))
return res; return res;
/* Record session id */ /* Record session id */
...@@ -140,7 +140,7 @@ static int do_init_dh(struct keyexchange_algorithm *c, ...@@ -140,7 +140,7 @@ static int do_init_dh(struct keyexchange_algorithm *c,
/* Send client's message */ /* Send client's message */
res = A_WRITE(connection->write, dh_make_client_msg(&dh->dh)); res = A_WRITE(connection->write, dh_make_client_msg(&dh->dh));
if (res != WRITE_OK) if (LSH_PROBLEMP(res))
return res; return res;
/* Install handler */ /* Install handler */
...@@ -148,7 +148,7 @@ static int do_init_dh(struct keyexchange_algorithm *c, ...@@ -148,7 +148,7 @@ static int do_init_dh(struct keyexchange_algorithm *c,
connection->kex_state = KEX_STATE_IN_PROGRESS; connection->kex_state = KEX_STATE_IN_PROGRESS;
return WRITE_OK; return LSH_OK | LSH_GOON;
} }
......
...@@ -38,7 +38,7 @@ static int handle_connection(struct abstract_write **w, ...@@ -38,7 +38,7 @@ static int handle_connection(struct abstract_write **w,
{ {
werror("Unexpected NEWKEYS message!\n"); werror("Unexpected NEWKEYS message!\n");
lsh_free(packet); lsh_free(packet);
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
break; break;
case KEX_STATE_IGNORE: case KEX_STATE_IGNORE:
...@@ -50,7 +50,7 @@ static int handle_connection(struct abstract_write **w, ...@@ -50,7 +50,7 @@ static int handle_connection(struct abstract_write **w,
* KEXDH_INIT or KEXDH_REPLY message. */ * KEXDH_INIT or KEXDH_REPLY message. */
closure->kex_state = KEX_STATE_IN_PROGRESS; closure->kex_state = KEX_STATE_IN_PROGRESS;
lsh_free(packet); lsh_free(packet);
return WRITE_OK; return LSH_OK | LSH_GOON;
case KEX_STATE_IN_PROGRESS: case KEX_STATE_IN_PROGRESS:
if ( (msg == SSH_MSG_NEWKEYS) if ( (msg == SSH_MSG_NEWKEYS)
...@@ -58,7 +58,7 @@ static int handle_connection(struct abstract_write **w, ...@@ -58,7 +58,7 @@ static int handle_connection(struct abstract_write **w,
{ {
werror("Unexpected KEXINIT or NEWKEYS message!\n"); werror("Unexpected KEXINIT or NEWKEYS message!\n");
lsh_free(packet); lsh_free(packet);
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
break; break;
case KEX_STATE_NEWKEYS: case KEX_STATE_NEWKEYS:
...@@ -68,7 +68,7 @@ static int handle_connection(struct abstract_write **w, ...@@ -68,7 +68,7 @@ static int handle_connection(struct abstract_write **w,
werror("Expected NEWKEYS message, but recieved message %d!\n", werror("Expected NEWKEYS message, but recieved message %d!\n",
msg); msg);
lsh_free(packet); lsh_free(packet);
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
break; break;
default: default:
...@@ -85,7 +85,7 @@ static int do_fail(struct packet_handler *closure, ...@@ -85,7 +85,7 @@ static int do_fail(struct packet_handler *closure,
MDEBUG(closure); MDEBUG(closure);
lsh_string_free(packet); lsh_string_free(packet);
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
struct packet_handler *make_fail_handler(void) struct packet_handler *make_fail_handler(void)
......
...@@ -80,7 +80,7 @@ int send_debug(struct abstract_write *write, char *msg, int always_display) ...@@ -80,7 +80,7 @@ int send_debug(struct abstract_write *write, char *msg, int always_display)
{ {
return (debug_flag) return (debug_flag)
? A_WRITE(write, make_debug_packet(msg, always_display)) ? A_WRITE(write, make_debug_packet(msg, always_display))
: WRITE_OK; : LSH_OK | LSH_GOON;
} }
...@@ -88,7 +88,7 @@ int send_verbose(struct abstract_write *write, char *msg, int always_display) ...@@ -88,7 +88,7 @@ int send_verbose(struct abstract_write *write, char *msg, int always_display)
{ {
return (verbose_flag) return (verbose_flag)
? A_WRITE(write, make_debug_packet(msg, always_display)) ? A_WRITE(write, make_debug_packet(msg, always_display))
: WRITE_OK; : LSH_OK | LSH_GOON;
} }
static int do_rec_debug(struct packet_handler *self, static int do_rec_debug(struct packet_handler *self,
...@@ -111,7 +111,7 @@ static int do_rec_debug(struct packet_handler *self, ...@@ -111,7 +111,7 @@ static int do_rec_debug(struct packet_handler *self,
&& parse_eod(&buffer))) && parse_eod(&buffer)))
{ {
lsh_string_free(packet); lsh_string_free(packet);
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
if (always_display) if (always_display)
...@@ -128,7 +128,7 @@ static int do_rec_debug(struct packet_handler *self, ...@@ -128,7 +128,7 @@ static int do_rec_debug(struct packet_handler *self,
} }
lsh_string_free(packet); lsh_string_free(packet);
return WRITE_OK; return LSH_OK | LSH_GOON;
} }
struct packet_handler *make_rec_debug_handler(void) struct packet_handler *make_rec_debug_handler(void)
......
...@@ -67,7 +67,7 @@ static int do_disconnect(struct packet_handler *closure, ...@@ -67,7 +67,7 @@ static int do_disconnect(struct packet_handler *closure,
/* FIXME: Mark the file as closed, somehow (probably a variable in /* FIXME: Mark the file as closed, somehow (probably a variable in
* the write buffer) */ * the write buffer) */
return WRITE_CLOSED; return LSH_CLOSE;
} }
struct packet_handler *make_disconnect_handler(void) struct packet_handler *make_disconnect_handler(void)
......
...@@ -148,7 +148,7 @@ int initiate_keyexchange(struct ssh_connection *connection, ...@@ -148,7 +148,7 @@ int initiate_keyexchange(struct ssh_connection *connection,
res = A_WRITE(connection->write, lsh_string_dup(s)); res = A_WRITE(connection->write, lsh_string_dup(s));
if ( (res == WRITE_OK) && first_packet) if (!LSH_PROBLEMP(res) && first_packet)
return A_WRITE(connection->write, first_packet); return A_WRITE(connection->write, first_packet);
else else
return res; return res;
...@@ -217,7 +217,7 @@ static int do_handle_kexinit(struct packet_handler *c, ...@@ -217,7 +217,7 @@ static int do_handle_kexinit(struct packet_handler *c,
connection->literal_kexinits[closure->type] = lsh_string_dup(packet); connection->literal_kexinits[closure->type] = lsh_string_dup(packet);
res = A_WRITE(connection->write, packet); res = A_WRITE(connection->write, packet);
if (res != WRITE_OK) if (LSH_PROBLEMP(res))
return res; return res;
} }
...@@ -248,9 +248,7 @@ static int do_handle_kexinit(struct packet_handler *c, ...@@ -248,9 +248,7 @@ static int do_handle_kexinit(struct packet_handler *c,
disconnect_kex_failed(connection, disconnect_kex_failed(connection,
"No common key exchange method.\r\n"); "No common key exchange method.\r\n");
/* FIXME: We want the disconnect message to be sent return LSH_FAIL | LSH_CLOSE;
* before the socket is closed. How? */
return WRITE_CLOSED;
} }
} }
hostkey_algorithm hostkey_algorithm
...@@ -266,7 +264,7 @@ static int do_handle_kexinit(struct packet_handler *c, ...@@ -266,7 +264,7 @@ static int do_handle_kexinit(struct packet_handler *c,
if (!parameters[i]) if (!parameters[i])
{ {
disconnect_kex_failed(connection, ""); disconnect_kex_failed(connection, "");
return WRITE_CLOSED; return LSH_FAIL | LSH_CLOSE;
} }
} }
...@@ -433,10 +431,10 @@ static int do_handle_newkeys(struct packet_handler *c, ...@@ -433,10 +431,10 @@ static int do_handle_newkeys(struct packet_handler *c,
connection->dispatch[SSH_MSG_NEWKEYS] = NULL; connection->dispatch[SSH_MSG_NEWKEYS] = NULL;
lsh_free(closure); lsh_free(closure);
return WRITE_OK; return LSH_OK | LSH_GOON;
} }
else else
return WRITE_CLOSED; return LSH_FAIL | LSH_DIE;
} }
struct packet_handler * struct packet_handler *
......
...@@ -32,7 +32,7 @@ static int do_ignore(struct packet_handler *closure, ...@@ -32,7 +32,7 @@ static int do_ignore(struct packet_handler *closure,
struct lsh_string *packet) struct lsh_string *packet)
{ {
lsh_string_free(packet); lsh_string_free(packet);
return WRITE_OK; return LSH_OK | LSH_GOON;
} }
struct packet_handler *make_ignore_handler(void) struct packet_handler *make_ignore_handler(void)
......
...@@ -60,14 +60,14 @@ static int do_read_data(struct read_handler **h, ...@@ -60,14 +60,14 @@ static int do_read_data(struct read_handler **h,
/* Fall through */ /* Fall through */
case A_EOF: case A_EOF:
CALLBACK(closure->close_callback); CALLBACK(closure->close_callback);
return WRITE_CLOSED; return LSH_OK | LSH_CLOSE;
default: default:
{ {
int res; int res;
packet->length = n; packet->length = n;
/* FIXME: Use returned value */ /* FIXME: Use returned value */
res = A_WRITE(closure->handler, packet); res = A_WRITE(closure->handler, packet);
if (res != WRITE_OK) if (LSH_PROBLEMP(res))
return res; return res;
break; break;
} }
......
...@@ -77,7 +77,7 @@ lsh_string_realloc(struct lsh_string *s, UINT32 length) ...@@ -77,7 +77,7 @@ lsh_string_realloc(struct lsh_string *s, UINT32 length)
else else
return s; return s;
} }
static int do_read_packet(struct read_handler **h, static int do_read_packet(struct read_handler **h,
struct abstract_read *read) struct abstract_read *read)
{ {
...@@ -85,214 +85,202 @@ static int do_read_packet(struct read_handler **h, ...@@ -85,214 +85,202 @@ static int do_read_packet(struct read_handler **h,
MDEBUG(closure); MDEBUG(closure);
#if 0 switch(closure->state)
while(1)
{ {
#endif case WAIT_START:
switch(closure->state) {
{ UINT32 block_size = closure->connection->rec_crypto
case WAIT_START: ? closure->connection->rec_crypto->block_size : 8;
closure->buffer = lsh_string_realloc(closure->buffer,
block_size);
closure->pos = 0;
closure->state = WAIT_HEADER;
/* FALL THROUGH */
}
case WAIT_HEADER:
{
UINT32 block_size = closure->connection->rec_crypto
? closure->connection->rec_crypto->block_size : 8;
UINT32 left;
int n;
left = block_size - closure->pos;
n = A_READ(read, left, closure->buffer->data + closure->pos);
switch(n)
{ {
UINT32 block_size = closure->connection->rec_crypto case 0:
? closure->connection->rec_crypto->block_size : 8; return LSH_OK | LSH_GOON;
case A_FAIL:
closure->buffer = lsh_string_realloc(closure->buffer, return LSH_FAIL | LSH_DIE;
block_size); case A_EOF:
closure->pos = 0; /* FIXME: Free associated resources! */
return LSH_OK | LSH_CLOSE;
closure->state = WAIT_HEADER;
/* FALL THROUGH */
} }
case WAIT_HEADER: closure->pos += n;
/* Read a complete block? */
if (n == left)
{ {
UINT32 block_size = closure->connection->rec_crypto UINT32 length;
? closure->connection->rec_crypto->block_size : 8;
UINT32 left;
int n;
left = block_size - closure->pos; if (closure->connection->rec_crypto)
CRYPT(closure->connection->rec_crypto,
n = A_READ(read, left, closure->buffer->data + closure->pos); block_size,
switch(n) closure->buffer->data,
closure->buffer->data);
length = READ_UINT32(closure->buffer->data);
if (length > closure->connection->rec_max_packet)
{ {
case 0: werror("read_packet: Recieving too large packet.\n"
return 1; " %d octets, limit is %d\n",
case A_FAIL: length, closure->connection->rec_max_packet);
/* Fall through */ return LSH_FAIL | LSH_DIE;
case A_EOF:
/* FIXME: Free associated resources! */
return 0;
} }
closure->pos += n;
/* Read a complete block? */ if ( (length < 12)
if (n == left) || (length < (block_size - 4))
|| ( (length + 4) % block_size))
{ {
UINT32 length; werror("read_packet: Bad packet length %d\n",
length);
return LSH_FAIL | LSH_DIE;
}
if (closure->connection->rec_crypto) /* Process this block before the length field is lost. */
CRYPT(closure->connection->rec_crypto, if (closure->connection->rec_mac)
block_size, {
closure->buffer->data, UINT8 s[4];
closure->buffer->data); WRITE_UINT32(s, closure->sequence_number);
length = READ_UINT32(closure->buffer->data);
if (length > closure->connection->rec_max_packet)
{
werror("read_packet: Recieving too large packet.\n"
" %d octets, limit is %d\n",
length, closure->connection->rec_max_packet);
return 0;
}
if ( (length < 12)
|| (length < (block_size - 4))
|| ( (length + 4) % block_size))
{
werror("read_packet: Bad packet length %d\n",
length);
return 0;
}
/* Process this block before the length field is lost. */
if (closure->connection->rec_mac)
{
UINT8 s[4];
WRITE_UINT32(s, closure->sequence_number);
HASH_UPDATE(closure->connection->rec_mac, 4, s); HASH_UPDATE(closure->connection->rec_mac, 4, s);
HASH_UPDATE(closure->connection->rec_mac, HASH_UPDATE(closure->connection->rec_mac,
closure->buffer->length, closure->buffer->length,
closure->buffer->data); closure->buffer->data);
}
/* Allocate full packet */
{
int done = block_size - 4;
closure->buffer
= ssh_format("%ls%lr",
done,
closure->buffer->data + 4,
length - done,
&closure->crypt_pos);
/* FIXME: Is this needed anywhere? */
closure->buffer->sequence_number
= closure->sequence_number++;
closure->pos = done;
closure->state = WAIT_CONTENTS;
}
/* Fall through */
} }
else
/* Try reading some more */ /* Allocate full packet */
break; {
int done = block_size - 4;
closure->buffer
= ssh_format("%ls%lr",
done,
closure->buffer->data + 4,
length - done,
&closure->crypt_pos);
/* FIXME: Is this needed anywhere? */
closure->buffer->sequence_number
= closure->sequence_number++;
closure->pos = done;
closure->state = WAIT_CONTENTS;
}
/* Fall through */
} }
case WAIT_CONTENTS: else