mirror of
https://github.com/openssh/libopenssh
synced 2026-04-23 13:16:51 +00:00
ssh_api.c: offer hostkey algorithms depending on registered keys
For now, the 'serialized' proposal is de-serialized, modified, and serialized again in order to change the hostkey algorithm.
This commit is contained in:
14
ssh/kex.c
14
ssh/kex.c
@@ -82,7 +82,7 @@ kex_names_valid(const char *names)
|
||||
}
|
||||
|
||||
/* put algorithm proposal into buffer */
|
||||
static void
|
||||
void
|
||||
kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
|
||||
{
|
||||
u_int i;
|
||||
@@ -101,7 +101,7 @@ kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
|
||||
}
|
||||
|
||||
/* parse buffer and return algorithm proposal */
|
||||
static char **
|
||||
char **
|
||||
kex_buf2prop(Buffer *raw, int *first_kex_follows)
|
||||
{
|
||||
Buffer b;
|
||||
@@ -131,7 +131,7 @@ kex_buf2prop(Buffer *raw, int *first_kex_follows)
|
||||
return proposal;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
kex_prop_free(char **proposal)
|
||||
{
|
||||
u_int i;
|
||||
@@ -262,6 +262,14 @@ kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
|
||||
return kex;
|
||||
}
|
||||
|
||||
void
|
||||
kex_free(Kex *kex)
|
||||
{
|
||||
buffer_free(&kex->peer);
|
||||
buffer_free(&kex->my);
|
||||
xfree(kex);
|
||||
}
|
||||
|
||||
Kex *
|
||||
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
|
||||
{
|
||||
|
||||
@@ -144,6 +144,11 @@ int kex_names_valid(const char *);
|
||||
Kex *kex_new(struct ssh *, char *[PROPOSAL_MAX]);
|
||||
Kex *kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
|
||||
void kex_finish(struct ssh *);
|
||||
void kex_free(Kex *);
|
||||
|
||||
char **kex_buf2prop(Buffer *, int *);
|
||||
void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]);
|
||||
void kex_prop_free(char **);
|
||||
|
||||
void kex_send_kexinit(struct ssh *);
|
||||
void kex_input_kexinit(int, u_int32_t, struct ssh *);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
% test -f /tmp/hk2 || ssh-keygen -N '' -t ecdsa -f /tmp/hk2
|
||||
% ssh-keyscan -t ecdsa 127.0.0.1 | sed 's/^[^ ]* //' > /tmp/hk.pub
|
||||
% ./ssh-proxy/obj/ssh-proxy -f -S /tmp/hk2 -C /tmp/hk.pub -L 127.0.0.1:12345:127.0.0.1:22 -d
|
||||
% ssh -o hostkeyalgorithms'='ecdsa-sha2-nistp256 -o hostkeyalias'='egal2 -v 127.0.0.1 -p 12345
|
||||
# example usage of proxy:
|
||||
# generate hostkey
|
||||
test -f /tmp/hk2 || ssh-keygen -N '' -t ecdsa -f /tmp/hk2
|
||||
# get known hostkey for target (127.0.0.1:22)
|
||||
ssh-keyscan -t ecdsa 127.0.0.1 | sed 's/^[^ ]* //' > /tmp/hk.pub
|
||||
# start proxy in foreground, enable packet dumping (except auth-requests)
|
||||
./ssh-proxy/obj/ssh-proxy -S /tmp/hk2 -C /tmp/hk.pub -L 127.0.0.1:12345:127.0.0.1:22 -dDf
|
||||
# connect
|
||||
ssh -o hostkeyalias'='egal2 -v 127.0.0.1 -p 12345
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
#include "ssh2.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
#include "myproposal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void _ssh_exchange_banner(struct ssh *);
|
||||
char *_ssh_send_banner(struct ssh *);
|
||||
char *_ssh_read_banner(struct ssh *);
|
||||
void _ssh_order_hostkeyalgs(struct ssh *);
|
||||
int _ssh_verify_host_key(struct sshkey *, struct ssh *);
|
||||
struct sshkey *_ssh_host_public_key(int, struct ssh *);
|
||||
struct sshkey *_ssh_host_private_key(int, struct ssh *);
|
||||
@@ -47,6 +49,7 @@ struct ssh *
|
||||
ssh_init(int is_server, struct kex_params *kex_params)
|
||||
{
|
||||
struct ssh *ssh;
|
||||
char **proposal;
|
||||
static int called;
|
||||
|
||||
if (!called) {
|
||||
@@ -59,7 +62,8 @@ ssh_init(int is_server, struct kex_params *kex_params)
|
||||
ssh_packet_set_server(ssh);
|
||||
|
||||
/* Initialize key exchange */
|
||||
ssh->kex = kex_new(ssh, kex_params->proposal);
|
||||
proposal = kex_params ? kex_params->proposal : myproposal;
|
||||
ssh->kex = kex_new(ssh, proposal);
|
||||
ssh->kex->server = is_server;
|
||||
if (is_server) {
|
||||
ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
|
||||
@@ -84,8 +88,8 @@ void
|
||||
ssh_free(struct ssh *ssh)
|
||||
{
|
||||
ssh_packet_close(ssh);
|
||||
if (ssh->kex)
|
||||
xfree(ssh->kex);
|
||||
if (ssh->kex);
|
||||
kex_free(ssh->kex);
|
||||
xfree(ssh);
|
||||
}
|
||||
|
||||
@@ -316,8 +320,10 @@ _ssh_exchange_banner(struct ssh *ssh)
|
||||
}
|
||||
/* start initial kex as soon as we have exchanged the banners */
|
||||
if (ssh->kex->server_version_string != NULL &&
|
||||
ssh->kex->client_version_string != NULL)
|
||||
ssh->kex->client_version_string != NULL) {
|
||||
_ssh_order_hostkeyalgs(ssh);
|
||||
kex_send_kexinit(ssh);
|
||||
}
|
||||
}
|
||||
|
||||
struct sshkey *
|
||||
@@ -362,3 +368,47 @@ _ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh)
|
||||
}
|
||||
return (-1); /* failed */
|
||||
}
|
||||
|
||||
/* offer hostkey algorithms in kexinit depending on registered keys */
|
||||
void
|
||||
_ssh_order_hostkeyalgs(struct ssh *ssh)
|
||||
{
|
||||
struct key_entry *k;
|
||||
char *orig, *avail, *oavail,*alg, *replace;
|
||||
char **proposal;
|
||||
size_t maxlen;
|
||||
int ktype;
|
||||
|
||||
/* XXX we de-serialize ssh->kex->my, modify it, and change it */
|
||||
proposal = kex_buf2prop(&ssh->kex->my, NULL);
|
||||
orig = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
|
||||
oavail = avail = xstrdup(orig);
|
||||
maxlen = strlen(avail) + 1;
|
||||
replace = xmalloc(maxlen);
|
||||
*replace = '\0';
|
||||
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
|
||||
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
|
||||
fatal("%s: unknown alg %s", __func__, alg);
|
||||
TAILQ_FOREACH(k, &ssh->public_keys, next) {
|
||||
if (k->key->type == ktype ||
|
||||
(sshkey_is_cert(k->key) && k->key->type ==
|
||||
sshkey_type_plain(ktype))) {
|
||||
if (*replace != '\0')
|
||||
strlcat(replace, ",", maxlen);
|
||||
strlcat(replace, alg, maxlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree(oavail);
|
||||
if (*replace != '\0') {
|
||||
debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig);
|
||||
debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace);
|
||||
xfree(orig);
|
||||
proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace;
|
||||
kex_prop2buf(&ssh->kex->my, proposal);
|
||||
} else {
|
||||
xfree(replace);
|
||||
}
|
||||
kex_prop_free(proposal);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user