Merge branch 'vendor/OPENSSH'
[dragonfly.git] / crypto / openssh / compat.c
index 9ab3688..f62618c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.79 2011/09/23 07:45:05 markus Exp $ */
+/* $OpenBSD: compat.c,v 1.85 2014/04/20 02:49:32 djm Exp $ */
 /*
  * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  *
@@ -45,6 +45,8 @@ int datafellows = 0;
 void
 enable_compat20(void)
 {
+       if (compat20)
+               return;
        debug("Enabling compatibility mode for protocol 2.0");
        compat20 = 1;
 }
@@ -93,6 +95,9 @@ compat_datafellows(const char *version)
                { "Sun_SSH_1.0*",       SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
                { "OpenSSH_4*",         0 },
                { "OpenSSH_5*",         SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
+               { "OpenSSH_6.6.1*",     SSH_NEW_OPENSSH},
+               { "OpenSSH_6.5*,"
+                 "OpenSSH_6.6*",       SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
                { "OpenSSH*",           SSH_NEW_OPENSSH },
                { "*MindTerm*",         0 },
                { "2.1.0*",             SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@@ -169,7 +174,6 @@ 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;
                        /* Check to see if the remote side is OpenSSH and not HPN */
                        if(strstr(version,"OpenSSH") != NULL)
@@ -180,6 +184,8 @@ compat_datafellows(const char *version)
                                        debug("Remote is NON-HPN aware");
                                }
                        }
+                       debug("match: %s pat %s compat 0x%08x",
+                           version, check[i].pat, datafellows);
                        return;
                }
        }
@@ -211,37 +217,75 @@ proto_spec(const char *spec)
                        break;
                }
        }
-       xfree(s);
+       free(s);
        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);
-       xfree(orig_prop);
-       debug2("Original cipher proposal: %s", cipher_prop);
-       debug2("Compat cipher proposal: %s", fix_ciphers);
-       if (!*fix_ciphers)
-               fatal("No available ciphers found.");
+       free(orig_prop);
+
+       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;
+}
 
-       return(fix_ciphers);
+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;
 }
+
+char *
+compat_kex_proposal(char *kex_prop)
+{
+       if (!(datafellows & SSH_BUG_CURVE25519PAD))
+               return kex_prop;
+       debug2("%s: original KEX proposal: %s", __func__, kex_prop);
+       kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
+       debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
+       if (*kex_prop == '\0')
+               fatal("No supported key exchange algorithms found");
+       return kex_prop;
+}
+