1*b1066cf3Schristos /* $NetBSD: compat.c,v 1.26 2023/07/26 17:58:15 christos Exp $ */
2*b1066cf3Schristos /* $OpenBSD: compat.c,v 1.126 2023/03/06 12:14:48 dtucker Exp $ */
3ca32bd8dSchristos /*
4ca32bd8dSchristos * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
5ca32bd8dSchristos *
6ca32bd8dSchristos * Redistribution and use in source and binary forms, with or without
7ca32bd8dSchristos * modification, are permitted provided that the following conditions
8ca32bd8dSchristos * are met:
9ca32bd8dSchristos * 1. Redistributions of source code must retain the above copyright
10ca32bd8dSchristos * notice, this list of conditions and the following disclaimer.
11ca32bd8dSchristos * 2. Redistributions in binary form must reproduce the above copyright
12ca32bd8dSchristos * notice, this list of conditions and the following disclaimer in the
13ca32bd8dSchristos * documentation and/or other materials provided with the distribution.
14ca32bd8dSchristos *
15ca32bd8dSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16ca32bd8dSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17ca32bd8dSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18ca32bd8dSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19ca32bd8dSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20ca32bd8dSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21ca32bd8dSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22ca32bd8dSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23ca32bd8dSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24ca32bd8dSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25ca32bd8dSchristos */
26ca32bd8dSchristos
27313c6c94Schristos #include "includes.h"
28*b1066cf3Schristos __RCSID("$NetBSD: compat.c,v 1.26 2023/07/26 17:58:15 christos Exp $");
29ca32bd8dSchristos #include <sys/types.h>
30ca32bd8dSchristos
31ca32bd8dSchristos #include <stdlib.h>
32ca32bd8dSchristos #include <string.h>
33ca32bd8dSchristos #include <stdarg.h>
34ca32bd8dSchristos
35ca32bd8dSchristos #include "xmalloc.h"
36ca32bd8dSchristos #include "packet.h"
37ca32bd8dSchristos #include "compat.h"
38ca32bd8dSchristos #include "log.h"
39ca32bd8dSchristos #include "match.h"
40ca32bd8dSchristos
4117418e98Schristos /* determine bug flags from SSH protocol banner */
4217418e98Schristos void
compat_banner(struct ssh * ssh,const char * version)4317418e98Schristos compat_banner(struct ssh *ssh, const char *version)
44ca32bd8dSchristos {
45ca32bd8dSchristos int i;
46ca32bd8dSchristos static struct {
47185c8f97Schristos const char *pat;
48ca32bd8dSchristos int bugs;
49ca32bd8dSchristos } check[] = {
50ca32bd8dSchristos { "OpenSSH_2.*,"
51ca32bd8dSchristos "OpenSSH_3.0*,"
5255a4608bSchristos "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
5355a4608bSchristos SSH_BUG_SIGTYPE},
5455a4608bSchristos { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE },
5555a4608bSchristos { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
5655a4608bSchristos SSH_BUG_SIGTYPE},
57ffae97bbSchristos { "OpenSSH_2*,"
58ffae97bbSchristos "OpenSSH_3*,"
5955a4608bSchristos "OpenSSH_4*", SSH_BUG_SIGTYPE },
6055a4608bSchristos { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT|
6155a4608bSchristos SSH_BUG_SIGTYPE},
6255a4608bSchristos { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
638a4530f9Schristos { "OpenSSH_6.5*,"
6455a4608bSchristos "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
6555a4608bSchristos SSH_BUG_SIGTYPE},
66b592f463Schristos { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE|
67b592f463Schristos SSH_BUG_SIGTYPE74},
6855a4608bSchristos { "OpenSSH_7.0*,"
6955a4608bSchristos "OpenSSH_7.1*,"
7055a4608bSchristos "OpenSSH_7.2*,"
7155a4608bSchristos "OpenSSH_7.3*,"
7255a4608bSchristos "OpenSSH_7.5*,"
7355a4608bSchristos "OpenSSH_7.6*,"
7455a4608bSchristos "OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
75ca32bd8dSchristos { "OpenSSH*", SSH_NEW_OPENSSH },
76ca32bd8dSchristos { "*MindTerm*", 0 },
77ca32bd8dSchristos { "3.0.*", SSH_BUG_DEBUG },
78ca32bd8dSchristos { "3.0 SecureCRT*", SSH_OLD_SESSIONID },
79ca32bd8dSchristos { "1.7 SecureFX*", SSH_OLD_SESSIONID },
808395c133Schristos { "Cisco-1.*", SSH_BUG_DHGEX_LARGE|
818395c133Schristos SSH_BUG_HOSTKEYS },
82ca32bd8dSchristos { "*SSH_Version_Mapper*",
83ca32bd8dSchristos SSH_BUG_SCANNER },
848395c133Schristos { "PuTTY_Local:*," /* dev versions < Sep 2014 */
858395c133Schristos "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
864054ffb0Schristos "PuTTY_Release_0.5*," /* 0.58-0.59 */
874054ffb0Schristos "PuTTY_Release_0.60*,"
884054ffb0Schristos "PuTTY_Release_0.61*,"
894054ffb0Schristos "PuTTY_Release_0.62*,"
904054ffb0Schristos "PuTTY_Release_0.63*,"
914054ffb0Schristos "PuTTY_Release_0.64*",
924054ffb0Schristos SSH_OLD_DHGEX },
93b1c8f1c6Schristos { "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */
94ca32bd8dSchristos { "Probe-*",
95ca32bd8dSchristos SSH_BUG_PROBE },
964054ffb0Schristos { "TeraTerm SSH*,"
974054ffb0Schristos "TTSSH/1.5.*,"
984054ffb0Schristos "TTSSH/2.1*,"
994054ffb0Schristos "TTSSH/2.2*,"
1004054ffb0Schristos "TTSSH/2.3*,"
1014054ffb0Schristos "TTSSH/2.4*,"
1024054ffb0Schristos "TTSSH/2.5*,"
1034054ffb0Schristos "TTSSH/2.6*,"
1044054ffb0Schristos "TTSSH/2.70*,"
1054054ffb0Schristos "TTSSH/2.71*,"
1064054ffb0Schristos "TTSSH/2.72*", SSH_BUG_HOSTKEYS },
107b1c8f1c6Schristos { "WinSCP_release_4*,"
108b1c8f1c6Schristos "WinSCP_release_5.0*,"
1097a183406Schristos "WinSCP_release_5.1,"
1107a183406Schristos "WinSCP_release_5.1.*,"
1117a183406Schristos "WinSCP_release_5.5,"
1127a183406Schristos "WinSCP_release_5.5.*,"
1137a183406Schristos "WinSCP_release_5.6,"
1147a183406Schristos "WinSCP_release_5.6.*,"
115b1c8f1c6Schristos "WinSCP_release_5.7,"
116b1c8f1c6Schristos "WinSCP_release_5.7.1,"
117b1c8f1c6Schristos "WinSCP_release_5.7.2,"
118b1c8f1c6Schristos "WinSCP_release_5.7.3,"
119b1c8f1c6Schristos "WinSCP_release_5.7.4",
120b1c8f1c6Schristos SSH_OLD_DHGEX },
121ffae97bbSchristos { "ConfD-*",
122ffae97bbSchristos SSH_BUG_UTF8TTYMODE },
12355a4608bSchristos { "Twisted_*", 0 },
12455a4608bSchristos { "Twisted*", SSH_BUG_DEBUG },
125ca32bd8dSchristos { NULL, 0 }
126ca32bd8dSchristos };
127ca32bd8dSchristos
128ca32bd8dSchristos /* process table, return first match */
12917418e98Schristos ssh->compat = 0;
130ca32bd8dSchristos for (i = 0; check[i].pat; i++) {
1314054ffb0Schristos if (match_pattern_list(version, check[i].pat, 0) == 1) {
13217418e98Schristos debug_f("match: %s pat %s compat 0x%08x",
133e4d43b82Schristos version, check[i].pat, check[i].bugs);
13417418e98Schristos ssh->compat = check[i].bugs;
13517418e98Schristos return;
136313c6c94Schristos }
137313c6c94Schristos }
13817418e98Schristos debug_f("no match: %s", version);
139ca32bd8dSchristos }
140ca32bd8dSchristos
141e160b4e8Schristos /* Always returns pointer to allocated memory, caller must free. */
142e160b4e8Schristos char *
compat_kex_proposal(struct ssh * ssh,const char * p)143*b1066cf3Schristos compat_kex_proposal(struct ssh *ssh, const char *p)
1448a4530f9Schristos {
145*b1066cf3Schristos char *cp = NULL, *cp2 = NULL;
146e160b4e8Schristos
14717418e98Schristos if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
148e160b4e8Schristos return xstrdup(p);
14917418e98Schristos debug2_f("original KEX proposal: %s", p);
15017418e98Schristos if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
151*b1066cf3Schristos if ((cp = match_filter_denylist(p,
15241768fc1Schristos "curve25519-sha256@libssh.org")) == NULL)
1532d3b0f52Schristos fatal("match_filter_denylist failed");
15417418e98Schristos if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
155*b1066cf3Schristos if ((cp2 = match_filter_denylist(cp ? cp : p,
15641768fc1Schristos "diffie-hellman-group-exchange-sha256,"
15741768fc1Schristos "diffie-hellman-group-exchange-sha1")) == NULL)
1582d3b0f52Schristos fatal("match_filter_denylist failed");
159e160b4e8Schristos free(cp);
160*b1066cf3Schristos cp = cp2;
1614054ffb0Schristos }
162*b1066cf3Schristos if (cp == NULL || *cp == '\0')
1638a4530f9Schristos fatal("No supported key exchange algorithms found");
164*b1066cf3Schristos debug2_f("compat KEX proposal: %s", cp);
165*b1066cf3Schristos return cp;
1668a4530f9Schristos }
1678a4530f9Schristos
168