⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acl.c

📁 -
💻 C
📖 第 1 页 / 共 5 页
字号:
	    }	    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 + -