1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 5*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 6*0Sstevel@tonic-gate * are met: 7*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 8*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 9*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 10*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 11*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23*0Sstevel@tonic-gate */ 24*0Sstevel@tonic-gate /* 25*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 26*0Sstevel@tonic-gate * Use is subject to license terms. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include "includes.h" 30*0Sstevel@tonic-gate RCSID("$OpenBSD: compat.c,v 1.65 2002/09/27 10:42:09 mickey Exp $"); 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include "buffer.h" 35*0Sstevel@tonic-gate #include "packet.h" 36*0Sstevel@tonic-gate #include "xmalloc.h" 37*0Sstevel@tonic-gate #include "compat.h" 38*0Sstevel@tonic-gate #include "log.h" 39*0Sstevel@tonic-gate #include "match.h" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate int compat13 = 0; 42*0Sstevel@tonic-gate int compat20 = 0; 43*0Sstevel@tonic-gate int datafellows = 0; 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate void 46*0Sstevel@tonic-gate enable_compat20(void) 47*0Sstevel@tonic-gate { 48*0Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 2.0"); 49*0Sstevel@tonic-gate compat20 = 1; 50*0Sstevel@tonic-gate } 51*0Sstevel@tonic-gate void 52*0Sstevel@tonic-gate enable_compat13(void) 53*0Sstevel@tonic-gate { 54*0Sstevel@tonic-gate debug("Enabling compatibility mode for protocol 1.3"); 55*0Sstevel@tonic-gate compat13 = 1; 56*0Sstevel@tonic-gate } 57*0Sstevel@tonic-gate /* datafellows bug compatibility */ 58*0Sstevel@tonic-gate void 59*0Sstevel@tonic-gate compat_datafellows(const char *version) 60*0Sstevel@tonic-gate { 61*0Sstevel@tonic-gate int i; 62*0Sstevel@tonic-gate static struct { 63*0Sstevel@tonic-gate char *pat; 64*0Sstevel@tonic-gate int bugs; 65*0Sstevel@tonic-gate } check[] = { 66*0Sstevel@tonic-gate { "OpenSSH-2.0*," 67*0Sstevel@tonic-gate "OpenSSH-2.1*," 68*0Sstevel@tonic-gate "OpenSSH_2.1*," 69*0Sstevel@tonic-gate "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| 70*0Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 71*0Sstevel@tonic-gate SSH_BUG_EXTEOF}, 72*0Sstevel@tonic-gate { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| 73*0Sstevel@tonic-gate SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 74*0Sstevel@tonic-gate SSH_BUG_EXTEOF}, 75*0Sstevel@tonic-gate { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 76*0Sstevel@tonic-gate SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 77*0Sstevel@tonic-gate { "OpenSSH_2.5.0p1*," 78*0Sstevel@tonic-gate "OpenSSH_2.5.1p1*", 79*0Sstevel@tonic-gate SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 80*0Sstevel@tonic-gate SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 81*0Sstevel@tonic-gate SSH_OLD_GSSAPI}, 82*0Sstevel@tonic-gate { "OpenSSH_2.5.0*," 83*0Sstevel@tonic-gate "OpenSSH_2.5.1*," 84*0Sstevel@tonic-gate "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 85*0Sstevel@tonic-gate SSH_BUG_EXTEOF}, 86*0Sstevel@tonic-gate { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 87*0Sstevel@tonic-gate { "OpenSSH_2.9p*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI| 88*0Sstevel@tonic-gate SSH_BUG_GSSKEX_HOSTKEY}, 89*0Sstevel@tonic-gate { "OpenSSH_2.*," 90*0Sstevel@tonic-gate "OpenSSH_3.0*," 91*0Sstevel@tonic-gate "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_GSSAPI| 92*0Sstevel@tonic-gate SSH_BUG_GSSAPI_BER| 93*0Sstevel@tonic-gate SSH_BUG_GSSKEX_HOSTKEY}, 94*0Sstevel@tonic-gate { "OpenSSH_3.2*," 95*0Sstevel@tonic-gate "OpenSSH_3.3*," 96*0Sstevel@tonic-gate "OpenSSH_3.4*," 97*0Sstevel@tonic-gate "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER|SSH_OLD_GSSAPI| 98*0Sstevel@tonic-gate SSH_BUG_GSSKEX_HOSTKEY}, 99*0Sstevel@tonic-gate { "OpenSSH_3.6*," 100*0Sstevel@tonic-gate "OpenSSH_3.7*," 101*0Sstevel@tonic-gate "OpenSSH_3.8*", SSH_BUG_GSSKEX_HOSTKEY}, 102*0Sstevel@tonic-gate { "OpenSSH*", 0 }, 103*0Sstevel@tonic-gate { "Sun_SSH_1.0.*", SSH_BUG_NOREKEY| 104*0Sstevel@tonic-gate SSH_BUG_DFLT_CLNT_EXIT_0| 105*0Sstevel@tonic-gate SSH_BUG_LOCALES_NOT_LANGTAGS}, 106*0Sstevel@tonic-gate { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 107*0Sstevel@tonic-gate SSH_BUG_DFLT_CLNT_EXIT_0| 108*0Sstevel@tonic-gate SSH_BUG_LOCALES_NOT_LANGTAGS}, 109*0Sstevel@tonic-gate { "*MindTerm*", 0 }, 110*0Sstevel@tonic-gate { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 111*0Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 112*0Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 113*0Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 114*0Sstevel@tonic-gate { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 115*0Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 116*0Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 117*0Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 118*0Sstevel@tonic-gate { "2.0.13*," 119*0Sstevel@tonic-gate "2.0.14*," 120*0Sstevel@tonic-gate "2.0.15*," 121*0Sstevel@tonic-gate "2.0.16*," 122*0Sstevel@tonic-gate "2.0.17*," 123*0Sstevel@tonic-gate "2.0.18*," 124*0Sstevel@tonic-gate "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 125*0Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 126*0Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 127*0Sstevel@tonic-gate SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| 128*0Sstevel@tonic-gate SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| 129*0Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 130*0Sstevel@tonic-gate { "2.0.11*," 131*0Sstevel@tonic-gate "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 132*0Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 133*0Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 134*0Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 135*0Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 136*0Sstevel@tonic-gate SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 137*0Sstevel@tonic-gate { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 138*0Sstevel@tonic-gate SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 139*0Sstevel@tonic-gate SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 140*0Sstevel@tonic-gate SSH_BUG_PKAUTH|SSH_BUG_PKOK| 141*0Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 142*0Sstevel@tonic-gate SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| 143*0Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 144*0Sstevel@tonic-gate { "2.2.0*," 145*0Sstevel@tonic-gate "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| 146*0Sstevel@tonic-gate SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, 147*0Sstevel@tonic-gate { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| 148*0Sstevel@tonic-gate SSH_BUG_FIRSTKEX }, 149*0Sstevel@tonic-gate { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ 150*0Sstevel@tonic-gate { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX }, 151*0Sstevel@tonic-gate { "3.0.*", SSH_BUG_DEBUG }, 152*0Sstevel@tonic-gate { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, 153*0Sstevel@tonic-gate { "1.7 SecureFX*", SSH_OLD_SESSIONID }, 154*0Sstevel@tonic-gate { "1.2.18*," 155*0Sstevel@tonic-gate "1.2.19*," 156*0Sstevel@tonic-gate "1.2.20*," 157*0Sstevel@tonic-gate "1.2.21*," 158*0Sstevel@tonic-gate "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 159*0Sstevel@tonic-gate { "1.3.2*", /* F-Secure */ 160*0Sstevel@tonic-gate SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, 161*0Sstevel@tonic-gate { "1.2.1*," 162*0Sstevel@tonic-gate "1.2.2*," 163*0Sstevel@tonic-gate "1.2.3*", SSH_BUG_K5USER }, 164*0Sstevel@tonic-gate { "*SSH Compatible Server*", /* Netscreen */ 165*0Sstevel@tonic-gate SSH_BUG_PASSWORDPAD }, 166*0Sstevel@tonic-gate { "*OSU_0*," 167*0Sstevel@tonic-gate "OSU_1.0*," 168*0Sstevel@tonic-gate "OSU_1.1*," 169*0Sstevel@tonic-gate "OSU_1.2*," 170*0Sstevel@tonic-gate "OSU_1.3*," 171*0Sstevel@tonic-gate "OSU_1.4*," 172*0Sstevel@tonic-gate "OSU_1.5alpha1*," 173*0Sstevel@tonic-gate "OSU_1.5alpha2*," 174*0Sstevel@tonic-gate "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, 175*0Sstevel@tonic-gate { "*SSH_Version_Mapper*", 176*0Sstevel@tonic-gate SSH_BUG_SCANNER }, 177*0Sstevel@tonic-gate { "Probe-*", 178*0Sstevel@tonic-gate SSH_BUG_PROBE }, 179*0Sstevel@tonic-gate { NULL, 0 } 180*0Sstevel@tonic-gate }; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* process table, return first match */ 183*0Sstevel@tonic-gate for (i = 0; check[i].pat; i++) { 184*0Sstevel@tonic-gate if (match_pattern_list(version, check[i].pat, 185*0Sstevel@tonic-gate strlen(check[i].pat), 0) == 1) { 186*0Sstevel@tonic-gate debug("match: %s pat %s", version, check[i].pat); 187*0Sstevel@tonic-gate datafellows = check[i].bugs; 188*0Sstevel@tonic-gate return; 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate debug("no match: %s", version); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate #define SEP "," 195*0Sstevel@tonic-gate int 196*0Sstevel@tonic-gate proto_spec(const char *spec) 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate char *s, *p, *q; 199*0Sstevel@tonic-gate int ret = SSH_PROTO_UNKNOWN; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (spec == NULL) 202*0Sstevel@tonic-gate return ret; 203*0Sstevel@tonic-gate q = s = xstrdup(spec); 204*0Sstevel@tonic-gate for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { 205*0Sstevel@tonic-gate switch (atoi(p)) { 206*0Sstevel@tonic-gate case 1: 207*0Sstevel@tonic-gate if (ret == SSH_PROTO_UNKNOWN) 208*0Sstevel@tonic-gate ret |= SSH_PROTO_1_PREFERRED; 209*0Sstevel@tonic-gate ret |= SSH_PROTO_1; 210*0Sstevel@tonic-gate break; 211*0Sstevel@tonic-gate case 2: 212*0Sstevel@tonic-gate ret |= SSH_PROTO_2; 213*0Sstevel@tonic-gate break; 214*0Sstevel@tonic-gate default: 215*0Sstevel@tonic-gate log("ignoring bad proto spec: '%s'.", p); 216*0Sstevel@tonic-gate break; 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate xfree(s); 220*0Sstevel@tonic-gate return ret; 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate char * 224*0Sstevel@tonic-gate compat_cipher_proposal(char *cipher_prop) 225*0Sstevel@tonic-gate { 226*0Sstevel@tonic-gate Buffer b; 227*0Sstevel@tonic-gate char *orig_prop, *fix_ciphers; 228*0Sstevel@tonic-gate char *cp, *tmp; 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate if (!(datafellows & SSH_BUG_BIGENDIANAES)) 231*0Sstevel@tonic-gate return(cipher_prop); 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate buffer_init(&b); 234*0Sstevel@tonic-gate tmp = orig_prop = xstrdup(cipher_prop); 235*0Sstevel@tonic-gate while ((cp = strsep(&tmp, ",")) != NULL) { 236*0Sstevel@tonic-gate if (strncmp(cp, "aes", 3) != 0) { 237*0Sstevel@tonic-gate if (buffer_len(&b) > 0) 238*0Sstevel@tonic-gate buffer_append(&b, ",", 1); 239*0Sstevel@tonic-gate buffer_append(&b, cp, strlen(cp)); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate buffer_append(&b, "\0", 1); 243*0Sstevel@tonic-gate fix_ciphers = xstrdup(buffer_ptr(&b)); 244*0Sstevel@tonic-gate buffer_free(&b); 245*0Sstevel@tonic-gate xfree(orig_prop); 246*0Sstevel@tonic-gate debug2("Original cipher proposal: %s", cipher_prop); 247*0Sstevel@tonic-gate debug2("Compat cipher proposal: %s", fix_ciphers); 248*0Sstevel@tonic-gate if (!*fix_ciphers) 249*0Sstevel@tonic-gate fatal("No available ciphers found."); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate return(fix_ciphers); 252*0Sstevel@tonic-gate } 253