📄 acl.c
字号:
debug(28, 3) ("aclMatchAclList: checking %s%s\n", list->op ? null_string : "!", list->acl->name); if (aclMatchAcl(list->acl, checklist) != list->op) { debug(28, 3) ("aclMatchAclList: returning 0\n"); return 0; } list = list->next; } debug(28, 3) ("aclMatchAclList: returning 1\n"); return 1;}intaclCheckFast(const acl_access * A, aclCheck_t * checklist){ int allow = 0; debug(28, 5) ("aclCheckFast: list: %p\n", A); while (A) { allow = A->allow; if (aclMatchAclList(A->acl_list, checklist)) return allow; A = A->next; } debug(28, 5) ("aclCheckFast: no matches, returning: %d\n", !allow); return !allow;}static voidaclCheck(aclCheck_t * checklist){ allow_t allow = ACCESS_DENIED; const acl_access *A; int match; ipcache_addrs *ia; while ((A = checklist->access_list) != NULL) { /* * If the _acl_access is no longer valid (i.e. its been * freed because of a reconfigure), then bail on this * access check. For now, return ACCESS_DENIED. */ if (!cbdataValid(A)) { cbdataUnlock(A); break; } debug(28, 3) ("aclCheck: checking '%s'\n", A->cfgline); allow = A->allow; match = aclMatchAclList(A->acl_list, checklist); if (checklist->state[ACL_DST_IP] == ACL_LOOKUP_NEEDED) { checklist->state[ACL_DST_IP] = ACL_LOOKUP_PENDING; ipcache_nbgethostbyname(checklist->request->host, aclLookupDstIPDone, checklist); return; } else if (checklist->state[ACL_DST_ASN] == ACL_LOOKUP_NEEDED) { checklist->state[ACL_DST_ASN] = ACL_LOOKUP_PENDING; ipcache_nbgethostbyname(checklist->request->host, aclLookupDstIPforASNDone, checklist); return; } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NEEDED) { checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_PENDING; fqdncache_nbgethostbyaddr(checklist->src_addr, aclLookupSrcFQDNDone, checklist); return; } else if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NEEDED) { ia = ipcacheCheckNumeric(checklist->request->host); if (ia == NULL) { checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_DONE; return; } checklist->dst_addr = ia->in_addrs[0]; checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_PENDING; fqdncache_nbgethostbyaddr(checklist->dst_addr, aclLookupDstFQDNDone, checklist); return; } else if (checklist->state[ACL_PROXY_AUTH] == ACL_LOOKUP_NEEDED) { debug(28, 3) ("aclCheck: checking password via authenticator\n"); aclLookupProxyAuthStart(checklist); checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_PENDING; return; } else if (checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_NEEDED) { /* Special case. Client is required to resend the request * with authentication. The request is denied. */ allow = ACCESS_REQ_PROXY_AUTH; match = -1; }#if USE_IDENT else if (checklist->state[ACL_IDENT] == ACL_LOOKUP_NEEDED) { debug(28, 3) ("aclCheck: Doing ident lookup\n"); if (cbdataValid(checklist->conn)) { identStart(&checklist->conn->me, &checklist->conn->peer, aclLookupIdentDone, checklist); checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING; return; } else { debug(28, 1) ("aclCheck: Can't start ident lookup. No client connection\n"); cbdataUnlock(checklist->conn); checklist->conn = NULL; allow = 0; match = -1; } }#endif /* * We are done with this _acl_access entry. Either the request * is allowed, denied, requires authentication, or we move on to * the next entry. */ cbdataUnlock(A); if (match) { debug(28, 3) ("aclCheck: match found, returning %d\n", allow); aclCheckCallback(checklist, allow); return; } checklist->access_list = A->next; /* * Lock the next _acl_access entry */ if (A->next) cbdataLock(A->next); } debug(28, 3) ("aclCheck: NO match found, returning %d\n", !allow); aclCheckCallback(checklist, !allow);}voidaclChecklistFree(aclCheck_t * checklist){ if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_PENDING) fqdncacheUnregister(checklist->src_addr, checklist); if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_PENDING) fqdncacheUnregister(checklist->dst_addr, checklist); if (checklist->state[ACL_DST_IP] == ACL_LOOKUP_PENDING) ipcacheUnregister(checklist->request->host, checklist); if (checklist->request) requestUnlink(checklist->request); checklist->request = NULL;#if USE_IDENT if (checklist->conn) { cbdataUnlock(checklist->conn); checklist->conn = NULL; }#endif cbdataFree(checklist);}static voidaclCheckCallback(aclCheck_t * checklist, allow_t answer){ debug(28, 3) ("aclCheckCallback: answer=%d\n", answer); if (cbdataValid(checklist->callback_data)) checklist->callback(answer, checklist->callback_data); cbdataUnlock(checklist->callback_data); checklist->callback = NULL; checklist->callback_data = NULL; aclChecklistFree(checklist);}#if USE_IDENTstatic voidaclLookupIdentDone(const char *ident, void *data){ aclCheck_t *checklist = data; if (ident) { xstrncpy(checklist->ident, ident, sizeof(checklist->ident)); xstrncpy(checklist->request->user_ident, ident, sizeof(checklist->request->user_ident)); } else { xstrncpy(checklist->ident, "-", sizeof(checklist->ident)); } /* * Cache the ident result in the connection, to avoid redoing ident lookup * over and over on persistent connections */ if (cbdataValid(checklist->conn) && !checklist->conn->ident[0]) xstrncpy(checklist->conn->ident, checklist->ident, sizeof(checklist->conn->ident)); aclCheck(checklist);}#endifstatic voidaclLookupDstIPDone(const ipcache_addrs * ia, void *data){ aclCheck_t *checklist = data; checklist->state[ACL_DST_IP] = ACL_LOOKUP_DONE; aclCheck(checklist);}static voidaclLookupDstIPforASNDone(const ipcache_addrs * ia, void *data){ aclCheck_t *checklist = data; checklist->state[ACL_DST_ASN] = ACL_LOOKUP_DONE; aclCheck(checklist);}static voidaclLookupSrcFQDNDone(const char *fqdn, void *data){ aclCheck_t *checklist = data; checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_DONE; aclCheck(checklist);}static voidaclLookupDstFQDNDone(const char *fqdn, void *data){ aclCheck_t *checklist = data; checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_DONE; aclCheck(checklist);}static voidaclLookupProxyAuthDone(void *data, char *result){ aclCheck_t *checklist = data; checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_DONE; debug(28, 4) ("aclLookupProxyAuthDone: result = %s\n", result ? result : "NULL"); if (result && (strncasecmp(result, "OK", 2) == 0)) checklist->auth_user->passwd_ok = 1; else checklist->auth_user->passwd_ok = 0; aclCheck(checklist);}aclCheck_t *aclChecklistCreate(const acl_access * A, request_t * request, struct in_addr src_addr, struct in_addr my_addr, const char *user_agent, const char *ident){ int i; aclCheck_t *checklist = memAllocate(MEM_ACLCHECK_T); cbdataAdd(checklist, memFree, MEM_ACLCHECK_T); checklist->access_list = A; /* * aclCheck() makes sure checklist->access_list is a valid * pointer, so lock it. */ cbdataLock(A); if (request != NULL) checklist->request = requestLink(request); checklist->src_addr = src_addr; checklist->my_addr = my_addr; for (i = 0; i < ACL_ENUM_MAX; i++) checklist->state[i] = ACL_LOOKUP_NONE; if (user_agent) xstrncpy(checklist->browser, user_agent, BROWSERNAMELEN);#if USE_IDENT if (ident) xstrncpy(checklist->ident, ident, USER_IDENT_SZ);#endif checklist->auth_user = NULL; /* init to NULL */ return checklist;}voidaclNBCheck(aclCheck_t * checklist, PF callback, void *callback_data){ checklist->callback = callback; checklist->callback_data = callback_data; cbdataLock(callback_data); aclCheck(checklist);}/*********************//* Destroy functions *//*********************/static voidaclDestroyTimeList(acl_time_data * data){ acl_time_data *next = NULL; for (; data; data = next) { next = data->next; memFree(data, MEM_ACL_TIME_DATA); }}voidaclDestroyRegexList(relist * data){ relist *next = NULL; for (; data; data = next) { next = data->next; regfree(&data->regex); safe_free(data->pattern); memFree(data, MEM_RELIST); }}static voidaclFreeProxyAuthUser(void *data){ acl_proxy_auth_user *u = data; xfree(u->user); xfree(u->passwd); memFree(u, MEM_ACL_PROXY_AUTH_USER);}static voidaclFreeIpData(void *p){ memFree(p, MEM_ACL_IP_DATA);}voidaclDestroyAcls(acl ** head){ acl *a = NULL; acl *next = NULL; for (a = *head; a; a = next) { next = a->next; debug(28, 3) ("aclDestroyAcls: '%s'\n", a->cfgline); switch (a->type) { case ACL_SRC_IP: case ACL_DST_IP: case ACL_MY_IP: splay_destroy(a->data, aclFreeIpData); break; case ACL_SRC_ARP: case ACL_DST_DOMAIN: case ACL_SRC_DOMAIN: splay_destroy(a->data, xfree); break;#if SQUID_SNMP case ACL_SNMP_COMMUNITY:#endif#if USE_IDENT case ACL_IDENT:#endif case ACL_PROXY_AUTH: wordlistDestroy((wordlist **) & a->data); break; case ACL_TIME: aclDestroyTimeList(a->data); break; case ACL_URL_REGEX: case ACL_URLPATH_REGEX: case ACL_BROWSER: case ACL_SRC_DOM_REGEX: case ACL_DST_DOM_REGEX: aclDestroyRegexList(a->data); break; case ACL_PROTO: case ACL_METHOD: case ACL_SRC_ASN: case ACL_DST_ASN: case ACL_NETDB_SRC_RTT: intlistDestroy((intlist **) & a->data); break; case ACL_URL_PORT: aclDestroyIntRange(a->data); break; case ACL_NONE: default: debug(28, 1) ("aclDestroyAcls: no case for ACL type %d\n", a->type); break; } safe_free(a->cfgline); memFree(a, MEM_ACL); } *head = NULL;}static voidaclDestroyAclList(acl_list * list){ acl_list *next = NULL; for (; list; list = next) { next = list->next; memFree(list, MEM_ACL_LIST); }}voidaclDestroyAccessList(acl_access ** list){ acl_access *l = NULL; acl_access *next = NULL; for (l = *list; l; l = next) { debug(28, 3) ("aclDestroyAccessList: '%s'\n", l->cfgline); next = l->next; aclDestroyAclList(l->acl_list); l->acl_list = NULL; safe_free(l->cfgline); cbdataFree(l); } *list = NULL;}/* maex@space.net (06.09.1996) * destroy an _acl_deny_info_list */voidaclDestroyDenyInfoList(acl_deny_info_list ** list){ acl_deny_info_list *a = NULL; acl_deny_info_list *a_next = NULL; acl_name_list *l = NULL; acl_name_list *l_next = NULL; for (a = *list; a; a = a_next) { for (l = a->acl_list; l; l = l_next) { l_next = l->next; safe_free(l); } a_next = a->next; xfree(a->err_page_name); safe_free(a); } *list = NULL;}static voidaclDestroyIntRange(intrange * list){ intrange *w = NULL; intrange *n = NULL; for (w = list; w; w = n) { n = w->next; safe_free(w); }}/* general compare functions, these are used for tree search algorithms * so they return <0, 0 or >0 *//* compare two domains */static intaclDomainCompare(const void *data, splayNode * n){ const char *d1 = data; const char *d2 = n->data; int l1; int l2; while ('.' == *d1) d1++; while ('.' == *d2) d2++; l1 = strlen(d1); l2 = strlen(d2); while (d1[l1] == d2[l2]) { if ((l1 == 0) && (l2 == 0)) return 0; /* d1 == d2 */ l1--; l2--; if (0 == l1) { if ('.' == d2[l2 - 1]) { debug(28, 0) ("WARNING: %s is a subdomain of %s\n", d2, d1); debug(28, 0) ("WARNING: This may break Splay tree searching\n"); debug(28, 0) ("WARNING: You should remove '%s' from the ACL named '%s'\n", d2, AclMatchedName); } return -1; /* d1 < d2 */ } if (0 == l2) { if ('.' == d1[l1 - 1]) { debug(28, 0) ("WARNING: %s is a subdomain of %s\n", d1, d2); debug(28, 0) ("WARNING: This may break Splay tree searching\n"); debug(28, 0) ("WARNING: You should remove '%s' from the ACL named '%s'\n", d1, AclMatchedName); } return 1; /* d1 > d2 */ } } return (d1[l1] - d2[l2]);}/* compare a host and a domain */static int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -