10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 50Sstevel@tonic-gate * modification, are permitted provided that the following conditions 60Sstevel@tonic-gate * are met: 70Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 80Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 90Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 100Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 110Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 140Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 150Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 160Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 170Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 180Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 190Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 200Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 210Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 220Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate /* 259600SNobutomo.Nakano@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 260Sstevel@tonic-gate * Use is subject to license terms. 270Sstevel@tonic-gate */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include "includes.h" 300Sstevel@tonic-gate RCSID("$OpenBSD: compat.c,v 1.65 2002/09/27 10:42:09 mickey Exp $"); 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include "buffer.h" 330Sstevel@tonic-gate #include "packet.h" 340Sstevel@tonic-gate #include "xmalloc.h" 350Sstevel@tonic-gate #include "compat.h" 360Sstevel@tonic-gate #include "log.h" 370Sstevel@tonic-gate #include "match.h" 380Sstevel@tonic-gate 390Sstevel@tonic-gate int compat13 = 0; 400Sstevel@tonic-gate int compat20 = 0; 419600SNobutomo.Nakano@Sun.COM uint32_t datafellows = 0; 420Sstevel@tonic-gate 430Sstevel@tonic-gate void 440Sstevel@tonic-gate enable_compat20(void) 450Sstevel@tonic-gate { 460Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 2.0"); 470Sstevel@tonic-gate compat20 = 1; 480Sstevel@tonic-gate } 490Sstevel@tonic-gate void 500Sstevel@tonic-gate enable_compat13(void) 510Sstevel@tonic-gate { 520Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 1.3"); 530Sstevel@tonic-gate compat13 = 1; 540Sstevel@tonic-gate } 550Sstevel@tonic-gate /* datafellows bug compatibility */ 560Sstevel@tonic-gate void 570Sstevel@tonic-gate compat_datafellows(const char *version) 580Sstevel@tonic-gate { 590Sstevel@tonic-gate int i; 600Sstevel@tonic-gate static struct { 610Sstevel@tonic-gate char *pat; 629600SNobutomo.Nakano@Sun.COM uint32_t bugs; 630Sstevel@tonic-gate } check[] = { 640Sstevel@tonic-gate { "OpenSSH-2.0*," 650Sstevel@tonic-gate "OpenSSH-2.1*," 660Sstevel@tonic-gate "OpenSSH_2.1*," 670Sstevel@tonic-gate "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| 680Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 695334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 700Sstevel@tonic-gate { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| 710Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 725334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 730Sstevel@tonic-gate { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 745334Sjp161948 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 755334Sjp161948 SSH_OLD_FORWARD_ADDR}, 760Sstevel@tonic-gate { "OpenSSH_2.5.0p1*," 770Sstevel@tonic-gate "OpenSSH_2.5.1p1*", 780Sstevel@tonic-gate SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 790Sstevel@tonic-gate SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 805334Sjp161948 SSH_OLD_GSSAPI|SSH_OLD_FORWARD_ADDR}, 810Sstevel@tonic-gate { "OpenSSH_2.5.0*," 820Sstevel@tonic-gate "OpenSSH_2.5.1*," 830Sstevel@tonic-gate "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 845334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 855334Sjp161948 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 865334Sjp161948 SSH_OLD_FORWARD_ADDR}, 870Sstevel@tonic-gate { "OpenSSH_2.9p*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI| 885334Sjp161948 SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 890Sstevel@tonic-gate { "OpenSSH_2.*," 900Sstevel@tonic-gate "OpenSSH_3.0*," 915334Sjp161948 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR| 925334Sjp161948 SSH_OLD_GSSAPI|SSH_BUG_GSSAPI_BER| 930Sstevel@tonic-gate SSH_BUG_GSSKEX_HOSTKEY}, 940Sstevel@tonic-gate { "OpenSSH_3.2*," 950Sstevel@tonic-gate "OpenSSH_3.3*," 960Sstevel@tonic-gate "OpenSSH_3.4*," 970Sstevel@tonic-gate "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER|SSH_OLD_GSSAPI| 985334Sjp161948 SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 990Sstevel@tonic-gate { "OpenSSH_3.6*," 1000Sstevel@tonic-gate "OpenSSH_3.7*," 1015334Sjp161948 "OpenSSH_3.8*", SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 1025334Sjp161948 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR}, 1030Sstevel@tonic-gate { "OpenSSH*", 0 }, 1040Sstevel@tonic-gate { "Sun_SSH_1.0.*", SSH_BUG_NOREKEY| 1055334Sjp161948 SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, 1060Sstevel@tonic-gate { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 1075334Sjp161948 SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, 1089600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, 1099600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1.2*", SSH_OLD_FORWARD_ADDR}, 1109600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, 1119600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.2*", SSH_BUG_STRING_ENCODING}, 1129600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.3*", SSH_BUG_STRING_ENCODING}, 1139600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.4*", 0 }, 114*10515SJan.Pechanec@Sun.COM { "Sun_SSH_1.5*", 0 }, 1158298SJan.Pechanec@Sun.COM { "Sun_SSH_*", 0 }, 1160Sstevel@tonic-gate { "*MindTerm*", 0 }, 1170Sstevel@tonic-gate { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1180Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1190Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 1200Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1210Sstevel@tonic-gate { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1220Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1230Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 1240Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1250Sstevel@tonic-gate { "2.0.13*," 1260Sstevel@tonic-gate "2.0.14*," 1270Sstevel@tonic-gate "2.0.15*," 1280Sstevel@tonic-gate "2.0.16*," 1290Sstevel@tonic-gate "2.0.17*," 1300Sstevel@tonic-gate "2.0.18*," 1310Sstevel@tonic-gate "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1320Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1330Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1340Sstevel@tonic-gate SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| 1350Sstevel@tonic-gate SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| 1360Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1370Sstevel@tonic-gate { "2.0.11*," 1380Sstevel@tonic-gate "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1390Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1400Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1410Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1420Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1430Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1440Sstevel@tonic-gate { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1450Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1460Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1470Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1480Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1490Sstevel@tonic-gate SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| 1500Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1510Sstevel@tonic-gate { "2.2.0*," 1520Sstevel@tonic-gate "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| 1530Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, 1540Sstevel@tonic-gate { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| 1550Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1560Sstevel@tonic-gate { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ 1575334Sjp161948 { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX| 1585334Sjp161948 SSH_BUG_RFWD_ADDR}, 1590Sstevel@tonic-gate { "3.0.*", SSH_BUG_DEBUG }, 1600Sstevel@tonic-gate { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, 1610Sstevel@tonic-gate { "1.7 SecureFX*", SSH_OLD_SESSIONID }, 1620Sstevel@tonic-gate { "1.2.18*," 1630Sstevel@tonic-gate "1.2.19*," 1640Sstevel@tonic-gate "1.2.20*," 1650Sstevel@tonic-gate "1.2.21*," 1660Sstevel@tonic-gate "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1670Sstevel@tonic-gate { "1.3.2*", /* F-Secure */ 1680Sstevel@tonic-gate SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1690Sstevel@tonic-gate { "1.2.1*," 1700Sstevel@tonic-gate "1.2.2*," 1710Sstevel@tonic-gate "1.2.3*", SSH_BUG_K5USER }, 1720Sstevel@tonic-gate { "*SSH Compatible Server*", /* Netscreen */ 1730Sstevel@tonic-gate SSH_BUG_PASSWORDPAD }, 1740Sstevel@tonic-gate { "*OSU_0*," 1750Sstevel@tonic-gate "OSU_1.0*," 1760Sstevel@tonic-gate "OSU_1.1*," 1770Sstevel@tonic-gate "OSU_1.2*," 1780Sstevel@tonic-gate "OSU_1.3*," 1790Sstevel@tonic-gate "OSU_1.4*," 1800Sstevel@tonic-gate "OSU_1.5alpha1*," 1810Sstevel@tonic-gate "OSU_1.5alpha2*," 1820Sstevel@tonic-gate "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, 1830Sstevel@tonic-gate { "*SSH_Version_Mapper*", 1840Sstevel@tonic-gate SSH_BUG_SCANNER }, 1850Sstevel@tonic-gate { "Probe-*", 1860Sstevel@tonic-gate SSH_BUG_PROBE }, 1870Sstevel@tonic-gate { NULL, 0 } 1880Sstevel@tonic-gate }; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* process table, return first match */ 1910Sstevel@tonic-gate for (i = 0; check[i].pat; i++) { 1920Sstevel@tonic-gate if (match_pattern_list(version, check[i].pat, 1930Sstevel@tonic-gate strlen(check[i].pat), 0) == 1) { 1940Sstevel@tonic-gate debug("match: %s pat %s", version, check[i].pat); 1950Sstevel@tonic-gate datafellows = check[i].bugs; 1960Sstevel@tonic-gate return; 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate debug("no match: %s", version); 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate #define SEP "," 2030Sstevel@tonic-gate int 2040Sstevel@tonic-gate proto_spec(const char *spec) 2050Sstevel@tonic-gate { 2060Sstevel@tonic-gate char *s, *p, *q; 2070Sstevel@tonic-gate int ret = SSH_PROTO_UNKNOWN; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if (spec == NULL) 2100Sstevel@tonic-gate return ret; 2110Sstevel@tonic-gate q = s = xstrdup(spec); 2120Sstevel@tonic-gate for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { 2130Sstevel@tonic-gate switch (atoi(p)) { 2140Sstevel@tonic-gate case 1: 2150Sstevel@tonic-gate if (ret == SSH_PROTO_UNKNOWN) 2160Sstevel@tonic-gate ret |= SSH_PROTO_1_PREFERRED; 2170Sstevel@tonic-gate ret |= SSH_PROTO_1; 2180Sstevel@tonic-gate break; 2190Sstevel@tonic-gate case 2: 2200Sstevel@tonic-gate ret |= SSH_PROTO_2; 2210Sstevel@tonic-gate break; 2220Sstevel@tonic-gate default: 2230Sstevel@tonic-gate log("ignoring bad proto spec: '%s'.", p); 2240Sstevel@tonic-gate break; 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate xfree(s); 2280Sstevel@tonic-gate return ret; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate char * 2320Sstevel@tonic-gate compat_cipher_proposal(char *cipher_prop) 2330Sstevel@tonic-gate { 2340Sstevel@tonic-gate Buffer b; 2350Sstevel@tonic-gate char *orig_prop, *fix_ciphers; 2360Sstevel@tonic-gate char *cp, *tmp; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate if (!(datafellows & SSH_BUG_BIGENDIANAES)) 2390Sstevel@tonic-gate return(cipher_prop); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate buffer_init(&b); 2420Sstevel@tonic-gate tmp = orig_prop = xstrdup(cipher_prop); 2430Sstevel@tonic-gate while ((cp = strsep(&tmp, ",")) != NULL) { 2440Sstevel@tonic-gate if (strncmp(cp, "aes", 3) != 0) { 2450Sstevel@tonic-gate if (buffer_len(&b) > 0) 2460Sstevel@tonic-gate buffer_append(&b, ",", 1); 2470Sstevel@tonic-gate buffer_append(&b, cp, strlen(cp)); 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate buffer_append(&b, "\0", 1); 2510Sstevel@tonic-gate fix_ciphers = xstrdup(buffer_ptr(&b)); 2520Sstevel@tonic-gate buffer_free(&b); 2530Sstevel@tonic-gate xfree(orig_prop); 2540Sstevel@tonic-gate debug2("Original cipher proposal: %s", cipher_prop); 2550Sstevel@tonic-gate debug2("Compat cipher proposal: %s", fix_ciphers); 2560Sstevel@tonic-gate if (!*fix_ciphers) 2570Sstevel@tonic-gate fatal("No available ciphers found."); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate return(fix_ciphers); 2600Sstevel@tonic-gate } 261