📄 serverconfig.c
字号:
/* * Copyright (c) 1997, 1998, 1999 * Inferno Nettverk A/S, Norway. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following * disclaimer must appear in all copies of the software, derivative works * or modified versions, and any portions thereof, aswell as in all * supporting documentation. * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by * Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * * Software Distribution Coordinator or sdc@inet.no * Inferno Nettverk A/S * Oslo Research Park * Gaustadal閑n 21 * N-0349 Oslo * Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"#include "config_parse.h"static const char rcsid[] ="$Id: serverconfig.c,v 1.92 1999/12/22 09:29:25 karls Exp $";__BEGIN_DECLSstatic voidshowuser __P((const struct linkedname_t *user));/* * shows usernames in "user". */static voidshowlog __P((const struct log_t *log));/* * shows what type of logging is specified in "log". */#if HAVE_LIBWRAP extern jmp_buf tcpd_buf;static voidlibwrapinit __P((int s, struct request_info *request));/* * Initializes "request" for later usage via libwrap. */static intconnectisok __P((struct request_info *request, const struct rule_t *rule, struct connectionstate_t *state));#else /* !HAVE_LIBWRAP */static intconnectisok __P((void *request, const struct rule_t *rule, struct connectionstate_t *state));#endif /* !HAVE_LIBWRAP *//* * Checks the connection on "s". * "rule" is the rule that matched the connection and "state" is the current * state. * This function should be called after each rulecheck for a new * connection/packet. * * Returns: * If connection is acceptable: true * If connection is not acceptable: false */static struct rule_t *addrule __P((const struct rule_t *newrule, struct rule_t **rulebase));/* * Appends a copy of "newrule" to "rulebase". * Returns a pointer to the added rule (not "newrule"). */static voidcheckrule __P((const struct rule_t *rule));/* * Check that the rule "rule" makes sense. */__END_DECLSstruct config_t config;const int configtype = CONFIGTYPE_SERVER;#if HAVE_LIBWRAPint allow_severity, deny_severity;#endif /* HAVE_LIBWRAP */struct rule_t *addclientrule(newrule) const struct rule_t *newrule;{ struct rule_t *rule; rule = addrule(newrule, &config.crule); /* * there are a few things that need to be changed versus the generic * init done by addrule(). */ if (rule->user != NULL) { /* * this is a clientrule so strip away any methods that * can not provide a username without socks negotiation. */ int i; for (i = 0; i < rule->state.methodc; ++i) switch (rule->state.methodv[i]) { case AUTHMETHOD_RFC931: break; default: rule->state.methodv[i--] = rule->state.methodv[--rule->state.methodc]; } } checkrule(rule); /* LINTED cast discards 'const' from pointer target type */ return (struct rule_t *)rule;}struct rule_t *addsocksrule(newrule) const struct rule_t *newrule;{ struct rule_t *rule; rule = addrule(newrule, &config.srule); if (rule->user == NULL) { /* * For each method taking a username, default to * allowing everybody that's in the passwordfile. */ int i; for (i = 0; i < rule->state.methodc; ++i) switch (rule->state.methodv[i]) { case AUTHMETHOD_UNAME: case AUTHMETHOD_RFC931: if (adduser(&rule->user, method2string(rule->state.methodv[i])) == NULL) serrx(EXIT_FAILURE, NOMEM); break; } } checkrule(rule); /* LINTED cast discards 'const' from pointer target type */ return (struct rule_t *)rule;}struct linkedname_t *adduser(ruleuser, name) struct linkedname_t **ruleuser; const char *name;{ struct linkedname_t *user, *last; for (user = *ruleuser, last = NULL; user != NULL; user = user->next) last = user; if ((user = (struct linkedname_t *)malloc(sizeof(*user))) == NULL) return NULL; if ((user->name = strdup(name)) == NULL) return NULL; user->next = NULL; if (*ruleuser == NULL) *ruleuser = user; else last->next = user; return *ruleuser;}voidshowrule(rule) const struct rule_t *rule;{ char addr[MAXRULEADDRSTRING]; slog(LOG_INFO, "socks-rule #%d", rule->number); slog(LOG_INFO, "verdict: %s", rule->verdict == VERDICT_PASS ? VERDICT_PASSs : VERDICT_BLOCKs); slog(LOG_INFO, "src: %s", ruleaddress2string(&rule->src, addr, sizeof(addr))); slog(LOG_INFO, "dst: %s", ruleaddress2string(&rule->dst, addr, sizeof(addr))); showuser(rule->user); showstate(&rule->state); showlog(&rule->log);#if HAVE_LIBWRAP if (*rule->libwrap != NUL) slog(LOG_INFO, "libwrap: %s", rule->libwrap);#endif /* HAVE_LIBWRAP */}voidshowclient(rule) const struct rule_t *rule;{ char addr[MAXRULEADDRSTRING]; slog(LOG_INFO, "client-rule #%d", rule->number); slog(LOG_INFO, "verdict: %s", rule->verdict == VERDICT_PASS ? VERDICT_PASSs : VERDICT_BLOCKs); slog(LOG_INFO, "from: %s", ruleaddress2string(&rule->src, addr, sizeof(addr))); slog(LOG_INFO, "to: %s", ruleaddress2string(&rule->dst, addr, sizeof(addr))); showuser(rule->user); showlog(&rule->log);#if HAVE_LIBWRAP if (*rule->libwrap != NUL) slog(LOG_INFO, "libwrap: %s", rule->libwrap);#endif /* HAVE_LIBWRAP */}voidshowconfig(config) const struct config_t *config;{ int i; char address[MAXSOCKADDRSTRING], buf[1024]; size_t bufused; slog(LOG_INFO, "internal addresses (%d):", config->internalc); for (i = 0; i < config->internalc; ++i) slog(LOG_INFO, "%s", /* LINTED pointer casts may be troublesome */ sockaddr2string((struct sockaddr *)&config->internalv[i], address, sizeof(address))); slog(LOG_INFO, "external addresses (%d):", config->externalc); for (i = 0; i < config->externalc; ++i) slog(LOG_INFO, "%s", /* LINTED pointer casts may be troublesome */ sockaddr2string((struct sockaddr *)&config->externalv[i], address, sizeof(address))); bufused = snprintf(buf, sizeof(buf), "compatibility options: "); if (config->compat.reuseaddr) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "reuseaddr, "); if (config->compat.sameport) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "sameport, "); slog(LOG_INFO, buf); bufused = snprintf(buf, sizeof(buf), "extensions enabled: "); if (config->extension.bind) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "bind, "); slog(LOG_INFO, buf); bufused = snprintf(buf, sizeof(buf), "logoutput goes to: "); if (config->log.type & LOGTYPE_SYSLOG) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "syslog, "); if (config->log.type & LOGTYPE_FILE) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "files (%d)", config->log.fpc); slog(LOG_INFO, buf); slog(LOG_INFO, "debug level: %d", config->option.debug); bufused = snprintf(buf, sizeof(buf), "resolveprotocol: "); switch (config->resolveprotocol) { case RESOLVEPROTOCOL_TCP: bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, PROTOCOL_TCPs); break; case RESOLVEPROTOCOL_UDP: bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, PROTOCOL_UDPs); break; case RESOLVEPROTOCOL_FAKE: bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "fake"); break; default: SERRX(config->resolveprotocol); } slog(LOG_INFO, buf); slog(LOG_INFO, "address/host mismatch tolerated: %s", config->srchost.nomismatch ? "no" : "yes"); slog(LOG_INFO, "unresolvable addresses tolerated: %s", config->srchost.nounknown ? "no" : "yes"); slog(LOG_INFO, "negotiate timeout: %lds", (long)config->timeout.negotiate); slog(LOG_INFO, "I/O timeout: %lds", (long)config->timeout.io); slog(LOG_INFO, "euid: %d", config->state.euid); slog(LOG_INFO, "userid.privileged: %lu", (unsigned long)config->uid.privileged); slog(LOG_INFO, "userid.unprivileged: %lu", (unsigned long)config->uid.unprivileged); slog(LOG_INFO, "userid.libwrap: %lu", (unsigned long)config->uid.libwrap); bufused = snprintf(buf, sizeof(buf), "method(s): "); for (i = 0; i < config->methodc; ++i) bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, "%s%s", i > 0 ? ", " : "", method2string(config->methodv[i])); slog(LOG_INFO, buf); if (config->option.debug) { struct rule_t *rule; int count; for (count = 0, rule = config->crule; rule != NULL; rule = rule->next) ++count; slog(LOG_INFO, "client-rules (%d): ", count); for (rule = config->crule; rule != NULL; rule = rule->next) showclient(rule); for (count = 0, rule = config->srule; rule != NULL; rule = rule->next) ++count; slog(LOG_INFO, "socks-rules (%d): ", count); for (rule = config->srule; rule != NULL; rule = rule->next) showrule(rule); }}voidresetconfig(void){ struct rule_t *rule; /* * internal; don't touch, only settable at start. */ /* external addresses can be changed. */ free(config.externalv); config.externalv = NULL; config.externalc = 0; /* delete all old rules */ rule = config.srule; while (rule != NULL) { struct rule_t *next = rule->next; struct linkedname_t *user, *nextuser; user = rule->user; while (user != NULL) { nextuser = user->next; free(user); user = nextuser; } free(rule); rule = next; } config.srule = NULL; /* clientrules too. */ rule = config.crule; while (rule != NULL) { struct rule_t *next = rule->next; struct linkedname_t *user, *nextuser; user = rule->user; while (user != NULL) { nextuser = user->next; free(user); user = nextuser; } free(rule); rule = next; } config.crule = NULL; /* route; currently not supported in server. */ /* compat, read from configfile. */ bzero(&config.compat, sizeof(config.compat)); /* extensions, read from configfile. */ bzero(&config.extension, sizeof(config.extension)); /* log; only settable at start. */ /* option; only settable at commandline. */ /* resolveprotocol, read from configfile. */ bzero(&config.resolveprotocol, sizeof(config.resolveprotocol)); /* srchost, read from configfile. */ bzero(&config.srchost, sizeof(config.srchost)); /* stat: keep it. */ /* state; keep it. */ /* methods, read from configfile. */ bzero(config.methodv, sizeof(config.methodv)); config.methodc = 0; /* timeout, read from configfile. */ bzero(&config.timeout, sizeof(config.timeout)); /* uid, read from configfile. */ bzero(&config.uid, sizeof(config.uid)); /* * initialize misc options to sensible default. */ config.resolveprotocol = RESOLVEPROTOCOL_UDP; config.option.keepalive = 1; config.timeout.negotiate = SOCKD_NEGOTIATETIMEOUT; config.timeout.io = SOCKD_IOTIMEOUT;}voidiolog(rule, state, operation, src, dst, data, count) struct rule_t *rule; const struct connectionstate_t *state; int operation; const struct sockshost_t *src, *dst; const char *data; size_t count;{ char srcstring[MAXSOCKSHOSTSTRING + MAXNAMELEN + sizeof("@") - 1]; char dststring[MAXSOCKSHOSTSTRING]; const char *name; int p; name = NULL; switch (state->auth.method) { case AUTHMETHOD_NONE: case AUTHMETHOD_NOACCEPT: /* closing connection. */ /* * doesn't take any space so it's possible it has a name, even * if method doesn't indicate it. */ name = state->auth.mdata.rfc931.name; break; case AUTHMETHOD_UNAME: name = state->auth.mdata.uname.name; break; case AUTHMETHOD_RFC931: name = state->auth.mdata.rfc931.name; break; default: SERRX(state->auth.method); } if (name != NULL && *name != NUL) p = snprintf(srcstring, sizeof(srcstring), "%s@", name); else p = 0; sockshost2string(src, &srcstring[p], sizeof(srcstring) - p); sockshost2string(dst, dststring, sizeof(dststring)); /* XXX should probably include authinfo somewhere here too. */ switch (operation) { case OPERATION_ACCEPT: case OPERATION_DISCONNECT: case OPERATION_CONNECT: if (rule->log.connect || rule->log.disconnect) slog(LOG_INFO, "%s(%d): %s: %s -> %s", rule->verdict == VERDICT_PASS ? VERDICT_PASSs : VERDICT_BLOCKs, rule->number, command2string(state->command), srcstring, dststring); break; case OPERATION_ABORT: if (rule->log.disconnect || rule->log.error) slog(LOG_INFO, "%s(%d): %s abort: %s -> %s: %s", rule->verdict == VERDICT_PASS ? VERDICT_PASSs : VERDICT_BLOCKs, rule->number, command2string(state->command), srcstring, dststring, data == NULL ? strerror(errno) : data); break; case OPERATION_ERROR: if (rule->log.error) slog(LOG_INFO, "%s(%d): %s error: %s -> %s: %s", rule->verdict == VERDICT_PASS ? VERDICT_PASSs : VERDICT_BLOCKs, rule->number, protocol2string(state->protocol), srcstring, dststring, data == NULL ? strerror(errno) : data); break; case OPERATION_IO: if (rule->log.data) { char *visdata; SASSERTX(data != NULL); slog(LOG_INFO, "%s(%d): %s: %s -> %s (%lu): %s", rule->verdict == VERDICT_BLOCK ? VERDICT_BLOCKs : VERDICT_PASSs, rule->number, protocol2string(state->protocol), srcstring, dststring, (unsigned long)count,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -