Suppose an SSH server has both RSA and DSA host keys for protocol 2, but I
only have the DSA key, and I want to use that. I'm stuck; the OpenSSH
client
is hard-wired to offer both algorithms in the key exchange, and will select
ssh-rsa if it's available (see myproposal.h, KEX_DEFAULT_PK_ALG).
Below is a patch adding the client configuration option "PKAlgorithms"
for
this purpose. It doesn't validate the supplied list; I'm not sure if
that's
really necessary or desirable.
This situation raises a couple of questions. The first is about the protocol,
which forces the client to commit to a choice of host key algorithm before it
sees the keys, and hence before it can determine whether that choice has any
chance of succeeding -- and if it fails, the whole connection fails. I wonder
if there's a better way of doing this?
The second is about implementation -- given the protocol as it is now, would
it be a good idea to automatically retry connections that fail because of an
unverifiable host key, using the next available host key algorithm?
--
Richard Silverman
slade at shore.net
===============================================================================
*** ../../openssh-2.5.1p2/readconf.c Wed Feb 14 22:02:00 2001
--- readconf.c Wed Mar 7 00:59:44 2001
***************
*** 109,115 ****
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
! oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias
} OpCodes;
/* Textual representations of the tokens. */
--- 109,116 ----
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
! oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
! oPKAlgorithms
} OpCodes;
/* Textual representations of the tokens. */
***************
*** 171,176 ****
--- 172,178 ----
{ "keepalive", oKeepAlives },
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "loglevel", oLogLevel },
+ { "pkalgorithms", oPKAlgorithms },
{ NULL, 0 }
};
***************
*** 516,521 ****
--- 518,532 ----
options->macs = xstrdup(arg);
break;
+ case oPKAlgorithms:
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ /* XXX validate pkalg list? */
+ if (*activep && options->pkalgorithms == NULL)
+ options->pkalgorithms = xstrdup(arg);
+ break;
+
case oProtocol:
intptr = &options->protocol;
arg = strdelim(&s);
***************
*** 708,713 ****
--- 719,725 ----
options->cipher = -1;
options->ciphers = NULL;
options->macs = NULL;
+ options->pkalgorithms = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->num_identity_files = 0;
options->hostname = NULL;
***************
*** 797,802 ****
--- 809,815 ----
options->cipher = SSH_CIPHER_NOT_SET;
/* options->ciphers, default set in myproposals.h */
/* options->macs, default set in myproposals.h */
+ /* options->pkalgorithms, default set in myproposals.h */
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
if (options->num_identity_files == 0) {
*** ../../openssh-2.5.1p2/readconf.h Wed Feb 14 22:02:00 2001
--- readconf.h Tue Mar 6 23:58:08 2001
***************
*** 69,74 ****
--- 69,75 ----
int cipher; /* Cipher to use. */
char *ciphers; /* SSH2 ciphers in order of preference. */
char *macs; /* SSH2 macs in order of preference. */
+ char *pkalgorithms; /* SSH2 server key types in order of preference. */
int protocol; /* Protocol in order of preference. */
char *hostname; /* Real host to connect. */
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
*** ../../openssh-2.5.1p2/sshconnect2.c Thu Feb 15 20:34:57 2001
--- sshconnect2.c Wed Mar 7 00:06:05 2001
***************
*** 94,99 ****
--- 94,102 ----
myproposal[PROPOSAL_MAC_ALGS_CTOS] myproposal[PROPOSAL_MAC_ALGS_STOC] =
options.macs;
}
+ if (options.pkalgorithms != NULL) {
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.pkalgorithms;
+ }
/* buffers with raw kexinit messages */
server_kexinit = xmalloc(sizeof(*server_kexinit));
================================================================================