📄 acl.c
字号:
} return 1; } prev = data; data = data->next; } return 0;}static intaclMatchUser(wordlist * data, const char *user){ if (user == NULL) return 0; debug(28, 3) ("aclMatchUser: checking '%s'\n", user); while (data) { debug(28, 3) ("aclMatchUser: looking for '%s'\n", data->key); if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0' && strcmp(user, "-") != 0) return 1; if (strcmp(data->key, user) == 0) return 1; data = data->next; } return 0;}static intaclDecodeProxyAuth(const char *proxy_auth, char **user, char **password, char *buf, size_t bufsize){ char *sent_auth; char *cleartext; if (proxy_auth == NULL) return 0; if (strlen(proxy_auth) < SKIP_BASIC_SZ) return 0; proxy_auth += SKIP_BASIC_SZ; sent_auth = xstrdup(proxy_auth); /* username and password */ /* Trim trailing \n before decoding */ strtok(sent_auth, "\n"); /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) proxy_auth++; cleartext = uudecode(sent_auth); xfree(sent_auth); debug(28, 6) ("aclDecodeProxyAuth: cleartext = '%s'\n", cleartext); xstrncpy(buf, cleartext, bufsize); xfree(cleartext); *user = buf; if ((*password = strchr(*user, ':')) != NULL) *(*password)++ = '\0'; if (*password == NULL) { debug(28, 1) ("aclDecodeProxyAuth: no password in proxy authorization header\n"); return 0; } return 1;}/* aclMatchProxyAuth can return three exit codes: * 0 : user denied access * 1 : user validated OK * -1 : check the password for this user via an external authenticator * -2 : invalid Proxy-authorization: header; * ask for Proxy-Authorization: header */static intaclMatchProxyAuth(wordlist * data, const char *proxy_auth, acl_proxy_auth_user * auth_user, aclCheck_t * checklist){ /* checklist is used to register user name when identified, nothing else */ LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); char *user, *password; if (!aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, sizeof(login_buf))) /* No or invalid Proxy-Auth header */ return -2; debug(28, 5) ("aclMatchProxyAuth: checking user '%s'\n", user); if (auth_user) { /* This should be optimized to a boolean argument indicating that the * password is invalid, instead of passing full acl_proxy_auth_user * structures, and all messing with checklist->proxy_auth should * be restricted the functions that deal with the authenticator. */ assert(auth_user == checklist->auth_user); checklist->auth_user = NULL; /* get rid of that special reference */ /* Check result from external validation */ if (auth_user->passwd_ok != 1) { /* password was checked but did not match */ assert(auth_user->passwd_ok == 0); debug(28, 4) ("aclMatchProxyAuth: authentication failed for user '%s'\n", user); aclFreeProxyAuthUser(auth_user); /* copy username to request for logging on client-side unless ident * is known (do not override ident with false proxy auth names) */ if (!*checklist->request->user_ident) xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); return -2; } else { /* password was checked and did match */ debug(28, 4) ("aclMatchProxyAuth: user '%s' validated OK\n", user); /* store validated user in hash, after filling in expiretime */ xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); auth_user->expiretime = current_time.tv_sec + Config.authenticateTTL; hash_join(proxy_auth_cache, (hash_link *) auth_user); /* Continue checking below, as normal */ } } /* see if we already know this user */ auth_user = hash_lookup(proxy_auth_cache, user); if (!auth_user) { /* user not yet known, ask external authenticator */ debug(28, 4) ("aclMatchProxyAuth: user '%s' not yet known\n", user); return -1; } else if ((0 == strcmp(auth_user->passwd, password)) && (auth_user->expiretime > current_time.tv_sec)) { /* user already known and valid */ debug(28, 5) ("aclMatchProxyAuth: user '%s' previously validated\n", user); /* copy username to request for logging on client-side */ xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); return aclMatchUser(data, user); } else { /* password mismatch/timeout */ debug(28, 4) ("aclMatchProxyAuth: user '%s' password mismatch/timeout\n", user); /* remove this user from the hash, making him unknown */ hash_remove_link(proxy_auth_cache, (hash_link *) auth_user); aclFreeProxyAuthUser(auth_user); /* ask the external authenticator in case the password is changed */ /* wrong password will be trapped above so this does not loop */ return -1; } /* NOTREACHED */}static voidaclLookupProxyAuthStart(aclCheck_t * checklist){ LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); const char *proxy_auth; char *user, *password; int ok; acl_proxy_auth_user *auth_user; assert(!checklist->auth_user); if (!checklist->request->flags.accelerated) { /* Proxy auth on proxy requests */ proxy_auth = httpHeaderGetStr(&checklist->request->header, HDR_PROXY_AUTHORIZATION); } else { /* WWW auth on accelerated requests */ proxy_auth = httpHeaderGetStr(&checklist->request->header, HDR_AUTHORIZATION); } ok = aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, sizeof(login_buf)); /* * if aclDecodeProxyAuth() fails, the same call should have failed * in aclMatchProxyAuth, and we should never get this far. */ assert(ok); debug(28, 4) ("aclLookupProxyAuthStart: going to ask authenticator on %s\n", user); /* we must still check this user's password */ auth_user = memAllocate(MEM_ACL_PROXY_AUTH_USER); auth_user->user = xstrdup(user); auth_user->passwd = xstrdup(password); auth_user->passwd_ok = -1; auth_user->expiretime = -1; checklist->auth_user = auth_user; authenticateStart(checklist->auth_user, aclLookupProxyAuthDone, checklist);}static intaclMatchInteger(intlist * data, int i){ intlist *first, *prev; first = data; prev = NULL; while (data) { if (data->i == i) { if (prev != NULL) { /* shift the element just found to the second position * in the list */ prev->next = data->next; data->next = first->next; first->next = data; } return 1; } prev = data; data = data->next; } return 0;}static intaclMatchIntegerRange(intrange * data, int i){ intrange *first, *prev; first = data; prev = NULL; while (data) { if (i < data->i) { (void) 0; } else if (i > data->j) { (void) 0; } else { /* matched */ if (prev != NULL) { /* shift the element just found to the second position * in the list */ prev->next = data->next; data->next = first->next; first->next = data; } return 1; } prev = data; data = data->next; } return 0;}static intaclMatchTime(acl_time_data * data, time_t when){ static time_t last_when = 0; static struct tm tm; time_t t; assert(data != NULL); if (when != last_when) { last_when = when; xmemcpy(&tm, localtime(&when), sizeof(struct tm)); } t = (time_t) (tm.tm_hour * 60 + tm.tm_min); debug(28, 3) ("aclMatchTime: checking %d in %d-%d, weekbits=%x\n", (int) t, (int) data->start, (int) data->stop, data->weekbits); if (t < data->start || t > data->stop) return 0; return data->weekbits & (1 << tm.tm_wday) ? 1 : 0;}#if SQUID_SNMPstatic intaclMatchWordList(wordlist * w, const char *word){ debug(28, 3) ("aclMatchWordList: looking for '%s'\n", word); while (w != NULL) { debug(28, 3) ("aclMatchWordList: checking '%s'\n", w->key); if (!strcmp(w->key, word)) return 1; w = w->next; } return 0;}#endifstatic intaclMatchAcl(acl * ae, aclCheck_t * checklist){ request_t *r = checklist->request; const ipcache_addrs *ia = NULL; const char *fqdn = NULL; char *esc_buf; const char *header; int k; if (!ae) return 0; debug(28, 3) ("aclMatchAcl: checking '%s'\n", ae->cfgline); switch (ae->type) { case ACL_SRC_IP: return aclMatchIp(&ae->data, checklist->src_addr); /* NOTREACHED */ case ACL_MY_IP: return aclMatchIp(&ae->data, checklist->my_addr); /* NOTREACHED */ case ACL_DST_IP: ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); if (ia) { for (k = 0; k < (int) ia->count; k++) { if (aclMatchIp(&ae->data, ia->in_addrs[k])) return 1; } return 0; } else if (checklist->state[ACL_DST_IP] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, r->host); checklist->state[ACL_DST_IP] = ACL_LOOKUP_NEEDED; return 0; } else { return aclMatchIp(&ae->data, no_addr); } /* NOTREACHED */ case ACL_DST_DOMAIN: if ((ia = ipcacheCheckNumeric(r->host)) == NULL) return aclMatchDomainList(&ae->data, r->host); fqdn = fqdncache_gethostbyaddr(ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); if (fqdn) return aclMatchDomainList(&ae->data, fqdn); if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, inet_ntoa(ia->in_addrs[0])); checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchDomainList(&ae->data, "none"); /* NOTREACHED */ case ACL_SRC_DOMAIN: fqdn = fqdncache_gethostbyaddr(checklist->src_addr, FQDN_LOOKUP_IF_MISS); if (fqdn) { return aclMatchDomainList(&ae->data, fqdn); } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, inet_ntoa(checklist->src_addr)); checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchDomainList(&ae->data, "none"); /* NOTREACHED */ case ACL_DST_DOM_REGEX: if ((ia = ipcacheCheckNumeric(r->host)) == NULL) return aclMatchRegex(ae->data, r->host); fqdn = fqdncache_gethostbyaddr(ia->in_addrs[0], FQDN_LOOKUP_IF_MISS); if (fqdn) return aclMatchRegex(ae->data, fqdn); if (checklist->state[ACL_DST_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, inet_ntoa(ia->in_addrs[0])); checklist->state[ACL_DST_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchRegex(ae->data, "none"); /* NOTREACHED */ case ACL_SRC_DOM_REGEX: fqdn = fqdncache_gethostbyaddr(checklist->src_addr, FQDN_LOOKUP_IF_MISS); if (fqdn) { return aclMatchRegex(ae->data, fqdn); } else if (checklist->state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NONE) { debug(28, 3) ("aclMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, inet_ntoa(checklist->src_addr)); checklist->state[ACL_SRC_DOMAIN] = ACL_LOOKUP_NEEDED; return 0; } return aclMatchRegex(ae->data, "none"); /* NOTREACHED */ case ACL_TIME: return aclMatchTime(ae->data, squid_curtime); /* NOTREACHED */ case ACL_URLPATH_REGEX: esc_buf = xstrdup(strBuf(r->urlpath)); rfc1738_unescape(esc_buf); k = aclMatchRegex(ae->data, esc_buf); safe_free(esc_buf); return k; /* NOTREACHED */ case ACL_URL_REGEX: esc_buf = xstrdup(urlCanonical(r)); rfc1738_unescape(esc_buf); k = aclMatchRegex(ae->data, esc_buf); safe_free(esc_buf); return k; /* NOTREACHED */ case ACL_URL_PORT: return aclMatchIntegerRange(ae->data, r->port); /* NOTREACHED */#if USE_IDENT case ACL_IDENT: if (checklist->ident[0]) { return aclMatchUser(ae->data, checklist->ident); } else { checklist->state[ACL_IDENT] = ACL_LOOKUP_NEEDED; return 0; } /* NOTREACHED */#endif case ACL_PROTO: return aclMatchInteger(ae->data, r->protocol); /* NOTREACHED */ case ACL_METHOD: return aclMatchInteger(ae->data, r->method); /* NOTREACHED */ case ACL_BROWSER: return aclMatchRegex(ae->data, checklist->browser); /* NOTREACHED */ case ACL_PROXY_AUTH: if (NULL == r) { return -1; } else if (!r->flags.accelerated) { /* Proxy authorization on proxy requests */ header = httpHeaderGetStr(&checklist->request->header, HDR_PROXY_AUTHORIZATION); } else if (r->flags.internal) { /* WWW authorization on accelerated internal requests */ header = httpHeaderGetStr(&checklist->request->header, HDR_AUTHORIZATION); } else {#if AUTH_ON_ACCELERATION /* WWW authorization on accelerated requests */ header = httpHeaderGetStr(&checklist->request->header, HDR_AUTHORIZATION);#else debug(28, 1) ("aclMatchAcl: proxy_auth %s not applicable on accelerated requests.\n", ae->name); return -1;#endif } /* * Register that we used the proxy authentication header so that * it is not forwarded to the next proxy */ r->flags.used_proxy_auth = 1; /* Check the password */ switch (aclMatchProxyAuth(ae->data, header, checklist->auth_user, checklist)) { case 0: /* Correct password, but was not allowed in this ACL */ return 0; case 1: /* user validated OK */ return 1; case -2: /* no such user OR we need a proxy authentication header */ checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_NEEDED; /* * XXX This is a bit oddly done.. should perhaps use different * return codes here */ return 0; case -1: /* * we need to validate the password */ checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_NEEDED; return 0; } /* NOTREACHED */#if SQUID_SNMP case ACL_SNMP_COMMUNITY: return aclMatchWordList(ae->data, checklist->snmp_community);#endif case ACL_SRC_ASN: return asnMatchIp(ae->data, checklist->src_addr); case ACL_DST_ASN: ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); if (ia) { for (k = 0; k < (int) ia->count; k++) { if (asnMatchIp(ae->data, ia->in_addrs[k])) return 1; } return 0; } else if (checklist->state[ACL_DST_ASN] == ACL_LOOKUP_NONE) { debug(28, 3) ("asnMatchAcl: Can't yet compare '%s' ACL for '%s'\n", ae->name, r->host); checklist->state[ACL_DST_ASN] = ACL_LOOKUP_NEEDED; } else { return asnMatchIp(ae->data, no_addr); } return 0;#if USE_ARP_ACL case ACL_SRC_ARP: return aclMatchArp(&ae->data, checklist->src_addr);#endif case ACL_NONE: default: debug(28, 0) ("aclMatchAcl: '%s' has bad type %d\n", ae->name, ae->type); return 0; } /* NOTREACHED */}intaclMatchAclList(const acl_list * list, aclCheck_t * checklist){ while (list) { AclMatchedName = list->acl->name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -