confutil.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:41k
源码类别:
代理服务器
开发平台:
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: confutil.c,v 1.74.4.9 1998/11/13 21:36:36 wlu Exp $
- */
- #include "socks5p.h"
- #include "threads.h"
- #include "buffer.h"
- #include "addr.h"
- #include "confutil.h"
- #include "log.h"
- #ifdef HAVE_IFADDRS_H
- #include <ifaddrs.h>
- #define ifassi(x) (((ssi *)(x))->sin_addr.s_addr)
- #endif
- #ifdef OSIOCGIFCONF
- #define RSIOCGIFCONF OSIOCGIFCONF
- #else
- #define RSIOCGIFCONF SIOCGIFCONF
- #endif
- #ifdef SIOCGIFADDR
- #define RSIOCGIFADDR SIOCGIFADDR
- #else
- #define RSIOCGIFADDR OSIOCGIFADDR
- #endif
- #ifdef SIOCGIFNETMASK
- #define RSIOCGIFNETMASK SIOCGIFNETMASK
- #else
- #define RSIOCGIFNETMASK OSIOCGIFNETMASK
- #endif
- IFTHREADED(extern MUTEX_T gh_mutex;)
- IFTHREADED(extern MUTEX_T gs_mutex;)
- int lsLineNo = 0;
- /* A function that checks if s1 is the first string in s1, and is followed */
- /* by whitespace. Used for configuration file entries. */
- static int CheckString(char *s1, char *s2) {
- if (s2 == NULL) return 1;
- if (strncmp(s1, s2, strlen(s2))) return 0;
- if (!isspace(s1[strlen(s2)])) return 0;
- return 1;
- }
- /* A function that checks if c's string or abbreviation member is the first */
- /* string in s1, and is followed by whitespace... */
- /* */
- /* Arguments: s1 -- the string which we are examining */
- /* Arguments: c -- a structure containing the string and abbreviation we */
- /* are checking for. */
- static int CheckStringOrAbbrev(char *s1, struct confid *c) {
- char *tmp;
- for (tmp = s1; *tmp && !isspace(*tmp); tmp++) if (isupper(*tmp)) *tmp = tolower(*tmp);
- if (CheckString(s1, c->string)) return 1;
- return CheckString(s1, c->abbrev);
- }
- /* This a malloc/realloc'ish function which takes orig, mallocs it if its */
- /* Null, or reallocs it if it is non-null...pretty simple...oh, if the size */
- /* is 0, and the pointer was allocated, it frees the memory, otherwise rets. */
- static void *remalloc(void *orig, size_t size) {
- if (size == 0) {
- if (orig) free(orig);
- return NULL;
- }
- if (orig == NULL) return (void *)malloc(size);
- else return (void *)realloc(orig, size);
- }
- int lsLinkedListInsertUnaligned(list **l, size_t s) {
- list *templ = remalloc(NULL, s+sizeof(list));
- if (templ == NULL) return -1;
- templ->dataptr = (void *)(templ+1);
- templ->ptrmalloced = 0;
- templ->next = *l;
- *l = templ;
- return 0;
- }
- int lsLinkedListInsertAligned(list **l, size_t s) {
- list *templ = remalloc(NULL, sizeof(list));
- void *vptr = remalloc(NULL, s);
- if (templ == NULL || vptr == NULL) return -1;
- templ->dataptr = vptr;
- templ->ptrmalloced = 1;
- templ->next = *l;
- *l = templ;
- return 0;
- }
- /* Delete a linked list...nothing to it really, except not freeing some ptrs */
- /* */
- /* Arguments: l -- a ptr to the list we need to free...will be set to null. */
- void lsDeleteLinkedList(list **l) {
- list *tmp, *cur;
- for (tmp = *l, *l = NULL; tmp;) {
- cur = tmp; tmp = tmp->next;
- if (cur->ptrmalloced) free(cur->dataptr);
- free(cur);
- }
- }
- /* Look at the buffer that ptr points to, and read an address... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* na -- a ptr to the address we are looking up...(out) */
- int lsGetHostAddress(char **ptr, S5NetAddr *na) {
- char *tmp, tc;
- int rval;
- SKIPSPACE(*ptr);
- tmp = *ptr;
- SKIPNSPNCOMMA(tmp);
- tc = *tmp; *tmp = ' ';
- rval = lsName2Addr(*ptr, na);
- *(*ptr = tmp) = tc;
- return rval;
- }
- /* Look at the buffer that ptr points to, and read a port... check ,'s */
- /* */
- /* 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 lsGetPort(char **ptr, u_short *val) {
- char *tmp, tc;
- int retval = 0;
- SKIPSPACE(*ptr);
- tmp = *ptr;
- SKIPNSPNCOMMA(tmp);
- tc = *tmp; *tmp = ' ';
- if (tmp != *ptr) retval = lsName2Port(*ptr, NULL /* XXX OK? */, val);
- else *val = INVALIDPORT;
- *(*ptr = tmp) = tc;
- return retval;
- }
- /* Look at the buffer that ptr points to, and read a port... no commas */
- /* Stuff the answer into an S5NetAddr... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* na -- a ptr to the address we are looking up...(out) */
- int lsGetHostPort(char **ptr, S5NetAddr *na) {
- u_short port = INVALIDPORT;
- int rval;
- rval = lsGetPort(ptr, &port);
- lsAddrSetPort(na, port);
- return rval;
- }
- /* Look at the buffer that ptr points to, and read an address and a port... */
- /* The address and port are separated by ':' ... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* na -- a ptr to the address we are looking up...(out) */
- int lsGetHostAddressAndPort(char **ptr, S5NetAddr *na) {
- int rval;
- char *tmp, tc;
- SKIPSPACE(*ptr);
- tmp = *ptr;
- SKIPNSPNCOLNCOM(tmp);
- if (tmp == *ptr) return 0;
- tc = *tmp; *tmp = ' ';
- rval = lsName2Addr(*ptr, na);
- *(*ptr = tmp) = tc;
- if (rval < 0) return rval;
- if (tc == ':') {
- (*ptr)++;
- return lsGetHostPort(ptr, na);
- }
- return 0;
- }
- /* Given ip (address in net order) return the standard subnet mask for it. */
- static void StandardSubnetMaskForClass(struct in_addr ip, struct in_addr *mask) {
- if ((ip.s_addr & htonl(0x80000000)) == 0) mask->s_addr = htonl(0xffff0000); /* class A */
- else if ((ip.s_addr & htonl(0x40000000)) == 0) mask->s_addr = htonl(0xffffff00); /* class B */
- else if ((ip.s_addr & htonl(0x20000000)) == 0) mask->s_addr = htonl(0xfffffff0); /* class C */
- else mask->s_addr = htonl(0xffffffff); /* class D */
- }
- /* Given ip (address in net order) return the standard net mask for it. */
- static void StandardNetMaskForClass(struct in_addr ip, struct in_addr *mask) {
- if ((ip.s_addr & htonl(0x80000000)) == 0) mask->s_addr = htonl(0xff000000); /* class A */
- else if ((ip.s_addr & htonl(0x40000000)) == 0) mask->s_addr = htonl(0xffff0000); /* class B */
- else if ((ip.s_addr & htonl(0x20000000)) == 0) mask->s_addr = htonl(0xffffff00); /* class C */
- else mask->s_addr = htonl(0xffffffff); /* class D */
- }
- /* Look at the buffer that ptr points to, and read either a net address of a */
- /* host and a netmask (n.n.n.n/m.m.m.m) or a abbreviated portion of that */
- /* (n.n.n. n.n. or n.) or the name of a valid machine (idaho.syl.dl.nec.com) */
- /* or a portion of that name which must match (.syl.dl.nec.com)... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* host -- a ptr to the address/mask we are looking up...(out) */
- int lsGetHostAndMask(char **ptr, struct host *h) {
- int i, nd = 0, rval = 0;
- struct hostent *hp;
- char *tmp, *st, c;
- if (!h) return -1;
- memset((char *)h, 0, sizeof(struct host));
- SKIPSPACE(*ptr);
- tmp = *ptr;
- if (*tmp == 'n') {
- h->type = IN_ADDR;
- h->mask.s_addr = 0xffffffff;
- h->ip.s_addr = INVALIDADDR;
- return -1;
- }
- for (st = tmp; !isspace(*tmp) && *tmp != ' ' && *tmp != '/'; tmp++) if (*tmp == '.') nd++;
- c = *tmp; *tmp = ' ';
- if (*st == '-') {
- /* - */
- /* This is obviously the easiest case...its a -, so any body matches */
- h->type = IN_ADDR;
- h->mask.s_addr = htonl(0x00000000);
- h->ip.s_addr = htonl(0x00000000);
- } else if (c == '/') {
- /* n.n.n.n/[m.m.m.m|h|s|n|a] */
- char *end, c2;
- for (end = tmp+1; !isspace(*end) && *end != ' '; end++);
- c2 = *end; *end = ' ';
- /* There was a /, so there has to have been an IP address before it. */
- /* Read the address, then read the mask... Pretty straight forward. */
- if ((h->ip.s_addr = inet_addr(st)) == INVALIDADDR) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Conf: Invalid address in address/mask host pair");
- rval = -1;
- }
- switch (*(tmp + 1)) {
- case 'h': h->mask.s_addr = htonl(0xffffffff); break;
- case 's': StandardSubnetMaskForClass(h->ip, &h->mask); break;
- case 'n': StandardNetMaskForClass (h->ip, &h->mask); break;
- case 'a': h->mask.s_addr = htonl(0x00000000); break;
- default: h->mask.s_addr = inet_addr(tmp+1); break;
- }
- h->type = IN_ADDR;
- h->ip.s_addr &= h->mask.s_addr;
- if (h->mask.s_addr == htonl(0xffffffff) && getenv("SOCKS5_REVERSEMAP") != NULL) {
- /* Map the IP, since the name we will be comparing it to */
- /* will already have been resolved and mapped (hopefully). */
- MUTEX_LOCK(gh_mutex);
- if ((hp = gethostbyaddr((char *)&h->ip, sizeof(struct in_addr), AF_INET)) != NULL) {
- /* Store all the aliases and the ip addresses */
- h->resolve = 1;
- strncpy(h->name, hp->h_name, MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1));
- h->name[MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1)] = ' ';
- for (i = 0; hp->h_aliases[i] && i < S5_HOSTALIASES_NUM; i++) {
- strncpy(h->aliases[i], hp->h_aliases[i], MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1));
- h->aliases[i][MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1)] = ' ';
- }
- h->aliascnt = i;
- for (i = 0; hp->h_addr_list[i] && i < S5_HOSTIP_NUM; i++) {
- memcpy((char *)&h->back[i], hp->h_addr_list[i], sizeof(struct in_addr));
- }
- h->ipcnt = i;
- }
- MUTEX_UNLOCK(gh_mutex);
- }
- *tmp = c;
- tmp = end;
- c = c2;
- } else if (*(tmp-1) == '.') {
- /* n.n.n. or n.n. or n. */
- /* Put a 0 on the end just for inet_addr's sake, even though it */
- /* seems to work without it...its not documented so it probably */
- /* won't work on some OS...restore it at the end... */
- char c2 = tmp[1];
- tmp[0] = '0';
- tmp[1] = ' ';
- if ((h->ip.s_addr = inet_addr(st)) == INVALIDADDR) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Conf: Invalid address in truncated address");
- rval = -1;
- }
- h->type = IN_ADDR;
- h->mask.s_addr = htonl(((u_int)0xffffffff) << (8*(4-nd)));
- h->ip.s_addr &= h->mask.s_addr;
- tmp[1] = c2;
- tmp[0] = ' ';
- } else if ((h->ip.s_addr = inet_addr(st)) != INVALIDADDR) {
- /* n.n.n.n or n.n.n or n.n or n */
- /* This one's really simple, inet_addr worked, and the mask */
- /* should be exact, so just do it... */
- h->type = IN_ADDR;
- h->mask.s_addr = htonl(0xffffffff);
- h->ip.s_addr &= h->mask.s_addr;
- /* Map the IP, since the name we will be comparing it to */
- /* will already have been resolved and mapped (hopefully). */
- if (getenv("SOCKS5_REVERSEMAP") != NULL) {
- MUTEX_LOCK(gh_mutex);
- if ((hp = gethostbyaddr((char *)&h->ip, sizeof(struct in_addr), AF_INET)) != NULL) {
- /* Store all the aliases and the ip addresses */
- h->resolve = 1;
- strncpy(h->name, hp->h_name, MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1));
- h->name[MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1)] = ' ';
- for (i = 0; hp->h_aliases[i] && i < S5_HOSTALIASES_NUM; i++) {
- strncpy(h->aliases[i], hp->h_aliases[i], MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1));
- h->aliases[i][MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1)] = ' ';
- }
- h->aliascnt = i;
- for (i = 0; hp->h_addr_list[i] && i < S5_HOSTIP_NUM; i++) {
- memcpy((char *)&h->back[i], hp->h_addr_list[i], sizeof(struct in_addr));
- }
- h->ipcnt = i;
- }
- MUTEX_UNLOCK(gh_mutex);
- }
- } else {
- /* name */
- h->type = NAME;
- h->resolve = (*st == '.')?0:1;
- /* Make this string lower case so we don't have to call (non-POSIX) */
- /* strncasecmp, but instead strncmp. */
- for (tmp = st; *tmp != ' '; tmp++) if (isupper(*tmp)) *tmp = tolower(*tmp);
- strncpy(h->name, st, MIN(strlen(st), S5_HOSTNAME_SIZE-1));
- h->name[MIN(strlen(st), S5_HOSTNAME_SIZE-1)] = ' ';
- if (h->resolve) {
- /* Reverse map the name, since the name we will be comparing it to */
- /* will already have been reverse and mapped (hopefully). */
- MUTEX_LOCK(gh_mutex);
- if ((hp = REAL(gethostbyname)(st)) != NULL) {
- /* Store all the aliases and the ip addresses */
- strncpy(h->name, hp->h_name, MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1));
- h->name[MIN(strlen(hp->h_name), S5_HOSTNAME_SIZE-1)] = ' ';
- for (i = 0; hp->h_aliases[i] && i < S5_HOSTALIASES_NUM; i++) {
- strncpy(h->aliases[i], hp->h_aliases[i], MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1));
- h->aliases[i][MIN(strlen(hp->h_aliases[i]), S5_HOSTNAME_SIZE-1)] = ' ';
- }
- h->aliascnt = i;
- for (i = 0; hp->h_addr_list[i] && i < S5_HOSTIP_NUM; i++) {
- memcpy((char *)&h->back[i], hp->h_addr_list[i], sizeof(struct in_addr));
- }
- h->ipcnt = i;
- }
- MUTEX_UNLOCK(gh_mutex);
- }
- h->length = strlen(h->name);
- }
- *tmp = c;
- SKIPNONSPACE(*ptr);
- return rval;
- }
- /* Look at the buffer that ptr points to, and read either a port number or */
- /* the name of a service...the name may be used in service name proxying. */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* p -- a ptr to the port/service we are looking up...(out) */
- int lsGetPortOrService(char **ptr, struct port *p) {
- char *tmp, c, *end, ec;
- int retval = 0;
- u_short tmpport;
- SKIPSPACE(*ptr);
- tmp = *ptr;
- p->lport = htons(INVALIDPORT);
- p->hport = htons(INVALIDPORT);
- if (*tmp == 'n') {
- p->lport = htons(0);
- return 0;
- }
- if ((c = *tmp) == '-') {
- /* anything goes */
- p->lport = htons(0);
- } else if (*tmp != '[' && *tmp != '(') {
- retval = lsGetPort(&tmp, &p->lport);
- p->hport = p->lport;
- } else {
- for (end = tmp; !isspace(*end) && *end != ',' && *end != ' '; end++);
- ec = *end; *end = ' ';
- tmp++;
- retval = lsName2Port(tmp, NULL /* XXX OK? */, &p->lport);
- *(tmp = end) = ec;
- if (retval) goto done;
- if (c == '(') {
- tmpport = ntohs(p->lport) + 1;
- p->lport = htons(tmpport);
- }
- if (*tmp != ',') {
- p->lport = INVALIDPORT;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "Conf: Expected a ',' between ports in a range");
- retval = -1;
- goto done;
- }
- for (end = tmp; !isspace(*end) && *end != ')' && *end != ']' && *end != ' '; end++);
- ec = *end; *end = ' ';
- tmp++;
- retval = lsName2Port(tmp, NULL /* XXX OK? */, &p->hport);
- *end = ec;
- if (retval) goto done;
- if (ec == ')') {
- tmpport = ntohs(p->hport) - 1;
- p->hport = htons(tmpport);
- }
- }
- done:
- SKIPNONSPACE(*ptr);
- return retval;
- }
- /* Look at the buffer that ptr points to, and read the string representing */
- /* valid authentication methods. */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* val -- a ptr to the char which will hold valid auths...(out) */
- int lsGetAuthMethods(char **ptr, list **val) {
- char *tmp, c, tmpn[S5_NAME_SIZE];
- int len, rval = 0;
- SKIPSPACE(*ptr);
- for (*val = NULL; **ptr != ' '; (*ptr)++) {
- for (tmp = *ptr; *tmp != ' ' && *tmp != ',' && !isspace(*tmp); tmp++);
- c = *tmp; *tmp = ' ';
- if (tmp == *ptr) {
- *tmp = c;
- break;
- }
- if (!strcmp(*ptr, "-")) {
- if (*val) lsDeleteLinkedList(val);
- *tmp = c;
- break;
- }
- if (lsLinkedListInsertUnaligned(val, 0) < 0) {
- *tmp = c;
- break;
- }
- len = MIN(strlen(*ptr), S5_NAME_SIZE-1);
- strncpy(tmpn, *ptr, len);
- tmpn[len] = ' ';
- *(*ptr = tmp) = c;
- /* Somehow, they know the auth number, so let them use it... */
- if (isdigit(*tmpn)) {
- if (((*val)->dataint = atoi(tmpn)) >= 0xff) {
- (*val)->dataint = 0xff;
- rval = -1;
- break;
- } else if (isspace(c) || c == ' ') break;
- continue;
- }
- /* See if the long (word) or short (letter) names match... */
- if (!strcmp(tmpn, "null") || !strcmp(tmpn, "n")) {
- (*val)->dataint = AUTH_NONE; /* null */
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "krb5gss") || !strcmp(tmpn, "k")) {
- (*val)->dataint = AUTH_GSSAPI; /* kerberos */
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "upwd") || !strcmp(tmpn, "u")) {
- (*val)->dataint = AUTH_PASSWD; /* passwd */
- if (isspace(c) || c == ' ') break;
- continue;
- }
- /* Nothing matched, so mark this as a bad entry and return -1... */
- (*val)->dataint = 0xff;
- lsDeleteLinkedList(&(*val)->next);
- rval = -1;
- break;
- }
- SKIPNONSPACE(*ptr);
- return rval;
- }
- /* Look at the buffer that ptr points to, and read the string representing */
- /* valid protocols... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* val -- a ptr to the char which will hold valid protos...(out) */
- int lsGetPermCommand(char **ptr, list **val) {
- char tmpn[S5_NAME_SIZE], *tmp, c;
- int len, rval = 0;
- SKIPSPACE(*ptr);
- for (*val = NULL; **ptr != ' '; (*ptr)++) {
- for (tmp = *ptr; *tmp != ' ' && *tmp != ',' && !isspace(*tmp); tmp++);
- c = *tmp; *tmp = ' ';
- if (tmp == *ptr) {
- *tmp = c;
- break;
- }
- if (!strcmp(*ptr, "-")) {
- if (*val) lsDeleteLinkedList(val);
- *tmp = c;
- break;
- }
- if (lsLinkedListInsertUnaligned(val, 0) < 0) {
- *tmp = c;
- break;
- }
- len = MIN(strlen(*ptr), S5_NAME_SIZE-1);
- strncpy(tmpn, *ptr, len);
- tmpn[len] = ' ';
- *(*ptr = tmp) = c;
- /* Somehow, they know the command number, so let them use it... */
- if (isdigit(*tmpn)) {
- if (((*val)->dataint = atoi(tmpn)) >= 0xff) {
- (*val)->dataint = 0xff;
- rval = -1;
- break;
- } else if (isspace(c) || c == ' ') break;
- continue;
- }
- /* See if the long (word) or short (letter) names match... */
- if (!strcmp(tmpn, "bind") || !strcmp(tmpn, "b")) {
- (*val)->dataint = SOCKS_BIND;
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "connect") || !strcmp(tmpn, "c")) {
- (*val)->dataint = SOCKS_CONNECT;
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "udp") || !strcmp(tmpn, "u")) {
- (*val)->dataint = SOCKS_UDP;
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "ping") || !strcmp(tmpn, "p")) {
- (*val)->dataint = SOCKS_PING;
- if (isspace(c) || c == ' ') break;
- continue;
- } else if (!strcmp(tmpn, "traceroute") || !strcmp(tmpn, "t")) {
- (*val)->dataint = SOCKS_TRACER;
- if (isspace(c) || c == ' ') break;
- continue;
- }
- /* Nothing matched, so mark this as a bad entry and return -1... */
- (*val)->dataint = 0xff;
- lsDeleteLinkedList(&(*val)->next);
- rval = -1;
- break;
- }
- SKIPNONSPACE(*ptr);
- return rval;
- }
- /* Look at the buffer that ptr points to, and read the string representing */
- /* a list of users. The list is comma separated with no whitespce between */
- /* usernames. "-" is a special string meaning any user is ok... */
- /* */
- /* Arguments: ptr -- a ptr to the buffer we are working with...(in/out) */
- /* l -- a ptr to the list of users which are ok...(out) */
- int lsGetPermUsers(char **ptr, list **l) {
- char *tmp, c;
- SKIPSPACE(*ptr);
- for (*l = NULL; **ptr != ' '; (*ptr)++) {
- for (tmp = *ptr; *tmp != ' ' && *tmp != ',' && !isspace(*tmp); tmp++);
- c = *tmp; *tmp = ' ';
- if (tmp == *ptr) {
- *tmp = c;
- break;
- }
- if (!strcmp(*ptr, "-")) {
- if (*l) lsDeleteLinkedList(l);
- *tmp = c;
- break;
- }
- if (lsLinkedListInsertUnaligned(l, strlen(*ptr)+1) < 0) {
- *tmp = c;
- break;
- }
- strcpy((*l)->dataptr, *ptr);
- *(*ptr = tmp) = c;
- if (isspace(c) || c == ' ') break;
- }
- SKIPNONSPACE(*ptr);
- return 0;
- }
- /* Check to see if username appears in userlist or if userlist is NULL. */
- /* If username is NULL, and the list is not, it obviously does not. */
- /* Returns 1 on success 0 on failure. */
- int lsCheckUser(list *userlist, const char *username) {
- list *tmp;
- if (!userlist) {
- /* Authentication is ok for anybody. */
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking username, %s is in -", username?username:"(null)");
- return 1;
- }
- if (!username) {
- /* Authentication is ok for nobody.. */
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking username, username is (null)");
- return 0;
- }
- for (tmp = userlist; tmp != NULL; tmp = tmp->next) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking if %s is %s", username, tmp->dataptr);
- if (!strcmp(tmp->dataptr, username)) return 1;
- }
- return 0;
- }
- /* Check to see if s or name match the host pattern specified in h. If so */
- /* return 1, if not return 0. */
- int lsCheckHost(struct host *h, const S5NetAddr *s, const char *name) {
- char tmp[S5_HOSTNAME_SIZE], nbuf[MAXHOSTNAMELEN];
- int offset, i;
- struct in_addr addr;
- /* Make sure the input address is valid */
- if (!s && !name) return 0;
- if (s && s->sa.sa_family == AF_INET && s->sin.sin_addr.s_addr == INVALIDADDR) return 0;
- /* The address was stored, not the name => compare addresses. */
- if (h->type == IN_ADDR) {
- if (h->ip.s_addr == INVALIDADDR) return 0;
- /* It is all.... */
- if (h->ip.s_addr == htonl(0x00000000) && h->mask.s_addr == htonl(0x00000000)) return 1;
- /* s is S5NAME but IP is not mapped... */
- if ((!s || s->sa.sa_family == AF_S5NAME) && !h->resolve) return 0;
- /* only name is available... */
- if (!s) {
- if (!strcmp(h->name, name)) return 1;
- for (i = 0; i < h->aliascnt; i++) {
- if (!strcmp(h->aliases[i], name)) return 1;
- }
- return 0;
- }
- if (s->sa.sa_family == AF_S5NAME) {
- if (!strcmp(h->name, s->sn.sn_name)) return 1;
- for (i = 0; i < h->aliascnt; i++) {
- if (!strcmp(h->aliases[i], s->sn.sn_name)) return 1;
- }
- return 0;
- }
- /* s is AF_INET... */
- if (s->sin.sin_addr.s_addr != INADDR_ANY) addr = s->sin.sin_addr;
- else addr.s_addr = (name)?inet_addr((char *)name):INVALIDADDR;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking host address (%08x == %08x)?", addr.s_addr & h->mask.s_addr, h->ip.s_addr);
- if ((addr.s_addr & h->mask.s_addr) == h->ip.s_addr) return 1;
- for (i = 0; i < h->ipcnt; i++) {
- if (h->back[i].s_addr == addr.s_addr) return 1;
- }
- /* last possibility, the name maches... */
- if (name && h->resolve) {
- if (!strcmp(h->name, name)) return 1;
- for (i = 0; i < h->aliascnt; i++) {
- if (!strcmp(h->aliases[i], name)) return 1;
- }
- }
- return 0;
- }
- /* The name was stored, not the address => compare names. */
- /* If we stored a backup address, check and see if it matches... */
- if (h->resolve) {
- if (s && s->sa.sa_family == AF_INET && s->sin.sin_addr.s_addr != INADDR_ANY) addr = s->sin.sin_addr;
- else addr.s_addr = (name)?inet_addr((char *)name):INVALIDADDR;
- for (i = 0; i < h->ipcnt; i++) {
- if (h->back[i].s_addr == addr.s_addr) return 1;
- }
- }
- if (s && s->sa.sa_family == AF_S5NAME) strcpy(tmp, s->sn.sn_name);
- else if (name) strcpy(tmp, name);
- else if (s && s->sa.sa_family == AF_INET) {
- struct hostent *hp = NULL;
- MUTEX_LOCK(gh_mutex);
- if (!(hp = gethostbyaddr((char *)&s->sin.sin_addr.s_addr, sizeof(struct in_addr), AF_INET))) {
- MUTEX_UNLOCK(gh_mutex);
- return 0;
- }
- strcpy(tmp, hp->h_name);
- MUTEX_UNLOCK(gh_mutex);
- } else return 0;
- for (i = 0; tmp[i] != ' '; i++) nbuf[i] = (isupper(tmp[i]))?tolower(tmp[i]):tmp[i];
- nbuf[i] = ' ';
- if (h->resolve) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking host name (%s is %s)?",nbuf, h->name);
- if (!strcmp(h->name, nbuf)) return 1;
- for (i = 0; i < h->aliascnt; i++) {
- if (!strcmp(h->aliases[i], nbuf)) return 1;
- }
- return 0;
- } else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking host domain (%s is in %s)?", nbuf, h->name);
- /* How much longer is name than the stored one? If its too short, well */
- /* its not a match...If it has to be exact and its too long, ditto. If */
- /* h->name isn't the last part of name, ditto...otherwise, a match. */
- if ((offset = i - h->length) < 0) return 0;
- if (strncmp(nbuf+offset, h->name, h->length)) return 0;
- return 1;
- }
- }
- /* Check to see if s or name match the port specified by p. */
- int lsCheckPort(struct port *p, const S5NetAddr *s, const char *name, char *proto) {
- u_short port = s?s->sin.sin_port:0;
- struct servent *sp;
- MUTEX_LOCK(gs_mutex);
- if (port == 0 && name && (sp = getservbyname((char *)name, proto))) port = sp->s_port;
- MUTEX_UNLOCK(gs_mutex);
- /* compare the port number to the range of numbers we stored.... */
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking port range (%d <= %d <= %d)?", ntohs(p->lport), ntohs(port), ntohs(p->hport));
- return ((ntohs(port) < ntohs(p->lport)) || (ntohs(port) > ntohs(p->hport)))?0:1;
- }
- /* Check to see if byte appears in bytes, a list of bytes. */
- /* */
- /* Arguments: bytes - the list of bytes we're checking */
- /* byte - the byte we're looking for in bytes */
- /* name - a name for the logs describing what this check is */
- int lsCheckByte(list *bytes, u_char byte, const char *name) {
- list *tl;
- if (!bytes) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking %s: Anything is ok ", name);
- return 1;
- }
- for (tl = bytes; tl; tl = tl->next) {
- if (tl->dataint == (int)byte && tl->dataint != 0xff) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking %s: %d matched ", name, (int)byte);
- return 1;
- } else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking %s: %d didn't match %d", name, tl->dataint, (int)byte);
- }
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(5), 0, "Check: Checking %s: No match for %d", name, (int)byte);
- return 0;
- }
- /* A function for use in LoopThroughFile which increments the number of */
- /* entries of this line type that need to be allocated... */
- static void ClassifyLine(confid *confids, int nids, int indx, char *tmp) {
- if (indx >= 0 && indx < nids) {
- if (confids[indx].number) (*confids[indx].number)++;
- return;
- }
- SKIPSPACE(tmp);
- if (*tmp == 'n' || *tmp ==' ') return;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "Bad line in configuration file: %d", lsLineNo);
- }
- /* A function for use in LoopThroughFile which actually reads the line into */
- /* the appropriate structure, by calling the right line handler... */
- static void ProcessLine(confid *confids, int nids, int indx, char *tmp) {
- char *end, c;
- for (end = tmp; *end != 'n' && *end != ' '; end++);
- c = *end; *end = ' ';
- if (indx < nids)
- confids[indx].handler(confids[indx].array, confids[indx].cnum?(*confids[indx].cnum)++:0, indx, tmp);
- *end = c;
- }
- /* LoopTroughFile() reads through (line by line) the file (read into buf) */
- /* and performs func on each line of the file...telling func what kind of */
- /* line it seems to be... */
- static void LoopThroughFile(char *buf, int fsize, confid *confids, int nids, void (*func)(confid *, int, int, char *)) {
- char *tmp, *nl;
- int i;
- for (lsLineNo = 1, tmp = buf; tmp && tmp < buf+fsize; tmp = nl+1, lsLineNo++) {
- if ((nl = strchr(tmp, 'n')) != NULL) *nl = ' ';
- SKIPSPACE(tmp);
- if (*tmp != '#' && *tmp != ' ') {
- /* Do this even if "i" is too big (so we only warn once) */
- for (i = 0; i < nids; i++) if (CheckStringOrAbbrev(tmp, &confids[i])) break;
- func(confids, nids, i, tmp);
- }
- if (!nl) break; else *nl = 'n';
- }
- }
- /* A function that reads teh configuration file SRVCONF_FILE int buf and */
- /* sets *size to be the size of the new buffer...if something goes wrong, it */
- /* returns NULL indicating there is no valid configuration (for now)... */
- static char *ReadConfigFile(const char *filename, int *sizep) {
- int size = 1024 * 1024;
- char *buf = NULL;
- S5IOHandle fd;
- struct stat sb;
- *sizep = 0;
- while ((fd = open(filename, O_RDONLY)) < 0 && errno == EINTR);
- if (fd < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "Config: Error opening config file (%s): %m", filename);
- return NULL;
- }
- if (fstat(fd, &sb) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "Config: Error stating open config file (%s): %m", filename);
- goto end;
- }
- size = sb.st_size;
- if ((buf = (char *)malloc((size+1)*sizeof(char))) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "Config: Error allocating space for config file (%s): %m", filename);
- goto end;
- }
- if ((size = READFILE(fd, buf, size)) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "Config: Error reading open config file (%s): %m", filename);
- free(buf);
- buf = NULL;
- } else {
- buf[size] = ' ';
- *sizep = size;
- }
- end:
- REAL(close)(fd);
- return buf;
- }
- /* ReadConfig() reads the configuration file specified by SRVCONF_FILE. It */
- /* first figures out how much memory it will need, allocates the memory, */
- /* reads in the array, counts the number of entries of each type, and */
- /* allocates (or reallocates) the appropriate arrays those entries are kept */
- /* in. After all that, it actually reads in the entries themselves (from */
- /* memory) and rstarts the logging in case its variables may have changed. */
- /* */
- /* Globals Affected: -- too many to list... big ones are... */
- /* -- confids, where the entries are stored. */
- /* -- environ, which may have new entries in it... */
- void lsReadConfig(const char *filename, confid *confids, int nids) {
- int i, fsize;
- char *buf;
- if ((buf = ReadConfigFile(filename, &fsize)) == NULL) return; /* read in */
- LoopThroughFile(buf, fsize, confids, nids, ClassifyLine); /* count */
- for (i = 0; i < nids; i++) if (confids[i].size > 0) {
- *confids[i].array = (void *)remalloc(*confids[i].array, *confids[i].number * confids[i].size);
- memset(*confids[i].array, 0, *confids[i].number * confids[i].size);
- }
- LoopThroughFile(buf, fsize, confids, nids, ProcessLine); /* process */
- free(buf);
- }
- /* check out interface's condition */
- int lsLookupIntfc(S5IOHandle sd, int query, struct ifreq *ifr) {
- int rval = -1;
- S5IOHandle osd = (sd != S5InvalidIOHandle)?sd:socket(AF_INET, SOCK_DGRAM, 0);
- if (osd == S5InvalidIOHandle) return rval;
- memset((char *)&ifr->ifr_ifru, 0, sizeof(ifr->ifr_ifru));
- switch (query) {
- case NET_STAT:
- if (ioctl(osd, SIOCGIFFLAGS, (char *)ifr) == 0) {
- if (!(ifr->ifr_flags & (IFF_UP | IFF_RUNNING))) {
- rval = 0;
- } else rval = 1;
- }
- break;
- case NET_TYPE:
- if (ioctl(osd, SIOCGIFFLAGS, (char *)ifr) == 0) {
- if ((ifr->ifr_flags & IFF_POINTOPOINT)) rval = 1;
- else rval = 0;
- }
- break;
- case NET_ADDR:
- #ifdef linux
- ((struct sockaddr *)&ifr->ifr_addr)->sa_family = AF_INET;
- #endif
- if (ioctl(osd, RSIOCGIFADDR, (char *)ifr) == 0) rval = 0;
- break;
- case NET_MASK:
- if (ioctl(osd, RSIOCGIFNETMASK, (char *)ifr) == 0) rval = 0;
- break;
- default:
- break;
- }
- if (sd == S5InvalidIOHandle && osd != S5InvalidIOHandle) CLOSESOCKET(osd);
- return rval;
- }
- /* Get a list of valid interfaces... */
- void lsSetupIntfcs(struct intfc **intfc, int *cnt) {
- #ifdef HAVE_GETIFADDRS
- struct ifaddrs *ifp, *ibuf = NULL;
- #else
- struct ifreq ibuf[1024];
- struct ifconf ifc;
- S5IOHandle s;
- #endif
- struct intfc *pintfc;
- struct intaddr *pintaddr;
- struct in_addr tmpaddr;
- char tmpname[16];
- int i, j, k, m, n;
- if (*intfc) {
- if (intfc[0]->addrlist) free(intfc[0]->addrlist);
- free(*intfc);
- *intfc = NULL;
- }
- *cnt = 0;
- #ifdef HAVE_GETIFADDRS
- if (getifaddrs(&ibuf) < 0 || !ibuf) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Interface Query: Error looking up interface names");
- return;
- }
- n = 0;
- strcpy(tmpname, ibuf->ifa_name);
- #else
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == S5InvalidIOHandle) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Interface Query: socket: %m");
- return;
- }
- ifc.ifc_len = sizeof(ibuf);
- ifc.ifc_buf = (caddr_t)ibuf;
- memset((char *)ibuf, 0, sizeof(ibuf));
- /* Get the list of all the interfaces... */
- if (ioctl(s, RSIOCGIFCONF, (char *)&ifc) < 0 || ifc.ifc_len < sizeof(struct ifreq)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Interface Query: Error looking up interface names");
- CLOSESOCKET(s);
- return;
- }
- n = ifc.ifc_len/sizeof(struct ifreq);
- if (n > 0) strcpy(tmpname, ibuf[0].ifr_name);
- #endif
- /* Walk through the list and count the interfaces that are configured */
- /* with IP... */
- i = 0; j = 0; k = 0;
- tmpaddr.s_addr = 0L;
- #ifdef HAVE_GETIFADDRS
- for (ifp = ibuf; ifp; ifp = ifp->ifa_next) {
- if (strcmp(tmpname, ifp->ifa_name)) {
- if (n) j++;
- n = 0;
- strcpy(tmpname, ifp->ifa_name);
- }
- i = (ifp->ifa_flags & (IFF_UP | IFF_RUNNING))?1:0;
- if (i && ifp->ifa_addr->sa_family != AF_INET) continue;
- if (!i && !(ifp->ifa_flags & IFF_POINTOPOINT)) continue;
- n = 1;
- if (!i || ifassi(ifp->ifa_addr) == 0L) continue;
- if (k > 0 && ifassi(ifp->ifa_addr) == tmpaddr.s_addr) continue;
- tmpaddr.s_addr = ifassi(ifp->ifa_addr);
- k++;
- }
- if (n) j++;
- #else
- for (; i < n; i++) {
- if (strcmp(tmpname, ibuf[i].ifr_name)) {
- j++;
- strcpy(tmpname, ibuf[i].ifr_name);
- }
- if (lsLookupIntfc(s, NET_ADDR, &ibuf[i]) < 0) continue;
- if (ifssi(ibuf[i])->sin_family != AF_INET) continue;
- if (k > 0 && tmpaddr.s_addr == ifssi(ibuf[i])->sin_addr.s_addr) continue;
- tmpaddr.s_addr = ifssi(ibuf[i])->sin_addr.s_addr;
- k++;
- }
- j++;
- #endif
- if ((pintfc = (struct intfc *)calloc(j, sizeof(struct intfc))) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Interface Query: no space");
- return;
- }
- if ((pintaddr = (struct intaddr *)calloc(k, sizeof(struct intaddr))) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Interface Query: no space");
- free(pintfc);
- return;
- }
- /* Store IP-configured interfaces information... */
- i = 0; j = 0; k = 0;
- #ifdef HAVE_GETIFADDRS
- strcpy(pintfc[j].name, ibuf->ifa_name);
- pintfc[j].up = (ibuf->ifa_flags & (IFF_UP | IFF_RUNNING))?1:0;
- pintfc[j].type = (ibuf->ifa_flags & IFF_POINTOPOINT)?1:0;
- pintfc[j].addrlist = &pintaddr[k];
- pintfc[j].addrcnt = 0;
- n = 0;
- m = 0;
- for (ifp = ibuf; ifp; ifp = ifp->ifa_next) {
- if (strcmp(pintfc[j].name, ifp->ifa_name)) {
- pintfc[j].addrcnt = m;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d is %s(%d) with %d IPs", j, pintfc[j].name, pintfc[j].up, m);
- if (n) j++;
- strcpy(pintfc[j].name, ifp->ifa_name);
- pintfc[j].up = (ifp->ifa_flags & (IFF_UP | IFF_RUNNING))?1:0;
- pintfc[j].type = (ifp->ifa_flags & IFF_POINTOPOINT)?1:0;
- pintfc[j].addrlist = &pintaddr[k];
- pintfc[j].addrcnt = 0;
- n = 0;
- m = 0;
- }
- if (pintfc[j].up && ifp->ifa_addr->sa_family != AF_INET) continue;
- if (!pintfc[j].up && !pintfc[j].type) continue;
- n = 1;
- if (!pintfc[j].up || ifassi(ifp->ifa_addr) == 0L) continue;
- if (k > 0 && ifassi(ifp->ifa_addr) == pintaddr[k-1].ip.s_addr) continue;
- pintaddr[k].ip.s_addr = ifassi(ifp->ifa_addr);
- pintaddr[k].net.s_addr = ifassi(ifp->ifa_netmask);
- m++; k++;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d addr/mask is %08x:%08x", j, pintaddr[k-1].ip.s_addr, pintaddr[k-1].net.s_addr);
- }
- pintfc[j].addrcnt = m;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d is %s(%d) with %d IPs", j, pintfc[j].name, pintfc[j].up, m);
- if (n) j++;
- *cnt = j;
- *intfc = pintfc;
- free(ibuf);
- #else
- strcpy(pintfc[j].name, ibuf[i].ifr_name);
- pintfc[j].up = lsLookupIntfc(s, NET_STAT, &ibuf[i]);
- pintfc[j].type = lsLookupIntfc(s, NET_TYPE, &ibuf[i]);
- pintfc[j].addrlist = &pintaddr[k];
- pintfc[j].addrcnt = 0;
- m = 0;
- for (; i < n; i++) {
- if (strcmp(pintfc[j].name, ibuf[i].ifr_name)) {
- pintfc[j].addrcnt = m;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d is %s(%d) with %d IPs", j, pintfc[j].name, pintfc[j].up, m);
- j++;
- strcpy(pintfc[j].name, ibuf[i].ifr_name);
- pintfc[j].up = lsLookupIntfc(s, NET_STAT, &ibuf[i]);
- pintfc[j].type = lsLookupIntfc(s, NET_TYPE, &ibuf[i]);
- pintfc[j].addrlist = &pintaddr[k];
- pintfc[j].addrcnt = 0;
- m = 0;
- }
- if (lsLookupIntfc(s, NET_ADDR, &ibuf[i]) < 0) continue;
- if (ifssi(ibuf[i])->sin_family != AF_INET) continue;
- if (k > 0 && pintaddr[k-1].ip.s_addr == ifssi(ibuf[i])->sin_addr.s_addr) continue;
- pintaddr[k].ip.s_addr = ifssi(ibuf[i])->sin_addr.s_addr;
- if (lsLookupIntfc(s, NET_MASK, &ibuf[i]) >= 0) {
- pintaddr[k].net.s_addr = ifssi(ibuf[i])->sin_addr.s_addr;
- } else pintaddr[k].net.s_addr = 0xffffffff;
- m++; k++;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d addr/mask is %08x:%08x", j, pintaddr[k-1].ip.s_addr, pintaddr[k-1].net.s_addr);
- }
- pintfc[j].addrcnt = m;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Interface Query: if%d is %s(%d) with %d IPs", j, pintfc[j].name, pintfc[j].up, m);
- *cnt = ++j;
- *intfc = pintfc;
- CLOSESOCKET(s);
- #endif
- }