validate.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:37k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
- /* */
- /* The redistribution, use and modification in source or binary forms of */
- /* this software is subject to the conditions set forth in the copyright */
- /* document ("Copyright") included with this distribution. */
- /*
- * $Id: validate.c,v 1.74.2.1.2.6 1998/09/22 20:34:39 wlu Exp $
- */
- /* This file contains all of the stuff associated with parsing the config */
- /* file, except for some utility routines which appear in valutil.c. The */
- /* routines for checking the parsed config file appear in check.c. */
- #include "socks5p.h"
- #include "threads.h"
- #include "daemon.h"
- #include "confutil.h"
- #include "validate.h"
- #include "protocol.h"
- #include "msgids.h"
- #include "info.h"
- #include "log.h"
- #define INVALID_TYPE (char)-1 /* some kind of config error... */
- IFTHREADED(static MUTEX_T confid_mutex = MUTEX_INITIALIZER;)
- static struct intfc *intfcs = NULL;
- static int ifcnt = 0;
- struct sroute {
- char type;
- int calloced;
- struct in_addr ifaddr;
- struct intfc *ifp;
- };
- struct authtuple {
- int realline;
- struct host source;
- struct port sport;
- list *authlist;
- u_char banned;
- };
- typedef struct authtuple AuthTuple;
- static AuthTuple *authList = NULL; /* An array of auth list entries */
- static int nalines = 0, na = 0; /* how many auth lines, and current index */
- /* A configuration tuple, used in the access control portion of the config */
- /* file...It tells us the permission as well as matching information... */
- struct conftuple {
- int realline;
- char permit;
- list *command;
- list *userlist;
- list *authlist;
- struct host source, dest;
- struct port sport, dport;
- };
- typedef struct conftuple ConfTuple;
- static ConfTuple *accessList = NULL; /* An array of access list entries */
- static int nplines = 0, np = 0; /* how many access lines, & index */
- /* A routing tuple...used in the routing portion of the config file to tell */
- /* the server how it should be connecting (and being connected) to hosts... */
- struct routetuple {
- int realline;
- struct host source;
- struct port sport;
- struct sroute nexthop;
- };
- typedef struct routetuple RouteTuple;
- static RouteTuple *routeList = NULL; /* An array of route list entries */
- static int nrlines = 0, nr = 0; /* how many route lines, & index */
- /* A proxy tuple...used in the proxy portion of the config file to tell the */
- /* server how it should get to a destination (what the next step is...) */
- struct proxytuple {
- int realline;
- struct host source;
- struct port sport;
- u_char nextver;
- S5NetAddr nextaddr[S5_SERVER_NUM];
- int nnextaddr;
- };
- typedef struct proxytuple ProxyTuple;
- static ProxyTuple *proxyList = NULL; /* An array of socks list entries */
- static int nslines = 0, ns = 0; /* how many proxy lines & index */
- /* A filter tuple, used in the filter portion of the config file...It tells */
- /* us the what filter to use for a given connection... */
- struct filtertuple {
- int realline;
- char name[S5_NAME_SIZE];
- list *command;
- list *userlist;
- list *authlist;
- struct host source, dest;
- struct port sport, dport;
- };
- typedef struct filtertuple FilterTuple;
- static FilterTuple *filterList = NULL; /* An array of socks list entries */
- static int nflines = 0, nf = 0; /* how many filter lines & index */
- static char **varList = NULL; /* A list of variables allocated */
- static int nvlines = 0, nv = 0; /* how many variable lines and cur index */
- extern void AuthsHandler P((void **, int, int, char *)); /* Auth line */
- extern void PermsHandler P((void **, int, int, char *)); /* permission line */
- extern void HowtoHandler P((void **, int, int, char *)); /* proxy line... */
- extern void RouteHandler P((void **, int, int, char *)); /* route line... */
- extern void EvarsHandler P((void **, int, int, char *)); /* evar line.. */
- extern void FilterHandler P((void **, int, int, char *)); /* filter line... */
- confid confids[] = {
- { "permit", "p", PermsHandler, (void **)&accessList, &nplines, &np, sizeof(ConfTuple) },
- #define PERMIT_IND 0 /* An indentifier that this line is "permit" */
- { "deny", "d", PermsHandler, (void **)&accessList, &nplines, &np, 0 },
- #define DENY_IND 1 /* An indentifier that this line is "deny" */
- { "route", "r", RouteHandler, (void **)&routeList, &nrlines, &nr, sizeof(RouteTuple) },
- #define ROUTE_IND 2 /* An indentifier that this line is "route" */
- { "interface", "i", RouteHandler, (void **)&routeList, &nrlines, &nr, 0 },
- #define INTFC_IND 3 /* An indentifier that this line is "interface" */
- { "socks4", "4", HowtoHandler, (void **)&proxyList, &nslines, &ns, 0 },
- #define SOCKS4_IND 4 /* An indentifier that this line is "socks" */
- { "socks5", "5", HowtoHandler, (void **)&proxyList, &nslines, &ns, sizeof(ProxyTuple) },
- #define SOCKS5_IND 5 /* An indentifier that this line is "socks5" */
- { "noproxy", "n", HowtoHandler, (void **)&proxyList, &nslines, &ns, 0 },
- #define DIRECT_IND 6 /* An indentifier that this line is "direct" */
- { "auth", "a", AuthsHandler, (void **)&authList, &nalines, &na, sizeof(AuthTuple) },
- #define AUTH_IND 7 /* An indentifier that this line is "auth" */
- { "ban", "b", AuthsHandler, (void **)&authList, &nalines, &na, 0 },
- #define BAN_IND 8 /* An indentifier that this line is "ban" */
- { "set", "s", EvarsHandler, (void **)&varList, &nvlines, &nv, sizeof(char *) },
- #define SET_IND 9 /* An indentifier that this line is "set" */
- { "filter", "f", FilterHandler,(void **)&filterList, &nflines, &nf, sizeof(FilterTuple) },
- #define FILTER_IND 10 /* An indentifier that this line is "filter" */
- };
- #define NCONFIDS (sizeof(confids)/sizeof(struct confid))
- /* Look at the buffer that ptr points to, and read either a net address of a */
- /* valid interface or the name (e.g. ef0, ef1, le0) of a valid int address. */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* val -- a ptr to the address we are looking up...(out) */
- static int lsGetHostOrIntfc(char **ptr, struct sroute *val) {
- struct in_addr guess;
- char *tmp, tc;
- int i, j;
- /* XXX ipv6 support here may get messy... */
- memset((char *)val, 0, sizeof(struct sroute));
- val->type = INVALID_TYPE;
- SKIPSPACE(*ptr);
- tmp = *ptr;
- SKIPNONSPACE(tmp);
- tc = *tmp; *tmp = ' ';
- if ((guess.s_addr = inet_addr(*ptr)) == INVALIDADDR) {
- val->type = NAME;
- val->ifp = NULL;
- for (i = 0; i < ifcnt; i++) {
- if (strcmp(*ptr, intfcs[i].name)) continue;
- val->ifp = &intfcs[i];
- break;
- }
- if (val->ifp == NULL && (val->ifp = (struct intfc *)calloc(1, sizeof(struct intfc)))) {
- strncpy(val->ifp->name, *ptr, 16);
- val->ifp->name[15] = ' ';
- val->calloced = 1;
- }
- } else {
- val->type = IN_ADDR;
- val->ifaddr.s_addr = guess.s_addr;
- val->ifp = NULL;
- for (i = 0; i < ifcnt; i++) {
- for (j = 0; j < intfcs[i].addrcnt; j++) {
- if (intfcs[i].addrlist[j].ip.s_addr == guess.s_addr) break;
- }
- if (j < intfcs[i].addrcnt) {
- val->ifp = &intfcs[i];
- break;
- }
- }
- }
- *(*ptr = tmp) = tc;
- return (val->type == INVALID_TYPE)?-1:0;
- }
- /* myunsetenv goes through and finds a variable=value pair which is the same */
- /* as (char *)n. Once it finds it, it switches it with the last variable in */
- /* the environment, and returns... */
- /* */
- /* Arguments: n -- the name=value pair we are looking for (just name) */
- /* */
- /* Globals affected: environ -- no longer contians n. */
- static void myunsetenv(void *n) {
- #ifdef HAVE_UNSETENV
- unsetenv((char *)n);
- free(n);
- #else
- char *name = (char *)n, **tmp, **end;
- extern char **environ;
- for (tmp = environ; *tmp; tmp++)
- if (!strncmp(name, *tmp, strlen(name))) break; /* find a match... */
- if (!*tmp) return; /* no match, so give up... */
- for (end = tmp; *(end+1); end++); /* find last set variable... */
- *tmp = *end; /* switch with the last set var... */
- *end = NULL; /* zero out the last set var... */
- free(name);
- #endif
- }
- #ifndef HAVE_SETENV
- static int myputenv(char *name) {
- #ifdef HAVE_PUTENV
- return putenv(name);
- #else
- char **tmp, *end = strchr(name, '='), c;
- extern char **environ;
- static int done;
- int nenv;
- if (end == NULL) return 0;
- /* Find a match or count the number of variables in the environment... */
- for (nenv = 0, tmp = environ; *tmp; tmp++, nenv++) {
- if (strncmp(name, *tmp, end-name)) continue;
- if ((*tmp)[end - name] != '=') continue;
- *tmp = name;
- return 1;
- }
- if (!done) {
- if ((tmp = (char **)malloc((nenv + 2) * sizeof(char *))) == NULL) {
- return 0;
- }
- memcpy(environ, tmp, nenv+1 * sizeof(char *));
- done = 1;
- } else {
- if ((tmp = (char **)realloc(environ, (nenv + 2) * sizeof(char *))) == NULL) {
- return 0;
- }
- }
- tmp[nenv+1] = name;
- tmp[nenv+2] = NULL;
- environ = tmp;
- return 1;
- #endif
- }
- #endif
- /* A function that clears up a given EntryList, for reading or rereading */
- /* the configuration file. It deallocates any memory used in allocating */
- /* the list to begin with, and memset's the array of entries to be 0... */
- /* */
- /* Arguments: index -- which index in the confids array to clear up... */
- static void ClearEntryList(confid *confids, int nconfids) {
- int i;
- #define CLEANUPIND(ind) do { if(*confids[(ind)].array) free(*confids[(ind)].array); *confids[(ind)].array = NULL, *confids[(ind)].number = 0; *confids[(ind)].cnum = 0; } while (0);
- for (i = 0; i < *confids[AUTH_IND].number; i++) {
- lsDeleteLinkedList(&((AuthTuple *)*confids[AUTH_IND].array)[i].authlist);
- }
- for (i = 0; i < *confids[ROUTE_IND].number; i++) {
- if (((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.calloced)
- free(((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.ifp);
- }
- for (i = 0; i < *confids[PERMIT_IND].number; i++) {
- lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].command);
- lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].userlist);
- lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].authlist);
- }
- for (i = 0; i < *confids[SET_IND].number; i++) {
- if (((char **)*confids[SET_IND].array)[i]) {
- MUTEX_LOCK(env_mutex);
- myunsetenv(((char **)*confids[SET_IND].array)[i]);
- MUTEX_UNLOCK(env_mutex);
- }
- }
- CLEANUPIND(AUTH_IND);
- CLEANUPIND(PERMIT_IND);
- CLEANUPIND(SOCKS5_IND);
- CLEANUPIND(ROUTE_IND);
- CLEANUPIND(SET_IND);
- }
- static void badline(int ln, char *msg) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, MSGID_SERVER_CONF_BADLINE, "Conf: Bad line (line number %d) in configuration file: %s", ln, msg);
- }
- /* Examine the current line for an entry setting an environment variable... */
- /* */
- /* Arguments: indx -- index into the array we are dealing with...(in) */
- /* i -- index of the array we came from...(in) */
- /* tmp -- postion in the buffer...(in) */
- void EvarsHandler(void **array, int indx, int i, char *ptr) {
- /* set up the "environment variables", only from file... */
- char *tmp, *end1, *new, **vlist = (*(char ***)array), buf[1024];
- int len;
- if (indx >= nvlines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough environment variable lines allocated");
- return;
- }
- SKIPNONSPACE(ptr);
- SKIPSPACE(ptr);
- if ((end1 = strstr(ptr, "n"))) len = MIN(sizeof(buf)-1, end1-ptr);
- else len = MIN(sizeof(buf)-1, strlen(ptr));
- memset(buf, 0, sizeof(buf));
- strncpy(buf, ptr, len);
- buf[len] = ' ';
- for (tmp = buf ; !isspace(*tmp) && *tmp != ' '; tmp++)
- if (islower(*tmp)) *tmp = toupper(*tmp);
- end1 = tmp;
- SKIPSPACE(tmp);
- #ifndef HAVE_SETENV
- /* mush "variable value" into "variable=value", and find the end */
- if (end1 != tmp) for (*end1++ = '='; !isspace(*tmp) && *tmp != ' '; tmp++, end1++) *end1 = *tmp;
- else *end1++ = '=';
- *end1 = ' ';
- #endif
- new = strdup(buf);
- MUTEX_LOCK(env_mutex);
- #ifdef HAVE_SETENV
- new[end1 - buf] = ' ';
- setenv(new, new + (tmp-buf), 1);
- #else
- myputenv(new); /* replace it in actual environ */
- #endif
- MUTEX_UNLOCK(env_mutex);
- vlist[indx] = new; /* put it in varList for future frees... */
- }
- /* Examine the current line for an entry setting a filter to use... */
- /* */
- /* Arguments: indx -- index into the array we are dealing with...(in) */
- /* i -- index of the array we came from...(in) */
- /* tmp -- postion in the buffer...(in) */
- void FilterHandler(void **array, int indx, int i, char *tmp) {
- FilterTuple *entry = &(*(FilterTuple **)array)[indx];
- char *start;
- if (indx >= nflines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough filter entries allocated");
- return;
- }
- SKIPNONSPACE(tmp);
- entry->realline = lsLineNo;
- SKIPSPACE(tmp);
- start = tmp;
- SKIPNONSPACE(tmp);
- strncpy(entry->name, start, MIN(tmp-start, S5_NAME_SIZE-1));
- entry->name[MIN(tmp-start, S5_NAME_SIZE-1)] = ' ';
- if (lsGetAuthMethods (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
- if (lsGetPermCommand (&tmp, &entry->command) < 0) badline(entry->realline, "command");
- if (lsGetHostAndMask (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
- if (lsGetHostAndMask (&tmp, &entry->dest) < 0) badline(entry->realline, "destination host");
- if (lsGetPortOrService (&tmp, &entry->sport) < 0) badline(entry->realline, "source port");
- if (lsGetPortOrService (&tmp, &entry->dport) < 0) badline(entry->realline, "destination port");
- if (lsGetPermUsers (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
- }
- /* Examine the current line for an entry setting a route to use... */
- /* */
- /* Arguments: indx -- index into the array we are dealing with...(in) */
- /* i -- index of the array we came from...(in) */
- /* tmp -- postion in the buffer...(in) */
- void RouteHandler(void **array, int indx, int i, char *tmp) {
- RouteTuple *entry = &(*(RouteTuple **)array)[indx];
- if (indx >= nrlines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough route entries allocated");
- return;
- }
- SKIPNONSPACE(tmp);
- entry->realline = lsLineNo;
- if (lsGetHostAndMask (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
- if (lsGetPortOrService (&tmp, &entry->sport) < 0) badline(entry->realline, "source port");
- if (lsGetHostOrIntfc (&tmp, &entry->nexthop) < 0) badline(entry->realline, "interface");
- }
- /* Examine the current line for an entry telling us how to get someplace... */
- /* */
- /* Arguments: indx -- index into the array we are dealing with...(in) */
- /* i -- index of the array we came from...(in) */
- /* tmp -- postion in the buffer...(in) */
- void HowtoHandler(void **array, int indx, int i, char *tmp) {
- static u_short socksport;
- u_short port;
- ProxyTuple *entry = &(*(ProxyTuple **)array)[indx];
- SKIPNONSPACE(tmp);
- if (indx >= nslines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough proxy entries allocated");
- return;
- }
- entry->realline = lsLineNo;
- if (lsGetHostAndMask (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
- if (lsGetPortOrService (&tmp, &entry->sport) < 0) badline(entry->realline, "source port");
- if (i == DIRECT_IND) {
- entry->nextver = 0;
- entry->nnextaddr = 0;
- memset((char *)entry->nextaddr, 0, sizeof(S5NetAddr));
- return;
- }
- entry->nextver = (i == SOCKS5_IND)?SOCKS5_VERSION:SOCKS4_VERSION;
- for (i = 0; i < S5_SERVER_NUM && *tmp && *tmp != 'n'; i++, tmp++) {
- if (lsGetHostAddressAndPort(&tmp, &entry->nextaddr[i]) < 0) badline(entry->realline, "server address");
- if ((port = lsAddr2Port(&entry->nextaddr[i])) == INVALIDPORT || port == (u_short)0) {
- if (!socksport && lsName2Port("socks", "tcp", &socksport) < 0) socksport = htons(SOCKS_DEFAULT_PORT);
- lsAddrSetPort(&entry->nextaddr[i], socksport);
- }
- SKIPSPACE(tmp);
- if (*tmp != ',') {
- i++;
- break;
- }
- }
- entry->nnextaddr = i;
- }
- /* Examine the current line for an entry telling us what is allowed... */
- /* */
- /* Arguments: indx -- index into the array we are dealing with...(in) */
- /* i -- index of the array we came from...(in) */
- /* tmp -- postion in the buffer...(in) */
- void PermsHandler(void **array, int indx, int i, char *tmp) {
- ConfTuple *entry = &(*(ConfTuple **)array)[indx];
- if (indx >= nplines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough permission entries allocated");
- return;
- }
- SKIPNONSPACE(tmp);
- entry->realline = lsLineNo;
- entry->permit = (i == PERMIT_IND)?AUTH_OK:AUTH_FAIL;
- if (lsGetAuthMethods (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
- if (lsGetPermCommand (&tmp, &entry->command) < 0) badline(entry->realline, "command");
- if (lsGetHostAndMask (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
- if (lsGetHostAndMask (&tmp, &entry->dest) < 0) badline(entry->realline, "destination host");
- if (lsGetPortOrService (&tmp, &entry->sport) < 0) badline(entry->realline, "source port");
- if (lsGetPortOrService (&tmp, &entry->dport) < 0) badline(entry->realline, "destination port");
- if (lsGetPermUsers (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
- }
- void AuthsHandler(void **array, int indx, int i, char *tmp) {
- AuthTuple *entry = &(*(AuthTuple **)array)[indx];
- if (indx >= nalines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough authentication entries allocated");
- return;
- }
- SKIPNONSPACE(tmp);
- entry->realline = lsLineNo;
- if (lsGetHostAndMask (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
- if (lsGetPortOrService (&tmp, &entry->sport) < 0) badline(entry->realline, "source port");
- if (i != BAN_IND) {
- if (lsGetAuthMethods (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
- entry->banned = 0;
- } else {
- entry->banned = 1;
- }
- }
- void ReadConfig(void) {
- char *file;
- static int mi = 0;
- if (mi == 0) {
- mi++;
- IFTHREADED(MUTEX_SETUP(confid_mutex);)
- }
- MUTEX_LOCK(env_mutex);
- file = getenv("SOCKS5_CONFFILE");
- if (file) file = strdup(file);
- MUTEX_UNLOCK(env_mutex);
- if (!file) file = strdup(SRVCONF_FILE);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Reading config file: %s", file);
- lsSetupIntfcs(&intfcs, &ifcnt);
- MUTEX_LOCK(confid_mutex);
- ClearEntryList(confids, NCONFIDS);
- lsReadConfig(file, confids, NCONFIDS);
- MUTEX_UNLOCK(confid_mutex);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Config file read");
- if (file) free(file);
- /*
- S5LogStart(&S5LogDefaultHandle, -1, -1,"Socks5");
- */
- }
- /* See what kind of auths we will have to use...If the client can't do one */
- /* of them, then we'll probably quit. Otherwise, we'll use this list to */
- /* decide which one we do do... */
- int GetAuths(S5LinkInfo *pri, list **authlist) {
- int i;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authentication");
- *authlist = NULL;
- if (nalines == 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No auth line specified");
- return 0;
- }
- MUTEX_LOCK(confid_mutex);
- for (i = 0; i < nalines; i++) {
- if (!lsCheckHost(&authList[i].source, &pri->srcAddr, pri->srcName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source host didn't match", authList[i].realline);
- continue;
- }
- if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER
- && !lsCheckPort(&authList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source port didn't match", authList[i].realline);
- continue;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Matched", authList[i].realline);
- if (authList[i].banned) {
- MUTEX_UNLOCK(confid_mutex);
- return -1;
- } else {
- *authlist = authList[i].authlist;
- MUTEX_UNLOCK(confid_mutex);
- return 0;
- }
- }
- MUTEX_UNLOCK(confid_mutex);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No line matched");
- return -1;
- }
- /* Check to see if the current set of global variables is allowed to proceed */
- /* by the current state of the configuration file. If we are accepting, we */
- /* don't need to necessariy match the destinaion host and port since they */
- /* are not specified yet... */
- int Authorize(S5LinkInfo *pri, int accepting) {
- int rval, i;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authorization");
- /* Before check with ACL, following address checking is performed: */
- /* */
- /* if src == dst => AUTH_FAIL... */
- /* if dst == LOOPBACK => AUTH_FAIL... */
- /* if src is one of the next proxy => AUTH_FAIL (avoid looping)... */
- if (pri->peerCommand != SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) return AUTH_FAIL;
- if (pri->dstAddr.sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) return AUTH_FAIL;
- for (i = 0; i < pri->nAltSckAddrs; i++) {
- if (!lsAddrComp(&pri->srcAddr, &pri->altSckAddrs[i])) return AUTH_FAIL;
- }
- MUTEX_LOCK(confid_mutex);
- for (i = 0; i < nplines; i++) {
- if (!lsCheckByte(accessList[i].command, pri->peerCommand, "commands")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Command didn't match", accessList[i].realline);
- continue;
- }
- if (!lsCheckByte(accessList[i].authlist, pri->peerAuth, "auths")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Authentication didn't match", accessList[i].realline);
- continue;
- }
- if (!lsCheckHost(&accessList[i].source, &pri->srcAddr, pri->srcName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source host didn't match", accessList[i].realline);
- continue;
- }
- if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER &&
- !lsCheckPort(&accessList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source port didn't match", accessList[i].realline);
- continue;
- }
- /* if it is a UDP request, source address matches destination */
- /* address, and permission is OK, we are done... */
- if (pri->peerCommand == SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) {
- if (accessList[i].permit != AUTH_OK) continue;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
- MUTEX_UNLOCK(confid_mutex);
- return AUTH_OK;
- }
- /* If we are accepting, we don't know the port. Therefore we should */
- /* only care about permit lines. If we know the destination address */
- /* we will check the address. */
- if (accepting) {
- if (accessList[i].permit != AUTH_OK) continue;
- if (lsAddrIsNull(&pri->dstAddr) != 0) {
- if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
- continue;
- }
- }
- } else {
- if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
- continue;
- }
- if (!lsCheckPort(&accessList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination port didn't match", accessList[i].realline);
- continue;
- }
- }
- if (!lsCheckUser(accessList[i].userlist, pri->srcUser)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Username didn't match", accessList[i].realline);
- continue;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
- rval = accessList[i].permit;
- MUTEX_UNLOCK(confid_mutex);
- return rval;
- }
- MUTEX_UNLOCK(confid_mutex);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: No line matched");
- return AUTH_FAIL;
- }
- /* Check the destination is on the same subnet. returns cwnumber of matching */
- /* interfaces... */
- static int lsCheckIntfc(const S5NetAddr *dst, S5NetAddr *addr) {
- struct intaddr tmpaddr;
- struct ifreq ifr;
- int i, j, k = 0;
- memset((char *)&ifr, 0, sizeof(struct ifreq));
- for (i = 0; i < ifcnt; i++) {
- if (intfcs[i].addrcnt == 0 || intfcs[i].up != 1 || intfcs[i].type == 1) {
- /* not an IP interface... */
- if (intfcs[i].up == 1 && intfcs[i].type != 1) continue;
- /* the interface is still down... */
- strcpy(ifr.ifr_name, intfcs[i].name);
- if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) continue;
- /* the interface is up now. Find the address and mask, and */
- /* check if the dst is on the same subnet ... */
- if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0) continue;
- if (ifssi(ifr)->sin_family != AF_INET) continue;
- tmpaddr.ip = ifssi(ifr)->sin_addr;
- if (lsLookupIntfc(S5InvalidIOHandle, NET_MASK, &ifr) < 0) continue;
- tmpaddr.net = ifssi(ifr)->sin_addr;
- if (checkifc(tmpaddr, dst->sin.sin_addr)) {
- addr->sin.sin_addr = tmpaddr.ip;
- k++;
- }
- continue;
- }
- /* loopback interface ... */
- if (intfcs[i].addrlist[0].ip.s_addr == htonl(INADDR_LOOPBACK)) continue;
- for (j = 0; j < intfcs[i].addrcnt; j++) {
- /* null address and null mask doesn't count ... */
- if (!(intfcs[i].addrlist[j].ip.s_addr & intfcs[i].addrlist[j].net.s_addr)) continue;
- /* on the same subnet... */
- if (checkifc(intfcs[i].addrlist[j], dst->sin.sin_addr)) {
- addr->sin.sin_addr = intfcs[i].addrlist[j].ip;
- k++;
- }
- }
- }
- return k;
- }
- /* GetProxy takes the destination and the type of the destination and picks */
- /* how it should and a demand for what kind of server is needed, and finds a */
- /* server of that type, or returns -1 if there is no such server. */
- /* */
- /* Globals used: proxyList, the array of proxy entries.... */
- int GetProxy(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *sckAddrs, int *nsckAddrs, u_char *verp) {
- int i;
- S5NetAddr tmpaddr;
- *verp = 0;
- *nsckAddrs = 0;
- if (!lsAddrIsNull(dst)) return 0;
- /* Before check the proxy lines, check if the dst is on the same subnet */
- /* as the server is on. */
- if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
- if (lsCheckIntfc(dst, &tmpaddr) > 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: dst on the same subnet");
- return 0;
- }
- }
- MUTEX_LOCK(confid_mutex);
- for (i = 0; i < nslines; i++) {
- if (!lsCheckHost(&proxyList[i].source, dst, name)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination host didn't match", proxyList[i].realline);
- continue;
- }
- if (!lsCheckPort(&proxyList[i].sport, dst, NULL, proto)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination port didn't match", proxyList[i].realline);
- continue;
- }
- #define REALDEST(x) ((x)->sa.sa_family == AF_INET && (x)->sin.sin_addr.s_addr != INVALIDADDR && (x)->sin.sin_addr.s_addr != INADDR_ANY)
- if (proxyList[i].nextver && !REALDEST(&proxyList[i].nextaddr[0])) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Invalid server address", proxyList[i].realline);
- continue;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Matched", proxyList[i].realline);
- if (!proxyList[i].nextver) break;
- *verp = proxyList[i].nextver;
- memcpy((char *)sckAddrs, (char *)proxyList[i].nextaddr, sizeof(proxyList[i].nextaddr));
- *nsckAddrs = proxyList[i].nnextaddr;
- MUTEX_UNLOCK(confid_mutex);
- return 0;
- }
- MUTEX_UNLOCK(confid_mutex);
- return -1;
- }
- /* Determine the outbound address for a given destination */
- /* If not route does match, default will by any interface */
- int GetRoute(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *addr) {
- struct ifreq ifr;
- int i;
- memset((char *)&ifr, 0, sizeof(struct ifreq));
- /* If we return before we change this, there was an error... */
- memset((char *)addr, 0, sizeof(S5NetAddr));
- addr->sin.sin_family = AF_INET;
- /* If dst is loopback, the route will be loopback.... */
- if (dst->sin.sin_family == AF_INET && !lsAddrIsNull(dst)) {
- lsAddrCopy(addr, dst, lsAddrSize(dst));
- return 0;
- }
- MUTEX_LOCK(confid_mutex);
- for (i = 0; i < nrlines; i++) {
- if (!lsCheckHost(&routeList[i].source, dst, name)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination host didn't match", routeList[i].realline);
- continue;
- }
- if (!lsCheckPort(&routeList[i].sport, dst, NULL, proto)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination port didn't match", routeList[i].realline);
- continue;
- }
- if (routeList[i].nexthop.type == INVALID_TYPE) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface type", routeList[i].realline);
- continue;
- }
- if (routeList[i].nexthop.type == NAME) {
- /* If the interface is not up when the daemon started or the interface */
- /* has multiple addresses, get the current active address... otherwise */
- /* we are done... */
- if (routeList[i].nexthop.ifp->type == 1 || routeList[i].nexthop.ifp->up <= 0 || routeList[i].nexthop.ifp->addrcnt != 1) {
- strcpy(ifr.ifr_name, routeList[i].nexthop.ifp->name);
- if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Interface is down", routeList[i].realline);
- continue;
- }
- if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0 || ifssi(ifr)->sin_family != AF_INET) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface address", routeList[i].realline);
- continue;
- }
- addr->sin.sin_addr = ifssi(ifr)->sin_addr;
- break;
- } else if (routeList[i].nexthop.ifp->addrcnt == 0) continue;
- else {
- addr->sin.sin_addr = routeList[i].nexthop.ifp->addrlist[0].ip;
- break;
- }
- } else {
- addr->sin.sin_addr = routeList[i].nexthop.ifaddr;
- break;
- }
- }
- if (i < nrlines) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Matched", routeList[i].realline);
- MUTEX_UNLOCK(confid_mutex);
- return 0;
- }
- /* No match... */
- MUTEX_UNLOCK(confid_mutex);
- /* Before check the route lines, check if the server is single-homed or */
- /* if the dst is on the same subnet as the server is on. If the server */
- /* is single-homed, route line is useless. If the dst is on the same */
- /* subnet, use that interface IP... */
- if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
- if (lsCheckIntfc(dst, addr) == 1) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: dst on the same subnet");
- return 0;
- }
- }
- return -1;
- }
- int GetFilter(S5LinkInfo *pri, char *name) {
- int i;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Filter");
- MUTEX_LOCK(confid_mutex);
- for (i = 0; i < nflines; i++) {
- if (!lsCheckByte(filterList[i].command, pri->peerCommand, "commands")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Command didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckByte(filterList[i].authlist, pri->peerAuth, "auths")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Authentication didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckHost(&filterList[i].source, &pri->srcAddr, pri->srcName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source host didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckPort(&filterList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source port didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckHost(&filterList[i].dest, &pri->dstAddr, pri->dstName)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination host didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckPort(&filterList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination port didn't match", filterList[i].realline);
- continue;
- }
- if (!lsCheckUser(filterList[i].userlist, pri->srcUser)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Username didn't match", filterList[i].realline);
- continue;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d:matched", filterList[i].realline);
- strcpy(name, filterList[i].name);
- MUTEX_UNLOCK(confid_mutex);
- return 0;
- }
- MUTEX_UNLOCK(confid_mutex);
- memset(name, 0, S5_NAME_SIZE);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: No line matched");
- return -1;
- }