Aaron Jones
2021-Mar-18 22:12 UTC
Feature Request: Allow certificate types in ssh-keyscan -t
Hello. I would like for the ssh-keyscan(1) -t argument (key type) to support the certificate types too (such as ssh-ed25519-cert-v01 at openssh.com), as from `ssh -Q key`. This would allow to dump remote host certificates, useful for various situations like certificate expiration monitoring. Regards, Aaron Jones -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20210318/175d3cb3/attachment.asc>
Darren Tucker
2021-Mar-19 07:17 UTC
Feature Request: Allow certificate types in ssh-keyscan -t
On Thu, Mar 18, 2021 at 10:12:30PM +0000, Aaron Jones wrote:> Hello. > > I would like for the ssh-keyscan(1) -t argument (key type) to support > the certificate types too (such as ssh-ed25519-cert-v01 at openssh.com), as > from `ssh -Q key`.Please try this patch. It is slightly complicated by the existing behaviour where adding "-c" will get cert type corresponding to the specified plain types and I have attempted to maintain the existing behaviour. Index: ssh-keyscan.c ==================================================================RCS file: /export/cvs/src/usr.bin/ssh/ssh-keyscan.c,v retrieving revision 1.139 diff -u -p -r1.139 ssh-keyscan.c --- ssh-keyscan.c 27 Jan 2021 09:26:54 -0000 1.139 +++ ssh-keyscan.c 19 Mar 2021 07:14:47 -0000 @@ -50,6 +50,10 @@ int IPv4or6 = AF_UNSPEC; int ssh_port = SSH_DEFAULT_PORT; +/* + * Key types. Note that the certificate types must appear after the non-cert + * types and in the same order so that -c "promotion" still works. + */ #define KT_DSA (1) #define KT_RSA (1<<1) #define KT_ECDSA (1<<2) @@ -57,9 +61,18 @@ int ssh_port = SSH_DEFAULT_PORT; #define KT_XMSS (1<<4) #define KT_ECDSA_SK (1<<5) #define KT_ED25519_SK (1<<6) +#define KT_DSA_CERT (1<<7) +#define KT_RSA_CERT (1<<8) +#define KT_ECDSA_CERT (1<<9) +#define KT_ED25519_CERT (1<<10) +#define KT_XMSS_CERT (1<<11) +#define KT_ECDSA_SK_CERT (1<<12) +#define KT_ED25519_SK_CERT (1<<13) +#define KT_NUM_KEYTYPES 14 #define KT_MIN KT_DSA -#define KT_MAX KT_ED25519_SK +#define KT_MIN_CERT KT_DSA_CERT +#define KT_MAX KT_ED25519_SK_CERT int get_cert = 0; int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; @@ -211,54 +224,66 @@ ssh2_capable(int remote_major, int remot static void keygrab_ssh2(con *c) { - char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *algs = NULL, *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; int r; switch (c->c_keytype) { case KT_DSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-dss-cert-v01 at openssh.com" : "ssh-dss"; + algs = "ssh-dss"; + break; + case KT_DSA_CERT: + algs = "ssh-dss-cert-v01 at openssh.com"; break; case KT_RSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "rsa-sha2-512-cert-v01 at openssh.com," - "rsa-sha2-256-cert-v01 at openssh.com," - "ssh-rsa-cert-v01 at openssh.com" : - "rsa-sha2-512," + algs = "rsa-sha2-512," "rsa-sha2-256," "ssh-rsa"; break; + case KT_RSA_CERT: + algs = "rsa-sha2-512-cert-v01 at openssh.com," + "rsa-sha2-256-cert-v01 at openssh.com," + "ssh-rsa-cert-v01 at openssh.com"; + break; case KT_ED25519: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-ed25519-cert-v01 at openssh.com" : "ssh-ed25519"; + algs = "ssh-ed25519"; + break; + case KT_ED25519_CERT: + algs = "ssh-ed25519-cert-v01 at openssh.com"; break; case KT_XMSS: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-xmss-cert-v01 at openssh.com" : "ssh-xmss at openssh.com"; + algs = "ssh-xmss at openssh.com"; + break; + case KT_XMSS_CERT: + algs = "ssh-xmss-cert-v01 at openssh.com"; break; case KT_ECDSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ecdsa-sha2-nistp256-cert-v01 at openssh.com," - "ecdsa-sha2-nistp384-cert-v01 at openssh.com," - "ecdsa-sha2-nistp521-cert-v01 at openssh.com" : - "ecdsa-sha2-nistp256," + algs = "ecdsa-sha2-nistp256," "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521"; break; + case KT_ECDSA_CERT: + algs = "ecdsa-sha2-nistp256-cert-v01 at openssh.com," + "ecdsa-sha2-nistp384-cert-v01 at openssh.com," + "ecdsa-sha2-nistp521-cert-v01 at openssh.com"; + break; case KT_ECDSA_SK: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com" : - "sk-ecdsa-sha2-nistp256 at openssh.com"; + algs = "sk-ecdsa-sha2-nistp256 at openssh.com"; + break; + case KT_ECDSA_SK_CERT: + algs = "sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com"; break; case KT_ED25519_SK: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "sk-ssh-ed25519-cert-v01 at openssh.com" : - "sk-ssh-ed25519 at openssh.com"; + algs = "sk-ssh-ed25519 at openssh.com"; + break; + case KT_ED25519_SK_CERT: + algs = "sk-ssh-ed25519-cert-v01 at openssh.com"; break; default: fatal("unknown key type %d", c->c_keytype); break; } + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = algs; + if ((r = kex_setup(c->c_ssh, myproposal)) != 0) { free(c->c_ssh); fprintf(stderr, "kex_setup: %s\n", ssh_err(r)); @@ -707,24 +732,45 @@ main(int argc, char **argv) case KEY_DSA: get_keytypes |= KT_DSA; break; + case KEY_DSA_CERT: + get_keytypes |= KT_DSA_CERT; + break; case KEY_ECDSA: get_keytypes |= KT_ECDSA; break; + case KEY_ECDSA_CERT: + get_keytypes |= KT_ECDSA_CERT; + break; case KEY_RSA: get_keytypes |= KT_RSA; break; + case KEY_RSA_CERT: + get_keytypes |= KT_RSA_CERT; + break; case KEY_ED25519: get_keytypes |= KT_ED25519; break; + case KEY_ED25519_CERT: + get_keytypes |= KT_ED25519_CERT; + break; case KEY_XMSS: get_keytypes |= KT_XMSS; break; + case KEY_XMSS_CERT: + get_keytypes |= KT_XMSS_CERT; + break; case KEY_ED25519_SK: get_keytypes |= KT_ED25519_SK; break; + case KEY_ED25519_SK_CERT: + get_keytypes |= KT_ED25519_SK_CERT; + break; case KEY_ECDSA_SK: get_keytypes |= KT_ECDSA_SK; break; + case KEY_ECDSA_SK_CERT: + get_keytypes |= KT_ECDSA_SK_CERT; + break; case KEY_UNSPEC: default: fatal("Unknown key type \"%s\"", tname); @@ -747,6 +793,22 @@ main(int argc, char **argv) usage(); log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); + + /* + * If -c is specified, promote non-cert to corresponding cert types + * to maintain previous behaviour. This relies on the cert key types + * being in the second half of the bit vector and being in the same + * order as the corresponding plain key types. + */ + if (get_cert) { + if (get_keytypes >= KT_MIN_CERT) + fatal("Both explicit certificate types and -c " + "specified"); + opt = get_keytypes << (KT_NUM_KEYTYPES / 2); + debug3_f("-c specified, promoted keytypes 0x%x -> 0x%x", + get_keytypes, opt); + get_keytypes = opt; + } maxfd = fdlim_get(1); if (maxfd < 0) -- Darren Tucker (dtucker at dtucker.net) GPG key 11EAA6FA / A86E 3E07 5B19 5880 E860 37F4 9357 ECEF 11EA A6FA (new) Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.