📄 acl.c
字号:
aclHostDomainCompare(const void *data, splayNode * n){ const char *h = data; char *d = n->data; int l1; int l2; if (matchDomainName(d, h)) return 0; l1 = strlen(h); l2 = strlen(d); /* h != d */ while (xtolower(h[l1]) == xtolower(d[l2])) { if (l1 == 0) break; if (l2 == 0) break; l1--; l2--; } /* a '.' is a special case */ if ((h[l1] == '.') || (l1 == 0)) return -1; /* domain(h) < d */ if ((d[l2] == '.') || (l2 == 0)) return 1; /* domain(h) > d */ return (xtolower(h[l1]) - xtolower(d[l2]));}/* compare two network specs * * NOTE: this is very similar to aclIpNetworkCompare and it's not yet * clear whether this OK. The problem could be with when a network * is a subset of the other networks: * * 128.1.2.0/255.255.255.128 == 128.1.2.0/255.255.255.0 ? * * Currently only the first address of the first network is used. *//* compare an address and a network spec */static intaclIpNetworkCompare(const void *a, splayNode * n){ struct in_addr A = *(struct in_addr *) a; acl_ip_data *q = n->data; struct in_addr B = q->addr1; struct in_addr C = q->addr2; int rc = 0; A.s_addr &= q->mask.s_addr; /* apply netmask */ if (C.s_addr == 0) { /* single address check */ if (ntohl(A.s_addr) > ntohl(B.s_addr)) rc = 1; else if (ntohl(A.s_addr) < ntohl(B.s_addr)) rc = -1; else rc = 0; } else { /* range address check */ if (ntohl(A.s_addr) > ntohl(C.s_addr)) rc = 1; else if (ntohl(A.s_addr) < ntohl(B.s_addr)) rc = -1; else rc = 0; } return rc;}static voidaclDumpIpListWalkee(void *node, void *state){ acl_ip_data *ip = node; MemBuf mb; wordlist **W = state; memBufDefInit(&mb); memBufPrintf(&mb, "%s", inet_ntoa(ip->addr1)); if (ip->addr2.s_addr != any_addr.s_addr) memBufPrintf(&mb, "-%s", inet_ntoa(ip->addr2)); if (ip->mask.s_addr != no_addr.s_addr) memBufPrintf(&mb, "/%s", inet_ntoa(ip->mask)); wordlistAdd(W, mb.buf); memBufClean(&mb);}static wordlist *aclDumpIpList(void *data){ wordlist *w = NULL; splay_walk(data, aclDumpIpListWalkee, &w); return w;}static voidaclDumpDomainListWalkee(void *node, void *state){ char *domain = node; wordlistAdd(state, domain);}static wordlist *aclDumpDomainList(void *data){ wordlist *w = NULL; splay_walk(data, aclDumpDomainListWalkee, &w); return w;}static wordlist *aclDumpTimeSpecList(acl_time_data * t){ wordlist *W = NULL; char buf[128]; while (t != NULL) { snprintf(buf, sizeof(buf), "%c%c%c%c%c%c%c %02d:%02d-%02d:%02d", t->weekbits & ACL_SUNDAY ? 'S' : '-', t->weekbits & ACL_MONDAY ? 'M' : '-', t->weekbits & ACL_TUESDAY ? 'T' : '-', t->weekbits & ACL_WEDNESDAY ? 'W' : '-', t->weekbits & ACL_THURSDAY ? 'H' : '-', t->weekbits & ACL_FRIDAY ? 'F' : '-', t->weekbits & ACL_SATURDAY ? 'A' : '-', t->start / 60, t->start % 60, t->stop / 60, t->stop % 60); wordlistAdd(&W, buf); t = t->next; } return W;}static wordlist *aclDumpRegexList(relist * data){ wordlist *W = NULL; while (data != NULL) { wordlistAdd(&W, data->pattern); data = data->next; } return W;}static wordlist *aclDumpIntlistList(intlist * data){ wordlist *W = NULL; char buf[32]; while (data != NULL) { snprintf(buf, sizeof(buf), "%d", data->i); wordlistAdd(&W, buf); data = data->next; } return W;}static wordlist *aclDumpIntRangeList(intrange * data){ wordlist *W = NULL; char buf[32]; while (data != NULL) { if (data->i == data->j) snprintf(buf, sizeof(buf), "%d", data->i); else snprintf(buf, sizeof(buf), "%d-%d", data->i, data->j); wordlistAdd(&W, buf); data = data->next; } return W;}static wordlist *aclDumpProtoList(intlist * data){ wordlist *W = NULL; while (data != NULL) { wordlistAdd(&W, ProtocolStr[data->i]); data = data->next; } return W;}static wordlist *aclDumpMethodList(intlist * data){ wordlist *W = NULL; while (data != NULL) { wordlistAdd(&W, RequestMethodStr[data->i]); data = data->next; } return W;}wordlist *aclDumpGeneric(const acl * a){ debug(28, 3) ("aclDumpGeneric: %s type %d\n", a->name, a->type); switch (a->type) { case ACL_SRC_IP: case ACL_DST_IP: case ACL_MY_IP: return aclDumpIpList(a->data); break; case ACL_SRC_DOMAIN: case ACL_DST_DOMAIN: return aclDumpDomainList(a->data); break;#if SQUID_SNMP case ACL_SNMP_COMMUNITY:#endif#if USE_IDENT case ACL_IDENT:#endif case ACL_PROXY_AUTH: return wordlistDup(a->data); break; case ACL_TIME: return aclDumpTimeSpecList(a->data); break; case ACL_URL_REGEX: case ACL_URLPATH_REGEX: case ACL_BROWSER: case ACL_SRC_DOM_REGEX: case ACL_DST_DOM_REGEX: return aclDumpRegexList(a->data); break; case ACL_SRC_ASN: case ACL_DST_ASN: return aclDumpIntlistList(a->data); break; case ACL_URL_PORT: return aclDumpIntRangeList(a->data); break; case ACL_PROTO: return aclDumpProtoList(a->data); break; case ACL_METHOD: return aclDumpMethodList(a->data); break;#if USE_ARP_ACL case ACL_SRC_ARP: return aclDumpArpList(a->data); break;#endif case ACL_NONE: default: debug(28, 1) ("aclDumpGeneric: no case for ACL type %d\n", a->type); break; } return NULL;}#if USE_ARP_ACL/* ==== BEGIN ARP ACL SUPPORT ============================================= *//* * From: dale@server.ctam.bitmcnit.bryansk.su (Dale) * To: wessels@nlanr.net * Subject: Another Squid patch... :) * Date: Thu, 04 Dec 1997 19:55:01 +0300 * ============================================================================ * * Working on setting up a proper firewall for a network containing some * Win'95 computers at our Univ, I've discovered that some smart students * avoid the restrictions easily just changing their IP addresses in Win'95 * Contol Panel... It has been getting boring, so I took Squid-1.1.18 * sources and added a new acl type for hard-wired access control: * * acl <name> arp <Ethernet address> ... * * For example, * * acl students arp 00:00:21:55:ed:22 00:00:21:ff:55:38 * * NOTE: Linux code by David Luyer <luyer@ucs.uwa.edu.au>. * Original (BSD-specific) code no longer works. */#include <sys/sysctl.h>#ifdef _SQUID_LINUX_#include <net/if_arp.h>#include <sys/ioctl.h>#else#include <net/if_dl.h>#endif#include <net/route.h>#include <net/if.h>#include <netinet/if_ether.h>/* * Decode an ascii representation (asc) of an ethernet adress, and place * it in eth[6]. */static intdecode_eth(const char *asc, char *eth){ int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0; if (sscanf(asc, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) { debug(28, 0) ("decode_eth: Invalid ethernet address '%s'\n", asc); return 0; /* This is not valid address */ } eth[0] = (u_char) a1; eth[1] = (u_char) a2; eth[2] = (u_char) a3; eth[3] = (u_char) a4; eth[4] = (u_char) a5; eth[5] = (u_char) a6; return 1;}static acl_arp_data *aclParseArpData(const char *t){ LOCAL_ARRAY(char, eth, 256); acl_arp_data *q = xcalloc(1, sizeof(acl_arp_data)); debug(28, 5) ("aclParseArpData: %s\n", t); if (sscanf(t, "%[0-9a-fA-F:]", eth) != 1) { debug(28, 0) ("aclParseArpData: Bad ethernet address: '%s'\n", t); safe_free(q); return NULL; } if (!decode_eth(eth, q->eth)) { debug(28, 0) ("%s line %d: %s\n", cfg_filename, config_lineno, config_input_line); debug(28, 0) ("aclParseArpData: Ignoring invalid ARP acl entry: can't parse '%s'\n", eth); safe_free(q); return NULL; } return q;}/*******************//* aclParseArpList *//*******************/static voidaclParseArpList(void *curlist){ char *t = NULL; splayNode **Top = curlist; acl_arp_data *q = NULL; while ((t = strtokFile())) { if ((q = aclParseArpData(t)) == NULL) continue; *Top = splay_insert(q, *Top, aclArpCompare); }}/***************//* aclMatchArp *//***************/#ifdef _SQUID_LINUX_static intaclMatchArp(void *dataptr, struct in_addr c){ struct arpreq arpReq; struct sockaddr_in ipAddr; splayNode **Top = dataptr; ipAddr.sin_family = AF_INET; ipAddr.sin_port = 0; ipAddr.sin_addr = c; memcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); arpReq.arp_dev[0] = '\0'; arpReq.arp_flags = 0; /* any AF_INET socket will do... gives back hardware type, device, etc */ if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) == -1) { debug(28, 1) ("ARP query failed - %d", errno); return 0; } else if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) { debug(28, 1) ("Non-ethernet interface returned from ARP query - %d", arpReq.arp_ha.sa_family); /* update here and MAC address parsing to handle non-ethernet */ return 0; } else *Top = splay_splay(&arpReq.arp_ha.sa_data, *Top, aclArpCompare); debug(28, 3) ("aclMatchArp: '%s' %s\n", inet_ntoa(c), splayLastResult ? "NOT found" : "found"); return !splayLastResult;}static intaclArpCompare(const void *data, splayNode * n){ const unsigned short *d1 = data; const unsigned short *d2 = n->data; if (d1[0] != d2[0]) return (d1[0] > d2[0]) ? 1 : -1; if (d1[1] != d2[1]) return (d1[1] > d2[1]) ? 1 : -1; if (d1[2] != d2[2]) return (d1[2] > d2[2]) ? 1 : -1; return 0;}#elsestatic intaclMatchArp(void *dataptr, struct in_addr c){ WRITE ME;}static intaclArpCompare(const void *data, splayNode * n){ WRITE ME;}/*********************************************************************** This is from the pre-splay-tree code for BSD* I suspect the Linux approach will work on most O/S and be much* better - <luyer@ucs.uwa.edu.au>***********************************************************************static intcheckARP(u_long ip, char *eth){ int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; size_t needed; char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr_inarp *sin; struct sockaddr_dl *sdl; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { debug(28, 0) ("Can't estimate ARP table size!\n"); return 0; } if ((buf = xmalloc(needed)) == NULL) { debug(28, 0) ("Can't allocate temporary ARP table!\n"); return 0; } if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { debug(28, 0) ("Can't retrieve ARP table!\n"); xfree(buf); return 0; } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *) next; sin = (struct sockaddr_inarp *) (rtm + 1); sdl = (struct sockaddr_dl *) (sin + 1); if (sin->sin_addr.s_addr == ip) { if (sdl->sdl_alen) if (!memcmp(LLADDR(sdl), eth, 6)) { xfree(buf); return 1; } break; } } xfree(buf); return 0;}**********************************************************************/#endifstatic voidaclDumpArpListWalkee(void *node, void *state){ acl_arp_data *arp = node; wordlist **W = state; static char buf[24]; while (*W != NULL) W = &(*W)->next; snprintf(buf, sizeof(buf), "%02x:%02x:02x:02x:02x:02x", arp->eth[0], arp->eth[1], arp->eth[2], arp->eth[3], arp->eth[4], arp->eth[5]); wordlistAdd(state, buf);}static wordlist *aclDumpArpList(void *data){ wordlist *w = NULL; splay_walk(data, aclDumpArpListWalkee, &w); return w;}/* ==== END ARP ACL SUPPORT =============================================== */#endif /* USE_ARP_ACL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -