Commit c93230a7 authored by Balázs Scheidler's avatar Balázs Scheidler Committed by Niels Möller
Browse files

* src/lsh_proxy.c, src/proxy.c, src/proxy.h, src/proxy_session.c,

src/proxy_session.h, src/proxy_userauth.c, src/proxy_userauth.h:
Applied Bazsi's patches.

Rev: src/lsh_proxy.c:1.3
Rev: src/proxy.c:1.2
Rev: src/proxy.h:1.2
Rev: src/proxy_session.c:1.2
Rev: src/proxy_session.h:1.2
Rev: src/proxy_userauth.c:1.2
Rev: src/proxy_userauth.h:1.2
parent 9376767d
......@@ -54,9 +54,21 @@
#include "proxy_session.h"
#include "sexp.h"
#include "sexp_commands.h"
#include "spki_commands.h"
#include "lsh_argp.h"
/* Forward declarations */
struct command_simple options2local;
#define OPTIONS2LOCAL (&options2local.super.super)
static struct command options2keyfile;
#define OPTIONS2KEYFILE (&options2keyfile.super)
struct command_simple options2signature_algorithms;
#define OPTIONS2SIGNATURE_ALGORITHMS \
(&options2signature_algorithms.super.super)
#include "lsh_proxy.c.x"
#include <assert.h>
......@@ -95,6 +107,8 @@
(name lsh_proxy_options)
(super algorithms_options)
(vars
(backend object io_backend)
(signature_algorithms object alist)
(style . sexp_argp_state)
(interface . "char *")
(port . "char *")
......@@ -110,12 +124,18 @@
*/
static struct lsh_proxy_options *
make_lsh_proxy_options(struct alist *algorithms)
make_lsh_proxy_options(struct io_backend *backend,
struct randomness *random,
struct alist *algorithms)
{
NEW(lsh_proxy_options, self);
init_algorithms_options(&self->super, algorithms);
self->signature_algorithms
= make_alist(1,
ATOM_DSA, make_dsa_algorithm(random), -1);
self->backend = backend;
self->style = SEXP_TRANSPORT;
self->interface = NULL;
self->port = "ssh";
......@@ -136,6 +156,46 @@ make_lsh_proxy_options(struct alist *algorithms)
return self;
}
/* Port to listen on */
COMMAND_SIMPLE(options2local)
{
CAST(lsh_proxy_options, options, a);
return &options->local->super;
}
/* alist of signature algorithms */
COMMAND_SIMPLE(options2signature_algorithms)
{
CAST(lsh_proxy_options, options, a);
return &options->signature_algorithms->super;
}
/* Read server's private key */
static void
do_options2keyfile(struct command *ignored UNUSED,
struct lsh_object *a,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(lsh_proxy_options, options, a);
struct io_fd *f;
f = io_read_file(options->backend, options->hostkey, e);
if (f)
COMMAND_RETURN(c, f);
else
{
werror("Failed to open '%z' (errno = %i): %z.\n",
options->hostkey, errno, STRERROR(errno));
EXCEPTION_RAISE(e, make_io_exception(EXC_IO_OPEN_READ, NULL, errno, NULL));
}
}
static struct command options2keyfile =
STATIC_COMMAND(do_options2keyfile);
static const struct argp_option
main_options[] =
{
......@@ -294,26 +354,27 @@ make_fake_host_db(void)
return &res->super;
}
/* GABA:
(expr
(name lsh_proxy_listen)
(params
(listen object command)
(handshake object handshake_info)
(keys object alist)
(services object command)
(connect_server object command)
(chain_connections object command))
(expr
(lambda (port)
(lambda (options)
(services
(let ((peer (listen port)))
(let ((peer (listen(options2local options))))
(chain_connections
connect_server
peer
(connection_handshake
handshake keys (log_peer peer))))))))
handshake
(spki_read_hostkeys (options2signature_algorithms options)
(options2keyfile options))
(log_peer peer))))))))
*/
/* GABA:
......@@ -325,7 +386,8 @@ make_fake_host_db(void)
(handshake object handshake_info))
(expr
(lambda (port)
(connection_handshake handshake verifier (connect port)))))
(init_connection_service
(connection_handshake handshake verifier (connect port))))))
*/
/* Invoked when the client requests the userauth service. */
......@@ -345,7 +407,7 @@ make_fake_host_db(void)
(name lsh_proxy_connection_service)
(params
(login object command)
(hooks object object_list))
(hooks object object_list))
(expr
(lambda (user connection)
((progn hooks) (login user
......@@ -365,7 +427,6 @@ int main(int argc, char **argv)
struct randomness *r;
struct alist *algorithms_server, *algorithms_client;
struct make_kexinit *make_kexinit;
struct keypair *hostkey;
/* FIXME: Why not allocate backend statically? */
NEW(io_backend, backend);
......@@ -387,7 +448,7 @@ int main(int argc, char **argv)
ATOM_SSH_DSS, make_dsa_algorithm(r),
-1);
options = make_lsh_proxy_options(algorithms_server);
options = make_lsh_proxy_options(backend, r, algorithms_server);
argp_parse(&main_argp, argc, argv, 0, NULL, options);
......@@ -483,22 +544,23 @@ int main(int argc, char **argv)
algorithms_server,
make_kexinit,
NULL),
keys,
make_offer_service(make_alist(1,
ATOM_SSH_USERAUTH,
lsh_proxy_services
(make_userauth_proxy
(make_int_list(1, ATOM_PASSWORD, -1),
make_alist(1, ATOM_PASSWORD, &proxy_password_auth, -1),
make_alist
(1,
ATOM_SSH_CONNECTION,
lsh_proxy_connection_service
(make_proxy_connection_service
(make_alist(0, -1)),
connection_hooks),
-1))),
-1)),
make_proxy_offer_service
(make_alist(1,
ATOM_SSH_USERAUTH,
lsh_proxy_services
(make_proxy_userauth
(make_int_list(1, ATOM_PASSWORD, -1),
make_alist(1, ATOM_PASSWORD, &proxy_password_auth, -1),
make_alist
(1,
ATOM_SSH_CONNECTION,
lsh_proxy_connection_service
(make_proxy_connection_service
(make_alist(0, -1),
make_alist(0, -1)),
connection_hooks),
-1))),
-1)),
/* callback to call when client<->proxy handshake finished */
(struct command *)lsh_proxy_connect_server(make_simple_connect(backend, NULL),
......@@ -517,7 +579,7 @@ int main(int argc, char **argv)
CAST_SUBTYPE(command, server_listen, o);
COMMAND_CALL(server_listen, options->local,
COMMAND_CALL(server_listen, options,
&discard_continuation,
make_report_exception_handler(EXC_IO, EXC_IO, "lsh_proxy: ",
&default_exception_handler,
......
......@@ -31,11 +31,12 @@
#include "command.h"
#include "format.h"
#include "io_commands.h"
#include "ssh.h"
#include <assert.h>
#include <arpa/inet.h>
#include "proxy.c.x"
#include "proxy.c.x"
/* GABA:
(class
......@@ -134,14 +135,14 @@ STATIC_COLLECT_2_FINAL(do_collect_chain_params);
struct collect_info_1 chain_connections =
STATIC_COLLECT_1(&chain_connections_2);
/* gets two params: user connection ->
handles user here, and returns a command taking a connection */
/* (proxy_connection_service user connection) -> connection */
/* GABA:
(class
(name proxy_connection_service)
(super command)
(vars
(session_requests object alist)))
(server_requests object alist)
(client_requests object alist)))
*/
static void
......@@ -155,15 +156,193 @@ do_login(struct command *s,
COMMAND_RETURN(c,
make_install_fix_channel_open_handler
(ATOM_SESSION,
make_proxy_open_session(self->session_requests)));
make_proxy_open_session(self->server_requests,
self->client_requests)));
}
struct command *
make_proxy_connection_service(struct alist *session_requests)
make_proxy_connection_service(struct alist *server_requests,
struct alist *client_requests)
{
NEW(proxy_connection_service, self);
self->super.call = do_login;
self->session_requests = session_requests;
self->server_requests = server_requests;
self->client_requests = client_requests;
return &self->super;
}
/* GABA:
(class
(name proxy_accept_service_handler)
(super packet_handler)
(vars
(name . UINT32)
(service object command)
(c object command_continuation)
(e object exception_handler)))
*/
static void
do_proxy_accept_service(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(proxy_accept_service_handler, closure, c);
struct simple_buffer buffer;
UINT32 msg_number;
UINT32 name;
simple_buffer_init(&buffer, packet->length, packet->data);
if (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_SERVICE_ACCEPT)
&& (
#if DATAFELLOWS_WORKAROUNDS
(connection->peer_flags & PEER_SERVICE_ACCEPT_KLUDGE)
#else
0
#endif
|| (parse_atom(&buffer, &name)
&& (name == closure->name)))
&& parse_eod(&buffer))
{
connection->dispatch[SSH_MSG_SERVICE_ACCEPT] = connection->fail;
C_WRITE(connection->chain, packet);
COMMAND_CALL(closure->service,
connection->chain,
closure->c, closure->e);
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(closure->e, "Invalid SSH_MSG_SERVICE_ACCEPT message");
}
}
static struct packet_handler *
make_proxy_accept_service_handler(UINT32 name,
struct command *service,
struct command_continuation *c,
struct exception_handler *e)
{
NEW(proxy_accept_service_handler, self);
self->super.handler = do_proxy_accept_service;
self->name = name;
self->service = service;
self->c = c;
self->e = e;
return &self->super;
}
/* GABA:
(class
(name proxy_service_handler)
(super packet_handler)
(vars
(services object alist)
(c object command_continuation)
(e object exception_handler)))
*/
static void
do_proxy_service_request(struct packet_handler *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(proxy_service_handler, self, c);
struct simple_buffer buffer;
unsigned msg_number;
int name;
simple_buffer_init(&buffer, packet->length, packet->data);
if (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_SERVICE_REQUEST)
&& parse_atom(&buffer, &name)
&& parse_eod(&buffer))
{
if (name)
{
CAST_SUBTYPE(command, service, ALIST_GET(self->services, name));
if (service)
{
/* Don't accept any further service requests */
connection->dispatch[SSH_MSG_SERVICE_REQUEST]
= connection->fail;
connection->chain->dispatch[SSH_MSG_SERVICE_ACCEPT]
= make_proxy_accept_service_handler(name, service, self->c, self->e);
C_WRITE(connection->chain, packet);
return;
}
}
EXCEPTION_RAISE(connection->e,
make_protocol_exception(SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, NULL));
}
else
{
lsh_string_free(packet);
PROTOCOL_ERROR(connection->e, "Invalid SERVICE_REQUEST message");
}
}
static struct packet_handler *
make_proxy_service_handler(struct alist *services,
struct command_continuation *c,
struct exception_handler *e)
{
NEW(proxy_service_handler, self);
self->super.handler = do_proxy_service_request;
self->services = services;
self->c = c;
self->e = e;
return &self->super;
}
/* GABA:
(class
(name proxy_offer_service)
(super command)
(vars
(services object alist)))
*/
static void
do_proxy_offer_service(struct command *s,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(proxy_offer_service, self, s);
CAST(ssh_connection, connection, x);
connection->dispatch[SSH_MSG_SERVICE_REQUEST]
= make_proxy_service_handler(self->services, c, e);
#if 0
/* currently servers may not ask for servives in clients */
connection->chain->dispatch[SSH_MSG_SERVICE_REQUEST]
= make_proxy_service_request(self->server_services, c, e);
#endif
}
struct command *
make_proxy_offer_service(struct alist *services)
{
NEW(proxy_offer_service, self);
self->super.call = do_proxy_offer_service;
self->services = services;
return &self->super;
}
......@@ -30,6 +30,11 @@
extern struct collect_info_1 chain_connections;
struct command *
make_proxy_connection_service(struct alist *session_requests);
make_proxy_connection_service(struct alist *server_requests,
struct alist *client_requests);
struct command *
make_proxy_offer_service(struct alist *services);
#endif /* LSH_PROXY_H_INCLUDED */
......@@ -25,6 +25,7 @@
#include "xalloc.h"
#include "ssh.h"
#include "werror.h"
#include "channel_commands.h"
#include "proxy_session.c.x"
......@@ -35,27 +36,150 @@
(name proxy_channel)
(super ssh_channel)
(vars
(chain object proxy_channel)))
(chain object proxy_channel)
(init_io method void "struct proxy_channel *chain")))
*/
static struct ssh_channel *
static void
do_receive(struct ssh_channel *c UNUSED,
int type UNUSED,
struct lsh_string *data UNUSED)
{
}
static void
do_send(struct ssh_channel *s UNUSED,
struct ssh_connection *c UNUSED)
{
}
static void
do_eof(struct ssh_channel *channel UNUSED)
{
}
static void
do_proxy_init_io(struct proxy_channel *self,
struct proxy_channel *chain)
{
self->chain = chain;
self->super.send = do_send;
self->super.receive = do_receive;
self->super.eof = do_eof;
}
static struct proxy_channel *
make_proxy_channel(UINT32 window_size,
struct alist *session_requests)
struct alist *request_types)
{
NEW(proxy_channel, self);
init_channel(&self->super);
self->super.max_window = SSH_MAX_PACKET << 3;
self->super.rec_window_size = window_size;
self->super.rec_max_packet = SSH_MAX_PACKET;
self->super.request_types = request_types;
self->init_io = do_proxy_init_io;
return self;
}
/*
* continuation to handle the returned channel, and chain two channels
* together
*/
/* GABA:
(class
(name proxy_channel_open_continuation)
(super command_continuation)
(vars
(up object command_continuation)
(channel object proxy_channel)))
*/
static void
do_proxy_channel_open_continuation(struct command_continuation *c,
struct lsh_object *x)
{
CAST(proxy_channel_open_continuation, self, c);
CAST(proxy_channel, chain_channel, x);
self->channel->chain = chain_channel;
chain_channel = self->channel;
COMMAND_RETURN(self->up, self->channel);
}
static struct command_continuation *
make_proxy_channel_open_continuation(struct command_continuation *up,
struct proxy_channel *channel)
{
NEW(proxy_channel_open_continuation, self);
self->super.c = do_proxy_channel_open_continuation;
self->channel = channel;
self->up = up;
return &self->super;
}
/* command to request a channel open */
/* GABA:
(class
(name proxy_channel_open_command)
(super channel_open_command)
(vars
; channel type
(type . UINT32)
(requests object alist)))
*/
static struct ssh_channel *
do_proxy_open_channel(struct channel_open_command *c,
struct ssh_connection *connection,
struct lsh_string **request)
{
return NULL;
CAST(proxy_channel_open_command, closure, c);
struct proxy_channel *client = make_proxy_channel(WINDOW_SIZE, closure->requests);
*request = prepare_channel_open(connection, closure->type, &client->super, "");
if (!*request)
return NULL;
return &client->super;
}
static struct command *
make_proxy_channel_open_command(UINT32 type,
struct alist *requests)
{
NEW(proxy_channel_open_command, self);
self->super.new_channel = do_proxy_open_channel;
self->super.super.call = do_channel_open_command;
self->type = type;
self->requests = requests;
return &self->super.super;
}
/* GABA:
(class
(name proxy_open_session)
(super channel_open)
(vars
(session_requests object alist)))
; requests to accept from server -> client
(server_requests object alist)
; requests to accept from client -> server
(client_requests object alist)))
*/
static void
do_proxy_open_session(struct channel_open *s,
struct ssh_connection *connection,
UINT32 type,
struct simple_buffer *args,
struct command_continuation *c,
struct exception_handler *e)
......@@ -66,20 +190,29 @@ do_proxy_open_session(struct channel_open *s,
if (parse_eod(args))
{
struct proxy_channel *server = make_proxy_channel(WINDOW_SIZE, closure->server_requests);
struct command *o = make_proxy_channel_open_command(type, closure->client_requests);
COMMAND_CALL(o,
connection->chain,
make_proxy_channel_open_continuation(c, server),
e);
}
else
{
PROTOCOL_ERROR(e, "trailing garbage in open message");
PROTOCOL_ERROR(e, "Trailing garbage in open message");
}
}
struct channel_open *
make_proxy_open_session(struct alist *session_requests)
make_proxy_open_session(struct alist *server_requests,
struct alist *client_requests)
{
NEW(proxy_open_session, self);