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