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 /* 255018Sjp161948 * Copyright 2007 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 #pragma ident "%Z%%M% %I% %E% SMI" 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include "buffer.h" 350Sstevel@tonic-gate #include "packet.h" 360Sstevel@tonic-gate #include "xmalloc.h" 370Sstevel@tonic-gate #include "compat.h" 380Sstevel@tonic-gate #include "log.h" 390Sstevel@tonic-gate #include "match.h" 400Sstevel@tonic-gate 410Sstevel@tonic-gate int compat13 = 0; 420Sstevel@tonic-gate int compat20 = 0; 430Sstevel@tonic-gate int datafellows = 0; 440Sstevel@tonic-gate 450Sstevel@tonic-gate void 460Sstevel@tonic-gate enable_compat20(void) 470Sstevel@tonic-gate { 480Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 2.0"); 490Sstevel@tonic-gate compat20 = 1; 500Sstevel@tonic-gate } 510Sstevel@tonic-gate void 520Sstevel@tonic-gate enable_compat13(void) 530Sstevel@tonic-gate { 540Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 1.3"); 550Sstevel@tonic-gate compat13 = 1; 560Sstevel@tonic-gate } 570Sstevel@tonic-gate /* datafellows bug compatibility */ 580Sstevel@tonic-gate void 590Sstevel@tonic-gate compat_datafellows(const char *version) 600Sstevel@tonic-gate { 610Sstevel@tonic-gate int i; 620Sstevel@tonic-gate static struct { 630Sstevel@tonic-gate char *pat; 640Sstevel@tonic-gate int bugs; 650Sstevel@tonic-gate } check[] = { 660Sstevel@tonic-gate { "OpenSSH-2.0*," 670Sstevel@tonic-gate "OpenSSH-2.1*," 680Sstevel@tonic-gate "OpenSSH_2.1*," 690Sstevel@tonic-gate "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| 700Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 71*5334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 720Sstevel@tonic-gate { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| 730Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 74*5334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 750Sstevel@tonic-gate { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 76*5334Sjp161948 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 77*5334Sjp161948 SSH_OLD_FORWARD_ADDR}, 780Sstevel@tonic-gate { "OpenSSH_2.5.0p1*," 790Sstevel@tonic-gate "OpenSSH_2.5.1p1*", 800Sstevel@tonic-gate SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 810Sstevel@tonic-gate SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 82*5334Sjp161948 SSH_OLD_GSSAPI|SSH_OLD_FORWARD_ADDR}, 830Sstevel@tonic-gate { "OpenSSH_2.5.0*," 840Sstevel@tonic-gate "OpenSSH_2.5.1*," 850Sstevel@tonic-gate "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 86*5334Sjp161948 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 87*5334Sjp161948 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 88*5334Sjp161948 SSH_OLD_FORWARD_ADDR}, 890Sstevel@tonic-gate { "OpenSSH_2.9p*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI| 90*5334Sjp161948 SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 910Sstevel@tonic-gate { "OpenSSH_2.*," 920Sstevel@tonic-gate "OpenSSH_3.0*," 93*5334Sjp161948 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR| 94*5334Sjp161948 SSH_OLD_GSSAPI|SSH_BUG_GSSAPI_BER| 950Sstevel@tonic-gate SSH_BUG_GSSKEX_HOSTKEY}, 960Sstevel@tonic-gate { "OpenSSH_3.2*," 970Sstevel@tonic-gate "OpenSSH_3.3*," 980Sstevel@tonic-gate "OpenSSH_3.4*," 990Sstevel@tonic-gate "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER|SSH_OLD_GSSAPI| 100*5334Sjp161948 SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 1010Sstevel@tonic-gate { "OpenSSH_3.6*," 1020Sstevel@tonic-gate "OpenSSH_3.7*," 103*5334Sjp161948 "OpenSSH_3.8*", SSH_BUG_GSSKEX_HOSTKEY|SSH_OLD_FORWARD_ADDR}, 104*5334Sjp161948 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR}, 1050Sstevel@tonic-gate { "OpenSSH*", 0 }, 1060Sstevel@tonic-gate { "Sun_SSH_1.0.*", SSH_BUG_NOREKEY| 107*5334Sjp161948 SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, 1080Sstevel@tonic-gate { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 109*5334Sjp161948 SSH_BUG_LOCALES_NOT_LANGTAGS|SSH_OLD_FORWARD_ADDR}, 110*5334Sjp161948 { "Sun_SSH_1.1*", SSH_OLD_FORWARD_ADDR}, 111*5334Sjp161948 { "Sun_SSH_1.2*", 0 }, 1120Sstevel@tonic-gate { "*MindTerm*", 0 }, 1130Sstevel@tonic-gate { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1140Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1150Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 1160Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1170Sstevel@tonic-gate { "2.1 *", 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.0.13*," 1220Sstevel@tonic-gate "2.0.14*," 1230Sstevel@tonic-gate "2.0.15*," 1240Sstevel@tonic-gate "2.0.16*," 1250Sstevel@tonic-gate "2.0.17*," 1260Sstevel@tonic-gate "2.0.18*," 1270Sstevel@tonic-gate "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1280Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1290Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1300Sstevel@tonic-gate SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| 1310Sstevel@tonic-gate SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| 1320Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1330Sstevel@tonic-gate { "2.0.11*," 1340Sstevel@tonic-gate "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1350Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1360Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1370Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1380Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1390Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 1400Sstevel@tonic-gate { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 1410Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 1420Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 1430Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 1440Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 1450Sstevel@tonic-gate SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| 1460Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1470Sstevel@tonic-gate { "2.2.0*," 1480Sstevel@tonic-gate "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| 1490Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, 1500Sstevel@tonic-gate { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| 1510Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 1520Sstevel@tonic-gate { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ 153*5334Sjp161948 { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX| 154*5334Sjp161948 SSH_BUG_RFWD_ADDR}, 1550Sstevel@tonic-gate { "3.0.*", SSH_BUG_DEBUG }, 1560Sstevel@tonic-gate { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, 1570Sstevel@tonic-gate { "1.7 SecureFX*", SSH_OLD_SESSIONID }, 1580Sstevel@tonic-gate { "1.2.18*," 1590Sstevel@tonic-gate "1.2.19*," 1600Sstevel@tonic-gate "1.2.20*," 1610Sstevel@tonic-gate "1.2.21*," 1620Sstevel@tonic-gate "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1630Sstevel@tonic-gate { "1.3.2*", /* F-Secure */ 1640Sstevel@tonic-gate SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 1650Sstevel@tonic-gate { "1.2.1*," 1660Sstevel@tonic-gate "1.2.2*," 1670Sstevel@tonic-gate "1.2.3*", SSH_BUG_K5USER }, 1680Sstevel@tonic-gate { "*SSH Compatible Server*", /* Netscreen */ 1690Sstevel@tonic-gate SSH_BUG_PASSWORDPAD }, 1700Sstevel@tonic-gate { "*OSU_0*," 1710Sstevel@tonic-gate "OSU_1.0*," 1720Sstevel@tonic-gate "OSU_1.1*," 1730Sstevel@tonic-gate "OSU_1.2*," 1740Sstevel@tonic-gate "OSU_1.3*," 1750Sstevel@tonic-gate "OSU_1.4*," 1760Sstevel@tonic-gate "OSU_1.5alpha1*," 1770Sstevel@tonic-gate "OSU_1.5alpha2*," 1780Sstevel@tonic-gate "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, 1790Sstevel@tonic-gate { "*SSH_Version_Mapper*", 1800Sstevel@tonic-gate SSH_BUG_SCANNER }, 1810Sstevel@tonic-gate { "Probe-*", 1820Sstevel@tonic-gate SSH_BUG_PROBE }, 1830Sstevel@tonic-gate { NULL, 0 } 1840Sstevel@tonic-gate }; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* process table, return first match */ 1870Sstevel@tonic-gate for (i = 0; check[i].pat; i++) { 1880Sstevel@tonic-gate if (match_pattern_list(version, check[i].pat, 1890Sstevel@tonic-gate strlen(check[i].pat), 0) == 1) { 1900Sstevel@tonic-gate debug("match: %s pat %s", version, check[i].pat); 1910Sstevel@tonic-gate datafellows = check[i].bugs; 1920Sstevel@tonic-gate return; 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate debug("no match: %s", version); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate #define SEP "," 1990Sstevel@tonic-gate int 2000Sstevel@tonic-gate proto_spec(const char *spec) 2010Sstevel@tonic-gate { 2020Sstevel@tonic-gate char *s, *p, *q; 2030Sstevel@tonic-gate int ret = SSH_PROTO_UNKNOWN; 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate if (spec == NULL) 2060Sstevel@tonic-gate return ret; 2070Sstevel@tonic-gate q = s = xstrdup(spec); 2080Sstevel@tonic-gate for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { 2090Sstevel@tonic-gate switch (atoi(p)) { 2100Sstevel@tonic-gate case 1: 2110Sstevel@tonic-gate if (ret == SSH_PROTO_UNKNOWN) 2120Sstevel@tonic-gate ret |= SSH_PROTO_1_PREFERRED; 2130Sstevel@tonic-gate ret |= SSH_PROTO_1; 2140Sstevel@tonic-gate break; 2150Sstevel@tonic-gate case 2: 2160Sstevel@tonic-gate ret |= SSH_PROTO_2; 2170Sstevel@tonic-gate break; 2180Sstevel@tonic-gate default: 2190Sstevel@tonic-gate log("ignoring bad proto spec: '%s'.", p); 2200Sstevel@tonic-gate break; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate xfree(s); 2240Sstevel@tonic-gate return ret; 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate char * 2280Sstevel@tonic-gate compat_cipher_proposal(char *cipher_prop) 2290Sstevel@tonic-gate { 2300Sstevel@tonic-gate Buffer b; 2310Sstevel@tonic-gate char *orig_prop, *fix_ciphers; 2320Sstevel@tonic-gate char *cp, *tmp; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate if (!(datafellows & SSH_BUG_BIGENDIANAES)) 2350Sstevel@tonic-gate return(cipher_prop); 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate buffer_init(&b); 2380Sstevel@tonic-gate tmp = orig_prop = xstrdup(cipher_prop); 2390Sstevel@tonic-gate while ((cp = strsep(&tmp, ",")) != NULL) { 2400Sstevel@tonic-gate if (strncmp(cp, "aes", 3) != 0) { 2410Sstevel@tonic-gate if (buffer_len(&b) > 0) 2420Sstevel@tonic-gate buffer_append(&b, ",", 1); 2430Sstevel@tonic-gate buffer_append(&b, cp, strlen(cp)); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate buffer_append(&b, "\0", 1); 2470Sstevel@tonic-gate fix_ciphers = xstrdup(buffer_ptr(&b)); 2480Sstevel@tonic-gate buffer_free(&b); 2490Sstevel@tonic-gate xfree(orig_prop); 2500Sstevel@tonic-gate debug2("Original cipher proposal: %s", cipher_prop); 2510Sstevel@tonic-gate debug2("Compat cipher proposal: %s", fix_ciphers); 2520Sstevel@tonic-gate if (!*fix_ciphers) 2530Sstevel@tonic-gate fatal("No available ciphers found."); 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate return(fix_ciphers); 2560Sstevel@tonic-gate } 257