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, &param)              == 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