1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2005, 2008, 2009, 2010,
3 * 2011, 2012, 2013, 2014, 2016, 2019, 2020
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: config.c,v 1.464.4.2.2.3.4.11 2020/11/11 17:02:23 karls Exp $";
49
50 void
genericinit(void)51 genericinit(void)
52 {
53 const char *function = "genericinit()";
54 #if BAREFOOTD
55 rule_t *rule;
56 #endif /* BAREFOOTD */
57 #if !SOCKS_CLIENT
58 sigset_t set, oset;
59 #endif /* !SOCKS_CLIENT */
60
61 #if SOCKS_CLIENT
62 SASSERTX(sockscf.loglock == -1);
63 #else /* !SOCKS_CLIENT */
64 if (sockscf.loglock == -1) {
65 if ((sockscf.loglock = socks_mklock(SOCKS_LOCKFILE, NULL, 0)) == -1)
66 serr("%s: socks_mklock() failed to create lockfile using base %s",
67 function, SOCKS_LOCKFILE);
68 }
69 #endif /* !SOCKS_CLIENT */
70
71 if (!sockscf.state.inited) {
72 #if !HAVE_SETPROCTITLE
73 /* create a backup to avoid setproctitle replacement overwriting it. */
74 if ((__progname = strdup(__progname)) == NULL)
75 serrx("%s: %s", function, NOMEM);
76 #endif /* !HAVE_SETPROCTITLE */
77 }
78
79 #if !SOCKS_CLIENT
80 sigemptyset(&set);
81 sigaddset(&set, SIGHUP);
82 sigaddset(&set, SIGTERM);
83 if (sigprocmask(SIG_BLOCK, &set, &oset) != 0)
84 swarn("%s: sigprocmask(SIG_BLOCK)", function);
85 #endif /* !SOCKS_CLIENT */
86
87 optioninit();
88
89 if (parseconfig(sockscf.option.configfile) != 0)
90 return;
91
92 #if !SOCKS_CLIENT
93 if (sigprocmask(SIG_SETMASK, &oset, NULL) != 0)
94 swarn("%s: sigprocmask(SIG_SETMASK)", function);
95 #endif /* !SOCKS_CLIENT */
96
97 postconfigloadinit();
98
99 #if BAREFOOTD
100 rule = sockscf.crule;
101 while (rule != NULL) {
102 if (rule->state.protocol.udp) {
103 sockscf.state.alludpbounced = 0;
104 break;
105 }
106
107 rule = rule->next;
108 }
109 #endif /* BAREFOOTD */
110
111 #if SOCKSLIBRARY_DYNAMIC
112 symbolcheck();
113 #endif /* SOCKSLIBRARY_DYNAMIC */
114 }
115
116 void
postconfigloadinit(void)117 postconfigloadinit(void)
118 {
119 const char *function = "postconfigloadinit()";
120 #if !SOCKS_CLIENT
121 cpusetting_t newcpu;
122 void (*procfunc)(void);
123 #endif /* !SOCKS_CLIENT */
124
125 slog(LOG_DEBUG, "%s: I am a %s",
126 function,
127 #if SOCKS_CLIENT
128 "client"
129 #else /* !SOCKS_CLIENT */
130 childtype2string(sockscf.state.type)
131 #endif /* !SOCKS_CLIENT */
132 );
133
134 #if !HAVE_NO_RESOLVESTUFF
135 if (!(_res.options & RES_INIT)) {
136 res_init();
137
138 #if !SOCKS_CLIENT
139 sockscf.initial.res_options = _res.options;
140 #endif /* !SOCKS_CLIENT */
141 }
142 #endif /* !HAVE_NO_RESOLVSTUFF */
143
144 switch (sockscf.resolveprotocol) {
145 case RESOLVEPROTOCOL_TCP:
146 #if HAVE_NO_RESOLVESTUFF
147 SERRX(sockscf.resolveprotocol);
148
149 #else /* !HAVE_NO_RESOLVESTUFF */
150 _res.options |= RES_USEVC;
151 slog(LOG_DEBUG,
152 "%s: configured resolver for resolving over tcp", function);
153 #endif /* HAVE_NO_RESOLVESTUFF */
154
155 break;
156
157 case RESOLVEPROTOCOL_UDP:
158 case RESOLVEPROTOCOL_FAKE:
159 break;
160
161 default:
162 SERRX(sockscf.resolveprotocol);
163 }
164
165 #if !HAVE_NO_RESOLVESTUFF && 0
166 _res.options |= RES_DEBUG;
167 slog(LOG_DEBUG, "%s: configured resolver for debugging", function);
168 #endif /* !HAVE_NO_RESOLVESTUFF && 0 */
169
170 #if !SOCKS_CLIENT
171
172 switch (sockscf.state.type) {
173 case PROC_MOTHER:
174 newcpu = sockscf.cpu.mother;
175 procfunc = mother_postconfigload;
176 break;
177
178 case PROC_MONITOR:
179 newcpu = sockscf.cpu.monitor;
180 procfunc = monitor_postconfigload;
181 break;
182
183 case PROC_NEGOTIATE:
184 newcpu = sockscf.cpu.negotiate;
185 procfunc = negotiate_postconfigload;
186 break;
187
188 case PROC_REQUEST:
189 newcpu = sockscf.cpu.request;
190 procfunc = request_postconfigload;
191 break;
192
193 case PROC_IO:
194 newcpu = sockscf.cpu.io;
195 procfunc = io_postconfigload;
196 break;
197
198 default:
199 SERRX(sockscf.state.type);
200 }
201
202 #if HAVE_SCHED_SETSCHEDULER
203 if (!newcpu.scheduling_isset) {
204 newcpu.policy = sockscf.initial.cpu.policy;
205 newcpu.param = sockscf.initial.cpu.param;
206 newcpu.scheduling_isset = sockscf.initial.cpu.scheduling_isset;
207 }
208 #endif /* HAVE_SCHED_SETSCHEDULER */
209
210 #if HAVE_SCHED_SETAFFINITY
211 if (!newcpu.affinity_isset) {
212 newcpu.mask = sockscf.initial.cpu.mask;
213 newcpu.affinity_isset = sockscf.initial.cpu.affinity_isset;
214 }
215 #endif /* HAVE_SCHED_SETAFFINITY */
216
217 if (!sockscf.option.verifyonly)
218 sockd_setcpusettings(&sockscf.state.cpu, &newcpu);
219
220 #if HAVE_SCHED_SETSCHEDULER
221 /*
222 * does not work on FreeBSD version 8.2 (only one checked).
223 * For some reason the sched_priority, as returned by sched_getparam(2),
224 * after we receive a signal (e.g. SIGHUP) is not the same it was before
225 * the signal, as well as other weirdness. There are some bug-reports
226 * related to what looks similar e.g.: kern/157657. That bug has apparently
227 * been fixed in in a commit in June 2011, after the FreeBSD 8.2 release
228 * running on our testmachine.
229 */
230 struct sched_param param;
231
232 SASSERTX(sockscf.state.cpu.policy == sched_getscheduler(0));
233 SASSERTX(sched_getparam(0, ¶m) == 0);
234 SASSERTX(sockscf.state.cpu.param.sched_priority == param.sched_priority);
235 #endif /* HAVE_SCHED_SETSCHEDULER */
236
237 if (procfunc != NULL)
238 procfunc();
239 #endif /* !SOCKS_CLIENT */
240 }
241
242
243 route_t *
socks_addroute(newroute,last)244 socks_addroute(newroute, last)
245 const route_t *newroute;
246 const int last;
247 {
248 const char *function = "socks_addroute()";
249 serverstate_t nilstate;
250 route_t *route, *nextroute;
251 size_t i, ifb, isoneshot;
252
253 if ((route = malloc(sizeof(*route))) == NULL)
254 yyerrorx("could not allocate %lu bytes for route",
255 (unsigned long)sizeof(*nextroute));
256
257 *route = *newroute;
258 bzero(&nilstate, sizeof(nilstate));
259
260 if (route->gw.state.proxyprotocol.upnp) {
261 if (route->gw.addr.atype == SOCKS_ADDR_DOMAIN
262 && strcmp(route->gw.addr.addr.domain, PROXY_BROADCASTs) == 0)
263 ;
264 else {
265 if (route->gw.addr.atype != SOCKS_ADDR_IFNAME
266 && route->gw.addr.atype != SOCKS_ADDR_URL)
267 yyerrorx("gateway for upnp proxy has to be an interface or url. "
268 "The %s %s is not a valid gateway",
269 atype2string(route->gw.addr.atype),
270 sockshost2string(&route->gw.addr, NULL, 0));
271
272 if (route->gw.addr.port == htons(0)) {
273 if (route->gw.addr.atype != SOCKS_ADDR_URL) {
274 slog(LOG_DEBUG, "%s: upnp gw port not set, using default (%d)",
275 function, DEFAULT_SSDP_PORT);
276
277 route->gw.addr.port = htons(DEFAULT_SSDP_PORT);
278 }
279 }
280 else if (route->gw.addr.port != htons(DEFAULT_SSDP_PORT))
281 yyerrorx("sorry, the upnp library %s is tested with does"
282 "not support setting the upnp/ssdp port",
283 PRODUCT);
284 }
285 }
286 else {
287 switch (route->gw.addr.atype) {
288 case SOCKS_ADDR_IPV4:
289 #if !SOCKS_CLIENT
290 case SOCKS_ADDR_IPV6:
291 #endif /* !SOCKS_CLIENT */
292 break;
293
294 case SOCKS_ADDR_DOMAIN:
295 if (memcmp(&nilstate.proxyprotocol,
296 &route->gw.state.proxyprotocol,
297 sizeof(nilstate.proxyprotocol)) == 0) {
298 if (strcmp(route->gw.addr.addr.domain, PROXY_DIRECTs) == 0)
299 route->gw.state.proxyprotocol.direct = 1;
300 else if (strcmp(route->gw.addr.addr.domain, PROXY_BROADCASTs)
301 == 0)
302 route->gw.state.proxyprotocol.upnp = 1;
303 }
304 break;
305
306 default:
307 yyerrorx("gateway must be an IP-address or qualified domainname, "
308 "but type of %s is %s",
309 sockshost2string(&route->gw.addr, NULL, 0),
310 atype2string(route->gw.addr.atype));
311 }
312 }
313
314 /* if no proxy protocol set, set socks v4 and v5. */
315 if (memcmp(&nilstate.proxyprotocol, &route->gw.state.proxyprotocol,
316 sizeof(nilstate.proxyprotocol)) == 0) {
317 memset(&route->gw.state.proxyprotocol, 0,
318 sizeof(route->gw.state.proxyprotocol));
319
320 route->gw.state.proxyprotocol.socks_v4 = 1;
321 route->gw.state.proxyprotocol.socks_v5 = 1;
322 }
323 else { /* proxy protocol set, do they make sense? */
324 proxyprotocol_t proxy;
325
326 if (route->gw.state.proxyprotocol.socks_v4
327 || route->gw.state.proxyprotocol.socks_v5) {
328 if (route->gw.state.proxyprotocol.http
329 || route->gw.state.proxyprotocol.upnp)
330 yyerrorx("%s: cannot combine proxyprotocol socks with other "
331 "proxyprotocols",
332 function);
333 }
334 else if (route->gw.state.proxyprotocol.http) {
335 memset(&proxy, 0, sizeof(proxy));
336 proxy.http = 1;
337
338 if (memcmp(&proxy, &route->gw.state.proxyprotocol, sizeof(proxy)) != 0)
339 yyerrorx("%s: cannot combine proxyprotocol http with other "
340 "proxyprotocols",
341 function);
342 }
343 else if (route->gw.state.proxyprotocol.upnp) {
344 #if !HAVE_LIBMINIUPNP
345 serrx("%s: not configured for using upnp", function);
346 #else /* HAVE_LIBMINIUPNP */
347
348 memset(&proxy, 0, sizeof(proxy));
349 proxy.upnp = 1;
350
351 if (memcmp(&proxy, &route->gw.state.proxyprotocol, sizeof(proxy)) != 0)
352 yyerrorx("%s: cannot combine proxyprotocol upnp with other "
353 "proxyprotocols",
354 function);
355 #endif /* HAVE_LIBMINIUPNP */
356 }
357 }
358
359 if (route->gw.addr.port == htons(0)) { /* no port, set default if known. */
360 if (route->gw.state.proxyprotocol.socks_v4
361 || route->gw.state.proxyprotocol.socks_v5)
362 route->gw.addr.port = htons((in_port_t)SOCKD_PORT);
363
364 else if (route->gw.state.proxyprotocol.http)
365 route->gw.addr.port = htons((in_port_t)SOCKD_HTTP_PORT);
366 }
367
368 if (memcmp(&nilstate.command, &route->gw.state.command,
369 sizeof(nilstate.command)) == 0) {
370 if (route->gw.state.proxyprotocol.direct) {
371 #if SOCKS_CLIENT
372 route->gw.state.command.udpassociate = 1;
373 route->gw.state.command.udpreply = 1;
374 #endif /* SOCKS_CLIENT */
375 route->gw.state.command.connect = 1;
376
377 /*
378 * in a normal client configuration, it makes more sense
379 * to not enable bind for direct routes, unless the user
380 * explicitly enables it.
381 * If not, bind(2) will always be local, which in most
382 * cases is probably not what the user wanted, even
383 * though he implied it by not specifying what commands
384 * the direct route should handle, meaning "all".
385 */
386 route->gw.state.command.bind = 0;
387 route->gw.state.command.bindreply = 0;
388 }
389
390 /*
391 * Now go through the proxy protocol(s) supported by this route,
392 * and enable the appropriate protocols and commands, if the
393 * user has not already done so.
394 */
395 if (route->gw.state.proxyprotocol.socks_v5) {
396 #if SOCKS_CLIENT
397 route->gw.state.command.udpassociate = 1;
398 route->gw.state.command.udpreply = 1;
399 route->gw.state.command.bind = 1;
400 route->gw.state.command.bindreply = 1;
401 #endif /* SOCKS_CLIENT */
402 route->gw.state.command.connect = 1;
403 }
404
405 if (route->gw.state.proxyprotocol.socks_v4) {
406 #if SOCKS_CLIENT
407 route->gw.state.command.bind = 1;
408 route->gw.state.command.bindreply = 1;
409 #endif /* SOCKS_CLIENT */
410 route->gw.state.command.connect = 1;
411 }
412
413 if (route->gw.state.proxyprotocol.http) {
414 route->gw.state.command.connect = 1;
415 }
416
417 if (route->gw.state.proxyprotocol.upnp) {
418 #if SOCKS_CLIENT
419 route->gw.state.command.udpassociate = 1;
420 route->gw.state.command.udpreply = 1;
421 route->gw.state.command.bind = 1;
422 route->gw.state.command.bindreply = 1;
423 #endif /* SOCKS_CLIENT */
424 route->gw.state.command.connect = 1;
425 }
426
427 }
428 #if !SOCKS_CLIENT
429 else {
430 if (!route->gw.state.proxyprotocol.direct) {
431 if (route->gw.state.command.bind
432 || route->gw.state.command.bindreply
433 || route->gw.state.command.udpassociate
434 || route->gw.state.command.udpreply
435 || route->gw.state.protocol.udp)
436 yyerrorx("serverchaining only supported for the connect command");
437 }
438 }
439 #endif /* !SOCKS_CLIENT */
440
441 if (memcmp(&nilstate.protocol, &route->gw.state.protocol,
442 sizeof(nilstate.protocol)) == 0) {
443 if (route->gw.state.proxyprotocol.direct) {
444 route->gw.state.protocol.udp = 1;
445 route->gw.state.protocol.tcp = 1;
446 }
447
448 if (route->gw.state.proxyprotocol.socks_v5) {
449 #if SOCKS_CLIENT
450 route->gw.state.protocol.udp = 1;
451 #endif /* SOCKS_CLIENT */
452 route->gw.state.protocol.tcp = 1;
453 }
454
455 if (route->gw.state.proxyprotocol.socks_v4)
456 route->gw.state.protocol.tcp = 1;
457
458 if (route->gw.state.proxyprotocol.http)
459 route->gw.state.protocol.tcp = 1;
460
461 if (route->gw.state.proxyprotocol.upnp) {
462 #if SOCKS_CLIENT
463 route->gw.state.protocol.udp = 1;
464 #endif /* SOCKS_CLIENT */
465 route->gw.state.protocol.tcp = 1;
466 }
467 }
468
469 #if HAVE_GSSAPI
470 /*
471 * if no gssapienctype set, or only nec-compatibility set,
472 * set all except per-message.
473 */
474 if (route->gw.state.gssapiencryption.clear == 0
475 && route->gw.state.gssapiencryption.integrity == 0
476 && route->gw.state.gssapiencryption.confidentiality == 0
477 && route->gw.state.gssapiencryption.permessage == 0) {
478 route->gw.state.gssapiencryption.integrity = 1;
479 route->gw.state.gssapiencryption.confidentiality = 1;
480 route->gw.state.gssapiencryption.permessage = 0;
481 }
482
483 /* if no gssapiservicename set, set to default. */
484 if (strcmp((char *)&nilstate.gssapiservicename,
485 (char *)&route->gw.state.gssapiservicename) == 0)
486 STRCPY_ASSERTSIZE(route->gw.state.gssapiservicename,
487 DEFAULT_GSSAPISERVICENAME);
488
489 /* if no gssapiservicename set, set to default. */
490 if (strcmp((char *)&nilstate.gssapikeytab,
491 (char *)&route->gw.state.gssapikeytab) == 0)
492 STRCPY_ASSERTSIZE(route->gw.state.gssapikeytab, DEFAULT_GSSAPIKEYTAB);
493 #endif /* HAVE_GSSAPI */
494
495 /* if no method is set, set all we support for the proxyprotocols. */
496 if (route->gw.state.smethodc == 0) {
497 int *methodv = route->gw.state.smethodv;
498 size_t *methodc = &route->gw.state.smethodc;
499
500 /* all proxyprotocols support this. */
501 methodv[(*methodc)++] = AUTHMETHOD_NONE;
502
503 #if SOCKS_CLIENT
504 /*
505 * currently only supported for routes in the client, not for
506 * serverchaining.
507 */
508
509 #if HAVE_GSSAPI
510 if (route->gw.state.proxyprotocol.socks_v5)
511 methodv[(*methodc)++] = AUTHMETHOD_GSSAPI;
512 #endif /* HAVE_GSSAPI */
513
514 #endif /* SOCKS_CLIENT */
515
516 #if SOCKS_CLIENT
517 /*
518 * If it's a socks_v5 route, we could set AUTMHETHOD_UNAME in the
519 * server case also, but that means we forward the clients password
520 * to an upstream proxy.
521 * Don't do that by default, but insist the operator configures
522 * this route as such if he really wants us to do that.
523 */
524 if (route->gw.state.proxyprotocol.socks_v5)
525 methodv[(*methodc)++] = AUTHMETHOD_UNAME;
526 #endif
527 }
528
529 /* Checks the methods set make sense for the given proxy protocols. */
530 for (i = 0; i < route->gw.state.smethodc; ++i)
531 switch (route->gw.state.smethodv[i]) {
532 case AUTHMETHOD_NONE:
533 break;
534
535 #if !SOCKS_CLIENT
536
537 case AUTHMETHOD_GSSAPI:
538 yyerrorx("sorry, %s authentication is not supported for "
539 "serverchaining",
540 method2string(route->gw.state.smethodv[i]));
541
542 #else /* SOCKS_CLIENT */
543
544 case AUTHMETHOD_GSSAPI:
545
546 #endif /* SOCKS_CLIENT */
547
548 case AUTHMETHOD_UNAME:
549 if (!route->gw.state.proxyprotocol.socks_v5)
550 yyerrorx("rule specifies method %s, but that is not supported "
551 "by the specified proxy protocol(s): %s",
552 method2string(route->gw.state.smethodv[i]),
553 proxyprotocols2string(&route->gw.state.proxyprotocol,
554 NULL,
555 0));
556
557 #if !SOCKS_CLIENT
558 if (route->gw.state.smethodv[i] == AUTHMETHOD_UNAME) {
559 size_t j, have_username_methods;
560
561
562 have_username_methods = 0;
563 for (j = 0; j < sockscf.smethodc; ++j) {
564 if (methodcanprovide(sockscf.smethodv[j], username)) {
565 have_username_methods = 1;
566 break;
567 }
568 }
569
570 if (!have_username_methods)
571 yyerrorx("route specifies method %s in the proxychain "
572 "route, but that can't work because no methods "
573 "that can provide a username are set in the "
574 "global socksmethod list; no client using "
575 "username/password authentication will ever be "
576 "accepted by us",
577 method2string(route->gw.state.smethodv[i]));
578
579 yylog(LOG_NOTICE,
580 "this serverchain route specifies authmethod %s, "
581 "indicating that we should forward username/password-"
582 "credentials received by our own user to an upstream "
583 "proxy. Unless the upstream proxy is also under your "
584 "control, this may not be what you want to do",
585 method2string(route->gw.state.smethodv[i]));
586 }
587 #endif /* !SOCKS_CLIENT */
588
589 break;
590
591 case AUTHMETHOD_BSDAUTH:
592 case AUTHMETHOD_PAM_ANY:
593 case AUTHMETHOD_PAM_ADDRESS:
594 case AUTHMETHOD_PAM_USERNAME:
595 case AUTHMETHOD_LDAPAUTH:
596 case AUTHMETHOD_RFC931:
597 yyerrorx("method %s is only valid for ACL rules",
598 method2string(route->gw.state.smethodv[i]));
599 break; /* NOTREACHED */
600
601 default:
602 SERRX(route->gw.state.smethodv[i]);
603 }
604
605 if (route->src.atype == SOCKS_ADDR_IFNAME)
606 yyerrorx("interface names not supported for src address");
607
608 #if SOCKS_CLIENT
609 if (route->rdr_from.atype == SOCKS_ADDR_IPV4) {
610 if (route->rdr_from.addr.ipv4.mask.s_addr != htonl(IPV4_FULLNETMASK))
611 yyerror("netmask for redirect from address must be %d, not %d",
612 IPV4_FULLNETMASK,
613 bitcount((unsigned long)route->rdr_from.addr.ipv4.mask.s_addr));
614 }
615
616 if (route->rdr_from.atype == SOCKS_ADDR_IPV6) {
617 if (route->rdr_from.addr.ipv6.maskbits != IPV6_NETMASKBITS)
618 yyerror("netmask for redirect from address must be %d, not %d",
619 IPV6_NETMASKBITS, route->rdr_from.addr.ipv6.maskbits);
620 }
621 #endif /* SOCKS_CLIENT */
622
623 isoneshot = (route->dst.atype == SOCKS_ADDR_IFNAME ? 0 : 1);
624 ifb = 0;
625 nextroute = NULL;
626 while (1) {
627 /*
628 * This needs to be a loop to handle the case where route->dst
629 * expands to multiple ip addresses, which can happen when it is
630 * e.g. a ifname with several addresses configured on it. In that
631 * case want to add almost identical routes for all the addresses
632 * configured on the interface, with the only difference being
633 * the "dst" field (one dst for each address/mask on the interface).
634 */
635 struct sockaddr_storage addr, mask;
636
637 if (route->dst.atype == SOCKS_ADDR_IFNAME) {
638 if (ifname2sockaddr(route->dst.addr.ifname, ifb, &addr, &mask)
639 == NULL) {
640 if (ifb == 0) {
641 char visbuf[MAXIFNAMELEN * 4];
642
643 yyerrorx("could not create route with destination interface %s: "
644 "no addresses found on interface",
645 str2vis(route->dst.addr.ifname,
646 strlen(route->dst.addr.ifname),
647 visbuf,
648 sizeof(visbuf)));
649 }
650
651 break; /* no more addresses on this interface. */
652 }
653 }
654
655 if (nextroute == NULL)
656 nextroute = route; /* first iteration. */
657 else {
658 if ((nextroute = malloc(sizeof(*nextroute))) == NULL)
659 yyerrorx("could not allocate %lu bytes for route",
660 (unsigned long)sizeof(*nextroute));
661
662 *nextroute = *route;/* stays identical to original except dst addr. */
663 }
664
665 if (route->dst.atype == SOCKS_ADDR_IFNAME) {
666 SASSERTX(nextroute->dst.atype == SOCKS_ADDR_IFNAME);
667
668 sockaddr2ruleaddr(&addr, &nextroute->dst);
669
670 SASSERTX(nextroute->dst.atype != SOCKS_ADDR_IFNAME);
671
672 switch (addr.ss_family) {
673 case AF_INET:
674 nextroute->dst.addr.ipv4.mask = TOIN(&mask)->sin_addr;
675 break;
676
677 case AF_INET6:
678 nextroute->dst.addr.ipv6.maskbits
679 = bitcount_in6addr(&TOIN6(&mask)->sin6_addr);
680 break;
681
682 default:
683 SERRX(addr.ss_family);
684 }
685 }
686
687 /*
688 * place next route in list. Last or first?
689 */
690 if (!last || sockscf.route == NULL) { /* first */
691 route_t *p;
692 size_t i;
693
694 nextroute->next = sockscf.route;
695 sockscf.route = nextroute;
696
697 if (nextroute->state.autoadded)
698 nextroute->number = 0;
699 else
700 if (ifb == 0) {
701 /*
702 * only update following route numbers for first
703 * ip-block on interface.
704 */
705 for (i = 1, p = sockscf.route; p != NULL; p = p->next, ++i)
706 p->number = i;
707 }
708 }
709 else { /* last */
710 route_t *lastroute;
711
712 lastroute = sockscf.route;
713 if (nextroute->state.autoadded)
714 nextroute->number = 0;
715 else {
716 while (lastroute->next != NULL)
717 lastroute = lastroute->next;
718
719 if (ifb == 0)
720 /*
721 * only update route numbers for first
722 * ip-block on interface.
723 */
724 nextroute->number = lastroute->number + 1;
725 }
726
727 lastroute->next = nextroute;
728 nextroute->next = NULL;
729 }
730
731 if (isoneshot)
732 break;
733
734 ++ifb;
735 }
736
737 if (!route->gw.state.proxyprotocol.direct
738 && !( route->gw.state.proxyprotocol.upnp
739 && route->gw.addr.atype == SOCKS_ADDR_DOMAIN
740 && strcmp(route->gw.addr.addr.domain, PROXY_BROADCASTs) == 0)) {
741 /*
742 * A proxyserver, so make sure we add a direct route to it also.
743 */
744 struct sockaddr_storage saddr, smask;
745 command_t commands;
746 protocol_t protocols;
747
748 bzero(&commands, sizeof(commands));
749 bzero(&protocols, sizeof(protocols));
750
751 bzero(&smask, sizeof(smask));
752 SET_SOCKADDR(&smask, AF_INET);
753 TOIN(&smask)->sin_port = htons(0);
754 TOIN(&smask)->sin_addr.s_addr = htonl(IPV4_FULLNETMASK);
755
756 if (route->gw.state.proxyprotocol.upnp
757 && route->gw.addr.atype == SOCKS_ADDR_IFNAME) {
758 /*
759 * Add direct route for the SSDP broadcast addr, only reachable
760 * by lan, so should always be there.
761 */
762 static int already_done;
763
764 if (!already_done) {
765 struct servent *service;
766
767 bzero(&saddr, sizeof(saddr));
768 SET_SOCKADDR(&saddr, AF_INET);
769 if (socks_inet_pton(AF_INET,
770 DEFAULT_SSDP_BROADCAST_IPV4ADDR,
771 &TOIN(&saddr)->sin_addr.s_addr,
772 NULL) != 1)
773 serr("%s: inet_pton(3): could not convert %s to IPv4 address",
774 function, DEFAULT_SSDP_BROADCAST_IPV4ADDR);
775
776 if ((service = getservbyname("ssdp", "udp")) == NULL)
777 TOIN(&saddr)->sin_port = htons(DEFAULT_SSDP_PORT);
778 else
779 TOIN(&saddr)->sin_port = service->s_port;
780
781 protocols.udp = 1;
782
783 socks_autoadd_directroute(&commands, &protocols, &saddr, &smask);
784
785 already_done = 1;
786 }
787 }
788 else {
789 sockshost2sockaddr(&route->gw.addr, &saddr);
790
791 commands.connect = 1;
792 protocols.tcp = 1;
793
794 socks_autoadd_directroute(&commands, &protocols, &saddr, &smask);
795 }
796 }
797
798 return route;
799 }
800
801 route_t *
socks_autoadd_directroute(command,protocol,saddr,netmask)802 socks_autoadd_directroute(command, protocol, saddr, netmask)
803 const command_t *command;
804 const protocol_t *protocol;
805 const struct sockaddr_storage *saddr;
806 const struct sockaddr_storage *netmask;
807 {
808 route_t route;
809
810 memset(&route, 0, sizeof(route));
811
812 route.src.atype = SOCKS_ADDR_IPV4;
813 route.src.operator = none;
814
815 route.dst.atype = SOCKS_ADDR_IPV4;
816 route.dst.addr.ipv4.ip = TOCIN(saddr)->sin_addr;
817 route.dst.addr.ipv4.mask.s_addr = TOCIN(netmask)->sin_addr.s_addr;
818 route.dst.port.tcp = route.dst.port.udp = TOCIN(saddr)->sin_port;
819 route.dst.operator = htons(TOCIN(saddr)->sin_port)
820 == 0 ? none : eq;
821
822 route.gw.addr.atype = SOCKS_ADDR_DOMAIN;
823 STRCPY_ASSERTSIZE(route.gw.addr.addr.domain, "direct");
824
825 route.gw.state.command = *command;
826 route.gw.state.protocol = *protocol;
827
828 route.gw.state.proxyprotocol.direct = 1;
829
830 route.state.autoadded = 1;
831
832 return socks_addroute(&route, 0);
833 }
834
835 route_t *
socks_getroute(req,src,dst)836 socks_getroute(req, src, dst)
837 const request_t *req;
838 const sockshost_t *src;
839 const sockshost_t *dst;
840 {
841 const char *function = "socks_getroute()";
842 route_t *route;
843 char srcbuf[MAXSOCKSHOSTSTRING], dstbuf[MAXSOCKSHOSTSTRING];
844
845 #if SOCKS_CLIENT
846 clientinit();
847 #endif /* SOCKS_CLIENT */
848
849 slog(LOG_DEBUG,
850 "%s: searching for %s route for %s, protocol %s, src %s, dst %s, ...",
851 function,
852 proxyprotocol2string(req->version),
853 command2string(req->command), protocol2string(req->protocol),
854 src == NULL ? "<NONE>" : sockshost2string(src, srcbuf, sizeof(srcbuf)),
855 dst == NULL ? "<NONE>" : sockshost2string(dst, dstbuf, sizeof(dstbuf)));
856
857 for (route = sockscf.route; route != NULL; route = route->next) {
858 socks_showroute(route);
859
860 if (sockscf.routeoptions.maxfail != 0
861 && route->state.failed >= sockscf.routeoptions.maxfail) {
862 if (sockscf.routeoptions.badexpire == 0
863 || socks_difftime(time_monotonic(NULL), route->state.badtime)
864 <= sockscf.routeoptions.badexpire) {
865 slog(LOG_DEBUG, "%s: route does not match; badtime", function);
866 continue;
867 }
868 else
869 route->state.failed = 0; /* reset. */
870 }
871
872 switch (req->version) {
873 /*
874 * First check if this rule can provide requested proxyprotocol
875 * version with necessary functionality.
876 */
877
878 case PROXY_SOCKS_V4:
879 if (!route->gw.state.proxyprotocol.socks_v4) {
880 slog(LOG_DEBUG, "%s: route does not match; version", function);
881 continue;
882 }
883
884 switch (req->host.atype) {
885 case SOCKS_ADDR_IPV4:
886 break;
887
888 default:
889 slog(LOG_DEBUG, "%s: route does not match; atype", function);
890 continue; /* not supported by v4. */
891 }
892
893 switch (req->command) {
894 case SOCKS_BIND:
895 case SOCKS_CONNECT:
896 break;
897
898 default:
899 slog(LOG_DEBUG, "%s: route does not match; cmd", function);
900 continue; /* not supported by v4. */
901 }
902
903 break;
904
905 case PROXY_SOCKS_V5:
906 if (!route->gw.state.proxyprotocol.socks_v5) {
907 slog(LOG_DEBUG, "%s: route does not match; version", function);
908 continue;
909 }
910
911 switch (req->host.atype) {
912 case SOCKS_ADDR_IPV4:
913 case SOCKS_ADDR_IPV6:
914 case SOCKS_ADDR_DOMAIN:
915 break;
916
917 default:
918 SERRX(req->host.atype); /* failure, nothing else exists. */
919 }
920 break;
921
922 case PROXY_HTTP_10:
923 case PROXY_HTTP_11:
924 if (!route->gw.state.proxyprotocol.http) {
925 slog(LOG_DEBUG, "%s: route does not match; version", function);
926 continue;
927 }
928
929 switch (req->command) {
930 case SOCKS_CONNECT:
931 break;
932
933 default:
934 slog(LOG_DEBUG, "%s: route does not match; cmd", function);
935 continue; /* not supported by http. */
936 }
937
938 break;
939
940 case PROXY_UPNP:
941 if (!route->gw.state.proxyprotocol.upnp) {
942 slog(LOG_DEBUG, "%s: route does not match; version", function);
943 continue;
944 }
945 break;
946
947 case PROXY_DIRECT:
948 if (!route->gw.state.proxyprotocol.direct) {
949 slog(LOG_DEBUG, "%s: route does not match; version", function);
950 continue;
951 }
952 break;
953
954 default:
955 SERRX(req->version);
956 }
957
958 switch (req->command) {
959 case SOCKS_BIND:
960 if (!route->gw.state.command.bind) {
961 slog(LOG_DEBUG, "%s: route does not match; cmd", function);
962 continue;
963 }
964
965 /*
966 * Need to check protocol and proxyprotocol also. Even if
967 * bind is supported for one protocol (e.g., tcp) it does
968 * not mean it is supported for another protocol (e.g., udp).
969 */
970 switch (req->version) {
971 case PROXY_SOCKS_V4:
972 case PROXY_SOCKS_V5:
973 if (req->protocol == SOCKS_TCP)
974 break; /* yes, supported. */
975
976 /* Else: not supported. */
977
978 SASSERTX(req->protocol == SOCKS_UDP);
979 /* FALLTHROUGH */
980
981 case PROXY_HTTP_10:
982 case PROXY_HTTP_11:
983 slog(LOG_DEBUG,
984 "%s: route does not match; bind command is not "
985 "supported by proxyprotocol",
986 function);
987
988 continue;
989
990 case PROXY_UPNP:
991 case PROXY_DIRECT:
992 break;
993
994 default:
995 SERRX(req->version);
996 }
997
998 break;
999
1000 case SOCKS_CONNECT:
1001 if (!route->gw.state.command.connect) {
1002 slog(LOG_DEBUG, "%s: route does not match; cmd", function);
1003 continue;
1004 }
1005 break;
1006
1007 case SOCKS_UDPASSOCIATE:
1008 if (!route->gw.state.command.udpassociate) {
1009 slog(LOG_DEBUG, "%s: route does not match; cmd", function);
1010 continue;
1011 }
1012 break;
1013
1014 default:
1015 SERRX(req->command);
1016 }
1017
1018 /*
1019 * server supports protocol?
1020 */
1021 if ((req->protocol == SOCKS_TCP && !route->gw.state.protocol.tcp)
1022 || (req->protocol == SOCKS_UDP && !route->gw.state.protocol.udp)) {
1023 slog(LOG_DEBUG, "%s: route does not match; protocol", function);
1024 continue;
1025 }
1026
1027 /*
1028 * server supports method?
1029 */
1030 switch (req->version) {
1031 /*
1032 * These proxyprotocols do not support authentication, or
1033 * we do not support the authentication part of them.
1034 * So if the requested proxyprotocol is one of the below, the
1035 * the route must not require authentication if we should be
1036 * able to use it. If it does not, there is no point in
1037 * checking what auth we have set for the client (if any).
1038 */
1039 case PROXY_DIRECT:
1040 case PROXY_HTTP_10:
1041 case PROXY_HTTP_11:
1042 case PROXY_SOCKS_V4:
1043 case PROXY_UPNP:
1044 if (!methodisset(AUTHMETHOD_NONE,
1045 route->gw.state.smethodv,
1046 route->gw.state.smethodc)) {
1047 slog(LOG_DEBUG, "%s: route does not match; method", function);
1048 continue;
1049 }
1050
1051 break;
1052
1053 case PROXY_SOCKS_V5: /* v5 supports all methods we can support. */
1054 break;
1055
1056 default:
1057 SERRX(req->version);
1058 }
1059
1060 if (req->auth != NULL && req->auth->method != AUTHMETHOD_NOTSET) {
1061 /*
1062 * authmethod is already set. Must be serverchaining.
1063 */
1064 SASSERTX(!SOCKS_CLIENT);
1065
1066 slog(LOG_DEBUG,
1067 "%s: authmethod already set to %s. Checking route for support",
1068 function, method2string(req->auth->method));
1069
1070 if (!methodisset(req->auth->method,
1071 route->gw.state.smethodv,
1072 route->gw.state.smethodc)) {
1073 if (methodisset(AUTHMETHOD_NONE,
1074 route->gw.state.smethodv,
1075 route->gw.state.smethodc)) {
1076 slog(LOG_DEBUG,
1077 "%s: route #%lu supports authmethod %s, meaning it "
1078 "should work regardless of the authinfo we have "
1079 "received from the client",
1080 function,
1081 (unsigned long)route->number,
1082 method2string(AUTHMETHOD_NONE));
1083 }
1084 else {
1085 slog(LOG_DEBUG, "%s: route does not match; method", function);
1086 continue;
1087 }
1088 }
1089 }
1090
1091 if (src != NULL) {
1092 slog(LOG_DEBUG, "%s: checking for src match ...", function);
1093 if (!addrmatch(&route->src, src, NULL, req->protocol, 0)) {
1094 slog(LOG_DEBUG, "%s: route does not match; src addr", function);
1095 continue;
1096 }
1097 }
1098
1099 if (dst != NULL) {
1100 slog(LOG_DEBUG, "%s: checking for dst match ...", function);
1101 if (!addrmatch(&route->dst, dst, NULL, req->protocol, 0)) {
1102 slog(LOG_DEBUG, "%s: route does not match; dst addr", function);
1103 continue;
1104 }
1105 }
1106
1107 break; /* all matched */
1108 }
1109
1110 if (route == NULL)
1111 slog(LOG_DEBUG, "%s: no %s route found",
1112 function, proxyprotocol2string(req->version));
1113 else {
1114 slog(LOG_DEBUG, "%s: %s route found, route #%d",
1115 function, proxyprotocol2string(req->version), route->number);
1116
1117 if (!route->gw.state.proxyprotocol.direct
1118 && dst != NULL) {
1119 /* simple but non-robust attempt at check for routing loop. */
1120 if (sockshostareeq(&route->gw.addr, dst))
1121 serrx("%s: route to gw %s is itself. Route loop in config\n",
1122 function, sockshost2string(&route->gw.addr, NULL, 0));
1123 }
1124 }
1125
1126 return route;
1127 }
1128
1129 int
socks_routesetup(control,data,route,emsg,emsglen)1130 socks_routesetup(control, data, route, emsg, emsglen)
1131 int control;
1132 int data;
1133 const route_t *route;
1134 char *emsg;
1135 const size_t emsglen;
1136 {
1137 const char *function = "socks_routesetup()";
1138 struct sockaddr_storage controladdr, dataaddr;
1139 socklen_t len;
1140 int control_type, data_type, rc;
1141
1142 if (route->rdr_from.atype == SOCKS_ADDR_NOTSET)
1143 return 0;
1144
1145 if (control == -1)
1146 control = data;
1147 else if (data == -1)
1148 data = control;
1149
1150 SASSERTX(control != -1);
1151 SASSERTX(data != -1);
1152
1153 len = sizeof(controladdr);
1154 if (getsockname(control, TOSA(&controladdr), &len) != 0) {
1155 snprintf(emsg, emsglen, "getsockname(2) on fd %d (control) failed: %s",
1156 control, strerror(errno));
1157
1158 swarnx("%s: %s", function, emsg);
1159 return -1;
1160 }
1161
1162 if (data == control)
1163 dataaddr = controladdr;
1164 else {
1165 len = sizeof(dataaddr);
1166 if (getsockname(data, TOSA(&dataaddr), &len) != 0) {
1167 snprintf(emsg, emsglen, "getsockname(2) on fd %d (data) failed: %s",
1168 data, strerror(errno));
1169
1170 swarnx("%s: %s", function, emsg);
1171 return -1;
1172 }
1173 }
1174
1175 len = sizeof(control_type);
1176 if (getsockopt(control, SOL_SOCKET, SO_TYPE, &control_type, &len) != 0) {
1177 snprintf(emsg, emsglen, "getsockopt(2) on fd %d (control) failed: %s",
1178 control, strerror(errno));
1179
1180 swarnx("%s: %s", function, emsg);
1181 return -1;
1182 }
1183
1184 if (data == control)
1185 data_type = control_type;
1186 else {
1187 len = sizeof(data_type);
1188 if (getsockopt(data, SOL_SOCKET, SO_TYPE, &data_type, &len) != 0) {
1189 snprintf(emsg, emsglen, "getsockopt(2) on fd %d (data) failed: %s",
1190 data, strerror(errno));
1191
1192 swarnx("%s: %s", function, emsg);
1193 return -1;
1194 }
1195 }
1196
1197 slog(LOG_DEBUG,
1198 "%s: control-fd: %d (%s), data-fd: %d (%s), proxyprotocols: %s, "
1199 "redirect from: %s",
1200 function,
1201 control,
1202 control_type == SOCK_STREAM ? "stream" : "dgram",
1203 data,
1204 data_type == SOCK_STREAM ? "stream" : "dgram",
1205 proxyprotocols2string(&route->gw.state.proxyprotocol, NULL, 0),
1206 ruleaddr2string(&route->rdr_from, ADDRINFO_PORT, NULL, 0));
1207
1208 rc = socks_rebind(control,
1209 control_type == SOCK_STREAM ? SOCKS_TCP : SOCKS_UDP,
1210 &controladdr,
1211 &route->rdr_from,
1212 emsg,
1213 emsglen);
1214
1215 if (rc != 0) {
1216 snprintf(emsg, emsglen, "socks_rebind() of control-fd %d failed: %s",
1217 control, strerror(errno));
1218
1219 swarnx("%s: %s", emsg, function);
1220 return -1;
1221 }
1222
1223 if (control == data)
1224 return 0;
1225
1226 if (data_type == SOCK_DGRAM) { /* only support udp now. */
1227 if (socks_rebind(data,
1228 data_type == SOCK_STREAM ? SOCKS_TCP : SOCKS_UDP,
1229 &dataaddr,
1230 &route->rdr_from,
1231 emsg,
1232 emsglen) != 0) {
1233 snprintf(emsg, emsglen, "rebind() of data-fd %d failed: %s",
1234 data, strerror(errno));
1235
1236 swarnx("%s: %s", emsg, function);
1237 return -1;
1238 }
1239 }
1240
1241 return 0;
1242 }
1243
1244 route_t *
socks_connectroute(s,packet,src,dst,emsg,emsglen)1245 socks_connectroute(s, packet, src, dst, emsg, emsglen)
1246 const int s;
1247 socks_t *packet;
1248 const sockshost_t *src;
1249 const sockshost_t *dst;
1250 char *emsg;
1251 const size_t emsglen;
1252 {
1253 const char *function = "socks_connectroute()";
1254 route_t *route;
1255 char dststring[MAXSOCKSHOSTSTRING], gwstring[MAXSOCKSHOSTSTRING];
1256 int rc;
1257
1258 slog(LOG_DEBUG, "%s: fd %d, command %s",
1259 function, s, command2string(packet->req.command));
1260
1261 if ((route = socks_getroute(&packet->req, src, dst)) == NULL)
1262 SERRX(0); /* should only be called if there is a route. */
1263
1264 slog(LOG_NEGOTIATE, "%s: have %s route (route #%d) to %s via %s",
1265 function,
1266 proxyprotocols2string(&route->gw.state.proxyprotocol, NULL, 0),
1267 route->number,
1268 dst == NULL ?
1269 "<UNKNOWN>" : sockshost2string(dst, dststring, sizeof(dststring)),
1270 sockshost2string(&route->gw.addr, gwstring, sizeof(gwstring)));
1271
1272 if (route->gw.state.proxyprotocol.direct)
1273 return route; /* nothing to do. */
1274
1275 #if HAVE_LIBMINIUPNP
1276 if (route->gw.state.proxyprotocol.upnp) {
1277 if (route->gw.addr.atype == SOCKS_ADDR_DOMAIN
1278 && strcmp(route->gw.addr.addr.domain, PROXY_BROADCASTs) == 0) {
1279 /*
1280 * Interface igd is reachable on was not specified, so need to
1281 * try all interfaces to see which one we can use.
1282 */
1283 struct ifaddrs *ifap, *iface;
1284 gateway_t gw;
1285
1286 if (getifaddrs(&ifap) == -1) {
1287 snprintf(emsg, emsglen,
1288 "getifaddrs() failed to get list of network interfaces on "
1289 "this machine via getifaddrs(3). This is necessary for "
1290 "supporting setting \"%s\" to the value \"%s\": %s",
1291 ENV_UPNP_IGD, route->gw.addr.addr.domain, strerror(errno));
1292
1293 swarnx("%s: %s", function, emsg);
1294
1295 socks_blacklist(route, emsg);
1296
1297 return NULL;
1298 }
1299
1300 gw = route->gw;
1301 gw.addr.atype = SOCKS_ADDR_IFNAME;
1302
1303 for (iface = ifap; iface != NULL; iface = iface->ifa_next) {
1304 if (iface->ifa_addr == NULL
1305 || iface->ifa_addr->sa_family != AF_INET
1306 || TOIN(iface->ifa_addr)->sin_addr.s_addr == htonl(0)
1307 || !(iface->ifa_flags & (IFF_UP | IFF_MULTICAST))
1308 || iface->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1309 continue;
1310
1311 if (strlen(iface->ifa_name) >= sizeof(gw.addr.addr.ifname)) {
1312 swarn("%s: ifname \"%s\" is too long according to our "
1313 "compile-time limit and will be skipped. Max length: %lu",
1314 function,
1315 iface->ifa_name,
1316 (unsigned long)sizeof(gw.addr.addr.ifname));
1317
1318 continue;
1319 }
1320
1321 STRCPY_ASSERTLEN(gw.addr.addr.ifname, iface->ifa_name);
1322
1323 if (socks_initupnp(&gw, emsg, emsglen) == 0) {
1324 slog(LOG_NEGOTIATE, "%s: socks_initupnp() succeeded on iface %s",
1325 function, gw.addr.addr.ifname);
1326
1327 /*
1328 * nothing more to do for now. Once we get the actual request
1329 * (connect(2), bind(2), etc.) we can set up the rest.
1330 * XXX cache this somehow, so we don't need to broadcast again
1331 * next time.
1332 */
1333 packet->gw = gw;
1334 return route;
1335 }
1336 else
1337 slog(LOG_NEGOTIATE,
1338 "%s: socks_initupnp() failed on ifname %s: %s",
1339 function, gw.addr.addr.ifname, emsg);
1340 }
1341
1342 snprintf(emsg, emsglen,
1343 "could not find an UPNP router on any interface");
1344
1345 swarnx("%s: %s", function, emsg);
1346
1347 if (errno == 0)
1348 errno = ENETUNREACH;
1349
1350 socks_blacklist(route, emsg);
1351 return NULL;
1352 }
1353 else {
1354 /*
1355 * nothing more to do for now. Once we get the actual request
1356 * (connect(2), bind(2), etc.) we can try connecting to the
1357 * igd and set up the rest.
1358 */
1359 packet->gw = route->gw;
1360 return route;
1361 }
1362
1363 }
1364 #endif /* HAVE_LIBMINIUPNP */
1365
1366 if ((rc = socks_connecthost(s,
1367 #if !SOCKS_CLIENT
1368 EXTERNALIF,
1369 #endif /* !SOCKS_CLIENT */
1370 &route->gw.addr,
1371 NULL,
1372 NULL,
1373 sockscf.timeout.connect ?
1374 (long)sockscf.timeout.connect : (long)-1,
1375 emsg,
1376 emsglen)) == 0
1377 || (rc == -1 && errno == EINPROGRESS)) {
1378 packet->gw = route->gw;
1379 return route;
1380 }
1381
1382 swarnx("%s: failed to connect route to %s on fd %d: %s",
1383 function, sockshost2string(&route->gw.addr, NULL, 0), s, emsg);
1384
1385 if (errno == EINVAL) {
1386 struct sockaddr_in laddr;
1387 socklen_t len = sizeof(laddr);
1388
1389 if (getsockname(s, TOSA(&laddr), &len) == 0
1390 && laddr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
1391 static route_t directroute;
1392
1393 slog(LOG_NEGOTIATE,
1394 "%s: failed to connect route, but that appears to be due to the "
1395 "socket (fd %d) having been bound to the loopback interface. "
1396 "Assuming this socket should not proxied, but a direct "
1397 "connection should be made instead",
1398 function, s);
1399
1400 directroute.gw.state.proxyprotocol.direct = 1;
1401 slog(LOG_DEBUG, "%s: XXX, line %d", function, __LINE__);
1402 return &directroute;
1403 }
1404 }
1405 else
1406 socks_blacklist(route, emsg);
1407
1408 return NULL;
1409 }
1410
1411 void
socks_clearblacklist(route)1412 socks_clearblacklist(route)
1413 route_t *route;
1414 {
1415
1416 if (route != NULL)
1417 route->state.failed = route->state.badtime = 0;
1418 }
1419
1420 void
socks_blacklist(route,reason)1421 socks_blacklist(route, reason)
1422 route_t *route;
1423 const char *reason;
1424 {
1425 const char *function = "socks_blacklist()";
1426
1427 if (route == NULL || sockscf.routeoptions.maxfail == 0)
1428 return;
1429
1430 slog(LOG_INFO,
1431 "%s: blacklisting %sroute #%d. Reason: %s",
1432 function,
1433 route->state.autoadded ? "autoadded " : "",
1434 route->number,
1435 reason);
1436
1437 #if HAVE_LIBMINIUPNP
1438 bzero(&route->gw.state.data, sizeof(route->gw.state.data));
1439 #endif /* HAVE_LIBMINIUPNP */
1440
1441 ++route->state.failed;
1442 time_monotonic(&route->state.badtime);
1443 }
1444
1445 route_t *
socks_requestpolish(req,src,dst)1446 socks_requestpolish(req, src, dst)
1447 request_t *req;
1448 const sockshost_t *src;
1449 const sockshost_t *dst;
1450 {
1451 const char *function = "socks_requestpolish()";
1452 const unsigned char originalversion = req->version;
1453 static route_t directroute;
1454 route_t *route;
1455 char srcbuf[MAXSOCKSHOSTSTRING], dstbuf[MAXSOCKSHOSTSTRING];
1456
1457 if (sockscf.route == NULL) {
1458 static route_t directroute;
1459
1460 slog(LOG_DEBUG,
1461 "%s: no routes configured. Going direct for all", function);
1462
1463 directroute.gw.state.proxyprotocol.direct = 1;
1464 return &directroute;
1465 }
1466
1467 slog(LOG_NEGOTIATE,
1468 "%s: searching for %s route for %s, protocol %s, src %s, dst %s, "
1469 "authmethod %d",
1470 function,
1471 proxyprotocol2string(req->version),
1472 command2string(req->command), protocol2string(req->protocol),
1473 src == NULL ? "<NONE>" : sockshost2string(src, srcbuf, sizeof(srcbuf)),
1474 dst == NULL ? "<NONE>" : sockshost2string(dst, dstbuf, sizeof(dstbuf)),
1475 req->auth->method);
1476
1477 directroute.gw.state.proxyprotocol.direct = 1;
1478
1479 if ((route = socks_getroute(req, src, dst)) != NULL)
1480 return route;
1481
1482 /*
1483 * no route found. Can we "polish" the request and then find a route?
1484 * Try all proxy protocols we support.
1485 */
1486
1487 /*
1488 * To simplify making sure we are trying all versions, for now,
1489 * make an assumption about what we start with.
1490 */
1491 SASSERTX(req->version == PROXY_DIRECT);
1492
1493 req->version = PROXY_SOCKS_V4;
1494 if ((route = socks_getroute(req, src, dst)) != NULL)
1495 return route;
1496
1497 req->version = PROXY_SOCKS_V5;
1498 if ((route = socks_getroute(req, src, dst)) != NULL)
1499 return route;
1500
1501 req->version = PROXY_HTTP_10;
1502 if ((route = socks_getroute(req, src, dst)) != NULL)
1503 return route;
1504
1505 req->version = PROXY_HTTP_11;
1506 if ((route = socks_getroute(req, src, dst)) != NULL)
1507 return route;
1508
1509 req->version = PROXY_UPNP;
1510 if ((route = socks_getroute(req, src, dst)) != NULL)
1511 return route;
1512
1513 req->version = originalversion;
1514
1515 if (sockscf.option.directfallback) {
1516 slog(LOG_NEGOTIATE,
1517 "%s: no route found for request %s, but direct fallback is enabled",
1518 function, command2string(req->command));
1519
1520 req->version = PROXY_DIRECT;
1521 return &directroute;
1522 }
1523
1524 slog(LOG_NEGOTIATE,
1525 "%s: no route found to handle request %s and direct route fallback "
1526 "disabled. Nothing we can do",
1527 function, command2string(req->command));
1528
1529 errno = ENETUNREACH;
1530 return NULL;
1531 }
1532
1533 void
optioninit(void)1534 optioninit(void)
1535 {
1536 /*
1537 * initialize misc. options to sensible default. Some may be
1538 * overridden later by user in the sockd.conf.
1539 */
1540
1541 #if SOCKS_SERVER && HAVE_LDAP
1542
1543 ldapauthorisation_t *ldapauthorisation = &sockscf.state.ldapauthorisation;
1544 ldapauthentication_t *ldapauthentication = &sockscf.state.ldapauthentication;
1545
1546 #endif /* SOCKS_SERVER &&HAVE_LDAP */
1547
1548 sockscf.resolveprotocol = RESOLVEPROTOCOL_UDP;
1549
1550 #if SOCKS_DIRECTROUTE_FALLBACK
1551
1552 if (socks_getenv(ENV_SOCKS_DIRECTROUTE_FALLBACK, isfalse) != NULL)
1553 sockscf.option.directfallback = 0;
1554 else
1555 sockscf.option.directfallback = 1;
1556
1557 #else /* !SOCKS_DIRECTROUTE_FALLBACK */
1558
1559 if (socks_getenv(ENV_SOCKS_DIRECTROUTE_FALLBACK, istrue) != NULL)
1560 sockscf.option.directfallback = 1;
1561 else
1562 sockscf.option.directfallback = 0;
1563
1564 #endif /* SOCKS_DIRECTROUTE_FALLBACK */
1565
1566 sockscf.routeoptions.maxfail = 1;
1567 sockscf.routeoptions.badexpire = (time_t)(ROUTEBLACKLIST_SECONDS);
1568
1569 #if !SOCKS_CLIENT
1570 sockscf.option.debug = 0;
1571 sockscf.option.keepalive = 1;
1572 sockscf.option.hosts_access = 0;
1573
1574 sockscf.udpconnectdst = 1;
1575
1576 sockscf.timeout.connect = SOCKD_CONNECTTIMEOUT;
1577 sockscf.timeout.negotiate = SOCKD_NEGOTIATETIMEOUT;
1578 sockscf.timeout.tcpio = SOCKD_IOTIMEOUT_TCP;
1579 sockscf.timeout.udpio = SOCKD_IOTIMEOUT_UDP;
1580 sockscf.timeout.tcp_fin_wait = SOCKD_FIN_WAIT_2_TIMEOUT;
1581
1582 sockscf.external.rotation = ROTATION_NONE;
1583
1584 #if HAVE_PAM
1585 STRCPY_ASSERTSIZE(sockscf.state.pamservicename, DEFAULT_PAMSERVICENAME);
1586 #endif /* HAVE_PAM */
1587
1588 #if HAVE_BSDAUTH
1589 STRCPY_ASSERTSIZE(sockscf.state.bsdauthstylename, DEFAULT_BSDAUTHSTYLENAME);
1590 #endif /* HAVE_BSDAUTH */
1591
1592 #if HAVE_GSSAPI
1593
1594 STRCPY_ASSERTSIZE(sockscf.state.gssapiservicename,
1595 DEFAULT_GSSAPISERVICENAME);
1596
1597 STRCPY_ASSERTSIZE(sockscf.state.gssapikeytab,
1598 DEFAULT_GSSAPIKEYTAB);
1599
1600 #endif /* HAVE_GSSAPI */
1601
1602 #if SOCKS_SERVER && HAVE_LDAP
1603
1604 /*
1605 * LDAP authorization.
1606 */
1607
1608 STRCPY_ASSERTSIZE(ldapauthorisation->attribute, DEFAULT_LDAP_ATTRIBUTE);
1609
1610 STRCPY_ASSERTSIZE(ldapauthorisation->attribute_AD,
1611 DEFAULT_LDAP_ATTRIBUTE_AD);
1612
1613 ldapauthorisation->auto_off = 0;
1614 ldapauthorisation->certcheck = 0;
1615
1616 STRCPY_ASSERTSIZE(ldapauthorisation->certfile, DEFAULT_LDAP_CACERTFILE);
1617 STRCPY_ASSERTSIZE(ldapauthorisation->certpath, DEFAULT_LDAP_CERTDBPATH);
1618
1619 ldapauthorisation->debug = 0;
1620 *ldapauthorisation->domain = NUL;
1621
1622 STRCPY_ASSERTSIZE(ldapauthorisation->filter, DEFAULT_LDAP_FILTER);
1623 STRCPY_ASSERTSIZE(ldapauthorisation->filter_AD, DEFAULT_LDAP_FILTER_AD);
1624
1625 ldapauthorisation->keeprealm = 0;
1626
1627 STRCPY_ASSERTSIZE(ldapauthorisation->keytab, DEFAULT_GSSAPIKEYTAB);
1628
1629 ldapauthorisation->mdepth = 0;
1630 ldapauthorisation->port = SOCKD_EXPLICIT_LDAP_PORT;
1631 ldapauthorisation->portssl = SOCKD_EXPLICIT_LDAPS_PORT;
1632 ldapauthorisation->ssl = 0;
1633
1634 /*
1635 * LDAP authentication.
1636 */
1637
1638 ldapauthentication->auto_off = 0;
1639 ldapauthentication->certcheck = 1;
1640
1641 STRCPY_ASSERTSIZE(ldapauthentication->certfile, DEFAULT_LDAP_CACERTFILE);
1642 STRCPY_ASSERTSIZE(ldapauthentication->certpath, DEFAULT_LDAP_CERTDBPATH);
1643
1644 ldapauthentication->debug = 0;
1645 *ldapauthentication->domain = NUL;
1646
1647 *ldapauthentication->filter = NUL;
1648 *ldapauthentication->filter_AD = NUL;
1649
1650 STRCPY_ASSERTSIZE(ldapauthentication->keytab, DEFAULT_GSSAPIKEYTAB);
1651
1652 ldapauthentication->port = SOCKD_EXPLICIT_LDAP_PORT;
1653 ldapauthentication->portssl = SOCKD_EXPLICIT_LDAPS_PORT;
1654 ldapauthentication->ssl = 1;
1655
1656 #endif /* SOCKS_SERVER && HAVE_LDAP */
1657
1658 #if BAREFOOTD
1659 /*
1660 * initially there is no udp traffic to bounce.
1661 * Changed later if we discover there are udp rules configured also.
1662 */
1663 sockscf.state.alludpbounced = 1;
1664 #endif /* BAREFOOTD */
1665
1666 #endif /* !SOCKS_CLIENT */
1667 }
1668