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

Work in progress.

Rev: src/abstract_io.h:1.29
Rev: src/channel.c:1.50
Rev: src/channel.h:1.40
Rev: src/channel_commands.c:1.12
Rev: src/client.c:1.70
Rev: src/client_keyexchange.c:1.30
Rev: src/client_pty.c:1.9
Rev: src/client_userauth.c:1.18
Rev: src/combinators.c:1.7
Rev: src/command.c:1.24
Rev: src/command.h:1.32
Rev: src/compress.c:1.6
Rev: src/connection.c:1.37
Rev: src/connection.h:1.33
Rev: src/connection_commands.c:1.9
Rev: src/debug.c:1.27
Rev: src/debug.h:1.11
Rev: src/disconnect.c:1.15
Rev: src/encrypt.c:1.20
Rev: src/exception.c:1.2
Rev: src/exception.h:1.3
Rev: src/io.c:1.68
Rev: src/io.h:1.41
Rev: src/io_commands.c:1.17
Rev: src/keyexchange.c:1.52
Rev: src/keyexchange.h:1.37
Rev: src/lsh.c:1.66
Rev: src/lsh.h:1.7
Rev: src/lsh_keygen.c:1.13
Rev: src/lsh_writekey.c:1.9
Rev: src/lshd.c:1.59
Rev: src/packet_ignore.c:1.9
Rev: src/pad.c:1.23
Rev: src/read_data.c:1.21
Rev: src/read_data.h:1.9
Rev: src/read_line.c:1.26
Rev: src/read_line.h:1.14
Rev: src/read_packet.c:1.39
Rev: src/read_scan.c:1.8
Rev: src/read_scan.h:1.6
Rev: src/server.c:1.57
Rev: src/server_keyexchange.c:1.28
Rev: src/server_password.c:1.21
Rev: src/server_session.c:1.12
Rev: src/server_userauth.c:1.13
Rev: src/sexp_test.c:1.9
Rev: src/tcpforward.c:1.26
Rev: src/tcpforward_commands.c:1.9
Rev: src/unpad.c:1.17
Rev: src/userauth.h:1.14
Rev: src/werror.c:1.34
Rev: src/write_buffer.c:1.19
parent 1d560ceb
......@@ -68,7 +68,7 @@
;; On errors, it can set self to NULL, but only for
;; debugging purposes; it's the responibility of the the
;; exception handler to close the corresponding fd and
;; make sure that handler is not called again.
;; make sure that handler is not called again. '
UINT32 "UINT32 available" "UINT8 *data")))
"struct exception_handler *e")))
......
This diff is collapsed.
......@@ -205,7 +205,7 @@
(class
(name global_request_callback)
(vars
(response method int "int success")
(response method void "int success")
(connection object ssh_connection)))
*/
......@@ -225,7 +225,8 @@
/* SSH_MSG_CHANNEL_OPEN */
/* Raised if opening of a channel fails. */
/* Raised if opening of a channel fails. Used both on the client and
* the server side.*/
/* GABA:
(class
(name channel_open_exception)
......@@ -234,6 +235,8 @@
(error_code . UINT32)))
*/
struct exception *make_channel_open_exception(UINT32 error_code, char *msg);
#if 0
/* Callback function, used to report success or failure for a
* requested channel open. */
......@@ -273,7 +276,7 @@
(class
(name channel_request)
(vars
(handler method int
(handler method void
"struct ssh_channel *channel"
"struct ssh_connection *connection"
"int want_reply"
......@@ -298,15 +301,19 @@ void init_channel(struct ssh_channel *channel);
struct channel_table *make_channel_table(void);
int alloc_channel(struct channel_table *table);
void dealloc_channel(struct channel_table *table, int i);
int register_channel(struct channel_table *table, struct ssh_channel *channel);
void register_channel(struct channel_table *table,
UINT32 local_channel_number,
struct ssh_channel *channel);
struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i);
struct abstract_write *make_channel_write(struct ssh_channel *channel);
struct abstract_write *make_channel_write_extended(struct ssh_channel *channel,
UINT32 type);
struct read_handler *make_channel_read_data(struct ssh_channel *channel);
struct read_handler *make_channel_read_stderr(struct ssh_channel *channel);
struct io_read_callback *make_channel_read_data(struct ssh_channel *channel);
struct io_read_callback *make_channel_read_stderr(struct ssh_channel *channel);
struct lsh_string *format_global_failure(void);
struct lsh_string *format_global_success(void);
......@@ -323,7 +330,7 @@ struct lsh_string *format_channel_failure(UINT32 channel);
struct lsh_string *prepare_window_adjust(struct ssh_channel *channel,
UINT32 add);
int channel_start_receive(struct ssh_channel *channel);
void channel_start_receive(struct ssh_channel *channel);
struct lsh_string *prepare_channel_open(struct channel_table *table,
int type,
......@@ -338,8 +345,8 @@ struct lsh_string *format_channel_request(int type,
struct lsh_string *format_channel_close(struct ssh_channel *channel);
struct lsh_string *format_channel_eof(struct ssh_channel *channel);
int channel_close(struct ssh_channel *channel);
int channel_eof(struct ssh_channel *channel);
void channel_close(struct ssh_channel *channel);
void channel_eof(struct ssh_channel *channel);
struct close_callback *make_channel_close(struct ssh_channel *channel);
......
......@@ -91,7 +91,7 @@ void do_channel_global_command(struct command *s,
= FORMAT_GLOBAL_REQUEST(self, connection, &c);
if (c)
object_queue_add_tail(&connection->channels->pending_global_requests,
object_queue_add_tail(&connection->table->pending_global_requests,
&make_command_context(c, e)->super);
C_WRITE(connection, request);
......@@ -111,7 +111,7 @@ do_install_global_request_handler(struct collect_info_2 *info,
trace("do_install_global_request_handler(%i)\n", self->name);
ALIST_SET(connection->channels->global_requests,
ALIST_SET(connection->table->global_requests,
self->name,
handler);
......@@ -132,7 +132,7 @@ do_install_channel_open_handler(struct collect_info_2 *info,
trace("do_install_channel_open_handler(%i)\n", self->name);
ALIST_SET(connection->channels->channel_types,
ALIST_SET(connection->table->channel_types,
self->name,
handler);
......@@ -162,7 +162,7 @@ do_install_fix_global_request_handler(struct command *s,
trace("do_install_fix_global_request_handler(%i)\n", self->name);
ALIST_SET(connection->channels->global_requests,
ALIST_SET(connection->table->global_requests,
self->name,
self->handler);
......@@ -205,7 +205,8 @@ do_install_fix_channel_open_handler(struct command *s,
trace("do_install_fix_channel_open_handler(%i)\n", self->name);
ALIST_SET(connection->channels->channel_types,
ALIST_SET(connection->table
->channel_types,
self->name,
self->handler);
......
......@@ -188,7 +188,8 @@ struct command *make_request_service(int service)
*/
/* Callback used when the server sends us eof */
static int do_client_session_eof(struct ssh_channel *c)
static void
do_client_session_eof(struct ssh_channel *c)
{
CAST(client_session, session, c);
......@@ -197,13 +198,15 @@ static int do_client_session_eof(struct ssh_channel *c)
close_fd(&session->out->super, 0);
close_fd(&session->err->super, 0);
#endif
return LSH_OK;
}
static int do_client_session_close(struct ssh_channel *c UNUSED)
static void
do_client_session_close(struct ssh_channel *c)
{
return LSH_CHANNEL_PENDING_CLOSE;
static const struct exception finish_exception
= STATIC_EXCEPTION(EXC_FINISH_PENDING, "Session closed.");
EXCEPTION_RAISE(c->e, &finish_exception);
}
......@@ -215,11 +218,12 @@ static int do_client_session_close(struct ssh_channel *c UNUSED)
(exit_status simple "int *")))
*/
static int do_exit_status(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
int want_reply,
struct simple_buffer *args)
static void
do_exit_status(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
int want_reply,
struct simple_buffer *args)
{
CAST(exit_handler, closure, c);
int status;
......@@ -233,25 +237,27 @@ static int do_exit_status(struct channel_request *c,
ALIST_SET(channel->request_types, ATOM_EXIT_STATUS, NULL);
ALIST_SET(channel->request_types, ATOM_EXIT_SIGNAL, NULL);
/* Sent EOF, if we haven't done that already. */
/* Send EOF, if we haven't done that already. */
/* FIXME: Make this behaviour configurable, there may be some
* child process alive that we could talk to. */
if (!(channel->flags & CHANNEL_SENT_EOF))
return channel_eof(channel);
return LSH_OK | LSH_GOON;
channel_eof(channel);
}
/* Invalid request */
return LSH_FAIL | LSH_DIE;
else
/* Invalid request */
EXCEPTION_RAISE
(channel->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid exit-status message"));
}
static int do_exit_signal(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
int want_reply,
struct simple_buffer *args)
static void
do_exit_signal(struct channel_request *c,
struct ssh_channel *channel,
struct ssh_connection *connection UNUSED,
int want_reply,
struct simple_buffer *args)
{
CAST(exit_handler, closure, c);
......@@ -291,13 +297,14 @@ static int do_exit_signal(struct channel_request *c,
* child process alive that we could talk to. */
if (!(channel->flags & CHANNEL_SENT_EOF))
return channel_eof(channel);
return LSH_OK | LSH_GOON;
channel_eof(channel);
}
/* Invalid request */
return LSH_FAIL | LSH_DIE;
else
/* Invalid request */
EXCEPTION_RAISE
(channel->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid exit-signal message"));
}
struct channel_request *make_handle_exit_status(int *exit_status)
......@@ -332,10 +339,10 @@ do_receive(struct ssh_channel *c,
switch(type)
{
case CHANNEL_DATA:
A_WRITE(&closure->out->buffer->super, data, c->e);
A_WRITE(&closure->out->write_buffer->super, data, c->e);
break;
case CHANNEL_STDERR_DATA:
A_WRITE(&closure->err->buffer->super, data, c->e);
A_WRITE(&closure->err->write_buffer->super, data, c->e);
break;
default:
fatal("Internal error!\n");
......@@ -353,10 +360,11 @@ static void do_send(struct ssh_channel *c)
}
/* We have a remote shell */
static int do_client_io(struct command *s UNUSED,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e UNUSED)
static void
do_client_io(struct command *s UNUSED,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e UNUSED)
{
assert(x);
......@@ -387,7 +395,7 @@ static int do_client_io(struct command *s UNUSED,
channel->eof = do_client_session_eof;
return COMMAND_RETURN(c, channel);
COMMAND_RETURN(c, channel);
}
}
......@@ -423,8 +431,8 @@ struct ssh_channel *make_client_session(struct io_fd *in,
self->err = err;
/* Flow control */
out->buffer->report = &self->super.super;
err->buffer->report = &self->super.super;
out->write_buffer->report = &self->super.super;
err->write_buffer->report = &self->super.super;
self->exit_status = exit_status;
......@@ -451,7 +459,7 @@ new_session(struct channel_open_command *s,
self->session->write = connection->write;
*request = prepare_channel_open(connection->channels, ATOM_SESSION,
*request = prepare_channel_open(connection->table, ATOM_SESSION,
self->session, "");
if (!*request)
return NULL;
......
......@@ -57,22 +57,21 @@
(install object install_keys)))
*/
static int do_handle_dh_reply(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
static void
do_handle_dh_reply(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(dh_client, closure, c);
struct verifier *v;
struct hash_instance *hash;
struct command_continuation *continuation;
int res;
verbose("handle_dh_reply()\n");
if (!dh_process_server_msg(&closure->dh, packet))
{
disconnect_kex_failed(connection, "Bad dh-reply\r\n");
return LSH_FAIL | LSH_CLOSE;
return;
}
v = LOOKUP_VERIFIER(closure->verifier, closure->dh.server_key);
......@@ -81,23 +80,23 @@ static int do_handle_dh_reply(struct packet_handler *c,
/* FIXME: Use a more appropriate error code? */
{
disconnect_kex_failed(connection, "Bad server host key\r\n");
return LSH_FAIL | LSH_CLOSE;
return;
}
if (!dh_verify_server_msg(&closure->dh, v))
/* FIXME: Same here */
return disconnect_kex_failed(connection, "Invalid server signature\r\n");
{
/* FIXME: Same here */
disconnect_kex_failed(connection, "Invalid server signature\r\n");
return;
}
/* Key exchange successful! Send a newkeys message, and install a
* handler for receiving the newkeys message. */
res = A_WRITE(connection->write, ssh_format("%c", SSH_MSG_NEWKEYS),
connection->e);
if (LSH_CLOSEDP(res))
return res;
C_WRITE(connection, ssh_format("%c", SSH_MSG_NEWKEYS));
/* FIXME: Perhaps more this key handling could be abstracted away,
* instead of duplicating it in client_keyexchange.c and
/* FIXME: Perhaps more of this key handling could be abstracted
* away, instead of duplicating it in client_keyexchange.c and
* server_keyexchange.c. */
/* A hash instance initialized with the key, to be used for key
......@@ -117,8 +116,12 @@ static int do_handle_dh_reply(struct packet_handler *c,
{
werror("Installing new keys failed. Hanging up.\n");
KILL(hash);
/* FIXME: Send a disconnect message */
return LSH_FAIL | LSH_DIE;
EXCEPTION_RAISE(connection->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Refusing to use weak key."));
return;
}
KILL(hash);
......@@ -126,27 +129,27 @@ static int do_handle_dh_reply(struct packet_handler *c,
connection->dispatch[SSH_MSG_KEXDH_REPLY] = connection->fail;
connection->kex_state = KEX_STATE_NEWKEYS;
res |= send_verbose(connection->write, "Key exchange successful!", 0);
if (LSH_CLOSEDP(res) || !connection->established)
return res;
send_verbose(connection, "Key exchange successful!", 0);
continuation = connection->established;
connection->established = NULL;
if (connection->established)
{
struct command_continuation *c = connection->established;
connection->established = NULL;
return res | COMMAND_RETURN(continuation, connection);
COMMAND_RETURN(c, connection);
}
}
static int do_init_client_dh(struct keyexchange_algorithm *c,
struct ssh_connection *connection,
int hostkey_algorithm_atom,
struct signature_algorithm *ignored,
struct object_list *algorithms)
static void
do_init_client_dh(struct keyexchange_algorithm *c,
struct ssh_connection *connection,
int hostkey_algorithm_atom,
struct signature_algorithm *ignored,
struct object_list *algorithms)
{
CAST(dh_client_exchange, closure, c);
NEW(dh_client, dh);
int res;
CHECK_SUBTYPE(ssh_connection, connection);
CHECK_SUBTYPE(signature_algorithm, ignored);
......@@ -162,17 +165,12 @@ static int do_init_client_dh(struct keyexchange_algorithm *c,
dh->install = make_install_new_keys(0, algorithms);
/* Send client's message */
res = A_WRITE(connection->write, dh_make_client_msg(&dh->dh));
C_WRITE(connection, dh_make_client_msg(&dh->dh));
if (LSH_CLOSEDP(res))
return res | LSH_FAIL;
/* Install handler */
connection->dispatch[SSH_MSG_KEXDH_REPLY] = &dh->super;
connection->kex_state = KEX_STATE_IN_PROGRESS;
return res | LSH_OK | LSH_GOON;
}
......
......@@ -29,6 +29,8 @@
#include "werror.h"
#include "xalloc.h"
#include <assert.h>
#include "client_pty.c.x"
/* GABA:
......@@ -53,11 +55,13 @@
(req object pty_request)))
*/
static int do_pty_continuation(struct command_continuation *s,
struct lsh_object *x)
static void
do_pty_continuation(struct command_continuation *s,
struct lsh_object *x)
{
CAST(pty_request_continuation, self, s);
assert(x);
verbose("lsh: pty request %z.\n", x ? "successful" : "failed");
if (x)
......@@ -70,7 +74,6 @@ static int do_pty_continuation(struct command_continuation *s,
}
COMMAND_RETURN(self->super.up, x);
}
return LSH_OK | LSH_GOON;
}
static struct command_continuation *
......
......@@ -79,6 +79,7 @@ static struct packet_handler *make_banner_handler(void);
(name failure_handler)
(super packet_handler)
(vars
(e object exception_handler)
(userauth object client_userauth)))
*/
......@@ -98,8 +99,9 @@ static struct lsh_string *format_userauth_password(struct lsh_string *name,
#define MAX_PASSWD 100
static int send_passwd(struct client_userauth *userauth,
struct ssh_connection *connection)
static void
send_passwd(struct client_userauth *userauth,
struct ssh_connection *connection)
{
struct lsh_string *passwd
= read_password(MAX_PASSWD,
......@@ -107,18 +109,22 @@ static int send_passwd(struct client_userauth *userauth,
userauth->username), 1);
if (!passwd)
return LSH_FAIL | LSH_DIE;
{
/* FIXME: What to do now??? */
fatal("read_password failed!?\n");
}
return A_WRITE(connection->write,
format_userauth_password(local_to_utf8(userauth->username, 0),
userauth->service_name,
local_to_utf8(passwd, 1),
1));
C_WRITE(connection,
format_userauth_password(local_to_utf8(userauth->username, 0),
userauth->service_name,
local_to_utf8(passwd, 1),
1));
}
static int do_userauth_success(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
static void
do_userauth_success(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(success_handler, closure, c);
struct simple_buffer buffer;
......@@ -139,19 +145,25 @@ static int do_userauth_success(struct packet_handler *c,
connection->dispatch[SSH_MSG_USERAUTH_FAILURE] = connection->fail;
connection->dispatch[SSH_MSG_USERAUTH_BANNER] = connection->fail;
return COMMAND_RETURN(closure->c, connection);
COMMAND_RETURN(closure->c, connection);
}
else
{
lsh_string_free(packet);
EXCEPTION_RAISE
(connection->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid USERAUTH_SUCCESS message"));
}
lsh_string_free(packet);
return LSH_FAIL | LSH_DIE;
}
/* Arbitrary limit on list length */
#define USERAUTH_MAX_METHODS 47
static int do_userauth_failure(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
static void
do_userauth_failure(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(failure_handler, closure, c);
struct simple_buffer buffer;
......@@ -169,39 +181,45 @@ static int do_userauth_failure(struct packet_handler *c,
&& parse_eod(&buffer))
{
unsigned i;
static const struct exception denied
= STATIC_EXCEPTION(EXC_FINISH_IO, "Access denied");
lsh_string_free(packet);
if (partial_success)
{ /* Doesn't help us */
werror("Received SSH_MSH_USERAUTH_FAILURE "
"indicating partial success.\n");
KILL(methods);
return LSH_FAIL | LSH_DIE;
}
/* Doesn't help us */
werror("Received SSH_MSH_USERAUTH_FAILURE "
"indicating partial success.\n");
for(i = 0; i < LIST_LENGTH(methods); i++)
if (LIST(methods)[i] == ATOM_PASSWORD)
{
/* Try again */
KILL(methods);
return send_passwd(closure->userauth, connection);
send_passwd(closure->userauth, connection);
return;
}
/* No methods that we can use */
KILL(methods);
return LSH_FAIL | LSH_DIE;
}
KILL(methods);
lsh_string_free(packet);
return LSH_FAIL | LSH_DIE;
EXCEPTION_RAISE(closure->e, &denied);
}
else
{
KILL(methods);
lsh_string_free(packet);
EXCEPTION_RAISE
(connection->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalud USERAUTH_FAILURE message."));
}
}
static int do_userauth_banner(struct packet_handler *closure,
struct ssh_connection *connection UNUSED,
struct lsh_string *packet)
static void
do_userauth_banner(struct packet_handler *closure,
struct ssh_connection *connection UNUSED,
struct lsh_string *packet)
{
struct simple_buffer buffer;
......@@ -223,13 +241,15 @@ static int do_userauth_banner(struct packet_handler *closure,
&& parse_eod(&buffer))
{
/* Ignore language tag */
werror("%us", length, msg);
lsh_string_free(packet);
return LSH_OK | LSH_GOON;
werror("%ups", length, msg);
}
else
EXCEPTION_RAISE
(connection->e,
make_protocol_exception(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid USERAUTH_SUCCESS message"));
lsh_string_free(packet);
return LSH_FAIL | LSH_DIE;
}
static struct packet_handler *
......@@ -244,11 +264,13 @@ make_success_handler(struct command_continuation *c)
}
static struct packet_handler *
make_failure_handler(struct client_userauth *userauth)
make_failure_handler(struct client_userauth *userauth,
struct exception_handler *e)