From 299a43a9012f4c361ff92b302e57990b3016bb64 Mon Sep 17 00:00:00 2001 From: jongfoster Date: Thu, 7 Jun 2001 23:10:26 +0000 Subject: [PATCH] Allowing unanchored domain patterns to back off and retry if they partially match. Optimized right-anchored patterns. Moving ACL and forward files into config file. Replacing struct gateway with struct forward_spec --- filters.c | 164 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 46 deletions(-) diff --git a/filters.c b/filters.c index e43ad99a..b31cb434 100644 --- a/filters.c +++ b/filters.c @@ -1,4 +1,4 @@ -const char filters_rcs[] = "$Id: filters.c,v 1.15 2001/06/03 11:03:48 oes Exp $"; +const char filters_rcs[] = "$Id: filters.c,v 1.15 2001/06/03 19:12:00 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.c,v $ @@ -38,6 +38,9 @@ const char filters_rcs[] = "$Id: filters.c,v 1.15 2001/06/03 11:03:48 oes Exp $" * * Revisions : * $Log: filters.c,v $ + * Revision 1.15 2001/06/03 19:12:00 oes + * extracted-CGI relevant stuff + * * Revision 1.15 2001/06/03 11:03:48 oes * Makefile/in * @@ -295,33 +298,31 @@ const char filters_h_rcs[] = FILTERS_H_VERSION; int block_acl(struct access_control_addr *dst, struct client_state *csp) { - struct file_list *fl; - struct access_control_list *a, *acl; + struct access_control_list *acl = csp->config->acl; /* if not using an access control list, then permit the connection */ - if (((fl = csp->alist) == NULL) || - ((acl = (struct access_control_list *) fl->f) == NULL)) + if (acl == NULL) { return(0); } /* search the list */ - for (a = acl->next ; a ; a = a->next) + while (acl != NULL) { - if ((csp->ip_addr_long & a->src->mask) == a->src->addr) + if ((csp->ip_addr_long & acl->src->mask) == acl->src->addr) { if (dst == NULL) { /* Just want to check if they have any access */ - if (a->action == ACL_PERMIT) + if (acl->action == ACL_PERMIT) { return(0); } } - else if ( ((dst->addr & a->dst->mask) == a->dst->addr) - && ((dst->port == a->dst->port) || (a->dst->port == 0))) + else if ( ((dst->addr & acl->dst->mask) == acl->dst->addr) + && ((dst->port == acl->dst->port) || (acl->dst->port == 0))) { - if (a->action == ACL_PERMIT) + if (acl->action == ACL_PERMIT) { return(0); } @@ -331,6 +332,7 @@ int block_acl(struct access_control_addr *dst, } } } + acl = acl->next; } return(1); @@ -872,51 +874,55 @@ void apply_url_actions(struct current_action_spec *action, * 1 : http = http_request request for current URL * 2 : csp = Current client state (buffers, headers, etc...) * - * Returns : Return gw_default for no forward match, - * else a gateway pointer to a specific forwarding proxy. + * Returns : Pointer to forwarding information. * *********************************************************************/ -const struct gateway *forward_url(struct http_request *http, struct client_state *csp) +const struct forward_spec * forward_url(struct http_request *http, + struct client_state *csp) { - struct file_list *fl; - struct forward_spec *b; + static const struct forward_spec fwd_default[1] = { 0 }; /* All zeroes */ + struct forward_spec *fwd = csp->config->forward; struct url_spec url[1]; - if (((fl = csp->flist) == NULL) || ((b = fl->f) == NULL)) + if (fwd == NULL) { - return(gw_default); + return(fwd_default); } *url = dsplit(http->host); /* if splitting the domain fails, punt */ - if (url->dbuf == NULL) return(gw_default); + if (url->dbuf == NULL) + { + return(fwd_default); + } - for (b = b->next; b ; b = b->next) + while (fwd != NULL) { - if ((b->url->port == 0) || (b->url->port == http->port)) + if ((fwd->url->port == 0) || (fwd->url->port == http->port)) { - if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0)) + if ((fwd->url->domain[0] == '\0') || (domaincmp(fwd->url, url) == 0)) { - if ((b->url->path == NULL) || + if ((fwd->url->path == NULL) || #ifdef REGEX - (regexec(b->url->preg, http->path, 0, NULL, 0) == 0) + (regexec(fwd->url->preg, http->path, 0, NULL, 0) == 0) #else - (strncmp(b->url->path, http->path, b->url->pathlen) == 0) + (strncmp(fwd->url->path, http->path, fwd->url->pathlen) == 0) #endif ) { freez(url->dbuf); freez(url->dvec); - return(b->gw); + return(fwd); } } } + fwd = fwd->next; } freez(url->dbuf); freez(url->dvec); - return(gw_default); + return(fwd_default); } @@ -981,6 +987,41 @@ struct url_spec dsplit(char *domain) } +/********************************************************************* + * + * Function : simple_domaincmp + * + * Description : Domain-wise Compare fqdn's. The comparison is + * both left- and right-anchored. The individual + * domain names are compared with trivialmatch(). + * This is only used by domaincmp. + * + * Parameters : + * 1 : pv = array of patterns to compare + * 2 : fv = array of domain components to compare + * 3 : len = length of the arrays (both arrays are the + * same length - if they weren't, it couldn't + * possibly be a match). + * + * Returns : 0 => domains are equivalent, else no match. + * + *********************************************************************/ +static int simple_domaincmp(char **pv, char **fv, int len) +{ + int n; + + for (n = 0; n < len; n++) + { + if (simplematch(pv[n], fv[n])) + { + return 1; + } + } + + return 0; +} + + /********************************************************************* * * Function : domaincmp @@ -1001,34 +1042,65 @@ struct url_spec dsplit(char *domain) int domaincmp(struct url_spec *pattern, struct url_spec *fqdn) { char **pv, **fv; /* vectors */ - int pn, fn; /* counters */ - char *p, *f; /* chars */ + int plen, flen; + int unanchored = pattern->unanchored & (ANCHOR_RIGHT | ANCHOR_LEFT); - pv = pattern->dvec; - fv = fqdn->dvec; - fn = pn = 0; + plen = pattern->dcnt; + flen = fqdn->dcnt; - while (fn < fqdn->dcnt && pn < pattern->dcnt) + if (flen < plen) { - p = pv[pn]; - f = fv[fn]; + /* fqdn is too short to match this pattern */ + return 1; + } + + pv = pattern->dvec; + fv = fqdn->dvec; - if (simplematch(p, f)) + if (unanchored == ANCHOR_LEFT) + { + /* + * Right anchored. + * + * Convert this into a fully anchored pattern with + * the fqdn and pattern the same length + */ + fv += (flen - plen); /* flen - plen >= 0 due to check above */ + return simple_domaincmp(pv, fv, plen); + } + else if (unanchored == 0) + { + /* Fully anchored, check length */ + if (flen != plen) { - if(pn || !(pattern->unanchored & ANCHOR_LEFT)) - { - return 1; - } + return 1; } - else + return simple_domaincmp(pv, fv, plen); + } + else if (unanchored == ANCHOR_RIGHT) + { + /* Left anchored, ignore all extra in fqdn */ + return simple_domaincmp(pv, fv, plen); + } + else + { + /* Unanchored */ + int n; + int maxn = flen - plen; + for (n = 0; n <= maxn; n++) { - pn++; + if (!simple_domaincmp(pv, fv, plen)) + { + return 0; + } + /* + * Doesn't match from start of fqdn + * Try skipping first part of fqdn + */ + fv++; } - fn++; + return 1; } - - return ((pn < pattern->dcnt) || ((fn < fqdn->dcnt) && !(pattern->unanchored & ANCHOR_RIGHT))); - } -- 2.39.2