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

Work in progress.

Rev: src/connection.h:1.9
Rev: src/keyexchange.c:1.6
Rev: src/keyexchange.h:1.7
parent 62ea4b3c
......@@ -24,9 +24,14 @@ struct packet_handler
#define HANDLE_PACKET(closure, connection, packet) \
((closure)->handler((closure), (connection), (packet)))
#define CONNECTION_SERVER 0
#define CONNECTION_CLIENT 1
struct ssh_connection
{
struct abstract_write super;
int type; /* CONNECTION_SERVER or CONNECTION_CLIENT */
/* Sent and recieved version strings */
struct lsh_string *client_version;
......@@ -49,9 +54,12 @@ struct ssh_connection
UINT32 max_packet;
/* Key exchange */
struct kexinit *recieved_kexinit;
struct kexinit *sent_kexinit;
int kex_state;
/* First element is the kexinit sent by the server */
struct kexinit *kexinits[2];
int ignore_one_packet;
int provides_privacy;
int provides_integrity;
};
......
/* keyexchange.c
*
*
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "abstract_io.h"
......@@ -59,32 +80,17 @@ struct kexinit *parse_kexinit(struct lsh_string *packet)
res->kex_algorithms = lists[0];
res->server_host_key_algorithms = lists[1];
res->encryption_algorithms_client_to_server = lists[2];
res->encryption_algorithms_server_to_client = lists[3];
res->mac_algorithms_client_to_server = lists[4];
res->mac_algorithms_server_to_client = lists[5];
res->compression_algorithms_client_to_server = lists[6];
res->compression_algorithms_server_to_client = lists[7];
for (i=0; i<KEX_PARAMETERS; i++)
res->parameters[i] = lists[2 + i];
res->languages_client_to_server = lists[8];
res->languages_server_to_client = lists[9];
return res;
}
static int do_handle_kexinit(struct abstract_write **w,
struct lsh_string *packet)
{
struct handle_kexinit_packet *closure = (struct handle_kexinit_packet *) *w;
struct kexinit *msg = parse_kexinit(packet);
if (!msg)
return 0;
lsh_free(packet);
return HANDLE_KEXINIT(closure->handler, msg);
}
#if 0
struct abstract_write *make_packet_kexinit(struct handle_kexinit *handler)
{
struct handle_kexinit_packet *closure
......@@ -95,6 +101,7 @@ struct abstract_write *make_packet_kexinit(struct handle_kexinit *handler)
return &closure->super;
}
#endif
struct lsh_string *format_kex(struct kexinit *kex)
{
......@@ -103,12 +110,12 @@ struct lsh_string *format_kex(struct kexinit *kex)
16, kex->cookie,
kex->kex_algorithms,
kex->server_host_key_algorithms,
kex->encryption_algorithms_client_to_server,
kex->encryption_algorithms_server_to_client,
kex->mac_algorithms_client_to_server,
kex->mac_algorithms_server_to_client,
kex->compression_algorithms_client_to_server,
kex->compression_algorithms_server_to_client,
kex->parameters[KEX_ENCRYPTION_CLIENT_TO_SERVER],
kex->parameters[KEX_ENCRYPTION_SERVER_TO_CLIENT],
kex->parameters[KEX_MAC_CLIENT_TO_SERVER],
kex->parameters[KEX_MAC_SERVER_TO_CLIENT],
kex->parameters[KEX_COMPRESSION_CLIENT_TO_SERVER],
kex->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT],
kex->languages_client_to_server,
kex->languages_server_to_client,
kex->first_kex_packet_follows, 0);
......@@ -132,4 +139,126 @@ int initiate_keyexchange(struct ssh_connection *connection,
return res;
}
int select_algorithm(int *server_list, int *client_list)
{
/* FIXME: This quadratic complexity algorithm should do as long as
* the lists are short. */
int i, j;
for(i = 0; client_list[i] >= 0; i++)
{
if (!client_list[i])
/* Unknown algorithm */
continue;
for(j = 0; server_list[j] > 0; j++)
if (client_list[i] = server_list[j])
return client_list[i];
}
return 0;
}
int send_disconnect(struct ssh_conection, char *msg)
{
return A_WRITE(connection->write,
ssh_format("%c%i%z%z",
SSH_MSG_DISCONNECT,
SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
msg, ""));
}
static int do_handle_kexinit(struct packet_hander *c,
struct ssh_connection *connection,
struct lsh_string *packet)
{
struct handle_kexinit *closure = (struct handle_kexinit_packet *) c;
struct kexinit *msg = parse_kexinit(packet);
int kex_algorithm;
int hostkey_algorithm;
int parameters[KEX_PARAMETERS];
void **algorithms;
struct packet_handler newkeys;
int i;
if (!msg)
return 0;
lsh_free(packet);
connection->kexinits[!connection->type] = msg;
/* Have we sent a kexinit message? */
if (!connection->kexinits[connection->type])
{
int res;
struct kexinit *sent = GENERATE_KEXINIT(closure->init);
connection->kexinits[connection->type] = sent;
res = A_WRITE(connection->write, format_kex(sent));
if (res != WRITE_OK)
return res;
}
/* Select key exchange algorithms */
if (connection->kexinits[0]->kex_algorithms[0]
== connection->kexinits[1]->kex_algorithms[1])
{
/* Use this algorithm */
kex_algorithm = connection->sent_kexinit->kex_algorithms[0];
}
else
{
if (msg->first_kex_packet_follows)
{
/* Wrong guess */
connection->ignore_one_packet = 1;
}
/* FIXME: Ignores that some keyechange algorithms require
* certain features of the host key algorithms. */
kex_algorithm = select_algorithm(connection->kexinits[0]->kex_algorithm,
connection->kexinits[1]->kex_algorithm);
if (!kex_algorithm)
{
send_disconnect(connection, "No common key exchange method.\r\n");
/* FIXME: We want the disconnect message to be sent
* before the socket is closed. How? */
return WRITE_CLOSED;
}
hostkey_algorithm
= select_algorithm(connection->kexinits[0]->server_hostkey_algorithms,
connection->kexinits[1]->server_hostkey_algorithms);
for(i = 0; i<KEX_PARAMETERS; i++)
{
parameters[i]
= select_algorithm(connection->kexinits[0]->parameters[i],
connection->kexinits[1]->parameters[i]);
if (!parameters[i])
{
send_disconnect(connection, "");
return wRITE_CLOSED;
}
}
algorithms = xalloc(KEX_PARAMETERS*sizeof(void *));
for (i = 0; i<KEX_PARAMETERS; i++)
algorithms[i] = ALIST_GET(closure->algorithms, parameters[i]);
newkeys = make_newkeys_handler(ALIST_GET(closure->alist, hostkey_algorithm),
algorithms);
return KEYEXCHANGE_INIT(ALIST_GET(algorithms, kex_algorithm), connection);
}
}
/* keyexchange.h
*
*
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LSH_KEYEXCHANGE_H_INCLUDED
......@@ -7,42 +28,81 @@
#include "lsh_types.h"
#include "abstract_io.h"
#include "alist.h"
#define KEX_ENCRYPTION_CLIENT_TO_SERVER 0
#define KEX_ENCRYPTION_SERVER_TO_CLIENT 1
#define KEX_MAC_CLIENT_TO_SERVER 2
#define KEX_MAC_SERVER_TO_CLIENT 3
#define KEX_COMPRESSION_CLIENT_TO_SERVER 4
#define KEX_COMPRESSION_SERVER_TO_CLIENT 5
#define KEX_PARAMETERS 6
struct keyexchange_algorithm
{
int (*init)(struct keyexchange_algorithm *closure,
struct ssh_connection *connection);
};
#define KEYEXCHANGE_INIT(kex, connection) \
((kex)->init((kex), (connection)))
struct kexinit
{
UINT8 cookie[16];
/* Zero terminated list of atoms */
int *kex_algorithms;
int *server_host_key_algorithms;
int *encryption_algorithms_client_to_server;
int *encryption_algorithms_server_to_client;
int *mac_algorithms_client_to_server;
int *mac_algorithms_server_to_client;
int *compression_algorithms_client_to_server;
int *compression_algorithms_server_to_client;
int *parameters[KEX_PARAMETERS];
int *languages_client_to_server;
int *languages_server_to_client;
int first_kex_packet_follows;
};
struct handle_kexinit
/* This function generates a new kexinit message.
*
* FIXME: It could be replaced with a function that does more: Send
* the message, record it in the connection structure, and possibly
* send a first guessed message. */
struct generate_kexinit
{
int (*f)(struct handle_kexinit *closure,
struct kexinit *msg);
struct kexinit * (*generate)(struct generate_kexinit *closure);
};
#define HANDLE_KEXINIT(handler, msg) ((handler)->f((handler), (msg)))
#define GENERATE_KEXINIT(g) ((g)->generate((g)))
struct handle_kexinit_packet
struct handle_keyexinit
{
struct abstract_write super;
struct handle_kexinit *handler;
};
struct packet_handler super;
struct choose_kexinit *init;
/* Maps names to algorithms. It's dangerous to lookup random atoms
* in this table, as not all objects have the same type. This
* mapping is used only on atoms that have appeared in *both* the
* client's and the server's list of algorithms (of a certain type),
* and therefore the remote side can't screw things up. */
struct abstract_write *make_packet_kexinit(struct handle_kexinit *handler);
struct alist *algorithms;
};
struct handle_newkeys
{
struct packet_handler super;
struct crypto_algorithm *encryption_client_to_server;
struct crypto_algorithm *encryption_server_to_client;
struct mac_algorithm *mac_client_to_server;
struct mac_algorithm *mac_server_to_client;
#if 0
struct lsh_string *make_keyexinit_packet(struct keyexinit *msg);
struct compression_algorithm *compression_client_to_server;
struct compression_algorithm *compression_server_to_client;
#endif
};
struct packet_handler *make_kexinit_handler();
struct packet_handler *make_newkeys_handler();
struct lsh_string *format_kex(struct kexinit *kex);
#endif /* LSH_KEYEXCHANGE_H_INCLUDED */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment