summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2013-12-30 23:52:29 +0000
committerDamien Miller <djm@cvs.openbsd.org>2013-12-30 23:52:29 +0000
commite514b87438697c32ab3cbb50e5e346fd11d72074 (patch)
treebefed29d63a592d86f8887f456ccf779061610af
parentd09c14e9c51a476c97026881388d6fa14b1148cd (diff)
refuse RSA keys from old proprietary clients/servers that use the
obsolete RSA+MD5 signature scheme. it will still be possible to connect with these clients/servers but only DSA keys will be accepted, and we'll deprecate them entirely in a future release. ok markus@
-rw-r--r--usr.bin/ssh/auth2-hostbased.c8
-rw-r--r--usr.bin/ssh/auth2-pubkey.c8
-rw-r--r--usr.bin/ssh/compat.c61
-rw-r--r--usr.bin/ssh/compat.h3
-rw-r--r--usr.bin/ssh/ssh-rsa.c23
-rw-r--r--usr.bin/ssh/sshconnect.c5
-rw-r--r--usr.bin/ssh/sshconnect2.c33
-rw-r--r--usr.bin/ssh/sshd.c13
8 files changed, 99 insertions, 55 deletions
diff --git a/usr.bin/ssh/auth2-hostbased.c b/usr.bin/ssh/auth2-hostbased.c
index 1714deb1b03..ae776c1ca10 100644
--- a/usr.bin/ssh/auth2-hostbased.c
+++ b/usr.bin/ssh/auth2-hostbased.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.16 2013/06/21 00:34:49 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -99,6 +99,12 @@ userauth_hostbased(Authctxt *authctxt)
"(received %d, expected %d)", key->type, pktype);
goto done;
}
+ if (key_type_plain(key->type) == KEY_RSA &&
+ (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ error("Refusing RSA key because peer uses unsafe "
+ "signature format");
+ goto done;
+ }
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
diff --git a/usr.bin/ssh/auth2-pubkey.c b/usr.bin/ssh/auth2-pubkey.c
index 1cace440cee..5b6a50ee3af 100644
--- a/usr.bin/ssh/auth2-pubkey.c
+++ b/usr.bin/ssh/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.38 2013/06/21 00:34:49 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.39 2013/12/30 23:52:27 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -113,6 +113,12 @@ userauth_pubkey(Authctxt *authctxt)
"(received %d, expected %d)", key->type, pktype);
goto done;
}
+ if (key_type_plain(key->type) == KEY_RSA &&
+ (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ logit("Refusing RSA key because client uses unsafe "
+ "signature scheme");
+ goto done;
+ }
if (have_sig) {
sig = packet_get_string(&slen);
packet_check_eom();
diff --git a/usr.bin/ssh/compat.c b/usr.bin/ssh/compat.c
index 3c4d68edfd8..52ce971e541 100644
--- a/usr.bin/ssh/compat.c
+++ b/usr.bin/ssh/compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.81 2013/05/17 00:13:13 djm Exp $ */
+/* $OpenBSD: compat.c,v 1.82 2013/12/30 23:52:27 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -169,8 +169,9 @@ compat_datafellows(const char *version)
for (i = 0; check[i].pat; i++) {
if (match_pattern_list(version, check[i].pat,
strlen(check[i].pat), 0) == 1) {
- debug("match: %s pat %s", version, check[i].pat);
datafellows = check[i].bugs;
+ debug("match: %s pat %s compat 0x%08x",
+ version, check[i].pat, datafellows);
return;
}
}
@@ -206,33 +207,59 @@ proto_spec(const char *spec)
return ret;
}
-char *
-compat_cipher_proposal(char *cipher_prop)
+/*
+ * Filters a proposal string, excluding any algorithm matching the 'filter'
+ * pattern list.
+ */
+static char *
+filter_proposal(char *proposal, const char *filter)
{
Buffer b;
- char *orig_prop, *fix_ciphers;
+ char *orig_prop, *fix_prop;
char *cp, *tmp;
- if (!(datafellows & SSH_BUG_BIGENDIANAES))
- return(cipher_prop);
-
buffer_init(&b);
- tmp = orig_prop = xstrdup(cipher_prop);
+ tmp = orig_prop = xstrdup(proposal);
while ((cp = strsep(&tmp, ",")) != NULL) {
- if (strncmp(cp, "aes", 3) != 0) {
+ if (match_pattern_list(cp, filter, strlen(cp), 0) != 1) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, cp, strlen(cp));
- }
+ } else
+ debug2("Compat: skipping algorithm \"%s\"", cp);
}
buffer_append(&b, "\0", 1);
- fix_ciphers = xstrdup(buffer_ptr(&b));
+ fix_prop = xstrdup(buffer_ptr(&b));
buffer_free(&b);
free(orig_prop);
- debug2("Original cipher proposal: %s", cipher_prop);
- debug2("Compat cipher proposal: %s", fix_ciphers);
- if (!*fix_ciphers)
- fatal("No available ciphers found.");
- return(fix_ciphers);
+ return fix_prop;
}
+
+char *
+compat_cipher_proposal(char *cipher_prop)
+{
+ if (!(datafellows & SSH_BUG_BIGENDIANAES))
+ return cipher_prop;
+ debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
+ cipher_prop = filter_proposal(cipher_prop, "aes*");
+ debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
+ if (*cipher_prop == '\0')
+ fatal("No supported ciphers found");
+ return cipher_prop;
+}
+
+
+char *
+compat_pkalg_proposal(char *pkalg_prop)
+{
+ if (!(datafellows & SSH_BUG_RSASIGMD5))
+ return pkalg_prop;
+ debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
+ pkalg_prop = filter_proposal(pkalg_prop, "ssh-rsa");
+ debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
+ if (*pkalg_prop == '\0')
+ fatal("No supported PK algorithms found");
+ return pkalg_prop;
+}
+
diff --git a/usr.bin/ssh/compat.h b/usr.bin/ssh/compat.h
index 3ae5d9c7836..b174fa1719c 100644
--- a/usr.bin/ssh/compat.h
+++ b/usr.bin/ssh/compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.h,v 1.43 2011/09/23 07:45:05 markus Exp $ */
+/* $OpenBSD: compat.h,v 1.44 2013/12/30 23:52:27 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -65,6 +65,7 @@ void enable_compat20(void);
void compat_datafellows(const char *);
int proto_spec(const char *);
char *compat_cipher_proposal(char *);
+char *compat_pkalg_proposal(char *);
extern int compat13;
extern int compat20;
diff --git a/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c
index 5971b526a2b..c2ed72cc36f 100644
--- a/usr.bin/ssh/ssh-rsa.c
+++ b/usr.bin/ssh/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.48 2013/12/27 22:37:18 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.49 2013/12/30 23:52:27 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@@ -50,7 +50,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
return -1;
}
- nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
+ nid = NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("%s: EVP_get_digestbynid %d failed", __func__, nid);
return -1;
@@ -158,7 +158,7 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
memset(sigblob, 0, diff);
len = modlen;
}
- nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
+ nid = NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("%s: EVP_get_digestbynid %d failed", __func__, nid);
free(sigblob);
@@ -193,18 +193,6 @@ static const u_char id_sha1[] = {
0x05, 0x00, /* NULL */
0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
};
-/*
- * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
- * rsadsi(113549) digestAlgorithm(2) 5 }
- */
-static const u_char id_md5[] = {
- 0x30, 0x20, /* type Sequence, length 0x20 (32) */
- 0x30, 0x0c, /* type Sequence, length 0x0c (12) */
- 0x06, 0x08, /* type OID, length 0x08 */
- 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
-};
static int
openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
@@ -222,11 +210,6 @@ openssh_RSA_verify(int type, u_char *hash, u_int hashlen,
oidlen = sizeof(id_sha1);
hlen = 20;
break;
- case NID_md5:
- oid = id_md5;
- oidlen = sizeof(id_md5);
- hlen = 16;
- break;
default:
goto done;
}
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index 6a77b9cafb6..28ea1d0f728 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.242 2013/12/29 05:57:02 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.243 2013/12/30 23:52:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -652,6 +652,9 @@ ssh_exchange_identification(int timeout_ms)
fatal("Protocol major versions differ: %d vs. %d",
(options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
remote_major);
+ if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
+ logit("Server version \"%.100s\" uses unsafe RSA signature "
+ "scheme; disabling use of RSA keys", remote_version);
if (!client_banner_sent)
send_client_banner(connection_out, minor1);
chop(server_version_string);
diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index 1572fe457f6..a992668a0d9 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.199 2013/11/02 21:59:15 markus Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.200 2013/12/30 23:52:28 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -182,11 +182,12 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
}
if (options.hostkeyalgorithms != NULL)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- options.hostkeyalgorithms;
+ compat_pkalg_proposal(options.hostkeyalgorithms);
else {
/* Prefer algorithms that we already have keys for */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- order_hostkeyalgs(host, hostaddr, port);
+ compat_pkalg_proposal(
+ order_hostkeyalgs(host, hostaddr, port));
}
if (options.kex_algorithms != NULL)
myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
@@ -1483,17 +1484,31 @@ userauth_pubkey(Authctxt *authctxt)
* encrypted keys we cannot do this and have to load the
* private key instead
*/
- if (id->key && id->key->type != KEY_RSA1) {
- debug("Offering %s public key: %s", key_type(id->key),
- id->filename);
- sent = send_pubkey_test(authctxt, id);
- } else if (id->key == NULL) {
+ if (id->key != NULL) {
+ if (key_type_plain(id->key->type) == KEY_RSA &&
+ (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ debug("Skipped %s key %s for RSA/MD5 server",
+ key_type(id->key), id->filename);
+ } else if (id->key->type != KEY_RSA1) {
+ debug("Offering %s public key: %s",
+ key_type(id->key), id->filename);
+ sent = send_pubkey_test(authctxt, id);
+ }
+ } else {
debug("Trying private key: %s", id->filename);
id->key = load_identity_file(id->filename,
id->userprovided);
if (id->key != NULL) {
id->isprivate = 1;
- sent = sign_and_send_pubkey(authctxt, id);
+ if (key_type_plain(id->key->type) == KEY_RSA &&
+ (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ debug("Skipped %s key %s for RSA/MD5 "
+ "server", key_type(id->key),
+ id->filename);
+ } else {
+ sent = sign_and_send_pubkey(
+ authctxt, id);
+ }
key_free(id->key);
id->key = NULL;
}
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index d040ec6d418..b4fd3478dbc 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.412 2013/12/06 13:39:49 markus Exp $ */
+/* $OpenBSD: sshd.c,v 1.413 2013/12/30 23:52:28 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -471,17 +471,19 @@ sshd_exchange_identification(int sock_in, int sock_out)
compat_datafellows(remote_version);
- if (datafellows & SSH_BUG_PROBE) {
+ if ((datafellows & SSH_BUG_PROBE) != 0) {
logit("probed from %s with %s. Don't panic.",
get_remote_ipaddr(), client_version_string);
cleanup_exit(255);
}
-
- if (datafellows & SSH_BUG_SCANNER) {
+ if ((datafellows & SSH_BUG_SCANNER) != 0) {
logit("scanned from %s with %s. Don't panic.",
get_remote_ipaddr(), client_version_string);
cleanup_exit(255);
}
+ if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
+ logit("Client version \"%.100s\" uses unsafe RSA signature "
+ "scheme; disabling use of RSA keys", remote_version);
mismatch = 0;
switch (remote_major) {
@@ -2300,7 +2302,8 @@ do_ssh2_kex(void)
packet_set_rekey_limits((u_int32_t)options.rekey_limit,
(time_t)options.rekey_interval);
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
+ list_hostkey_types());
/* start key exchange */
kex = kex_setup(myproposal);