validate.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:37k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: validate.c,v 1.74.2.1.2.6 1998/09/22 20:34:39 wlu Exp $
  8.  */
  9. /* This file contains all of the stuff associated with parsing the config    */
  10. /* file, except for some utility routines which appear in valutil.c.  The    */
  11. /* routines for checking the parsed config file appear in check.c.           */
  12. #include "socks5p.h"
  13. #include "threads.h"
  14. #include "daemon.h"
  15. #include "confutil.h"
  16. #include "validate.h"
  17. #include "protocol.h"
  18. #include "msgids.h"
  19. #include "info.h"
  20. #include "log.h"
  21. #define INVALID_TYPE (char)-1   /* some kind of config error...               */
  22. IFTHREADED(static MUTEX_T confid_mutex = MUTEX_INITIALIZER;)
  23. static struct intfc *intfcs = NULL;
  24. static int ifcnt = 0;
  25. struct sroute {
  26.     char type;
  27.     int calloced;
  28.     struct in_addr ifaddr;
  29.     struct intfc *ifp;
  30. };
  31. struct authtuple {
  32.     int realline;
  33.     struct host source;
  34.     struct port sport;
  35.     list *authlist;
  36.     u_char banned;
  37. };
  38. typedef struct authtuple AuthTuple;
  39. static AuthTuple *authList = NULL; /* An array of auth list entries          */
  40. static int nalines = 0, na = 0;    /* how many auth lines, and current index */
  41. /* A configuration tuple, used in the access control portion of the config   */
  42. /* file...It tells us the permission as well as matching information...      */
  43. struct conftuple {
  44.     int realline;
  45.     char permit;
  46.     list *command;
  47.     list *userlist;
  48.     list *authlist;
  49.     struct host source, dest;
  50.     struct port sport, dport;
  51. };
  52. typedef struct conftuple ConfTuple;
  53. static ConfTuple *accessList  = NULL; /* An array of access list entries     */
  54. static int nplines = 0, np = 0;       /* how many access lines, & index      */
  55. /* A routing tuple...used in the routing portion of the config file to tell  */
  56. /* the server how it should be connecting (and being connected) to hosts...  */
  57. struct routetuple {
  58.     int realline;
  59.     struct host source;
  60.     struct port sport;
  61.     struct sroute nexthop;
  62. };
  63. typedef struct routetuple RouteTuple;
  64. static RouteTuple *routeList = NULL; /* An array of route list entries       */
  65. static int nrlines = 0, nr = 0;      /* how many route lines, & index        */
  66. /* A proxy tuple...used in the proxy portion of the config file to tell the  */
  67. /* server how it should get to a destination (what the next step is...)      */
  68. struct proxytuple {
  69.     int realline;
  70.     struct host source;
  71.     struct port sport;
  72.     
  73.     u_char  nextver;
  74.     S5NetAddr nextaddr[S5_SERVER_NUM];
  75.     int nnextaddr;
  76. };
  77. typedef struct proxytuple ProxyTuple;
  78. static ProxyTuple *proxyList = NULL; /* An array of socks list entries       */
  79. static int nslines = 0, ns = 0;      /* how many proxy lines & index         */
  80. /* A filter tuple, used in the filter portion of the config file...It tells  */
  81. /* us the what filter to use for a given connection...                       */
  82. struct filtertuple {
  83.     int realline;
  84.     char name[S5_NAME_SIZE];
  85.     list *command;
  86.     list *userlist;
  87.     list *authlist;
  88.     struct host source, dest;
  89.     struct port sport, dport;
  90. };
  91. typedef struct filtertuple FilterTuple;
  92. static FilterTuple *filterList = NULL; /* An array of socks list entries     */
  93. static int nflines = 0, nf = 0;        /* how many filter lines & index      */
  94. static char **varList = NULL;    /* A list of variables allocated            */
  95. static int nvlines = 0, nv = 0;  /* how many variable lines and cur index    */
  96. extern void AuthsHandler  P((void **, int, int, char *)); /* Auth line       */
  97. extern void PermsHandler  P((void **, int, int, char *)); /* permission line */
  98. extern void HowtoHandler  P((void **, int, int, char *)); /* proxy line...   */
  99. extern void RouteHandler  P((void **, int, int, char *)); /* route line...   */
  100. extern void EvarsHandler  P((void **, int, int, char *)); /* evar line..     */
  101. extern void FilterHandler P((void **, int, int, char *)); /* filter line...  */
  102. confid confids[] = {
  103.     { "permit",  "p",   PermsHandler, (void **)&accessList, &nplines, &np, sizeof(ConfTuple)    },
  104. #define PERMIT_IND  0 /* An indentifier that this line is "permit"            */
  105.     { "deny",    "d",   PermsHandler, (void **)&accessList, &nplines, &np, 0                    },
  106. #define DENY_IND    1 /* An indentifier that this line is "deny"              */
  107.     { "route",   "r",   RouteHandler, (void **)&routeList,  &nrlines, &nr, sizeof(RouteTuple)   },
  108. #define ROUTE_IND   2 /* An indentifier that this line is "route"             */
  109.     { "interface",   "i",   RouteHandler, (void **)&routeList,  &nrlines, &nr, 0 },
  110. #define INTFC_IND   3 /* An indentifier that this line is "interface"         */
  111.     { "socks4",  "4",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, 0                    },
  112. #define SOCKS4_IND  4 /* An indentifier that this line is "socks"             */
  113.     { "socks5",  "5",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, sizeof(ProxyTuple)   },
  114. #define SOCKS5_IND  5 /* An indentifier that this line is "socks5"            */
  115.     { "noproxy", "n",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, 0                    },
  116. #define DIRECT_IND  6 /* An indentifier that this line is "direct"            */
  117.     { "auth",    "a",   AuthsHandler, (void **)&authList,   &nalines, &na, sizeof(AuthTuple)    },
  118. #define AUTH_IND    7 /* An indentifier that this line is "auth"              */
  119.     { "ban",     "b",   AuthsHandler, (void **)&authList,   &nalines, &na, 0                    },
  120. #define BAN_IND     8 /* An indentifier that this line is "ban"               */
  121.     { "set",     "s",   EvarsHandler, (void **)&varList,     &nvlines, &nv, sizeof(char *)      },
  122. #define SET_IND     9 /* An indentifier that this line is "set"               */
  123.     { "filter",  "f",   FilterHandler,(void **)&filterList,  &nflines, &nf, sizeof(FilterTuple) },
  124. #define FILTER_IND  10 /* An indentifier that this line is "filter"            */
  125. };
  126. #define NCONFIDS (sizeof(confids)/sizeof(struct confid))
  127. /* Look at the buffer that ptr points to, and read either a net address of a */
  128. /* valid interface or the name (e.g. ef0, ef1, le0) of a valid int address.  */
  129. /*                                                                           */
  130. /* Arguments: ptr  -- a ptr to the buffer we are working with...(in/out)     */
  131. /*            val  -- a ptr to the address we are looking up...(out)         */
  132. static int lsGetHostOrIntfc(char **ptr, struct sroute *val) {
  133.     struct in_addr guess;
  134.     char *tmp, tc;
  135.     int i, j;
  136.     /* XXX ipv6 support here may get messy...                                */
  137.     memset((char *)val, 0, sizeof(struct sroute));
  138.     val->type = INVALID_TYPE;
  139.     SKIPSPACE(*ptr);
  140.     tmp = *ptr;
  141.     SKIPNONSPACE(tmp);
  142.     tc = *tmp; *tmp = '';
  143.     if ((guess.s_addr = inet_addr(*ptr)) == INVALIDADDR) {
  144. val->type = NAME;
  145. val->ifp = NULL;
  146. for (i = 0; i < ifcnt; i++) {
  147.     if (strcmp(*ptr, intfcs[i].name)) continue;
  148.     val->ifp  = &intfcs[i];
  149.     break;
  150. }
  151. if (val->ifp == NULL && (val->ifp = (struct intfc *)calloc(1, sizeof(struct intfc)))) {
  152.     strncpy(val->ifp->name, *ptr, 16);
  153.     val->ifp->name[15] = '';
  154.     val->calloced = 1;
  155. }
  156.     } else {
  157. val->type = IN_ADDR;
  158. val->ifaddr.s_addr = guess.s_addr;
  159. val->ifp = NULL;
  160. for (i = 0; i < ifcnt; i++) {
  161.     for (j = 0; j < intfcs[i].addrcnt; j++) {
  162.         if (intfcs[i].addrlist[j].ip.s_addr == guess.s_addr) break;
  163.     }
  164.     if (j < intfcs[i].addrcnt) {
  165. val->ifp = &intfcs[i];
  166.      break;
  167.     }
  168. }
  169.     }
  170.     *(*ptr = tmp) = tc;
  171.     return (val->type == INVALID_TYPE)?-1:0;
  172. }
  173. /* myunsetenv goes through and finds a variable=value pair which is the same */
  174. /* as (char *)n.  Once it finds it, it switches it with the last variable in */
  175. /* the environment, and returns...                                           */
  176. /*                                                                           */
  177. /* Arguments: n -- the name=value pair we are looking for (just name)        */
  178. /*                                                                           */
  179. /* Globals affected: environ -- no longer contians n.                        */
  180. static void myunsetenv(void *n) {
  181. #ifdef HAVE_UNSETENV
  182.     unsetenv((char *)n);
  183.     free(n);
  184. #else
  185.     char *name = (char *)n, **tmp, **end;
  186.     extern char **environ;
  187.     for (tmp = environ; *tmp; tmp++) 
  188. if (!strncmp(name, *tmp, strlen(name))) break; /* find a match...    */
  189.     if (!*tmp) return;                /* no match, so give up...             */
  190.     for (end = tmp; *(end+1); end++); /* find last set variable...           */
  191.     *tmp = *end;                      /* switch with the last set var...     */
  192.     *end = NULL;                      /* zero out the last set var...        */
  193.     free(name);
  194. #endif
  195. }
  196. #ifndef HAVE_SETENV
  197. static int myputenv(char *name) {
  198. #ifdef HAVE_PUTENV
  199.     return putenv(name);
  200. #else
  201.     char **tmp, *end = strchr(name, '='), c;
  202.     extern char **environ;
  203.     static int done;
  204.     int nenv;
  205.     
  206.     if (end == NULL) return 0;
  207.     /* Find a match or count the number of variables in the environment...   */
  208.     for (nenv = 0, tmp = environ; *tmp; tmp++, nenv++) {
  209. if (strncmp(name, *tmp, end-name)) continue;
  210. if ((*tmp)[end - name] != '=') continue;
  211. *tmp = name;
  212. return 1;
  213.     }
  214.     if (!done) {
  215. if ((tmp = (char **)malloc((nenv + 2) * sizeof(char *))) == NULL) {
  216.     return 0;
  217. }
  218. memcpy(environ, tmp, nenv+1 * sizeof(char *));
  219. done = 1;
  220.     } else {
  221. if ((tmp = (char **)realloc(environ, (nenv + 2) * sizeof(char *))) == NULL) {
  222.     return 0;
  223. }
  224.     }
  225.     tmp[nenv+1] = name;
  226.     tmp[nenv+2] = NULL;
  227.     environ = tmp;
  228.     return 1;
  229. #endif
  230. }
  231. #endif
  232. /* A function that clears up a given EntryList, for reading or rereading     */
  233. /* the configuration file.   It deallocates any memory used in allocating    */
  234. /* the list to begin with, and memset's the array of entries to be 0...      */
  235. /*                                                                           */
  236. /* Arguments: index -- which index in the confids array to clear up...       */
  237. static void ClearEntryList(confid *confids, int nconfids) {
  238.     int i;
  239. #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);
  240.     for (i = 0; i < *confids[AUTH_IND].number; i++) {
  241. lsDeleteLinkedList(&((AuthTuple *)*confids[AUTH_IND].array)[i].authlist);
  242.     }
  243.     for (i = 0; i < *confids[ROUTE_IND].number; i++) {
  244.         if (((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.calloced)
  245. free(((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.ifp);
  246.     }
  247.     for (i = 0; i < *confids[PERMIT_IND].number; i++) {
  248. lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].command);
  249. lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].userlist);
  250. lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].authlist);
  251.     }
  252.     for (i = 0; i < *confids[SET_IND].number; i++) {
  253. if (((char **)*confids[SET_IND].array)[i]) {
  254.     MUTEX_LOCK(env_mutex);
  255.     myunsetenv(((char **)*confids[SET_IND].array)[i]);
  256.     MUTEX_UNLOCK(env_mutex);
  257. }
  258.     }
  259.     CLEANUPIND(AUTH_IND);
  260.     CLEANUPIND(PERMIT_IND);
  261.     CLEANUPIND(SOCKS5_IND);
  262.     CLEANUPIND(ROUTE_IND);
  263.     CLEANUPIND(SET_IND);
  264. }
  265. static void badline(int ln, char *msg) {
  266.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, MSGID_SERVER_CONF_BADLINE, "Conf: Bad line (line number %d) in configuration file: %s", ln, msg);
  267. }
  268.     
  269. /* Examine the current line for an entry setting an environment variable...  */
  270. /*                                                                           */
  271. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  272. /*            i    -- index of the array we came from...(in)                 */
  273. /*            tmp  -- postion in the buffer...(in)                           */
  274. void EvarsHandler(void **array, int indx, int i, char *ptr) {
  275.     /* set up the "environment variables", only from file... */  
  276.     char *tmp, *end1, *new, **vlist = (*(char ***)array), buf[1024];
  277.     int len;
  278.     if (indx >= nvlines) {
  279. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough environment variable lines allocated");
  280. return;
  281.     }
  282.     SKIPNONSPACE(ptr);
  283.     SKIPSPACE(ptr);
  284.     if ((end1 = strstr(ptr, "n"))) len = MIN(sizeof(buf)-1, end1-ptr);
  285.     else len = MIN(sizeof(buf)-1, strlen(ptr));
  286.     memset(buf, 0, sizeof(buf));
  287.     strncpy(buf, ptr, len);
  288.     buf[len] = '';
  289.     for (tmp = buf ; !isspace(*tmp) && *tmp != ''; tmp++)
  290. if (islower(*tmp)) *tmp = toupper(*tmp); 
  291.     end1 = tmp;
  292.     SKIPSPACE(tmp);
  293.     
  294. #ifndef HAVE_SETENV
  295.     /* mush "variable    value" into "variable=value", and find the end     */
  296.     if (end1 != tmp) for (*end1++ = '='; !isspace(*tmp) && *tmp != ''; tmp++, end1++) *end1 = *tmp;
  297.     else *end1++ = '=';
  298.     *end1 = '';
  299. #endif
  300.     new = strdup(buf);
  301.     MUTEX_LOCK(env_mutex);
  302. #ifdef HAVE_SETENV
  303.     new[end1 - buf] = '';
  304.     setenv(new, new + (tmp-buf), 1);
  305. #else
  306.     myputenv(new);        /* replace it in actual environ                    */
  307. #endif
  308.     MUTEX_UNLOCK(env_mutex);
  309.     vlist[indx] = new;    /* put it in varList for future frees...           */
  310. }
  311. /* Examine the current line for an entry setting a filter to use...          */
  312. /*                                                                           */
  313. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  314. /*            i    -- index of the array we came from...(in)                 */
  315. /*            tmp  -- postion in the buffer...(in)                           */
  316. void FilterHandler(void **array, int indx, int i, char *tmp) {
  317.     FilterTuple *entry = &(*(FilterTuple **)array)[indx];
  318.     char *start;
  319.     
  320.     if (indx >= nflines) {
  321. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough filter entries allocated");
  322. return;
  323.     }
  324.     SKIPNONSPACE(tmp);
  325.     entry->realline = lsLineNo;
  326.     SKIPSPACE(tmp);
  327.     start = tmp;
  328.     SKIPNONSPACE(tmp);
  329.     strncpy(entry->name, start, MIN(tmp-start, S5_NAME_SIZE-1));
  330.     entry->name[MIN(tmp-start, S5_NAME_SIZE-1)] = '';
  331.     if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  332.     if (lsGetPermCommand   (&tmp, &entry->command)  < 0) badline(entry->realline, "command");
  333.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  334.     if (lsGetHostAndMask   (&tmp, &entry->dest)     < 0) badline(entry->realline, "destination host");
  335.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  336.     if (lsGetPortOrService (&tmp, &entry->dport)    < 0) badline(entry->realline, "destination port");
  337.     if (lsGetPermUsers     (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
  338. }
  339. /* Examine the current line for an entry setting a route to use...           */
  340. /*                                                                           */
  341. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  342. /*            i    -- index of the array we came from...(in)                 */
  343. /*            tmp  -- postion in the buffer...(in)                           */
  344. void RouteHandler(void **array, int indx, int i, char *tmp) {
  345.     RouteTuple *entry = &(*(RouteTuple **)array)[indx];
  346.     
  347.     if (indx >= nrlines) {
  348. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough route entries allocated");
  349. return;
  350.     }
  351.     SKIPNONSPACE(tmp);
  352.     entry->realline = lsLineNo;
  353.     if (lsGetHostAndMask   (&tmp, &entry->source)  < 0) badline(entry->realline, "source host");
  354.     if (lsGetPortOrService (&tmp, &entry->sport)   < 0) badline(entry->realline, "source port");
  355.     if (lsGetHostOrIntfc   (&tmp, &entry->nexthop) < 0) badline(entry->realline, "interface");
  356. }
  357. /* Examine the current line for an entry telling us how to get someplace...  */
  358. /*                                                                           */
  359. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  360. /*            i    -- index of the array we came from...(in)                 */
  361. /*            tmp  -- postion in the buffer...(in)                           */
  362. void HowtoHandler(void **array, int indx, int i, char *tmp) {
  363.     static u_short socksport;
  364.     u_short port;
  365.     
  366.     ProxyTuple *entry = &(*(ProxyTuple **)array)[indx];
  367.     SKIPNONSPACE(tmp);
  368.     
  369.     if (indx >= nslines) {
  370. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough proxy entries allocated");
  371. return;
  372.     }
  373.     entry->realline = lsLineNo;
  374.     if (lsGetHostAndMask   (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
  375.     if (lsGetPortOrService (&tmp, &entry->sport)  < 0) badline(entry->realline, "source port");
  376.     if (i == DIRECT_IND) {
  377. entry->nextver   = 0;
  378. entry->nnextaddr = 0;
  379. memset((char *)entry->nextaddr, 0, sizeof(S5NetAddr));
  380. return;
  381.     } 
  382.     entry->nextver = (i == SOCKS5_IND)?SOCKS5_VERSION:SOCKS4_VERSION;
  383.     for (i = 0; i < S5_SERVER_NUM && *tmp && *tmp != 'n'; i++, tmp++) {
  384. if (lsGetHostAddressAndPort(&tmp, &entry->nextaddr[i]) < 0) badline(entry->realline, "server address");
  385. if ((port = lsAddr2Port(&entry->nextaddr[i])) == INVALIDPORT || port == (u_short)0) {
  386.     if (!socksport && lsName2Port("socks", "tcp", &socksport) < 0) socksport = htons(SOCKS_DEFAULT_PORT);
  387.     lsAddrSetPort(&entry->nextaddr[i], socksport);
  388. }
  389. SKIPSPACE(tmp);
  390. if (*tmp != ',') {
  391.     i++;
  392.     break;
  393. }
  394.     }
  395.     entry->nnextaddr = i;
  396. }
  397. /* Examine the current line for an entry telling us what is allowed...       */
  398. /*                                                                           */
  399. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  400. /*            i    -- index of the array we came from...(in)                 */
  401. /*            tmp  -- postion in the buffer...(in)                           */
  402. void PermsHandler(void **array, int indx, int i, char *tmp) {
  403.     ConfTuple *entry = &(*(ConfTuple **)array)[indx];
  404.     if (indx >= nplines) {
  405. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough permission entries allocated");
  406. return;
  407.     }
  408.     SKIPNONSPACE(tmp);
  409.     entry->realline = lsLineNo;
  410.     entry->permit = (i == PERMIT_IND)?AUTH_OK:AUTH_FAIL;
  411.     if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  412.     if (lsGetPermCommand   (&tmp, &entry->command)  < 0) badline(entry->realline, "command");
  413.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  414.     if (lsGetHostAndMask   (&tmp, &entry->dest)     < 0) badline(entry->realline, "destination host");
  415.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  416.     if (lsGetPortOrService (&tmp, &entry->dport)    < 0) badline(entry->realline, "destination port");
  417.     if (lsGetPermUsers     (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
  418. }
  419. void AuthsHandler(void **array, int indx, int i, char *tmp) {
  420.     AuthTuple *entry = &(*(AuthTuple **)array)[indx];
  421.     if (indx >= nalines) {
  422. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough authentication entries allocated");
  423. return;
  424.     }
  425.     SKIPNONSPACE(tmp);
  426.     entry->realline = lsLineNo;
  427.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  428.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  429.     if (i != BAN_IND) {
  430. if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  431. entry->banned = 0;
  432.     } else {
  433. entry->banned = 1;
  434.     }
  435. }
  436. void ReadConfig(void) {
  437.     char *file;
  438.     static int mi = 0;
  439.     if (mi == 0) {
  440.         mi++;
  441.         IFTHREADED(MUTEX_SETUP(confid_mutex);)
  442.     }
  443.     MUTEX_LOCK(env_mutex);
  444.     file = getenv("SOCKS5_CONFFILE");
  445.     if (file) file = strdup(file);
  446.     MUTEX_UNLOCK(env_mutex);
  447.     if (!file) file = strdup(SRVCONF_FILE);
  448.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Reading config file: %s", file);
  449.     lsSetupIntfcs(&intfcs, &ifcnt);
  450.     MUTEX_LOCK(confid_mutex);
  451.     ClearEntryList(confids, NCONFIDS);
  452.     lsReadConfig(file, confids, NCONFIDS);
  453.     MUTEX_UNLOCK(confid_mutex);
  454.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Config file read");
  455.     if (file) free(file);
  456. /*
  457.     S5LogStart(&S5LogDefaultHandle, -1, -1,"Socks5");
  458. */
  459. }
  460. /* See what kind of auths we will have to use...If the client can't do one   */
  461. /* of them, then we'll probably quit.  Otherwise, we'll use this list to     */
  462. /* decide which one we do do...                                              */
  463. int GetAuths(S5LinkInfo *pri, list **authlist) {
  464.     int i;
  465.     
  466.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authentication");
  467.     *authlist = NULL;
  468.     if (nalines == 0) {
  469. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No auth line specified");
  470. return 0;
  471.     }
  472.     MUTEX_LOCK(confid_mutex);
  473.     for (i = 0; i < nalines; i++) {
  474. if (!lsCheckHost(&authList[i].source, &pri->srcAddr, pri->srcName)) {
  475.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source host didn't match", authList[i].realline);
  476.     continue;
  477. }
  478. if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER
  479. && !lsCheckPort(&authList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  480.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source port didn't match", authList[i].realline);
  481.     continue;
  482. }
  483. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Matched", authList[i].realline);
  484. if (authList[i].banned) {
  485.     MUTEX_UNLOCK(confid_mutex);
  486.     return -1;
  487. } else {
  488.     *authlist = authList[i].authlist;
  489.     MUTEX_UNLOCK(confid_mutex);
  490.     return 0;
  491. }
  492.     }
  493.     MUTEX_UNLOCK(confid_mutex);
  494.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No line matched");
  495.     return -1;
  496. }
  497. /* Check to see if the current set of global variables is allowed to proceed */
  498. /* by the current state of the configuration file.  If we are accepting, we  */
  499. /* don't need to necessariy match the destinaion host and port since they    */
  500. /* are not specified yet...                                                  */
  501. int Authorize(S5LinkInfo *pri, int accepting) {
  502.     int rval, i;
  503.     
  504.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authorization");
  505.     /* Before check with ACL, following address checking is performed:       */
  506.     /*                                                                       */
  507.     /* if src == dst => AUTH_FAIL...                                         */ 
  508.     /* if dst == LOOPBACK => AUTH_FAIL...                                    */ 
  509.     /* if src is one of the next proxy => AUTH_FAIL (avoid looping)...       */ 
  510.     if (pri->peerCommand != SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) return AUTH_FAIL;
  511.     if (pri->dstAddr.sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) return AUTH_FAIL;
  512.     for (i = 0; i < pri->nAltSckAddrs; i++) {
  513.      if (!lsAddrComp(&pri->srcAddr, &pri->altSckAddrs[i])) return AUTH_FAIL;
  514.     }
  515.     MUTEX_LOCK(confid_mutex);
  516.     for (i = 0; i < nplines; i++) {
  517. if (!lsCheckByte(accessList[i].command, pri->peerCommand, "commands")) {
  518.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Command didn't match", accessList[i].realline);
  519.     continue;
  520. }
  521. if (!lsCheckByte(accessList[i].authlist, pri->peerAuth, "auths")) {
  522.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Authentication didn't match", accessList[i].realline);
  523.     continue;
  524. }
  525. if (!lsCheckHost(&accessList[i].source, &pri->srcAddr, pri->srcName)) {
  526.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source host didn't match", accessList[i].realline);
  527.     continue;
  528. }
  529. if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER &&
  530. !lsCheckPort(&accessList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  531.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source port didn't match", accessList[i].realline);
  532.     continue;
  533. }
  534. /* if it is a UDP request, source address matches destination        */
  535.         /* address, and permission is OK, we are done...                     */
  536. if (pri->peerCommand == SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) {
  537.     if (accessList[i].permit != AUTH_OK) continue;
  538.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
  539.     MUTEX_UNLOCK(confid_mutex);
  540.     return AUTH_OK;
  541. }
  542.         /* If we are accepting, we don't know the port. Therefore we should  */
  543. /* only care about permit lines. If we know the destination address  */
  544.    /* we will check the address.                                        */
  545.         if (accepting) {
  546.     if (accessList[i].permit != AUTH_OK) continue;
  547.     if (lsAddrIsNull(&pri->dstAddr) != 0) {
  548.              if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
  549.                     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
  550.                     continue;
  551.                 }
  552.     }
  553. } else {
  554.     if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
  555.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
  556.         continue;
  557.     }
  558.     if (!lsCheckPort(&accessList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  559.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination port didn't match", accessList[i].realline);
  560.         continue;
  561.     }
  562. }
  563. if (!lsCheckUser(accessList[i].userlist, pri->srcUser)) {
  564.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Username didn't match", accessList[i].realline);
  565.     continue;
  566. }
  567. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
  568. rval = accessList[i].permit;
  569. MUTEX_UNLOCK(confid_mutex);
  570. return rval;
  571.     }
  572.     
  573.     MUTEX_UNLOCK(confid_mutex);
  574.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: No line matched");
  575.     return AUTH_FAIL;
  576. }
  577. /* Check the destination is on the same subnet. returns cwnumber of matching */
  578. /* interfaces...                                                             */
  579. static int lsCheckIntfc(const S5NetAddr *dst, S5NetAddr *addr) {
  580.     struct intaddr tmpaddr;
  581.     struct ifreq ifr;
  582.     int i, j, k = 0;
  583.     memset((char *)&ifr, 0, sizeof(struct ifreq));
  584.     for (i = 0; i < ifcnt; i++) {
  585. if (intfcs[i].addrcnt == 0 || intfcs[i].up != 1 || intfcs[i].type == 1) {
  586.     /* not an IP interface...                                    */
  587.             if (intfcs[i].up == 1 && intfcs[i].type != 1) continue;
  588.     /* the interface is still down...                            */
  589.     strcpy(ifr.ifr_name, intfcs[i].name);
  590.     if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) continue;
  591.     /* the interface is up now. Find the address and mask, and   */
  592.     /* check if the dst is on the same subnet ...                */
  593.     if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0) continue;
  594.     if (ifssi(ifr)->sin_family != AF_INET) continue;
  595.     tmpaddr.ip = ifssi(ifr)->sin_addr;
  596.     if (lsLookupIntfc(S5InvalidIOHandle, NET_MASK, &ifr) < 0) continue;
  597.             tmpaddr.net = ifssi(ifr)->sin_addr;
  598.             if (checkifc(tmpaddr, dst->sin.sin_addr)) {
  599.         addr->sin.sin_addr = tmpaddr.ip;
  600.         k++;
  601.             }
  602.     continue; 
  603. }
  604. /* loopback interface ...                                        */
  605. if (intfcs[i].addrlist[0].ip.s_addr == htonl(INADDR_LOOPBACK)) continue;
  606.     
  607. for (j = 0; j < intfcs[i].addrcnt; j++) {
  608.     /* null address and null mask doesn't count ...              */
  609.     if (!(intfcs[i].addrlist[j].ip.s_addr & intfcs[i].addrlist[j].net.s_addr)) continue;
  610.     /* on the same subnet...                                     */
  611.             if (checkifc(intfcs[i].addrlist[j], dst->sin.sin_addr)) {
  612. addr->sin.sin_addr = intfcs[i].addrlist[j].ip;
  613. k++;
  614.     }
  615. }
  616.     }
  617.     return k;
  618. }
  619. /* GetProxy takes the destination and the type of the destination and picks  */
  620. /* how it should and a demand for what kind of server is needed, and finds a */
  621. /* server of that type, or returns -1 if there is no such server.            */
  622. /*                                                                           */
  623. /* Globals used: proxyList, the array of proxy entries....                   */
  624. int GetProxy(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *sckAddrs, int *nsckAddrs, u_char *verp) {
  625.     int i;
  626.     S5NetAddr tmpaddr;
  627.     *verp = 0;
  628.     *nsckAddrs = 0;
  629.     if (!lsAddrIsNull(dst)) return 0;
  630.     /* Before check the proxy lines, check if the dst is on the same subnet  */
  631.     /* as the server is on.                                                  */
  632.     if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
  633. if (lsCheckIntfc(dst, &tmpaddr) > 0) {
  634.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: dst on the same subnet");
  635.             return 0;
  636.         }
  637.     }
  638.     MUTEX_LOCK(confid_mutex);
  639.     for (i = 0; i < nslines; i++) {
  640. if (!lsCheckHost(&proxyList[i].source, dst, name)) {
  641.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination host didn't match", proxyList[i].realline);
  642.     continue;
  643. }
  644. if (!lsCheckPort(&proxyList[i].sport, dst, NULL, proto)) {
  645.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination port didn't match", proxyList[i].realline);
  646.     continue;
  647. }
  648. #define REALDEST(x) ((x)->sa.sa_family == AF_INET && (x)->sin.sin_addr.s_addr != INVALIDADDR && (x)->sin.sin_addr.s_addr != INADDR_ANY)
  649. if (proxyList[i].nextver && !REALDEST(&proxyList[i].nextaddr[0])) {
  650.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Invalid server address", proxyList[i].realline);
  651.     continue;
  652. }
  653. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Matched", proxyList[i].realline);
  654. if (!proxyList[i].nextver) break;
  655. *verp      = proxyList[i].nextver;
  656. memcpy((char *)sckAddrs, (char *)proxyList[i].nextaddr, sizeof(proxyList[i].nextaddr));
  657. *nsckAddrs = proxyList[i].nnextaddr;
  658. MUTEX_UNLOCK(confid_mutex);
  659. return 0;
  660.     }
  661.     MUTEX_UNLOCK(confid_mutex);
  662.     return -1;
  663. }
  664. /* Determine the outbound address for a given destination           */
  665. /* If not route does match, default will by any interface           */
  666. int GetRoute(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *addr) {
  667.     struct ifreq ifr;
  668.     int i;
  669.     memset((char *)&ifr, 0, sizeof(struct ifreq));
  670.     /* If we return before we change this, there was an error...             */
  671.     memset((char *)addr, 0, sizeof(S5NetAddr));
  672.     addr->sin.sin_family = AF_INET;
  673.     /* If dst is loopback, the route will be loopback....                    */
  674.     if (dst->sin.sin_family == AF_INET && !lsAddrIsNull(dst)) {
  675.         lsAddrCopy(addr, dst, lsAddrSize(dst));
  676.         return 0;
  677.     }
  678.     MUTEX_LOCK(confid_mutex);
  679.     for (i = 0; i < nrlines; i++) {
  680. if (!lsCheckHost(&routeList[i].source, dst, name)) {
  681.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination host didn't match", routeList[i].realline);     
  682.     continue;
  683. }
  684. if (!lsCheckPort(&routeList[i].sport, dst, NULL, proto)) {
  685.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination port didn't match", routeList[i].realline);     
  686.     continue;
  687. }
  688. if (routeList[i].nexthop.type == INVALID_TYPE) {
  689.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface type", routeList[i].realline);     
  690.     continue;
  691. }
  692. if (routeList[i].nexthop.type == NAME) {
  693.     /* If the interface is not up when the daemon started or the interface */
  694.     /* has multiple addresses, get the current active address... otherwise */
  695.     /* we are done...                                                      */
  696.             if (routeList[i].nexthop.ifp->type == 1 || routeList[i].nexthop.ifp->up <= 0 || routeList[i].nexthop.ifp->addrcnt != 1) {
  697. strcpy(ifr.ifr_name, routeList[i].nexthop.ifp->name);
  698.      if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) {
  699.                  S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Interface is down", routeList[i].realline);
  700.          continue;
  701. }
  702.      if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0 || ifssi(ifr)->sin_family != AF_INET) {
  703.                  S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface address", routeList[i].realline);
  704.          continue;
  705. }
  706. addr->sin.sin_addr = ifssi(ifr)->sin_addr;
  707. break;
  708.     } else if (routeList[i].nexthop.ifp->addrcnt == 0) continue;
  709.     else {
  710. addr->sin.sin_addr = routeList[i].nexthop.ifp->addrlist[0].ip;
  711. break;
  712.     }
  713. } else {
  714.     addr->sin.sin_addr = routeList[i].nexthop.ifaddr;
  715.     break;
  716. }
  717.     }
  718.     if (i < nrlines) {
  719. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Matched", routeList[i].realline);     
  720. MUTEX_UNLOCK(confid_mutex);
  721. return 0;
  722.     }
  723.     /* No match...                                                           */
  724.     MUTEX_UNLOCK(confid_mutex);
  725.     /* Before check the route lines, check if the server is single-homed or  */
  726.     /* if the dst is on the same subnet as the server is on. If the server   */
  727.     /* is single-homed, route line is useless. If the dst is on the same     */
  728.     /* subnet, use that interface IP...                                      */
  729.     if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
  730. if (lsCheckIntfc(dst, addr) == 1) {
  731.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: dst on the same subnet");
  732.             return 0;
  733. }
  734.     }
  735.     return -1;
  736. }
  737. int GetFilter(S5LinkInfo *pri, char *name) {
  738.     int i;
  739.     
  740.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Filter");
  741.     MUTEX_LOCK(confid_mutex);
  742.     for (i = 0; i < nflines; i++) {
  743. if (!lsCheckByte(filterList[i].command,  pri->peerCommand, "commands")) {
  744.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Command didn't match", filterList[i].realline);
  745.     continue;
  746. }
  747. if (!lsCheckByte(filterList[i].authlist, pri->peerAuth, "auths")) {
  748.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Authentication didn't match", filterList[i].realline);
  749.     continue;
  750. }
  751. if (!lsCheckHost(&filterList[i].source,  &pri->srcAddr, pri->srcName)) {
  752.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source host didn't match", filterList[i].realline);
  753.     continue;
  754. }
  755. if (!lsCheckPort(&filterList[i].sport,   &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  756.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source port didn't match", filterList[i].realline);
  757.     continue;
  758. }
  759. if (!lsCheckHost(&filterList[i].dest,    &pri->dstAddr, pri->dstName)) {
  760.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination host didn't match", filterList[i].realline);
  761.     continue;
  762. }
  763. if (!lsCheckPort(&filterList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  764.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination port didn't match", filterList[i].realline);
  765.     continue;
  766. }
  767. if (!lsCheckUser(filterList[i].userlist, pri->srcUser)) {
  768.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Username didn't match", filterList[i].realline);
  769.     continue;
  770. }
  771. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d:matched", filterList[i].realline);
  772. strcpy(name, filterList[i].name);
  773. MUTEX_UNLOCK(confid_mutex);
  774. return 0;
  775.     }
  776.     
  777.     MUTEX_UNLOCK(confid_mutex);
  778.     memset(name, 0, S5_NAME_SIZE);
  779.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: No line matched");
  780.     return -1;
  781. }