1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019, 2020, 2021
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: serverconfig.c,v 1.567.4.12.6.14 2021/03/24 23:06:07 karls Exp $";
49
50 static int
51 safamily_isenabled(const sa_family_t family, const char *addrstr,
52 const interfaceside_t side);
53 /*
54 * Returns true if the address family "family" is enabled on the
55 * interface-side "side". "addrstr" is a printable representation of
56 * the address we tried to add.
57 *
58 * Returns false if the address family "family" is not enabled.
59 */
60
61 static int addexternaladdr(const struct ruleaddr_t *ra);
62 /*
63 * Returns 0 if the address "ra" was addedd to the list of external addresses.
64 *
65 * Returns -1 if the address "ra" was not added for a non-fatal reason,
66 * after loging a message if apropriate.
67 */
68
69 static int addinternaladdr(const char *ifname,
70 const struct sockaddr_storage *sa,
71 const int protocol);
72 /*
73 * Returns 0 if the address "ra" was addedd to the list of internal addresses.
74 *
75 * Returns -1 if the address "ra" was not added for a non-fatal reason,
76 * after loging a message if apropriate.
77 */
78
79
80 static void
81 add_more_old_shmem(struct config *config, const size_t memc,
82 const oldshmeminfo_t memv[]);
83 /*
84 * Adds "memv" to the list of old shmem entries stored in "config".
85 */
86
87 struct config sockscf; /* current config. */
88
89 void
addinternal(addr,protocol)90 addinternal(addr, protocol)
91 const ruleaddr_t *addr;
92 const int protocol;
93 {
94 const char *function = "addinternal()";
95 struct sockaddr_storage sa;
96 char ifname[MAXIFNAMELEN];
97 int changesupported;
98
99 if (sockscf.option.serverc == 1
100 || sockscf.state.inited == 0
101 || protocol == SOCKS_UDP)
102 changesupported = 1;
103 else
104 changesupported = 0;
105
106 slog(LOG_DEBUG, "%s: (%s, %s). Change supported: %d",
107 function,
108 ruleaddr2string(addr,
109 ADDRINFO_PORT | ADDRINFO_ATYPE,
110 NULL,
111 0),
112 protocol2string(protocol),
113 changesupported);
114
115 switch (addr->atype) {
116 case SOCKS_ADDR_IPV4:
117 case SOCKS_ADDR_IPV6:
118 if (addr->atype == SOCKS_ADDR_IPV4)
119 SASSERTX(addr->addr.ipv4.mask.s_addr == htonl(IPV4_FULLNETMASK));
120 else if (addr->atype == SOCKS_ADDR_IPV6)
121 SASSERTX(addr->addr.ipv6.maskbits == IPV6_NETMASKBITS);
122
123 ruleaddr2sockaddr(addr, &sa, protocol);
124
125 if (!PORTISBOUND(&sa))
126 yyerrorx("%s: address %s does not specify a portnumber to bind",
127 function, sockaddr2string(&sa, NULL, 0));
128
129 if (addrindex_on_listenlist(sockscf.internal.addrc,
130 sockscf.internal.addrv,
131 &sa,
132 protocol) == -1) {
133 if (!changesupported) {
134 yywarnx("cannot change internal addresses once running. "
135 "%s looks like a new address and will be ignored",
136 sockaddr2string(&sa, NULL, 0));
137
138 break;
139 }
140 }
141 else {
142 /*
143 * Already here, but do make sure to update globalstate to reflect
144 * it too.
145 */
146 add_internal_safamily(sa.ss_family);
147 break;
148 }
149
150 if (sa.ss_family == AF_INET
151 && TOIN(&sa)->sin_addr.s_addr == htonl(INADDR_ANY))
152 STRCPY_ASSERTSIZE(ifname, "<any IPv4-interface>");
153 else if (sa.ss_family == AF_INET6
154 && memcmp(&TOIN6(&sa)->sin6_addr,
155 &in6addr_any,
156 sizeof(in6addr_any)) == 0)
157 STRCPY_ASSERTSIZE(ifname, "<any IPv6-interface>");
158 else if (sockaddr2ifname(&sa, ifname, sizeof(ifname)) == NULL) {
159 /*
160 * Probably config-error, but could be a bug in sockaddr2ifname(),
161 * so don't error out yet. Will know for sure when we try to bind
162 * the address later.
163 */
164 strncpy(ifname, "<unknown>", sizeof(ifname) - 1);
165 ifname[sizeof(ifname) - 1] = NUL;
166
167 yywarn("%s: could not find address %s on any network interface",
168 function, sockaddr2string2(&sa, 0, NULL, 0));
169 }
170
171 addinternaladdr(ifname, &sa, protocol);
172 break;
173
174 case SOCKS_ADDR_DOMAIN: {
175 size_t i;
176 char emsg[1024];
177 int gaierr;
178
179 for (i = 0;
180 hostname2sockaddr2(addr->addr.domain,
181 i,
182 &sa,
183 &gaierr,
184 emsg,
185 sizeof(emsg)) != NULL;
186 ++i) {
187 SET_SOCKADDRPORT(&sa,
188 protocol == SOCKS_TCP ?
189 addr->port.tcp : addr->port.udp);
190
191 if (addrindex_on_listenlist(sockscf.internal.addrc,
192 sockscf.internal.addrv,
193 &sa,
194 protocol) == -1) {
195 if (!changesupported) {
196 swarnx("cannot change internal addresses once running "
197 "and %s looks like a new address. Ignored",
198 sockaddr2string(&sa, NULL, 0));
199
200 continue;
201 }
202 }
203 else {
204 /*
205 * Already here, but do make sure to update globalstate to
206 * reflect it too.
207 */
208 add_internal_safamily(sa.ss_family);
209 continue;
210 }
211
212 if (sockaddr2ifname(&sa, ifname, sizeof(ifname)) == NULL) {
213 /*
214 * Probably config-error, but could be bug in our
215 * sockaddr2ifname().
216 * Will know for sure when we try to bind the address later,
217 * so don't error out quite yet.
218 */
219
220 yywarn("%s: could not find address %s (resolved from %s) on "
221 "any network interface",
222 function,
223 sockaddr2string(&sa, NULL, 0),
224 addr->addr.domain);
225
226 STRCPY_ASSERTSIZE(ifname, "<unknown>");
227 }
228
229 addinternaladdr(ifname, &sa, protocol);
230 }
231
232 if (i == 0)
233 yyerrorx("%s", emsg);
234
235 break;
236 }
237
238 case SOCKS_ADDR_IFNAME: {
239 struct ifaddrs *ifap, *iface;
240 int isvalidif;
241
242 ifap = NULL;
243
244 if (getifaddrs(&ifap) != 0)
245 serr("getifaddrs()");
246
247 SASSERTX(ifap != NULL);
248
249 for (isvalidif = 0, iface = ifap;
250 iface != NULL;
251 iface = iface->ifa_next) {
252 if (iface->ifa_addr == NULL)
253 continue;
254
255 if (!safamily_issupported(iface->ifa_addr->sa_family))
256 continue;
257
258 if (strcmp(iface->ifa_name, addr->addr.ifname) != 0)
259 continue;
260
261 isvalidif = 1;
262
263 sockaddrcpy(&sa, TOSS(iface->ifa_addr), sizeof(sa));
264
265 SET_SOCKADDRPORT(&sa, protocol == SOCKS_TCP ?
266 addr->port.tcp : addr->port.udp);
267
268 if (addrindex_on_listenlist(sockscf.internal.addrc,
269 sockscf.internal.addrv,
270 &sa,
271 protocol) == -1) {
272 if (!changesupported) {
273 swarnx("cannot change internal addresses once running, "
274 "and %s, expanded from the ifname \"%s\" looks "
275 "like a new address. Ignored",
276 sockaddr2string(&sa, NULL, 0),
277 addr->addr.ifname);
278
279 continue;
280 }
281 }
282 else {
283 /*
284 * Already here, but do make sure to update globalstate to
285 * reflect it too.
286 */
287 add_internal_safamily(sa.ss_family);
288 continue;
289 }
290
291 addinternaladdr(addr->addr.ifname, &sa, protocol);
292 }
293
294 freeifaddrs(ifap);
295
296 if (!isvalidif)
297 swarnx("cannot find interface/address for %s", addr->addr.ifname);
298
299 break;
300 }
301
302 default:
303 SERRX(addr->atype);
304 }
305 }
306
307 void
addexternal(addr)308 addexternal(addr)
309 const ruleaddr_t *addr;
310 {
311 const char *function = "addexternal()";
312 ruleaddr_t ra;
313 int added_ipv4 = 0, added_ipv6 = 0, added_ipv6_gs = 0;
314
315 SASSERTX(ntohs(addr->port.tcp) == 0);
316 SASSERTX(ntohs(addr->port.udp) == 0);
317
318 switch (addr->atype) {
319 case SOCKS_ADDR_DOMAIN: {
320 /*
321 * XXX this is not good. It is be better to not resolve this now,
322 * but resolve it when using. Since we have a hostcache, that
323 * should not add too much expense. Sending servers a SIGHUP
324 * when local addresses change is quite common though, so
325 * assume it's good enough for now.
326 */
327 struct sockaddr_storage sa;
328 size_t i;
329 char emsg[1024];
330 int gaierr;
331
332 for (i = 0;
333 hostname2sockaddr2(addr->addr.domain,
334 i,
335 &sa,
336 &gaierr,
337 emsg,
338 sizeof(emsg)) != NULL;
339 ++i) {
340 SET_SOCKADDRPORT(&sa, addr->port.tcp);
341
342 sockaddr2ruleaddr(&sa, &ra);
343
344 if (addexternaladdr(&ra) == 0) {
345 switch (sa.ss_family) {
346 case AF_INET:
347 added_ipv4 = 1;
348 break;
349
350 case AF_INET6:
351 added_ipv6 = 1;
352
353 if (!IN6_IS_ADDR_LINKLOCAL(&TOIN6(&sa)->sin6_addr))
354 added_ipv6_gs = 1;
355
356 break;
357
358 default:
359 SERRX(sa.ss_family);
360 }
361 }
362 }
363
364 if (i == 0)
365 yyerrorx("%s", emsg);
366
367 break;
368 }
369
370 case SOCKS_ADDR_IPV4:
371 if (addr->addr.ipv4.ip.s_addr == htonl(INADDR_ANY))
372 yyerrorx("external address (%s) to connect out from cannot "
373 "be a wildcard address",
374 ruleaddr2string(addr, 0, NULL, 0));
375
376 ra = *addr;
377 ra.addr.ipv4.mask.s_addr = htonl(IPV4_FULLNETMASK);
378
379 if (addexternaladdr(&ra) == 0)
380 added_ipv4 = 1;
381
382 break;
383
384 case SOCKS_ADDR_IPV6:
385 if (memcmp(&addr->addr.ipv6.ip, &in6addr_any, sizeof(in6addr_any))
386 == 0)
387 yyerrorx("external address (%s) cannot be a wildcard address",
388 ruleaddr2string(addr, 0, NULL, 0));
389
390 ra = *addr;
391 ra.addr.ipv6.maskbits = IPV6_NETMASKBITS;
392
393 if (addexternaladdr(&ra) == 0) {
394 added_ipv6 = 1;
395
396 if (!IN6_IS_ADDR_LINKLOCAL(&ra.addr.ipv6.ip))
397 added_ipv6_gs = 1;
398 }
399
400 break;
401
402 case SOCKS_ADDR_IFNAME: {
403 /*
404 * Would be nice if this could be cached, e.g. by monitoring a
405 * routing socket for changes. Have no code for that however.
406 */
407 struct sockaddr_storage sa, t;
408 size_t i;
409
410 /*
411 * We add the interface, not the addresses. But we want to
412 * know whether the addresses, at least currently, resolve
413 * to ipv4 or ipv6 so we can resolve hostnames appropriately.
414 * E.g., no need to resolve hostname to ipv6 address if we do
415 * not have ipv6 on the external interface.
416 */
417 for (i = 0;
418 ifname2sockaddr(addr->addr.ifname, i, &sa, &t) != NULL;
419 ++i) {
420 const int enabled
421 = safamily_isenabled(sa.ss_family,
422 sockaddr2string(&sa, NULL, 0),
423 EXTERNALIF);
424
425 slog(LOG_DEBUG, "%s: ifname %s resolved to address %s. %s",
426 function,
427 addr->addr.ifname,
428 sockaddr2string2(&sa, ADDRINFO_ATYPE, NULL, 0),
429 enabled ? "enabled" : "not enabled due to address family");
430
431 if (!enabled)
432 continue;
433
434 switch (sa.ss_family) {
435 case AF_INET:
436 added_ipv4 = 1;
437 break;
438
439 case AF_INET6:
440 added_ipv6 = 1;
441
442 if (!IN6_IS_ADDR_LINKLOCAL(&TOIN6(&sa)->sin6_addr))
443 added_ipv6_gs = 1;
444
445 break;
446
447 default:
448 SERRX(sa.ss_family);
449 }
450 }
451
452 /*
453 * Not resolving but adding the ifname itself.
454 */
455 (void)addexternaladdr(addr);
456
457 break;
458 }
459
460 default:
461 SERRX(addr->atype);
462 }
463
464 if (added_ipv4)
465 add_external_safamily(AF_INET, 1);
466
467 if (added_ipv6)
468 add_external_safamily(AF_INET6, added_ipv6_gs);
469 }
470
471 void
resetconfig(config,exiting)472 resetconfig(config, exiting)
473 struct config *config;
474 const int exiting;
475 {
476 const char *function = "resetconfig()";
477 const int ismainmother = pidismainmother(config->state.pid);
478 rule_t *rulev[] = { config->crule, config->hrule, config->srule };
479 monitor_t *monitor;
480 size_t oldc, i;
481
482 slog(LOG_DEBUG, "%s: exiting? %s, ismainmother? %s",
483 function,
484 exiting ? "yes" : "no",
485 ismainmother? "yes" : "no");
486
487 if (!exiting) {
488 #if !HAVE_NO_RESOLVESTUFF
489 _res.options = config->initial.res_options;
490 #endif /* !HAVE_NO_RESOLVSTUFF */
491 }
492
493 switch (sockscf.state.type) {
494 case PROC_MOTHER:
495 mother_preconfigload();
496 break;
497
498 case PROC_MONITOR:
499 monitor_preconfigload();
500 break;
501
502 case PROC_NEGOTIATE:
503 negotiate_preconfigload();
504 break;
505
506 case PROC_REQUEST:
507 request_preconfigload();
508 break;
509
510 case PROC_IO:
511 io_preconfigload();
512 break;
513 }
514
515 /*
516 * config->initial: nothing to do here.
517 */
518
519 /*
520 * Internal interface.
521 */
522
523 if (config->option.serverc == 1 || !ismainmother) {
524 /*
525 * We only support changing these as long as we only have one mother
526 * process.
527 * If we are not the main mother, we do need to free the memory as
528 * usual however, so it will not be leaked when we realloc based on
529 * the config in shmem that main mother has now installed and from
530 * which we will update.
531 */
532
533 free(config->internal.addrv);
534 config->internal.addrv = NULL;
535 config->internal.addrc = 0;
536
537 bzero(&config->internal.protocol, sizeof(config->internal.protocol));
538 }
539
540 bzero(&config->internal.log, sizeof(config->internal.log));
541
542 /*
543 * External interface.
544 */
545
546 /* external addresses can always be changed. */
547 free(config->external.addrv);
548 config->external.addrv = NULL;
549 config->external.addrc = 0;
550
551 config->external.rotation = ROTATION_NOTSET;
552 bzero(&config->external.log, sizeof(config->external.log));
553 bzero(&config->external.protocol, sizeof(config->external.protocol));
554
555 /* can always be changed from config. */
556 bzero(&config->cpu, sizeof(config->cpu));
557
558 for (i = 0; i < ELEMENTS(rulev); ++i) {
559 rule_t *rule, prevrule, *next;
560 int haveprevrule;
561
562 haveprevrule = 0;
563 rule = rulev[i];
564
565 while (rule != NULL) {
566 /*
567 * Free normal process-local memory.
568 */
569 int rule_is_autoexpanded;
570
571 #if !HAVE_SOCKS_RULES
572 if (rule->type == object_srule) {
573 /*
574 * All pointers are pointers to the same memory in the clientrule,
575 * so it has already been freed and only the rule itself remains
576 * to be freed.
577 */
578 next = rule->next;
579 free(rule);
580 rule = next;
581
582 continue;
583 }
584 #endif /* !HAVE_SOCKS_RULES */
585
586 if (haveprevrule
587 && prevrule.type == rule->type
588 && prevrule.number == rule->number) {
589 slog(LOG_DEBUG,
590 "%s: another %s with same rule-number (%lu). "
591 "Must be expanded from the same \"to\"-address",
592 function,
593 objecttype2string(rule->type),
594 (unsigned long)rule->number);
595
596 rule_is_autoexpanded = 1;
597 SASSERTX(BAREFOOTD);
598 }
599 else
600 rule_is_autoexpanded = 0;
601
602 if (!rule_is_autoexpanded)
603 /*
604 * We don't bother allocating identical memory for auto-expanded
605 * rules, so only need to free it if it is not auto-expanded.
606 */
607 freelinkedname(rule->user);
608 rule->user = NULL;
609
610 if (!rule_is_autoexpanded)
611 freelinkedname(rule->group);
612 rule->group = NULL;
613
614 if (!rule_is_autoexpanded)
615 free(rule->socketoptionv);
616 rule->socketoptionv = NULL;
617 rule->socketoptionc = 0;
618
619 if (ismainmother) {
620 /*
621 * Next go through the shmem in this rule. It's possible
622 * we have children that are still using, or about to use,
623 * these segments, so don't delete them now, but save
624 * them for later. Only upon exit we delete them all.
625 *
626 * This means we may have a lot of unneeded shmem segments
627 * laying around, but since they are just files, rather
628 * than the, on some systems very scarce, sysv-style shmem
629 * segments, that should not be any problem. It allows
630 * us to ignore a lot of nasty locking issues.
631 */
632 size_t moreoldshmemc = 0;
633 oldshmeminfo_t moreoldshmemv[ 1 /* bw */
634 + 1 /* session */
635 + 1 /* session state. */
636 ];
637
638 if (rule_is_autoexpanded) {
639 SASSERTX(BAREFOOTD);
640 SHMEM_CLEAR(rule, SHMEM_ALL, 1);
641 }
642 else {
643 if (rule->bw_shmid != 0) {
644 moreoldshmemv[moreoldshmemc].id = rule->bw_shmid;
645 moreoldshmemv[moreoldshmemc].key = key_unset;
646 moreoldshmemv[moreoldshmemc].type = SHMEM_BW;
647
648 ++moreoldshmemc;
649 }
650
651 if (rule->ss_shmid != 0) {
652 /*
653 * session-module supports statekeys too, so need to save that
654 * too.
655 */
656 if (sockd_shmat(rule, SHMEM_SS) == 0) {
657 moreoldshmemv[moreoldshmemc].id = rule->ss_shmid;
658 moreoldshmemv[moreoldshmemc].key = rule->ss->keystate.key;
659 moreoldshmemv[moreoldshmemc].type = SHMEM_SS;
660
661 ++moreoldshmemc;
662
663 sockd_shmdt(rule, SHMEM_SS);
664 }
665 }
666
667 if (moreoldshmemc > 0)
668 add_more_old_shmem(config, moreoldshmemc, moreoldshmemv);
669 }
670 }
671
672 prevrule = *rule;
673 haveprevrule = 1;
674
675 next = rule->next;
676 free(rule);
677 rule = next;
678 }
679 }
680
681 config->crule = config->hrule = config->srule = NULL;
682
683 /* routeoptions, read from config file. */
684 bzero(&config->routeoptions, sizeof(config->routeoptions));
685
686 /* free routes. */
687 freeroutelist(config->route);
688 config->route = NULL;
689
690 /* and monitors. */
691 monitor = sockscf.monitor;
692 while (monitor != NULL) {
693 monitor_t *next = monitor->next;
694
695 if (ismainmother && monitor->mstats_shmid != 0) {
696 oldshmeminfo_t moreoldshmemv[ 1 /* just the monitor shmid. */ ];
697
698 moreoldshmemv[0].id = monitor->mstats_shmid;
699 moreoldshmemv[0].key = key_unset;
700 moreoldshmemv[0].type = SHMEM_MONITOR;
701
702 add_more_old_shmem(config, ELEMENTS(moreoldshmemv), moreoldshmemv);
703 }
704
705 free(monitor);
706 monitor = next;
707 }
708 config->monitor = NULL;
709
710 /* monitoroptions. Reset on each reload. */
711 bzero(&config->monitorspec, sizeof(config->monitorspec));
712
713 free(config->socketoptionv);
714 config->socketoptionv = NULL;
715 config->socketoptionc = 0;
716
717 /* compat, read from config file. */
718 bzero(&config->compat, sizeof(config->compat));
719
720 /* extensions, read from config file. */
721 bzero(&config->extension, sizeof(config->extension));
722
723 /*
724 * log, errlog; handled specially when parsing.
725 */
726
727 /*
728 * option; some only settable at commandline, some only read from config
729 * file. Those only read from config file will be reset to default in
730 * optioninit().
731 */
732
733 /* resolveprotocol, read from config file. */
734 bzero(&config->resolveprotocol, sizeof(config->resolveprotocol));
735
736 /*
737 * socketconfig, read from config file, but also has defaults set by
738 * optioninit(), so don't need to touch it.
739 */
740
741 /* srchost, read from config file. */
742 bzero(&config->srchost, sizeof(config->srchost));
743
744 /* stat: not touch. Accumulated continously. */
745
746 /*
747 * state; keep most of it, with the following exceptions:
748 */
749 /* don't want to have too much code for tracking this, so regen this now. */
750 config->state.highestfdinuse = 0;
751
752 /* timeout, read from config file. */
753 bzero(&config->timeout, sizeof(config->timeout));
754
755 #if HAVE_SOLARIS_PRIVS
756 /* uid; is special. Needs clearing, but must reopen config-file first. */
757 #endif /* HAVE_SOLARIS_PRIVS */
758
759 /* (child)state: not touched. */
760
761
762 /*
763 * various method settings. All read from config file.
764 */
765
766 bzero(config->cmethodv, sizeof(config->cmethodv));
767 config->cmethodc = 0;
768
769 bzero(config->smethodv, sizeof(config->smethodv));
770 config->smethodc = 0;
771
772 /* udpconnectdst. No need to touch. Reset to default on reload. */
773
774 #if HAVE_LIBWRAP
775 if (config->hosts_allow_original != NULL
776 && hosts_allow_table != config->hosts_allow_original) {
777 free(hosts_allow_table);
778 hosts_allow_table = config->hosts_allow_original;
779 }
780
781 if (config->hosts_deny_original != NULL
782 && hosts_deny_table != config->hosts_deny_original) {
783 free(hosts_deny_table);
784 hosts_deny_table = config->hosts_deny_original;
785 }
786 #endif /* HAVE_LIBWRAP */
787
788 if (exiting && ismainmother && config->oldshmemc > 0) {
789 /*
790 * Go through the list of saved segments and delete them.
791 * Any (io) children using them should already have them open,
792 * and nobody not already using them should need to attach to them
793 * after we exit. The exception is clients using the session module,
794 * where we do not keep attached to the segment, but who need to attach
795 * to it when removing the client. Unfortunately failure to attach
796 * to a shmem segment is normally a serious error and logged as thus,
797 * but if mother has removed the segment, then obviously the other
798 * processes can not attach to it again.
799 *
800 * There is some code to only debug log failure to attach to the
801 * shmem segments (or rather, failure to open the file) if mother
802 * does not exist (presumably having deleted the files before exiting),
803 * rather than warn. It depends on mother having exited before the
804 * child process tries to remove the client though, which may not
805 * be the case even though we do a little work to increase the odds.
806 * Worst case is that we end up with some useless warnings though,
807 * so not worth going overboard with it.
808 */
809
810 SASSERTX(ismainmother);
811 SASSERTX(sockscf.state.type == PROC_MOTHER);
812
813 /*
814 * Lock to increase the chance of us having time to exit before
815 * any children try to attach/detach (they will be blocked waiting for
816 * the lock). Don't unlock ourselves, but let the kernel release the
817 * lock when we exit, further reducing gap between us exiting and
818 * a child process being able to detect it.
819 */
820 socks_lock(config->shmemfd, 0, 0, 1, 1);
821
822 slog(LOG_DEBUG, "%s: %ld old shmem entr%s saved. Deleting now",
823 function, (unsigned long)config->oldshmemc,
824 config->oldshmemc == 1 ? "y" : "ies");
825
826 for (oldc = 0; oldc < config->oldshmemc; ++oldc) {
827 char fname[PATH_MAX];
828
829 snprintf(fname, sizeof(fname), "%s",
830 sockd_getshmemname(config->oldshmemv[oldc].id, key_unset));
831
832 slog(LOG_DEBUG,
833 "%s: deleting shmem segment shmid %lu in file %s at index #%lu",
834 function,
835 (unsigned long)config->oldshmemv[oldc].id,
836 fname,
837 (unsigned long)oldc);
838
839 if (unlink(fname) != 0)
840 swarn("%s: failed to unlink shmem segment %ld in file %s",
841 function, config->oldshmemv[oldc].id, fname);
842
843 if (config->oldshmemv[oldc].key != key_unset) {
844 snprintf(fname, sizeof(fname), "%s",
845 sockd_getshmemname(config->oldshmemv[oldc].id,
846 config->oldshmemv[oldc].key));
847
848 slog(LOG_DEBUG,
849 "%s: deleting shmem segment shmid %lu/key %lu in file %s",
850 function,
851 (unsigned long)config->oldshmemv[oldc].id,
852 (unsigned long)config->oldshmemv[oldc].key,
853 fname);
854
855 if (unlink(fname) != 0)
856 swarn("%s: failed to unlink shmem segment %ld.%d in file %s",
857 function,
858 config->oldshmemv[oldc].id,
859 (int)config->oldshmemv[oldc].key,
860 fname);
861 }
862 }
863 }
864 }
865
866 void
freeroutelist(routehead)867 freeroutelist(routehead)
868 route_t *routehead;
869 {
870
871 while (routehead != NULL) {
872 route_t *next = routehead->next;
873
874 free(routehead->socketoptionv);
875 free(routehead);
876 routehead = next;
877 }
878 }
879
880 int
addrisbindable(addr)881 addrisbindable(addr)
882 const ruleaddr_t *addr;
883 {
884 const char *function = "addrisbindable()";
885 struct sockaddr_storage saddr;
886 int rc, s;
887
888 switch (addr->atype) {
889 case SOCKS_ADDR_IPV4:
890 case SOCKS_ADDR_IPV6:
891 sockshost2sockaddr(ruleaddr2sockshost(addr, NULL, SOCKS_TCP), &saddr);
892 break;
893
894 case SOCKS_ADDR_IFNAME: {
895 struct sockaddr_storage mask;
896
897 if (ifname2sockaddr(addr->addr.ifname, 0, &saddr, &mask) == NULL) {
898 swarn("%s: cannot find interface named %s with ip configured",
899 function, addr->addr.ifname);
900
901 return 0;
902 }
903
904 break;
905 }
906
907 case SOCKS_ADDR_DOMAIN: {
908 sockshost_t host;
909
910 sockshost2sockaddr(ruleaddr2sockshost(addr, &host, SOCKS_TCP), &saddr);
911 if (!IPADDRISBOUND(&saddr)) {
912 swarnx("%s can not resolve host %s: %s",
913 function,
914 sockshost2string(&host, NULL, 0),
915 hstrerror(h_errno));
916
917 return 0;
918 }
919
920 break;
921 }
922
923 default:
924 SERRX(addr->atype);
925 }
926
927 if ((s = socket(saddr.ss_family, SOCK_STREAM, 0)) == -1) {
928 swarn("%s: socket(SOCK_STREAM)", function);
929 return 0;
930 }
931
932 rc = socks_bind(s, &saddr, 0);
933 close(s);
934
935 if (rc != 0)
936 swarn("%s: cannot bind address: %s (from address specification %s)",
937 function,
938 sockaddr2string(&saddr, NULL, 0),
939 ruleaddr2string(addr, 0, NULL, 0));
940
941 return rc == 0;
942 }
943
944 int
isreplycommandonly(command)945 isreplycommandonly(command)
946 const command_t *command;
947 {
948
949 if ((command->bindreply || command->udpreply)
950 && !(command->connect || command->bind || command->udpassociate))
951 return 1;
952 else
953 return 0;
954 }
955
956 int
hasreplycommands(command)957 hasreplycommands(command)
958 const command_t *command;
959 {
960
961 if (command->bindreply || command->udpreply)
962 return 1;
963 else
964 return 0;
965 }
966
967
968 ssize_t
addrindex_on_listenlist(listc,listv,_addr,protocol)969 addrindex_on_listenlist(listc, listv, _addr, protocol)
970 const size_t listc;
971 const listenaddress_t *listv;
972 const struct sockaddr_storage *_addr;
973 const int protocol;
974 {
975 size_t i;
976
977 for (i = 0; i < listc; ++i) {
978 struct sockaddr_storage addr = *(const struct sockaddr_storage *)_addr;
979
980 if (listv[i].protocol != protocol)
981 continue;
982
983 if (GET_SOCKADDRPORT(&addr) == htons(0)) /* match any internal port. */
984 SET_SOCKADDRPORT(&addr, GET_SOCKADDRPORT(&listv[i].addr));
985
986 if (sockaddrareeq(&addr, &listv[i].addr, 0))
987 return (ssize_t)i;
988 }
989
990 return (ssize_t)-1;
991 }
992
993 ssize_t
addrindex_on_externallist(external,_addr)994 addrindex_on_externallist(external, _addr)
995 const externaladdress_t *external;
996 const struct sockaddr_storage *_addr;
997 {
998 const char *function = "addrindex_on_externallist()";
999 struct sockaddr_storage sa, addr;
1000 size_t i;
1001
1002 /*
1003 * Not interested in comparing portnumber.
1004 */
1005 sockaddrcpy(&addr, _addr, sizeof(addr));
1006 SET_SOCKADDRPORT(&addr, htons(0));
1007
1008 slog(LOG_DEBUG,
1009 "%s: checking if address %s is a configured external address",
1010 function, sockaddr2string(&addr, NULL, 0));
1011
1012 for (i = 0; i < external->addrc; ++i) {
1013 slog(LOG_DEBUG, "%s: external address #%lu: %s",
1014 function,
1015 (unsigned long)i,
1016 ruleaddr2string(&external->addrv[i], ADDRINFO_ATYPE, NULL, 0));
1017
1018 switch (external->addrv[i].atype) {
1019 case SOCKS_ADDR_IPV4:
1020 case SOCKS_ADDR_IPV6: {
1021 sockshost_t host;
1022
1023 sockshost2sockaddr(ruleaddr2sockshost(&external->addrv[i],
1024 &host,
1025 SOCKS_TCP),
1026 &sa);
1027 #if DIAGNOSTIC
1028 SASSERTX(safamily_isenabled(sa.ss_family,
1029 sockaddr2string(&sa, NULL, 0),
1030 EXTERNALIF));
1031 #endif /* DIAGNOSTIC */
1032
1033 if (sockaddrareeq(&addr, &sa, 0))
1034 return (ssize_t)i;
1035
1036 break;
1037 }
1038 case SOCKS_ADDR_DOMAIN: {
1039 char emsg[1024];
1040 int gaierr;
1041 size_t ii;
1042
1043 ii = 0;
1044 while (hostname2sockaddr2(external->addrv[i].addr.domain,
1045 ii++,
1046 &sa,
1047 &gaierr,
1048 emsg,
1049 sizeof(emsg)) != NULL) {
1050 slog(LOG_DEBUG, "%s: checking resolved address %s ...",
1051 function, sockaddr2string(&sa, NULL, 0));
1052
1053 if (!safamily_isenabled(sa.ss_family,
1054 sockaddr2string(&sa, NULL, 0),
1055 EXTERNALIF))
1056 continue;
1057
1058 if (sockaddrareeq(&addr, &sa, 0))
1059 return (ssize_t)i;
1060 }
1061
1062 if (ii == 0)
1063 swarnx("%s: problem with address on external interface: %s",
1064 function, emsg);
1065
1066 break;
1067 }
1068
1069 case SOCKS_ADDR_IFNAME: {
1070 struct sockaddr_storage mask;
1071 size_t ii;
1072
1073 ii = 0;
1074 while (ifname2sockaddr(external->addrv[i].addr.ifname,
1075 ii++,
1076 &sa,
1077 &mask) != NULL) {
1078 if (!safamily_isenabled(sa.ss_family,
1079 sockaddr2string(&sa, NULL, 0),
1080 EXTERNALIF))
1081 continue;
1082
1083 if (sockaddrareeq(&addr, &sa, 0))
1084 return (ssize_t)i;
1085 }
1086
1087 break;
1088 }
1089
1090 default:
1091 SERRX(external->addrv[i].atype);
1092 }
1093 }
1094
1095 return (ssize_t)-1;
1096 }
1097
1098 void
checkconfig(void)1099 checkconfig(void)
1100 {
1101 const char *function = "checkconfig()";
1102
1103 #if HAVE_PAM
1104 char *pamservicename = NULL;
1105 #endif /* HAVE_PAM */
1106
1107 #if HAVE_BSDAUTH
1108 char *bsdauthstylename = NULL;
1109 #endif /* HAVE_BSDAUTH */
1110
1111 #if HAVE_LDAP
1112
1113 ldapauthentication_t ldapauthentication =
1114 { .ldapurl = NULL,
1115 /* .ldapbasedn = NULL, */
1116 .domain = { NUL },
1117 .keytab = { NUL },
1118 .filter = { NUL },
1119 .certfile = { NUL },
1120 .certpath = { NUL },
1121 .debug = LDAP_UNSET_DEBUG_VALUE,
1122 .auto_off = -1,
1123 .ssl = -1,
1124 .certcheck = -1,
1125 .port = -1,
1126 .portssl = -1,
1127 };
1128
1129 /*
1130 * XXX need same for ldap_t?
1131 */
1132
1133 int ldom = -1, lfil = -1;
1134
1135 #endif /* HAVE_LDAP */
1136
1137 #if HAVE_GSSAPI
1138
1139 char *gssapiservicename = NULL, *gssapikeytab = NULL;
1140
1141 #endif /* HAVE_GSSAPI */
1142
1143
1144 rule_t *rulebasev[] = { sockscf.crule,
1145 sockscf.hrule,
1146 sockscf.srule
1147 };
1148 size_t i, basec;
1149 int usinglibwrap = 0;
1150
1151 for (i = 0; i < sockscf.cmethodc; ++i) {
1152 SASSERTX(sockscf.cmethodv[i] >= AUTHMETHOD_NONE);
1153 SASSERTX(sockscf.cmethodv[i] <= AUTHMETHOD_MAX);
1154
1155 SASSERTX(methodisvalid(sockscf.cmethodv[i], object_crule));
1156
1157 if (sockscf.cmethodv[i] == AUTHMETHOD_RFC931)
1158 usinglibwrap = 1;
1159 }
1160
1161 #if HAVE_SOCKS_RULES
1162 if (sockscf.smethodc == 0)
1163 swarnx("%s: no socks authentication methods enabled. This means all "
1164 "socks requests will be blocked after negotiation. "
1165 "Perhaps this is not intended?",
1166 function);
1167 else {
1168 for (i = 0; i < sockscf.smethodc; ++i) {
1169 SASSERTX(sockscf.smethodv[i] >= AUTHMETHOD_NONE);
1170 SASSERTX(sockscf.smethodv[i] <= AUTHMETHOD_MAX);
1171
1172 if (sockscf.smethodv[i] == AUTHMETHOD_RFC931)
1173 usinglibwrap = 1;
1174
1175 if (sockscf.smethodv[i] == AUTHMETHOD_NONE
1176 && i + 1 < sockscf.smethodc)
1177 yywarnx("authentication method \"%s\" is configured in the "
1178 "global socksmethod list, but since authentication "
1179 "methods are selected by the priority given, we will "
1180 "never try to match any of the subsequent authentication "
1181 "methods. I.e., no match will ever be attempted on the "
1182 "next method, method \"%s\"",
1183 method2string(sockscf.smethodv[i]),
1184 method2string(sockscf.smethodv[i + 1]));
1185
1186 }
1187 }
1188 #endif /* HAVE_SOCKS_RULES */
1189
1190 /*
1191 * Check rules, including if some rule-specific settings vary across
1192 * rules.
1193 *
1194 * If they don't vary we can optimize things when running and set the
1195 * corresponding variable in the global sockscf object to the constant
1196 * value.
1197 * If they vary, we set the corresponding global variable in sockscf to
1198 * NULL/NUL to indicate we don't have a constant value for this
1199 * variable/setting.
1200 */
1201 basec = 0;
1202 while (basec < ELEMENTS(rulebasev)) {
1203 rule_t *rule = rulebasev[basec++];
1204
1205 if (rule == NULL)
1206 continue;
1207
1208 for (; rule != NULL; rule = rule->next) {
1209 size_t methodc;
1210 int *methodv;
1211
1212 slog(LOG_DEBUG, "%s: %s %u",
1213 function, objecttype2string(rule->type), (unsigned)rule->number);
1214
1215 #if HAVE_LIBWRAP
1216
1217 if (*rule->libwrap != NUL)
1218 usinglibwrap = 1;
1219
1220 #endif /* HAVE_LIBWRAP */
1221
1222 /*
1223 * What methods do we need to check? clientmethods for
1224 * client-rules, socksmethods for socks-rules.
1225 */
1226 switch (rule->type) {
1227 case object_crule:
1228
1229 #if HAVE_SOCKS_HOSTID
1230
1231 case object_hrule:
1232
1233 #endif /* HAVE_SOCKS_HOSTID */
1234
1235 methodc = rule->state.cmethodc;
1236 methodv = rule->state.cmethodv;
1237 break;
1238
1239 case object_srule:
1240 methodc = rule->state.smethodc;
1241 methodv = rule->state.smethodv;
1242 break;
1243
1244 default:
1245 SERRX(rule->type);
1246 }
1247
1248 for (i = 0; i < methodc; ++i) {
1249 switch (methodv[i]) {
1250
1251 #if HAVE_PAM
1252 case AUTHMETHOD_PAM_ANY:
1253 case AUTHMETHOD_PAM_ADDRESS:
1254 case AUTHMETHOD_PAM_USERNAME:
1255 if (*sockscf.state.pamservicename == NUL)
1256 break; /* already found to vary. */
1257
1258 if (pamservicename == NULL) /* first pam rule. */
1259 pamservicename = rule->state.pamservicename;
1260 else if (strcmp(pamservicename, rule->state.pamservicename)
1261 != 0) {
1262 slog(LOG_DEBUG, "%s: pam.servicename varies, %s ne %s",
1263 function,
1264 pamservicename,
1265 rule->state.pamservicename);
1266
1267 *sockscf.state.pamservicename = NUL;
1268 }
1269
1270 break;
1271
1272 #endif /* HAVE_PAM */
1273
1274 #if HAVE_BSDAUTH
1275
1276 case AUTHMETHOD_BSDAUTH:
1277 if (*sockscf.state.bsdauthstylename == NUL)
1278 break; /* already found to vary. */
1279
1280 if (bsdauthstylename == NULL) /* first bsdauth rule. */
1281 bsdauthstylename = rule->state.bsdauthstylename;
1282 else if (strcmp(bsdauthstylename,
1283 rule->state.bsdauthstylename) != 0) {
1284 slog(LOG_DEBUG,
1285 "%s: bsdauth.stylename varies, %s ne %s",
1286 function,
1287 bsdauthstylename,
1288 rule->state.bsdauthstylename);
1289
1290 *sockscf.state.bsdauthstylename = NUL;
1291 }
1292
1293 break;
1294
1295 #endif /* HAVE_BSDAUTH */
1296
1297 #if HAVE_LDAP
1298
1299 case AUTHMETHOD_LDAPAUTH:
1300 if (sockscf.state.ldapauthentication.ldapurl == NULL)
1301 ; /* varies. */
1302 else {
1303 if (ldapauthentication.ldapurl == NULL)
1304 ldapauthentication.ldapurl
1305 = rule->state.ldapauthentication.ldapurl;
1306 else if (!linkednamesareeq(ldapauthentication.ldapurl,
1307 rule->state.ldapauthentication.ldapurl)) {
1308 slog(LOG_DEBUG,
1309 "%s: ldapauthentication.ldapurl varies",
1310 function);
1311
1312 sockscf.state.ldapauthentication.ldapurl = NULL;
1313 }
1314 }
1315
1316 if (*sockscf.state.ldapauthentication.certfile == NUL)
1317 ; /* varies. */
1318 else {
1319 if (*ldapauthentication.certfile == NUL)
1320 STRCPY_ASSERTSIZE(ldapauthentication.certfile,
1321 rule->state.ldapauthentication.certfile);
1322 else if (strcmp(ldapauthentication.certfile,
1323 rule->state.ldapauthentication.certfile)
1324 != 0) {
1325 slog(LOG_DEBUG,
1326 "%s: ldapauthentication.certfile varies, "
1327 "%s ne %s",
1328 function,
1329 ldapauthentication.certfile,
1330 rule->state.ldapauthentication.certfile);
1331
1332 *sockscf.state.ldapauthentication.certfile = NUL;
1333 }
1334 }
1335
1336 if (*sockscf.state.ldapauthentication.certpath == NUL)
1337 ; /* varies. */
1338 else {
1339 if (*ldapauthentication.certpath == NUL)
1340 STRCPY_ASSERTSIZE(ldapauthentication.certpath,
1341 rule->state.ldapauthentication.certpath);
1342 else if (strcmp(ldapauthentication.certpath,
1343 rule->state.ldapauthentication.certpath)
1344 != 0) {
1345 slog(LOG_DEBUG,
1346 "%s: ldapauthentication.certpath varies, "
1347 "%s ne %s",
1348 function,
1349 ldapauthentication.certpath,
1350 rule->state.ldapauthentication.certpath);
1351
1352 *sockscf.state.ldapauthentication.certpath = NUL;
1353 }
1354 }
1355
1356 if (*sockscf.state.ldapauthentication.keytab == NUL)
1357 ; /* varies. */
1358 else {
1359 if (*ldapauthentication.keytab == NUL)
1360 STRCPY_ASSERTSIZE(ldapauthentication.keytab,
1361 rule->state.ldapauthentication.keytab);
1362 else if (strcmp(ldapauthentication.keytab,
1363 rule->state.ldapauthentication.keytab)
1364 != 0) {
1365 slog(LOG_DEBUG,
1366 "%s: ldapauthentication.keytab varies, "
1367 "%s ne %s",
1368 function,
1369 ldapauthentication.keytab,
1370 rule->state.ldapauthentication.keytab);
1371
1372 *sockscf.state.ldapauthentication.keytab = NUL;
1373 }
1374 }
1375
1376 if (ldom != 0
1377 && *rule->state.ldapauthentication.domain != NUL) {
1378 if (*ldapauthentication.domain == NUL)
1379 STRCPY_ASSERTSIZE(ldapauthentication.domain,
1380 rule->state.ldapauthentication.domain);
1381 else if (strcmp(ldapauthentication.domain,
1382 rule->state.ldapauthentication.domain)
1383 != 0) {
1384 slog(LOG_DEBUG,
1385 "%s: ldapauthentication.domain varies, "
1386 "%s ne %s",
1387 function,
1388 ldapauthentication.domain,
1389 rule->state.ldapauthentication.domain);
1390
1391 ldom = 0;
1392 }
1393 }
1394
1395 if (lfil != 0
1396 && *rule->state.ldapauthentication.filter != NUL) {
1397 if (*ldapauthentication.filter == NUL)
1398 STRCPY_ASSERTSIZE(ldapauthentication.filter,
1399 rule->state.ldapauthentication.filter);
1400 else if (strcmp(ldapauthentication.filter,
1401 rule->state.ldapauthentication.filter)
1402 != 0) {
1403 slog(LOG_DEBUG,
1404 "%s: ldapauthentication.filter varies, "
1405 "%s ne %s",
1406 function,
1407 ldapauthentication.filter,
1408 rule->state.ldapauthentication.filter);
1409
1410 lfil = 0;
1411 }
1412 }
1413
1414 if (sockscf.state.ldapauthentication.debug
1415 != LDAP_UNSET_DEBUG_VALUE) {
1416 if (ldapauthentication.debug == LDAP_UNSET_DEBUG_VALUE)
1417 ldapauthentication.debug
1418 = rule->state.ldapauthentication.debug;
1419 else if (ldapauthentication.debug
1420 != rule->state.ldapauthentication.debug) {
1421 slog(LOG_DEBUG,
1422 "%s: ldapauthentication.debug varies, %d ne %d",
1423 function,
1424 (int)ldapauthentication.debug,
1425 (int)rule->state.ldapauthentication.debug);
1426
1427 sockscf.state.ldapauthentication.debug
1428 = LDAP_UNSET_DEBUG_VALUE;
1429 }
1430 }
1431
1432 if (sockscf.state.ldapauthentication.auto_off != -1) {
1433 if (ldapauthentication.auto_off == -1)
1434 ldapauthentication.auto_off
1435 = rule->state.ldapauthentication.auto_off;
1436 else if (ldapauthentication.auto_off
1437 != rule->state.ldapauthentication.auto_off) {
1438 slog(LOG_DEBUG,
1439 "%s: ldapauthentication.auto_off varies, "
1440 "%d ne %d",
1441 function,
1442 (int)ldapauthentication.auto_off,
1443 (int)rule->state.ldapauthentication.auto_off);
1444
1445 sockscf.state.ldapauthentication.auto_off = -1;
1446 }
1447 }
1448
1449 if (sockscf.state.ldapauthentication.ssl != -1) {
1450 if (ldapauthentication.ssl == -1)
1451 ldapauthentication.ssl
1452 = rule->state.ldapauthentication.ssl ;
1453 else if (ldapauthentication.ssl
1454 != rule->state.ldapauthentication.ssl) {
1455 slog(LOG_DEBUG,
1456 "%s: ldapauthentication.ssl varies, %d ne %d",
1457 function,
1458 (int)ldapauthentication.ssl ,
1459 (int)rule->state.ldapauthentication.ssl);
1460
1461 sockscf.state.ldapauthentication.ssl = -1;
1462 }
1463 }
1464
1465 if (sockscf.state.ldapauthentication.certcheck != -1) {
1466 if (ldapauthentication.certcheck == -1)
1467 ldapauthentication.certcheck
1468 = rule->state.ldapauthentication.certcheck;
1469 else if (ldapauthentication.certcheck
1470 != rule->state.ldapauthentication.certcheck) {
1471 slog(LOG_DEBUG,
1472 "%s: ldapauthentication.certcheck varies, "
1473 "%d ne %d",
1474 function,
1475 (int)ldapauthentication.certcheck,
1476 (int)rule->state.ldapauthentication.certcheck);
1477
1478 sockscf.state.ldapauthentication.certcheck = -1;
1479 }
1480 }
1481
1482 if (sockscf.state.ldapauthentication.port != -1) {
1483 if (ldapauthentication.port == -1)
1484 ldapauthentication.port
1485 = rule->state.ldapauthentication.port;
1486 else if (ldapauthentication.port
1487 != rule->state.ldapauthentication.port) {
1488 slog(LOG_DEBUG,
1489 "%s: ldapauthentication.port varies, %d ne %d",
1490 function,
1491 ldapauthentication.port,
1492 rule->state.ldapauthentication.port);
1493
1494 sockscf.state.ldapauthentication.port = -1;
1495 }
1496 }
1497
1498 if (sockscf.state.ldapauthentication.portssl != -1) {
1499 if (ldapauthentication.portssl == -1)
1500 ldapauthentication.portssl
1501 = rule->state.ldapauthentication.portssl;
1502 else if (ldapauthentication.portssl
1503 != rule->state.ldapauthentication.portssl) {
1504 slog(LOG_DEBUG,
1505 "%s: ldapauthentication.portssl varies, "
1506 "%d ne %d",
1507 function,
1508 ldapauthentication.portssl,
1509 rule->state.ldapauthentication.portssl);
1510
1511 sockscf.state.ldapauthentication.portssl = -1;
1512 }
1513 }
1514
1515 break;
1516
1517 #endif /* HAVE_LDAP */
1518
1519 #if HAVE_GSSAPI
1520 case AUTHMETHOD_GSSAPI:
1521 if (*sockscf.state.gssapiservicename != NUL) {
1522 if (gssapiservicename == NULL) /* first gssapi rule. */
1523 gssapiservicename = rule->state.gssapiservicename;
1524 else if (strcmp(gssapiservicename,
1525 rule->state.gssapiservicename) != 0) {
1526 slog(LOG_DEBUG,
1527 "%s: gssapi.servicename varies, %s ne %s",
1528 function,
1529 gssapiservicename,
1530 rule->state.gssapiservicename);
1531
1532 *sockscf.state.gssapiservicename = NUL;
1533 }
1534 }
1535 /* else; already found to vary. */
1536
1537 if (*sockscf.state.gssapikeytab != NUL) {
1538 if (gssapikeytab == NULL) /* first gssapi rule. */
1539 gssapikeytab = rule->state.gssapikeytab;
1540 else if (strcmp(gssapikeytab, rule->state.gssapikeytab)
1541 != 0) {
1542 slog(LOG_DEBUG, "%s: gssapi.keytab varies, %s ne %s",
1543 function,
1544 gssapikeytab,
1545 rule->state.gssapikeytab);
1546
1547 *sockscf.state.gssapikeytab = NUL;
1548 }
1549 }
1550 /* else; already found to vary. */
1551
1552 break;
1553 #endif /* HAVE_GSSAPI */
1554
1555 default:
1556 break;
1557 }
1558 }
1559
1560 #if BAREFOOTD
1561 if (rule->type == object_crule) {
1562 if (rule->state.protocol.tcp)
1563 /*
1564 * Add all "to:" addresses to the list of internal interfaces;
1565 * barefootd doesn't use a separate "internal:" keyword for it.
1566 */
1567 addinternal(&rule->dst, SOCKS_TCP);
1568
1569 if (rule->state.protocol.udp)
1570 sockscf.state.alludpbounced = 0;
1571 }
1572 #endif /* BAREFOOTD */
1573
1574 }
1575 }
1576
1577 /*
1578 * Check that the main configured privileges work.
1579 */
1580 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_ON);
1581 sockd_priv(SOCKD_PRIV_PRIVILEGED, PRIV_OFF);
1582
1583 sockd_priv(SOCKD_PRIV_UNPRIVILEGED, PRIV_ON);
1584 sockd_priv(SOCKD_PRIV_UNPRIVILEGED, PRIV_OFF);
1585
1586 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_ON);
1587 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_OFF);
1588
1589 #if !HAVE_PRIVILEGES
1590 SASSERTX(sockscf.state.euid == geteuid());
1591 SASSERTX(sockscf.state.egid == getegid());
1592
1593 if (sockscf.uid.unprivileged_uid == 0)
1594 swarnx("%s: setting the unprivileged uid to %d is not recommended "
1595 "for security reasons",
1596 function, sockscf.uid.unprivileged_uid);
1597
1598 #if HAVE_LIBWRAP
1599 if (usinglibwrap && sockscf.uid.libwrap_uid == 0)
1600 swarnx("%s: setting the libwrap uid to %d is almost never needed, and "
1601 "is not recommended for security reasons",
1602 function, sockscf.uid.libwrap_uid);
1603 #endif /* HAVE_LIBWRAP */
1604 #endif /* !HAVE_PRIVILEGES */
1605
1606 #if HAVE_PAM
1607 if (*sockscf.state.pamservicename != NUL
1608 && pamservicename != NULL) {
1609 /*
1610 * pamservicename does not vary, but is not necessarily the
1611 * the same as sockscf.state.pamservicename (default).
1612 * If it is not, set sockscf.state.pamservicename to
1613 * what the user used in one or more of the rules, since
1614 * it is the same in all rules, i.e. making it that value
1615 * we use to make passworddbisunique() work as expected.
1616 *
1617 * Likewise for bsdauth, gssapi, etc.
1618 */
1619
1620 if (strcmp(pamservicename, sockscf.state.pamservicename) != 0)
1621 STRCPY_CHECKLEN(sockscf.state.pamservicename,
1622 pamservicename,
1623 sizeof(sockscf.state.pamservicename) - 1,
1624 yyerrorx);
1625 }
1626 #endif /* HAVE_PAM */
1627
1628 #if HAVE_BSDAUTH
1629 if (*sockscf.state.bsdauthstylename != NUL
1630 && bsdauthstylename != NULL) {
1631 if (strcmp(bsdauthstylename, sockscf.state.bsdauthstylename) != 0)
1632 STRCPY_CHECKLEN(sockscf.state.bsdauthstylename,
1633 bsdauthstylename,
1634 sizeof(sockscf.state.bsdauthstylename) - 1,
1635 yyerrorx);
1636 }
1637 #endif /* HAVE_BSDAUTH */
1638
1639 # if HAVE_LDAP
1640
1641 if (sockscf.state.ldapauthentication.ldapurl != NULL
1642 && ldapauthentication.ldapurl != NULL)
1643 sockscf.state.ldapauthentication.ldapurl = ldapauthentication.ldapurl;
1644
1645 if (*sockscf.state.ldapauthentication.certfile != NUL
1646 && *ldapauthentication.certfile != NUL)
1647 if (strcmp(ldapauthentication.certfile,
1648 sockscf.state.ldapauthentication.certfile) != 0)
1649 STRCPY_CHECKLEN(sockscf.state.ldapauthentication.certfile,
1650 ldapauthentication.certfile,
1651 sizeof(sockscf.state.ldapauthentication.certfile) - 1,
1652 yyerrorx);
1653
1654 if (*sockscf.state.ldapauthentication.certpath != NUL
1655 && *ldapauthentication.certpath != NUL)
1656 if (strcmp(ldapauthentication.certpath,
1657 sockscf.state.ldapauthentication.certpath) != 0)
1658 STRCPY_CHECKLEN(sockscf.state.ldapauthentication.certpath,
1659 ldapauthentication.certpath,
1660 sizeof(sockscf.state.ldapauthentication.certpath) - 1,
1661 yyerrorx);
1662
1663 if (*sockscf.state.ldapauthentication.keytab != NUL
1664 && *ldapauthentication.keytab != NUL)
1665 if (strcmp(ldapauthentication.keytab,
1666 sockscf.state.ldapauthentication.keytab) != 0)
1667 STRCPY_CHECKLEN(sockscf.state.ldapauthentication.keytab,
1668 ldapauthentication.keytab,
1669 sizeof(sockscf.state.ldapauthentication.keytab) - 1,
1670 yyerrorx);
1671
1672 if (ldom == -1
1673 && *ldapauthentication.domain != NUL)
1674 if (strcmp(ldapauthentication.domain,
1675 sockscf.state.ldapauthentication.domain) != 0)
1676 STRCPY_CHECKLEN(sockscf.state.ldapauthentication.domain,
1677 ldapauthentication.domain,
1678 sizeof(sockscf.state.ldapauthentication.domain) - 1,
1679 yyerrorx);
1680
1681 if (lfil == -1
1682 && *ldapauthentication.filter != NUL)
1683 if (strcmp(ldapauthentication.filter,
1684 sockscf.state.ldapauthentication.filter) != 0)
1685 STRCPY_CHECKLEN(sockscf.state.ldapauthentication.filter,
1686 ldapauthentication.filter,
1687 sizeof(sockscf.state.ldapauthentication.filter) - 1,
1688 yyerrorx);
1689
1690 if (sockscf.state.ldapauthentication.debug != LDAP_UNSET_DEBUG_VALUE
1691 && ldapauthentication.debug != LDAP_UNSET_DEBUG_VALUE)
1692 sockscf.state.ldapauthentication.debug = ldapauthentication.debug;
1693
1694 if (sockscf.state.ldapauthentication.auto_off != -1
1695 && ldapauthentication.auto_off != -1)
1696 sockscf.state.ldapauthentication.auto_off = ldapauthentication.auto_off;
1697
1698 if (sockscf.state.ldapauthentication.ssl != -1
1699 && ldapauthentication.ssl != -1)
1700 sockscf.state.ldapauthentication.ssl = ldapauthentication.ssl;
1701
1702 if (sockscf.state.ldapauthentication.certcheck != -1
1703 && ldapauthentication.certcheck != -1)
1704 sockscf.state.ldapauthentication.certcheck = ldapauthentication.certcheck;
1705
1706 if (sockscf.state.ldapauthentication.port != -1
1707 && ldapauthentication.port != -1)
1708 sockscf.state.ldapauthentication.port = ldapauthentication.port;
1709
1710 if (sockscf.state.ldapauthentication.portssl != -1
1711 && ldapauthentication.portssl != -1)
1712 sockscf.state.ldapauthentication.portssl = ldapauthentication.portssl;
1713
1714 #endif /* HAVE_LDAP */
1715
1716 #if HAVE_GSSAPI
1717 if (*sockscf.state.gssapiservicename != NUL
1718 && gssapiservicename != NULL) {
1719 if (strcmp(gssapiservicename, sockscf.state.gssapiservicename) != 0)
1720 STRCPY_CHECKLEN(sockscf.state.gssapiservicename,
1721 gssapiservicename,
1722 sizeof(sockscf.state.gssapiservicename) - 1,
1723 yyerrorx);
1724 }
1725
1726 if (*sockscf.state.gssapikeytab != NUL
1727 && gssapikeytab != NULL) {
1728 if (strcmp(gssapikeytab, sockscf.state.gssapikeytab) != 0)
1729 STRCPY_CHECKLEN(sockscf.state.gssapikeytab,
1730 gssapikeytab,
1731 sizeof(sockscf.state.gssapikeytab) - 1,
1732 yyerrorx);
1733 }
1734 #endif /* HAVE_GSSAPI */
1735
1736 /*
1737 * Go through all rules again and set default values for
1738 * authentication-methods based on the global method-lines, if none set.
1739 */
1740 #if BAREFOOTD
1741 if (sockscf.internal.addrc == 0 && ALL_UDP_BOUNCED())
1742 serrx("%s: no client-rules to accept clients on specified", function);
1743
1744 #else /* !BAREFOOTD */
1745 if (sockscf.internal.addrc == 0)
1746 serrx("%s: no internal address given for server to listen for clients on",
1747 function);
1748 #endif /* !BAREFOOTD */
1749
1750
1751 if (sockscf.external.addrc == 0)
1752 serrx("%s: no external address specified for server to use when "
1753 "forwarding data on behalf of clients",
1754 function);
1755
1756 if (sockscf.external.rotation == ROTATION_NONE) {
1757 size_t ipv4c = 0, ipv6c = 0;
1758
1759 for (i = 0; i < sockscf.external.addrc; ++i) {
1760 switch (sockscf.external.addrv[i].atype) {
1761 case SOCKS_ADDR_IPV4:
1762 ++ipv4c;
1763 break;
1764
1765 case SOCKS_ADDR_IPV6:
1766 ++ipv6c;
1767 break;
1768
1769 case SOCKS_ADDR_IFNAME:
1770 case SOCKS_ADDR_DOMAIN:
1771 break;
1772
1773 default:
1774 SERRX(sockscf.external.addrv[i].atype);
1775 }
1776 }
1777
1778 if (ipv4c > 1 || ipv6c > 1)
1779 swarnx("%s: more than one external address has been specified, but "
1780 "as long as external.rotation has the default value %s "
1781 "only the first address specified will be used",
1782 function, rotation2string(sockscf.external.rotation));
1783 }
1784
1785 if (sockscf.external.rotation == ROTATION_SAMESAME
1786 && sockscf.external.addrc == 1)
1787 swarnx("%s: rotation for external addresses is set to same-same, but "
1788 "the number of external addresses is only one, so this does "
1789 "not make sense",
1790 function);
1791
1792 if (sockscf.routeoptions.maxfail == 0 && sockscf.routeoptions.badexpire != 0)
1793 swarnx("%s: it does not make sense to set \"route.badexpire\" "
1794 "when \"route.maxfail\" is set to zero",
1795 function);
1796
1797 #if COVENANT
1798 if (*sockscf.realmname == NUL)
1799 STRCPY_ASSERTSIZE(sockscf.realmname, DEFAULT_REALMNAME);
1800 #endif /* COVENANT */
1801
1802 #if HAVE_SCHED_SETAFFINITY
1803 {
1804 const cpusetting_t *cpuv[] = { &sockscf.cpu.mother,
1805 &sockscf.cpu.monitor,
1806 &sockscf.cpu.negotiate,
1807 &sockscf.cpu.request,
1808 &sockscf.cpu.io };
1809
1810 const int proctypev[] = { PROC_MOTHER,
1811 PROC_MONITOR,
1812 PROC_NEGOTIATE,
1813 PROC_REQUEST,
1814 PROC_IO };
1815 size_t i;
1816
1817 for (i = 0; i < ELEMENTS(cpuv); ++i)
1818 if (cpuv[i]->affinity_isset && !sockd_cpuset_isok(&cpuv[i]->mask))
1819 serrx("%s: invalid cpu mask configured for %s process: %s",
1820 function,
1821 childtype2string(proctypev[i]),
1822 cpuset2string(&cpuv[i]->mask, NULL, 0));
1823 }
1824 #endif /* HAVE_SCHED_SETAFFINITY */
1825
1826 for (i = 0; i < sockscf.external.addrc; ++i)
1827 if (!addrisbindable(&sockscf.external.addrv[i]))
1828 serrx("%s: cannot bind external address #%ld: %s",
1829 function,
1830 (long)i,
1831 ruleaddr2string(&sockscf.external.addrv[i], 0, NULL, 0));
1832 }
1833
1834 void
add_external_safamily(safamily,globalscope)1835 add_external_safamily(safamily, globalscope)
1836 const sa_family_t safamily;
1837 const int globalscope;
1838 {
1839 switch (safamily) {
1840 case AF_INET:
1841 sockscf.external.protocol.hasipv4 = 1;
1842 break;
1843
1844 case AF_INET6:
1845 sockscf.external.protocol.hasipv6 = 1;
1846
1847 if (globalscope)
1848 sockscf.external.protocol.hasipv6_globalscope = 1;
1849
1850 break;
1851
1852 default:
1853 SERRX(safamily);
1854 }
1855 }
1856
1857
1858 int
external_has_safamily(safamily)1859 external_has_safamily(safamily)
1860 const sa_family_t safamily;
1861 {
1862 const char *function = "external_has_safamily()";
1863
1864 SASSERTX(sockscf.shmeminfo != NULL);
1865
1866 #if 0
1867 slog(LOG_DEBUG, "%s: hasipv4: %d, hasipv6: %d, hasipv6_globalscope: %d",
1868 function,
1869 sockscf.shmeminfo->state.external_hasipv4,
1870 sockscf.shmeminfo->state.external_hasipv6,
1871 sockscf.shmeminfo->state.external_hasipv6_globalscope);
1872 #endif
1873
1874 switch (safamily) {
1875 case AF_INET:
1876 return sockscf.external.protocol.hasipv4;
1877
1878 case AF_INET6:
1879 return sockscf.external.protocol.hasipv6;
1880
1881 default:
1882 SERRX(safamily);
1883 }
1884 }
1885
1886 void
add_internal_safamily(safamily)1887 add_internal_safamily(safamily)
1888 const sa_family_t safamily;
1889 {
1890 switch (safamily) {
1891 case AF_INET:
1892 sockscf.internal.protocol.hasipv4 = 1;
1893 break;
1894
1895 case AF_INET6:
1896 sockscf.internal.protocol.hasipv6 = 1;
1897 break;
1898
1899 default:
1900 SERRX(safamily);
1901 }
1902 }
1903
1904
1905 int
internal_has_safamily(safamily)1906 internal_has_safamily(safamily)
1907 const sa_family_t safamily;
1908 {
1909 const char *function = "internal_has_safamily()";
1910
1911 SASSERTX(sockscf.shmeminfo != NULL);
1912
1913 #if 0
1914 slog(LOG_DEBUG, "%s: hasipv4: %d, hasipv6: %d",
1915 function,
1916 sockscf.internal.protocol.hasipv4,
1917 sockscf.internal.protocol.hasipv6);
1918 #endif
1919
1920 switch (safamily) {
1921 case AF_INET:
1922 return sockscf.internal.protocol.hasipv4;
1923
1924 case AF_INET6:
1925 return sockscf.internal.protocol.hasipv6;
1926
1927 default:
1928 SERRX(safamily);
1929 }
1930 }
1931
1932 int
external_has_only_safamily(safamily)1933 external_has_only_safamily(safamily)
1934 const sa_family_t safamily;
1935 {
1936
1937 switch (safamily) {
1938 case AF_INET:
1939 return (external_has_safamily(AF_INET)
1940 && !external_has_safamily(AF_INET6));
1941
1942 case AF_INET6:
1943 return (external_has_safamily(AF_INET6)
1944 && !external_has_safamily(AF_INET));
1945
1946 default:
1947 SERRX(safamily);
1948 }
1949 }
1950
1951
1952 int
external_has_global_safamily(safamily)1953 external_has_global_safamily(safamily)
1954 const sa_family_t safamily;
1955 {
1956
1957 SASSERTX(sockscf.shmeminfo != NULL);
1958
1959 switch (safamily) {
1960 case AF_INET: /* don't care about scope for IPv4. */
1961 return sockscf.external.protocol.hasipv4;
1962
1963 case AF_INET6:
1964 return sockscf.external.protocol.hasipv6_globalscope;
1965
1966 default:
1967 SERRX(safamily);
1968 }
1969 }
1970
1971
1972
1973
1974 static void
add_more_old_shmem(config,memc,memv)1975 add_more_old_shmem(config, memc, memv)
1976 struct config *config;
1977 const size_t memc;
1978 const oldshmeminfo_t memv[];
1979 {
1980 const char *function = "add_more_old_shmem()";
1981 void *old;
1982 size_t i;
1983
1984 if ((old = realloc(config->oldshmemv,
1985 sizeof(*config->oldshmemv) * (config->oldshmemc + memc)))
1986 == NULL) {
1987 swarn("%s: could not allocate %lu bytes of memory to "
1988 "hold old shmids for later removal",
1989 function,
1990 (unsigned long)(sizeof(*config->oldshmemv)
1991 * (config->oldshmemc + memc)));
1992 return;
1993 }
1994 config->oldshmemv = old;
1995
1996 for (i = 0; i < memc; ++i) {
1997 const char *type;
1998
1999 switch (memv[i].type) {
2000 case SHMEM_BW:
2001 type = "bw";
2002 break;
2003
2004 case SHMEM_MONITOR:
2005 type = "monitor";
2006 break;
2007
2008 case SHMEM_SS:
2009 type = "session";
2010 break;
2011
2012 default:
2013 SERRX(memv[i].type);
2014 }
2015
2016 slog(LOG_DEBUG,
2017 "%s: saving old shmem-object of type %lu (%s), with "
2018 "shmid %lu/key %lu, at index #%lu, for removal upon exit",
2019 function,
2020 (unsigned long)memv[i].type,
2021 type,
2022 (unsigned long)memv[i].id,
2023 (unsigned long)memv[i].key,
2024 (unsigned long)i);
2025
2026 config->oldshmemv[config->oldshmemc++] = memv[i];
2027 }
2028 }
2029
2030 static int
safamily_isenabled(safamily,addrstr,side)2031 safamily_isenabled(safamily, addrstr, side)
2032 const sa_family_t safamily;
2033 const char *addrstr;
2034 const interfaceside_t side;
2035 {
2036 const char *function = "safamily_isenabled()";
2037 interfaceprotocol_t *interface;
2038 int isenabled;
2039
2040 switch (side) {
2041 case INTERNALIF:
2042 interface = &sockscf.internal.protocol;
2043 break;
2044
2045 case EXTERNALIF:
2046 interface = &sockscf.external.protocol;
2047 break;
2048
2049 default:
2050 SERRX(side);
2051 }
2052
2053 isenabled = 0;
2054 switch (safamily) {
2055 case AF_INET:
2056 if (interface->ipv4)
2057 isenabled = 1;
2058 break;
2059
2060 case AF_INET6:
2061 if (interface->ipv6)
2062 isenabled = 1;
2063 break;
2064
2065 default:
2066 SERRX(safamily);
2067 }
2068
2069 if (!isenabled)
2070 slog(LOG_DEBUG,
2071 "%s: address family %s option is not enabled on the %s-side "
2072 "interface. Can not use address \"%s\"",
2073 function,
2074 safamily2string(safamily),
2075 interfaceside2string(side),
2076 addrstr);
2077
2078 return isenabled;
2079 }
2080
2081 static int
addexternaladdr(ra)2082 addexternaladdr(ra)
2083 const struct ruleaddr_t *ra;
2084 {
2085 void *old;
2086
2087 switch (ra->atype) {
2088 case SOCKS_ADDR_IPV4:
2089 case SOCKS_ADDR_IPV6:
2090 if (!safamily_isenabled(atype2safamily(ra->atype),
2091 ruleaddr2string(ra, ADDRINFO_ATYPE, NULL, 0),
2092 EXTERNALIF))
2093 return -1;
2094 break;
2095
2096 default:
2097 /*
2098 * Will be resolved when needed.
2099 */
2100 break;
2101 }
2102
2103 old = realloc(sockscf.external.addrv,
2104 sizeof(*sockscf.external.addrv) * (sockscf.external.addrc + 1));
2105
2106 if (old == NULL)
2107 yyerror(NOMEM);
2108
2109 sockscf.external.addrv = old;
2110
2111 sockscf.external.addrv[sockscf.external.addrc++] = *ra;
2112 return 0;
2113 }
2114
2115
2116 static int
addinternaladdr(ifname,sa,protocol)2117 addinternaladdr(ifname, sa, protocol)
2118 const char *ifname;
2119 const struct sockaddr_storage *sa;
2120 const int protocol;
2121 {
2122 const char *function = "addinternaladdr()";
2123 void *old;
2124
2125 if (!safamily_isenabled(sa->ss_family,
2126 sockaddr2string2(sa, ADDRINFO_ATYPE, NULL, 0),
2127 INTERNALIF) != 0)
2128 return -1;
2129
2130 slog(LOG_DEBUG, "%s: adding address %s on nic %s to the internal list",
2131 function, sockaddr2string(sa, NULL, 0), ifname);
2132
2133 old = realloc(sockscf.internal.addrv,
2134 sizeof(*sockscf.internal.addrv) * (sockscf.internal.addrc + 1));
2135
2136 if (old == NULL)
2137 yyerror(NOMEM);
2138
2139 sockscf.internal.addrv = old;
2140
2141 #if 0
2142 bzero(&sockscf.internal.addrv[sockscf.internal.addrc],
2143 sizeof(sockscf.internal.addrv[sockscf.internal.addrc]));
2144 #endif
2145 sockaddrcpy(&sockscf.internal.addrv[sockscf.internal.addrc].addr,
2146 sa,
2147 sizeof(sockscf.internal.addrv[sockscf.internal.addrc].addr));
2148
2149 sockscf.internal.addrv[sockscf.internal.addrc].protocol = protocol;
2150 sockscf.internal.addrv[sockscf.internal.addrc].s = -1;
2151
2152 ++sockscf.internal.addrc;
2153
2154 add_internal_safamily(sa->ss_family);
2155
2156 return 0;
2157 }
2158