]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
- djm@cvs.openbsd.org 2013/12/30 23:52:28
authorDamien Miller <djm@mindrot.org>
Tue, 31 Dec 2013 01:25:40 +0000 (12:25 +1100)
committerDamien Miller <djm@mindrot.org>
Tue, 31 Dec 2013 01:25:40 +0000 (12:25 +1100)
     [auth2-hostbased.c auth2-pubkey.c compat.c compat.h ssh-rsa.c]
     [sshconnect.c sshconnect2.c sshd.c]
     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@

ChangeLog
auth2-hostbased.c
auth2-pubkey.c
compat.c
compat.h
ssh-rsa.c
sshconnect.c
sshconnect2.c
sshd.c

index d33de38a7c2611898f652d3af80934066673d600..7b51234126985a5ea0245eec754dcf93380bf85a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+20131231
+ - (djm) OpenBSD CVS Sync
+   - djm@cvs.openbsd.org 2013/12/30 23:52:28
+     [auth2-hostbased.c auth2-pubkey.c compat.c compat.h ssh-rsa.c]
+     [sshconnect.c sshconnect2.c sshd.c]
+     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@
+
 20131229
  - (djm) [loginrec.c] Check for username truncation when looking up lastlog
    entries
index a344dcc1f7974d09a5f1a981a545e32c01dfdb22..488008f622894aabee768e90cdd1728ee8f8e995 100644 (file)
@@ -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.
  *
@@ -100,6 +100,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);
index 2b3ecb10405dbcfad9886f51a3141ede0d99dbcc..0fd27bb9283c843ff26a6875068a0dbc15a98219 100644 (file)
@@ -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.
  *
@@ -116,6 +116,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();
index ac353a706f520acd2cc08d1f818fd5bdec135952..9d9fabef3b457a7874d1e1cf3abb472d678fd14d 100644 (file)
--- a/compat.c
+++ b/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.
  *
@@ -171,8 +171,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;
                }
        }
@@ -208,33 +209,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;
+}
+
index 3ae5d9c7836e5593a3cbf9dcca23f3fae73a31c0..b174fa1719c085c0fc912048da0056d0778d5873 100644 (file)
--- a/compat.h
+++ b/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;
index 6e28bb4a697e2b8985a9b12cbe95e6844a1a4045..b1ac50b31d311c45e972330b4a90f7b9b31b409c 100644 (file)
--- a/ssh-rsa.c
+++ b/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>
  *
@@ -53,7 +53,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;
@@ -161,7 +161,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);
@@ -196,18 +196,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,
@@ -225,11 +213,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;
        }
index b492ce915b00f3eb447480fa106d4a5481f9ad8b..791b31c12f3711e819ce9cfc5dc76b53ff6cf120 100644 (file)
@@ -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
@@ -662,6 +662,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);
index 1f6160e863dc24fb2815c79bc4d6100f1b424f90..0d339b9c5c347b25ed7b5e763560f3f14c19ac57 100644 (file)
@@ -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.
@@ -188,11 +188,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;
@@ -1489,17 +1490,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/sshd.c b/sshd.c
index 786d9ff907bfc34a9e9442d9bebecf6ea0e56e15..87795bea529e85ce22679a7eaef08b51d2f10384 100644 (file)
--- a/sshd.c
+++ b/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
@@ -492,17 +492,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) {
@@ -2446,7 +2448,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);