compat.c revision 69587
1/*
2 * Copyright (c) 1999,2000 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"
26RCSID("$OpenBSD: compat.c,v 1.27 2000/10/31 09:31:58 markus Exp $");
27
28#include "ssh.h"
29#include "packet.h"
30#include "xmalloc.h"
31#include "compat.h"
32#include <regex.h>
33
34int compat13 = 0;
35int compat20 = 0;
36int datafellows = 0;
37
38void
39enable_compat20(void)
40{
41	verbose("Enabling compatibility mode for protocol 2.0");
42	compat20 = 1;
43}
44void
45enable_compat13(void)
46{
47	verbose("Enabling compatibility mode for protocol 1.3");
48	compat13 = 1;
49}
50/* datafellows bug compatibility */
51void
52compat_datafellows(const char *version)
53{
54	int i, ret;
55	char ebuf[1024];
56	regex_t reg;
57	static struct {
58		char	*pat;
59		int	bugs;
60	} check[] = {
61		{ "^OpenSSH[-_]2\\.[012]",	SSH_OLD_SESSIONID },
62		{ "MindTerm",		0 },
63		{ "^2\\.1\\.0 ",	SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
64					SSH_OLD_SESSIONID },
65		{ "^2\\.0\\.",		SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
66					SSH_OLD_SESSIONID|
67					SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD },
68		{ "^2\\.[23]\\.0 ",	SSH_BUG_HMAC},
69		{ "^2\\.[2-9]\\.",	0 },
70		{ "^2\\.4$",		SSH_OLD_SESSIONID}, /* Van Dyke */
71		{ "^3\\.0 SecureCRT",	SSH_OLD_SESSIONID},
72		{ "^1\\.7 SecureFX",	SSH_OLD_SESSIONID},
73		{ "^2\\.",		SSH_BUG_HMAC},	/* XXX fallback */
74		{ NULL,			0 }
75	};
76	/* process table, return first match */
77	for (i = 0; check[i].pat; i++) {
78		ret = regcomp(&reg, check[i].pat, REG_EXTENDED|REG_NOSUB);
79		if (ret != 0) {
80			regerror(ret, &reg, ebuf, sizeof(ebuf));
81			ebuf[sizeof(ebuf)-1] = '\0';
82			error("regerror: %s", ebuf);
83			continue;
84		}
85		ret = regexec(&reg, version, 0, NULL, 0);
86		regfree(&reg);
87		if (ret == 0) {
88			debug("match: %s pat %s\n", version, check[i].pat);
89			datafellows = check[i].bugs;
90			return;
91		}
92	}
93	debug("no match: %s", version);
94}
95
96#define	SEP	","
97int
98proto_spec(const char *spec)
99{
100	char *s, *p, *q;
101	int ret = SSH_PROTO_UNKNOWN;
102
103	if (spec == NULL)
104		return ret;
105	q = s = xstrdup(spec);
106	for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
107		switch(atoi(p)) {
108		case 1:
109			if (ret == SSH_PROTO_UNKNOWN)
110				ret |= SSH_PROTO_1_PREFERRED;
111			ret |= SSH_PROTO_1;
112			break;
113		case 2:
114			ret |= SSH_PROTO_2;
115			break;
116		default:
117			log("ignoring bad proto spec: '%s'.", p);
118			break;
119		}
120	}
121	xfree(s);
122	return ret;
123}
124