Uppity: option to use a pregenerated key for RSA kex.

As and when I make this SSH server into a test suite, I'm not going to
want to wait for a gratuitous RSA key generation in every test run. So
now you can provide one in advance.

It has to be in SSH-1 format, because that's the format for which I
happen to already have internal API routines that return an RSAKey
instead of an opaque ssh_key. But since you also have to store it
without a passphrase, that doesn't really matter anyway.
This commit is contained in:
Simon Tatham 2019-03-31 21:08:55 +01:00
Родитель 7a49ff9ac1
Коммит 6d7a6d47e6
6 изменённых файлов: 60 добавлений и 5 удалений

Просмотреть файл

@ -552,6 +552,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
*aborted = true; *aborted = true;
return; return;
} }
s->rsa_kex_key_needs_freeing = true;
put_stringpl(s->exhash, rsakeydata); put_stringpl(s->exhash, rsakeydata);
@ -611,6 +612,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
ssh_rsakex_freekey(s->rsa_kex_key); ssh_rsakex_freekey(s->rsa_kex_key);
s->rsa_kex_key = NULL; s->rsa_kex_key = NULL;
s->rsa_kex_key_needs_freeing = false;
crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL); crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
if (pktin->type != SSH2_MSG_KEXRSA_DONE) { if (pktin->type != SSH2_MSG_KEXRSA_DONE) {

Просмотреть файл

@ -9,6 +9,7 @@
#include "sshbpp.h" #include "sshbpp.h"
#include "sshppl.h" #include "sshppl.h"
#include "sshcr.h" #include "sshcr.h"
#include "sshserver.h"
#include "storage.h" #include "storage.h"
#include "ssh2transport.h" #include "ssh2transport.h"
#include "mpint.h" #include "mpint.h"
@ -243,13 +244,27 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
ssh_hash_alg(s->exhash)->text_name); ssh_hash_alg(s->exhash)->text_name);
s->ppl.bpp->pls->kctx = SSH2_PKTCTX_RSAKEX; s->ppl.bpp->pls->kctx = SSH2_PKTCTX_RSAKEX;
{ const struct ssh_rsa_kex_extra *extra =
const struct ssh_rsa_kex_extra *extra = (const struct ssh_rsa_kex_extra *)s->kex_alg->extra;
(const struct ssh_rsa_kex_extra *)s->kex_alg->extra;
if (s->ssc && s->ssc->rsa_kex_key) {
int klen = ssh_rsakex_klen(s->ssc->rsa_kex_key);
if (klen >= extra->minklen) {
ppl_logevent("Using configured %d-bit RSA key", klen);
s->rsa_kex_key = s->ssc->rsa_kex_key;
} else {
ppl_logevent("Configured %d-bit RSA key is too short (min %d)",
klen, extra->minklen);
}
}
if (!s->rsa_kex_key) {
ppl_logevent("Generating a %d-bit RSA key", extra->minklen);
s->rsa_kex_key = snew(RSAKey); s->rsa_kex_key = snew(RSAKey);
rsa_generate(s->rsa_kex_key, extra->minklen, no_progress, NULL); rsa_generate(s->rsa_kex_key, extra->minklen, no_progress, NULL);
s->rsa_kex_key->comment = NULL; s->rsa_kex_key->comment = NULL;
s->rsa_kex_key_needs_freeing = true;
} }
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXRSA_PUBKEY); pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXRSA_PUBKEY);
@ -288,8 +303,12 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
return; return;
} }
ssh_rsakex_freekey(s->rsa_kex_key); if (s->rsa_kex_key_needs_freeing) {
ssh_rsakex_freekey(s->rsa_kex_key);
sfree(s->rsa_kex_key);
}
s->rsa_kex_key = NULL; s->rsa_kex_key = NULL;
s->rsa_kex_key_needs_freeing = false;
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXRSA_DONE); pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXRSA_DONE);
put_stringsb(pktout, finalise_and_sign_exhash(s)); put_stringsb(pktout, finalise_and_sign_exhash(s));

Просмотреть файл

@ -220,8 +220,10 @@ static void ssh2_transport_free(PacketProtocolLayer *ppl)
if (s->K) mp_free(s->K); if (s->K) mp_free(s->K);
if (s->dh_ctx) if (s->dh_ctx)
dh_cleanup(s->dh_ctx); dh_cleanup(s->dh_ctx);
if (s->rsa_kex_key) if (s->rsa_kex_key_needs_freeing) {
ssh_rsakex_freekey(s->rsa_kex_key); ssh_rsakex_freekey(s->rsa_kex_key);
sfree(s->rsa_kex_key);
}
if (s->ecdh_key) if (s->ecdh_key)
ssh_ecdhkex_freekey(s->ecdh_key); ssh_ecdhkex_freekey(s->ecdh_key);
if (s->exhash) if (s->exhash)

Просмотреть файл

@ -173,6 +173,7 @@ struct ssh2_transport_state {
char *keystr, *fingerprint; char *keystr, *fingerprint;
ssh_key *hkey; /* actual host key */ ssh_key *hkey; /* actual host key */
RSAKey *rsa_kex_key; /* for RSA kex */ RSAKey *rsa_kex_key; /* for RSA kex */
bool rsa_kex_key_needs_freeing;
ecdh_key *ecdh_key; /* for ECDH kex */ ecdh_key *ecdh_key; /* for ECDH kex */
unsigned char exchange_hash[MAX_HASH_LEN]; unsigned char exchange_hash[MAX_HASH_LEN];
bool can_gssapi_keyex; bool can_gssapi_keyex;

Просмотреть файл

@ -1,6 +1,8 @@
typedef struct AuthPolicy AuthPolicy; typedef struct AuthPolicy AuthPolicy;
struct SshServerConfig { struct SshServerConfig {
RSAKey *rsa_kex_key;
/* /*
* In all of these ptrlens, setting the 'ptr' member to NULL means * In all of these ptrlens, setting the 'ptr' member to NULL means
* that we're not overriding the default configuration. * that we're not overriding the default configuration.

Просмотреть файл

@ -579,6 +579,35 @@ int main(int argc, char **argv)
key_type_to_str(keytype)); key_type_to_str(keytype));
exit(1); exit(1);
} }
} else if (longoptarg(arg, "--rsakexkey", &val, &argc, &argv)) {
Filename *keyfile;
int keytype;
const char *error;
keyfile = filename_from_str(val);
keytype = key_type(keyfile);
if (keytype != SSH_KEYTYPE_SSH1) {
fprintf(stderr, "%s: '%s' is not loadable as an SSH-1 format "
"private key (%s)", appname, val,
key_type_to_str(keytype));
exit(1);
}
if (ssc.rsa_kex_key) {
freersakey(ssc.rsa_kex_key);
} else {
ssc.rsa_kex_key = snew(RSAKey);
}
if (!rsa_ssh1_loadkey(keyfile, ssc.rsa_kex_key,
NULL, &error)) {
fprintf(stderr, "%s: unable to load RSA kex key '%s': "
"%s\n", appname, val, error);
exit(1);
}
ssc.rsa_kex_key->sshk.vt = &ssh_rsa;
} else if (longoptarg(arg, "--userkey", &val, &argc, &argv)) { } else if (longoptarg(arg, "--userkey", &val, &argc, &argv)) {
Filename *keyfile; Filename *keyfile;
int keytype; int keytype;