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