Here is a quick patch against openssh-2.5.1p1 to add a new config option (pkalg) for the ssh client allowing the selection of which public keys are obtained/verified. --cut-here- diff -c3 -r orig/openssh-2.5.1p1/key.c openssh-2.5.1p1/key.c *** orig/openssh-2.5.1p1/key.c Mon Feb 5 18:16:28 2001 --- openssh-2.5.1p1/key.c Sun Mar 11 23:10:10 2001 *************** *** 534,539 **** --- 534,567 ---- return KEY_UNSPEC; } + #define PKALG_SEP "," + int + pkalg_valid(const char *names) + { + int k; + char *keys, *kp; + char *p; + + if (names == NULL || strcmp(names, "") == 0) + return 0; + keys = kp = xstrdup(names); + for ((p = strsep(&kp, PKALG_SEP)); p && *p != '\0'; + (p = strsep(&kp, PKALG_SEP))) { + if ((strcmp(p, "ssh-rsa") != 0) && + (strcmp(p, "ssh-dss") != 0)) { + debug("bad pkalg %s [%s]", p, names); + xfree(keys); + return 0; + } else { + debug3("pkalg ok: %s [%s]", p, names); + } + } + debug3("pkalgs ok: [%s]", names); + xfree(keys); + return 1; + } + + Key * key_from_blob(char *blob, int blen) { diff -c3 -r orig/openssh-2.5.1p1/key.h openssh-2.5.1p1/key.h *** orig/openssh-2.5.1p1/key.h Mon Jan 29 07:39:26 2001 --- openssh-2.5.1p1/key.h Sun Mar 11 22:50:23 2001 *************** *** 55,60 **** --- 55,61 ---- Key *key_generate(int type, u_int bits); Key *key_from_private(Key *k); int key_type_from_name(char *name); + int pkalg_valid(const char *name); Key *key_from_blob(char *blob, int blen); int key_to_blob(Key *key, u_char **blobp, u_int *lenp); Only in orig/openssh-2.5.1p1/: mkstring diff -c3 -r orig/openssh-2.5.1p1/readconf.c openssh-2.5.1p1/readconf.c *** orig/openssh-2.5.1p1/readconf.c Thu Feb 15 03:02:00 2001 --- openssh-2.5.1p1/readconf.c Sun Mar 11 23:12:34 2001 *************** *** 25,30 **** --- 25,31 ---- #include "misc.h" #include "kex.h" #include "mac.h" + #include "key.h" /* Format of the configuration file: *************** *** 107,113 **** oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, ! oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias } OpCodes; --- 108,114 ---- oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, ! oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, oPkalg, oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias } OpCodes; *************** *** 151,156 **** --- 152,158 ---- { "cipher", oCipher }, { "ciphers", oCiphers }, { "macs", oMacs }, + { "pkalg", oPkalg }, { "protocol", oProtocol }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, *************** *** 516,521 **** --- 518,534 ---- options->macs = xstrdup(arg); break; + case oPkalg: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + if (!pkalg_valid(arg)) + fatal("%.200s line %d: Bad SSH2 PKalg spec '%s'.", + filename, linenum, arg ? arg : "<NONE>"); + if (*activep && options->pkalg == NULL) + options->pkalg = xstrdup(arg); + break; + case oProtocol: intptr = &options->protocol; arg = strdelim(&s); *************** *** 708,713 **** --- 721,727 ---- options->cipher = -1; options->ciphers = NULL; options->macs = NULL; + options->pkalg = NULL; options->protocol = SSH_PROTO_UNKNOWN; options->num_identity_files = 0; options->hostname = NULL; diff -c3 -r orig/openssh-2.5.1p1/readconf.h openssh-2.5.1p1/readconf.h *** orig/openssh-2.5.1p1/readconf.h Thu Feb 15 03:02:00 2001 --- openssh-2.5.1p1/readconf.h Sun Mar 11 22:50:23 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 *pkalg; /* SSH2 PK_ALG list to use */ int protocol; /* Protocol in order of preference. */ char *hostname; /* Real host to connect. */ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ diff -c3 -r orig/openssh-2.5.1p1/sshconnect2.c openssh-2.5.1p1/sshconnect2.c *** orig/openssh-2.5.1p1/sshconnect2.c Fri Feb 16 01:34:57 2001 --- openssh-2.5.1p1/sshconnect2.c Sun Mar 11 23:15:37 2001 *************** *** 94,99 **** --- 94,104 ---- myproposal[PROPOSAL_MAC_ALGS_CTOS] myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; } + if (options.pkalg != NULL) { + debug("Copying pkalg=%.100s to mypromposal", options.pkalg); + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.pkalg; + } + /* buffers with raw kexinit messages */ server_kexinit = xmalloc(sizeof(*server_kexinit)); --cut-here- Most of the patch is based on the handling of 'macs', and 'ciphers', it is quite possible that there is a cleaner way to achieve the same effect. I wasn't sure that key.c was the right place to put pkalg_valid(), but it seems to do the right thing for me: $ ./ssh -o 'pkalg ssh-rsa' -2 testhost uptime The authenticity of host 'testhost (10.16.18.11)' can't be established. RSA key fingerprint is e9:20:0b:9a:22:e9:69:b3:52:76:27:ff:41:50:cb:81. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'testhost,10.16.18.11' (RSA) to the list of known hosts. <snip> $ ./ssh -o 'pkalg ssh-dss' -2 testhost uptime The authenticity of host 'testhost (10.16.18.11)' can't be established. DSA key fingerprint is 95:df:c5:cc:d9:3b:53:7a:a3:de:42:9c:93:bd:93:2e. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'testhost,10.16.18.11' (DSA) to the list of known hosts. Of course I may have missed somthing important, and I've currently only tested it on one implementation (Linux). Any improvements or suggestions welcome. -- Jon Peatfield, DAMTP, Computer Officer, University of Cambridge Telephone: +44 1223 3 37852 Mail: J.S.Peatfield at damtp.cam.ac.uk