1*ba1276acSMatthew Dillon /* $OpenBSD: compat.c,v 1.126 2023/03/06 12:14:48 dtucker Exp $ */
218de8d7fSPeter Avalos /*
318de8d7fSPeter Avalos * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
418de8d7fSPeter Avalos *
518de8d7fSPeter Avalos * Redistribution and use in source and binary forms, with or without
618de8d7fSPeter Avalos * modification, are permitted provided that the following conditions
718de8d7fSPeter Avalos * are met:
818de8d7fSPeter Avalos * 1. Redistributions of source code must retain the above copyright
918de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer.
1018de8d7fSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
1118de8d7fSPeter Avalos * notice, this list of conditions and the following disclaimer in the
1218de8d7fSPeter Avalos * documentation and/or other materials provided with the distribution.
1318de8d7fSPeter Avalos *
1418de8d7fSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1518de8d7fSPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1618de8d7fSPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1718de8d7fSPeter Avalos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1818de8d7fSPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1918de8d7fSPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2018de8d7fSPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2118de8d7fSPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2218de8d7fSPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2318de8d7fSPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2418de8d7fSPeter Avalos */
2518de8d7fSPeter Avalos
2618de8d7fSPeter Avalos #include "includes.h"
2718de8d7fSPeter Avalos
2818de8d7fSPeter Avalos #include <sys/types.h>
2918de8d7fSPeter Avalos
3018de8d7fSPeter Avalos #include <stdlib.h>
3118de8d7fSPeter Avalos #include <string.h>
3218de8d7fSPeter Avalos #include <stdarg.h>
3318de8d7fSPeter Avalos
3418de8d7fSPeter Avalos #include "xmalloc.h"
3518de8d7fSPeter Avalos #include "packet.h"
3618de8d7fSPeter Avalos #include "compat.h"
3718de8d7fSPeter Avalos #include "log.h"
3818de8d7fSPeter Avalos #include "match.h"
3918de8d7fSPeter Avalos
4050a69bb5SSascha Wildner /* determine bug flags from SSH protocol banner */
4150a69bb5SSascha Wildner void
compat_banner(struct ssh * ssh,const char * version)4250a69bb5SSascha Wildner compat_banner(struct ssh *ssh, const char *version)
4318de8d7fSPeter Avalos {
4418de8d7fSPeter Avalos int i;
4518de8d7fSPeter Avalos static struct {
4618de8d7fSPeter Avalos char *pat;
4718de8d7fSPeter Avalos int bugs;
4818de8d7fSPeter Avalos } check[] = {
4918de8d7fSPeter Avalos { "OpenSSH_2.*,"
5018de8d7fSPeter Avalos "OpenSSH_3.0*,"
51664f4763Szrj "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
52664f4763Szrj SSH_BUG_SIGTYPE},
53664f4763Szrj { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE },
54664f4763Szrj { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
55664f4763Szrj SSH_BUG_SIGTYPE},
56664f4763Szrj { "OpenSSH_2*,"
57664f4763Szrj "OpenSSH_3*,"
58664f4763Szrj "OpenSSH_4*", SSH_BUG_SIGTYPE },
59664f4763Szrj { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT|
60664f4763Szrj SSH_BUG_SIGTYPE},
61664f4763Szrj { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
6236e94dc5SPeter Avalos { "OpenSSH_6.5*,"
63664f4763Szrj "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
64664f4763Szrj SSH_BUG_SIGTYPE},
6550a69bb5SSascha Wildner { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE|
6650a69bb5SSascha Wildner SSH_BUG_SIGTYPE74},
67664f4763Szrj { "OpenSSH_7.0*,"
68664f4763Szrj "OpenSSH_7.1*,"
69664f4763Szrj "OpenSSH_7.2*,"
70664f4763Szrj "OpenSSH_7.3*,"
71664f4763Szrj "OpenSSH_7.5*,"
72664f4763Szrj "OpenSSH_7.6*,"
73664f4763Szrj "OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
74cb5eb4f1SPeter Avalos { "OpenSSH*", SSH_NEW_OPENSSH },
7518de8d7fSPeter Avalos { "*MindTerm*", 0 },
7618de8d7fSPeter Avalos { "3.0.*", SSH_BUG_DEBUG },
7718de8d7fSPeter Avalos { "3.0 SecureCRT*", SSH_OLD_SESSIONID },
7818de8d7fSPeter Avalos { "1.7 SecureFX*", SSH_OLD_SESSIONID },
79e9778795SPeter Avalos { "Cisco-1.*", SSH_BUG_DHGEX_LARGE|
80e9778795SPeter Avalos SSH_BUG_HOSTKEYS },
8118de8d7fSPeter Avalos { "*SSH_Version_Mapper*",
8218de8d7fSPeter Avalos SSH_BUG_SCANNER },
83e9778795SPeter Avalos { "PuTTY_Local:*," /* dev versions < Sep 2014 */
84e9778795SPeter Avalos "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
85e9778795SPeter Avalos "PuTTY_Release_0.5*," /* 0.58-0.59 */
86e9778795SPeter Avalos "PuTTY_Release_0.60*,"
87e9778795SPeter Avalos "PuTTY_Release_0.61*,"
88e9778795SPeter Avalos "PuTTY_Release_0.62*,"
89e9778795SPeter Avalos "PuTTY_Release_0.63*,"
90e9778795SPeter Avalos "PuTTY_Release_0.64*",
91e9778795SPeter Avalos SSH_OLD_DHGEX },
92e9778795SPeter Avalos { "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */
9318de8d7fSPeter Avalos { "Probe-*",
9418de8d7fSPeter Avalos SSH_BUG_PROBE },
95e9778795SPeter Avalos { "TeraTerm SSH*,"
96e9778795SPeter Avalos "TTSSH/1.5.*,"
97e9778795SPeter Avalos "TTSSH/2.1*,"
98e9778795SPeter Avalos "TTSSH/2.2*,"
99e9778795SPeter Avalos "TTSSH/2.3*,"
100e9778795SPeter Avalos "TTSSH/2.4*,"
101e9778795SPeter Avalos "TTSSH/2.5*,"
102e9778795SPeter Avalos "TTSSH/2.6*,"
103e9778795SPeter Avalos "TTSSH/2.70*,"
104e9778795SPeter Avalos "TTSSH/2.71*,"
105e9778795SPeter Avalos "TTSSH/2.72*", SSH_BUG_HOSTKEYS },
106e9778795SPeter Avalos { "WinSCP_release_4*,"
107e9778795SPeter Avalos "WinSCP_release_5.0*,"
108ce74bacaSMatthew Dillon "WinSCP_release_5.1,"
109ce74bacaSMatthew Dillon "WinSCP_release_5.1.*,"
110ce74bacaSMatthew Dillon "WinSCP_release_5.5,"
111ce74bacaSMatthew Dillon "WinSCP_release_5.5.*,"
112ce74bacaSMatthew Dillon "WinSCP_release_5.6,"
113ce74bacaSMatthew Dillon "WinSCP_release_5.6.*,"
114e9778795SPeter Avalos "WinSCP_release_5.7,"
115e9778795SPeter Avalos "WinSCP_release_5.7.1,"
116e9778795SPeter Avalos "WinSCP_release_5.7.2,"
117e9778795SPeter Avalos "WinSCP_release_5.7.3,"
118e9778795SPeter Avalos "WinSCP_release_5.7.4",
119e9778795SPeter Avalos SSH_OLD_DHGEX },
120664f4763Szrj { "ConfD-*",
121664f4763Szrj SSH_BUG_UTF8TTYMODE },
122664f4763Szrj { "Twisted_*", 0 },
123664f4763Szrj { "Twisted*", SSH_BUG_DEBUG },
12418de8d7fSPeter Avalos { NULL, 0 }
12518de8d7fSPeter Avalos };
12618de8d7fSPeter Avalos
12718de8d7fSPeter Avalos /* process table, return first match */
12850a69bb5SSascha Wildner ssh->compat = 0;
12918de8d7fSPeter Avalos for (i = 0; check[i].pat; i++) {
130e9778795SPeter Avalos if (match_pattern_list(version, check[i].pat, 0) == 1) {
13150a69bb5SSascha Wildner debug_f("match: %s pat %s compat 0x%08x",
132e9778795SPeter Avalos version, check[i].pat, check[i].bugs);
13350a69bb5SSascha Wildner ssh->compat = check[i].bugs;
13450a69bb5SSascha Wildner return;
13518de8d7fSPeter Avalos }
13618de8d7fSPeter Avalos }
13750a69bb5SSascha Wildner debug_f("no match: %s", version);
13818de8d7fSPeter Avalos }
13918de8d7fSPeter Avalos
140ee116499SAntonio Huete Jimenez /* Always returns pointer to allocated memory, caller must free. */
14118de8d7fSPeter Avalos char *
compat_kex_proposal(struct ssh * ssh,const char * p)142*ba1276acSMatthew Dillon compat_kex_proposal(struct ssh *ssh, const char *p)
14318de8d7fSPeter Avalos {
144*ba1276acSMatthew Dillon char *cp = NULL, *cp2 = NULL;
145ee116499SAntonio Huete Jimenez
14650a69bb5SSascha Wildner if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
147ee116499SAntonio Huete Jimenez return xstrdup(p);
14850a69bb5SSascha Wildner debug2_f("original KEX proposal: %s", p);
14950a69bb5SSascha Wildner if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
150*ba1276acSMatthew Dillon if ((cp = match_filter_denylist(p,
151ce74bacaSMatthew Dillon "curve25519-sha256@libssh.org")) == NULL)
15250a69bb5SSascha Wildner fatal("match_filter_denylist failed");
15350a69bb5SSascha Wildner if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
154*ba1276acSMatthew Dillon if ((cp2 = match_filter_denylist(cp ? cp : p,
155ce74bacaSMatthew Dillon "diffie-hellman-group-exchange-sha256,"
156ce74bacaSMatthew Dillon "diffie-hellman-group-exchange-sha1")) == NULL)
15750a69bb5SSascha Wildner fatal("match_filter_denylist failed");
158ee116499SAntonio Huete Jimenez free(cp);
159*ba1276acSMatthew Dillon cp = cp2;
160e9778795SPeter Avalos }
161*ba1276acSMatthew Dillon if (cp == NULL || *cp == '\0')
16236e94dc5SPeter Avalos fatal("No supported key exchange algorithms found");
163*ba1276acSMatthew Dillon debug2_f("compat KEX proposal: %s", cp);
164*ba1276acSMatthew Dillon return cp;
16518de8d7fSPeter Avalos }
16636e94dc5SPeter Avalos
167