1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2008, 2009, 2010, 2011, 2012,
3 * 2013, 2019
4 * Inferno Nettverk A/S, Norway. 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. The above copyright notice, this list of conditions and the following
10 * disclaimer must appear in all copies of the software, derivative works
11 * or modified versions, and any portions thereof, aswell as in all
12 * supporting documentation.
13 * 2. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by
16 * Inferno Nettverk A/S, Norway.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Inferno Nettverk A/S requests users of this software to return to
32 *
33 * Software Distribution Coordinator or sdc@inet.no
34 * Inferno Nettverk A/S
35 * Oslo Research Park
36 * Gaustadall�en 21
37 * NO-0349 Oslo
38 * Norway
39 *
40 * any improvements or extensions that they make and grant Inferno Nettverk A/S
41 * the rights to redistribute these changes.
42 *
43 */
44
45 #include "common.h"
46
47 static const char rcsid[] =
48 "$Id: protocol.c,v 1.88.10.2 2020/11/11 16:11:54 karls Exp $";
49
50 unsigned char *
sockshost2mem(host,mem,version)51 sockshost2mem(host, mem, version)
52 const sockshost_t *host;
53 unsigned char *mem;
54 int version;
55 {
56
57 switch (version) {
58 case PROXY_SOCKS_V4:
59 case PROXY_SOCKS_V4REPLY_VERSION:
60 SASSERTX(host->atype == SOCKS_ADDR_IPV4);
61
62 /* DSTPORT */
63 memcpy(mem, &host->port, sizeof(host->port));
64 mem += sizeof(host->port);
65
66 /* DSTIP */
67 memcpy(mem, &host->addr.ipv4, sizeof(host->addr.ipv4));
68 mem += sizeof(host->addr.ipv4);
69
70 break;
71
72 case PROXY_SOCKS_V5:
73 /* ATYP */
74 memcpy(mem, &host->atype, sizeof(host->atype));
75 mem += sizeof(host->atype);
76
77 switch (host->atype) {
78 case SOCKS_ADDR_IPV4:
79 memcpy(mem, &host->addr.ipv4.s_addr,
80 sizeof(host->addr.ipv4.s_addr));
81 mem += sizeof(host->addr.ipv4.s_addr);
82 break;
83
84 case SOCKS_ADDR_IPV6:
85 memcpy(mem, &host->addr.ipv6.ip, sizeof(host->addr.ipv6.ip));
86 mem += sizeof(host->addr.ipv6.ip);
87 break;
88
89 case SOCKS_ADDR_DOMAIN:
90 /* first byte gives length of rest. */
91 *mem = (unsigned char)strlen(host->addr.domain);
92
93 memcpy(mem + 1, host->addr.domain, (size_t)*mem);
94 mem += *mem + 1;
95 break;
96
97 default:
98 SERRX(host->atype);
99 }
100
101 /* DST.PORT */
102 memcpy(mem, &host->port, sizeof(host->port));
103 mem += sizeof(host->port);
104
105 break;
106
107 default:
108 SERRX(version);
109 }
110
111 return mem;
112 }
113
114 const unsigned char *
mem2sockshost(host,mem,len,version)115 mem2sockshost(host, mem, len, version)
116 sockshost_t *host;
117 const unsigned char *mem;
118 size_t len;
119 int version;
120 {
121 const char *function = "mem2sockshost()";
122
123 switch (version) {
124 case PROXY_SOCKS_V5:
125 if (len < MINSOCKSHOSTLEN)
126 return NULL;
127
128 if (len < sizeof(host->atype))
129 return NULL;
130
131 memcpy(&host->atype, mem, sizeof(host->atype));
132 mem += sizeof(host->atype);
133 len -= sizeof(host->atype);
134
135 switch (host->atype) {
136 case SOCKS_ADDR_IPV4:
137 if (len < sizeof(host->addr.ipv4))
138 return NULL;
139
140 memcpy(&host->addr.ipv4, mem, sizeof(host->addr.ipv4));
141 mem += sizeof(host->addr.ipv4);
142 len -= sizeof(host->addr.ipv4);
143 break;
144
145 case SOCKS_ADDR_DOMAIN: {
146 size_t domainlen = (size_t)*mem;
147
148 mem += sizeof(*mem);
149
150 OCTETIFY(domainlen);
151
152 if (len < domainlen + 1) /* +1 for NUL to be added. */
153 return NULL;
154
155 SASSERTX(domainlen < sizeof(host->addr.domain));
156
157 memcpy(host->addr.domain, mem, domainlen);
158 host->addr.domain[domainlen] = NUL;
159 mem += domainlen;
160 len -= domainlen + 1; /* +1 for added NUL. */
161 break;
162 }
163
164 case SOCKS_ADDR_IPV6:
165 if (len < sizeof(host->addr.ipv6.ip))
166 return NULL;
167
168 memcpy(&host->addr.ipv6.ip, mem, sizeof(host->addr.ipv6.ip));
169 mem += sizeof(host->addr.ipv6.ip);
170 len -= sizeof(host->addr.ipv6.ip);
171
172 host->addr.ipv6.scopeid = 0;
173
174 break;
175
176 default:
177 slog(LOG_NEGOTIATE, "%s: unknown atype value: %d",
178 function, host->atype);
179 return NULL;
180 }
181
182 if (len < sizeof(host->port))
183 return NULL;
184
185 memcpy(&host->port, mem, sizeof(host->port));
186 mem += sizeof(host->port);
187 len -= sizeof(host->port);
188
189 break;
190
191 default:
192 SERRX(version);
193 }
194
195 return mem;
196 }
197
198 void
socks_set_responsevalue(response,value)199 socks_set_responsevalue(response, value)
200 response_t *response;
201 unsigned int value;
202 {
203
204 switch (response->version) {
205 case PROXY_SOCKS_V4REPLY_VERSION:
206 case PROXY_SOCKS_V5:
207 response->reply.socks = (unsigned char)value;
208 break;
209
210 case PROXY_UPNP:
211 response->reply.upnp = (unsigned char)value;
212 break;
213
214 case PROXY_HTTP_10:
215 case PROXY_HTTP_11:
216 response->reply.http = (unsigned short)value;
217 break;
218
219 default:
220 SERRX(response->version);
221 }
222 }
223
224 unsigned int
socks_get_responsevalue(response)225 socks_get_responsevalue(response)
226 const response_t *response;
227 {
228
229 switch (response->version) {
230 case PROXY_SOCKS_V4REPLY_VERSION:
231 case PROXY_SOCKS_V5:
232 return response->reply.socks;
233
234 case PROXY_UPNP:
235 return response->reply.upnp;
236
237 case PROXY_HTTP_10:
238 case PROXY_HTTP_11:
239 return response->reply.http;
240
241 default:
242 SERRX(response->version);
243 }
244
245 /* NOTREACHED */
246 }
247
248 int
proxyprotocolisknown(version)249 proxyprotocolisknown(version)
250 const int version;
251 {
252
253 switch (version) {
254 /* don't include PROXY_SOCKS_V4REPLY_VERSION. Stupid thing set to 0. */
255 case PROXY_SOCKS_V4:
256 case PROXY_SOCKS_V5:
257 case PROXY_UPNP:
258 case PROXY_HTTP_10:
259 case PROXY_HTTP_11:
260 return 1;
261
262 default:
263 return 0;
264 }
265 }
266
267 int
authmethodisknown(method)268 authmethodisknown(method)
269 const int method;
270 {
271
272 switch (method) {
273 case AUTHMETHOD_NOTSET:
274 case AUTHMETHOD_NONE:
275 case AUTHMETHOD_GSSAPI:
276 case AUTHMETHOD_UNAME:
277 case AUTHMETHOD_NOACCEPT:
278 case AUTHMETHOD_RFC931:
279 case AUTHMETHOD_PAM_ANY:
280 case AUTHMETHOD_PAM_ADDRESS:
281 case AUTHMETHOD_PAM_USERNAME:
282 case AUTHMETHOD_BSDAUTH:
283 #if HAVE_LDAP
284 case AUTHMETHOD_LDAPAUTH:
285 #endif /* HAVE_LDAP */
286 return 1;
287
288 default:
289 return 0;
290 }
291 }
292
293 int *
charmethod2intmethod(methodc,charmethodv,intmethodv)294 charmethod2intmethod(methodc, charmethodv, intmethodv)
295 const size_t methodc;
296 const unsigned char charmethodv[];
297 int intmethodv[];
298 {
299 size_t i;
300
301 for (i = 0; i < methodc; ++i)
302 intmethodv[i] = (int)charmethodv[i];
303
304 return intmethodv;
305 }
306