~ubuntu-branches/ubuntu/trusty/dante/trusty-proposed

« back to all changes in this revision

Viewing changes to sockd/serverconfig.c

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Bridgett
  • Date: 2002-04-07 12:45:55 UTC
  • Revision ID: james.westby@ubuntu.com-20020407124555-qke8rt2tdor0naz2
Tags: upstream-1.1.11.12p1
ImportĀ upstreamĀ versionĀ 1.1.11.12p1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997, 1998, 1999, 2000, 2001
 
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 "config_parse.h"
 
46
 
 
47
static const char rcsid[] =
 
48
"$Id: serverconfig.c,v 1.178 2002/01/01 15:47:11 michaels Exp $";
 
49
 
 
50
__BEGIN_DECLS
 
51
 
 
52
static void
 
53
showuser __P((const struct linkedname_t *user));
 
54
/*
 
55
 * shows usernames in "user".
 
56
 */
 
57
 
 
58
static void
 
59
showlog __P((const struct log_t *log));
 
60
/*
 
61
 * shows what type of logging is specified in "log".
 
62
 */
 
63
 
 
64
#if HAVE_LIBWRAP
 
65
        extern jmp_buf tcpd_buf;
 
66
 
 
67
static void
 
68
libwrapinit __P((int s, struct request_info *request));
 
69
/*
 
70
 * Initializes "request" for later usage via libwrap.
 
71
 */
 
72
 
 
73
static int
 
74
connectisok __P((struct request_info *request, const struct rule_t *rule));
 
75
#else /* !HAVE_LIBWRAP */
 
76
static int
 
77
connectisok __P((void *request, const struct rule_t *rule));
 
78
#endif /* !HAVE_LIBWRAP */
 
79
/*
 
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
 
83
 * connection/packet.
 
84
 *
 
85
 * Returns:
 
86
 *              If connection is acceptable: true
 
87
 *              If connection is not acceptable: false
 
88
 */
 
89
 
 
90
static struct rule_t *
 
91
addrule __P((const struct rule_t *newrule, struct rule_t **rulebase,
 
92
                                 int client));
 
93
/*
 
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").
 
97
 */
 
98
 
 
99
static void
 
100
checkrule __P((const struct rule_t *rule));
 
101
/*
 
102
 * Check that the rule "rule" makes sense.
 
103
 */
 
104
 
 
105
__END_DECLS
 
106
 
 
107
struct config_t sockscf;
 
108
const int socks_configtype = CONFIGTYPE_SERVER;
 
109
 
 
110
#if HAVE_LIBWRAP
 
111
int allow_severity, deny_severity;
 
112
#endif  /* HAVE_LIBWRAP */
 
113
 
 
114
/* expand array by one, increment argc. */
 
115
#define NEWINTERNAL_EXTERNAL(argc, argv)  \
 
116
do { \
 
117
        if ((argv = realloc(argv, sizeof(*argv) * ++argc)) == NULL) \
 
118
                yyerror(NOMEM); \
 
119
        bzero(&argv[argc - 1], sizeof(*argv)); \
 
120
} while (lintnoloop_common_h)
 
121
 
 
122
 
 
123
void
 
124
addinternal(addr)
 
125
        const struct ruleaddress_t *addr;
 
126
{
 
127
 
 
128
        if (sockscf.state.init) {
 
129
#if 0 /* don't know how to do this now, seems like too much work. */
 
130
                int i;
 
131
 
 
132
                for (i = 0; i < sockscf.internalc; ++i)
 
133
                        if (memcmp(&sockscf.internalv[i], addr, sizeof(addr)) == 0)
 
134
                                break;
 
135
 
 
136
                if (i == sockscf.internalc)
 
137
                        swarnx("can't change internal addresses once running");
 
138
#endif
 
139
        }
 
140
        else
 
141
                switch (addr->atype) {
 
142
                        case SOCKS_ADDR_IPV4: {
 
143
                                struct sockshost_t host;
 
144
 
 
145
                                NEWINTERNAL_EXTERNAL(sockscf.internalc, sockscf.internalv);
 
146
 
 
147
                                sockshost2sockaddr(ruleaddress2sockshost(addr, &host, SOCKS_TCP),
 
148
                                &sockscf.internalv[sockscf.internalc - 1].addr);
 
149
                                break;
 
150
                        }
 
151
 
 
152
                        case SOCKS_ADDR_DOMAIN: {
 
153
                                struct sockaddr sa;
 
154
                                int i;
 
155
 
 
156
                                i = 0;
 
157
                                while (hostname2sockaddr(addr->addr.domain, i, &sa) != NULL) {
 
158
                                        NEWINTERNAL_EXTERNAL(sockscf.internalc,
 
159
                                        sockscf.internalv);
 
160
 
 
161
                                        /* LINTED pointer casts may be troublesome */
 
162
                                        TOIN(&sa)->sin_port = addr->port.tcp;
 
163
                                        sockscf.internalv[sockscf.internalc - 1].addr = sa;
 
164
                                        ++i;
 
165
                                }
 
166
 
 
167
                                if (i == 0)
 
168
                                        yyerror("could not resolve name %s: %s",
 
169
                                        addr->addr.domain, hstrerror(h_errno));
 
170
                                break;
 
171
                        }
 
172
 
 
173
                        case SOCKS_ADDR_IFNAME: {
 
174
                                struct ifaddrs ifa, *ifap = &ifa, *iface;
 
175
                                int m;
 
176
 
 
177
                                if (getifaddrs(&ifap) != 0)
 
178
                                        serr(EXIT_FAILURE, "getifaddrs()");
 
179
 
 
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,
 
185
                                                sockscf.internalv);
 
186
 
 
187
                                                /* LINTED pointer casts may be troublesome */
 
188
                                                TOIN(iface->ifa_addr)->sin_port = addr->port.tcp;
 
189
 
 
190
                                                sockscf.internalv[sockscf.internalc - 1].addr
 
191
                                                = *iface->ifa_addr;
 
192
 
 
193
                                                m = 1;
 
194
                                        }
 
195
                                freeifaddrs(ifap);
 
196
 
 
197
                                if (!m)
 
198
                                        yyerror("can't find interface/address: %s", addr->addr.ifname);
 
199
                                break;
 
200
                        }
 
201
 
 
202
                        default:
 
203
                                SERRX(addr->atype);
 
204
                }
 
205
}
 
206
 
 
207
void
 
208
addexternal(addr)
 
209
        const struct ruleaddress_t *addr;
 
210
{
 
211
 
 
212
        switch (addr->atype) {
 
213
                        case SOCKS_ADDR_DOMAIN: {
 
214
                                struct sockaddr sa;
 
215
                                int i;
 
216
 
 
217
                                i = 0;
 
218
                                while (hostname2sockaddr(addr->addr.domain, i, &sa) != NULL) {
 
219
                                        NEWINTERNAL_EXTERNAL(sockscf.external.addrc,
 
220
                                        sockscf.external.addrv);
 
221
 
 
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]);
 
226
                                        ++i;
 
227
                                }
 
228
 
 
229
                                if (i == 0)
 
230
                                        yyerror("could not resolve name %s: %s",
 
231
                                        addr->addr.domain, hstrerror(h_errno));
 
232
                                break;
 
233
                        }
 
234
 
 
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);
 
242
                        break;
 
243
 
 
244
                case SOCKS_ADDR_IFNAME:
 
245
                        NEWINTERNAL_EXTERNAL(sockscf.external.addrc,
 
246
                        sockscf.external.addrv);
 
247
                        sockscf.external.addrv[sockscf.external.addrc - 1] = *addr;
 
248
                        break;
 
249
                }
 
250
 
 
251
                default:
 
252
                        SERRX(addr->atype);
 
253
        }
 
254
}
 
255
 
 
256
 
 
257
struct rule_t *
 
258
addclientrule(newrule)
 
259
        const struct rule_t *newrule;
 
260
{
 
261
        struct rule_t *rule, ruletoadd;
 
262
        size_t i;
 
263
 
 
264
        ruletoadd = *newrule; /* for const. */
 
265
 
 
266
        rule = addrule(&ruletoadd, &sockscf.crule, 1);
 
267
 
 
268
        if (rule->state.methodc == 0)
 
269
                if (rule->user == NULL)
 
270
                        rule->state.methodv[rule->state.methodc++] = AUTHMETHOD_NONE;
 
271
 
 
272
        for (i = 0; i < rule->state.methodc; ++i)
 
273
                switch (rule->state.methodv[i]) {
 
274
                        case AUTHMETHOD_NONE:
 
275
                        case AUTHMETHOD_RFC931:
 
276
                        case AUTHMETHOD_PAM:
 
277
                                break;
 
278
 
 
279
                        default:
 
280
                                yyerror("method %s is not valid for clientrules",
 
281
                                method2string(rule->state.methodv[i]));
 
282
                }
 
283
 
 
284
        checkrule(rule);
 
285
 
 
286
        /* LINTED cast discards 'const' from pointer target type */
 
287
        return (struct rule_t *)rule;
 
288
}
 
289
 
 
290
struct rule_t *
 
291
addsocksrule(newrule)
 
292
        const struct rule_t *newrule;
 
293
{
 
294
 
 
295
        struct rule_t *rule;
 
296
 
 
297
        rule = addrule(newrule, &sockscf.srule, 0);
 
298
 
 
299
        checkrule(rule);
 
300
 
 
301
        /* LINTED cast discards 'const' from pointer target type */
 
302
        return (struct rule_t *)rule;
 
303
}
 
304
 
 
305
struct linkedname_t *
 
306
adduser(ruleuser, name)
 
307
        struct linkedname_t **ruleuser;
 
308
        const char *name;
 
309
{
 
310
        struct linkedname_t *user, *last;
 
311
 
 
312
        for (user = *ruleuser, last = NULL; user != NULL; user = user->next)
 
313
                last = user;
 
314
 
 
315
        if ((user = (struct linkedname_t *)malloc(sizeof(*user))) == NULL)
 
316
                return NULL;
 
317
 
 
318
        if ((user->name = strdup(name)) == NULL)
 
319
                return NULL;
 
320
        user->next = NULL;
 
321
 
 
322
        if (*ruleuser == NULL)
 
323
                *ruleuser = user;
 
324
        else
 
325
                last->next = user;
 
326
 
 
327
        return *ruleuser;
 
328
}
 
329
 
 
330
 
 
331
void
 
332
showrule(rule)
 
333
        const struct rule_t *rule;
 
334
{
 
335
        char addr[MAXRULEADDRSTRING];
 
336
 
 
337
        slog(LOG_INFO, "socks-rule #%u, line #%lu",
 
338
        rule->number, rule->linenumber);
 
339
 
 
340
        slog(LOG_INFO, "verdict: %s", verdict2string(rule->verdict));
 
341
 
 
342
        slog(LOG_INFO, "src: %s",
 
343
        ruleaddress2string(&rule->src, addr, sizeof(addr)));
 
344
 
 
345
        slog(LOG_INFO, "dst: %s",
 
346
        ruleaddress2string(&rule->dst, addr, sizeof(addr)));
 
347
 
 
348
        slog(LOG_INFO, "redirect from: %s",
 
349
        ruleaddress2string(&rule->rdr_from, addr, sizeof(addr)));
 
350
 
 
351
        slog(LOG_INFO, "redirect to: %s",
 
352
        ruleaddress2string(&rule->rdr_to, addr, sizeof(addr)));
 
353
 
 
354
        if (rule->bw != NULL)
 
355
                slog(LOG_INFO, "max bandwidth to use: %ld B/s", rule->bw->maxbps);
 
356
 
 
357
        showuser(rule->user);
 
358
 
 
359
#if HAVE_PAM
 
360
        if (*rule->pamservicename != NUL)
 
361
                slog(LOG_INFO, "pam.servicename: %s", rule->pamservicename);
 
362
#endif  /* HAVE_PAM */
 
363
 
 
364
        showstate(&rule->state);
 
365
 
 
366
        showlog(&rule->log);
 
367
 
 
368
#if HAVE_LIBWRAP
 
369
        if (*rule->libwrap != NUL)
 
370
                slog(LOG_INFO, "libwrap: %s", rule->libwrap);
 
371
#endif  /* HAVE_LIBWRAP */
 
372
}
 
373
 
 
374
void
 
375
showclient(rule)
 
376
        const struct rule_t *rule;
 
377
{
 
378
        char addr[MAXRULEADDRSTRING];
 
379
 
 
380
        slog(LOG_INFO, "client-rule #%u, line #%lu",
 
381
        rule->number, rule->linenumber);
 
382
 
 
383
        slog(LOG_INFO, "verdict: %s", verdict2string(rule->verdict));
 
384
 
 
385
        slog(LOG_INFO, "src: %s",
 
386
        ruleaddress2string(&rule->src, addr, sizeof(addr)));
 
387
 
 
388
        slog(LOG_INFO, "dst: %s",
 
389
        ruleaddress2string(&rule->dst, addr, sizeof(addr)));
 
390
 
 
391
        showmethod(rule->state.methodc, rule->state.methodv);
 
392
 
 
393
        showuser(rule->user);
 
394
 
 
395
#if HAVE_PAM
 
396
        if (*rule->pamservicename != NUL)
 
397
                slog(LOG_INFO, "pamservicename: %s", rule->pamservicename);
 
398
#endif  /* HAVE_PAM */
 
399
 
 
400
        if (rule->bw != NULL)
 
401
                slog(LOG_INFO, "max bandwidth to use: %ld B/s", rule->bw->maxbps);
 
402
 
 
403
        showlog(&rule->log);
 
404
 
 
405
#if HAVE_LIBWRAP
 
406
        if (*rule->libwrap != NUL)
 
407
                slog(LOG_INFO, "libwrap: %s", rule->libwrap);
 
408
#endif  /* HAVE_LIBWRAP */
 
409
}
 
410
 
 
411
void
 
412
showconfig(sockscf)
 
413
        const struct config_t *sockscf;
 
414
{
 
415
        int i;
 
416
        char address[MAXRULEADDRSTRING], buf[1024];
 
417
        size_t bufused;
 
418
 
 
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,
 
423
                sizeof(address)));
 
424
 
 
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,
 
428
                sizeof(address));
 
429
 
 
430
                slog(LOG_DEBUG, "\t%s", address);
 
431
        }
 
432
        slog(LOG_DEBUG, "external address rotation: %s",
 
433
        rotation2string(sockscf->external.rotation));
 
434
 
 
435
        slog(LOG_DEBUG, "compatibility options: %s",
 
436
        compats2string(&sockscf->compat, buf, sizeof(buf)));
 
437
 
 
438
        slog(LOG_DEBUG, "extensions enabled: %s",
 
439
        extensions2string(&sockscf->extension, buf, sizeof(buf)));
 
440
 
 
441
        slog(LOG_DEBUG, "logoutput goes to: %s",
 
442
        logtypes2string(&sockscf->log, buf, sizeof(buf)));
 
443
 
 
444
        slog(LOG_DEBUG, "cmdline options:\n%s",
 
445
        options2string(&sockscf->option, "", buf, sizeof(buf)));
 
446
 
 
447
        slog(LOG_DEBUG, "resolveprotocol: %s",
 
448
        resolveprotocol2string(sockscf->resolveprotocol));
 
449
 
 
450
        slog(LOG_DEBUG, "srchost:\n%s",
 
451
        srchosts2string(&sockscf->srchost, "", buf, sizeof(buf)));
 
452
 
 
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);
 
457
 
 
458
        slog(LOG_DEBUG, "euid: %d", sockscf->state.euid);
 
459
 
 
460
        slog(LOG_DEBUG, "userid:\n%s",
 
461
        userids2string(&sockscf->uid, "", buf, sizeof(buf)));
 
462
 
 
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);
 
468
 
 
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);
 
474
 
 
475
        if (sockscf->option.debug) {
 
476
                struct rule_t *rule;
 
477
                int count;
 
478
 
 
479
                for (count = 0, rule = sockscf->crule; rule != NULL;
 
480
                rule = rule->next)
 
481
                        ++count;
 
482
                slog(LOG_DEBUG, "client-rules (%d): ", count);
 
483
                for (rule = sockscf->crule; rule != NULL; rule = rule->next)
 
484
                        showclient(rule);
 
485
 
 
486
                for (count = 0, rule = sockscf->srule; rule != NULL;
 
487
                rule = rule->next)
 
488
                        ++count;
 
489
                slog(LOG_DEBUG, "socks-rules (%d): ", count);
 
490
                for (rule = sockscf->srule; rule != NULL; rule = rule->next)
 
491
                        showrule(rule);
 
492
        }
 
493
}
 
494
 
 
495
 
 
496
void
 
497
resetconfig(void)
 
498
{
 
499
        struct rule_t *rule;
 
500
 
 
501
        /*
 
502
         * internal; don't touch, only settable at start.
 
503
         */
 
504
 
 
505
        /* external addresses can be changed. */
 
506
        free(sockscf.external.addrv);
 
507
        sockscf.external.addrv                  = NULL;
 
508
        sockscf.external.addrc                  = 0;
 
509
 
 
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;
 
515
 
 
516
                user = rule->user;
 
517
                while (user != NULL) {
 
518
                        nextuser = user->next;
 
519
                        free(user);
 
520
                        user = nextuser;
 
521
                }
 
522
 
 
523
                free(rule);
 
524
                rule = next;
 
525
        }
 
526
        sockscf.srule = NULL;
 
527
 
 
528
        /* clientrules too. */
 
529
        rule = sockscf.crule;
 
530
        while (rule != NULL) {
 
531
                struct rule_t *next = rule->next;
 
532
                struct linkedname_t *user, *nextuser;
 
533
 
 
534
                user = rule->user;
 
535
                while (user != NULL) {
 
536
                        nextuser = user->next;
 
537
                        free(user);
 
538
                        user = nextuser;
 
539
                }
 
540
 
 
541
                free(rule);
 
542
                rule = next;
 
543
        }
 
544
        sockscf.crule = NULL;
 
545
 
 
546
        /* route; currently not supported in server. */
 
547
 
 
548
        /* compat, read from configfile. */
 
549
        bzero(&sockscf.compat, sizeof(sockscf.compat));
 
550
 
 
551
        /* extensions, read from configfile. */
 
552
        bzero(&sockscf.extension, sizeof(sockscf.extension));
 
553
 
 
554
        /* log; only settable at start. */
 
555
 
 
556
        /* option; only settable at commandline. */
 
557
 
 
558
        /* resolveprotocol, read from configfile. */
 
559
        bzero(&sockscf.resolveprotocol, sizeof(sockscf.resolveprotocol));
 
560
 
 
561
        /* srchost, read from configfile. */
 
562
        bzero(&sockscf.srchost, sizeof(sockscf.srchost));
 
563
 
 
564
        /* stat: keep it. */
 
565
 
 
566
        /* state; keep it. */
 
567
 
 
568
        /* methods, read from configfile. */
 
569
        bzero(sockscf.methodv, sizeof(sockscf.methodv));
 
570
        sockscf.methodc = 0;
 
571
 
 
572
        bzero(sockscf.clientmethodv, sizeof(sockscf.clientmethodv));
 
573
        sockscf.clientmethodc = 0;
 
574
 
 
575
 
 
576
        /* timeout, read from configfile. */
 
577
        bzero(&sockscf.timeout, sizeof(sockscf.timeout));
 
578
 
 
579
        /* uid, read from configfile. */
 
580
        bzero(&sockscf.uid, sizeof(sockscf.uid));
 
581
}
 
582
 
 
583
void
 
584
iolog(rule, state, operation, src, srcauth, dst, dstauth, data, count)
 
585
        struct rule_t *rule;
 
586
        const struct connectionstate_t *state;
 
587
        int operation;
 
588
        const struct sockshost_t *src;
 
589
        const struct authmethod_t *srcauth;
 
590
        const struct sockshost_t *dst;
 
591
        const struct authmethod_t *dstauth;
 
592
        const char *data;
 
593
        size_t count;
 
594
{
 
595
        /* CONSTCOND */
 
596
        char srcstring[MAXSOCKSHOSTSTRING + MAXAUTHINFOLEN];
 
597
        char dststring[sizeof(srcstring)];
 
598
        char rulecommand[256];
 
599
        int p;
 
600
 
 
601
        authinfo(srcauth, srcstring, sizeof(srcstring));
 
602
        p = strlen(srcstring);
 
603
        sockshost2string(src, &srcstring[p], sizeof(srcstring) - p);
 
604
 
 
605
        authinfo(dstauth, dststring, sizeof(dststring));
 
606
        p = strlen(dststring);
 
607
        sockshost2string(dst, &dststring[p], sizeof(dststring) - p);
 
608
 
 
609
        snprintfn(rulecommand, sizeof(rulecommand), "%s(%d): %s/%s",
 
610
        verdict2string(rule->verdict),
 
611
        rule->number, protocol2string(state->protocol),
 
612
        command2string(state->command));
 
613
 
 
614
        switch (operation) {
 
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);
 
622
                        break;
 
623
 
 
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);
 
629
                        break;
 
630
 
 
631
                case OPERATION_ERROR:
 
632
                        if (rule->log.error)
 
633
                                slog(LOG_INFO, "%s ]: %s -> %s: %s",
 
634
                                rulecommand, srcstring, dststring,
 
635
                                data == NULL ? strerror(errno) : data);
 
636
                        break;
 
637
 
 
638
                case OPERATION_IO:
 
639
                        if (rule->log.data) {
 
640
                                char *visdata;
 
641
 
 
642
                                SASSERTX(data != NULL);
 
643
 
 
644
                                slog(LOG_INFO, "%s -: %s -> %s (%lu): %s",
 
645
                                rulecommand, srcstring, dststring, (unsigned long)count,
 
646
                                strcheck(visdata = str2vis(data, count)));
 
647
 
 
648
                                free(visdata);
 
649
                                break;
 
650
                        }
 
651
 
 
652
                        if (rule->log.iooperation)
 
653
                                slog(LOG_INFO, "%s -: %s -> %s (%lu)",
 
654
                                rulecommand, srcstring, dststring, (unsigned long)count);
 
655
                        break;
 
656
 
 
657
                default:
 
658
                        SERRX(operation);
 
659
        }
 
660
}
 
661
 
 
662
int
 
663
rulespermit(s, peer, local, match, state, src, dst, msg, msgsize)
 
664
        int s;
 
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;
 
670
        char *msg;
 
671
        size_t msgsize;
 
672
{
 
673
        const char *function = "rulespermit()";
 
674
        static int init;
 
675
        static struct rule_t defrule;
 
676
        struct rule_t *rule;
 
677
        struct connectionstate_t ostate;
 
678
        int *methodv;
 
679
        int methodc;
 
680
#if HAVE_LIBWRAP
 
681
        struct request_info libwraprequest;
 
682
 
 
683
        libwrapinit(s, &libwraprequest);
 
684
#else /* !HAVE_LIBWRAP */
 
685
        void *libwraprequest = NULL;
 
686
#endif
 
687
 
 
688
        /* make a somewhat sensible default rule for entries with no match. */
 
689
        if (!init) {
 
690
                defrule.verdict                                                 = VERDICT_BLOCK;
 
691
                defrule.number                                                          = 0;
 
692
 
 
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;
 
700
 
 
701
                defrule.dst                                                                     = defrule.src;
 
702
 
 
703
                memset(&defrule.log, 0, sizeof(defrule.log));
 
704
                defrule.log.connect             = 1;
 
705
                defrule.log.iooperation = 1; /* blocked iooperations. */
 
706
 
 
707
                if (sockscf.option.debug) {
 
708
                        defrule.log.disconnect  = 1;
 
709
                        defrule.log.error                       = 1;
 
710
                }
 
711
 
 
712
                memset(&defrule.state.command, UCHAR_MAX, sizeof(defrule.state.command));
 
713
 
 
714
                defrule.state.methodc = 0;
 
715
 
 
716
                memset(&defrule.state.protocol, UCHAR_MAX,
 
717
                sizeof(defrule.state.protocol));
 
718
 
 
719
                memset(&defrule.state.proxyprotocol, UCHAR_MAX,
 
720
                sizeof(defrule.state.proxyprotocol));
 
721
 
 
722
#if HAVE_LIBWRAP
 
723
                *defrule.libwrap = NUL;
 
724
#endif  /* HAVE_LIBWRAP */
 
725
 
 
726
                init = 1;
 
727
        }
 
728
 
 
729
        if (msgsize > 0)
 
730
                *msg = NUL;
 
731
 
 
732
        /* what rulebase to use.  XXX nicer way to do this. */
 
733
        switch (state->command) {
 
734
                case SOCKS_ACCEPT:
 
735
                        /* only set by negotiate children so must be clientrule. */
 
736
                        rule            = sockscf.crule;
 
737
                        methodv = sockscf.clientmethodv;
 
738
                        methodc = sockscf.clientmethodc;
 
739
                        break;
 
740
 
 
741
                default:
 
742
                        /* everyone else, socksrules. */
 
743
                        rule = sockscf.srule;
 
744
                        methodv = sockscf.methodv;
 
745
                        methodc = sockscf.methodc;
 
746
                        break;
 
747
        }
 
748
 
 
749
        /*
 
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.
 
754
         */
 
755
        for (ostate = *state; rule != NULL; rule = rule->next, *state = ostate) {
 
756
                int i;
 
757
 
 
758
                /* current rule covers desired command? */
 
759
                switch (state->command) {
 
760
                        case SOCKS_BIND:
 
761
                                if (!rule->state.command.bind)
 
762
                                        continue;
 
763
                                break;
 
764
 
 
765
                        case SOCKS_CONNECT:
 
766
                                if (!rule->state.command.connect)
 
767
                                        continue;
 
768
                                break;
 
769
 
 
770
                        case SOCKS_UDPASSOCIATE:
 
771
                                if (!rule->state.command.udpassociate)
 
772
                                        continue;
 
773
                                break;
 
774
 
 
775
                        /* pseudo commands. */
 
776
 
 
777
                        case SOCKS_BINDREPLY:
 
778
                                if (!rule->state.command.bindreply)
 
779
                                        continue;
 
780
                                break;
 
781
 
 
782
                        case SOCKS_UDPREPLY:
 
783
                                if (!rule->state.command.udpreply)
 
784
                                        continue;
 
785
                                break;
 
786
 
 
787
                        /* client-rule commands. */
 
788
                        case SOCKS_ACCEPT:
 
789
                                break;
 
790
 
 
791
                        default:
 
792
                                SERRX(state->command);
 
793
                }
 
794
 
 
795
                /* current rule covers desired protocol? */
 
796
                switch (state->protocol) {
 
797
                        case SOCKS_TCP:
 
798
                                if (!rule->state.protocol.tcp)
 
799
                                        continue;
 
800
                                break;
 
801
 
 
802
                        case SOCKS_UDP:
 
803
                                if (!rule->state.protocol.udp)
 
804
                                        continue;
 
805
                                break;
 
806
 
 
807
                        default:
 
808
                                SERRX(state->protocol);
 
809
                }
 
810
 
 
811
                /* current rule covers desired version? */
 
812
                switch (state->version) {
 
813
                        case SOCKS_V4:
 
814
                                if (!rule->state.proxyprotocol.socks_v4)
 
815
                                        continue;
 
816
                                break;
 
817
 
 
818
                        case SOCKS_V5:
 
819
                                if (!rule->state.proxyprotocol.socks_v5)
 
820
                                        continue;
 
821
                                break;
 
822
 
 
823
                        default:
 
824
                                SERRX(state->version);
 
825
                }
 
826
 
 
827
                /* current rule allows for selected authentication? */
 
828
                if (!methodisset(state->auth.method, rule->state.methodv,
 
829
                rule->state.methodc)) {
 
830
                        size_t methodisok;
 
831
 
 
832
                        /*
 
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.
 
837
                         *
 
838
                         * We therefor look at what methods this rule wants and see
 
839
                         * if can match it with what we have, or get it.
 
840
                         *
 
841
                         * Currently these methods are: rfc931 and pam.
 
842
                         */
 
843
 
 
844
                        for (i = methodisok = 0; i < methodc; ++i) {
 
845
                                if (methodisset(methodv[i], rule->state.methodv,
 
846
                                rule->state.methodc)) {
 
847
                                        switch (methodv[i]) {
 
848
#if HAVE_LIBWRAP
 
849
                                                case AUTHMETHOD_RFC931:
 
850
                                                        strncpy((char *)state->auth.mdata.rfc931.name,
 
851
                                                        eval_user(&libwraprequest),
 
852
                                                        sizeof(state->auth.mdata.rfc931.name) - 1);
 
853
 
 
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;
 
858
 
 
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;
 
864
 
 
865
                                                                /* better safe than sorry. */
 
866
                                                                *state->auth.mdata.rfc931.name = NUL;
 
867
                                                        }
 
868
 
 
869
                                                        if (*state->auth.mdata.rfc931.name != NUL)
 
870
                                                                methodisok = 1;
 
871
                                                        break;
 
872
#endif /* HAVE_LIBWRAP */
 
873
 
 
874
#if HAVE_PAM
 
875
                                                case AUTHMETHOD_PAM:
 
876
                                                        slog(LOG_DEBUG, "%s: trying to find match for pam ...",
 
877
                                                        function);
 
878
 
 
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;
 
884
 
 
885
                                                                        /* similar enough, just copy name/password. */
 
886
 
 
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);
 
891
 
 
892
                                                                        methodisok = 1;
 
893
                                                                        break;
 
894
                                                                }
 
895
 
 
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;
 
900
 
 
901
                                                                        strcpy((char *)state->auth.mdata.pam.name,
 
902
                                                                        (const char *)rfc931.name);
 
903
                                                                        *state->auth.mdata.pam.password = NUL;
 
904
                                                                        methodisok = 1;
 
905
                                                                        break;
 
906
                                                                }
 
907
 
 
908
                                                                case AUTHMETHOD_NONE:
 
909
                                                                        *state->auth.mdata.pam.name             = NUL;
 
910
                                                                        *state->auth.mdata.pam.password = NUL;
 
911
                                                                        methodisok = 1;
 
912
                                                                        break;
 
913
 
 
914
                                                        }
 
915
 
 
916
                                                        strcpy(state->auth.mdata.pam.servicename,
 
917
                                                        rule->pamservicename);
 
918
#endif /* HAVE_PAM */
 
919
                                        }
 
920
 
 
921
                                        if (methodisok) {
 
922
                                                state->auth.method = methodv[i];
 
923
                                                break;
 
924
                                        }
 
925
                                }
 
926
                        }
 
927
 
 
928
                        if (i == methodc)
 
929
                                continue;       /* no usable method found. */
 
930
                }
 
931
 
 
932
 
 
933
                SASSERTX(methodisset(state->auth.method, rule->state.methodv,
 
934
                rule->state.methodc));
 
935
 
 
936
                i = accessmatch(s, &state->auth, peer, local, rule->user, msg, msgsize);
 
937
 
 
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;
 
945
 
 
946
                if (!i)
 
947
                        /*
 
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
 
952
                         * for other methods.
 
953
                         */
 
954
                        continue;
 
955
 
 
956
                /*
 
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
 
964
                 * is triggered.
 
965
                 */
 
966
 
 
967
                if (src != NULL) {
 
968
                        if (!addressmatch(&rule->src, src, state->protocol, 0))
 
969
                                continue;
 
970
                }
 
971
                else
 
972
                        if (rule->verdict == VERDICT_BLOCK)
 
973
                                continue; /* continue scan. */
 
974
 
 
975
                if (dst != NULL) {
 
976
                         if (!addressmatch(&rule->dst, dst, state->protocol, 0))
 
977
                                continue;
 
978
                }
 
979
                else
 
980
                        if (rule->verdict == VERDICT_BLOCK)
 
981
                                continue; /* continue scan. */
 
982
 
 
983
                break;
 
984
        }
 
985
 
 
986
        if (rule == NULL) /* no rules matched; match default rule. */
 
987
                rule = &defrule;
 
988
 
 
989
        *match = *rule;
 
990
 
 
991
        /*
 
992
         * got our rule, now check connection.  Connectioncheck
 
993
         * requires the rule matched so needs to be delayed til here.
 
994
         */
 
995
 
 
996
        if (!connectisok(&libwraprequest, match))
 
997
                match->verdict = VERDICT_BLOCK;
 
998
 
 
999
        /*
 
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.
 
1002
         */
 
1003
        switch (state->command) {
 
1004
                case SOCKS_BIND:
 
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",
 
1008
                                        function);
 
1009
                                        match->verdict = VERDICT_BLOCK;
 
1010
                                }
 
1011
                        break;
 
1012
        }
 
1013
 
 
1014
        return match->verdict == VERDICT_PASS;
 
1015
}
 
1016
 
 
1017
const char *
 
1018
authinfo(auth, info, infolen)
 
1019
        const struct authmethod_t *auth;
 
1020
        char *info;
 
1021
        size_t infolen;
 
1022
{
 
1023
        const char *authname, *methodname;
 
1024
 
 
1025
        if (auth != NULL) {
 
1026
                methodname = method2string(auth->method);
 
1027
 
 
1028
                switch (auth->method) {
 
1029
                        case AUTHMETHOD_NONE:
 
1030
                        case AUTHMETHOD_NOACCEPT: /* closing connection next presumably. */
 
1031
                                authname = methodname = NULL;
 
1032
                                break;
 
1033
 
 
1034
                        case AUTHMETHOD_UNAME:
 
1035
                                authname = (const char *)auth->mdata.uname.name;
 
1036
                                break;
 
1037
 
 
1038
                        case AUTHMETHOD_RFC931:
 
1039
                                authname = (const char *)auth->mdata.rfc931.name;
 
1040
                                break;
 
1041
 
 
1042
                        case AUTHMETHOD_PAM:
 
1043
                                authname = (const char *)auth->mdata.pam.name;
 
1044
                                break;
 
1045
 
 
1046
                        default:
 
1047
                                SERRX(auth->method);
 
1048
                }
 
1049
        }
 
1050
        else
 
1051
                authname = methodname = NULL;
 
1052
 
 
1053
        if (authname == NULL || *authname == NUL)
 
1054
                *info = NUL;
 
1055
        else
 
1056
                snprintfn(info, infolen, "%s%%%s@", methodname, authname);
 
1057
 
 
1058
        return info;
 
1059
}
 
1060
 
 
1061
int
 
1062
addressisbindable(addr)
 
1063
        const struct ruleaddress_t *addr;
 
1064
{
 
1065
        const char *function = "addressisbindable()";
 
1066
        struct sockaddr saddr;
 
1067
        char saddrs[MAX(MAXSOCKSHOSTSTRING, MAXSOCKADDRSTRING)];
 
1068
        int s;
 
1069
 
 
1070
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
 
1071
                swarn("%s: socket(SOCK_STREAM)", function);
 
1072
                return 0;
 
1073
        }
 
1074
 
 
1075
        switch (addr->atype) {
 
1076
                case SOCKS_ADDR_IPV4: {
 
1077
                        struct sockshost_t host;
 
1078
 
 
1079
                        sockshost2sockaddr(ruleaddress2sockshost(addr, &host, SOCKS_TCP),
 
1080
                        &saddr);
 
1081
 
 
1082
                        if (sockd_bind(s, &saddr, 0) != 0) {
 
1083
                                swarn("%s: can't bind address: %s",
 
1084
                                function, sockaddr2string(&saddr, saddrs, sizeof(saddrs)));
 
1085
                                close(s);
 
1086
                                return 0;
 
1087
                        }
 
1088
                        break;
 
1089
                }
 
1090
 
 
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);
 
1094
                                close(s);
 
1095
                                return 0;
 
1096
                        }
 
1097
 
 
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)),
 
1101
                                addr->addr.ifname);
 
1102
                                close(s);
 
1103
                                return 0;
 
1104
                        }
 
1105
                        break;
 
1106
 
 
1107
                default:
 
1108
                        SERRX(addr->atype);
 
1109
        }
 
1110
 
 
1111
        close(s);
 
1112
        return 1;
 
1113
}
 
1114
 
 
1115
 
 
1116
static struct rule_t *
 
1117
addrule(newrule, rulebase, client)
 
1118
        const struct rule_t *newrule;
 
1119
        struct rule_t **rulebase;
 
1120
        int client;
 
1121
{
 
1122
        static const struct serverstate_t state;
 
1123
        const char *function = "addrule()";
 
1124
        struct rule_t *rule;
 
1125
        size_t i;
 
1126
        int *methodv;
 
1127
        size_t methodc;
 
1128
 
 
1129
        if (client) {
 
1130
                methodv = sockscf.clientmethodv;
 
1131
                methodc = sockscf.clientmethodc;
 
1132
        }
 
1133
        else {
 
1134
                methodv = sockscf.methodv;
 
1135
                methodc = sockscf.methodc;
 
1136
        }
 
1137
 
 
1138
        if ((rule = malloc(sizeof(*rule))) == NULL)
 
1139
                serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);
 
1140
        *rule = *newrule;
 
1141
 
 
1142
        /* try to set values not set to a sensible default. */
 
1143
 
 
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;
 
1149
        }
 
1150
        /* else; don't touch logging, no logging is ok. */
 
1151
 
 
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));
 
1155
 
 
1156
        /*
 
1157
         * If no method set, set all set from global methodline that make sense.
 
1158
         */
 
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)
 
1164
                                                break;
 
1165
                                        /* else; */ /* FALLTHROUGH */
 
1166
 
 
1167
                                default:
 
1168
                                        rule->state.methodv[rule->state.methodc++] = methodv[i];
 
1169
                        }
 
1170
        }
 
1171
 
 
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]));
 
1177
 
 
1178
        /* if no protocol set, set all. */
 
1179
        if (memcmp(&state.protocol, &rule->state.protocol, sizeof(state.protocol))
 
1180
        == 0)
 
1181
                memset(&rule->state.protocol, UCHAR_MAX, sizeof(rule->state.protocol));
 
1182
 
 
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;
 
1188
        }
 
1189
 
 
1190
        if (*rulebase == NULL) {
 
1191
                *rulebase = rule;
 
1192
                (*rulebase)->number = 1;
 
1193
        }
 
1194
        else {
 
1195
                struct rule_t *lastrule;
 
1196
 
 
1197
                /* append this rule to the end of our list. */
 
1198
 
 
1199
                lastrule = *rulebase;
 
1200
                while (lastrule->next != NULL)
 
1201
                        lastrule = lastrule->next;
 
1202
 
 
1203
                rule->number = lastrule->number + 1;
 
1204
                lastrule->next = rule;
 
1205
        }
 
1206
 
 
1207
        rule->next = NULL;
 
1208
 
 
1209
        return rule;
 
1210
}
 
1211
 
 
1212
static void
 
1213
checkrule(rule)
 
1214
        const struct rule_t *rule;
 
1215
{
 
1216
        size_t i;
 
1217
        struct ruleaddress_t ruleaddr;
 
1218
 
 
1219
        if (rule->state.methodc == 0)
 
1220
                yywarn("rule allows no methods");
 
1221
 
 
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:
 
1229
                                        break;
 
1230
 
 
1231
                                default:
 
1232
                                        yyerror("method \"%s\" can not provide usernames",
 
1233
                                        method2string(rule->state.methodv[i]));
 
1234
                        }
 
1235
        }
 
1236
 
 
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");
 
1240
 
 
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];
 
1246
 
 
1247
                yyerror("%s is not bindable",
 
1248
                ruleaddress2string(&ruleaddr, addr, sizeof(addr)));
 
1249
        }
 
1250
 
 
1251
        if (rule->rdr_to.atype == SOCKS_ADDR_IFNAME)
 
1252
                yyerror("redirect to an interface (%s) is not supported "
 
1253
                "(or meaningful?)",
 
1254
                rule->rdr_to.addr.ifname);
 
1255
 
 
1256
#if HAVE_PAM
 
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");
 
1261
                else
 
1262
                        if (strcmp(rule->pamservicename, DEFAULT_PAMSERVICENAME) != 0)
 
1263
                                sockscf.state.unfixedpamdata = 1; /* pamservicename varies. */
 
1264
#endif /* HAVE_PAM */
 
1265
}
 
1266
 
 
1267
static void
 
1268
showuser(user)
 
1269
        const struct linkedname_t *user;
 
1270
{
 
1271
        char buf[10240];
 
1272
 
 
1273
        users2string(user, buf, sizeof(buf));
 
1274
        if (strlen(buf) > 0)
 
1275
                slog(LOG_INFO, "user: %s", buf);
 
1276
}
 
1277
 
 
1278
static void
 
1279
showlog(log)
 
1280
        const struct log_t *log;
 
1281
{
 
1282
        char buf[1024];
 
1283
 
 
1284
        slog(LOG_INFO, "log: %s", logs2string(log, buf, sizeof(buf)));
 
1285
}
 
1286
 
 
1287
 
 
1288
#if HAVE_LIBWRAP
 
1289
static void
 
1290
libwrapinit(s, request)
 
1291
        int s;
 
1292
        struct request_info *request;
 
1293
{
 
1294
 
 
1295
        request_init(request, RQ_FILE, s, RQ_DAEMON, __progname, 0);
 
1296
        fromhost(request);
 
1297
}
 
1298
#endif /* HAVE_LIBWRAP */
 
1299
 
 
1300
static int
 
1301
connectisok(request, rule)
 
1302
#if HAVE_LIBWRAP
 
1303
        struct request_info *request;
 
1304
#else
 
1305
        void *request;
 
1306
#endif
 
1307
        const struct rule_t *rule;
 
1308
{
 
1309
 
 
1310
#if HAVE_LIBWRAP
 
1311
 
 
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];
 
1318
                uid_t euid;
 
1319
 
 
1320
                socks_seteuid(&euid, sockscf.uid.libwrap);
 
1321
 
 
1322
                /* libwrap modifies the passed buffer. */
 
1323
                SASSERTX(strlen(rule->libwrap) < sizeof(libwrap));
 
1324
                strcpy(libwrap, rule->libwrap);
 
1325
 
 
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. */
 
1331
                }
 
1332
                process_options(libwrap, request);
 
1333
 
 
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);
 
1339
                                return 0;
 
1340
                }
 
1341
 
 
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);
 
1347
                                return 0;
 
1348
                }
 
1349
 
 
1350
                socks_reseteuid(sockscf.uid.libwrap, euid);
 
1351
        }
 
1352
 
 
1353
#else   /* !HAVE_LIBWRAP */
 
1354
 
 
1355
#endif  /* !HAVE_LIBWRAP */
 
1356
 
 
1357
        return 1;
 
1358
}