1 /*
2 * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2019, 2020, 2021
3 * Inferno Nettverk A/S, Norway. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. The above copyright notice, this list of conditions and the following
9 * disclaimer must appear in all copies of the software, derivative works
10 * or modified versions, and any portions thereof, aswell as in all
11 * supporting documentation.
12 * 2. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by
15 * Inferno Nettverk A/S, Norway.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Inferno Nettverk A/S requests users of this software to return to
31 *
32 * Software Distribution Coordinator or sdc@inet.no
33 * Inferno Nettverk A/S
34 * Oslo Research Park
35 * Gaustadall�en 21
36 * NO-0349 Oslo
37 * Norway
38 *
39 * any improvements or extensions that they make and grant Inferno Nettverk A/S
40 * the rights to redistribute these changes.
41 *
42 */
43
44 #include "common.h"
45 #include "monitor.h"
46 #include "config_parse.h"
47
48 static const char rcsid[] =
49 "$Id: rule.c,v 1.332.4.4.2.3.4.17 2021/02/27 15:27:17 karls Exp $";
50
51 #if HAVE_LIBWRAP
52 extern jmp_buf tcpd_buf;
53 int allow_severity, deny_severity;
54
55 static void
56 libwrapinit(int s, struct sockaddr_storage *local,
57 struct sockaddr_storage *peer, struct request_info *request);
58 /*
59 * Initializes "request" for later usage via libwrap.
60 * "s" is the socket the connection from "peer" was accepted on, with
61 * the local address of "s" being "local".
62 */
63
64 static int
65 libwrap_hosts_access(struct request_info *request,
66 const struct sockaddr_storage *peer);
67 /*
68 * Perform libwrap hosts_access() check on the client "peer".
69 */
70 #endif /* !HAVE_LIBWRAP */
71
72 static int
73 srchost_isok(const struct sockaddr_storage *peer, char *msg, size_t msgsize);
74 /*
75 * Checks whether the connection/packet from "peer" is ok, according
76 * to srchost-settings. If the connection/packet is not ok, "msg" is filled
77 * in with the reason why not.
78 *
79 * This function should be called after each rule check for a new
80 * connection/packet.
81 *
82 * Returns:
83 * If connection is acceptable: true
84 * If connection is not acceptable: false
85 */
86
87 static int
88 ruleaddr_matches_all_external(const ruleaddr_t *ruleaddr, const int protocol);
89 /*
90 * Returns true if the ruleaddress "ruleaddr" matches all external addresses
91 * we have configured for the protocol "protocol".
92 * Returns false otherwise.
93 */
94
95 static void
96 showlog(const log_t *log);
97 /*
98 * shows what type of logging is specified in "log".
99 */
100
101 static rule_t *
102 addrule(const rule_t *newrule, rule_t **rulebase, const objecttype_t ruletype);
103 /*
104 * Appends a copy of "newrule" to "rulebase", setting sensible defaults where
105 * appropriate.
106 *
107 * Returns a pointer to the added rule (not "newrule").
108 */
109
110 static void
111 checkrule(const rule_t *rule);
112 /*
113 * Check that the rule "rule" makes sense.
114 */
115
116 static void
117 log_shmeminherit(const rule_t *from, const rule_t *to, const int type,
118 const int isoverride);
119 /*
120 * Logs that shmem settings are inherited by rule "to" from rule "from",
121 * or that rule "to" overrides settings from rule "from", depending on
122 * whether isoverride is set or not.
123 * "type" must be the SHMEM_ type in question.
124 */
125
126 static void
127 log_inheritable(const char *prefix, const rule_t *rule,
128 const unsigned long shmid, const char *settings,
129 const int inheritable);
130 /*
131 * logs whether the "settings" settings belonging to shmid "shmid" in
132 * rule "rule" are inheritable or not, according to "inheritable".
133 */
134
135
136 rule_t *
addclientrule(newrule)137 addclientrule(newrule)
138 const rule_t *newrule;
139 {
140 const char *function = "addclientrule()";
141 rule_t *rule, ruletoadd;
142
143 ruletoadd = *newrule; /* for const. */
144
145 #if BAREFOOTD
146 /*
147 * In Barefoot the "to"/dst-address is the address we listen on for
148 * client-connections/packets. If that is a hostname/interface that
149 * expands to multiple IP-addresses, we need to listen on them all.
150 *
151 * We handle this by expanding the dst-address to the required number of
152 * addresses and creating separate rules for them all. This will mostly
153 * work as-is, but we need to make some modifications:
154 * - make sure all rules have the same rule number (the user has only
155 * created one rule, our problem that it expands to multiple rules).
156 * - make sure the shmem-objects reference the same shmem ids, as the
157 * limits/settings the user has specifed should be shared across
158 * all clients matching the rule(s).
159 */
160
161 switch (newrule->dst.atype) {
162 case SOCKS_ADDR_IPV4:
163 case SOCKS_ADDR_IPV6:
164 break;
165
166 case SOCKS_ADDR_DOMAIN:
167 case SOCKS_ADDR_IFNAME: {
168 struct sockaddr_storage sa, mask;
169 size_t i, rulenumber;
170 char emsg[1024], ifname[sizeof(newrule->dst.addr.ifname)],
171 hostname[sizeof(newrule->dst.addr.domain)];
172 int rc;
173
174 switch (newrule->dst.atype) {
175 case SOCKS_ADDR_DOMAIN:
176 STRCPY_ASSERTLEN(hostname, newrule->dst.addr.domain);
177 break;
178
179 case SOCKS_ADDR_IFNAME:
180 STRCPY_ASSERTLEN(ifname, newrule->dst.addr.ifname);
181 break;
182
183 default:
184 SERRX(newrule->dst.atype);
185 }
186
187 i = 0;
188 rulenumber = 0;
189
190 while (1) {
191 if (newrule->dst.atype == SOCKS_ADDR_DOMAIN) {
192 if (hostname2sockaddr2(hostname,
193 i,
194 &sa,
195 &rc,
196 emsg,
197 sizeof(emsg)) == NULL)
198 break;
199 }
200 else if (newrule->dst.atype == SOCKS_ADDR_IFNAME) {
201 if (ifname2sockaddr(ifname, i, &sa, &mask) == NULL) {
202 snprintf(emsg, sizeof(emsg),
203 "no usable IP-addresses found on interface %s",
204 ifname);
205 break;
206 }
207 }
208 else
209 SERRX(newrule->dst.atype);
210
211 slog(LOG_DEBUG, "%s: expanding address %s from %s %s",
212 function,
213 sockaddr2string2(&sa, 0, NULL, 0),
214 atype2string(newrule->dst.atype),
215 newrule->dst.atype == SOCKS_ADDR_DOMAIN ? hostname : ifname);
216
217 ruletoadd = *newrule;
218 switch (ruletoadd.dst.atype = safamily2atype(sa.ss_family)) {
219 case SOCKS_ADDR_IPV4:
220 ruletoadd.dst.addr.ipv4.ip = TOIN(&sa)->sin_addr;
221 ruletoadd.dst.addr.ipv4.mask.s_addr = htonl(IPV4_FULLNETMASK);
222 break;
223
224 case SOCKS_ADDR_IPV6:
225 ruletoadd.dst.addr.ipv6.ip = TOIN6(&sa)->sin6_addr;
226 ruletoadd.dst.addr.ipv6.maskbits = IPV6_NETMASKBITS;
227 ruletoadd.dst.addr.ipv6.scopeid = TOIN6(&sa)->sin6_scope_id;
228 break;
229
230 default:
231 SERRX(ruletoadd.dst.atype);
232 }
233
234 rule = addclientrule(&ruletoadd);
235
236 if (rulenumber == 0)
237 /*
238 * first expanded address we add for the original rule.
239 * Save the assigned rulenumber so we can use it for all
240 * rules/addresses expanded from this original rule.
241 */
242 rulenumber = rule->number;
243 else
244 rule->number = rulenumber;
245
246 ++i;
247 }
248
249 if (i == 0)
250 yyerrorx("could not determine IP-address to receive clients on: %s",
251 emsg);
252
253 return NULL;
254 }
255
256 default:
257 yyerrorx("addresses of type %s are not supported in the \"to\"-field "
258 "of %s",
259 atype2string(ruletoadd.dst.atype),
260 PRODUCT);
261 }
262 #endif /* BAREFOOTD */
263
264 rule = addrule(&ruletoadd, &sockscf.crule, object_crule);
265
266 checkrule(rule);
267
268 #if BAREFOOTD
269 if (rule->state.protocol.udp) {
270 /*
271 * Only one level of acls in Barefoot.
272 *
273 * In the tcp-case, we don't need any socks-rules; the client-rule
274 * is enough as the endpoints get fixed at session-establishment
275 * and we can just short-circuit the process because we know the
276 * session is allowed if it gets past the client-rule state.
277 *
278 * For udp, thins are similar, but on the reply-side things can
279 * vary if sockscf.udpconnectdst is not set. If it is not set,
280 * it means we should not connect to the target, and that means
281 * we will be able to receive reply-packets from addresses other
282 * than the target address. We want the client to be able to do
283 * that, if the Barefoot admin has explicitly allowed it by disabling
284 * sockscf.udpconnectdst. That however also means that there is
285 * no way to configure things so replies from only some targets
286 * are allowed; if sockscf.udpconnectdst is not set, replies from
287 * all targets will be allowed.
288 * The conclusion is thus that we do not need to generate any
289 * socks-rules for udp either; if the client rule permitted things,
290 * any corresponding socks-rule would too.
291 */
292 struct sockaddr_storage sa;
293
294 /*
295 * so we know there may be udp traffic to bounce (may, since this may
296 * be a sighup and the same rule being reloaded).
297 */
298 sockscf.state.alludpbounced = 0;
299
300 if (addrindex_on_listenlist(sockscf.internal.addrc,
301 sockscf.internal.addrv,
302 ruleaddr2sockaddr(&rule->dst, &sa, SOCKS_UDP),
303 SOCKS_UDP) == -1) {
304 /*
305 * add address to internal list also; need to listen for packets
306 * from udp clients.
307 */
308 addinternal(&rule->dst, SOCKS_UDP);
309 }
310 else {
311 slog(LOG_DEBUG,
312 "%s: not adding address %s from rule #%lu to internal list; "
313 "address already there",
314 function,
315 sockaddr2string(&sa, NULL, 0),
316 (unsigned long)rule->number);
317
318 rule->bounced = 1;
319 }
320 }
321 #endif /* BAREFOOTD */
322
323 return rule;
324 }
325
326 #if HAVE_SOCKS_HOSTID
327 rule_t *
addhostidrule(newrule)328 addhostidrule(newrule)
329 const rule_t *newrule;
330 {
331
332 rule_t *rule = addrule(newrule, &sockscf.hrule, object_hrule);
333 checkrule(rule);
334
335 return rule;
336 }
337 #endif /* HAVE_SOCKS_HOSTID */
338
339
340 rule_t *
addsocksrule(newrule)341 addsocksrule(newrule)
342 const rule_t *newrule;
343 {
344
345 rule_t *rule = addrule(newrule, &sockscf.srule, object_srule);
346 checkrule(rule);
347
348 return rule;
349 }
350
351 linkedname_t *
addlinkedname(linkedname,name)352 addlinkedname(linkedname, name)
353 linkedname_t **linkedname;
354 const char *name;
355 {
356 linkedname_t *user, *last;
357
358 if (name == NULL)
359 return NULL;
360
361 for (user = *linkedname, last = NULL; user != NULL; user = user->next)
362 last = user;
363
364 if ((user = malloc(sizeof(*user))) == NULL)
365 return NULL;
366
367 if ((user->name = strdup(name)) == NULL) {
368 free(user);
369 return NULL;
370 }
371
372 user->next = NULL;
373
374 if (last == NULL)
375 *linkedname = user;
376 else
377 last->next = user;
378
379 return *linkedname;
380 }
381
382 void
freelinkedname(list)383 freelinkedname(list)
384 linkedname_t *list;
385 {
386
387 while (list != NULL) {
388 linkedname_t *next = list->next;
389
390 free(list->name);
391 free(list);
392
393 list = next;
394 }
395 }
396
397 void
showrule(_rule,ruletype)398 showrule(_rule, ruletype)
399 const rule_t *_rule;
400 const objecttype_t ruletype;
401 {
402 const char *function = "showrule()";
403 rule_t rule = *_rule; /* shmat()/shmdt() changes rule. */
404 size_t bufused, i;
405 char buf[256];
406
407 slog(LOG_DEBUG, "%s #%lu, line #%lu",
408 objecttype2string(ruletype),
409 (unsigned long)rule.number,
410 (unsigned long)rule.linenumber);
411
412 slog(LOG_DEBUG, "verdict: %s", verdict2string(rule.verdict));
413
414 slog(LOG_DEBUG, "src: %s",
415 ruleaddr2string(&rule.src, ADDRINFO_PORT | ADDRINFO_ATYPE, NULL, 0));
416
417 slog(LOG_DEBUG, "dst: %s",
418 ruleaddr2string(&rule.dst, ADDRINFO_PORT | ADDRINFO_ATYPE, NULL, 0));
419
420 #if HAVE_SOCKS_HOSTID
421 if (rule.hostid.atype != SOCKS_ADDR_NOTSET)
422 slog(LOG_DEBUG, "hostindex: %d, hostid: %s",
423 rule.hostindex, ruleaddr2string(&rule.hostid, 0, NULL, 0));
424 #endif /* HAVE_SOCKS_HOSTID */
425
426 for (i = 0; i < rule.socketoptionc; ++i)
427 slog(LOG_DEBUG, "socketoption %s (%s side)",
428 sockopt2string(&rule.socketoptionv[i], NULL, 0),
429 rule.socketoptionv[i].isinternalside ? "internal" : "external");
430
431 switch (ruletype) {
432 case object_crule:
433 #if BAREFOOTD
434 slog(LOG_DEBUG, "bounce to: %s",
435 ruleaddr2string(&rule.extra.bounceto,
436 ADDRINFO_PORT | ADDRINFO_ATYPE,
437 NULL,
438 0));
439 #endif /* BAREFOOTD */
440 break;
441
442 #if HAVE_SOCKS_HOSTID
443 case object_hrule:
444 SASSERTX(rule.hostidoption_isset);
445 slog(LOG_DEBUG, "hostindex: %d", rule.hostindex);
446 break;
447 #endif /* HAVE_SOCKS_HOSTID */
448
449 #if HAVE_SOCKS_RULES
450 case object_srule:
451 break;
452 #endif /* HAVE_SOCKS_RULES */
453
454 default:
455 SERRX(ruletype);
456 }
457
458 /* only show if timeout differs from default. */
459 if (memcmp(&rule.timeout, &sockscf.timeout, sizeof(rule.timeout)) != 0)
460 showtimeout(&rule.timeout);
461
462 if (rule.udprange.op == range)
463 slog(LOG_DEBUG, "udp port range: %u - %u",
464 ntohs(rule.udprange.start), ntohs(rule.udprange.end));
465
466 if (rule.rdr_from.atype != SOCKS_ADDR_NOTSET)
467 slog(LOG_DEBUG, "redirect from: %s",
468 ruleaddr2string(&rule.rdr_from,
469 ADDRINFO_PORT | ADDRINFO_ATYPE,
470 NULL,
471 0));
472
473 if (rule.rdr_to.atype != SOCKS_ADDR_NOTSET)
474 slog(LOG_DEBUG, "redirect to: %s",
475 ruleaddr2string(&rule.rdr_to, ADDRINFO_PORT | ADDRINFO_ATYPE, NULL, 0));
476
477 if (sockd_shmat(&rule, SHMEM_ALL) != 0)
478 swarn("%s: could not attach to shmem segments for %s #%lu",
479 function, objecttype2string(rule.type), (unsigned long)rule.number);
480
481 if (rule.bw_shmid != 0) {
482 SASSERTX(rule.bw != NULL);
483
484 *buf = NUL;
485 bufused = 0;
486
487 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
488 "bw_shmid: %lu\n", (unsigned long)rule.bw_shmid);
489
490 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
491 "bandwidth limits inheritable: %s\n",
492 rule.bw_isinheritable ? "yes" : "no");
493
494 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
495 "max bandwidth allowed: %lu bytes/s\n",
496 (unsigned long)rule.bw->object.bw.maxbps);
497
498 SASSERTX(bufused > 0);
499 slog(LOG_DEBUG, "%s", buf);
500 }
501
502 if (rule.ss_shmid != 0) {
503 SASSERT(rule.ss != NULL);
504
505 *buf = NUL;
506 bufused = 0;
507
508 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
509 "ss_shmid: %lu\n", (unsigned long)rule.ss_shmid);
510
511 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
512 "sessions limits inheritable: %s\n",
513 rule.ss_isinheritable ? "yes" : "no");
514
515 if (rule.ss->object.ss.max_isset)
516 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
517 "session.max: %lu\n",
518 (unsigned long)rule.ss->object.ss.max);
519
520 if (rule.ss->object.ss.throttle_isset)
521 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
522 "session.throttle: %lu client%s per %lds\n",
523 (unsigned long)rule.ss->object.ss.throttle.limit.clients,
524 rule.ss->object.ss.throttle.limit.clients == 1 ? "" : "s",
525 (long)rule.ss->object.ss.throttle.limit.seconds);
526
527 if (rule.ss->keystate.key != key_unset) {
528 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
529 "session.state.key: %s\n",
530 statekey2string(rule.ss->keystate.key));
531
532 if (rule.ss->keystate.key == key_hostid) {
533 SASSERTX(rule.hostidoption_isset);
534 bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
535 "session.state.hostindex: %d\n",
536 rule.ss->keystate.keyinfo.hostindex);
537 }
538
539 if (rule.ss->object.ss.max_isset)
540 bufused +=
541 snprintf(&buf[bufused], sizeof(buf) - bufused,
542 "session.state.max : %lu\n",
543 (unsigned long)rule.ss->object.ss.max);
544
545 if (rule.ss->object.ss.throttle_perstate_isset)
546 bufused +=
547 snprintf(&buf[bufused], sizeof(buf) - bufused,
548 "session.state.throttle: %lu clients per %lds\n",
549 (unsigned long)rule.ss->object.ss.throttle.limit.clients,
550 (long)rule.ss->object.ss.throttle.limit.seconds);
551 }
552
553 SASSERTX(bufused > 0);
554 slog(LOG_DEBUG, "%s", buf);
555 }
556
557 sockd_shmdt(&rule, SHMEM_ALL);
558
559 showlist(rule.user, "user: ");
560 showlist(rule.group, "group: ");
561
562 #if HAVE_PAM
563 slog(LOG_DEBUG, "pam.servicename: %s", rule.state.pamservicename);
564 #endif /* HAVE_PAM */
565
566 #if HAVE_BSDAUTH
567 slog(LOG_DEBUG, "bsdauth.stylename: %s", rule.state.bsdauthstylename);
568 #endif /* HAVE_BSDAUTH */
569
570 #if HAVE_LDAP
571 /*
572 * Does this rule have specific settings for performing LDAP-based
573 * authentication of the client?
574 */
575 if (rule.state.ldapauthentication.ldapurl != NULL ||
576 rule.state.ldapauthentication.ldapserver != NULL ||
577 rule.state.ldapauthentication.ldapbasedn != NULL ||
578 *rule.state.ldapauthentication.domain != NUL) {
579 /*
580 * Yes.
581 */
582 const ldapauthentication_t *ldapauthentication
583 = &rule.state.ldapauthentication;
584
585 showlist(ldapauthentication->ldapbasedn, "ldapauth.auth.basedn: ");
586
587 slog(LOG_DEBUG, "ldapauth.auth.auto.off: %s",
588 ldapauthentication->auto_off ? "yes" : "no");
589
590 slog(LOG_DEBUG, "ldapauth.auth.debug: %d", ldapauthentication->debug);
591
592 if (*ldapauthentication->keytab != NUL)
593 slog(LOG_DEBUG,
594 "ldapauth.auth.keytab: %s", ldapauthentication->keytab);
595
596 if (ldapauthentication->ldapurl != NULL)
597 slog(LOG_DEBUG,
598 "ldapauth.auth.url: <value set, but not displayed for security reasons "
599 "as it may contain passwords>");
600 else
601 showlist(ldapauthentication->ldapserver, "ldap.server: ");
602
603 if (*ldapauthentication->filter != NUL)
604 slog(LOG_DEBUG,
605 "ldapauth.auth.filter: %s", ldapauthentication->filter);
606
607 if (*ldapauthentication->domain != NUL)
608 slog(LOG_DEBUG,
609 "ldapauth.auth.domain: %s", ldapauthentication->domain);
610
611 slog(LOG_DEBUG, "ldapauth.auth.port: %d", ldapauthentication->port);
612 slog(LOG_DEBUG, "ldapauth.auth.portssl: %d", ldapauthentication->portssl);
613
614 slog(LOG_DEBUG, "ldapauth.auth.ssl: %s",
615 ldapauthentication->ssl ? "yes" : "no");
616
617 slog(LOG_DEBUG, "ldapauth.auth.certcheck: %s",
618 ldapauthentication->certcheck ? "yes" : "no");
619
620 if (*ldapauthentication->certfile != NUL)
621 slog(LOG_DEBUG,
622 "ldapauth.auth.certfile: %s", ldapauthentication->certfile);
623
624 if (*ldapauthentication->certpath != NUL)
625 slog(LOG_DEBUG,
626 "ldapauth.auth.certpath: %s", ldapauthentication->certpath);
627 }
628
629 /*
630 * Specific LDAP-based authorization settings set for this rule?
631 */
632 if (rule.ldapgroup != NULL) {
633 /*
634 * Yes.
635 */
636 const ldapauthorisation_t *ldapauthorisation
637 = &rule.state.ldapauthorisation;
638
639 showlist(rule.ldapgroup, "ldap.group: ");
640
641 if (*ldapauthorisation->domain != NUL)
642 slog(LOG_DEBUG, "ldap.domain: %s", ldapauthorisation->domain);
643
644 slog(LOG_DEBUG,
645 "ldap.auto.off: %s", ldapauthorisation->auto_off ? "yes" : "no");
646
647 slog(LOG_DEBUG, "ldap.debug: %d", ldapauthorisation->debug);
648
649 slog(LOG_DEBUG,
650 "ldap.keeprealm: %s", ldapauthorisation->keeprealm ? "yes" : "no");
651
652 if (*ldapauthorisation->keytab != NUL)
653 slog(LOG_DEBUG, "ldap.keytab: %s", ldapauthorisation->keytab);
654
655 if (ldapauthorisation->ldapurl != NULL)
656 slog(LOG_DEBUG,
657 "ldap.url: <value set, but not displayed for security reasons "
658 "as it may contain passwords>");
659 else
660 showlist(ldapauthorisation->ldapserver, "ldap.server: ");
661
662 showlist(ldapauthorisation->ldapbasedn, "ldap.basedn: ");
663
664 if (*ldapauthorisation->filter != NUL)
665 slog(LOG_DEBUG, "ldap.filter: %s", ldapauthorisation->filter);
666
667 if (*ldapauthorisation->filter_AD != NUL)
668 slog(LOG_DEBUG, "ldap.filter.ad: %s", ldapauthorisation->filter_AD);
669
670 if (*ldapauthorisation->attribute != NUL)
671 slog(LOG_DEBUG, "ldap.attribute: %s", ldapauthorisation->attribute);
672
673 if (*ldapauthorisation->attribute_AD != NUL)
674 slog(LOG_DEBUG,
675 "ldap.attribute.ad: %s", ldapauthorisation->attribute_AD);
676
677 slog(LOG_DEBUG, "ldap.mdepth: %d", ldapauthorisation->mdepth);
678 slog(LOG_DEBUG, "ldap.port: %d", ldapauthorisation->port);
679 slog(LOG_DEBUG, "ldap.portssl: %d", ldapauthorisation->portssl);
680
681 slog(LOG_DEBUG, "ldap.ssl: %s", ldapauthorisation->ssl ? "yes" : "no");
682
683 slog(LOG_DEBUG,
684 "ldap.certcheck: %s", ldapauthorisation->certcheck ? "yes" : "no");
685
686 if (*ldapauthorisation->certfile != NUL)
687 slog(LOG_DEBUG, "ldap.certfile: %s", ldapauthorisation->certfile);
688
689 if (*ldapauthorisation->certpath != NUL)
690 slog(LOG_DEBUG, "ldap.certpath: %s", ldapauthorisation->certpath);
691 }
692
693 #endif /* HAVE_LDAP */
694
695 #if HAVE_PAC
696
697 showlist(rule.objectsids, "pac.sids: ");
698 slog(LOG_DEBUG, "pac.off: %s", rule.pacoff ? "yes" : "no");
699
700 #endif /* HAVE_PAC */
701
702 showstate(&rule.state);
703
704 showlog(&rule.log);
705
706 #if HAVE_LIBWRAP
707
708 if (*rule.libwrap != NUL)
709 slog(LOG_DEBUG, "libwrap: %s", rule.libwrap);
710
711 #endif /* HAVE_LIBWRAP */
712 }
713
714 int
rulespermit(s,peer,local,clientauth,srcauth,match,state,src,dst,dstmatched,msg,msgsize)715 rulespermit(s, peer, local, clientauth, srcauth, match, state,
716 src, dst, dstmatched, msg, msgsize)
717 int s;
718 const struct sockaddr_storage *peer;
719 const struct sockaddr_storage *local;
720 const authmethod_t *clientauth;
721 authmethod_t *srcauth;
722 rule_t *match;
723 connectionstate_t *state;
724 const sockshost_t *src;
725 const sockshost_t *dst;
726 sockshost_t *dstmatched;
727 char *msg;
728 size_t msgsize;
729 {
730 const char *function = "rulespermit()";
731 static int init;
732 static rule_t defrule;
733 rule_t *rule;
734 objecttype_t ruletype;
735 authmethod_t oldauth;
736 sockshost_t dstmatched_mem;
737 #if HAVE_LIBWRAP
738 struct request_info libwraprequest;
739 struct sockaddr_storage _local, _peer;
740 unsigned libwrapinited = 0;
741 #endif /* !HAVE_LIBWRAP */
742 unsigned isreplycommand;
743 char srcstr[MAXSOCKSHOSTSTRING], dststr[MAXSOCKSHOSTSTRING],
744 lstr[MAXSOCKADDRSTRING], pstr[MAXSOCKADDRSTRING];
745
746 if (dstmatched == NULL)
747 dstmatched = &dstmatched_mem;
748
749 if (s != -1) {
750 SASSERTX(local != NULL);
751 SASSERTX(peer != NULL);
752
753 #if HAVE_LIBWRAP /* libwrap wants non-const. */
754 sockaddrcpy(&_local, local, salen(local->ss_family));
755 sockaddrcpy(&_peer, peer, salen(peer->ss_family));
756 #endif /* !HAVE_LIBWRAP */
757 }
758
759 SASSERTX(srcauth != NULL);
760
761 slog(LOG_DEBUG,
762 "%s: %s -> %s, clientauth %s, srcauth %s, command %s, fd %d "
763 "from %s, accepted on %s",
764 function,
765 src == NULL ? "N/A" : sockshost2string(src, srcstr, sizeof(srcstr)),
766 dst == NULL ? "N/A" : sockshost2string(dst, dststr, sizeof(dststr)),
767 clientauth == NULL ? "N/A" : method2string(clientauth->method),
768 method2string(srcauth->method),
769 command2string(state->command),
770 s,
771 peer == NULL ? "N/A" : sockaddr2string(peer, pstr, sizeof(pstr)),
772 local == NULL ? "N/A" : sockaddr2string(local, lstr, sizeof(lstr)));
773
774 if (msgsize > 0)
775 *msg = NUL;
776
777 /* make a somewhat sensible default rule for entries with no match. */
778 if (!init) {
779 bzero(&defrule, sizeof(defrule));
780
781 defrule.verdict = VERDICT_BLOCK;
782 defrule.src.atype = SOCKS_ADDR_IPVANY;
783
784 defrule.dst = defrule.src;
785
786 #if BAREFOOTD
787 defrule.extra.bounceto.atype = SOCKS_ADDR_IPV4;
788 #endif /* BAREFOOTD */
789
790 if (sockscf.option.debug) {
791 defrule.log.connect = 1;
792 defrule.log.disconnect = 1;
793 defrule.log.error = 1;
794 defrule.log.iooperation = 1;
795 }
796
797 memset(&defrule.state.command, UCHAR_MAX, sizeof(defrule.state.command));
798
799 memset(&defrule.state.protocol,
800 UCHAR_MAX,
801 sizeof(defrule.state.protocol));
802
803 memset(&defrule.state.proxyprotocol,
804 UCHAR_MAX,
805 sizeof(defrule.state.proxyprotocol));
806
807 init = 1;
808 }
809
810 /*
811 * what rulebase to use.
812 */
813 switch (state->command) {
814 case SOCKS_ACCEPT:
815 case SOCKS_BOUNCETO:
816 ruletype = object_crule;
817 rule = sockscf.crule;
818 break;
819
820 #if HAVE_SOCKS_HOSTID
821 case SOCKS_HOSTID:
822 ruletype = object_hrule;
823 rule = sockscf.hrule;
824 break;
825 #endif /* HAVE_SOCKS_HOSTID */
826
827 default:
828 ruletype = object_srule;
829 rule = sockscf.srule;
830 break;
831 }
832
833
834 #if HAVE_LIBWRAP
835 if (s != -1 && sockscf.option.hosts_access) {
836 libwrapinit(s, &_local, &_peer, &libwraprequest);
837 libwrapinited = 1;
838
839 if (libwrap_hosts_access(&libwraprequest, peer) == 0) {
840 snprintf(msg, msgsize, "blocked by libwrap/tcp_wrappers");
841
842 *match = defrule;
843 match->type = ruletype;
844
845 return 0;
846 }
847 }
848 #endif /* HAVE_LIBWRAP */
849
850 if (state->extension.bind && !sockscf.extension.bind) {
851 snprintf(msg, msgsize, "client requested disabled Dante extension: bind");
852
853 *match = defrule;
854 match->type = ruletype;
855
856 return 0; /* will never succeed. */
857 }
858
859 #if HAVE_SOCKS_HOSTID
860 if (ruletype == object_crule) { /*
861 * only need to check once; presumably
862 * hostids do not get added to the
863 * session by the client later.
864 */
865 if (s == -1)
866 HOSTIDZERO(state);
867 else {
868 SASSERTX(peer != NULL);
869
870 state->hostidc = getsockethostid(s,
871 ELEMENTS(state->hostidv),
872 state->hostidv);
873
874 slog(LOG_DEBUG, "%s: retrieved %u hostids on connection from %s",
875 function,
876 (unsigned)state->hostidc,
877 sockaddr2string(peer, NULL, 0));
878 }
879 }
880
881 if (ruletype == object_hrule && state->hostidc == 0 ) {
882 SASSERTX(sockscf.hrule != NULL);
883
884 slog(LOG_DEBUG,
885 "%s: no hostid set on connection from client - can not match any "
886 "%s, so ignoring %ss for this client as per spec",
887 function, objecttype2string(ruletype), objecttype2string(ruletype));
888
889 *match = defrule;
890 match->type = ruletype;
891 match->verdict = VERDICT_PASS;
892
893 return 1;
894 }
895 #endif /* HAVE_SOCKS_HOSTID */
896
897 if (state->command == SOCKS_BINDREPLY
898 || state->command == SOCKS_UDPREPLY)
899 isreplycommand = 1;
900 else
901 isreplycommand = 0;
902
903 /*
904 * let srcauth be unchanged from original unless we actually get a match.
905 */
906 for (oldauth = *srcauth;
907 rule != NULL;
908 rule = rule->next, *srcauth = oldauth) {
909 size_t methodc;
910 int *methodv;
911 size_t i;
912 int sidmatched = 0;
913
914 slog(LOG_DEBUG,
915 "%s: trying to match against %s-rule #%lu, verdict = %s",
916 function,
917 objecttype2string(ruletype),
918 (unsigned long)rule->number,
919 verdict2string(rule->verdict));
920
921 if (!protocol_matches(state->protocol, &rule->state.protocol))
922 continue;
923
924 if (!command_matches(state->command, &rule->state.command))
925 continue;
926
927 /* current rule covers desired version? */
928 if (ruletype == object_srule) { /* no version check for other rules. */
929 if (!proxyprotocol_matches(state->proxyprotocol,
930 &rule->state.proxyprotocol))
931 continue;
932 }
933
934 #if HAVE_SOCKS_HOSTID
935 if (rule->hostid.atype != SOCKS_ADDR_NOTSET) {
936 slog(LOG_DEBUG, "%s: rule %lu requires hostid to be present on the "
937 "connection, checking ...",
938 function,
939 (unsigned long)rule->number);
940
941 if (!hostidmatches(state->hostidc,
942 state->hostidv,
943 rule->hostindex,
944 &rule->hostid,
945 ruletype,
946 rule->number))
947 continue;
948 }
949 #endif /* HAVE_SOCKS_HOSTID */
950
951 /*
952 * This is a little tricky. For some commands we may not have
953 * all info at time of (preliminary) rule checks. What we want
954 * to do if there is no (complete) address given is to see if
955 * there's any chance at all the rules will permit this request
956 * when the address (later) becomes available. We therefore
957 * continue to scan the rules until we either get a pass
958 * (ignoring peer with missing info), or the default block is
959 * triggered.
960 * This is the case for e.g. bindreply and udp, where we will
961 * have to call this function again when we get the addresses in
962 * question.
963 */
964
965 if (src != NULL) {
966 #if HAVE_SOCKS_HOSTID
967 if (ruletype == object_hrule) {
968 slog(LOG_DEBUG, "%s: checking against hostids rather than "
969 "physical address %s",
970 function, sockshost2string(src, NULL, 0));
971
972 if (!hostidmatches(state->hostidc,
973 state->hostidv,
974 rule->hostindex,
975 &rule->src,
976 ruletype,
977 rule->number))
978 continue;
979 }
980 else /* hostid matches, check the remaining fields too. */
981 #endif /* HAVE_SOCKS_HOSTID */
982 if (!addrmatch(&rule->src, src, NULL, state->protocol, 0))
983 continue;
984 }
985 else
986 if (rule->verdict == VERDICT_BLOCK)
987 continue; /* don't have complete address. */
988
989 if (dst != NULL) {
990 if (!addrmatch(&rule->dst, dst, dstmatched, state->protocol, 0))
991 continue;
992 }
993 else {
994 if (rule->verdict == VERDICT_BLOCK) {
995 /*
996 * don't have a complete address tuple, so see if it's possible
997 * to find a pass rule matching what info we have.
998 * If we do, it's possible the rules will permit when we have the
999 * complete address tuple and are ready to do i/o at some later
1000 * point. If not, can return a block verdict now, as there is
1001 * no way things will pass later.
1002 */
1003 const int dstmatchesall
1004 = ruleaddr_matches_all_external(&rule->dst, state->protocol);
1005
1006 slog(LOG_DEBUG,
1007 "%s: dst ruleaddr %s %s limited to certain addresses, so %s "
1008 "decide for sure now whether it will match all future target "
1009 "addresses from this client",
1010 function,
1011 ruleaddr2string(&rule->dst,
1012 ADDRINFO_PORT | ADDRINFO_ATYPE,
1013 NULL,
1014 0),
1015 dstmatchesall ? "is not" : "is",
1016 dstmatchesall ? "can" : "can not");
1017
1018 if (dstmatchesall) {
1019 SASSERTX(src != NULL);
1020 /*
1021 * this rule matches any dst and since src has
1022 * already been verified to match, this is the rule
1023 * that will match any dst from this src.
1024 */
1025 }
1026 else
1027 /*
1028 * this block-rule only matches some targets, other rules may
1029 * match other targets and let packets from the client through.
1030 */
1031 continue;
1032 }
1033 }
1034
1035 /*
1036 * What methods does this rule require?
1037 * - Client-rules require clientmethods.
1038 * - Socks-rules require both the socksmethod and the underlying
1039 * clientmethod to match.
1040 */
1041
1042 switch (ruletype) {
1043 case object_crule:
1044 #if HAVE_SOCKS_HOSTID
1045 case object_hrule:
1046 #endif /* HAVE_SOCKS_HOSTID */
1047 methodv = rule->state.cmethodv;
1048 methodc = rule->state.cmethodc;
1049 break;
1050
1051 case object_srule:
1052 if (isreplycommand) {
1053 SASSERTX(clientauth == NULL);
1054
1055 slog(LOG_DEBUG,
1056 "%s: is a replycommand. No underlying clientauth to match",
1057 function);
1058 }
1059 else {
1060 SASSERTX(clientauth != NULL);
1061 SASSERTX(clientauth->method != AUTHMETHOD_NOTSET);
1062
1063 if (!methodisset(clientauth->method,
1064 rule->state.cmethodv,
1065 rule->state.cmethodc)) {
1066 slog(LOG_DEBUG,
1067 "%s: client uses a clientmethod (%s) that is not set "
1068 "in the list over clientmethods to match for this rule",
1069 function, method2string(clientauth->method));
1070
1071 continue;
1072 }
1073 }
1074
1075 methodv = rule->state.smethodv;
1076 methodc = rule->state.smethodc;
1077 break;
1078
1079 default:
1080 SERRX(object_srule);
1081 }
1082
1083
1084 /*
1085 * Does this rule's authentication requirements match the current
1086 * authentication in use by the client?
1087 */
1088 if (isreplycommand && !sockscf.srchost.checkreplyauth) {
1089 /*
1090 * checkreplyauth not set, so should not check auth on replies.
1091 */
1092 srcauth->method = AUTHMETHOD_NONE;
1093 }
1094 else if (!methodisset(srcauth->method, methodv, methodc)) {
1095 /*
1096 * Auth used by client at the moment does not match. There are
1097 * however some methods on which it's possible to get a match on
1098 * even if it is not the method currently used by the client.
1099 * This is done by changing/upgrading the method, if possible.
1100 *
1101 * E.g. if the client is using method NONE (or any other),
1102 * it might still be possible to change the authentication to
1103 * AUTHMETHOD_RFC931, or AUTHMETHOD_PAM_ADDRESS.
1104 * Likewise, if the current method is AUTHMETHOD_USERNAME, it can
1105 * be changed to AUTHMETHOD_BSDAUTH or AUTHMETHOD_PAM_USERNAME.
1106 *
1107 * We therefore look at what methods this rule requires and see
1108 * if can match it with what the client _can_ provide, if we
1109 * do some more work to get that information.
1110 */
1111
1112 /*
1113 * This variable only says if we have the necessary information to
1114 * check one of the methods required by the current rule.
1115 *
1116 * It does *not* mean the information was checked. I.e. if it's
1117 * AUTHMETHOD_RFC931, and methodischeckable is set, it means we
1118 * were able to retrieve rfc931 info, but not that we checked the
1119 * retrieved information against anything.
1120 * We will have to check the information as normal (as if this
1121 * was the authmethod set already, which we now need to check).
1122 */
1123 size_t methodischeckable = 0;
1124
1125 /*
1126 * Go through all methods this rule supports and see if
1127 * we can get a match by modifying the authmethod the client
1128 * is currently using.
1129 */
1130 for (i = 0; i < methodc; ++i) {
1131 if (sockscf.option.debug >= DEBUG_VERBOSE)
1132 slog(LOG_DEBUG, "%s: no match yet for method %s, command %s",
1133 function,
1134 method2string(methodv[i]),
1135 command2string(state->command));
1136
1137 switch (methodv[i]) {
1138 case AUTHMETHOD_NONE:
1139 /*
1140 * Rule requires authmethod none, but that does
1141 * not match current authentication in use by the
1142 * client. If clients authmethod is not yet set,
1143 * we can set it to none however.
1144 */
1145 if (srcauth->method == AUTHMETHOD_NOTSET)
1146 methodischeckable = 1;
1147
1148 break;
1149
1150 #if HAVE_LIBWRAP
1151 case AUTHMETHOD_RFC931: {
1152 /*
1153 * Rule supports rfc931. No matter what method the
1154 * client is currently using, we can always attempt
1155 * to do a rfc931 lookup to get the rfc931 name as
1156 * long as we have a tcp connection.
1157 */
1158 const char *evaleduser;
1159
1160 if (clientauth != NULL
1161 && clientauth->method == AUTHMETHOD_RFC931) {
1162 slog(LOG_DEBUG,
1163 "%s: already have %s name %s from "
1164 "clientauthentication done before. No need to "
1165 "do lookup again, but can just copy the data "
1166 "provided during the earlier rfc931 lookup",
1167 function,
1168 method2string(methodv[i]),
1169 clientauth->mdata.rfc931.name);
1170
1171 srcauth->mdata.rfc931 = clientauth->mdata.rfc931;
1172 }
1173 else {
1174 /*
1175 * Need to do a lookup. RFC931 requires a tcp
1176 * connection, so won't work in Barefoot's udp
1177 * case, where we only have a udp socket.
1178 */
1179 int errno_s = errno;
1180
1181 #if !HAVE_CONTROL_CONNECTION
1182 if (state->protocol == SOCKS_UDP)
1183 break;
1184 #endif /* !HAVE_CONTROL_CONNECTION */
1185
1186 if (!libwrapinited) {
1187 libwrapinit(s,
1188 &_local,
1189 &_peer,
1190 &libwraprequest);
1191
1192 libwrapinited = 1;
1193 }
1194
1195 if (errno != 0 && errno != errno_s) {
1196 slog(LOG_DEBUG,
1197 "%s: libwrapinit() set errno to %d (%s)",
1198 function, errno, strerror(errno));
1199
1200 errno = errno_s = 0;
1201 }
1202
1203 SASSERTX(peer != NULL);
1204
1205 slog(LOG_DEBUG, "%s: trying to get rfc931 name for %s",
1206 function, sockaddr2string(peer, NULL, 0));
1207
1208 if ((evaleduser = eval_user(&libwraprequest)) == NULL) {
1209 slog(LOG_DEBUG, "%s: eval_user() failed: %s",
1210 function, strerror(errno));
1211
1212 if (errno != 0 && errno != errno_s)
1213 errno = 0;
1214
1215 break;
1216 }
1217
1218 strncpy((char *)srcauth->mdata.rfc931.name,
1219 evaleduser,
1220 sizeof(srcauth->mdata.rfc931.name) - 1);
1221
1222 if (errno != 0 && errno != errno_s) {
1223 slog(LOG_DEBUG,
1224 "%s: eval_user() set errno to %d (%s)",
1225 function, errno, strerror(errno));
1226
1227 errno = 0;
1228 }
1229
1230 /* libwrap sets this if no identreply. */
1231 if (strcmp((char *)srcauth->mdata.rfc931.name,
1232 STRING_UNKNOWN) == 0) {
1233 *srcauth->mdata.rfc931.name = NUL;
1234 slog(LOG_DEBUG, "%s: no rfc931 name", function);
1235 }
1236 else if (srcauth->mdata.rfc931.name[
1237 sizeof(srcauth->mdata.rfc931.name) - 1] != NUL) {
1238
1239 srcauth->mdata.rfc931.name[
1240 sizeof(srcauth->mdata.rfc931.name) - 1] = NUL;
1241
1242 slog(LOG_NOTICE,
1243 "%s: Strange. RFC931 name \"%s...\" returned "
1244 "from %s is too long. Max length is %lu",
1245 function,
1246 srcauth->mdata.rfc931.name,
1247 sockaddr2string(peer, NULL, 0),
1248 (unsigned long)
1249 (sizeof(srcauth->mdata.rfc931.name) - 1));
1250
1251 *srcauth->mdata.rfc931.name = NUL; /* unusable. */
1252 }
1253 else
1254 slog(LOG_DEBUG, "%s: received rfc931 name \"%s\"",
1255 function, srcauth->mdata.rfc931.name);
1256 }
1257
1258 if (*srcauth->mdata.rfc931.name != NUL)
1259 methodischeckable = 1;
1260 break;
1261 }
1262 #endif /* HAVE_LIBWRAP */
1263
1264 #if HAVE_PAM
1265 case AUTHMETHOD_PAM_ANY:
1266 case AUTHMETHOD_PAM_ADDRESS:
1267 case AUTHMETHOD_PAM_USERNAME: {
1268 /*
1269 * Rule supports PAM. PAM can support username/password,
1270 * just username, or neither username nor password (i.e.
1271 * ip-address-only auth.
1272 */
1273 switch (srcauth->method) {
1274 case AUTHMETHOD_UNAME: {
1275 /*
1276 * similar enough, just copy name/password from pam
1277 * uname struct.
1278 */
1279 const authmethod_uname_t uname = srcauth->mdata.uname;
1280
1281 STRCPY_ASSERTSIZE(srcauth->mdata.pam.name, uname.name);
1282
1283 STRCPY_ASSERTSIZE(srcauth->mdata.pam.password,
1284 uname.password);
1285
1286 methodischeckable = 1;
1287 break;
1288 }
1289
1290 #if HAVE_BSDAUTH
1291 case AUTHMETHOD_BSDAUTH: {
1292 const authmethod_bsd_t bsd = srcauth->mdata.bsd;
1293
1294 STRCPY_ASSERTSIZE(srcauth->mdata.pam.name, bsd.name);
1295
1296 STRCPY_ASSERTSIZE(srcauth->mdata.pam.password,
1297 bsd.password);
1298
1299 methodischeckable = 1;
1300 break;
1301 }
1302 #endif /* HAVE_BSDAUTH */
1303
1304 #if HAVE_LIBWRAP
1305 case AUTHMETHOD_RFC931: {
1306 /*
1307 * no password, but we can check the username
1308 * we got from ident, with an empty password,
1309 * against the pam-database.
1310 */
1311 const authmethod_rfc931_t rfc931
1312 = srcauth->mdata.rfc931;
1313
1314
1315 STRCPY_ASSERTSIZE(srcauth->mdata.pam.name,
1316 rfc931.name);
1317
1318 *srcauth->mdata.pam.password = NUL;
1319
1320 methodischeckable = 1;
1321 break;
1322 }
1323 #endif /* HAVE_LIBWRAP */
1324
1325 case AUTHMETHOD_NOTSET:
1326 case AUTHMETHOD_NONE:
1327 if (methodv[i] == AUTHMETHOD_PAM_ANY
1328 || methodv[i] == AUTHMETHOD_PAM_ADDRESS) {
1329 *srcauth->mdata.pam.name = NUL;
1330 *srcauth->mdata.pam.password = NUL;
1331
1332 methodischeckable = 1;
1333 }
1334
1335 break;
1336 }
1337
1338 if (methodischeckable)
1339 STRCPY_ASSERTSIZE(srcauth->mdata.pam.servicename,
1340 rule->state.pamservicename);
1341
1342 break;
1343 }
1344 #endif /* HAVE_PAM */
1345
1346 #if HAVE_BSDAUTH
1347 case AUTHMETHOD_BSDAUTH: {
1348 /*
1349 * Requires username and password, but assume
1350 * the password can also be empty.
1351 */
1352
1353 switch (srcauth->method) {
1354 case AUTHMETHOD_UNAME: {
1355 const authmethod_uname_t uname
1356 = srcauth->mdata.uname;
1357
1358 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.name, uname.name);
1359
1360 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.password,
1361 uname.password);
1362
1363 methodischeckable = 1;
1364 break;
1365 }
1366
1367 #if HAVE_PAM
1368 case AUTHMETHOD_PAM_USERNAME: {
1369 const authmethod_pam_t pam
1370 = srcauth->mdata.uname;
1371
1372 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.name,
1373 pam.name);
1374
1375 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.password,
1376 pam.password);
1377
1378 methodischeckable = 1;
1379 break;
1380 }
1381 #endif /* HAVE_PAM */
1382
1383 #if HAVE_LIBWRAP
1384 case AUTHMETHOD_RFC931: {
1385 const authmethod_rfc931_t rfc931
1386 = srcauth->mdata.rfc931;
1387
1388 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.name,
1389 rfc931.name);
1390
1391 *srcauth->mdata.bsd.password = NUL;
1392
1393 methodischeckable = 1;
1394 break;
1395 }
1396 #endif /* HAVE_LIBWRAP */
1397 }
1398
1399 if (methodischeckable)
1400 STRCPY_ASSERTSIZE(srcauth->mdata.bsd.style,
1401 rule->state.bsdauthstylename);
1402 break;
1403 }
1404 #endif /* HAVE_BSDAUTH */
1405
1406
1407 #if SOCKS_SERVER
1408 #if HAVE_LDAP
1409 case AUTHMETHOD_LDAPAUTH: {
1410 switch (srcauth->method) {
1411 case AUTHMETHOD_UNAME: {
1412 const authmethod_uname_t uname
1413 = srcauth->mdata.uname;
1414
1415 STRCPY_ASSERTSIZE(srcauth->mdata.ldap.name,
1416 uname.name);
1417
1418 STRCPY_ASSERTSIZE(srcauth->mdata.ldap.password,
1419 uname.password);
1420
1421 srcauth->mdata.ldap.ldapauthentication
1422 = rule->state.ldapauthentication;
1423
1424 methodischeckable = 1;
1425 break;
1426 }
1427 }
1428
1429 break;
1430 }
1431 #endif /* HAVE_LDAP */
1432
1433 #if HAVE_GSSAPI
1434 case AUTHMETHOD_GSSAPI: {
1435 /*
1436 * GSSAPI can only be checked/established during
1437 * negotiation (command = SOCKS_ACCEPT).
1438 * After that stage has completed, we either have
1439 * it or we don't.
1440 */
1441 if (state->command != SOCKS_ACCEPT)
1442 continue;
1443
1444 STRCPY_ASSERTSIZE(srcauth->mdata.gssapi.servicename,
1445 rule->state.gssapiservicename);
1446
1447 STRCPY_ASSERTSIZE(srcauth->mdata.gssapi.keytab,
1448 rule->state.gssapikeytab);
1449
1450 srcauth->mdata.gssapi.encryption.nec
1451 = rule->state.gssapiencryption.nec;
1452
1453 srcauth->mdata.gssapi.encryption.clear
1454 = rule->state.gssapiencryption.clear;
1455
1456 srcauth->mdata.gssapi.encryption.integrity
1457 = rule->state.gssapiencryption.integrity;
1458
1459 srcauth->mdata.gssapi.encryption.confidentiality
1460 = rule->state.gssapiencryption.confidentiality;
1461
1462 methodischeckable = 1;
1463 break;
1464 }
1465 #endif /* HAVE_GSSAPI */
1466 #endif /* SOCKS_SERVER */
1467 }
1468
1469 if (methodischeckable) {
1470 slog(LOG_DEBUG, "%s: changing authmethod from %d to %d",
1471 function, srcauth->method, methodv[i]);
1472
1473 srcauth->method = methodv[i];
1474 break;
1475 }
1476 }
1477
1478 if (i == methodc) {
1479 #if COVENANT
1480 /*
1481 * Respond to the client that it must provide proxy
1482 * authentication, which means we can go from no authentication
1483 * to "any" authentication, if the client goes on to provide
1484 * authentication later.
1485 */
1486 if (methodc > 0) { /* auth is required. */
1487 match->verdict = VERDICT_BLOCK;
1488 match->whyblock.missingproxyauth = 1;
1489 SHMEM_CLEAR(match, SHMEM_ALL, 1);
1490
1491 SASSERTX(!SHMID_ISATTACHED(match));
1492
1493 return 0;
1494 }
1495 #else /* !COVENANT */
1496 /*
1497 * the methods of the current rule differs from what client can
1498 * provide us with. Go to next rule.
1499 */
1500 continue;
1501 #endif /* !COVENANT */
1502 }
1503 }
1504
1505 SASSERTX(isreplycommand
1506 || state->command == SOCKS_HOSTID
1507 || methodisset(srcauth->method, methodv, methodc));
1508
1509 if (srcauth->method != AUTHMETHOD_NONE && rule->user != NULL) {
1510 /*
1511 * rule requires username. Does it covers the current user?
1512 */
1513 if (!usermatch(srcauth, rule->user)) {
1514 slog(LOG_DEBUG,
1515 "%s: username \"%s\" did not match rule #%lu for %s",
1516 function,
1517 authname(srcauth) == NULL ? "<null>" : authname(srcauth),
1518 (unsigned long)rule->number,
1519 command2string(state->command));
1520
1521 continue; /* no match. */
1522 }
1523 }
1524
1525 if (srcauth->method != AUTHMETHOD_NONE && rule->group != NULL) {
1526 /*
1527 * Does rule cover current group?
1528 */
1529 if (!groupmatch(srcauth, rule->group)) {
1530 slog(LOG_DEBUG,
1531 "%s: groupname \"%s\" did not match rule #%lu for %s",
1532 function,
1533 authname(srcauth) == NULL ? "<null>" : authname(srcauth),
1534 (unsigned long)rule->number,
1535 command2string(state->command));
1536
1537 continue; /* no match. */
1538 }
1539 }
1540
1541 #if HAVE_PAC
1542 /* rule requires a group, and covers current user? */
1543 if (srcauth->method == AUTHMETHOD_GSSAPI && rule->objectsids != NULL) {
1544 if (!sidmatch(srcauth, rule->objectsids)) {
1545 slog(LOG_DEBUG,
1546 "%s: sids \"%s\" did not match rule #%lu for %s",
1547 function,
1548 authsids(srcauth) == NULL ? "<null>" : authsids(srcauth),
1549 (unsigned long)rule->number,
1550 command2string(state->command));
1551
1552 sidmatched = 0;
1553 continue; /* no match. */
1554 }
1555 else
1556 sidmatched = 1;
1557 }
1558 #endif /* HAVE_PAC */
1559
1560 #if HAVE_LDAP
1561
1562 /*
1563 * rule requires a ldapgroup, and group covers current user?
1564 */
1565 if (srcauth->method != AUTHMETHOD_NONE && rule->ldapgroup != NULL
1566 && !sidmatched) {
1567 if (!ldapgroupmatch(srcauth, rule)) {
1568 slog(LOG_DEBUG,
1569 "%s: username \"%s\" did not match rule #%lu for %s",
1570 function,
1571 authname(srcauth) == NULL ? "<null>" : authname(srcauth),
1572 (unsigned long)rule->number,
1573 command2string(state->command));
1574
1575 continue; /* no match. */
1576 }
1577 }
1578
1579 #endif /* HAVE_LDAP */
1580
1581 /*
1582 * Ok, all looks good. Now finally check if the authentication
1583 * credentials we've received are correct. Do this last as it
1584 * can involve external libraries (e.g. PAM) which we have
1585 * little control over.
1586 */
1587 if (!accesscheck(s, srcauth, peer, local, msg, msgsize)) {
1588 *match = *rule;
1589
1590 match->verdict = VERDICT_BLOCK;
1591 SHMEM_CLEAR(match, SHMEM_ALL, 1);
1592
1593 return 0;
1594 }
1595
1596 break;
1597 }
1598
1599 if (rule == NULL) {
1600 char buf[1024];
1601
1602 if (msg == NULL || msgsize == 0) {
1603 msg = buf;
1604 msgsize = sizeof(buf);
1605 }
1606
1607 snprintf(msg, msgsize, "no rules matched; using default block rule");
1608
1609 *match = defrule;
1610 match->type = ruletype;
1611 }
1612 else {
1613 *match = *rule;
1614
1615 slog(LOG_DEBUG, "%s: rule matched: %lu (%s), verdict %s",
1616 function,
1617 (unsigned long)match->number,
1618 objecttype2string(match->type),
1619 verdict2string(match->verdict));
1620 }
1621
1622 /*
1623 * got our rule, now check connection.
1624 */
1625 if (match->verdict == VERDICT_PASS && peer != NULL)
1626 if (!srchost_isok(peer, msg, msgsize)) {
1627 match->verdict = VERDICT_BLOCK;
1628 SHMEM_CLEAR(match, SHMEM_ALL, 1);
1629
1630 return 0;
1631 }
1632
1633 #if HAVE_LIBWRAP
1634 if (s != -1 && *match->libwrap != NUL) {
1635 char libwrapcmd[LIBWRAPBUF];
1636 int errno_pre, errno_post;
1637
1638 if (!libwrapinited)
1639 libwrapinit(s, &_local, &_peer, &libwraprequest);
1640
1641 /* libwrap modifies the passed buffer. */
1642 STRCPY_ASSERTSIZE(libwrapcmd, match->libwrap);
1643
1644 /* Wietse Venema says something along the lines of: */
1645 if (setjmp(tcpd_buf) != 0) {
1646 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_OFF);
1647
1648 swarnx("%s: failed libwrap line: \"%s\"", function, libwrapcmd);
1649
1650 match->verdict = VERDICT_BLOCK;
1651 SHMEM_CLEAR(match, SHMEM_ALL, 1);
1652
1653 return 0; /* something got screwed up. */
1654 }
1655
1656 slog(LOG_DEBUG, "%s: executing libwrap command: \"%s\"",
1657 function, libwrapcmd);
1658
1659 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_ON);
1660 errno_pre = errno;
1661 errno = 0;
1662 process_options(libwrapcmd, &libwraprequest);
1663 errno_post = errno;
1664 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_OFF);
1665
1666 if (errno_post != 0)
1667 slog(LOG_INFO,
1668 "%s: processing of libwrap options set errno (%s)",
1669 function, strerror(errno_post));
1670 errno = errno_pre;
1671
1672 if (match->verdict == VERDICT_BLOCK
1673 && strstr(match->libwrap, "banners ") != NULL) {
1674 /*
1675 * We don't want the kernel to RST this connection upon our
1676 * subsequent close(2) without us having sent the whole banner to
1677 * the client first. But if the kernel wants to send RST while
1678 * we have data not yet sent, it will discard the data not yet
1679 * sent. We therefor drain the data first, trying to make sure the
1680 * kernel does not discard the data in the outbuffer and sends a
1681 * RST when we close(2). Note that this changes the RST to FIN.
1682 * See 2.17 in RFC 2525, "Failure to RST on close with data pending",
1683 * for more information about this.
1684 *
1685 * Note there is a race here, as the client could send us data
1686 * between our last read(2) call and us closing the session later, not
1687 * but much to do about that.
1688 */
1689 char buf[1024];
1690 ssize_t p;
1691
1692 while ((p = read(s, buf, sizeof(buf))) > 0)
1693 slog(LOG_DEBUG, "%s: reading and discarding %ld bytes from blocked "
1694 "connection so the banner is sent to the client",
1695 function, (long)p);
1696 }
1697 }
1698 #endif /* !HAVE_LIBWRAP */
1699
1700 if (match->verdict == VERDICT_BLOCK)
1701 SHMEM_CLEAR(match, SHMEM_ALL, 1);
1702 else {
1703 if (sockscf.monitor != NULL) {
1704 if (src != NULL) {
1705 const monitor_t *monitor;
1706
1707 SASSERTX(match->mstats == NULL);
1708 SASSERTX(match->mstats_shmid == 0);
1709
1710 if ((monitor = monitormatch(src,
1711 dst,
1712 srcauth,
1713 state)) != NULL) {
1714 slog(LOG_DEBUG, "%s: matched monitor #%lu, mstats_shmid = %lu",
1715 function,
1716 (unsigned long)monitor->number,
1717 (unsigned long)monitor->mstats_shmid);
1718
1719 SASSERTX(monitor->mstats == NULL);
1720
1721 COPY_MONITORFIELDS(monitor, match);
1722 }
1723 }
1724 }
1725 }
1726
1727 SASSERTX(!SHMID_ISATTACHED(match));
1728
1729 return match->verdict == VERDICT_PASS;
1730 }
1731
1732 int
command_matches(command,commands)1733 command_matches(command, commands)
1734 const int command;
1735 const command_t *commands;
1736 {
1737 switch (command) {
1738 /* client-rule commands. XXX set them to in commands for crule.*/
1739 case SOCKS_ACCEPT:
1740 case SOCKS_BOUNCETO:
1741 return 1;
1742
1743 /* hostid: same as SOCKS_ACCEPT basically. */
1744 case SOCKS_HOSTID:
1745 return 1;
1746
1747 /* socks-rule commands. */
1748 case SOCKS_BIND:
1749 if (commands->bind)
1750 return 1;
1751 else
1752 return 0;
1753
1754 case SOCKS_CONNECT:
1755 if (commands->connect)
1756 return 1;
1757 else
1758 return 0;
1759
1760 case SOCKS_UDPASSOCIATE:
1761 if (commands->udpassociate)
1762 return 1;
1763 else
1764 return 0;
1765
1766 /*
1767 * pseudo commands.
1768 */
1769
1770 case SOCKS_BINDREPLY:
1771 if (commands->bindreply)
1772 return 1;
1773 else
1774 return 0;
1775
1776 case SOCKS_UDPREPLY:
1777 if (commands->udpreply)
1778 return 1;
1779 else
1780 return 0;
1781
1782 default:
1783 SERRX(command);
1784 }
1785 }
1786
1787 int
protocol_matches(protocol,protocols)1788 protocol_matches(protocol, protocols)
1789 const int protocol;
1790 const protocol_t *protocols;
1791 {
1792 switch (protocol) {
1793 case SOCKS_TCP:
1794 if (protocols->tcp)
1795 return 1;
1796 else
1797 return 0;
1798
1799 case SOCKS_UDP:
1800 if (protocols->udp)
1801 return 1;
1802 else
1803 return 0;
1804
1805 default:
1806 SERRX(protocol);
1807 }
1808 }
1809
1810 int
proxyprotocol_matches(protocol,protocols)1811 proxyprotocol_matches(protocol, protocols)
1812 const int protocol;
1813 const proxyprotocol_t *protocols;
1814 {
1815
1816 switch (protocol) {
1817 case PROXY_SOCKS_V4:
1818 if (protocols->socks_v4)
1819 return 1;
1820 else
1821 return 0;
1822
1823 case PROXY_SOCKS_V5:
1824 if (protocols->socks_v5)
1825 return 1;
1826 else
1827 return 0;
1828
1829 case PROXY_HTTP_10:
1830 case PROXY_HTTP_11:
1831 if (protocols->http)
1832 return 1;
1833 else
1834 return 0;
1835
1836 default:
1837 SERRX(protocol);
1838 }
1839 }
1840
1841 void
showlist(list,prefix)1842 showlist(list, prefix)
1843 const linkedname_t *list;
1844 const char *prefix;
1845 {
1846 char buf[10240];
1847
1848 list2string(list, buf, sizeof(buf));
1849 if (strlen(buf) > 0)
1850 slog(LOG_DEBUG, "%s%s", prefix, buf);
1851 }
1852
1853 int
rulerequires(rule,what)1854 rulerequires(rule, what)
1855 const rule_t *rule;
1856 const methodinfo_t what;
1857 {
1858 const char *function = "rulerequires()";
1859 int rc;
1860
1861 switch (what) {
1862 case username:
1863 if (rule->user != NULL
1864 || rule->group != NULL
1865
1866 #if HAVE_LDAP
1867
1868 || rule->ldapgroup != NULL
1869 || rule->ldapsettingsfromuser /* ldapauthorisation also requires username. */
1870
1871 #endif /* HAVE_LDAP */
1872
1873 #if HAVE_PAC
1874
1875 || rule->objectsids != NULL
1876
1877 #endif /* HAVE_PAC */
1878 )
1879 rc = 1;
1880 else
1881 rc =0;
1882
1883 break;
1884
1885 default:
1886 SERRX(what);
1887 }
1888
1889 slog(LOG_DEBUG, "%s: %s: %lu requires %d: %s",
1890 function,
1891 objecttype2string(rule->type),
1892 (unsigned long)rule->number,
1893 (int)what,
1894 rc == 1 ? "yes" : "no");
1895
1896 return rc;
1897 }
1898
1899 int
rule_inheritoruse(from,cinfo_from,to,cinfo_to,sidesconnected,emsg,emsglen)1900 rule_inheritoruse(from, cinfo_from, to, cinfo_to, sidesconnected, emsg, emsglen)
1901 struct rule_t *from;
1902 const clientinfo_t *cinfo_from;
1903 struct rule_t *to;
1904 const clientinfo_t *cinfo_to;
1905 const size_t sidesconnected;
1906 char *emsg;
1907 const size_t emsglen;
1908 {
1909 const char *function = "rule_inheritoruse()";
1910 char fromstr[512], tostr[sizeof(fromstr)];
1911 int rc, use_to, unuse_from,
1912 to_attached = SHMEM_NONE, from_attached = SHMEM_NONE;
1913
1914 #define SET_USEUNUSE(failedalready, _from, _cinfo_from, _unuse_from, \
1915 _to, _cinfo_to, _use_to, \
1916 inheritablefield, idfield, type) \
1917 do { \
1918 (_unuse_from) = (_use_to) = 0; \
1919 \
1920 if ((failedalready)) { \
1921 if ((_from)->idfield != 0) \
1922 (_unuse_from) = 1; \
1923 \
1924 slog(LOG_DEBUG, "%s: unuse_from? %s use_to? %s", \
1925 function, (_unuse_from) ? "yes" : "no", (_use_to) ? "yes" : "no"); \
1926 \
1927 break; \
1928 } \
1929 \
1930 if ((_from)->idfield == 0) { \
1931 if ((_to)->idfield != 0) \
1932 (_use_to) = 1; \
1933 } \
1934 else { \
1935 if ((_from)->inheritablefield) { \
1936 if (memcmp((_cinfo_from), (_cinfo_to), sizeof(*(_cinfo_to))) == 0 \
1937 && ((_to)->idfield == 0 || (_to)->idfield == (_from)->idfield)) { \
1938 log_shmeminherit((_from), (_to), (type), (_to)->idfield != 0); \
1939 SHMEM_MOVE((_from), (_to), (type)); \
1940 } \
1941 else { \
1942 (_unuse_from) = 1; \
1943 log_shmeminherit((_from), (_to), (type), 1); \
1944 (_use_to) = 1; \
1945 } \
1946 } \
1947 else { \
1948 (_unuse_from) = 1; \
1949 \
1950 if ((_to)->idfield != 0) \
1951 (_use_to) = 1; \
1952 } \
1953 } \
1954 \
1955 slog(LOG_DEBUG, "%s: unuse_from? %s use_to? %s", \
1956 function, (_unuse_from) ? "yes" : "no", (_use_to) ? "yes" : "no"); \
1957 } while (/* CONSTCOND */ 0)
1958
1959 #define ATTACH_IF_NEEDED(_rule, _attr, _type, _rule_attached, _rc) \
1960 do { \
1961 if ((_rule)->_attr == NULL) { \
1962 if (sockd_shmat((_rule), (_type)) == 0) \
1963 *(_rule_attached) |= (_type); \
1964 else \
1965 *(_rc) = -1; \
1966 } \
1967 } while (/* CONSTCOND */ 0)
1968
1969
1970 snprintf(fromstr, sizeof(fromstr),
1971 "from-rule before (cinfo: %s)",
1972 clientinfo2string(cinfo_from, NULL, 0));
1973
1974 snprintf(tostr, sizeof(tostr),
1975 "to-rule before (cinfo: %s)",
1976 clientinfo2string(cinfo_to, NULL, 0));
1977
1978 log_ruleinfo_shmid(from, function, fromstr);
1979 log_ruleinfo_shmid(to, function, tostr);
1980
1981 rc = 0;
1982
1983 /*
1984 * Session-settings to inherit? Check this first since that's the one
1985 * that can fail.
1986 */
1987
1988 log_inheritable(function,
1989 from,
1990 from->ss_shmid,
1991 "session",
1992 from->ss_shmid == 0 ? 0 : from->ss_isinheritable);
1993
1994 SET_USEUNUSE(rc == -1,
1995 from,
1996 cinfo_from,
1997 unuse_from,
1998 to,
1999 cinfo_to,
2000 use_to,
2001 ss_isinheritable,
2002 ss_shmid,
2003 SHMEM_SS);
2004
2005 if (unuse_from) {
2006 ATTACH_IF_NEEDED(from, ss, SHMEM_SS, &from_attached, &rc);
2007
2008 if (from->ss != NULL)
2009 session_unuse(from->ss, cinfo_from, sockscf.shmemfd);
2010 }
2011
2012 if (use_to) {
2013 ATTACH_IF_NEEDED(to, ss, SHMEM_SS, &to_attached, &rc);
2014
2015 if (to->ss != NULL) {
2016 if (!session_use(to->ss, cinfo_to, sockscf.shmemfd, emsg, emsglen)) {
2017 SHMEM_CLEAR(to, SHMEM_SS, 1); /* could not be used. */
2018 rc = -1;
2019 }
2020 }
2021 }
2022
2023 /*
2024 * BW-settings to inherit?
2025 */
2026
2027 log_inheritable(function,
2028 from,
2029 from->bw_shmid,
2030 "bandwidth",
2031 from->bw_shmid == 0 ? 0 : from->bw_isinheritable);
2032
2033 SET_USEUNUSE(rc == -1,
2034 from,
2035 cinfo_from,
2036 unuse_from,
2037 to,
2038 cinfo_to,
2039 use_to,
2040 bw_isinheritable,
2041 bw_shmid,
2042 SHMEM_BW);
2043
2044 if (unuse_from) {
2045 ATTACH_IF_NEEDED(from, bw, SHMEM_BW, &from_attached, &rc);
2046
2047 if (from->bw != NULL)
2048 bw_unuse(from->bw, cinfo_from, sockscf.shmemfd);
2049 }
2050
2051 if (use_to) {
2052 ATTACH_IF_NEEDED(to, bw, SHMEM_BW, &to_attached, &rc);
2053
2054 if (to->bw != NULL)
2055 bw_use(to->bw, cinfo_to, sockscf.shmemfd);
2056 }
2057
2058
2059 if (rc == 0) /* only inherit alarms on success. */
2060 /*
2061 * Do this before we potentially clear fields in the code below.
2062 */
2063 alarm_inherit(from, cinfo_from, to, cinfo_to, sidesconnected);
2064
2065
2066 /*
2067 * Monitor-settings to inherit?
2068 */
2069
2070 log_inheritable(function,
2071 from,
2072 from->mstats_shmid,
2073 "mstats",
2074 from->mstats_shmid == 0 ? 0 : from->mstats_isinheritable);
2075
2076 SET_USEUNUSE(rc == -1,
2077 from,
2078 cinfo_from,
2079 unuse_from,
2080 to,
2081 cinfo_to,
2082 use_to,
2083 mstats_isinheritable,
2084 mstats_shmid,
2085 SHMEM_MONITOR);
2086
2087 if (unuse_from) {
2088 ATTACH_IF_NEEDED(from, mstats, SHMEM_MONITOR, &from_attached, &rc);
2089
2090 if (from->mstats != NULL)
2091 monitor_unuse(from->mstats, cinfo_from, sockscf.shmemfd);
2092 }
2093
2094 if (use_to) {
2095 ATTACH_IF_NEEDED(to, mstats, SHMEM_MONITOR, &to_attached, &rc);
2096
2097 if (to->mstats != NULL)
2098 monitor_use(to->mstats, cinfo_to, sockscf.shmemfd);
2099 }
2100
2101 /*
2102 * Redirect settings to inherit?
2103 * Like the other settings, we inherit all or nothing.
2104 */
2105 if (rc != -1) {
2106 if (from->rdr_from.atype != SOCKS_ADDR_NOTSET
2107 || from->rdr_to.atype != SOCKS_ADDR_NOTSET) {
2108 if (to->rdr_from.atype == SOCKS_ADDR_NOTSET
2109 && to->rdr_to.atype == SOCKS_ADDR_NOTSET) {
2110 slog(LOG_DEBUG,
2111 "%s: %s #%lu inherits redirect settings from %s #%lu",
2112 function,
2113 objecttype2string(to->type),
2114 (unsigned long)to->number,
2115 objecttype2string(from->type),
2116 (unsigned long)from->number);
2117
2118 to->rdr_from = from->rdr_from;
2119 to->rdr_to = from->rdr_to;
2120 }
2121 else {
2122 slog(LOG_DEBUG,
2123 "%s: %s #%lu overrides redirect settings of %s #%lu",
2124 function,
2125 objecttype2string(to->type),
2126 (unsigned long)to->number,
2127 objecttype2string(from->type),
2128 (unsigned long)from->number);
2129
2130 bzero(&from->rdr_from, sizeof(from->rdr_from));
2131 bzero(&from->rdr_to, sizeof(from->rdr_to));
2132 }
2133 }
2134 /* else; nothing to inherit. */
2135 }
2136
2137 if (from_attached != SHMEM_NONE)
2138 sockd_shmdt(from, from_attached);
2139
2140 if (to_attached != SHMEM_NONE)
2141 sockd_shmdt(to, to_attached);
2142
2143 /*
2144 * what should be inherited has been inherited; no need to reference
2145 * any limits in "from" ever again.
2146 */
2147 SHMEM_CLEAR(from, SHMEM_ALL, 1);
2148
2149 if (rc == -1) {
2150 /*
2151 * Did not use anything in to.
2152 */
2153 SASSERTX(to->bw == NULL);
2154 SASSERTX(to->mstats == NULL);
2155 SASSERTX(to->ss == NULL);
2156
2157 SHMEM_CLEAR(to, SHMEM_ALL, 1);
2158
2159 to->verdict = VERDICT_BLOCK;
2160 }
2161
2162 log_ruleinfo_shmid(from, function, "from-rule after");
2163 log_ruleinfo_shmid(to, function, "to-rule after");
2164
2165 return rc;
2166 }
2167
2168
2169 static int
srchost_isok(peer,msg,msgsize)2170 srchost_isok(peer, msg, msgsize)
2171 const struct sockaddr_storage *peer;
2172 char *msg;
2173 size_t msgsize;
2174 {
2175 const char *function = "srchost_isok()";
2176 char hostname[MAXHOSTNAMELEN], vishname[sizeof(hostname) * 4];
2177 int rc;
2178
2179 if (!sockscf.srchost.nodnsmismatch
2180 && !sockscf.srchost.nodnsunknown)
2181 return 1;
2182
2183 rc = cgetnameinfo(TOCSA(peer),
2184 salen(peer->ss_family),
2185 hostname,
2186 sizeof(hostname),
2187 NULL,
2188 0,
2189 NI_NAMEREQD);
2190
2191 if (rc == 0)
2192 slog(LOG_DEBUG, "%s: %s has a dns entry: %s",
2193 function,
2194 sockaddr2string(peer, NULL, 0),
2195 str2vis(hostname, strlen(hostname), vishname, sizeof(vishname)));
2196 else
2197 log_reversemapfailed(peer, INTERNALIF, rc);
2198
2199 if (rc != 0 && sockscf.srchost.nodnsunknown) {
2200 snprintf(msg, msgsize, "no dns entry found for srchost %s",
2201 sockaddr2string(peer, NULL, 0));
2202
2203 return 0;
2204 }
2205
2206 if (rc == 0 && sockscf.srchost.nodnsmismatch) {
2207 /*
2208 * Check if the reversemapped hostname maps back to the ipaddress.
2209 */
2210 ruleaddr_t ruleaddr;
2211 sockshost_t resolvedhost;
2212
2213 sockaddr2ruleaddr(peer, &ruleaddr);
2214 ruleaddr.operator = none;
2215
2216 if (strlen(hostname) >= sizeof(resolvedhost.addr.domain)) {
2217 swarnx("%s: ipaddress %s resolved to a hostname (%s) which is too "
2218 "long. %lu is the defined maximum",
2219 function,
2220 sockaddr2string2(peer, 0, NULL, 0),
2221 vishname,
2222 (unsigned long)sizeof(resolvedhost.addr.domain) - 1);
2223
2224 return 0;
2225 }
2226
2227 resolvedhost.atype = SOCKS_ADDR_DOMAIN;
2228 resolvedhost.port = htons(0);
2229 strcpy(resolvedhost.addr.domain, hostname);
2230
2231 if (!addrmatch(&ruleaddr, &resolvedhost, NULL, SOCKS_TCP, 0)) {
2232 snprintf(msg, msgsize,
2233 "DNS IP/hostname mismatch. %s does not match "
2234 "reversemapped addresses for hostname \"%s\"",
2235 sockaddr2string2(peer, 0, NULL, 0), vishname);
2236
2237 return 0;
2238 }
2239 }
2240
2241 return 1;
2242 }
2243
2244 #if HAVE_LIBWRAP
2245 static void
libwrapinit(s,local,peer,request)2246 libwrapinit(s, local, peer, request)
2247 int s;
2248 struct sockaddr_storage *local;
2249 struct sockaddr_storage *peer;
2250 struct request_info *request;
2251 {
2252 const char *function = "libwrapinit()";
2253 const int errno_s = errno;
2254 char hostname[MAXHOSTNAMELEN],
2255 localstr[MAXSOCKADDRSTRING], peerstr[MAXSOCKADDRSTRING];
2256 int rc;
2257
2258 slog(LOG_DEBUG,
2259 "%s: initing libwrap using fd %d for local %s, peer %s",
2260 function,
2261 s,
2262 sockaddr2string(local, localstr, sizeof(localstr)),
2263 sockaddr2string(peer, peerstr, sizeof(peerstr)));
2264
2265 rc = cgetnameinfo(TOSA(local),
2266 salen(local->ss_family),
2267 hostname,
2268 sizeof(hostname),
2269 NULL,
2270 0,
2271 NI_NAMEREQD);
2272
2273 request_init(request,
2274 RQ_FILE, s,
2275 RQ_DAEMON, __progname,
2276 RQ_CLIENT_SIN, peer,
2277 RQ_SERVER_SIN, local,
2278 RQ_SERVER_NAME, rc == 0 ? hostname : "",
2279 0);
2280
2281 rc = cgetnameinfo(TOSA(peer),
2282 salen(peer->ss_family),
2283 hostname,
2284 sizeof(hostname),
2285 NULL,
2286 0,
2287 NI_NAMEREQD);
2288
2289 request_set(request,
2290 RQ_CLIENT_NAME, rc == 0 ? hostname : "",
2291 0);
2292
2293 /* apparently some obscure libwrap bug requires this call. */
2294 sock_methods(request);
2295
2296 errno = errno_s;
2297 }
2298
2299 static int
libwrap_hosts_access(request,peer)2300 libwrap_hosts_access(request, peer)
2301 struct request_info *request;
2302 const struct sockaddr_storage *peer;
2303 {
2304 const char *function = "libwrap_hosts_access()";
2305 int allow;
2306
2307 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_ON);
2308 allow = hosts_access(request) != 0;
2309 sockd_priv(SOCKD_PRIV_LIBWRAP, PRIV_OFF);
2310
2311 slog(LOG_DEBUG, "%s: libwrap/tcp_wrappers hosts_access() %s address %s",
2312 function,
2313 allow ? "allows" : "denies",
2314 sockaddr2string(peer, NULL, 0));
2315
2316 if (allow)
2317 return 1;
2318
2319 return 0;
2320 }
2321 #endif /* HAVE_LIBWRAP */
2322
2323 static rule_t *
addrule(newrule,rulebase,ruletype)2324 addrule(newrule, rulebase, ruletype)
2325 const rule_t *newrule;
2326 rule_t **rulebase;
2327 const objecttype_t ruletype;
2328 {
2329 const char *function = "addrule()";
2330 serverstate_t zstate;
2331 rule_t *rule;
2332 size_t i;
2333
2334 bzero(&zstate, sizeof(zstate));
2335
2336 if ((rule = malloc(sizeof(*rule))) == NULL)
2337 serr("%s: could not allocate %lu bytes for a rule",
2338 function, (unsigned long)sizeof(*rule));
2339
2340 *rule = *newrule;
2341
2342 rule->type = ruletype;
2343
2344 /*
2345 * try to set values not set to a sensible default.
2346 */
2347
2348 if (sockscf.option.debug) {
2349 rule->log.connect = 1;
2350 rule->log.disconnect = 1;
2351 rule->log.error = 1;
2352 rule->log.iooperation = 1;
2353 /* rule->log.tcpinfo = 1; */
2354 }
2355 /* else; don't touch logging, no logging is ok. */
2356
2357 switch (ruletype) {
2358 case object_srule:
2359 if (rule->timeout.tcpio != 0)
2360 if (rule->timeout.tcp_fin_wait != 0
2361 && rule->timeout.tcp_fin_wait > rule->timeout.tcpio) {
2362 yywarnx("%s: it does not make sense to let the tcp-fin-wait "
2363 "timeout be longer than the tcp i/o timeout, so "
2364 "reducing tcp-fin-wait for this rule from %ld to %ld",
2365 function,
2366 (long)rule->timeout.tcp_fin_wait,
2367 (long)rule->timeout.tcpio);
2368
2369 rule->timeout.tcp_fin_wait = rule->timeout.tcpio;
2370 }
2371 break;
2372
2373 default:
2374 break;
2375 }
2376
2377 setcommandprotocol(rule->type, &rule->state.command, &rule->state.protocol);
2378
2379 /*
2380 * If no global clientmethod is set, set AUTHMETHOD_NONE. Avoids operator
2381 * having to always manually set it, since there are no cases where it
2382 * makes sense to not have at least one clientmethod set.
2383 * Doesn't make much sense to not have any global socksmethod set either,
2384 * but do require operator to set at least that to be more sure that is set
2385 * correctly.
2386 */
2387 if (sockscf.cmethodc == 0)
2388 sockscf.cmethodv[sockscf.cmethodc++] = AUTHMETHOD_NONE;
2389
2390 /*
2391 * need to do this check before adding methods ourselves, as if user
2392 * explicitly sets a method that will not work with all commands the
2393 * rule supports, we want to error out. We are less strict if he
2394 * does not and it's a method we add ourselves when it make sense.
2395 */
2396 if (isreplycommandonly(&rule->state.command)) {
2397 SASSERTX(rule->type == object_srule);
2398
2399 for (i = 0; i < rule->state.cmethodc; ++i) {
2400 if (( rule->state.command.udpreply
2401 && !methodworkswith(rule->state.smethodv[i], udpreplies))
2402 || ( rule->state.command.bindreply
2403 && !methodworkswith(rule->state.smethodv[i], tcpreplies)))
2404 yyerrorx("%s #%lu specifies method %s, but this "
2405 "method can not be provided by %sreplies",
2406 objecttype2string(rule->type),
2407 (unsigned long)rule->number,
2408 method2string(rule->state.smethodv[i]),
2409 rule->state.command.udpreply ? "udp" : "");
2410 }
2411 }
2412
2413 /*
2414 * If no clientmethod is set in this rule, set all from the global methods.
2415 */
2416 if (rule->state.cmethodc == 0) {
2417 for (i = 0; i < sockscf.cmethodc; ++i)
2418 rule->state.cmethodv[rule->state.cmethodc++] = sockscf.cmethodv[i];
2419 }
2420 else {
2421 for (i = 0; i < rule->state.cmethodc; ++i) {
2422 if (!methodisset(rule->state.cmethodv[i],
2423 sockscf.cmethodv,
2424 sockscf.cmethodc))
2425 yyerrorx("clientmethod \"%s\" is set in the rule, but not in the "
2426 "global clientmethod specification (containing \"%s\'). "
2427 "Only methods that are part of the global method "
2428 "specification can be part of the methods set in a local "
2429 "rule",
2430 method2string(rule->state.cmethodv[i]),
2431 methods2string(sockscf.cmethodc,
2432 sockscf.cmethodv,
2433 NULL,
2434 0));
2435
2436 if (rule->state.cmethodv[i] == AUTHMETHOD_NONE
2437 && i + 1 < rule->state.cmethodc)
2438 yywarnx("authentication method \"%s\" is configured in this "
2439 "clientmethod list, but since authentication methods "
2440 "are selected by the priority given, we will never try "
2441 "to match any of the subsequent authentication methods. "
2442 "I.e., no match will ever be attempted on the next "
2443 "method, method \"%s\"",
2444 method2string(rule->state.cmethodv[i]),
2445 method2string(rule->state.cmethodv[i + 1]));
2446 }
2447 }
2448
2449 /*
2450 * If no socksmethod is set in this rule, set all from the global methods.
2451 * For the client-rule there isn't really many checks we can do on what
2452 * methods to set (e.g., do they support what will be required by the
2453 * matchin socks-rule?), as we won't know what is required until we know
2454 * what the matching socks-rule will be for the clients request.
2455 *
2456 * For the socks-rule, we can check things however.
2457 */
2458 if (rule->state.smethodc == 0) {
2459 for (i = 0; i < sockscf.smethodc; ++i) {
2460 switch (rule->type) {
2461 case object_crule:
2462
2463 #if HAVE_SOCKS_HOSTID
2464 case object_hrule:
2465 #endif /* HAVE_SOCKS_HOSTID */
2466
2467 rule->state.smethodv[rule->state.smethodc++]
2468 = sockscf.smethodv[i];
2469 break;
2470
2471 #if HAVE_SOCKS_RULES
2472 case object_srule:
2473 if (isreplycommandonly(&rule->state.command)) {
2474 if (rule->state.command.udpreply
2475 && !methodworkswith(sockscf.smethodv[i], udpreplies))
2476 continue;
2477
2478 if (rule->state.command.bindreply
2479 && !methodworkswith(sockscf.smethodv[i], tcpreplies))
2480 continue;
2481 }
2482
2483 if (rulerequires(rule, username))
2484 if (!methodcanprovide(sockscf.smethodv[i], username))
2485 continue;
2486
2487 rule->state.smethodv[rule->state.smethodc++]
2488 = sockscf.smethodv[i];
2489
2490 break;
2491 #endif /* HAVE_SOCKS_RULES */
2492
2493 default:
2494 SERRX(rule->type);
2495 }
2496
2497 }
2498 }
2499 else {
2500 /*
2501 * socksmethods set by user. Make sure they are also part of the
2502 * global socksmethods set.
2503 */
2504 for (i = 0; i < rule->state.smethodc; ++i) {
2505 if (!methodisset(rule->state.smethodv[i],
2506 sockscf.smethodv,
2507 sockscf.smethodc))
2508 yyerrorx("method \"%s\" is set in the rule, but not in the global "
2509 "socksmethod specification (containing \"%s\'). "
2510 "Only methods that are part of the global method "
2511 "specification can be part of the methods set in a local "
2512 "rule",
2513 method2string(rule->state.smethodv[i]),
2514 methods2string(sockscf.smethodc,
2515 sockscf.smethodv,
2516 NULL,
2517 0));
2518
2519 if (rule->type != object_srule) {
2520 /*
2521 * At srule time, the socksmethod is already set and no
2522 * priority settings apply. Before that (in clientrule
2523 * and hostidrule), the socksmethod-list set will specify
2524 * the priority however.
2525 */
2526 if (rule->state.smethodv[i] == AUTHMETHOD_NONE
2527 && i + 1 < rule->state.smethodc)
2528 yywarnx("authentication method \"%s\" is configured in this "
2529 "socksmethod list, but since authentication methods "
2530 "are selected by the priority given, we will never try "
2531 "to match any of the subsequent authentication "
2532 "methods. I.e., no match will ever be attempted on "
2533 "the next method, method \"%s\"",
2534 method2string(rule->state.smethodv[i]),
2535 method2string(rule->state.smethodv[i + 1]));
2536 }
2537 }
2538 }
2539
2540 /* if no proxy protocol set, set appropriate. */
2541 if (memcmp(&zstate.proxyprotocol, &rule->state.proxyprotocol,
2542 sizeof(zstate.proxyprotocol)) == 0) {
2543 #if SOCKS_SERVER
2544 rule->state.proxyprotocol.socks_v4 = 1;
2545 rule->state.proxyprotocol.socks_v5 = 1;
2546
2547 #elif BAREFOOTD /* !SOCKS_SERVER */
2548 rule->state.proxyprotocol.socks_v5 = 1;
2549
2550 #elif COVENANT
2551 rule->state.proxyprotocol.http = 1;
2552 #endif /* COVENANT */
2553 }
2554
2555 #if BAREFOOTD
2556 SASSERTX(rule->type != object_srule);
2557
2558 if (rule->verdict == VERDICT_PASS
2559 && ( (rule->extra.bounceto.port.tcp == htons(0))
2560 || (rule->extra.bounceto.port.udp == htons(0)))) {
2561 /*
2562 * If no port-number is given for the bounce-to address, default to
2563 * using the same port as the port we accept the client on. Only do
2564 * this if it's a pass rule however. In the block case, we don't care
2565 * what the bounce-to address is as we will never connect there, so
2566 * prefer it to be 0.0.0.0, port 0, simply for cosmetic reasons.
2567 */
2568 if (rule->state.protocol.tcp
2569 && rule->extra.bounceto.port.tcp == htons(0)) {
2570 rule->extra.bounceto.port.tcp = rule->dst.port.tcp;
2571
2572 slog(LOG_DEBUG,
2573 "%s: no bounce-to port given for protocol %s in %s #%lu. "
2574 "Using dst port %u",
2575 function,
2576 protocol2string(SOCKS_TCP),
2577 objecttype2string(rule->type),
2578 (unsigned long)rule->number,
2579 ntohs(rule->dst.port.tcp));
2580 }
2581
2582 if (rule->state.protocol.udp
2583 && rule->extra.bounceto.port.udp == htons(0)) {
2584 rule->extra.bounceto.port.udp = rule->dst.port.udp;
2585
2586 slog(LOG_DEBUG,
2587 "%s: no bounce-to port given for protocol %s in %s #%lu. "
2588 "Using dst port %u",
2589 function,
2590 protocol2string(SOCKS_UDP),
2591 objecttype2string(rule->type),
2592 (unsigned long)rule->number,
2593 ntohs(rule->dst.port.udp));
2594 }
2595 }
2596 #endif /* BAREFOOTD */
2597
2598
2599 /*
2600 * Set default values for some authentication-methods, if none
2601 * set. Note that this needs to be set regardless of what the
2602 * method set in the rule is, as checkconfig() might add methods
2603 * to the rules as part of it's operation. This happens e.g. when
2604 * adding default methods to the global clientmethod line, if appropriate,
2605 * and then adding the same methods to the client-rules, if the rules
2606 * do not already have a method.
2607 */
2608
2609 #if HAVE_PAM
2610
2611 if (*rule->state.pamservicename == NUL) /* set to default. */
2612 STRCPY_ASSERTSIZE(rule->state.pamservicename, DEFAULT_PAMSERVICENAME);
2613
2614 #endif /* HAVE_PAM */
2615
2616 #if HAVE_BSDAUTH
2617
2618 if (*rule->state.bsdauthstylename == NUL) /* set to default. */
2619 STRCPY_ASSERTSIZE(rule->state.bsdauthstylename, DEFAULT_BSDAUTHSTYLENAME);
2620
2621 #endif /* HAVE_BSDAUTH */
2622
2623 #if HAVE_GSSAPI
2624
2625 if (*rule->state.gssapiservicename == NUL) /* set to default. */
2626 STRCPY_ASSERTSIZE(rule->state.gssapiservicename,
2627 DEFAULT_GSSAPISERVICENAME);
2628
2629 if (*rule->state.gssapikeytab == NUL) /* set to default. */
2630 STRCPY_ASSERTSIZE(rule->state.gssapikeytab, DEFAULT_GSSAPIKEYTAB);
2631
2632 /*
2633 * can't do memcmp since we don't want to include
2634 * gssapiencryption.nec in the compare.
2635 */
2636 if (rule->state.gssapiencryption.clear == 0
2637 && rule->state.gssapiencryption.integrity == 0
2638 && rule->state.gssapiencryption.confidentiality == 0
2639 && rule->state.gssapiencryption.permessage == 0) {
2640 rule->state.gssapiencryption.integrity = 1;
2641 rule->state.gssapiencryption.confidentiality= 1;
2642 rule->state.gssapiencryption.permessage = 0;
2643 }
2644 #endif /* HAVE_GSSAPI */
2645
2646 #if HAVE_LDAP
2647
2648 /*
2649 * Have LDAP authorization and LDAP authentication.
2650 */
2651
2652 /*
2653 * First LDAP authorization:
2654 */
2655
2656 if (*rule->state.ldapauthorisation.attribute == NUL)
2657 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.attribute,
2658 sockscf.state.ldapauthorisation.attribute);
2659 else
2660 rule->ldapsettingsfromuser = 1;
2661
2662 if (*rule->state.ldapauthorisation.attribute_AD == NUL)
2663 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.attribute_AD,
2664 sockscf.state.ldapauthorisation.attribute_AD);
2665 else
2666 rule->ldapsettingsfromuser = 1;
2667
2668 if (rule->state.ldapauthorisation.auto_off == -1)
2669 rule->state.ldapauthorisation.auto_off
2670 = sockscf.state.ldapauthorisation.auto_off;
2671 else
2672 rule->ldapsettingsfromuser = 1;
2673
2674 if (rule->state.ldapauthorisation.certcheck == -1)
2675 rule->state.ldapauthorisation.certcheck
2676 = sockscf.state.ldapauthorisation.certcheck;
2677 else
2678 rule->ldapsettingsfromuser = 1;
2679
2680 if (*rule->state.ldapauthorisation.certfile == NUL)
2681 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.certfile,
2682 sockscf.state.ldapauthorisation.certfile);
2683 else
2684 rule->ldapsettingsfromuser = 1;
2685
2686 if (*rule->state.ldapauthorisation.certpath == NUL)
2687 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.certpath,
2688 sockscf.state.ldapauthorisation.certpath);
2689 else
2690 rule->ldapsettingsfromuser = 1;
2691
2692 if (rule->state.ldapauthorisation.debug == LDAP_UNSET_DEBUG_VALUE)
2693 rule->state.ldapauthorisation.debug
2694 = sockscf.state.ldapauthorisation.debug;
2695 else
2696 rule->ldapsettingsfromuser = 1;
2697
2698 if (*rule->state.ldapauthorisation.domain == NUL)
2699 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.domain,
2700 sockscf.state.ldapauthorisation.domain);
2701 else
2702 rule->ldapsettingsfromuser = 1;
2703
2704 if (*rule->state.ldapauthorisation.filter == NUL)
2705 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.filter,
2706 sockscf.state.ldapauthorisation.filter);
2707 else
2708 rule->ldapsettingsfromuser = 1;
2709
2710 if (*rule->state.ldapauthorisation.filter_AD == NUL)
2711 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.filter_AD,
2712 sockscf.state.ldapauthorisation.filter_AD);
2713 else
2714 rule->ldapsettingsfromuser = 1;
2715
2716 if (rule->state.ldapauthorisation.keeprealm == -1)
2717 rule->state.ldapauthorisation.keeprealm
2718 = sockscf.state.ldapauthorisation.keeprealm;
2719 else
2720 rule->ldapsettingsfromuser = 1;
2721
2722 if (*rule->state.ldapauthorisation.keytab == NUL)
2723 STRCPY_ASSERTSIZE(rule->state.ldapauthorisation.keytab,
2724 sockscf.state.ldapauthorisation.keytab);
2725 else
2726 rule->ldapsettingsfromuser = 1;
2727
2728 if (rule->state.ldapauthorisation.mdepth == -1)
2729 rule->state.ldapauthorisation.mdepth
2730 = sockscf.state.ldapauthorisation.mdepth;
2731 else
2732 rule->ldapsettingsfromuser = 1;
2733
2734 if (rule->state.ldapauthorisation.port == -1)
2735 rule->state.ldapauthorisation.port
2736 = sockscf.state.ldapauthorisation.port;
2737 else
2738 rule->ldapsettingsfromuser = 1;
2739
2740 if (rule->state.ldapauthorisation.portssl == -1)
2741 rule->state.ldapauthorisation.portssl
2742 = sockscf.state.ldapauthorisation.portssl;
2743 else
2744 rule->ldapsettingsfromuser = 1;
2745
2746 if (rule->state.ldapauthorisation.ssl == -1)
2747 rule->state.ldapauthorisation.ssl = sockscf.state.ldapauthorisation.ssl;
2748 else
2749 rule->ldapsettingsfromuser = 1;
2750
2751 /*
2752 * ... and now LDAP authentication.
2753 */
2754
2755 if (rule->state.ldapauthentication.auto_off == -1)
2756 rule->state.ldapauthentication.auto_off
2757 = sockscf.state.ldapauthentication.auto_off;
2758 else
2759 rule->ldapsettingsfromuser = 1;
2760
2761 if (rule->state.ldapauthentication.certcheck == -1)
2762 rule->state.ldapauthentication.certcheck
2763 = sockscf.state.ldapauthentication.certcheck;
2764 else
2765 rule->ldapsettingsfromuser = 1;
2766
2767 if (*rule->state.ldapauthentication.certfile == NUL)
2768 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.certfile,
2769 sockscf.state.ldapauthentication.certfile);
2770 else
2771 rule->ldapsettingsfromuser = 1;
2772
2773 if (*rule->state.ldapauthentication.certpath == NUL)
2774 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.certpath,
2775 sockscf.state.ldapauthentication.certpath);
2776 else
2777 rule->ldapsettingsfromuser = 1;
2778
2779 if (rule->state.ldapauthentication.debug == LDAP_UNSET_DEBUG_VALUE)
2780 rule->state.ldapauthentication.debug
2781 = sockscf.state.ldapauthentication.debug;
2782 else
2783 rule->ldapsettingsfromuser = 1;
2784
2785 if (*rule->state.ldapauthentication.domain == NUL)
2786 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.domain,
2787 sockscf.state.ldapauthentication.domain);
2788 else
2789 rule->ldapsettingsfromuser = 1;
2790
2791 if (*rule->state.ldapauthentication.filter == NUL)
2792 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.filter,
2793 sockscf.state.ldapauthentication.filter);
2794 else
2795 rule->ldapsettingsfromuser = 1;
2796
2797 if (*rule->state.ldapauthentication.filter_AD == NUL)
2798 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.filter_AD,
2799 sockscf.state.ldapauthentication.filter_AD);
2800 else
2801 rule->ldapsettingsfromuser = 1;
2802
2803 if (*rule->state.ldapauthentication.keytab == NUL)
2804 STRCPY_ASSERTSIZE(rule->state.ldapauthentication.keytab,
2805 sockscf.state.ldapauthentication.keytab);
2806 else
2807 rule->ldapsettingsfromuser = 1;
2808
2809 if (rule->state.ldapauthentication.port == -1)
2810 rule->state.ldapauthentication.port
2811 = sockscf.state.ldapauthentication.port;
2812 else
2813 rule->ldapsettingsfromuser = 1;
2814
2815 if (rule->state.ldapauthentication.portssl == -1)
2816 rule->state.ldapauthentication.portssl
2817 = sockscf.state.ldapauthentication.portssl;
2818 else
2819 rule->ldapsettingsfromuser = 1;
2820
2821 if (rule->state.ldapauthentication.ssl == -1)
2822 rule->state.ldapauthentication.ssl = sockscf.state.ldapauthentication.ssl;
2823 else
2824 rule->ldapsettingsfromuser = 1;
2825
2826 #endif /* HAVE_LDAP */
2827
2828 if (*rulebase == NULL) {
2829 *rulebase = rule;
2830 (*rulebase)->number = 1;
2831 }
2832 else { /* append this rule to the end of our list. */
2833 rule_t *lastrule;
2834
2835 lastrule = *rulebase;
2836 while (lastrule->next != NULL)
2837 lastrule = lastrule->next;
2838
2839 rule->number = lastrule->number + 1;
2840 lastrule->next = rule;
2841 }
2842
2843 INIT_MSTATES(rule, rule->type, rule->number);
2844 rule->next = NULL;
2845
2846 return rule;
2847 }
2848
2849 static void
checkrule(rule)2850 checkrule(rule)
2851 const rule_t *rule;
2852 {
2853 const char *function = "checkrule()";
2854 ruleaddr_t ruleaddr;
2855 const int *methodv[] = {
2856 rule->state.cmethodv,
2857 rule->state.smethodv
2858 };
2859 const size_t methodc[] = {
2860 rule->state.cmethodc,
2861 rule->state.smethodc
2862 };
2863 const char methodtype[][32] = {
2864 "clientmethod",
2865 "socksmethod"
2866 };
2867 const objecttype_t ruletype[] = {
2868 object_crule,
2869 object_srule
2870 };
2871
2872 size_t i, methodi;
2873
2874 if (rule->src.atype == SOCKS_ADDR_IFNAME) {
2875 struct sockaddr_storage addr, mask;
2876
2877 if (ifname2sockaddr(rule->src.addr.ifname, 0, &addr, &mask) == NULL)
2878 yyerror("no ip address found on interface %s", rule->src.addr.ifname);
2879 }
2880
2881 if (rule->dst.atype == SOCKS_ADDR_IFNAME) {
2882 struct sockaddr_storage addr, mask;
2883
2884 if (ifname2sockaddr(rule->dst.addr.ifname, 0, &addr, &mask)
2885 == NULL)
2886 yyerror("no ip address found on interface %s", rule->dst.addr.ifname);
2887 }
2888
2889
2890 if (rule->ss != NULL) {
2891 SASSERTX(rule->ss->type == SHMEM_SS);
2892
2893 if (rule->ss->keystate.key == key_unset) {
2894 if (rule->ss->object.ss.max_perstate_isset)
2895 yyerrorx("state.session.max is set, but session.state.key is not");
2896
2897 if (rule->ss->object.ss.throttle_perstate_isset)
2898 yyerrorx("session.state.throttle is set, but session.state.key "
2899 "is not");
2900 }
2901 else {
2902 if (!rule->ss->object.ss.max_perstate_isset
2903 && !rule->ss->object.ss.throttle_perstate_isset)
2904 yyerrorx("session state key is set (%d), but no value has been "
2905 "given to state.max or state.throttle",
2906 (int)rule->ss->keystate.key);
2907
2908 switch (rule->ss->keystate.key) {
2909 case key_hostid:
2910 SASSERTX(rule->hostidoption_isset);
2911
2912 #if 0 /* XXX more thought needed. */
2913 if (rule->state.protocol.udp)
2914 yyerrorx("hostids are not available on sessions using UDP");
2915 #endif /* 0 */
2916
2917 if (rule->ss->keystate.keyinfo.hostindex < 1)
2918 yyerrorx("illegal hostindex value %d%s",
2919 (int)rule->ss->keystate.keyinfo.hostindex,
2920 rule->ss->keystate.keyinfo.hostindex == 0 ?
2921 "/any" : "");
2922 break;
2923
2924 case key_from:
2925 if (rule->ss->keystate.keyinfo.hostindex != 0)
2926 yyerrorx("it does not make sense to set a hostindex value "
2927 "for state key %s. The hostindex keyword "
2928 "is only usable with hostid keys",
2929 statekey2string(rule->ss->keystate.key));
2930 break;
2931
2932 default:
2933 SERRX(rule->ss->keystate.key);
2934 }
2935
2936 if (rule->ss->object.ss.max_isset
2937 && (rule->ss->object.ss.max_perstate
2938 > rule->ss->object.ss.max))
2939 yyerrorx("it does not make sense to have a larger value for "
2940 "session.state.max (%ld) than the combined, state-less, "
2941 "session.max value (%ld). Configuration error?",
2942 (unsigned long)rule->ss->object.ss.max_perstate,
2943 (unsigned long)rule->ss->object.ss.max);
2944
2945 if (rule->ss->object.ss.throttle_perstate_isset
2946 && rule->ss->object.ss.throttle_isset) {
2947 if ((rule->ss->object.ss.throttle_perstate.limit.seconds
2948 <= rule->ss->object.ss.throttle.limit.seconds)
2949 && (rule->ss->object.ss.throttle_perstate.limit.clients
2950 > rule->ss->object.ss.throttle.limit.clients))
2951 yyerrorx("it does not make sense to have a more strict limit for "
2952 "the combined, state-less, session.throttle limit "
2953 "(%lu/%ld), than for the per %s state "
2954 "session.state.throttle (%lu/%ld). Configuration error?",
2955 (unsigned long)rule->ss->object.ss.throttle.limit.clients,
2956 (long)rule->ss->object.ss.throttle.limit.seconds,
2957 statekey2string(rule->ss->keystate.key),
2958 (unsigned long)rule->ss->object.ss.throttle_perstate.limit.clients,
2959 (long)rule->ss->object.ss.throttle_perstate.limit.seconds);
2960 }
2961 }
2962 }
2963
2964 if (rule->bw != NULL) {
2965 SASSERTX(rule->bw->type == SHMEM_BW);
2966
2967 if (!rule->bw->object.bw.maxbps_isset)
2968 yyerrorx("no value for maxbps has been given");
2969 }
2970
2971 #if 0
2972 /*
2973 * XXX
2974 * Needs more thought. Would it be more meaningful to consider
2975 * hostids provided as long as any part of the session (i.e., the
2976 * TCP control connection) has provided it?
2977 */
2978
2979 if (rule->state.protocol.udp) {
2980 if (rule->hostidoption_isset)
2981 yyerrorx("hostids are not available on sessions using UDP");
2982 }
2983 #endif /* 0 */
2984
2985
2986 if (rule->src.atype == SOCKS_ADDR_IPVANY) {
2987 SASSERTX(rule->src.addr.ipvany.ip.s_addr == htonl(0));
2988 SASSERTX(rule->src.addr.ipvany.mask.s_addr == htonl(0));
2989 }
2990
2991 if (rule->dst.atype == SOCKS_ADDR_IPVANY) {
2992 SASSERTX(rule->dst.addr.ipvany.ip.s_addr == htonl(0));
2993 SASSERTX(rule->dst.addr.ipvany.mask.s_addr == htonl(0));
2994 }
2995
2996 #if BAREFOOTD
2997 SASSERTX(rule->type != object_srule);
2998
2999 if (rule->type == object_crule) {
3000 if (rule->dst.atype == SOCKS_ADDR_IPV4)
3001 SASSERTX(rule->dst.addr.ipv4.mask.s_addr == htonl(IPV4_FULLNETMASK));
3002 else if (rule->dst.atype == SOCKS_ADDR_IPV6)
3003 SASSERTX(rule->dst.addr.ipv6.maskbits == IPV6_NETMASKBITS);
3004 }
3005 #endif /* BAREFOOTD */
3006
3007 for (methodi = 0; methodi < ELEMENTS(methodv); ++methodi) {
3008 for (i = 0; i < methodc[methodi]; ++i) {
3009 if (!methodisvalid(methodv[methodi][i], ruletype[methodi]))
3010 yyerrorx("%smethod %s is not valid for %ss",
3011 methodtype[i],
3012 method2string(methodv[methodi][i]),
3013 objecttype2string(ruletype[methodi]));
3014 }
3015 }
3016
3017 switch (rule->type) {
3018 case object_crule:
3019 #if HAVE_SOCKS_HOSTID
3020 case object_hrule:
3021 #endif /* HAVE_SOCKS_HOSTID */
3022
3023 /*
3024 * we always set AUTHMETHOD_NONE ourselves if the user does not
3025 * set anything.
3026 */
3027 SASSERTX(rule->state.cmethodc > 0);
3028 break;
3029
3030 #if HAVE_SOCKS_RULES
3031 case object_srule:
3032 if (rule->state.smethodc == 0) {
3033 if (isreplycommandonly(&rule->state.command)
3034 && !sockscf.srchost.checkreplyauth) {
3035 /*
3036 * don't require user to specify a method for reply-only
3037 * rules as normally noting can be gotten from there.
3038 */
3039 ;
3040 }
3041 else
3042 yywarnx("%s: %s #%lu sets no socks authentication methods, not "
3043 "even the method \"none\". This means no clients can "
3044 "ever be matched by this rule. "
3045 "Is that really intended?",
3046 function,
3047 objecttype2string(rule->type),
3048 (unsigned long)rule->number);
3049 }
3050
3051 break;
3052 #endif /* HAVE_SOCKS_RULES */
3053
3054
3055 default:
3056 SERRX(rule->type);
3057 }
3058
3059 if (rulerequires(rule, username)) {
3060 unsigned allmethodsareok;
3061 char badmethod[256];
3062
3063 if (rule->state.command.udpreply) {
3064 if (isreplycommandonly(&rule->state.command))
3065 yyerrorx("UDP replies cannot provide any username, but the "
3066 "settings in this rule requires an username to be "
3067 "provided by the target sending the UDP reply");
3068
3069 if (sockscf.srchost.checkreplyauth)
3070 yyerrorx("\"checkreplyauth\" is enabled, but the target "
3071 "sending us the UDP reply cannot provide any "
3072 "username. This rule has however specified that an "
3073 "username must be provided");
3074 }
3075
3076 /*
3077 * Are all specified methods able to provide an username?
3078 */
3079
3080 allmethodsareok = 1;
3081
3082 switch (rule->type) {
3083 case object_crule:
3084 #if HAVE_SOCKS_HOSTID
3085 case object_hrule:
3086 #endif /* HAVE_SOCKS_HOSTID */
3087 /*
3088 * * Clientrule. the methods to check are the clientmethods.
3089 */
3090
3091 for (i = 0; i < rule->state.cmethodc; ++i) {
3092 if (!methodcanprovide(rule->state.cmethodv[i], username)) {
3093 snprintf(badmethod, sizeof(badmethod),
3094 "clientmethod %s",
3095 method2string(rule->state.cmethodv[i]));
3096
3097 allmethodsareok = 0;
3098 break;
3099 }
3100 }
3101
3102 break;
3103
3104 case object_srule:
3105 /*
3106 * A socksrule. This is a bit more complex.
3107 *
3108 * The methods to check are normally the socksmethods, but
3109 * if we are checking a reply (bindreply/udpreply), it's the
3110 * clientmethod we need to check, as socksmethods cannot
3111 * possibly apply to these replies.
3112 */
3113
3114 if ((sockscf.srchost.checkreplyauth
3115 && hasreplycommands(&rule->state.command))
3116 || isreplycommandonly(&rule->state.command)) {
3117 for (i = 0; i < rule->state.cmethodc; ++i) {
3118 if (!methodcanprovide(rule->state.cmethodv[i], username)) {
3119 snprintf(badmethod, sizeof(badmethod),
3120 "clientmethod \"%s\" to be used for replies",
3121 method2string(rule->state.cmethodv[i]));
3122
3123 allmethodsareok = 0;
3124 break;
3125 }
3126 }
3127 }
3128
3129 if (!allmethodsareok)
3130 break;
3131
3132 if (isreplycommandonly(&rule->state.command))
3133 break;
3134
3135 for (i = 0; i < rule->state.smethodc; ++i) {
3136 if (!methodcanprovide(rule->state.smethodv[i], username)) {
3137 snprintf(badmethod, sizeof(badmethod),
3138 "socksmethod %s",
3139 method2string(rule->state.smethodv[i]));
3140
3141 allmethodsareok = 0;
3142 break;
3143 }
3144 }
3145
3146 break;
3147
3148 default:
3149 SERRX(object_srule);
3150 }
3151
3152 if (!allmethodsareok)
3153 yyerrorx("the settings in this %s requires the client to "
3154 "provide a user/group-name in some way, but this rule "
3155 "specifies, implicitly or explicitly, the %s, which "
3156 "cannot be depended on to provide this information",
3157 objecttype2string(rule->type), badmethod);
3158
3159 }
3160
3161 if (rule->rdr_from.atype != SOCKS_ADDR_NOTSET) {
3162 switch (rule->rdr_from.atype) {
3163 case SOCKS_ADDR_IPV4:
3164 case SOCKS_ADDR_IPV6:
3165 case SOCKS_ADDR_IFNAME:
3166 case SOCKS_ADDR_DOMAIN:
3167 break;
3168
3169 default:
3170 yyerrorx("redirect from address can not be a %s",
3171 atype2string(rule->rdr_from.atype));
3172 }
3173
3174 ruleaddr = rule->rdr_from;
3175 ruleaddr.port.tcp = htons(0); /* any port is good for testing. */
3176
3177 if (!addrisbindable(&ruleaddr)) {
3178 char addr[MAXRULEADDRSTRING];
3179
3180 yyerrorx("address %s in rule #%lu is not bindable",
3181 ruleaddr2string(&ruleaddr, 0, addr, sizeof(addr)),
3182 (unsigned long)rule->number);
3183 }
3184 }
3185
3186 if (rule->rdr_to.atype != SOCKS_ADDR_NOTSET) {
3187 switch (rule->rdr_to.atype) {
3188 case SOCKS_ADDR_IPV4:
3189 case SOCKS_ADDR_IPV6:
3190 case SOCKS_ADDR_DOMAIN:
3191 break;
3192
3193 default:
3194 yyerrorx("redirect to a %s-type address is not supported "
3195 "(or meaningful?)",
3196 atype2string(rule->rdr_to.atype));
3197 }
3198 }
3199
3200 /* check socket options and warn if something does not look right. */
3201 if (rule->socketoptionv != NULL
3202 #if !HAVE_SOCKS_RULES
3203 && rule->type != object_srule /*
3204 * socks-rules are autogenerated based on
3205 * client-rule and will contain most of the ,
3206 * same, so avoid duplicate warnings by only
3207 * checking the options when checking the
3208 * crule.
3209 */
3210 #endif /* !HAVE_SOCKS_RULES */
3211 ) {
3212 for (i = 0; i < rule->socketoptionc; ++i) {
3213 if (rule->type != object_srule) {
3214 #if HAVE_SOCKS_RULES
3215 if (!rule->socketoptionv[i].isinternalside)
3216 yyerrorx("can not set socket options for the external side in "
3217 "a %s, as there is no external side set up "
3218 "yet at this point. Needs to be set in the "
3219 "corresponding socks-rule if necessary",
3220 objecttype2string(rule->type));
3221 #else
3222 /* reusing the client-rule as a srule later. */
3223 #endif
3224 }
3225
3226 if (rule->socketoptionv[i].info == NULL)
3227 continue;
3228 }
3229 }
3230 }
3231
3232 static void
showlog(log)3233 showlog(log)
3234 const log_t *log;
3235 {
3236 char buf[1024];
3237
3238 slog(LOG_DEBUG, "log: %s", logs2string(log, buf, sizeof(buf)));
3239 }
3240
3241 static void
log_shmeminherit(from,to,type,isoverride)3242 log_shmeminherit(from, to, type, isoverride)
3243 const rule_t *from;
3244 const rule_t *to;
3245 const int type;
3246 const int isoverride;
3247 {
3248 const char *function = "log_shmeminherit()";
3249 const char *settings;
3250 long shmid_from, shmid_to;
3251
3252 if (type == SHMEM_BW) {
3253 settings = "bandwidth";
3254 shmid_from = from->bw_shmid;
3255 shmid_to = to->bw_shmid;
3256 }
3257 else if (type == SHMEM_MONITOR) {
3258 settings = "monitor";
3259 shmid_from = from->mstats_shmid;
3260 shmid_to = to->mstats_shmid;
3261 }
3262 else if (type == SHMEM_SS) {
3263 settings = "session";
3264 shmid_from = from->ss_shmid;
3265 shmid_to = to->ss_shmid;
3266 }
3267 else
3268 SERRX(type);
3269
3270 if (isoverride)
3271 slog(LOG_DEBUG, "%s: %s #%lu with shmid %ld overrides %s "
3272 "settings of %s #%lu with shmid %ld",
3273 function,
3274 objecttype2string(to->type),
3275 (unsigned long)to->number,
3276 shmid_to,
3277 settings,
3278 objecttype2string(from->type),
3279 (unsigned long)from->number,
3280 shmid_from);
3281 else
3282 slog(LOG_DEBUG,
3283 "%s: %s #%lu inherits %s settings from %s #%lu using shmid %ld",
3284 function,
3285 objecttype2string(to->type),
3286 (unsigned long)to->number,
3287 settings,
3288 objecttype2string(from->type),
3289 (unsigned long)from->number,
3290 shmid_from);
3291 }
3292
3293 static void
log_inheritable(prefix,rule,shmid,settings,inheritable)3294 log_inheritable(prefix, rule, shmid, settings, inheritable)
3295 const char *prefix;
3296 const rule_t *rule;
3297 const unsigned long shmid;
3298 const char *settings;
3299 const int inheritable;
3300 {
3301
3302 if (shmid == 0)
3303 slog(LOG_DEBUG,
3304 "%s: no %s settings in %s #%lu to consider for inheritance",
3305 prefix,
3306 settings,
3307 objecttype2string(rule->type),
3308 (unsigned long)rule->number);
3309 else
3310 slog(LOG_DEBUG,
3311 "%s: %s settings (shmid %ld) in %s #%lu marked as %sinheritable",
3312 prefix,
3313 settings,
3314 shmid,
3315 objecttype2string(rule->type),
3316 (unsigned long)rule->number,
3317 inheritable ? "" : "not ");
3318 }
3319
3320 void
setcommandprotocol(type,commands,protocols)3321 setcommandprotocol(type, commands, protocols)
3322 const objecttype_t type;
3323 command_t *commands;
3324 protocol_t *protocols;
3325 {
3326 serverstate_t zstate;
3327
3328 /*
3329 * protocol and commands are two sides of the same coin.
3330 * If only protocol is set, set all commands that can apply to that
3331 * protocol.
3332 * If only command is set, set all protocols that can apply to that
3333 * command.
3334 * If none are set, set all protocols and commands.
3335 * If both are set, don't touch; user has explicitly set what he wants.
3336 */
3337
3338 bzero(&zstate, sizeof(zstate));
3339
3340 if (memcmp(&zstate.protocol, protocols, sizeof(zstate.protocol)) != 0
3341 && memcmp(&zstate.command, commands, sizeof(zstate.command)) == 0) {
3342 /*
3343 * only protocol is set. Add all applicable commands.
3344 */
3345
3346 if (type == object_srule || type == object_monitor) {
3347 if (protocols->tcp) {
3348 /*
3349 * All commands, except the udp-specific.
3350 */
3351 memset(commands, UCHAR_MAX, sizeof(*commands));
3352 commands->udpassociate = 0;
3353 commands->udpreply = 0;
3354 }
3355
3356 if (protocols->udp) {
3357 commands->udpassociate = 1;
3358 commands->udpreply = 1;
3359 }
3360 }
3361 }
3362 else if (memcmp(&zstate.command, commands, sizeof(zstate.command)) != 0
3363 && memcmp(&zstate.protocol, protocols, sizeof(zstate.protocol)) == 0) {
3364 /*
3365 * only command is set. Add all applicable protocols.
3366 */
3367
3368 if (type == object_srule || type == object_monitor) {
3369 if (commands->bind
3370 || commands->bindreply
3371 || commands->connect)
3372 protocols->tcp = 1;
3373
3374 if (commands->udpassociate
3375 || commands->udpreply
3376 || commands->connect)
3377 protocols->udp = 1;
3378 }
3379 else {
3380 #if HAVE_NEGOTIATE_PHASE
3381 protocols->tcp = 1;
3382 #else /* !HAVE_NEGOTIATE_PHASE. */
3383 memset(protocols, UCHAR_MAX, sizeof(*protocols));
3384 #endif /* !HAVE_NEGOTIATE_PHASE. */
3385 }
3386 }
3387 else if (memcmp(&zstate.command, commands, sizeof(zstate.command)) == 0
3388 && memcmp(&zstate.protocol, protocols, sizeof(zstate.protocol)) == 0) {
3389 /*
3390 * nothing is set. Set all.
3391 */
3392
3393 if (type == object_srule || type == object_monitor) {
3394 memset(protocols, UCHAR_MAX, sizeof(*protocols));
3395 memset(commands, UCHAR_MAX, sizeof(*commands));
3396 }
3397 else {
3398 #if HAVE_NEGOTIATE_PHASE
3399 protocols->tcp = 1;
3400 #else /* !HAVE_NEGOTIATE_PHASE. */
3401 memset(protocols, UCHAR_MAX, sizeof(*protocols));
3402 #endif /* !HAVE_NEGOTIATE_PHASE. */
3403 }
3404 }
3405 else {
3406 /*
3407 * both are set. Don't touch, but check it makes sense.
3408 */
3409
3410 SASSERTX(memcmp(&zstate.command, commands, sizeof(*commands)) != 0);
3411 SASSERTX(memcmp(&zstate.protocol, protocols, sizeof(*protocols)) != 0);
3412
3413 if ((commands->udpassociate || commands->udpreply)
3414 && !protocols->udp)
3415 yywarnx("%s specifies UDP-based commands, but does not enable the "
3416 "UDP protocol. This is probably not what was intended",
3417 objecttype2string(type));
3418
3419 if ((commands->bind || commands->bindreply || commands->connect)
3420 && !protocols->tcp)
3421 yywarnx("%s specifies TCP-based commands, but does not enable the "
3422 "TCP protocol. This is probably not what was intended",
3423 objecttype2string(type));
3424 }
3425 }
3426
3427 #define RULEADDR_MATCHES_ALL_PORTS(a, p) ( \
3428 ((a)->operator == none) \
3429 || ((a)->operator == range \
3430 && ntohs(RULEPORT_START((a), (p))) <= 1 \
3431 && ntohs((a)->portend) >= IP_MAXPORT) \
3432 || ((a)->operator == ge && ntohs(RULEPORT_START(a, p)) <= 1) \
3433 || ((a)->operator == gt && ntohs(RULEPORT_START(a, p)) == 0) \
3434 || ((a)->operator == le && ntohs(RULEPORT_START(a, p)) == IP_MAXPORT) \
3435 )
3436
3437 #define RULEADDR_MATCHES_ALL_ADDRESSES(a) ( \
3438 (a)->atype == SOCKS_ADDR_IPVANY \
3439 && (a)->addr.ipvany.mask.s_addr == htonl(0))
3440
3441 #define RULEADDR_MATCHES_ALL(a, p) \
3442 (RULEADDR_MATCHES_ALL_PORTS((a), p) && RULEADDR_MATCHES_ALL_ADDRESSES((a)))
3443
3444 static int
ruleaddr_matches_all_external(ruleaddr,protocol)3445 ruleaddr_matches_all_external(ruleaddr, protocol)
3446 const ruleaddr_t *ruleaddr;
3447 const int protocol;
3448 {
3449
3450 if (!RULEADDR_MATCHES_ALL_PORTS(ruleaddr, protocol))
3451 return 0;
3452
3453 if (ruleaddr->atype != SOCKS_ADDR_IPVANY
3454 && ruleaddr->atype != SOCKS_ADDR_IPV4
3455 && ruleaddr->atype != SOCKS_ADDR_IPV6)
3456 return 0;
3457
3458 if (RULEADDR_MATCHES_ALL_ADDRESSES(ruleaddr))
3459 return 1;
3460
3461 SASSERTX(ruleaddr->atype == SOCKS_ADDR_IPV4
3462 || ruleaddr->atype == SOCKS_ADDR_IPV6);
3463
3464 if (!external_has_only_safamily(atype2safamily(ruleaddr->atype)))
3465 return 0;
3466
3467 switch (ruleaddr->atype) {
3468 case SOCKS_ADDR_IPV4:
3469 return ( ruleaddr->atype == SOCKS_ADDR_IPV4
3470 && ruleaddr->addr.ipv4.mask.s_addr == htonl(0));
3471
3472 case SOCKS_ADDR_IPV6:
3473 return ( ruleaddr->atype == SOCKS_ADDR_IPV6
3474 && ruleaddr->addr.ipv6.maskbits == 0);
3475
3476 default:
3477 SERRX(ruleaddr->atype);
3478 }
3479
3480 /* NOTREACHED */
3481 return 0;
3482 }
3483
3484 #if HAVE_SOCKS_HOSTID
3485 int
hostidmatches(hostidc,hostidv,hostindex,addr,ruletype,number)3486 hostidmatches(hostidc, hostidv, hostindex, addr, ruletype, number)
3487 const size_t hostidc;
3488 const struct in_addr *hostidv;
3489 const unsigned char hostindex;
3490 const ruleaddr_t *addr;
3491 const objecttype_t ruletype;
3492 const size_t number;
3493 {
3494 const char *function = "hostidmatches()";
3495 sockshost_t hostid;
3496
3497 hostid.atype = SOCKS_ADDR_IPV4;
3498 hostid.port = htons(0);
3499
3500 if (hostindex == 0) {
3501 size_t i;
3502
3503 slog(LOG_DEBUG, "%s: %s #%lu specifies checking against all %u hostids",
3504 function,
3505 objecttype2string(ruletype),
3506 (unsigned long)number,
3507 (unsigned)hostidc);
3508
3509 for (i = 0; i < hostidc; ++i) {
3510 hostid.addr.ipv4 = hostidv[i];
3511 if (addrmatch(addr, &hostid, NULL, SOCKS_TCP, 0))
3512 return 1;
3513 }
3514
3515 return 0;
3516 }
3517 else { /* check a specific hostid index only. */
3518 if (hostindex > hostidc) {
3519 slog(LOG_DEBUG,
3520 "%s: %s #%lu specifies checking against hostid index %d, "
3521 "but the number of hostids set on the connection is %lu, "
3522 "so it can not match",
3523 function,
3524 objecttype2string(ruletype),
3525 (unsigned long)number,
3526 hostindex,
3527 (unsigned long)hostidc);
3528
3529 return 0;
3530 }
3531
3532 SASSERTX(hostindex <= hostidc);
3533
3534 hostid.addr.ipv4 = hostidv[hostindex - 1];
3535 slog(LOG_DEBUG, "%s: checking against hostid address %s",
3536 function, sockshost2string(&hostid, NULL, 0));
3537
3538 return addrmatch(addr, &hostid, NULL, SOCKS_TCP, 0);
3539 }
3540 }
3541 #endif /* HAVE_SOCKS_HOSTID */
3542