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 /* 25*9600SNobutomo.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; 41*9600SNobutomo.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; 62*9600SNobutomo.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}, 108*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, 109*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1.2*", SSH_OLD_FORWARD_ADDR}, 110*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.1*", SSH_OLD_FORWARD_ADDR|SSH_BUG_STRING_ENCODING}, 111*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.2*", SSH_BUG_STRING_ENCODING}, 112*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.3*", SSH_BUG_STRING_ENCODING}, 113*9600SNobutomo.Nakano@Sun.COM { "Sun_SSH_1.4*", 0 }, 1148298SJan.Pechanec@Sun.COM { "Sun_SSH_*", 0 }, 1150Sstevel@tonic-gate { "*MindTerm*", 0 }, 1160Sstevel@tonic-gate { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1170Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1180Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 1190Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1200Sstevel@tonic-gate { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1210Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1220Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 1230Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1240Sstevel@tonic-gate { "2.0.13*," 1250Sstevel@tonic-gate "2.0.14*," 1260Sstevel@tonic-gate "2.0.15*," 1270Sstevel@tonic-gate "2.0.16*," 1280Sstevel@tonic-gate "2.0.17*," 1290Sstevel@tonic-gate "2.0.18*," 1300Sstevel@tonic-gate "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1310Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1320Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1330Sstevel@tonic-gate SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| 1340Sstevel@tonic-gate SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| 1350Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1360Sstevel@tonic-gate { "2.0.11*," 1370Sstevel@tonic-gate "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1380Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1390Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1400Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1410Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1420Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1430Sstevel@tonic-gate { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1440Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1450Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1460Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1470Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1480Sstevel@tonic-gate SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| 1490Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1500Sstevel@tonic-gate { "2.2.0*," 1510Sstevel@tonic-gate "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| 1520Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, 1530Sstevel@tonic-gate { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| 1540Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1550Sstevel@tonic-gate { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ 1565334Sjp161948 { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX| 1575334Sjp161948 SSH_BUG_RFWD_ADDR}, 1580Sstevel@tonic-gate { "3.0.*", SSH_BUG_DEBUG }, 1590Sstevel@tonic-gate { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, 1600Sstevel@tonic-gate { "1.7 SecureFX*", SSH_OLD_SESSIONID }, 1610Sstevel@tonic-gate { "1.2.18*," 1620Sstevel@tonic-gate "1.2.19*," 1630Sstevel@tonic-gate "1.2.20*," 1640Sstevel@tonic-gate "1.2.21*," 1650Sstevel@tonic-gate "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1660Sstevel@tonic-gate { "1.3.2*", /* F-Secure */ 1670Sstevel@tonic-gate SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1680Sstevel@tonic-gate { "1.2.1*," 1690Sstevel@tonic-gate "1.2.2*," 1700Sstevel@tonic-gate "1.2.3*", SSH_BUG_K5USER }, 1710Sstevel@tonic-gate { "*SSH Compatible Server*", /* Netscreen */ 1720Sstevel@tonic-gate SSH_BUG_PASSWORDPAD }, 1730Sstevel@tonic-gate { "*OSU_0*," 1740Sstevel@tonic-gate "OSU_1.0*," 1750Sstevel@tonic-gate "OSU_1.1*," 1760Sstevel@tonic-gate "OSU_1.2*," 1770Sstevel@tonic-gate "OSU_1.3*," 1780Sstevel@tonic-gate "OSU_1.4*," 1790Sstevel@tonic-gate "OSU_1.5alpha1*," 1800Sstevel@tonic-gate "OSU_1.5alpha2*," 1810Sstevel@tonic-gate "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, 1820Sstevel@tonic-gate { "*SSH_Version_Mapper*", 1830Sstevel@tonic-gate SSH_BUG_SCANNER }, 1840Sstevel@tonic-gate { "Probe-*", 1850Sstevel@tonic-gate SSH_BUG_PROBE }, 1860Sstevel@tonic-gate { NULL, 0 } 1870Sstevel@tonic-gate }; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate /* process table, return first match */ 1900Sstevel@tonic-gate for (i = 0; check[i].pat; i++) { 1910Sstevel@tonic-gate if (match_pattern_list(version, check[i].pat, 1920Sstevel@tonic-gate strlen(check[i].pat), 0) == 1) { 1930Sstevel@tonic-gate debug("match: %s pat %s", version, check[i].pat); 1940Sstevel@tonic-gate datafellows = check[i].bugs; 1950Sstevel@tonic-gate return; 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate debug("no match: %s", version); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate #define SEP "," 2020Sstevel@tonic-gate int 2030Sstevel@tonic-gate proto_spec(const char *spec) 2040Sstevel@tonic-gate { 2050Sstevel@tonic-gate char *s, *p, *q; 2060Sstevel@tonic-gate int ret = SSH_PROTO_UNKNOWN; 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate if (spec == NULL) 2090Sstevel@tonic-gate return ret; 2100Sstevel@tonic-gate q = s = xstrdup(spec); 2110Sstevel@tonic-gate for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { 2120Sstevel@tonic-gate switch (atoi(p)) { 2130Sstevel@tonic-gate case 1: 2140Sstevel@tonic-gate if (ret == SSH_PROTO_UNKNOWN) 2150Sstevel@tonic-gate ret |= SSH_PROTO_1_PREFERRED; 2160Sstevel@tonic-gate ret |= SSH_PROTO_1; 2170Sstevel@tonic-gate break; 2180Sstevel@tonic-gate case 2: 2190Sstevel@tonic-gate ret |= SSH_PROTO_2; 2200Sstevel@tonic-gate break; 2210Sstevel@tonic-gate default: 2220Sstevel@tonic-gate log("ignoring bad proto spec: '%s'.", p); 2230Sstevel@tonic-gate break; 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate xfree(s); 2270Sstevel@tonic-gate return ret; 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate char * 2310Sstevel@tonic-gate compat_cipher_proposal(char *cipher_prop) 2320Sstevel@tonic-gate { 2330Sstevel@tonic-gate Buffer b; 2340Sstevel@tonic-gate char *orig_prop, *fix_ciphers; 2350Sstevel@tonic-gate char *cp, *tmp; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate if (!(datafellows & SSH_BUG_BIGENDIANAES)) 2380Sstevel@tonic-gate return(cipher_prop); 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate buffer_init(&b); 2410Sstevel@tonic-gate tmp = orig_prop = xstrdup(cipher_prop); 2420Sstevel@tonic-gate while ((cp = strsep(&tmp, ",")) != NULL) { 2430Sstevel@tonic-gate if (strncmp(cp, "aes", 3) != 0) { 2440Sstevel@tonic-gate if (buffer_len(&b) > 0) 2450Sstevel@tonic-gate buffer_append(&b, ",", 1); 2460Sstevel@tonic-gate buffer_append(&b, cp, strlen(cp)); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate buffer_append(&b, "\0", 1); 2500Sstevel@tonic-gate fix_ciphers = xstrdup(buffer_ptr(&b)); 2510Sstevel@tonic-gate buffer_free(&b); 2520Sstevel@tonic-gate xfree(orig_prop); 2530Sstevel@tonic-gate debug2("Original cipher proposal: %s", cipher_prop); 2540Sstevel@tonic-gate debug2("Compat cipher proposal: %s", fix_ciphers); 2550Sstevel@tonic-gate if (!*fix_ciphers) 2560Sstevel@tonic-gate fatal("No available ciphers found."); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate return(fix_ciphers); 2590Sstevel@tonic-gate } 260