1 /* $NetBSD: compat.c,v 1.17 2017/10/07 19:39:19 christos Exp $ */ 2 /* $OpenBSD: compat.c,v 1.104 2017/07/25 09:22:25 dtucker Exp $ */ 3 /* 4 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "includes.h" 28 __RCSID("$NetBSD: compat.c,v 1.17 2017/10/07 19:39:19 christos Exp $"); 29 #include <sys/types.h> 30 31 #include <stdlib.h> 32 #include <string.h> 33 #include <stdarg.h> 34 35 #include "xmalloc.h" 36 #include "buffer.h" 37 #include "packet.h" 38 #include "compat.h" 39 #include "log.h" 40 #include "match.h" 41 #include "kex.h" 42 43 int datafellows = 0; 44 45 /* datafellows bug compatibility */ 46 u_int 47 compat_datafellows(const char *version) 48 { 49 int i; 50 static struct { 51 const char *pat; 52 int bugs; 53 } check[] = { 54 { "OpenSSH-2.0*," 55 "OpenSSH-2.1*," 56 "OpenSSH_2.1*," 57 "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| 58 SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 59 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 60 { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| 61 SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 62 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 63 { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 64 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 65 SSH_OLD_FORWARD_ADDR}, 66 { "OpenSSH_2.5.0p1*," 67 "OpenSSH_2.5.1p1*", 68 SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| 69 SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 70 SSH_OLD_FORWARD_ADDR}, 71 { "OpenSSH_2.5.0*," 72 "OpenSSH_2.5.1*," 73 "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| 74 SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 75 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| 76 SSH_OLD_FORWARD_ADDR}, 77 { "OpenSSH_2.*," 78 "OpenSSH_3.0*," 79 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 80 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR }, 81 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 82 { "OpenSSH_4*", 0 }, 83 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT}, 84 { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH}, 85 { "OpenSSH_6.5*," 86 "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD}, 87 { "OpenSSH*", SSH_NEW_OPENSSH }, 88 { "*MindTerm*", 0 }, 89 { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 90 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 91 SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 92 SSH_BUG_FIRSTKEX }, 93 { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 94 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 95 SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE| 96 SSH_BUG_FIRSTKEX }, 97 { "2.0.13*," 98 "2.0.14*," 99 "2.0.15*," 100 "2.0.16*," 101 "2.0.17*," 102 "2.0.18*," 103 "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 104 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 105 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 106 SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| 107 SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| 108 SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 109 { "2.0.11*," 110 "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 111 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 112 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 113 SSH_BUG_PKAUTH|SSH_BUG_PKOK| 114 SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 115 SSH_BUG_DUMMYCHAN|SSH_BUG_FIRSTKEX }, 116 { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 117 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 118 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 119 SSH_BUG_PKAUTH|SSH_BUG_PKOK| 120 SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| 121 SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN| 122 SSH_BUG_FIRSTKEX }, 123 { "2.2.0*," 124 "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| 125 SSH_BUG_RSASIGMD5|SSH_BUG_FIRSTKEX }, 126 { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5| 127 SSH_BUG_FIRSTKEX }, 128 { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ 129 { "2.*", SSH_BUG_DEBUG|SSH_BUG_FIRSTKEX| 130 SSH_BUG_RFWD_ADDR }, 131 { "3.0.*", SSH_BUG_DEBUG }, 132 { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, 133 { "1.7 SecureFX*", SSH_OLD_SESSIONID }, 134 { "1.2.18*," 135 "1.2.19*," 136 "1.2.20*," 137 "1.2.21*," 138 "1.2.22*", SSH_BUG_IGNOREMSG }, 139 { "1.3.2*", /* F-Secure */ 140 SSH_BUG_IGNOREMSG }, 141 { "Cisco-1.*", SSH_BUG_DHGEX_LARGE| 142 SSH_BUG_HOSTKEYS }, 143 { "*SSH Compatible Server*", /* Netscreen */ 144 SSH_BUG_PASSWORDPAD }, 145 { "*OSU_0*," 146 "OSU_1.0*," 147 "OSU_1.1*," 148 "OSU_1.2*," 149 "OSU_1.3*," 150 "OSU_1.4*," 151 "OSU_1.5alpha1*," 152 "OSU_1.5alpha2*," 153 "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, 154 { "*SSH_Version_Mapper*", 155 SSH_BUG_SCANNER }, 156 { "PuTTY_Local:*," /* dev versions < Sep 2014 */ 157 "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */ 158 "PuTTY_Release_0.5*," /* 0.58-0.59 */ 159 "PuTTY_Release_0.60*," 160 "PuTTY_Release_0.61*," 161 "PuTTY_Release_0.62*," 162 "PuTTY_Release_0.63*," 163 "PuTTY_Release_0.64*", 164 SSH_OLD_DHGEX }, 165 { "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */ 166 { "Probe-*", 167 SSH_BUG_PROBE }, 168 { "TeraTerm SSH*," 169 "TTSSH/1.5.*," 170 "TTSSH/2.1*," 171 "TTSSH/2.2*," 172 "TTSSH/2.3*," 173 "TTSSH/2.4*," 174 "TTSSH/2.5*," 175 "TTSSH/2.6*," 176 "TTSSH/2.70*," 177 "TTSSH/2.71*," 178 "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, 179 { "WinSCP_release_4*," 180 "WinSCP_release_5.0*," 181 "WinSCP_release_5.1," 182 "WinSCP_release_5.1.*," 183 "WinSCP_release_5.5," 184 "WinSCP_release_5.5.*," 185 "WinSCP_release_5.6," 186 "WinSCP_release_5.6.*," 187 "WinSCP_release_5.7," 188 "WinSCP_release_5.7.1," 189 "WinSCP_release_5.7.2," 190 "WinSCP_release_5.7.3," 191 "WinSCP_release_5.7.4", 192 SSH_OLD_DHGEX }, 193 { NULL, 0 } 194 }; 195 196 /* process table, return first match */ 197 for (i = 0; check[i].pat; i++) { 198 if (match_pattern_list(version, check[i].pat, 0) == 1) { 199 debug("match: %s pat %s compat 0x%08x", 200 version, check[i].pat, check[i].bugs); 201 datafellows = check[i].bugs; /* XXX for now */ 202 /* Check to see if the remote side is OpenSSH and not HPN */ 203 if(strstr(version,"OpenSSH") != NULL) 204 { 205 if (strstr(version,"hpn") == NULL) 206 { 207 datafellows |= SSH_BUG_LARGEWINDOW; 208 debug("Remote is NON-HPN aware"); 209 } 210 } 211 return check[i].bugs; 212 } 213 } 214 debug("no match: %s", version); 215 return 0; 216 } 217 218 #define SEP "," 219 int 220 proto_spec(const char *spec) 221 { 222 char *s, *p, *q; 223 int ret = SSH_PROTO_UNKNOWN; 224 225 if (spec == NULL) 226 return ret; 227 q = s = strdup(spec); 228 if (s == NULL) 229 return ret; 230 for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { 231 switch (atoi(p)) { 232 case 2: 233 ret |= SSH_PROTO_2; 234 break; 235 default: 236 logit("ignoring bad proto spec: '%s'.", p); 237 break; 238 } 239 } 240 free(s); 241 return ret; 242 } 243 244 const char * 245 compat_cipher_proposal(const char *cipher_prop) 246 { 247 if (!(datafellows & SSH_BUG_BIGENDIANAES)) 248 return cipher_prop; 249 debug2("%s: original cipher proposal: %s", __func__, cipher_prop); 250 if ((cipher_prop = match_filter_list(cipher_prop, "aes*")) == NULL) 251 fatal("match_filter_list failed"); 252 debug2("%s: compat cipher proposal: %s", __func__, cipher_prop); 253 if (*cipher_prop == '\0') 254 fatal("No supported ciphers found"); 255 return cipher_prop; 256 } 257 258 char * 259 compat_pkalg_proposal(char *pkalg_prop) 260 { 261 if (!(datafellows & SSH_BUG_RSASIGMD5)) 262 return pkalg_prop; 263 debug2("%s: original public key proposal: %s", __func__, pkalg_prop); 264 if ((pkalg_prop = match_filter_list(pkalg_prop, "ssh-rsa")) == NULL) 265 fatal("match_filter_list failed"); 266 debug2("%s: compat public key proposal: %s", __func__, pkalg_prop); 267 if (*pkalg_prop == '\0') 268 fatal("No supported PK algorithms found"); 269 return pkalg_prop; 270 } 271 272 const char * 273 compat_kex_proposal(const char *p) 274 { 275 if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) 276 return p; 277 debug2("%s: original KEX proposal: %s", __func__, p); 278 if ((datafellows & SSH_BUG_CURVE25519PAD) != 0) 279 if ((p = match_filter_list(p, 280 "curve25519-sha256@libssh.org")) == NULL) 281 fatal("match_filter_list failed"); 282 if ((datafellows & SSH_OLD_DHGEX) != 0) { 283 if ((p = match_filter_list(p, 284 "diffie-hellman-group-exchange-sha256," 285 "diffie-hellman-group-exchange-sha1")) == NULL) 286 fatal("match_filter_list failed"); 287 } 288 debug2("%s: compat KEX proposal: %s", __func__, p); 289 if (*p == '\0') 290 fatal("No supported key exchange algorithms found"); 291 return p; 292 } 293 294