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