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