2
* Copyright (c) 1997, 1998, 1999, 2000, 2001
3
* Inferno Nettverk A/S, Norway. All rights reserved.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
30
* Inferno Nettverk A/S requests users of this software to return to
32
* Software Distribution Coordinator or sdc@inet.no
33
* Inferno Nettverk A/S
39
* any improvements or extensions that they make and grant Inferno Nettverk A/S
40
* the rights to redistribute these changes.
45
#include "config_parse.h"
47
static const char rcsid[] =
48
"$Id: serverconfig.c,v 1.178 2002/01/01 15:47:11 michaels Exp $";
53
showuser __P((const struct linkedname_t *user));
55
* shows usernames in "user".
59
showlog __P((const struct log_t *log));
61
* shows what type of logging is specified in "log".
65
extern jmp_buf tcpd_buf;
68
libwrapinit __P((int s, struct request_info *request));
70
* Initializes "request" for later usage via libwrap.
74
connectisok __P((struct request_info *request, const struct rule_t *rule));
75
#else /* !HAVE_LIBWRAP */
77
connectisok __P((void *request, const struct rule_t *rule));
78
#endif /* !HAVE_LIBWRAP */
80
* Checks the connection on "s".
81
* "rule" is the rule that matched the connection.
82
* This function should be called after each rulecheck for a new
86
* If connection is acceptable: true
87
* If connection is not acceptable: false
90
static struct rule_t *
91
addrule __P((const struct rule_t *newrule, struct rule_t **rulebase,
94
* Appends a copy of "newrule" to "rulebase".
95
* If "client" is true, "newrule" is a clientrule.
96
* Returns a pointer to the added rule (not "newrule").
100
checkrule __P((const struct rule_t *rule));
102
* Check that the rule "rule" makes sense.
107
struct config_t sockscf;
108
const int socks_configtype = CONFIGTYPE_SERVER;
111
int allow_severity, deny_severity;
112
#endif /* HAVE_LIBWRAP */
114
/* expand array by one, increment argc. */
115
#define NEWINTERNAL_EXTERNAL(argc, argv) \
117
if ((argv = realloc(argv, sizeof(*argv) * ++argc)) == NULL) \
119
bzero(&argv[argc - 1], sizeof(*argv)); \
120
} while (lintnoloop_common_h)
125
const struct ruleaddress_t *addr;
128
if (sockscf.state.init) {
129
#if 0 /* don't know how to do this now, seems like too much work. */
132
for (i = 0; i < sockscf.internalc; ++i)
133
if (memcmp(&sockscf.internalv[i], addr, sizeof(addr)) == 0)
136
if (i == sockscf.internalc)
137
swarnx("can't change internal addresses once running");
141
switch (addr->atype) {
142
case SOCKS_ADDR_IPV4: {
143
struct sockshost_t host;
145
NEWINTERNAL_EXTERNAL(sockscf.internalc, sockscf.internalv);
147
sockshost2sockaddr(ruleaddress2sockshost(addr, &host, SOCKS_TCP),
148
&sockscf.internalv[sockscf.internalc - 1].addr);
152
case SOCKS_ADDR_DOMAIN: {
157
while (hostname2sockaddr(addr->addr.domain, i, &sa) != NULL) {
158
NEWINTERNAL_EXTERNAL(sockscf.internalc,
161
/* LINTED pointer casts may be troublesome */
162
TOIN(&sa)->sin_port = addr->port.tcp;
163
sockscf.internalv[sockscf.internalc - 1].addr = sa;
168
yyerror("could not resolve name %s: %s",
169
addr->addr.domain, hstrerror(h_errno));
173
case SOCKS_ADDR_IFNAME: {
174
struct ifaddrs ifa, *ifap = &ifa, *iface;
177
if (getifaddrs(&ifap) != 0)
178
serr(EXIT_FAILURE, "getifaddrs()");
180
for (m = 0, iface = ifap; iface != NULL; iface = iface->ifa_next)
181
if (strcmp(iface->ifa_name, addr->addr.ifname) == 0
182
&& iface->ifa_addr != NULL
183
&& iface->ifa_addr->sa_family == AF_INET) {
184
NEWINTERNAL_EXTERNAL(sockscf.internalc,
187
/* LINTED pointer casts may be troublesome */
188
TOIN(iface->ifa_addr)->sin_port = addr->port.tcp;
190
sockscf.internalv[sockscf.internalc - 1].addr
198
yyerror("can't find interface/address: %s", addr->addr.ifname);
209
const struct ruleaddress_t *addr;
212
switch (addr->atype) {
213
case SOCKS_ADDR_DOMAIN: {
218
while (hostname2sockaddr(addr->addr.domain, i, &sa) != NULL) {
219
NEWINTERNAL_EXTERNAL(sockscf.external.addrc,
220
sockscf.external.addrv);
222
/* LINTED pointer casts may be troublesome */
223
TOIN(&sa)->sin_port = addr->port.tcp;
224
sockaddr2ruleaddress(&sa,
225
&sockscf.external.addrv[sockscf.external.addrc - 1]);
230
yyerror("could not resolve name %s: %s",
231
addr->addr.domain, hstrerror(h_errno));
235
case SOCKS_ADDR_IPV4: {
236
if (addr->addr.ipv4.ip.s_addr == htonl(INADDR_ANY))
237
yyerror("external address can't be a wildcard address");
238
NEWINTERNAL_EXTERNAL(sockscf.external.addrc,
239
sockscf.external.addrv);
240
sockscf.external.addrv[sockscf.external.addrc - 1] = *addr;
241
sockscf.external.addrv[sockscf.external.addrc - 1].addr.ipv4.mask.s_addr = htonl(0xffffffff);
244
case SOCKS_ADDR_IFNAME:
245
NEWINTERNAL_EXTERNAL(sockscf.external.addrc,
246
sockscf.external.addrv);
247
sockscf.external.addrv[sockscf.external.addrc - 1] = *addr;
258
addclientrule(newrule)
259
const struct rule_t *newrule;
261
struct rule_t *rule, ruletoadd;
264
ruletoadd = *newrule; /* for const. */
266
rule = addrule(&ruletoadd, &sockscf.crule, 1);
268
if (rule->state.methodc == 0)
269
if (rule->user == NULL)
270
rule->state.methodv[rule->state.methodc++] = AUTHMETHOD_NONE;
272
for (i = 0; i < rule->state.methodc; ++i)
273
switch (rule->state.methodv[i]) {
274
case AUTHMETHOD_NONE:
275
case AUTHMETHOD_RFC931:
280
yyerror("method %s is not valid for clientrules",
281
method2string(rule->state.methodv[i]));
286
/* LINTED cast discards 'const' from pointer target type */
287
return (struct rule_t *)rule;
291
addsocksrule(newrule)
292
const struct rule_t *newrule;
297
rule = addrule(newrule, &sockscf.srule, 0);
301
/* LINTED cast discards 'const' from pointer target type */
302
return (struct rule_t *)rule;
305
struct linkedname_t *
306
adduser(ruleuser, name)
307
struct linkedname_t **ruleuser;
310
struct linkedname_t *user, *last;
312
for (user = *ruleuser, last = NULL; user != NULL; user = user->next)
315
if ((user = (struct linkedname_t *)malloc(sizeof(*user))) == NULL)
318
if ((user->name = strdup(name)) == NULL)
322
if (*ruleuser == NULL)
333
const struct rule_t *rule;
335
char addr[MAXRULEADDRSTRING];
337
slog(LOG_INFO, "socks-rule #%u, line #%lu",
338
rule->number, rule->linenumber);
340
slog(LOG_INFO, "verdict: %s", verdict2string(rule->verdict));
342
slog(LOG_INFO, "src: %s",
343
ruleaddress2string(&rule->src, addr, sizeof(addr)));
345
slog(LOG_INFO, "dst: %s",
346
ruleaddress2string(&rule->dst, addr, sizeof(addr)));
348
slog(LOG_INFO, "redirect from: %s",
349
ruleaddress2string(&rule->rdr_from, addr, sizeof(addr)));
351
slog(LOG_INFO, "redirect to: %s",
352
ruleaddress2string(&rule->rdr_to, addr, sizeof(addr)));
354
if (rule->bw != NULL)
355
slog(LOG_INFO, "max bandwidth to use: %ld B/s", rule->bw->maxbps);
357
showuser(rule->user);
360
if (*rule->pamservicename != NUL)
361
slog(LOG_INFO, "pam.servicename: %s", rule->pamservicename);
362
#endif /* HAVE_PAM */
364
showstate(&rule->state);
369
if (*rule->libwrap != NUL)
370
slog(LOG_INFO, "libwrap: %s", rule->libwrap);
371
#endif /* HAVE_LIBWRAP */
376
const struct rule_t *rule;
378
char addr[MAXRULEADDRSTRING];
380
slog(LOG_INFO, "client-rule #%u, line #%lu",
381
rule->number, rule->linenumber);
383
slog(LOG_INFO, "verdict: %s", verdict2string(rule->verdict));
385
slog(LOG_INFO, "src: %s",
386
ruleaddress2string(&rule->src, addr, sizeof(addr)));
388
slog(LOG_INFO, "dst: %s",
389
ruleaddress2string(&rule->dst, addr, sizeof(addr)));
391
showmethod(rule->state.methodc, rule->state.methodv);
393
showuser(rule->user);
396
if (*rule->pamservicename != NUL)
397
slog(LOG_INFO, "pamservicename: %s", rule->pamservicename);
398
#endif /* HAVE_PAM */
400
if (rule->bw != NULL)
401
slog(LOG_INFO, "max bandwidth to use: %ld B/s", rule->bw->maxbps);
406
if (*rule->libwrap != NUL)
407
slog(LOG_INFO, "libwrap: %s", rule->libwrap);
408
#endif /* HAVE_LIBWRAP */
413
const struct config_t *sockscf;
416
char address[MAXRULEADDRSTRING], buf[1024];
419
slog(LOG_DEBUG, "internal addresses (%d):", sockscf->internalc);
420
for (i = 0; i < sockscf->internalc; ++i)
421
slog(LOG_DEBUG, "\t%s",
422
sockaddr2string(&sockscf->internalv[i].addr, address,
425
slog(LOG_DEBUG, "external addresses (%d):", sockscf->external.addrc);
426
for (i = 0; i < sockscf->external.addrc; ++i) {
427
ruleaddress2string(&sockscf->external.addrv[i], address,
430
slog(LOG_DEBUG, "\t%s", address);
432
slog(LOG_DEBUG, "external address rotation: %s",
433
rotation2string(sockscf->external.rotation));
435
slog(LOG_DEBUG, "compatibility options: %s",
436
compats2string(&sockscf->compat, buf, sizeof(buf)));
438
slog(LOG_DEBUG, "extensions enabled: %s",
439
extensions2string(&sockscf->extension, buf, sizeof(buf)));
441
slog(LOG_DEBUG, "logoutput goes to: %s",
442
logtypes2string(&sockscf->log, buf, sizeof(buf)));
444
slog(LOG_DEBUG, "cmdline options:\n%s",
445
options2string(&sockscf->option, "", buf, sizeof(buf)));
447
slog(LOG_DEBUG, "resolveprotocol: %s",
448
resolveprotocol2string(sockscf->resolveprotocol));
450
slog(LOG_DEBUG, "srchost:\n%s",
451
srchosts2string(&sockscf->srchost, "", buf, sizeof(buf)));
453
slog(LOG_DEBUG, "negotiate timeout: %lds",
454
(long)sockscf->timeout.negotiate);
455
slog(LOG_DEBUG, "i/o timeout: %lds",
456
(long)sockscf->timeout.io);
458
slog(LOG_DEBUG, "euid: %d", sockscf->state.euid);
460
slog(LOG_DEBUG, "userid:\n%s",
461
userids2string(&sockscf->uid, "", buf, sizeof(buf)));
463
bufused = snprintfn(buf, sizeof(buf), "method(s): ");
464
for (i = 0; (size_t)i < sockscf->methodc; ++i)
465
bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s%s",
466
i > 0 ? ", " : "", method2string(sockscf->methodv[i]));
467
slog(LOG_DEBUG, buf);
469
bufused = snprintfn(buf, sizeof(buf), "clientmethod(s): ");
470
for (i = 0; (size_t)i < sockscf->clientmethodc; ++i)
471
bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s%s",
472
i > 0 ? ", " : "", method2string(sockscf->clientmethodv[i]));
473
slog(LOG_DEBUG, buf);
475
if (sockscf->option.debug) {
479
for (count = 0, rule = sockscf->crule; rule != NULL;
482
slog(LOG_DEBUG, "client-rules (%d): ", count);
483
for (rule = sockscf->crule; rule != NULL; rule = rule->next)
486
for (count = 0, rule = sockscf->srule; rule != NULL;
489
slog(LOG_DEBUG, "socks-rules (%d): ", count);
490
for (rule = sockscf->srule; rule != NULL; rule = rule->next)
502
* internal; don't touch, only settable at start.
505
/* external addresses can be changed. */
506
free(sockscf.external.addrv);
507
sockscf.external.addrv = NULL;
508
sockscf.external.addrc = 0;
510
/* delete all old socks rules */
511
rule = sockscf.srule;
512
while (rule != NULL) {
513
struct rule_t *next = rule->next;
514
struct linkedname_t *user, *nextuser;
517
while (user != NULL) {
518
nextuser = user->next;
526
sockscf.srule = NULL;
528
/* clientrules too. */
529
rule = sockscf.crule;
530
while (rule != NULL) {
531
struct rule_t *next = rule->next;
532
struct linkedname_t *user, *nextuser;
535
while (user != NULL) {
536
nextuser = user->next;
544
sockscf.crule = NULL;
546
/* route; currently not supported in server. */
548
/* compat, read from configfile. */
549
bzero(&sockscf.compat, sizeof(sockscf.compat));
551
/* extensions, read from configfile. */
552
bzero(&sockscf.extension, sizeof(sockscf.extension));
554
/* log; only settable at start. */
556
/* option; only settable at commandline. */
558
/* resolveprotocol, read from configfile. */
559
bzero(&sockscf.resolveprotocol, sizeof(sockscf.resolveprotocol));
561
/* srchost, read from configfile. */
562
bzero(&sockscf.srchost, sizeof(sockscf.srchost));
566
/* state; keep it. */
568
/* methods, read from configfile. */
569
bzero(sockscf.methodv, sizeof(sockscf.methodv));
572
bzero(sockscf.clientmethodv, sizeof(sockscf.clientmethodv));
573
sockscf.clientmethodc = 0;
576
/* timeout, read from configfile. */
577
bzero(&sockscf.timeout, sizeof(sockscf.timeout));
579
/* uid, read from configfile. */
580
bzero(&sockscf.uid, sizeof(sockscf.uid));
584
iolog(rule, state, operation, src, srcauth, dst, dstauth, data, count)
586
const struct connectionstate_t *state;
588
const struct sockshost_t *src;
589
const struct authmethod_t *srcauth;
590
const struct sockshost_t *dst;
591
const struct authmethod_t *dstauth;
596
char srcstring[MAXSOCKSHOSTSTRING + MAXAUTHINFOLEN];
597
char dststring[sizeof(srcstring)];
598
char rulecommand[256];
601
authinfo(srcauth, srcstring, sizeof(srcstring));
602
p = strlen(srcstring);
603
sockshost2string(src, &srcstring[p], sizeof(srcstring) - p);
605
authinfo(dstauth, dststring, sizeof(dststring));
606
p = strlen(dststring);
607
sockshost2string(dst, &dststring[p], sizeof(dststring) - p);
609
snprintfn(rulecommand, sizeof(rulecommand), "%s(%d): %s/%s",
610
verdict2string(rule->verdict),
611
rule->number, protocol2string(state->protocol),
612
command2string(state->command));
615
case OPERATION_ACCEPT:
616
case OPERATION_CONNECT:
617
if (rule->log.connect)
618
slog(LOG_INFO, "%s [: %s -> %s%s%s",
619
rulecommand, srcstring, dststring,
620
(data == NULL || *data == NUL) ? "" : ": ",
621
(data == NULL || *data == NUL) ? "" : data);
624
case OPERATION_ABORT:
625
if (rule->log.disconnect || rule->log.error)
626
slog(LOG_INFO, "%s ]: %s -> %s: %s",
627
rulecommand, srcstring, dststring,
628
data == NULL ? strerror(errno) : data);
631
case OPERATION_ERROR:
633
slog(LOG_INFO, "%s ]: %s -> %s: %s",
634
rulecommand, srcstring, dststring,
635
data == NULL ? strerror(errno) : data);
639
if (rule->log.data) {
642
SASSERTX(data != NULL);
644
slog(LOG_INFO, "%s -: %s -> %s (%lu): %s",
645
rulecommand, srcstring, dststring, (unsigned long)count,
646
strcheck(visdata = str2vis(data, count)));
652
if (rule->log.iooperation)
653
slog(LOG_INFO, "%s -: %s -> %s (%lu)",
654
rulecommand, srcstring, dststring, (unsigned long)count);
663
rulespermit(s, peer, local, match, state, src, dst, msg, msgsize)
665
const struct sockaddr *peer, *local;
666
struct rule_t *match;
667
struct connectionstate_t *state;
668
const struct sockshost_t *src;
669
const struct sockshost_t *dst;
673
const char *function = "rulespermit()";
675
static struct rule_t defrule;
677
struct connectionstate_t ostate;
681
struct request_info libwraprequest;
683
libwrapinit(s, &libwraprequest);
684
#else /* !HAVE_LIBWRAP */
685
void *libwraprequest = NULL;
688
/* make a somewhat sensible default rule for entries with no match. */
690
defrule.verdict = VERDICT_BLOCK;
693
defrule.src.atype = SOCKS_ADDR_IPV4;
694
defrule.src.addr.ipv4.ip.s_addr = htonl(INADDR_ANY);
695
defrule.src.addr.ipv4.mask.s_addr = htonl(0);
696
defrule.src.port.tcp = htons(0);
697
defrule.src.port.udp = htons(0);
698
defrule.src.portend = htons(0);
699
defrule.src.operator = none;
701
defrule.dst = defrule.src;
703
memset(&defrule.log, 0, sizeof(defrule.log));
704
defrule.log.connect = 1;
705
defrule.log.iooperation = 1; /* blocked iooperations. */
707
if (sockscf.option.debug) {
708
defrule.log.disconnect = 1;
709
defrule.log.error = 1;
712
memset(&defrule.state.command, UCHAR_MAX, sizeof(defrule.state.command));
714
defrule.state.methodc = 0;
716
memset(&defrule.state.protocol, UCHAR_MAX,
717
sizeof(defrule.state.protocol));
719
memset(&defrule.state.proxyprotocol, UCHAR_MAX,
720
sizeof(defrule.state.proxyprotocol));
723
*defrule.libwrap = NUL;
724
#endif /* HAVE_LIBWRAP */
732
/* what rulebase to use. XXX nicer way to do this. */
733
switch (state->command) {
735
/* only set by negotiate children so must be clientrule. */
736
rule = sockscf.crule;
737
methodv = sockscf.clientmethodv;
738
methodc = sockscf.clientmethodc;
742
/* everyone else, socksrules. */
743
rule = sockscf.srule;
744
methodv = sockscf.methodv;
745
methodc = sockscf.methodc;
750
* let "state" be unchanged from original unless we actually get a match.
751
* The exception to this is state->auth.methodv and state->auth.badmethodv,
752
* we change them so we can "cache" it, and callee could in theory
753
* use it to see which methods we tried.
755
for (ostate = *state; rule != NULL; rule = rule->next, *state = ostate) {
758
/* current rule covers desired command? */
759
switch (state->command) {
761
if (!rule->state.command.bind)
766
if (!rule->state.command.connect)
770
case SOCKS_UDPASSOCIATE:
771
if (!rule->state.command.udpassociate)
775
/* pseudo commands. */
777
case SOCKS_BINDREPLY:
778
if (!rule->state.command.bindreply)
783
if (!rule->state.command.udpreply)
787
/* client-rule commands. */
792
SERRX(state->command);
795
/* current rule covers desired protocol? */
796
switch (state->protocol) {
798
if (!rule->state.protocol.tcp)
803
if (!rule->state.protocol.udp)
808
SERRX(state->protocol);
811
/* current rule covers desired version? */
812
switch (state->version) {
814
if (!rule->state.proxyprotocol.socks_v4)
819
if (!rule->state.proxyprotocol.socks_v5)
824
SERRX(state->version);
827
/* current rule allows for selected authentication? */
828
if (!methodisset(state->auth.method, rule->state.methodv,
829
rule->state.methodc)) {
833
* There are some "extra" (non-standard) methods that are independent
834
* of socks protocol negotiation and it's thus possible
835
* to get a match on them even if above check failed, i.e.
836
* it's possible to "upgrade" the method.
838
* We therefor look at what methods this rule wants and see
839
* if can match it with what we have, or get it.
841
* Currently these methods are: rfc931 and pam.
844
for (i = methodisok = 0; i < methodc; ++i) {
845
if (methodisset(methodv[i], rule->state.methodv,
846
rule->state.methodc)) {
847
switch (methodv[i]) {
849
case AUTHMETHOD_RFC931:
850
strncpy((char *)state->auth.mdata.rfc931.name,
851
eval_user(&libwraprequest),
852
sizeof(state->auth.mdata.rfc931.name) - 1);
854
/* libwrap sets it to unknown if no identreply. */
855
if (strcmp((char *)state->auth.mdata.rfc931.name,
856
STRING_UNKNOWN) == 0)
857
*state->auth.mdata.rfc931.name = NUL;
859
if (state->auth.mdata.rfc931.name[
860
sizeof(state->auth.mdata.rfc931.name) - 1] != NUL) {
861
slog(LOG_NOTICE, "%s: rfc931 name truncated", function);
862
state->auth.mdata.rfc931.name[
863
sizeof(state->auth.mdata.rfc931.name) - 1] = NUL;
865
/* better safe than sorry. */
866
*state->auth.mdata.rfc931.name = NUL;
869
if (*state->auth.mdata.rfc931.name != NUL)
872
#endif /* HAVE_LIBWRAP */
876
slog(LOG_DEBUG, "%s: trying to find match for pam ...",
879
switch (state->auth.method) {
880
case AUTHMETHOD_UNAME: {
881
/* it's a union, make a copy first. */
882
const struct authmethod_uname_t uname
883
= state->auth.mdata.uname;
885
/* similar enough, just copy name/password. */
887
strcpy((char *)state->auth.mdata.pam.name,
888
(const char *)uname.name);
889
strcpy((char *)state->auth.mdata.pam.password,
890
(const char *)uname.password);
896
case AUTHMETHOD_RFC931: {
897
/* it's a union, make a copy first. */
898
const struct authmethod_rfc931_t rfc931
899
= state->auth.mdata.rfc931;
901
strcpy((char *)state->auth.mdata.pam.name,
902
(const char *)rfc931.name);
903
*state->auth.mdata.pam.password = NUL;
908
case AUTHMETHOD_NONE:
909
*state->auth.mdata.pam.name = NUL;
910
*state->auth.mdata.pam.password = NUL;
916
strcpy(state->auth.mdata.pam.servicename,
917
rule->pamservicename);
918
#endif /* HAVE_PAM */
922
state->auth.method = methodv[i];
929
continue; /* no usable method found. */
933
SASSERTX(methodisset(state->auth.method, rule->state.methodv,
934
rule->state.methodc));
936
i = accessmatch(s, &state->auth, peer, local, rule->user, msg, msgsize);
938
/* two fields we want to copy. */
939
memcpy(ostate.auth.methodv, state->auth.methodv,
940
state->auth.methodc * sizeof(*state->auth.methodv));
941
ostate.auth.methodc = state->auth.methodc;
942
memcpy(ostate.auth.badmethodv, state->auth.badmethodv,
943
state->auth.badmethodc * sizeof(*state->auth.badmethodv));
944
ostate.auth.badmethodc = state->auth.badmethodc;
948
* The reason for the continue is the fact that we can
949
* "upgrade" the method if we have a rule specifying a
950
* non-socks method. That means "name" and "password"
951
* gotten for this method/rule need not be the same as gotten
957
* This is a little tricky. For some commands we may not
958
* have all info at time of (preliminary) rulechecks.
959
* What we want to do if there is no (complete) address given is
960
* to see if there's any chance at all the rules will permit this
961
* request when the address (later) becomes available.
962
* We therefore continue to scan the rules until we either get
963
* a pass (ignoring peer with missing info), or the default block
968
if (!addressmatch(&rule->src, src, state->protocol, 0))
972
if (rule->verdict == VERDICT_BLOCK)
973
continue; /* continue scan. */
976
if (!addressmatch(&rule->dst, dst, state->protocol, 0))
980
if (rule->verdict == VERDICT_BLOCK)
981
continue; /* continue scan. */
986
if (rule == NULL) /* no rules matched; match default rule. */
992
* got our rule, now check connection. Connectioncheck
993
* requires the rule matched so needs to be delayed til here.
996
if (!connectisok(&libwraprequest, match))
997
match->verdict = VERDICT_BLOCK;
1000
* specialcases that we delay til here to get correct addr/rule match,
1001
* even if we could have decided on the final answer before.
1003
switch (state->command) {
1005
if (dst->atype == SOCKS_ADDR_IPV4 && dst->addr.ipv4.s_addr == htonl(0))
1006
if (!sockscf.extension.bind) {
1007
slog(LOG_DEBUG, "%s: client requested disabled extension: bind",
1009
match->verdict = VERDICT_BLOCK;
1014
return match->verdict == VERDICT_PASS;
1018
authinfo(auth, info, infolen)
1019
const struct authmethod_t *auth;
1023
const char *authname, *methodname;
1026
methodname = method2string(auth->method);
1028
switch (auth->method) {
1029
case AUTHMETHOD_NONE:
1030
case AUTHMETHOD_NOACCEPT: /* closing connection next presumably. */
1031
authname = methodname = NULL;
1034
case AUTHMETHOD_UNAME:
1035
authname = (const char *)auth->mdata.uname.name;
1038
case AUTHMETHOD_RFC931:
1039
authname = (const char *)auth->mdata.rfc931.name;
1042
case AUTHMETHOD_PAM:
1043
authname = (const char *)auth->mdata.pam.name;
1047
SERRX(auth->method);
1051
authname = methodname = NULL;
1053
if (authname == NULL || *authname == NUL)
1056
snprintfn(info, infolen, "%s%%%s@", methodname, authname);
1062
addressisbindable(addr)
1063
const struct ruleaddress_t *addr;
1065
const char *function = "addressisbindable()";
1066
struct sockaddr saddr;
1067
char saddrs[MAX(MAXSOCKSHOSTSTRING, MAXSOCKADDRSTRING)];
1070
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1071
swarn("%s: socket(SOCK_STREAM)", function);
1075
switch (addr->atype) {
1076
case SOCKS_ADDR_IPV4: {
1077
struct sockshost_t host;
1079
sockshost2sockaddr(ruleaddress2sockshost(addr, &host, SOCKS_TCP),
1082
if (sockd_bind(s, &saddr, 0) != 0) {
1083
swarn("%s: can't bind address: %s",
1084
function, sockaddr2string(&saddr, saddrs, sizeof(saddrs)));
1091
case SOCKS_ADDR_IFNAME:
1092
if (ifname2sockaddr(addr->addr.ifname, 0, &saddr) == NULL) {
1093
swarn("%s: can't find interface: %s", function, addr->addr.ifname);
1098
if (sockd_bind(s, &saddr, 0) != 0) {
1099
swarn("%s: can't bind address %s of interface %s",
1100
function, sockaddr2string(&saddr, saddrs, sizeof(saddrs)),
1116
static struct rule_t *
1117
addrule(newrule, rulebase, client)
1118
const struct rule_t *newrule;
1119
struct rule_t **rulebase;
1122
static const struct serverstate_t state;
1123
const char *function = "addrule()";
1124
struct rule_t *rule;
1130
methodv = sockscf.clientmethodv;
1131
methodc = sockscf.clientmethodc;
1134
methodv = sockscf.methodv;
1135
methodc = sockscf.methodc;
1138
if ((rule = malloc(sizeof(*rule))) == NULL)
1139
serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);
1142
/* try to set values not set to a sensible default. */
1144
if (sockscf.option.debug) {
1145
rule->log.connect = 1;
1146
rule->log.disconnect = 1;
1147
rule->log.error = 1;
1148
rule->log.iooperation = 1;
1150
/* else; don't touch logging, no logging is ok. */
1152
/* if no command set, set all. */
1153
if (memcmp(&state.command, &rule->state.command, sizeof(state.command)) == 0)
1154
memset(&rule->state.command, UCHAR_MAX, sizeof(rule->state.command));
1157
* If no method set, set all set from global methodline that make sense.
1159
if (rule->state.methodc == 0) {
1160
for (i = 0; i < methodc; ++i)
1161
switch (methodv[i]) {
1162
case AUTHMETHOD_NONE:
1163
if (rule->user != NULL)
1165
/* else; */ /* FALLTHROUGH */
1168
rule->state.methodv[rule->state.methodc++] = methodv[i];
1172
/* warn about methods not set in the global method? May not be an error. */
1173
for (i = 0; i < rule->state.methodc; ++i)
1174
if (!methodisset(rule->state.methodv[i], methodv, methodc))
1175
yywarn("method \"%s\" set in rule but not in global methodline",
1176
method2string(rule->state.methodv[i]));
1178
/* if no protocol set, set all. */
1179
if (memcmp(&state.protocol, &rule->state.protocol, sizeof(state.protocol))
1181
memset(&rule->state.protocol, UCHAR_MAX, sizeof(rule->state.protocol));
1183
/* if no proxyprotocol set, set all socks protocols. */
1184
if (memcmp(&state.proxyprotocol, &rule->state.proxyprotocol,
1185
sizeof(state.proxyprotocol)) == 0) {
1186
rule->state.proxyprotocol.socks_v4 = 1;
1187
rule->state.proxyprotocol.socks_v5 = 1;
1190
if (*rulebase == NULL) {
1192
(*rulebase)->number = 1;
1195
struct rule_t *lastrule;
1197
/* append this rule to the end of our list. */
1199
lastrule = *rulebase;
1200
while (lastrule->next != NULL)
1201
lastrule = lastrule->next;
1203
rule->number = lastrule->number + 1;
1204
lastrule->next = rule;
1214
const struct rule_t *rule;
1217
struct ruleaddress_t ruleaddr;
1219
if (rule->state.methodc == 0)
1220
yywarn("rule allows no methods");
1222
if (rule->user != NULL) {
1223
/* check that all methods given provide usernames. */
1224
for (i = 0; i < rule->state.methodc; ++i)
1225
switch (rule->state.methodv[i]) {
1226
case AUTHMETHOD_UNAME:
1227
case AUTHMETHOD_RFC931:
1228
case AUTHMETHOD_PAM:
1232
yyerror("method \"%s\" can not provide usernames",
1233
method2string(rule->state.methodv[i]));
1237
if (rule->src.atype == SOCKS_ADDR_IFNAME
1238
|| rule->dst.atype == SOCKS_ADDR_IFNAME)
1239
yyerror("src/dst address in rules can't use interfacenames");
1241
/* any port is good for testing. */
1242
ruleaddr = rule->rdr_from;
1243
ruleaddr.port.tcp = htons(0);
1244
if (!addressisbindable(&ruleaddr)) {
1245
char addr[MAXRULEADDRSTRING];
1247
yyerror("%s is not bindable",
1248
ruleaddress2string(&ruleaddr, addr, sizeof(addr)));
1251
if (rule->rdr_to.atype == SOCKS_ADDR_IFNAME)
1252
yyerror("redirect to an interface (%s) is not supported "
1254
rule->rdr_to.addr.ifname);
1257
if (*rule->pamservicename != NUL)
1258
if (!methodisset(AUTHMETHOD_PAM, rule->state.methodv,
1259
rule->state.methodc))
1260
yyerror("pamservicename set for rule but not method pam");
1262
if (strcmp(rule->pamservicename, DEFAULT_PAMSERVICENAME) != 0)
1263
sockscf.state.unfixedpamdata = 1; /* pamservicename varies. */
1264
#endif /* HAVE_PAM */
1269
const struct linkedname_t *user;
1273
users2string(user, buf, sizeof(buf));
1274
if (strlen(buf) > 0)
1275
slog(LOG_INFO, "user: %s", buf);
1280
const struct log_t *log;
1284
slog(LOG_INFO, "log: %s", logs2string(log, buf, sizeof(buf)));
1290
libwrapinit(s, request)
1292
struct request_info *request;
1295
request_init(request, RQ_FILE, s, RQ_DAEMON, __progname, 0);
1298
#endif /* HAVE_LIBWRAP */
1301
connectisok(request, rule)
1303
struct request_info *request;
1307
const struct rule_t *rule;
1312
/* do we need to involve libwrap for this rule? */
1313
if (*rule->libwrap != NUL
1314
|| sockscf.srchost.nomismatch
1315
|| sockscf.srchost.nounknown) {
1316
const char *function = "connectisok()";
1317
char libwrap[LIBWRAPBUF];
1320
socks_seteuid(&euid, sockscf.uid.libwrap);
1322
/* libwrap modifies the passed buffer. */
1323
SASSERTX(strlen(rule->libwrap) < sizeof(libwrap));
1324
strcpy(libwrap, rule->libwrap);
1326
/* Wietse Venema says something along the lines of: */
1327
if (setjmp(tcpd_buf) != 0) {
1328
socks_reseteuid(sockscf.uid.libwrap, euid);
1329
swarnx("%s: failed libwrap line: %s", function, libwrap);
1330
return 0; /* something got screwed up. */
1332
process_options(libwrap, request);
1334
if (sockscf.srchost.nounknown)
1335
if (strcmp(eval_hostname(request->client), STRING_UNKNOWN) == 0) {
1336
slog(LOG_INFO, "%s: srchost unknown",
1337
eval_hostaddr(request->client));
1338
socks_reseteuid(sockscf.uid.libwrap, euid);
1342
if (sockscf.srchost.nomismatch)
1343
if (strcmp(eval_hostname(request->client), STRING_PARANOID) == 0) {
1344
slog(LOG_INFO, "%s: srchost ip/host mismatch",
1345
eval_hostaddr(request->client));
1346
socks_reseteuid(sockscf.uid.libwrap, euid);
1350
socks_reseteuid(sockscf.uid.libwrap, euid);
1353
#else /* !HAVE_LIBWRAP */
1355
#endif /* !HAVE_LIBWRAP */