X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/3aa0b69123fa8df44b74572aaf279dff9ae3e5d6..ec68f1043faae93f56c036077fb320db72914b47:/sshdss.c diff --git a/sshdss.c b/sshdss.c index 2a5e2689..01c452b9 100644 --- a/sshdss.c +++ b/sshdss.c @@ -161,11 +161,24 @@ static int dss_verifysig(char *sig, int siglen, char *data, int datalen) { if (!dss_p) return 0; - getstring(&sig, &siglen, &p, &slen); - if (!p || memcmp(p, "ssh-dss", 7)) { - return 0; + /* + * Commercial SSH (2.0.13) and OpenSSH disagree over the format + * of a DSA signature. OpenSSH is in line with the IETF drafts: + * it uses a string "ssh-dss", followed by a 40-byte string + * containing two 160-bit integers end-to-end. Commercial SSH + * can't be bothered with the header bit, and considers a DSA + * signature blob to be _just_ the 40-byte string containing + * the two 160-bit integers. We tell them apart by measuring + * the length: length 40 means the commercial-SSH bug, anything + * else is assumed to be IETF-compliant. + */ + if (siglen != 40) { /* bug not present; read admin fields */ + getstring(&sig, &siglen, &p, &slen); + if (!p || memcmp(p, "ssh-dss", 7)) { + return 0; + } + sig += 4, siglen -= 4; /* skip yet another length field */ } - sig += 4, siglen -= 4; /* skip yet another length field */ r = get160(&sig, &siglen); s = get160(&sig, &siglen); if (!r || !s)